@fuf-stack/uniform 1.11.1 → 1.11.3
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/dist/Checkboxes/index.cjs +1 -1
- package/dist/Checkboxes/index.d.cts +1 -1
- package/dist/Checkboxes/index.d.ts +1 -1
- package/dist/Checkboxes/index.js +1 -1
- package/dist/{Checkboxes-CGWhnpBp.js → Checkboxes-BvW4D5Nm.js} +6 -6
- package/dist/Checkboxes-BvW4D5Nm.js.map +1 -0
- package/dist/{Checkboxes-Ds6bzl6p.cjs → Checkboxes-Cvdazf25.cjs} +18 -18
- package/dist/Checkboxes-Cvdazf25.cjs.map +1 -0
- package/dist/FieldArray/index.cjs +1 -1
- package/dist/FieldArray/index.d.cts +1 -1
- package/dist/FieldArray/index.d.ts +1 -1
- package/dist/FieldArray/index.js +1 -1
- package/dist/{FieldArray-BexXN9bO.cjs → FieldArray-CJpDgK_t.cjs} +49 -49
- package/dist/FieldArray-CJpDgK_t.cjs.map +1 -0
- package/dist/{FieldArray-D3iUaRLo.js → FieldArray-omRNwxgy.js} +9 -9
- package/dist/FieldArray-omRNwxgy.js.map +1 -0
- package/dist/FieldCard/index.cjs +1 -1
- package/dist/FieldCard/index.d.cts +1 -1
- package/dist/FieldCard/index.d.ts +1 -1
- package/dist/FieldCard/index.js +1 -1
- package/dist/{FieldCard-pP7aniZU.cjs → FieldCard-Dt6QU7o7.cjs} +13 -13
- package/dist/{FieldCard-pP7aniZU.cjs.map → FieldCard-Dt6QU7o7.cjs.map} +1 -1
- package/dist/{FieldCard-mpmErfDK.js → FieldCard-Dyi-2qr6.js} +3 -3
- package/dist/{FieldCard-mpmErfDK.js.map → FieldCard-Dyi-2qr6.js.map} +1 -1
- package/dist/{FieldCopyTestIdButton-AaLwu_8y.cjs → FieldCopyTestIdButton-By-hEZgA.cjs} +10 -10
- package/dist/{FieldCopyTestIdButton-AaLwu_8y.cjs.map → FieldCopyTestIdButton-By-hEZgA.cjs.map} +1 -1
- package/dist/{FieldCopyTestIdButton-Cx8AXJhO.js → FieldCopyTestIdButton-D9f1B-VS.js} +4 -4
- package/dist/{FieldCopyTestIdButton-Cx8AXJhO.js.map → FieldCopyTestIdButton-D9f1B-VS.js.map} +1 -1
- package/dist/{FieldValidationError-D86DPSOH.js → FieldValidationError-BYwitb_B.js} +4 -4
- package/dist/{FieldValidationError-D86DPSOH.js.map → FieldValidationError-BYwitb_B.js.map} +1 -1
- package/dist/{FieldValidationError-Cq6aI0tE.cjs → FieldValidationError-D64j5gnH.cjs} +13 -13
- package/dist/{FieldValidationError-Cq6aI0tE.cjs.map → FieldValidationError-D64j5gnH.cjs.map} +1 -1
- package/dist/Form/index.cjs +1 -1
- package/dist/Form/index.d.cts +1 -1
- package/dist/Form/index.d.ts +1 -1
- package/dist/Form/index.js +1 -1
- package/dist/{Form-CFmCTl60.js → Form-B1fvbnxi.js} +6 -6
- package/dist/{Form-CFmCTl60.js.map → Form-B1fvbnxi.js.map} +1 -1
- package/dist/{Form-FvN3SXfF.cjs → Form-CvnnGF45.cjs} +19 -19
- package/dist/{Form-FvN3SXfF.cjs.map → Form-CvnnGF45.cjs.map} +1 -1
- package/dist/{FormContext-CN9n_KdE.js → FormContext-Dl3k1r_k.js} +2 -2
- package/dist/FormContext-Dl3k1r_k.js.map +1 -0
- package/dist/{FormContext-C3GymQOA.cjs → FormContext-Lw4YL4-B.cjs} +8 -8
- package/dist/FormContext-Lw4YL4-B.cjs.map +1 -0
- package/dist/Grid/index.cjs +1 -1
- package/dist/Grid/index.d.cts +1 -1
- package/dist/Grid/index.d.ts +1 -1
- package/dist/Grid/index.js +1 -1
- package/dist/{Grid-DG60vYYG.cjs → Grid-DezBAZbx.cjs} +8 -8
- package/dist/{Grid-DG60vYYG.cjs.map → Grid-DezBAZbx.cjs.map} +1 -1
- package/dist/{Grid-DEH7Sezi.js → Grid-LRjQlZms.js} +4 -4
- package/dist/{Grid-DEH7Sezi.js.map → Grid-LRjQlZms.js.map} +1 -1
- package/dist/Input/index.cjs +1 -1
- package/dist/Input/index.d.cts +1 -1
- package/dist/Input/index.d.ts +1 -1
- package/dist/Input/index.js +1 -1
- package/dist/{Input-DKfFFOpo.cjs → Input-DR0gCf9q.cjs} +16 -15
- package/dist/Input-DR0gCf9q.cjs.map +1 -0
- package/dist/{Input--h5t7Sbl.js → Input-DksaHK1Y.js} +7 -6
- package/dist/Input-DksaHK1Y.js.map +1 -0
- package/dist/RadioBoxes/index.cjs +1 -1
- package/dist/RadioBoxes/index.d.cts +1 -1
- package/dist/RadioBoxes/index.d.ts +1 -1
- package/dist/RadioBoxes/index.js +1 -1
- package/dist/{RadioBoxes-7qdHj3ti.js → RadioBoxes-DdIHH6B5.js} +5 -5
- package/dist/RadioBoxes-DdIHH6B5.js.map +1 -0
- package/dist/{RadioBoxes-Bd9ahl4i.cjs → RadioBoxes-h-VLhJ9d.cjs} +22 -22
- package/dist/RadioBoxes-h-VLhJ9d.cjs.map +1 -0
- package/dist/RadioTabs/index.cjs +1 -1
- package/dist/RadioTabs/index.d.cts +1 -1
- package/dist/RadioTabs/index.d.ts +1 -1
- package/dist/RadioTabs/index.js +1 -1
- package/dist/{RadioTabs-DcEUdW7r.cjs → RadioTabs-D6yF9jE3.cjs} +18 -18
- package/dist/RadioTabs-D6yF9jE3.cjs.map +1 -0
- package/dist/{RadioTabs-DXs98jng.js → RadioTabs-dLdlF91p.js} +5 -5
- package/dist/RadioTabs-dLdlF91p.js.map +1 -0
- package/dist/Radios/index.cjs +1 -1
- package/dist/Radios/index.d.cts +1 -1
- package/dist/Radios/index.d.ts +1 -1
- package/dist/Radios/index.js +1 -1
- package/dist/{Radios-CIPNqPzi.cjs → Radios-D8alyG2f.cjs} +14 -14
- package/dist/{Radios-CIPNqPzi.cjs.map → Radios-D8alyG2f.cjs.map} +1 -1
- package/dist/{Radios-BIx06mzU.js → Radios-DiZ0Dfmp.js} +5 -5
- package/dist/{Radios-BIx06mzU.js.map → Radios-DiZ0Dfmp.js.map} +1 -1
- package/dist/Select/index.cjs +1 -1
- package/dist/Select/index.d.cts +1 -1
- package/dist/Select/index.d.ts +1 -1
- package/dist/Select/index.js +1 -1
- package/dist/{Select-CBjqYDcs.js → Select-C9otN8uu.js} +6 -6
- package/dist/Select-C9otN8uu.js.map +1 -0
- package/dist/{Select-BsL7qn2v.cjs → Select-DQVskslz.cjs} +19 -19
- package/dist/Select-DQVskslz.cjs.map +1 -0
- package/dist/Slider/index.cjs +1 -1
- package/dist/Slider/index.d.cts +1 -1
- package/dist/Slider/index.d.ts +1 -1
- package/dist/Slider/index.js +1 -1
- package/dist/{Slider-BDLbD7d5.cjs → Slider-DwfyCQDM.cjs} +15 -15
- package/dist/{Slider-BDLbD7d5.cjs.map → Slider-DwfyCQDM.cjs.map} +1 -1
- package/dist/{Slider-BHjHSoIk.js → Slider-meuLEC2k.js} +5 -5
- package/dist/{Slider-BHjHSoIk.js.map → Slider-meuLEC2k.js.map} +1 -1
- package/dist/SubmitButton/index.cjs +1 -1
- package/dist/SubmitButton/index.d.cts +1 -1
- package/dist/SubmitButton/index.d.ts +1 -1
- package/dist/SubmitButton/index.js +1 -1
- package/dist/{SubmitButton-DhtPJuro.cjs → SubmitButton-B0kvUqkd.cjs} +12 -12
- package/dist/{SubmitButton-DhtPJuro.cjs.map → SubmitButton-B0kvUqkd.cjs.map} +1 -1
- package/dist/{SubmitButton-7iOaKzhB.js → SubmitButton-BHP9J9ml.js} +5 -5
- package/dist/{SubmitButton-7iOaKzhB.js.map → SubmitButton-BHP9J9ml.js.map} +1 -1
- package/dist/Switch/index.cjs +1 -1
- package/dist/Switch/index.d.cts +1 -1
- package/dist/Switch/index.d.ts +1 -1
- package/dist/Switch/index.js +1 -1
- package/dist/{Switch-DCxAgt_L.js → Switch-DkciIYnD.js} +5 -5
- package/dist/{Switch-DCxAgt_L.js.map → Switch-DkciIYnD.js.map} +1 -1
- package/dist/{Switch-Dczzog3v.cjs → Switch-Ds0gDzjR.cjs} +15 -15
- package/dist/{Switch-Dczzog3v.cjs.map → Switch-Ds0gDzjR.cjs.map} +1 -1
- package/dist/SwitchBox/index.cjs +1 -1
- package/dist/SwitchBox/index.d.cts +1 -1
- package/dist/SwitchBox/index.d.ts +1 -1
- package/dist/SwitchBox/index.js +1 -1
- package/dist/{SwitchBox-DPHryDOM.js → SwitchBox-B6Z4rtWt.js} +5 -5
- package/dist/{SwitchBox-DPHryDOM.js.map → SwitchBox-B6Z4rtWt.js.map} +1 -1
- package/dist/{SwitchBox-DqVmZYId.cjs → SwitchBox-B9JqwDtN.cjs} +19 -19
- package/dist/{SwitchBox-DqVmZYId.cjs.map → SwitchBox-B9JqwDtN.cjs.map} +1 -1
- package/dist/TextArea/index.cjs +1 -1
- package/dist/TextArea/index.d.cts +1 -1
- package/dist/TextArea/index.d.ts +1 -1
- package/dist/TextArea/index.js +1 -1
- package/dist/{TextArea-CH-F6_ax.cjs → TextArea-BqQtlPSV.cjs} +14 -13
- package/dist/{TextArea-CH-F6_ax.cjs.map → TextArea-BqQtlPSV.cjs.map} +1 -1
- package/dist/{TextArea-BR6e-Fio.js → TextArea-DAx49KI6.js} +7 -6
- package/dist/{TextArea-BR6e-Fio.js.map → TextArea-DAx49KI6.js.map} +1 -1
- package/dist/helpers/index.cjs +2 -1
- package/dist/helpers/index.d.cts +164 -2
- package/dist/helpers/index.d.cts.map +1 -0
- package/dist/helpers/index.d.ts +164 -2
- package/dist/helpers/index.d.ts.map +1 -0
- package/dist/helpers/index.js +2 -2
- package/dist/{helpers-B-CJOBt3.js → helpers-CCINRgQk.js} +43 -2
- package/dist/helpers-CCINRgQk.js.map +1 -0
- package/dist/{helpers-KTgXi0lA.cjs → helpers-nYTmL2gX.cjs} +51 -4
- package/dist/helpers-nYTmL2gX.cjs.map +1 -0
- package/dist/hooks/useClientValidation/index.cjs +1 -1
- package/dist/hooks/useClientValidation/index.d.cts +1 -1
- package/dist/hooks/useClientValidation/index.d.ts +1 -1
- package/dist/hooks/useClientValidation/index.js +1 -1
- package/dist/hooks/useController/index.cjs +1 -1
- package/dist/hooks/useController/index.d.cts +1 -1
- package/dist/hooks/useController/index.d.ts +2 -2
- package/dist/hooks/useController/index.js +1 -1
- package/dist/hooks/useFormContext/index.cjs +1 -1
- package/dist/hooks/useFormContext/index.d.cts +1 -1
- package/dist/hooks/useFormContext/index.d.ts +2 -2
- package/dist/hooks/useFormContext/index.js +1 -1
- package/dist/hooks/useInput/index.cjs +3 -3
- package/dist/hooks/useInput/index.d.cts +1 -1
- package/dist/hooks/useInput/index.d.ts +1 -1
- package/dist/hooks/useInputValueDebounce/index.cjs +1 -1
- package/dist/hooks/useInputValueDebounce/index.d.cts +1 -1
- package/dist/hooks/useInputValueDebounce/index.d.ts +1 -1
- package/dist/hooks/useInputValueDebounce/index.js +1 -1
- package/dist/hooks/useInputValueTransform/index.cjs +1 -1
- package/dist/hooks/useInputValueTransform/index.d.cts +1 -1
- package/dist/hooks/useInputValueTransform/index.d.ts +1 -1
- package/dist/hooks/useInputValueTransform/index.js +1 -1
- package/dist/hooks/useUniformField/index.cjs +1 -1
- package/dist/hooks/useUniformField/index.d.cts +1 -1
- package/dist/hooks/useUniformField/index.d.ts +4 -4
- package/dist/hooks/useUniformField/index.js +1 -1
- package/dist/hooks/useUniformFieldArray/index.cjs +1 -1
- package/dist/hooks/useUniformFieldArray/index.d.cts +1 -1
- package/dist/hooks/useUniformFieldArray/index.d.ts +5 -5
- package/dist/hooks/useUniformFieldArray/index.js +1 -1
- package/dist/hooks/useWatchUserChange/index.cjs +1 -1
- package/dist/hooks/useWatchUserChange/index.d.cts +1 -1
- package/dist/hooks/useWatchUserChange/index.d.ts +1 -1
- package/dist/hooks/useWatchUserChange/index.js +1 -1
- package/dist/{index-BJ7tmJCw.d.cts → index-0wXxS5M7.d.ts} +6 -6
- package/dist/{index-DJFrZluU.d.ts.map → index-0wXxS5M7.d.ts.map} +1 -1
- package/dist/{index-ATMELmS_.d.ts → index-1Egh73pR.d.ts} +3 -3
- package/dist/{index-ATMELmS_.d.ts.map → index-1Egh73pR.d.ts.map} +1 -1
- package/dist/{index-BO2gua86.d.ts → index-3v_vja2i.d.ts} +6 -6
- package/dist/{index-BO2gua86.d.ts.map → index-3v_vja2i.d.ts.map} +1 -1
- package/dist/{index-DG83pAQU.d.cts → index-7mx-IcDp.d.ts} +1 -1
- package/dist/{index-cvKMShf8.d.ts.map → index-7mx-IcDp.d.ts.map} +1 -1
- package/dist/{index-DJFrZluU.d.ts → index-BDV3JVoX.d.cts} +7 -7
- package/dist/{index-BJ7tmJCw.d.cts.map → index-BDV3JVoX.d.cts.map} +1 -1
- package/dist/{index-BSJlD_z1.d.ts → index-BFLKkqA3.d.ts} +3 -3
- package/dist/{index-BSJlD_z1.d.ts.map → index-BFLKkqA3.d.ts.map} +1 -1
- package/dist/{index-DrAaB1si.d.cts → index-BGXgvZKr.d.ts} +36 -35
- package/dist/{index-BMSwSLB0.d.ts.map → index-BGXgvZKr.d.ts.map} +1 -1
- package/dist/{index-Ce5d5ud1.d.ts → index-BSjUaHEO.d.cts} +4 -4
- package/dist/{index-CuZ0szCF.d.cts.map → index-BSjUaHEO.d.cts.map} +1 -1
- package/dist/{index-BFMNC6rA.d.cts → index-B_aIzCcx.d.cts} +3 -3
- package/dist/{index-BFMNC6rA.d.cts.map → index-B_aIzCcx.d.cts.map} +1 -1
- package/dist/{index-CuZ0szCF.d.cts → index-Bcppi5O7.d.ts} +4 -4
- package/dist/{index-Ce5d5ud1.d.ts.map → index-Bcppi5O7.d.ts.map} +1 -1
- package/dist/{index-C1GCfD5q.d.cts → index-C2A_i57R.d.cts} +21 -21
- package/dist/index-C2A_i57R.d.cts.map +1 -0
- package/dist/{index-DHTrsq8u.d.cts → index-CHNp5R5N.d.cts} +6 -6
- package/dist/{index-DHTrsq8u.d.cts.map → index-CHNp5R5N.d.cts.map} +1 -1
- package/dist/{index-Cb0AgRRa.d.cts → index-CHXv_rNR.d.ts} +3 -3
- package/dist/{index-CQXf1sXV.d.ts.map → index-CHXv_rNR.d.ts.map} +1 -1
- package/dist/{index-t8GMrjmp.d.cts → index-CTp4vdDb.d.ts} +6 -6
- package/dist/{index-B5K7Sos4.d.ts.map → index-CTp4vdDb.d.ts.map} +1 -1
- package/dist/{index-0l1ioOFh.d.cts → index-CUn9q5KD.d.ts} +6 -6
- package/dist/{index-BDBmlcs9.d.ts.map → index-CUn9q5KD.d.ts.map} +1 -1
- package/dist/{index-CpPCHyTk.d.cts → index-CZyNkPDq.d.ts} +22 -22
- package/dist/index-CZyNkPDq.d.ts.map +1 -0
- package/dist/{index-CqIAvXWT.d.ts → index-CeYRsehb.d.cts} +22 -22
- package/dist/index-CeYRsehb.d.cts.map +1 -0
- package/dist/{index-B5K7Sos4.d.ts → index-CiF2KXB7.d.cts} +3 -3
- package/dist/{index-t8GMrjmp.d.cts.map → index-CiF2KXB7.d.cts.map} +1 -1
- package/dist/{index-BMSwSLB0.d.ts → index-CjJHVJwD.d.cts} +35 -36
- package/dist/{index-DrAaB1si.d.cts.map → index-CjJHVJwD.d.cts.map} +1 -1
- package/dist/{index-DUAqAErG.d.cts → index-CnsR8nkm.d.cts} +34 -34
- package/dist/{index-DUAqAErG.d.cts.map → index-CnsR8nkm.d.cts.map} +1 -1
- package/dist/{index-C32OyAvG.d.ts → index-CqGabrzW.d.cts} +37 -37
- package/dist/{index-BIt4xz_x.d.cts.map → index-CqGabrzW.d.cts.map} +1 -1
- package/dist/{index-cvKMShf8.d.ts → index-CuvvZMop.d.cts} +3 -3
- package/dist/{index-DG83pAQU.d.cts.map → index-CuvvZMop.d.cts.map} +1 -1
- package/dist/{index-BmW4khHl.d.cts → index-DNFUttM8.d.ts} +48 -48
- package/dist/index-DNFUttM8.d.ts.map +1 -0
- package/dist/{index-D6qgJDAm.d.ts → index-DVRtBywt.d.ts} +3 -3
- package/dist/{index-D6qgJDAm.d.ts.map → index-DVRtBywt.d.ts.map} +1 -1
- package/dist/{index-BDBmlcs9.d.ts → index-D_WidR7r.d.cts} +6 -6
- package/dist/{index-0l1ioOFh.d.cts.map → index-D_WidR7r.d.cts.map} +1 -1
- package/dist/index-D_egu-QT.d.cts +264 -0
- package/dist/{index-BNdmJR51.d.cts.map → index-D_egu-QT.d.cts.map} +1 -1
- package/dist/index-DajjPPWM.d.ts +264 -0
- package/dist/{index-Da-quK_d.d.ts.map → index-DajjPPWM.d.ts.map} +1 -1
- package/dist/{index-BLmXGxoy.d.ts → index-DcYFLiul.d.cts} +48 -48
- package/dist/index-DcYFLiul.d.cts.map +1 -0
- package/dist/{index-DiC-e6iW.d.ts → index-DnzC0GCS.d.ts} +4 -4
- package/dist/{index-DiC-e6iW.d.ts.map → index-DnzC0GCS.d.ts.map} +1 -1
- package/dist/{index-ByDAUZR8.d.cts → index-DvF_C1Bz.d.cts} +3 -3
- package/dist/{index-ByDAUZR8.d.cts.map → index-DvF_C1Bz.d.cts.map} +1 -1
- package/dist/{index-CQXf1sXV.d.ts → index-cadUZZIY.d.cts} +3 -3
- package/dist/{index-Cb0AgRRa.d.cts.map → index-cadUZZIY.d.cts.map} +1 -1
- package/dist/{index-cda9yEEN.d.cts → index-g9TZhGnE.d.cts} +3 -3
- package/dist/{index-cda9yEEN.d.cts.map → index-g9TZhGnE.d.cts.map} +1 -1
- package/dist/{index-BCXuFO6D.d.ts → index-op7zETAQ.d.ts} +34 -34
- package/dist/{index-BCXuFO6D.d.ts.map → index-op7zETAQ.d.ts.map} +1 -1
- package/dist/{index-BIt4xz_x.d.cts → index-yVkU2v6b.d.ts} +38 -38
- package/dist/index-yVkU2v6b.d.ts.map +1 -0
- package/dist/index.cjs +30 -29
- package/dist/index.d.cts +28 -28
- package/dist/index.d.ts +30 -30
- package/dist/index.js +27 -27
- package/dist/partials/FieldCopyTestIdButton/index.cjs +1 -1
- package/dist/partials/FieldCopyTestIdButton/index.d.cts +1 -1
- package/dist/partials/FieldCopyTestIdButton/index.d.ts +1 -1
- package/dist/partials/FieldCopyTestIdButton/index.js +1 -1
- package/dist/partials/FieldValidationError/index.cjs +1 -1
- package/dist/partials/FieldValidationError/index.d.cts +1 -1
- package/dist/partials/FieldValidationError/index.d.ts +1 -1
- package/dist/partials/FieldValidationError/index.js +1 -1
- package/dist/{useClientValidation-CbRkwhHc.d.ts → useClientValidation-Bg0q3Axc.d.ts} +3 -3
- package/dist/{useClientValidation-CbRkwhHc.d.ts.map → useClientValidation-Bg0q3Axc.d.ts.map} +1 -1
- package/dist/{useClientValidation-BnnscAEe.js → useClientValidation-BrTtRnqi.js} +3 -3
- package/dist/useClientValidation-BrTtRnqi.js.map +1 -0
- package/dist/{useClientValidation-DdRlhoG1.d.cts → useClientValidation-BvPDQmf6.d.cts} +3 -3
- package/dist/{useClientValidation-DdRlhoG1.d.cts.map → useClientValidation-BvPDQmf6.d.cts.map} +1 -1
- package/dist/{useClientValidation-oZd4_ocQ.cjs → useClientValidation-CdC7lEYP.cjs} +7 -7
- package/dist/useClientValidation-CdC7lEYP.cjs.map +1 -0
- package/dist/{useController-C_MZLZIp.d.cts → useController-BArZd2Vp.d.cts} +1 -1
- package/dist/{useController-C_MZLZIp.d.cts.map → useController-BArZd2Vp.d.cts.map} +1 -1
- package/dist/{useController-BzkCcbSo.cjs → useController-BBxji1nQ.cjs} +3 -3
- package/dist/{useController-BzkCcbSo.cjs.map → useController-BBxji1nQ.cjs.map} +1 -1
- package/dist/{useController-hjpJQf0w.d.ts → useController-MVHJ7WFp.d.ts} +1 -1
- package/dist/{useController-hjpJQf0w.d.ts.map → useController-MVHJ7WFp.d.ts.map} +1 -1
- package/dist/{useController-CumIERks.js → useController-g0AlWM__.js} +3 -3
- package/dist/{useController-CumIERks.js.map → useController-g0AlWM__.js.map} +1 -1
- package/dist/{useFormContext-CFwuH4nn.d.cts → useFormContext--yod5xzQ.d.cts} +3 -3
- package/dist/useFormContext--yod5xzQ.d.cts.map +1 -0
- package/dist/{useFormContext-JCm1UR_e.js → useFormContext-BFoXZNkp.js} +3 -3
- package/dist/useFormContext-BFoXZNkp.js.map +1 -0
- package/dist/{useFormContext-CWuN-_7P.cjs → useFormContext-CEr3zcL6.cjs} +3 -3
- package/dist/useFormContext-CEr3zcL6.cjs.map +1 -0
- package/dist/{useFormContext-3AAPT6eZ.d.ts → useFormContext-Cw6aAhos.d.ts} +3 -3
- package/dist/useFormContext-Cw6aAhos.d.ts.map +1 -0
- package/dist/{useInputValueDebounce-C7_bvNGH.d.ts → useInputValueDebounce-DI1C6oaU.d.cts} +5 -1
- package/dist/useInputValueDebounce-DI1C6oaU.d.cts.map +1 -0
- package/dist/{useInputValueDebounce-DaH5ONlQ.js → useInputValueDebounce-Dop_8_OK.js} +12 -3
- package/dist/useInputValueDebounce-Dop_8_OK.js.map +1 -0
- package/dist/{useInputValueDebounce-tL8maIp8.cjs → useInputValueDebounce-TiNR4jtG.cjs} +13 -4
- package/dist/useInputValueDebounce-TiNR4jtG.cjs.map +1 -0
- package/dist/{useInputValueDebounce-B2RzCWty.d.cts → useInputValueDebounce-fhmVn1aO.d.ts} +5 -1
- package/dist/useInputValueDebounce-fhmVn1aO.d.ts.map +1 -0
- package/dist/{useInputValueTransform-C-uSW8Y3.cjs → useInputValueTransform-BNmfaj5D.cjs} +4 -3
- package/dist/{useInputValueTransform-C-uSW8Y3.cjs.map → useInputValueTransform-BNmfaj5D.cjs.map} +1 -1
- package/dist/{useInputValueTransform-D7LfyYRe.d.ts → useInputValueTransform-BV8o0PMI.d.cts} +3 -2
- package/dist/useInputValueTransform-BV8o0PMI.d.cts.map +1 -0
- package/dist/{useInputValueTransform-aiIf8lq5.js → useInputValueTransform-CMNC21vX.js} +3 -2
- package/dist/{useInputValueTransform-aiIf8lq5.js.map → useInputValueTransform-CMNC21vX.js.map} +1 -1
- package/dist/{useInputValueTransform-BID-CQ-y.d.cts → useInputValueTransform-Cc0qEsnS.d.ts} +3 -2
- package/dist/useInputValueTransform-Cc0qEsnS.d.ts.map +1 -0
- package/dist/{useUniformField-u_7uBpco.d.cts → useUniformField-B2zQtEbr.d.cts} +5 -5
- package/dist/{useUniformField-u_7uBpco.d.cts.map → useUniformField-B2zQtEbr.d.cts.map} +1 -1
- package/dist/{useUniformField-ClprfrES.js → useUniformField-BKVVns0E.js} +34 -8
- package/dist/useUniformField-BKVVns0E.js.map +1 -0
- package/dist/{useUniformField-BMvnRC_r.cjs → useUniformField-D6fwSjrH.cjs} +41 -15
- package/dist/useUniformField-D6fwSjrH.cjs.map +1 -0
- package/dist/{useUniformField-DDHQ5B11.d.ts → useUniformField-RxZqXMuD.d.ts} +5 -5
- package/dist/{useUniformField-DDHQ5B11.d.ts.map → useUniformField-RxZqXMuD.d.ts.map} +1 -1
- package/dist/{useUniformFieldArray-BhPi3gPv.d.ts → useUniformFieldArray-B_c55CnX.d.ts} +3 -3
- package/dist/useUniformFieldArray-B_c55CnX.d.ts.map +1 -0
- package/dist/{useUniformFieldArray-C-0OXG3N.js → useUniformFieldArray-BwE634m6.js} +4 -4
- package/dist/useUniformFieldArray-BwE634m6.js.map +1 -0
- package/dist/{useUniformFieldArray-btjvJdZ6.cjs → useUniformFieldArray-Byfmzq97.cjs} +7 -7
- package/dist/useUniformFieldArray-Byfmzq97.cjs.map +1 -0
- package/dist/{useUniformFieldArray-D3lsJvhA.d.cts → useUniformFieldArray-WRuIMhw6.d.cts} +3 -3
- package/dist/useUniformFieldArray-WRuIMhw6.d.cts.map +1 -0
- package/dist/{useWatchUserChange-BAdiqg2q.d.ts → useWatchUserChange-Bf5JKDJJ.d.ts} +1 -1
- package/dist/{useWatchUserChange-BAdiqg2q.d.ts.map → useWatchUserChange-Bf5JKDJJ.d.ts.map} +1 -1
- package/dist/{useWatchUserChange-COVdHmki.d.cts → useWatchUserChange-Br4Q7syM.d.cts} +1 -1
- package/dist/{useWatchUserChange-COVdHmki.d.cts.map → useWatchUserChange-Br4Q7syM.d.cts.map} +1 -1
- package/dist/{useWatchUserChange-C5dr12By.cjs → useWatchUserChange-TMfaTCcp.cjs} +3 -3
- package/dist/{useWatchUserChange-C5dr12By.cjs.map → useWatchUserChange-TMfaTCcp.cjs.map} +1 -1
- package/dist/{useWatchUserChange-C1ezpj0t.js → useWatchUserChange-fZy6nGtD.js} +2 -2
- package/dist/{useWatchUserChange-C1ezpj0t.js.map → useWatchUserChange-fZy6nGtD.js.map} +1 -1
- package/package.json +10 -10
- package/dist/Checkboxes-CGWhnpBp.js.map +0 -1
- package/dist/Checkboxes-Ds6bzl6p.cjs.map +0 -1
- package/dist/FieldArray-BexXN9bO.cjs.map +0 -1
- package/dist/FieldArray-D3iUaRLo.js.map +0 -1
- package/dist/FormContext-C3GymQOA.cjs.map +0 -1
- package/dist/FormContext-CN9n_KdE.js.map +0 -1
- package/dist/Input--h5t7Sbl.js.map +0 -1
- package/dist/Input-DKfFFOpo.cjs.map +0 -1
- package/dist/RadioBoxes-7qdHj3ti.js.map +0 -1
- package/dist/RadioBoxes-Bd9ahl4i.cjs.map +0 -1
- package/dist/RadioTabs-DXs98jng.js.map +0 -1
- package/dist/RadioTabs-DcEUdW7r.cjs.map +0 -1
- package/dist/Select-BsL7qn2v.cjs.map +0 -1
- package/dist/Select-CBjqYDcs.js.map +0 -1
- package/dist/helpers-B-CJOBt3.js.map +0 -1
- package/dist/helpers-KTgXi0lA.cjs.map +0 -1
- package/dist/index-BLmXGxoy.d.ts.map +0 -1
- package/dist/index-BNdmJR51.d.cts +0 -264
- package/dist/index-BmW4khHl.d.cts.map +0 -1
- package/dist/index-C1GCfD5q.d.cts.map +0 -1
- package/dist/index-C32OyAvG.d.ts.map +0 -1
- package/dist/index-CpPCHyTk.d.cts.map +0 -1
- package/dist/index-CqIAvXWT.d.ts.map +0 -1
- package/dist/index-Da-quK_d.d.ts +0 -264
- package/dist/index-G0IgQWoU.d.cts +0 -134
- package/dist/index-G0IgQWoU.d.cts.map +0 -1
- package/dist/index-UjKqRe-8.d.ts +0 -134
- package/dist/index-UjKqRe-8.d.ts.map +0 -1
- package/dist/useClientValidation-BnnscAEe.js.map +0 -1
- package/dist/useClientValidation-oZd4_ocQ.cjs.map +0 -1
- package/dist/useFormContext-3AAPT6eZ.d.ts.map +0 -1
- package/dist/useFormContext-CFwuH4nn.d.cts.map +0 -1
- package/dist/useFormContext-CWuN-_7P.cjs.map +0 -1
- package/dist/useFormContext-JCm1UR_e.js.map +0 -1
- package/dist/useInputValueDebounce-B2RzCWty.d.cts.map +0 -1
- package/dist/useInputValueDebounce-C7_bvNGH.d.ts.map +0 -1
- package/dist/useInputValueDebounce-DaH5ONlQ.js.map +0 -1
- package/dist/useInputValueDebounce-tL8maIp8.cjs.map +0 -1
- package/dist/useInputValueTransform-BID-CQ-y.d.cts.map +0 -1
- package/dist/useInputValueTransform-D7LfyYRe.d.ts.map +0 -1
- package/dist/useUniformField-BMvnRC_r.cjs.map +0 -1
- package/dist/useUniformField-ClprfrES.js.map +0 -1
- package/dist/useUniformFieldArray-BhPi3gPv.d.ts.map +0 -1
- package/dist/useUniformFieldArray-C-0OXG3N.js.map +0 -1
- package/dist/useUniformFieldArray-D3lsJvhA.d.cts.map +0 -1
- package/dist/useUniformFieldArray-btjvJdZ6.cjs.map +0 -1
- /package/dist/{index-B3Z8gdjC.d.ts → index-BRLjimYW.d.ts} +0 -0
- /package/dist/{index-BXpMZvwA.d.cts → index-CFBmva_r.d.ts} +0 -0
- /package/dist/{index-CJNLQVjx.d.ts → index-DpEKQcoR.d.cts} +0 -0
- /package/dist/{index-CwSIy_W-.d.cts → index-lQ_hGQ08.d.cts} +0 -0
- /package/dist/{useInput-IGJqJ2tR.d.ts → useInput--wjwIBc5.d.cts} +0 -0
- /package/dist/{useInput-NMHJNZ5A.d.cts → useInput-BCdeYOOg.d.ts} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUniformFieldArray-BwE634m6.js","names":["useRHFFieldArray","useFormContext"],"sources":["../src/hooks/useUniformFieldArray/useUniformFieldArray.ts","../src/hooks/useUniformFieldArray/index.ts"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { ArrayPath, FieldValues, Path } from 'react-hook-form';\n\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { useFieldArray as useRHFFieldArray } from 'react-hook-form';\n\nimport { useReducedMotion } from '@fuf-stack/pixel-motion';\n\nimport { flatArrayKey } from '../../helpers';\nimport { useFormContext } from '../useFormContext';\nimport { useUniformField } from '../useUniformField';\n\nexport interface UseUniformFieldArrayProps<\n TFieldValues extends FieldValues = FieldValues,\n> {\n /** Field name for the array */\n name: ArrayPath<TFieldValues>;\n /** Whether this is a flat array (array of primitives) */\n flat?: boolean;\n /** Initial value for new array elements */\n elementInitialValue?: unknown;\n /** Whether the last element cannot be removed (always maintain at least one element) */\n lastElementNotRemovable?: boolean;\n /** Disable the field */\n disabled?: boolean;\n /** Optional explicit test id used to build stable test ids */\n testId?: string;\n /** Optional label content */\n label?: ReactNode;\n}\n\n/**\n * Enhanced useFieldArray hook with initialization and animation logic.\n * Based on React Hook Form's useFieldArray with additional features:\n * - Automatic initialization when lastElementNotRemovable is set\n * - Animation control (disabled during initialization)\n * - Support for flat arrays (arrays of primitives)\n *\n * Note: Automatic validation triggering on length change is disabled to prevent\n * triggering form-wide validation. Array validation still runs on form submission.\n *\n * @see https://react-hook-form.com/docs/usefieldarray\n */\nexport const useUniformFieldArray = <\n TFieldValues extends FieldValues = FieldValues,\n>({\n name,\n flat = false,\n elementInitialValue: _elementInitialValue = null,\n lastElementNotRemovable = false,\n disabled,\n testId: explicitTestId,\n label,\n}: UseUniformFieldArrayProps<TFieldValues>) => {\n // Get uniform field state and utilities\n const uniformField = useUniformField<TFieldValues>({\n name: name as Path<TFieldValues> & string,\n disabled,\n testId: explicitTestId,\n label,\n });\n\n const { control } = uniformField;\n\n const { fields, append, remove, insert, move } = useRHFFieldArray({\n control,\n name,\n });\n\n const { trigger, setValue } = useFormContext<TFieldValues>();\n\n // Determine if initialization is needed (initially or after reset).\n // This flag automatically handles both scenarios:\n // - Initial mount: fields.length starts at 0\n // - Form reset: fields.length becomes 0 again\n // Additional initialization conditions can be added here later (e.g., minElements > 0)\n // Using useMemo ensures this value is properly tracked by React and effects can depend on it\n const needsInitialize = useMemo(() => {\n return lastElementNotRemovable && fields.length === 0;\n }, [lastElementNotRemovable, fields.length]);\n\n // Track whether initialization has completed. Initialized contextually:\n // - If initialization IS needed (needsInitialize = true): starts as false, set to true after init\n // - If initialization is NOT needed (needsInitialize = false): starts as true (already initialized)\n // This ref is used to:\n // 1. Skip validation during initialization/re-initialization\n // 2. Gate animation enabling until after initialization\n // 3. Gate motion preference effect until after initialization\n const hasInitialized = useRef(!needsInitialize);\n\n // Reset initialization flag when needsInitialize changes to true.\n // This handles form reset: when fields become empty (needsInitialize becomes true),\n // hasInitialized is reset to false, triggering re-initialization in the effect below.\n useEffect(() => {\n if (needsInitialize) {\n hasInitialized.current = false;\n }\n }, [needsInitialize]);\n\n // Validate array-level constraints (min/max items) when length changes.\n // This ensures min/max errors appear instantly when user adds/removes items.\n // Note: Child field validation also runs, but new empty fields won't show as invalid\n // because useFormContext only sets invalid=true for touched fields or after form submission.\n // Skip validation during initialization/re-initialization to avoid showing errors prematurely.\n useEffect(() => {\n if (hasInitialized.current) {\n setTimeout(() => {\n trigger(name as Path<TFieldValues>);\n }, 200);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [fields.length]);\n\n // Animation control: Start with animations disabled to prevent animating in initial elements.\n // Will be enabled after initialization completes (unless user prefers reduced motion).\n const [disableAnimation, setDisableAnimation] = useState(true);\n\n // Respond to user's motion preference changes (after initialization).\n // During initialization, animations stay disabled regardless of preference.\n const prefersReducedMotion = useReducedMotion();\n useEffect(() => {\n if (hasInitialized.current) {\n setDisableAnimation(!!prefersReducedMotion);\n }\n }, [prefersReducedMotion]);\n\n // Prepare initial element value based on mode\n // - flat=true: arrays of primitives → object with flatArrayKey and null value by default\n // - flat=false: arrays of objects → empty object by default\n const elementInitialValue = useMemo(() => {\n return flat\n ? { [flatArrayKey]: _elementInitialValue ?? null }\n : (_elementInitialValue ?? {});\n }, [flat, _elementInitialValue]);\n\n // Initialization/Re-initialization: Add initial element when needed.\n // This handles both initial mount and form reset scenarios by reacting to needsInitialize.\n // CRITICAL: This effect MUST be the LAST hook in this component.\n // It sets hasInitialized.current = true, which acts as a gate for other effects.\n // If this runs before other effects, hasInitialized will be true during their first run,\n // causing them to execute logic meant only for post-initialization (e.g., validation,\n // animation enabling). By placing this last, all other effects run first with\n // hasInitialized = false, allowing them to skip initialization-phase logic.\n useEffect(\n () => {\n if (needsInitialize) {\n // use setValue instead of append to avoid focusing the added element\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n setValue(name as Path<TFieldValues>, [elementInitialValue] as any, {\n shouldDirty: false,\n shouldTouch: false,\n });\n\n // Mark initialization as complete\n hasInitialized.current = true;\n\n // Enable animations after a brief delay (unless user prefers reduced motion or animations are already enabled).\n // This only runs on initial mount when animations start disabled.\n // On reset, disableAnimation is typically false, so this setTimeout won't run and animations stay enabled.\n if (!prefersReducedMotion && disableAnimation) {\n setTimeout(() => {\n setDisableAnimation(false);\n }, 1);\n }\n }\n },\n // Run when needsInitialize changes (initial mount or reset)\n // needsInitialize is memoized based on fields.length and lastElementNotRemovable\n // Other dependencies are intentionally omitted:\n // - append, setValue, trigger, setDisableAnimation are stable refs/functions\n // - elementInitialValue, name, flat, prefersReducedMotion, disableAnimation are props/stable values\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [needsInitialize],\n );\n\n return {\n // Field array methods and state\n fields,\n append,\n remove,\n insert,\n move,\n disableAnimation,\n elementInitialValue,\n // Uniform field state and utilities (spread all)\n ...uniformField,\n };\n};\n","/* v8 ignore start */\n\nexport * from './useUniformFieldArray';\n\n/* v8 ignore stop */\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA2CA,MAAa,wBAEX,EACA,MACA,OAAO,OACP,qBAAqB,uBAAuB,MAC5C,0BAA0B,OAC1B,UACA,QAAQ,gBACR,YAC6C;CAE7C,MAAM,eAAe,gBAA8B;EAC3C;EACN;EACA,QAAQ;EACR;EACD,CAAC;CAEF,MAAM,EAAE,YAAY;CAEpB,MAAM,EAAE,QAAQ,QAAQ,QAAQ,QAAQ,SAASA,cAAiB;EAChE;EACA;EACD,CAAC;CAEF,MAAM,EAAE,SAAS,aAAaC,kBAA8B;CAQ5D,MAAM,kBAAkB,cAAc;AACpC,SAAO,2BAA2B,OAAO,WAAW;IACnD,CAAC,yBAAyB,OAAO,OAAO,CAAC;CAS5C,MAAM,iBAAiB,OAAO,CAAC,gBAAgB;AAK/C,iBAAgB;AACd,MAAI,gBACF,gBAAe,UAAU;IAE1B,CAAC,gBAAgB,CAAC;AAOrB,iBAAgB;AACd,MAAI,eAAe,QACjB,kBAAiB;AACf,WAAQ,KAA2B;KAClC,IAAI;IAGR,CAAC,OAAO,OAAO,CAAC;CAInB,MAAM,CAAC,kBAAkB,uBAAuB,SAAS,KAAK;CAI9D,MAAM,uBAAuB,kBAAkB;AAC/C,iBAAgB;AACd,MAAI,eAAe,QACjB,qBAAoB,CAAC,CAAC,qBAAqB;IAE5C,CAAC,qBAAqB,CAAC;CAK1B,MAAM,sBAAsB,cAAc;AACxC,SAAO,OACH,GAAG,eAAe,wBAAwB,MAAM,GAC/C,wBAAwB,EAAE;IAC9B,CAAC,MAAM,qBAAqB,CAAC;AAUhC,iBACQ;AACJ,MAAI,iBAAiB;AAGnB,YAAS,MAA4B,CAAC,oBAAoB,EAAS;IACjE,aAAa;IACb,aAAa;IACd,CAAC;AAGF,kBAAe,UAAU;AAKzB,OAAI,CAAC,wBAAwB,iBAC3B,kBAAiB;AACf,wBAAoB,MAAM;MACzB,EAAE;;IAUX,CAAC,gBAAgB,CAClB;AAED,QAAO;EAEL;EACA;EACA;EACA;EACA;EACA;EACA;EAEA,GAAG;EACJ"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
const require_FormContext = require('./FormContext-
|
|
2
|
-
const require_helpers = require('./helpers-
|
|
3
|
-
const require_useFormContext = require('./useFormContext-
|
|
4
|
-
const require_useUniformField = require('./useUniformField-
|
|
1
|
+
const require_FormContext = require('./FormContext-Lw4YL4-B.cjs');
|
|
2
|
+
const require_helpers = require('./helpers-nYTmL2gX.cjs');
|
|
3
|
+
const require_useFormContext = require('./useFormContext-CEr3zcL6.cjs');
|
|
4
|
+
const require_useUniformField = require('./useUniformField-D6fwSjrH.cjs');
|
|
5
5
|
let react = require("react");
|
|
6
|
-
let
|
|
6
|
+
let _fuf_stack_pixel_motion = require("@fuf-stack/pixel-motion");
|
|
7
7
|
let react_hook_form = require("react-hook-form");
|
|
8
8
|
|
|
9
9
|
//#region src/hooks/useUniformFieldArray/useUniformFieldArray.ts
|
|
@@ -45,7 +45,7 @@ const useUniformFieldArray = ({ name, flat = false, elementInitialValue: _elemen
|
|
|
45
45
|
}, 200);
|
|
46
46
|
}, [fields.length]);
|
|
47
47
|
const [disableAnimation, setDisableAnimation] = (0, react.useState)(true);
|
|
48
|
-
const prefersReducedMotion = (0,
|
|
48
|
+
const prefersReducedMotion = (0, _fuf_stack_pixel_motion.useReducedMotion)();
|
|
49
49
|
(0, react.useEffect)(() => {
|
|
50
50
|
if (hasInitialized.current) setDisableAnimation(!!prefersReducedMotion);
|
|
51
51
|
}, [prefersReducedMotion]);
|
|
@@ -87,4 +87,4 @@ Object.defineProperty(exports, 'useUniformFieldArray', {
|
|
|
87
87
|
return useUniformFieldArray;
|
|
88
88
|
}
|
|
89
89
|
});
|
|
90
|
-
//# sourceMappingURL=useUniformFieldArray-
|
|
90
|
+
//# sourceMappingURL=useUniformFieldArray-Byfmzq97.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUniformFieldArray-Byfmzq97.cjs","names":["useUniformField","useFormContext","flatArrayKey"],"sources":["../src/hooks/useUniformFieldArray/useUniformFieldArray.ts","../src/hooks/useUniformFieldArray/index.ts"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { ArrayPath, FieldValues, Path } from 'react-hook-form';\n\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { useFieldArray as useRHFFieldArray } from 'react-hook-form';\n\nimport { useReducedMotion } from '@fuf-stack/pixel-motion';\n\nimport { flatArrayKey } from '../../helpers';\nimport { useFormContext } from '../useFormContext';\nimport { useUniformField } from '../useUniformField';\n\nexport interface UseUniformFieldArrayProps<\n TFieldValues extends FieldValues = FieldValues,\n> {\n /** Field name for the array */\n name: ArrayPath<TFieldValues>;\n /** Whether this is a flat array (array of primitives) */\n flat?: boolean;\n /** Initial value for new array elements */\n elementInitialValue?: unknown;\n /** Whether the last element cannot be removed (always maintain at least one element) */\n lastElementNotRemovable?: boolean;\n /** Disable the field */\n disabled?: boolean;\n /** Optional explicit test id used to build stable test ids */\n testId?: string;\n /** Optional label content */\n label?: ReactNode;\n}\n\n/**\n * Enhanced useFieldArray hook with initialization and animation logic.\n * Based on React Hook Form's useFieldArray with additional features:\n * - Automatic initialization when lastElementNotRemovable is set\n * - Animation control (disabled during initialization)\n * - Support for flat arrays (arrays of primitives)\n *\n * Note: Automatic validation triggering on length change is disabled to prevent\n * triggering form-wide validation. Array validation still runs on form submission.\n *\n * @see https://react-hook-form.com/docs/usefieldarray\n */\nexport const useUniformFieldArray = <\n TFieldValues extends FieldValues = FieldValues,\n>({\n name,\n flat = false,\n elementInitialValue: _elementInitialValue = null,\n lastElementNotRemovable = false,\n disabled,\n testId: explicitTestId,\n label,\n}: UseUniformFieldArrayProps<TFieldValues>) => {\n // Get uniform field state and utilities\n const uniformField = useUniformField<TFieldValues>({\n name: name as Path<TFieldValues> & string,\n disabled,\n testId: explicitTestId,\n label,\n });\n\n const { control } = uniformField;\n\n const { fields, append, remove, insert, move } = useRHFFieldArray({\n control,\n name,\n });\n\n const { trigger, setValue } = useFormContext<TFieldValues>();\n\n // Determine if initialization is needed (initially or after reset).\n // This flag automatically handles both scenarios:\n // - Initial mount: fields.length starts at 0\n // - Form reset: fields.length becomes 0 again\n // Additional initialization conditions can be added here later (e.g., minElements > 0)\n // Using useMemo ensures this value is properly tracked by React and effects can depend on it\n const needsInitialize = useMemo(() => {\n return lastElementNotRemovable && fields.length === 0;\n }, [lastElementNotRemovable, fields.length]);\n\n // Track whether initialization has completed. Initialized contextually:\n // - If initialization IS needed (needsInitialize = true): starts as false, set to true after init\n // - If initialization is NOT needed (needsInitialize = false): starts as true (already initialized)\n // This ref is used to:\n // 1. Skip validation during initialization/re-initialization\n // 2. Gate animation enabling until after initialization\n // 3. Gate motion preference effect until after initialization\n const hasInitialized = useRef(!needsInitialize);\n\n // Reset initialization flag when needsInitialize changes to true.\n // This handles form reset: when fields become empty (needsInitialize becomes true),\n // hasInitialized is reset to false, triggering re-initialization in the effect below.\n useEffect(() => {\n if (needsInitialize) {\n hasInitialized.current = false;\n }\n }, [needsInitialize]);\n\n // Validate array-level constraints (min/max items) when length changes.\n // This ensures min/max errors appear instantly when user adds/removes items.\n // Note: Child field validation also runs, but new empty fields won't show as invalid\n // because useFormContext only sets invalid=true for touched fields or after form submission.\n // Skip validation during initialization/re-initialization to avoid showing errors prematurely.\n useEffect(() => {\n if (hasInitialized.current) {\n setTimeout(() => {\n trigger(name as Path<TFieldValues>);\n }, 200);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [fields.length]);\n\n // Animation control: Start with animations disabled to prevent animating in initial elements.\n // Will be enabled after initialization completes (unless user prefers reduced motion).\n const [disableAnimation, setDisableAnimation] = useState(true);\n\n // Respond to user's motion preference changes (after initialization).\n // During initialization, animations stay disabled regardless of preference.\n const prefersReducedMotion = useReducedMotion();\n useEffect(() => {\n if (hasInitialized.current) {\n setDisableAnimation(!!prefersReducedMotion);\n }\n }, [prefersReducedMotion]);\n\n // Prepare initial element value based on mode\n // - flat=true: arrays of primitives → object with flatArrayKey and null value by default\n // - flat=false: arrays of objects → empty object by default\n const elementInitialValue = useMemo(() => {\n return flat\n ? { [flatArrayKey]: _elementInitialValue ?? null }\n : (_elementInitialValue ?? {});\n }, [flat, _elementInitialValue]);\n\n // Initialization/Re-initialization: Add initial element when needed.\n // This handles both initial mount and form reset scenarios by reacting to needsInitialize.\n // CRITICAL: This effect MUST be the LAST hook in this component.\n // It sets hasInitialized.current = true, which acts as a gate for other effects.\n // If this runs before other effects, hasInitialized will be true during their first run,\n // causing them to execute logic meant only for post-initialization (e.g., validation,\n // animation enabling). By placing this last, all other effects run first with\n // hasInitialized = false, allowing them to skip initialization-phase logic.\n useEffect(\n () => {\n if (needsInitialize) {\n // use setValue instead of append to avoid focusing the added element\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n setValue(name as Path<TFieldValues>, [elementInitialValue] as any, {\n shouldDirty: false,\n shouldTouch: false,\n });\n\n // Mark initialization as complete\n hasInitialized.current = true;\n\n // Enable animations after a brief delay (unless user prefers reduced motion or animations are already enabled).\n // This only runs on initial mount when animations start disabled.\n // On reset, disableAnimation is typically false, so this setTimeout won't run and animations stay enabled.\n if (!prefersReducedMotion && disableAnimation) {\n setTimeout(() => {\n setDisableAnimation(false);\n }, 1);\n }\n }\n },\n // Run when needsInitialize changes (initial mount or reset)\n // needsInitialize is memoized based on fields.length and lastElementNotRemovable\n // Other dependencies are intentionally omitted:\n // - append, setValue, trigger, setDisableAnimation are stable refs/functions\n // - elementInitialValue, name, flat, prefersReducedMotion, disableAnimation are props/stable values\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [needsInitialize],\n );\n\n return {\n // Field array methods and state\n fields,\n append,\n remove,\n insert,\n move,\n disableAnimation,\n elementInitialValue,\n // Uniform field state and utilities (spread all)\n ...uniformField,\n };\n};\n","/* v8 ignore start */\n\nexport * from './useUniformFieldArray';\n\n/* v8 ignore stop */\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA2CA,MAAa,wBAEX,EACA,MACA,OAAO,OACP,qBAAqB,uBAAuB,MAC5C,0BAA0B,OAC1B,UACA,QAAQ,gBACR,YAC6C;CAE7C,MAAM,eAAeA,wCAA8B;EAC3C;EACN;EACA,QAAQ;EACR;EACD,CAAC;CAEF,MAAM,EAAE,YAAY;CAEpB,MAAM,EAAE,QAAQ,QAAQ,QAAQ,QAAQ,4CAA0B;EAChE;EACA;EACD,CAAC;CAEF,MAAM,EAAE,SAAS,aAAaC,uCAA8B;CAQ5D,MAAM,2CAAgC;AACpC,SAAO,2BAA2B,OAAO,WAAW;IACnD,CAAC,yBAAyB,OAAO,OAAO,CAAC;CAS5C,MAAM,mCAAwB,CAAC,gBAAgB;AAK/C,4BAAgB;AACd,MAAI,gBACF,gBAAe,UAAU;IAE1B,CAAC,gBAAgB,CAAC;AAOrB,4BAAgB;AACd,MAAI,eAAe,QACjB,kBAAiB;AACf,WAAQ,KAA2B;KAClC,IAAI;IAGR,CAAC,OAAO,OAAO,CAAC;CAInB,MAAM,CAAC,kBAAkB,2CAAgC,KAAK;CAI9D,MAAM,sEAAyC;AAC/C,4BAAgB;AACd,MAAI,eAAe,QACjB,qBAAoB,CAAC,CAAC,qBAAqB;IAE5C,CAAC,qBAAqB,CAAC;CAK1B,MAAM,+CAAoC;AACxC,SAAO,OACH,GAAGC,+BAAe,wBAAwB,MAAM,GAC/C,wBAAwB,EAAE;IAC9B,CAAC,MAAM,qBAAqB,CAAC;AAUhC,4BACQ;AACJ,MAAI,iBAAiB;AAGnB,YAAS,MAA4B,CAAC,oBAAoB,EAAS;IACjE,aAAa;IACb,aAAa;IACd,CAAC;AAGF,kBAAe,UAAU;AAKzB,OAAI,CAAC,wBAAwB,iBAC3B,kBAAiB;AACf,wBAAoB,MAAM;MACzB,EAAE;;IAUX,CAAC,gBAAgB,CAClB;AAED,QAAO;EAEL;EACA;EACA;EACA;EACA;EACA;EACA;EAEA,GAAG;EACJ"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { r as useController } from "./useController-
|
|
2
|
-
import { n as useFormContext } from "./useFormContext
|
|
1
|
+
import { r as useController } from "./useController-BArZd2Vp.cjs";
|
|
2
|
+
import { n as useFormContext } from "./useFormContext--yod5xzQ.cjs";
|
|
3
3
|
import { ReactNode } from "react";
|
|
4
4
|
import * as react_hook_form14 from "react-hook-form";
|
|
5
5
|
import { ArrayPath, FieldValues } from "react-hook-form";
|
|
@@ -76,4 +76,4 @@ declare const useUniformFieldArray: <TFieldValues extends FieldValues = FieldVal
|
|
|
76
76
|
};
|
|
77
77
|
//#endregion
|
|
78
78
|
export { useUniformFieldArray as n, UseUniformFieldArrayProps as t };
|
|
79
|
-
//# sourceMappingURL=useUniformFieldArray-
|
|
79
|
+
//# sourceMappingURL=useUniformFieldArray-WRuIMhw6.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUniformFieldArray-WRuIMhw6.d.cts","names":[],"sources":["../src/hooks/useUniformFieldArray/useUniformFieldArray.ts"],"sourcesContent":[],"mappings":";;;;;;;;UAYiB,+CACM,cAAc;;QAG7B,UAAU;;;EAJD;EACM,mBAAA,CAAA,EAAA,OAAA;EAAc;EAGnB,uBAAA,CAAA,EAAA,OAAA;EAAV;EAYE,QAAA,CAAA,EAAA,OAAA;EAAS;EAeN,MAAA,CAAA,EAAA,MAAA;EACU;EAAc,KAAA,CAAA,EAhB3B,SAgB2B;;;;;;;;;;;;;;cADxB,4CACU,cAAc;;;uBACnC;;;UAAA;;GAQC,0BAA0B;;;;;;;;;;;;;;;;;EAuDpB,KAAA,WAAA,GAAA,IAAA;EAAA,MAAA,EAAA,UAAA,CAAA,oBAAA,CAAA,CAAA,OAAA,CAAA,CAAA,QAAA,CAAA;EAKwC,QAAA,EAAA,UAAA,CAAA,OALxC,aAKwC,CAAA,CAAA,OAAA,CAAA,CAAA,UAAA,CAAA;EAAA,GAAA,EACyB,UADzB,CAAA,OAAA,aAAA,CAAA,CAAA,OAAA,CAAA,CAAA,KAAA,CAAA;EACyB,QAAA,EAAA,OAAA"}
|
|
@@ -75,4 +75,4 @@ declare const useWatchUserChange: <TFieldValues extends FieldValues = FieldValue
|
|
|
75
75
|
}: UseWatchUserChangeOptions<TFieldValues>) => void;
|
|
76
76
|
//#endregion
|
|
77
77
|
export { useWatchUserChange as n, UseWatchUserChangeOptions as t };
|
|
78
|
-
//# sourceMappingURL=useWatchUserChange-
|
|
78
|
+
//# sourceMappingURL=useWatchUserChange-Bf5JKDJJ.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWatchUserChange-
|
|
1
|
+
{"version":3,"file":"useWatchUserChange-Bf5JKDJJ.d.ts","names":[],"sources":["../src/hooks/useWatchUserChange/useWatchUserChange.ts"],"sourcesContent":[],"mappings":";;;UAYiB,+CAA+C;;EAA/C,KAAA,EAER,IAFQ,CAEH,YAFG,CAAA;EAA+C;;;;EAUhD,QAAA,EAAA,CAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA;IACoB,QAAA,EADpB,eACoB,CADJ,YACI,CAAA;IAAlB,UAAA,EAAA,iBAAA,CAAkB,YAAlB,CAAA;IACQ,KAAA,EAAb,YAAa,CAAA,YAAA,CAAA;EAAb,CAAA,EAAA,GAAA,IAAA;;AA4Db;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAAa,0CACU,cAAc;SACnC;;GAGC,0BAA0B"}
|
|
@@ -75,4 +75,4 @@ declare const useWatchUserChange: <TFieldValues extends FieldValues = FieldValue
|
|
|
75
75
|
}: UseWatchUserChangeOptions<TFieldValues>) => void;
|
|
76
76
|
//#endregion
|
|
77
77
|
export { useWatchUserChange as n, UseWatchUserChangeOptions as t };
|
|
78
|
-
//# sourceMappingURL=useWatchUserChange-
|
|
78
|
+
//# sourceMappingURL=useWatchUserChange-Br4Q7syM.d.cts.map
|
package/dist/{useWatchUserChange-COVdHmki.d.cts.map → useWatchUserChange-Br4Q7syM.d.cts.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWatchUserChange-
|
|
1
|
+
{"version":3,"file":"useWatchUserChange-Br4Q7syM.d.cts","names":[],"sources":["../src/hooks/useWatchUserChange/useWatchUserChange.ts"],"sourcesContent":[],"mappings":";;;UAYiB,+CAA+C;;EAA/C,KAAA,EAER,IAFQ,CAEH,YAFG,CAAA;EAA+C;;;;EAUhD,QAAA,EAAA,CAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA;IACoB,QAAA,EADpB,eACoB,CADJ,YACI,CAAA;IAAlB,UAAA,EAAA,iBAAA,CAAkB,YAAlB,CAAA;IACQ,KAAA,EAAb,YAAa,CAAA,YAAA,CAAA;EAAb,CAAA,EAAA,GAAA,IAAA;;AA4Db;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAAa,0CACU,cAAc;SACnC;;GAGC,0BAA0B"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const require_FormContext = require('./FormContext-
|
|
2
|
-
const require_useFormContext = require('./useFormContext-
|
|
1
|
+
const require_FormContext = require('./FormContext-Lw4YL4-B.cjs');
|
|
2
|
+
const require_useFormContext = require('./useFormContext-CEr3zcL6.cjs');
|
|
3
3
|
let react = require("react");
|
|
4
4
|
|
|
5
5
|
//#region src/hooks/useWatchUserChange/useWatchUserChange.ts
|
|
@@ -86,4 +86,4 @@ Object.defineProperty(exports, 'useWatchUserChange', {
|
|
|
86
86
|
return useWatchUserChange;
|
|
87
87
|
}
|
|
88
88
|
});
|
|
89
|
-
//# sourceMappingURL=useWatchUserChange-
|
|
89
|
+
//# sourceMappingURL=useWatchUserChange-TMfaTCcp.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWatchUserChange-
|
|
1
|
+
{"version":3,"file":"useWatchUserChange-TMfaTCcp.cjs","names":["useFormContext"],"sources":["../src/hooks/useWatchUserChange/useWatchUserChange.ts"],"sourcesContent":["import type {\n FieldValues,\n Path,\n UseFormReset,\n UseFormResetField,\n UseFormSetValue,\n} from 'react-hook-form';\n\nimport { useEffect } from 'react';\n\nimport { useFormContext } from '../useFormContext/useFormContext';\n\nexport interface UseWatchUserChangeOptions<TFieldValues extends FieldValues> {\n /** Field name to watch for user changes */\n watch: Path<TFieldValues>;\n /**\n * Callback when watched field is changed by user input.\n * Receives the new value and form helpers (setValue, resetField, reset).\n */\n onChange: (\n value: unknown,\n helpers: {\n setValue: UseFormSetValue<TFieldValues>;\n resetField: UseFormResetField<TFieldValues>;\n reset: UseFormReset<TFieldValues>;\n },\n ) => void;\n}\n\n/**\n * Hook that watches for user changes on a specific form field.\n *\n * Only triggers on manual user input (typing, clicking, selecting),\n * NOT on programmatic changes like form.reset() or form.setValue().\n *\n * This hook subscribes to field changes at the source (useController),\n * ensuring immediate and accurate detection of user interactions.\n *\n * Use cases:\n * - Reset dependent fields when parent field changes\n * - Set mode-specific default values when a toggle changes\n * - Clear form sections based on user selections\n * - Trigger side effects only on user interaction\n *\n * Note: To watch multiple fields, call this hook multiple times.\n *\n * @example\n * ```tsx\n * // Reset city and address when user changes country\n * useWatchUserChange({\n * watch: 'country',\n * onChange: (value, { resetField }) => {\n * resetField('city');\n * resetField('address');\n * },\n * });\n *\n * // Set defaults when user changes payment method\n * useWatchUserChange({\n * watch: 'paymentMethod',\n * onChange: (value, { setValue }) => {\n * if (value === 'credit') {\n * setValue('installments', 3);\n * } else {\n * setValue('installments', 1);\n * }\n * },\n * });\n *\n * // Watch multiple fields by calling the hook multiple times\n * useWatchUserChange({\n * watch: 'category',\n * onChange: (value, { resetField }) => {\n * resetField('productId');\n * },\n * });\n * useWatchUserChange({\n * watch: 'brand',\n * onChange: (value, { resetField }) => {\n * resetField('productId');\n * },\n * });\n * ```\n */\nexport const useWatchUserChange = <\n TFieldValues extends FieldValues = FieldValues,\n>({\n watch: watchField,\n onChange,\n}: UseWatchUserChangeOptions<TFieldValues>) => {\n const { setValue, resetField, reset, userChange } =\n useFormContext<TFieldValues>();\n\n useEffect(() => {\n // Create listener that checks if changed field is the one we're watching\n const listener = (fieldName: Path<TFieldValues>, value: unknown) => {\n // Check if this is the field we're watching\n if (fieldName === watchField) {\n // Call the onChange callback with helpers\n onChange(value, { setValue, resetField, reset });\n }\n };\n\n // Subscribe to user changes\n const unsubscribe = userChange.subscribe(listener);\n\n // Cleanup on unmount\n return unsubscribe;\n }, [watchField, onChange, setValue, resetField, reset, userChange]);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoFA,MAAa,sBAEX,EACA,OAAO,YACP,eAC6C;CAC7C,MAAM,EAAE,UAAU,YAAY,OAAO,eACnCA,uCAA8B;AAEhC,4BAAgB;EAEd,MAAM,YAAY,WAA+B,UAAmB;AAElE,OAAI,cAAc,WAEhB,UAAS,OAAO;IAAE;IAAU;IAAY;IAAO,CAAC;;AAQpD,SAHoB,WAAW,UAAU,SAAS;IAIjD;EAAC;EAAY;EAAU;EAAU;EAAY;EAAO;EAAW,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as useFormContext } from "./useFormContext-
|
|
1
|
+
import { n as useFormContext } from "./useFormContext-BFoXZNkp.js";
|
|
2
2
|
import { useEffect } from "react";
|
|
3
3
|
|
|
4
4
|
//#region src/hooks/useWatchUserChange/useWatchUserChange.ts
|
|
@@ -80,4 +80,4 @@ const useWatchUserChange = ({ watch: watchField, onChange }) => {
|
|
|
80
80
|
|
|
81
81
|
//#endregion
|
|
82
82
|
export { useWatchUserChange as t };
|
|
83
|
-
//# sourceMappingURL=useWatchUserChange-
|
|
83
|
+
//# sourceMappingURL=useWatchUserChange-fZy6nGtD.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWatchUserChange-
|
|
1
|
+
{"version":3,"file":"useWatchUserChange-fZy6nGtD.js","names":[],"sources":["../src/hooks/useWatchUserChange/useWatchUserChange.ts"],"sourcesContent":["import type {\n FieldValues,\n Path,\n UseFormReset,\n UseFormResetField,\n UseFormSetValue,\n} from 'react-hook-form';\n\nimport { useEffect } from 'react';\n\nimport { useFormContext } from '../useFormContext/useFormContext';\n\nexport interface UseWatchUserChangeOptions<TFieldValues extends FieldValues> {\n /** Field name to watch for user changes */\n watch: Path<TFieldValues>;\n /**\n * Callback when watched field is changed by user input.\n * Receives the new value and form helpers (setValue, resetField, reset).\n */\n onChange: (\n value: unknown,\n helpers: {\n setValue: UseFormSetValue<TFieldValues>;\n resetField: UseFormResetField<TFieldValues>;\n reset: UseFormReset<TFieldValues>;\n },\n ) => void;\n}\n\n/**\n * Hook that watches for user changes on a specific form field.\n *\n * Only triggers on manual user input (typing, clicking, selecting),\n * NOT on programmatic changes like form.reset() or form.setValue().\n *\n * This hook subscribes to field changes at the source (useController),\n * ensuring immediate and accurate detection of user interactions.\n *\n * Use cases:\n * - Reset dependent fields when parent field changes\n * - Set mode-specific default values when a toggle changes\n * - Clear form sections based on user selections\n * - Trigger side effects only on user interaction\n *\n * Note: To watch multiple fields, call this hook multiple times.\n *\n * @example\n * ```tsx\n * // Reset city and address when user changes country\n * useWatchUserChange({\n * watch: 'country',\n * onChange: (value, { resetField }) => {\n * resetField('city');\n * resetField('address');\n * },\n * });\n *\n * // Set defaults when user changes payment method\n * useWatchUserChange({\n * watch: 'paymentMethod',\n * onChange: (value, { setValue }) => {\n * if (value === 'credit') {\n * setValue('installments', 3);\n * } else {\n * setValue('installments', 1);\n * }\n * },\n * });\n *\n * // Watch multiple fields by calling the hook multiple times\n * useWatchUserChange({\n * watch: 'category',\n * onChange: (value, { resetField }) => {\n * resetField('productId');\n * },\n * });\n * useWatchUserChange({\n * watch: 'brand',\n * onChange: (value, { resetField }) => {\n * resetField('productId');\n * },\n * });\n * ```\n */\nexport const useWatchUserChange = <\n TFieldValues extends FieldValues = FieldValues,\n>({\n watch: watchField,\n onChange,\n}: UseWatchUserChangeOptions<TFieldValues>) => {\n const { setValue, resetField, reset, userChange } =\n useFormContext<TFieldValues>();\n\n useEffect(() => {\n // Create listener that checks if changed field is the one we're watching\n const listener = (fieldName: Path<TFieldValues>, value: unknown) => {\n // Check if this is the field we're watching\n if (fieldName === watchField) {\n // Call the onChange callback with helpers\n onChange(value, { setValue, resetField, reset });\n }\n };\n\n // Subscribe to user changes\n const unsubscribe = userChange.subscribe(listener);\n\n // Cleanup on unmount\n return unsubscribe;\n }, [watchField, onChange, setValue, resetField, reset, userChange]);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoFA,MAAa,sBAEX,EACA,OAAO,YACP,eAC6C;CAC7C,MAAM,EAAE,UAAU,YAAY,OAAO,eACnC,gBAA8B;AAEhC,iBAAgB;EAEd,MAAM,YAAY,WAA+B,UAAmB;AAElE,OAAI,cAAc,WAEhB,UAAS,OAAO;IAAE;IAAU;IAAY;IAAO,CAAC;;AAQpD,SAHoB,WAAW,UAAU,SAAS;IAIjD;EAAC;EAAY;EAAU;EAAU;EAAY;EAAO;EAAW,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fuf-stack/uniform",
|
|
3
|
-
"version": "1.11.
|
|
3
|
+
"version": "1.11.3",
|
|
4
4
|
"description": "fuf react form library",
|
|
5
5
|
"author": "Fröhlich ∧ Frei",
|
|
6
6
|
"homepage": "https://github.com/fuf-stack/pixels#readme",
|
|
@@ -153,10 +153,10 @@
|
|
|
153
153
|
"@dnd-kit/modifiers": "9.0.0",
|
|
154
154
|
"@dnd-kit/sortable": "10.0.0",
|
|
155
155
|
"@dnd-kit/utilities": "3.2.2",
|
|
156
|
-
"@fuf-stack/pixel-motion": "1.1.
|
|
157
|
-
"@fuf-stack/pixel-utils": "1.1.
|
|
158
|
-
"@fuf-stack/pixels": "1.7.
|
|
159
|
-
"@fuf-stack/veto": "0.13.
|
|
156
|
+
"@fuf-stack/pixel-motion": "1.1.1",
|
|
157
|
+
"@fuf-stack/pixel-utils": "1.1.1",
|
|
158
|
+
"@fuf-stack/pixels": "1.7.1",
|
|
159
|
+
"@fuf-stack/veto": "0.13.2",
|
|
160
160
|
"@heroui/button": "2.2.24",
|
|
161
161
|
"@heroui/checkbox": "2.3.24",
|
|
162
162
|
"@heroui/input": "2.4.25",
|
|
@@ -167,19 +167,19 @@
|
|
|
167
167
|
"@heroui/switch": "2.2.22",
|
|
168
168
|
"@heroui/system": "2.4.20",
|
|
169
169
|
"@heroui/theme": "2.4.20",
|
|
170
|
-
"@react-aria/visually-hidden": "3.8.
|
|
170
|
+
"@react-aria/visually-hidden": "3.8.29",
|
|
171
171
|
"debug": "4.4.3",
|
|
172
|
-
"framer-motion": "12.
|
|
173
|
-
"react-hook-form": "7.
|
|
172
|
+
"framer-motion": "12.26.2",
|
|
173
|
+
"react-hook-form": "7.71.1",
|
|
174
174
|
"react-icons": "5.5.0",
|
|
175
175
|
"react-select": "5.10.2"
|
|
176
176
|
},
|
|
177
177
|
"devDependencies": {
|
|
178
178
|
"@types/debug": "4.1.12",
|
|
179
|
-
"@types/react": "19.2.
|
|
179
|
+
"@types/react": "19.2.8",
|
|
180
180
|
"@types/react-dom": "19.2.3",
|
|
181
181
|
"react": "19.2.3",
|
|
182
182
|
"react-dom": "19.2.3"
|
|
183
183
|
},
|
|
184
|
-
"gitHead": "
|
|
184
|
+
"gitHead": "b68c72db4df79ae8c5efcf07e42daac808c0a9aa"
|
|
185
185
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Checkboxes-CGWhnpBp.js","names":["heroCheckboxVariants","FieldValidationError","heroCheckboxGroupClassNames: HeroCheckboxGroupProps['classNames']","heroCheckboxClassNames: HeroCheckboxProps['classNames']","HeroCheckboxGroup","labelContent: ReactNode","HeroCheckbox","Checkboxes"],"sources":["../src/Checkboxes/Checkboxes.tsx","../src/Checkboxes/index.ts"],"sourcesContent":["import type { TVClassName, TVProps } from '@fuf-stack/pixel-utils';\nimport type {\n CheckboxGroupProps as HeroCheckboxGroupProps,\n CheckboxProps as HeroCheckboxProps,\n} from '@heroui/checkbox';\nimport type { ReactNode } from 'react';\nimport type { FieldError } from 'react-hook-form';\nimport type { InputValueTransform } from '../hooks/useInputValueTransform';\n\nimport {\n Checkbox as HeroCheckbox,\n CheckboxGroup as HeroCheckboxGroup,\n} from '@heroui/checkbox';\nimport { checkbox as heroCheckboxVariants } from '@heroui/theme';\n\nimport { slugify, tv, variantsToClassNames } from '@fuf-stack/pixel-utils';\n\nimport { useUniformField } from '../hooks/useUniformField';\nimport { FieldValidationError } from '../partials/FieldValidationError';\n\nexport const checkboxesVariants = tv({\n slots: {\n base: 'group', // Needs group for group-data condition\n errorMessage: 'text-tiny',\n // see HeroUI styles for group-data condition,\n // e.g.: https://github.com/heroui-inc/heroui/blob/main/packages/core/theme/src/components/select.ts\n label:\n 'inline-flex text-sm text-foreground subpixel-antialiased group-data-[invalid=true]:!text-danger',\n optionBase: '',\n optionIcon: '',\n optionLabel: '',\n optionLabelSubline: 'text-foreground-400 !text-small',\n optionWrapper: '',\n wrapper: '',\n },\n variants: {\n // see: https://github.com/heroui-inc/heroui/blob/canary/packages/core/theme/src/components/checkbox.ts\n color: {\n info: {\n wrapper:\n 'text-info-foreground after:bg-info after:text-info-foreground',\n },\n ...heroCheckboxVariants.variants.color,\n } as const,\n lineThrough: {\n true: {\n optionLabel: [\n ...heroCheckboxVariants.variants.lineThrough.true.label,\n // fix stroke position when used with subline and enable animation\n 'relative before:transition-all before:duration-200',\n ],\n optionLabelSubline: 'group-data-[selected=true]:opacity-60',\n },\n },\n },\n});\n\ntype VariantProps = TVProps<typeof checkboxesVariants>;\ntype ClassName = TVClassName<typeof checkboxesVariants>;\n\nexport interface CheckboxOption {\n /** option label */\n label?: ReactNode;\n /** subline displayed below the label */\n labelSubline?: ReactNode;\n /** option value */\n value: string;\n /** disables the option */\n disabled?: boolean;\n /** HTML data-testid attribute of the option */\n testId?: string;\n}\n\nexport interface CheckboxesProps extends VariantProps {\n /** Custom aria-label for accessibility. If not provided, falls back to field name when no visible label exists */\n ariaLabel?: string;\n /** CSS class name */\n className?: ClassName;\n /** Color scheme of the checkboxes */\n color?: VariantProps['color'];\n /** Sets all checkboxes disabled */\n disabled?: boolean;\n /** Orientation of the checkboxes */\n inline?: boolean;\n /** Label displayed above the checkboxes */\n label?: ReactNode;\n /** Whether the checkboxes label should be crossed out */\n lineThrough?: boolean;\n /** Name the Field is registered on the form */\n name: string;\n /** Checkboxes that should be displayed. */\n options: CheckboxOption[];\n /** HTML data-testid attribute used in e2e tests */\n testId?: string;\n /** allows disentangled display and form values for a field */\n transform?: InputValueTransform<string[]>;\n}\n\n/**\n * Checkboxes component based on [HeroUI CheckboxGroup](https://www.heroui.com//docs/components/checkbox-group)\n */\nconst Checkboxes = ({\n className = undefined,\n color = 'primary',\n inline = false,\n lineThrough = false,\n options,\n name,\n ...uniformFieldProps\n}: CheckboxesProps) => {\n const {\n ariaLabel,\n disabled,\n error: _error,\n field: { onChange, value: fieldValue, ref, onBlur },\n invalid,\n label,\n required,\n testId,\n } = useUniformField({\n name,\n ...uniformFieldProps,\n });\n\n // Ensure value is always an array (checkboxes need arrays)\n const value = Array.isArray(fieldValue) ? fieldValue : [];\n\n // Convert React Hook Form's nested error object structure to a flat array\n // RHF errors can be nested like: checkboxField.0 (individual checkbox errors)\n // and checkboxField._error (global field errors) - this flattens all\n // error values into a single array for rendering with FieldValidationError\n const errorFlat: FieldError[] =\n (_error &&\n Object.values(\n _error as unknown as Record<string, FieldError[]>,\n ).flat()) ??\n [];\n const errorMessage = (\n <FieldValidationError error={errorFlat} testId={testId} />\n );\n\n // classNames from slots\n const variants = checkboxesVariants({ lineThrough });\n const classNames = variantsToClassNames(variants, className, 'base');\n\n // map slots to HeroUI class names\n const heroCheckboxGroupClassNames: HeroCheckboxGroupProps['classNames'] = {\n base: classNames.base,\n label: classNames.label,\n wrapper: classNames.wrapper,\n };\n const heroCheckboxClassNames: HeroCheckboxProps['classNames'] = {\n base: classNames.optionBase,\n icon: classNames.optionIcon,\n label: classNames.optionLabel,\n wrapper: classNames.optionWrapper,\n };\n\n return (\n <HeroCheckboxGroup\n ref={ref}\n aria-label={ariaLabel}\n classNames={heroCheckboxGroupClassNames}\n color={color === 'info' ? 'primary' : color}\n // see HeroUI styles for group-data condition (data-invalid),\n // e.g.: https://github.com/heroui-inc/heroui/blob/main/packages/components/select/src/use-select.ts\n data-invalid={invalid}\n data-testid={testId}\n errorMessage={errorMessage}\n isDisabled={disabled}\n isInvalid={invalid}\n isRequired={required}\n label={label ? <legend>{label}</legend> : null}\n name={name}\n onBlur={onBlur}\n onChange={onChange}\n orientation={inline ? 'horizontal' : 'vertical'}\n value={value}\n >\n {options?.map((option) => {\n const optionTestId = slugify(\n `${testId}_option_${option?.testId ?? option?.value}`,\n { replaceDots: true },\n );\n\n // set content and classes depending option has subline\n const hasSubline = !!option.labelSubline;\n let labelContent: ReactNode;\n let optionClassNames = heroCheckboxClassNames;\n if (hasSubline) {\n labelContent = (\n <div className=\"flex grow flex-col items-start\">\n <span className={classNames.optionLabel}>{option.label}</span>\n <span className={classNames.optionLabelSubline}>\n {option.labelSubline}\n </span>\n </div>\n );\n // remove label classes from outer label when subline is used\n optionClassNames = { ...optionClassNames, label: '' };\n } else {\n labelContent = option.label;\n }\n\n return (\n <HeroCheckbox\n key={`index_${option.value}`}\n classNames={optionClassNames}\n data-invalid={invalid}\n data-testid={optionTestId}\n isDisabled={!!disabled || option.disabled}\n value={option?.value}\n aria-label={\n typeof option.label === 'string' ? option.label : option.value\n }\n >\n {labelContent}\n </HeroCheckbox>\n );\n })}\n </HeroCheckboxGroup>\n );\n};\n\nexport default Checkboxes;\n","import Checkboxes from './Checkboxes';\n\nexport type { CheckboxesProps, CheckboxOption } from './Checkboxes';\n\nexport { Checkboxes };\n\nexport default Checkboxes;\n"],"mappings":";;;;;;;;AAoBA,MAAa,qBAAqB,GAAG;CACnC,OAAO;EACL,MAAM;EACN,cAAc;EAGd,OACE;EACF,YAAY;EACZ,YAAY;EACZ,aAAa;EACb,oBAAoB;EACpB,eAAe;EACf,SAAS;EACV;CACD,UAAU;EAER,OAAO;GACL,MAAM,EACJ,SACE,iEACH;GACD,GAAGA,SAAqB,SAAS;GAClC;EACD,aAAa,EACX,MAAM;GACJ,aAAa,CACX,GAAGA,SAAqB,SAAS,YAAY,KAAK,OAElD,qDACD;GACD,oBAAoB;GACrB,EACF;EACF;CACF,CAAC;;;;AA8CF,MAAM,cAAc,EAClB,YAAY,QACZ,QAAQ,WACR,SAAS,OACT,cAAc,OACd,SACA,MACA,GAAG,wBACkB;CACrB,MAAM,EACJ,WACA,UACA,OAAO,QACP,OAAO,EAAE,UAAU,OAAO,YAAY,KAAK,UAC3C,SACA,OACA,UACA,WACE,gBAAgB;EAClB;EACA,GAAG;EACJ,CAAC;CAGF,MAAM,QAAQ,MAAM,QAAQ,WAAW,GAAG,aAAa,EAAE;CAYzD,MAAM,eACJ,oBAACC;EAAqB,QANrB,UACC,OAAO,OACL,OACD,CAAC,MAAM,KACV,EAAE;EAE8C;GAAU;CAK5D,MAAM,aAAa,qBADF,mBAAmB,EAAE,aAAa,CAAC,EACF,WAAW,OAAO;CAGpE,MAAMC,8BAAoE;EACxE,MAAM,WAAW;EACjB,OAAO,WAAW;EAClB,SAAS,WAAW;EACrB;CACD,MAAMC,yBAA0D;EAC9D,MAAM,WAAW;EACjB,MAAM,WAAW;EACjB,OAAO,WAAW;EAClB,SAAS,WAAW;EACrB;AAED,QACE,oBAACC;EACM;EACL,cAAY;EACZ,YAAY;EACZ,OAAO,UAAU,SAAS,YAAY;EAGtC,gBAAc;EACd,eAAa;EACC;EACd,YAAY;EACZ,WAAW;EACX,YAAY;EACZ,OAAO,QAAQ,oBAAC,sBAAQ,QAAe,GAAG;EACpC;EACE;EACE;EACV,aAAa,SAAS,eAAe;EAC9B;YAEN,SAAS,KAAK,WAAW;GACxB,MAAM,eAAe,QACnB,GAAG,OAAO,UAAU,QAAQ,UAAU,QAAQ,SAC9C,EAAE,aAAa,MAAM,CACtB;GAGD,MAAM,aAAa,CAAC,CAAC,OAAO;GAC5B,IAAIC;GACJ,IAAI,mBAAmB;AACvB,OAAI,YAAY;AACd,mBACE,qBAAC;KAAI,WAAU;gBACb,oBAAC;MAAK,WAAW,WAAW;gBAAc,OAAO;OAAa,EAC9D,oBAAC;MAAK,WAAW,WAAW;gBACzB,OAAO;OACH;MACH;AAGR,uBAAmB;KAAE,GAAG;KAAkB,OAAO;KAAI;SAErD,gBAAe,OAAO;AAGxB,UACE,oBAACC;IAEC,YAAY;IACZ,gBAAc;IACd,eAAa;IACb,YAAY,CAAC,CAAC,YAAY,OAAO;IACjC,OAAO,QAAQ;IACf,cACE,OAAO,OAAO,UAAU,WAAW,OAAO,QAAQ,OAAO;cAG1D;MAVI,SAAS,OAAO,QAWR;IAEjB;GACgB;;AAIxB,yBAAe;;;;AC1Nf,2BAAeC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Checkboxes-Ds6bzl6p.cjs","names":["heroCheckboxVariants","useUniformField","FieldValidationError","heroCheckboxGroupClassNames: HeroCheckboxGroupProps['classNames']","heroCheckboxClassNames: HeroCheckboxProps['classNames']","HeroCheckboxGroup","labelContent: ReactNode","HeroCheckbox","Checkboxes"],"sources":["../src/Checkboxes/Checkboxes.tsx","../src/Checkboxes/index.ts"],"sourcesContent":["import type { TVClassName, TVProps } from '@fuf-stack/pixel-utils';\nimport type {\n CheckboxGroupProps as HeroCheckboxGroupProps,\n CheckboxProps as HeroCheckboxProps,\n} from '@heroui/checkbox';\nimport type { ReactNode } from 'react';\nimport type { FieldError } from 'react-hook-form';\nimport type { InputValueTransform } from '../hooks/useInputValueTransform';\n\nimport {\n Checkbox as HeroCheckbox,\n CheckboxGroup as HeroCheckboxGroup,\n} from '@heroui/checkbox';\nimport { checkbox as heroCheckboxVariants } from '@heroui/theme';\n\nimport { slugify, tv, variantsToClassNames } from '@fuf-stack/pixel-utils';\n\nimport { useUniformField } from '../hooks/useUniformField';\nimport { FieldValidationError } from '../partials/FieldValidationError';\n\nexport const checkboxesVariants = tv({\n slots: {\n base: 'group', // Needs group for group-data condition\n errorMessage: 'text-tiny',\n // see HeroUI styles for group-data condition,\n // e.g.: https://github.com/heroui-inc/heroui/blob/main/packages/core/theme/src/components/select.ts\n label:\n 'inline-flex text-sm text-foreground subpixel-antialiased group-data-[invalid=true]:!text-danger',\n optionBase: '',\n optionIcon: '',\n optionLabel: '',\n optionLabelSubline: 'text-foreground-400 !text-small',\n optionWrapper: '',\n wrapper: '',\n },\n variants: {\n // see: https://github.com/heroui-inc/heroui/blob/canary/packages/core/theme/src/components/checkbox.ts\n color: {\n info: {\n wrapper:\n 'text-info-foreground after:bg-info after:text-info-foreground',\n },\n ...heroCheckboxVariants.variants.color,\n } as const,\n lineThrough: {\n true: {\n optionLabel: [\n ...heroCheckboxVariants.variants.lineThrough.true.label,\n // fix stroke position when used with subline and enable animation\n 'relative before:transition-all before:duration-200',\n ],\n optionLabelSubline: 'group-data-[selected=true]:opacity-60',\n },\n },\n },\n});\n\ntype VariantProps = TVProps<typeof checkboxesVariants>;\ntype ClassName = TVClassName<typeof checkboxesVariants>;\n\nexport interface CheckboxOption {\n /** option label */\n label?: ReactNode;\n /** subline displayed below the label */\n labelSubline?: ReactNode;\n /** option value */\n value: string;\n /** disables the option */\n disabled?: boolean;\n /** HTML data-testid attribute of the option */\n testId?: string;\n}\n\nexport interface CheckboxesProps extends VariantProps {\n /** Custom aria-label for accessibility. If not provided, falls back to field name when no visible label exists */\n ariaLabel?: string;\n /** CSS class name */\n className?: ClassName;\n /** Color scheme of the checkboxes */\n color?: VariantProps['color'];\n /** Sets all checkboxes disabled */\n disabled?: boolean;\n /** Orientation of the checkboxes */\n inline?: boolean;\n /** Label displayed above the checkboxes */\n label?: ReactNode;\n /** Whether the checkboxes label should be crossed out */\n lineThrough?: boolean;\n /** Name the Field is registered on the form */\n name: string;\n /** Checkboxes that should be displayed. */\n options: CheckboxOption[];\n /** HTML data-testid attribute used in e2e tests */\n testId?: string;\n /** allows disentangled display and form values for a field */\n transform?: InputValueTransform<string[]>;\n}\n\n/**\n * Checkboxes component based on [HeroUI CheckboxGroup](https://www.heroui.com//docs/components/checkbox-group)\n */\nconst Checkboxes = ({\n className = undefined,\n color = 'primary',\n inline = false,\n lineThrough = false,\n options,\n name,\n ...uniformFieldProps\n}: CheckboxesProps) => {\n const {\n ariaLabel,\n disabled,\n error: _error,\n field: { onChange, value: fieldValue, ref, onBlur },\n invalid,\n label,\n required,\n testId,\n } = useUniformField({\n name,\n ...uniformFieldProps,\n });\n\n // Ensure value is always an array (checkboxes need arrays)\n const value = Array.isArray(fieldValue) ? fieldValue : [];\n\n // Convert React Hook Form's nested error object structure to a flat array\n // RHF errors can be nested like: checkboxField.0 (individual checkbox errors)\n // and checkboxField._error (global field errors) - this flattens all\n // error values into a single array for rendering with FieldValidationError\n const errorFlat: FieldError[] =\n (_error &&\n Object.values(\n _error as unknown as Record<string, FieldError[]>,\n ).flat()) ??\n [];\n const errorMessage = (\n <FieldValidationError error={errorFlat} testId={testId} />\n );\n\n // classNames from slots\n const variants = checkboxesVariants({ lineThrough });\n const classNames = variantsToClassNames(variants, className, 'base');\n\n // map slots to HeroUI class names\n const heroCheckboxGroupClassNames: HeroCheckboxGroupProps['classNames'] = {\n base: classNames.base,\n label: classNames.label,\n wrapper: classNames.wrapper,\n };\n const heroCheckboxClassNames: HeroCheckboxProps['classNames'] = {\n base: classNames.optionBase,\n icon: classNames.optionIcon,\n label: classNames.optionLabel,\n wrapper: classNames.optionWrapper,\n };\n\n return (\n <HeroCheckboxGroup\n ref={ref}\n aria-label={ariaLabel}\n classNames={heroCheckboxGroupClassNames}\n color={color === 'info' ? 'primary' : color}\n // see HeroUI styles for group-data condition (data-invalid),\n // e.g.: https://github.com/heroui-inc/heroui/blob/main/packages/components/select/src/use-select.ts\n data-invalid={invalid}\n data-testid={testId}\n errorMessage={errorMessage}\n isDisabled={disabled}\n isInvalid={invalid}\n isRequired={required}\n label={label ? <legend>{label}</legend> : null}\n name={name}\n onBlur={onBlur}\n onChange={onChange}\n orientation={inline ? 'horizontal' : 'vertical'}\n value={value}\n >\n {options?.map((option) => {\n const optionTestId = slugify(\n `${testId}_option_${option?.testId ?? option?.value}`,\n { replaceDots: true },\n );\n\n // set content and classes depending option has subline\n const hasSubline = !!option.labelSubline;\n let labelContent: ReactNode;\n let optionClassNames = heroCheckboxClassNames;\n if (hasSubline) {\n labelContent = (\n <div className=\"flex grow flex-col items-start\">\n <span className={classNames.optionLabel}>{option.label}</span>\n <span className={classNames.optionLabelSubline}>\n {option.labelSubline}\n </span>\n </div>\n );\n // remove label classes from outer label when subline is used\n optionClassNames = { ...optionClassNames, label: '' };\n } else {\n labelContent = option.label;\n }\n\n return (\n <HeroCheckbox\n key={`index_${option.value}`}\n classNames={optionClassNames}\n data-invalid={invalid}\n data-testid={optionTestId}\n isDisabled={!!disabled || option.disabled}\n value={option?.value}\n aria-label={\n typeof option.label === 'string' ? option.label : option.value\n }\n >\n {labelContent}\n </HeroCheckbox>\n );\n })}\n </HeroCheckboxGroup>\n );\n};\n\nexport default Checkboxes;\n","import Checkboxes from './Checkboxes';\n\nexport type { CheckboxesProps, CheckboxOption } from './Checkboxes';\n\nexport { Checkboxes };\n\nexport default Checkboxes;\n"],"mappings":";;;;;;;;;AAoBA,MAAa,qDAAwB;CACnC,OAAO;EACL,MAAM;EACN,cAAc;EAGd,OACE;EACF,YAAY;EACZ,YAAY;EACZ,aAAa;EACb,oBAAoB;EACpB,eAAe;EACf,SAAS;EACV;CACD,UAAU;EAER,OAAO;GACL,MAAM,EACJ,SACE,iEACH;GACD,GAAGA,wBAAqB,SAAS;GAClC;EACD,aAAa,EACX,MAAM;GACJ,aAAa,CACX,GAAGA,wBAAqB,SAAS,YAAY,KAAK,OAElD,qDACD;GACD,oBAAoB;GACrB,EACF;EACF;CACF,CAAC;;;;AA8CF,MAAM,cAAc,EAClB,YAAY,QACZ,QAAQ,WACR,SAAS,OACT,cAAc,OACd,SACA,MACA,GAAG,wBACkB;CACrB,MAAM,EACJ,WACA,UACA,OAAO,QACP,OAAO,EAAE,UAAU,OAAO,YAAY,KAAK,UAC3C,SACA,OACA,UACA,WACEC,wCAAgB;EAClB;EACA,GAAG;EACJ,CAAC;CAGF,MAAM,QAAQ,MAAM,QAAQ,WAAW,GAAG,aAAa,EAAE;CAYzD,MAAM,eACJ,2CAACC;EAAqB,QANrB,UACC,OAAO,OACL,OACD,CAAC,MAAM,KACV,EAAE;EAE8C;GAAU;CAK5D,MAAM,+DADW,mBAAmB,EAAE,aAAa,CAAC,EACF,WAAW,OAAO;CAGpE,MAAMC,8BAAoE;EACxE,MAAM,WAAW;EACjB,OAAO,WAAW;EAClB,SAAS,WAAW;EACrB;CACD,MAAMC,yBAA0D;EAC9D,MAAM,WAAW;EACjB,MAAM,WAAW;EACjB,OAAO,WAAW;EAClB,SAAS,WAAW;EACrB;AAED,QACE,2CAACC;EACM;EACL,cAAY;EACZ,YAAY;EACZ,OAAO,UAAU,SAAS,YAAY;EAGtC,gBAAc;EACd,eAAa;EACC;EACd,YAAY;EACZ,WAAW;EACX,YAAY;EACZ,OAAO,QAAQ,2CAAC,sBAAQ,QAAe,GAAG;EACpC;EACE;EACE;EACV,aAAa,SAAS,eAAe;EAC9B;YAEN,SAAS,KAAK,WAAW;GACxB,MAAM,oDACJ,GAAG,OAAO,UAAU,QAAQ,UAAU,QAAQ,SAC9C,EAAE,aAAa,MAAM,CACtB;GAGD,MAAM,aAAa,CAAC,CAAC,OAAO;GAC5B,IAAIC;GACJ,IAAI,mBAAmB;AACvB,OAAI,YAAY;AACd,mBACE,4CAAC;KAAI,WAAU;gBACb,2CAAC;MAAK,WAAW,WAAW;gBAAc,OAAO;OAAa,EAC9D,2CAAC;MAAK,WAAW,WAAW;gBACzB,OAAO;OACH;MACH;AAGR,uBAAmB;KAAE,GAAG;KAAkB,OAAO;KAAI;SAErD,gBAAe,OAAO;AAGxB,UACE,2CAACC;IAEC,YAAY;IACZ,gBAAc;IACd,eAAa;IACb,YAAY,CAAC,CAAC,YAAY,OAAO;IACjC,OAAO,QAAQ;IACf,cACE,OAAO,OAAO,UAAU,WAAW,OAAO,QAAQ,OAAO;cAG1D;MAVI,SAAS,OAAO,QAWR;IAEjB;GACgB;;AAIxB,yBAAe;;;;AC1Nf,2BAAeC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FieldArray-BexXN9bO.cjs","names":["Button","FaPlus","menuItems: MenuItem[]","FaCopy","VscInsert","FaTimes","Menu","Button","FaTimes","motion","FaGripVertical","CSS","listItemMotionVariants: MotionVariants","AnimatePresence","motion","SortDragHandle","Grid","ElementActionsMenu","ElementRemoveButton","useUniformField","useUniformField","AnimatePresence","motion","FieldValidationError","PointerSensor","KeyboardSensor","DndContext","closestCenter","restrictToVerticalAxis","restrictToWindowEdges","SortableContext","verticalListSortingStrategy","useUniformFieldArray","FieldArrayLabel","SortContext","flatArrayKey","elementMethods: FieldArrayElementMethods","FieldArrayElement","FieldArrayValidationError","ElementAppendButton","FieldArray"],"sources":["../src/FieldArray/subcomponents/ElementAppendButton.tsx","../src/FieldArray/subcomponents/ElementActionsMenu.tsx","../src/FieldArray/subcomponents/ElementRemoveButton.tsx","../src/FieldArray/subcomponents/SortDragHandle.tsx","../src/FieldArray/subcomponents/FieldArrayElement.tsx","../src/FieldArray/subcomponents/FieldArrayLabel.tsx","../src/FieldArray/subcomponents/FieldArrayValidationError.tsx","../src/FieldArray/subcomponents/SortContext.tsx","../src/FieldArray/FieldArray.tsx","../src/FieldArray/index.ts"],"sourcesContent":["import type { ClassValue } from '@fuf-stack/pixel-utils';\n\nimport { FaPlus } from 'react-icons/fa';\n\nimport { cn } from '@fuf-stack/pixel-utils';\nimport { Button } from '@fuf-stack/pixels';\n\ninterface ElementAppendButtonProps {\n /** text of the append element button */\n appendButtonText?: string;\n /** CSS class name */\n className?: ClassValue;\n /** click handler */\n onClick: () => void;\n /** HTML data-testid attribute used in e2e tests */\n testId?: string;\n}\n\nconst ElementAppendButton = ({\n appendButtonText = 'Add Element',\n className = undefined,\n onClick,\n testId = undefined,\n}: ElementAppendButtonProps) => {\n return (\n <Button\n disableAnimation\n className={cn(className)}\n onClick={onClick}\n size=\"sm\"\n testId={testId}\n variant=\"light\"\n >\n <FaPlus />\n <span>{appendButtonText}</span>\n </Button>\n );\n};\n\nexport default ElementAppendButton;\n","import type { ClassValue } from '@fuf-stack/pixel-utils';\nimport type { MenuItem } from '@fuf-stack/pixels';\nimport type { Key } from 'react';\nimport type { FieldArrayElementMethods } from './FieldArrayElement';\n\nimport { FaCopy, FaTimes } from 'react-icons/fa';\nimport { VscInsert } from 'react-icons/vsc';\n\nimport { cn } from '@fuf-stack/pixel-utils';\nimport { Menu } from '@fuf-stack/pixels';\n\nexport interface ElementActionsMenuProps {\n /** CSS class name */\n className?: ClassValue;\n /** Whether duplicate action is available */\n duplicate?: boolean;\n /** Whether insert after action is available */\n insertAfter?: boolean;\n /** Whether to show remove button (false when last element is not deletable) */\n showRemove?: boolean;\n /** Field array operation methods */\n methods: FieldArrayElementMethods;\n /** HTML data-testid attribute used in e2e tests */\n testId?: string;\n}\n\n/**\n * Menu component for field array element actions (remove, duplicate, insert after)\n */\nconst ElementActionsMenu = ({\n className = undefined,\n duplicate = false,\n insertAfter = false,\n showRemove = true,\n methods,\n testId = undefined,\n}: ElementActionsMenuProps) => {\n const handleAction = (key: Key) => {\n switch (key) {\n case 'remove':\n methods.remove();\n break;\n case 'duplicate':\n methods.duplicate();\n break;\n case 'insertAfter':\n methods.insert();\n break;\n default:\n break;\n }\n };\n\n // Build menu items based on available actions\n const menuItems: MenuItem[] = [];\n\n if (duplicate) {\n menuItems.push({\n key: 'duplicate',\n label: 'Duplicate',\n icon: <FaCopy />,\n });\n }\n\n if (insertAfter) {\n menuItems.push({\n key: 'insertAfter',\n label: 'Insert After',\n icon: <VscInsert />,\n });\n }\n\n if (showRemove) {\n menuItems.push({\n key: 'remove',\n className: 'text-danger',\n label: 'Remove',\n icon: <FaTimes />,\n });\n }\n\n return (\n <Menu\n ariaLabel=\"Element actions\"\n items={menuItems}\n onAction={handleAction}\n placement=\"right\"\n testId={testId}\n triggerButtonProps={{\n className: cn(className),\n disableRipple: true,\n size: 'md',\n variant: 'light',\n }}\n />\n );\n};\n\nexport default ElementActionsMenu;\n","import type { ClassValue } from '@fuf-stack/pixel-utils';\n\nimport { FaTimes } from 'react-icons/fa';\n\nimport { motion } from '@fuf-stack/pixel-motion';\nimport { cn } from '@fuf-stack/pixel-utils';\nimport { Button } from '@fuf-stack/pixels';\n\ninterface ElementRemoveButtonProps {\n /** CSS class name */\n className?: ClassValue;\n /** Globally disable animations (used for first render or prefers-reduced-motion) */\n disableAnimation?: boolean;\n /** click handler */\n onClick: () => void;\n /** HTML data-testid attribute used in e2e tests */\n testId?: string;\n}\n\nconst ElementRemoveButton = ({\n className = undefined,\n disableAnimation = false,\n onClick,\n testId = undefined,\n}: ElementRemoveButtonProps) => {\n const button = (\n <Button\n ariaLabel=\"remove element\"\n className={cn(className)}\n color=\"danger\"\n icon={<FaTimes />}\n onClick={onClick}\n size=\"sm\"\n testId={testId}\n variant=\"light\"\n />\n );\n\n if (disableAnimation) {\n return button;\n }\n\n return (\n <motion.div\n animate={{ opacity: 1, width: 'auto' }}\n className=\"flex\"\n exit={{ opacity: 0, width: 0 }}\n initial={{ opacity: 0, width: 0 }}\n transition={{ duration: 0.2 }}\n >\n {button}\n </motion.div>\n );\n};\n\nexport default ElementRemoveButton;\n","import type { ClassValue } from '@fuf-stack/pixel-utils';\n\nimport { FaGripVertical } from 'react-icons/fa';\n\nimport { useSortable } from '@dnd-kit/sortable';\n\nimport { cn } from '@fuf-stack/pixel-utils';\n\ninterface SortDragHandleProps {\n /** Optional CSS class name */\n className?: ClassValue;\n /** Unique identifier for sortable item */\n id: string | number;\n /** HTML data-testid attribute used in e2e tests */\n testId?: string;\n}\n\n/**\n * Drag handle component that integrates with dnd-kit sortable functionality.\n * Renders a vertical grip icon that can be used to reorder items.\n */\nconst SortDragHandle = ({\n className = undefined,\n id,\n testId = undefined,\n}: SortDragHandleProps) => {\n // Get dnd-kit sortable attributes and listeners\n const { attributes, listeners } = useSortable({ id });\n\n return (\n <div\n className={cn(className)}\n data-testid={testId}\n {...attributes}\n {...listeners}\n >\n <FaGripVertical />\n </div>\n );\n};\n\nexport default SortDragHandle;\n","import type { Variants as MotionVariants } from '@fuf-stack/pixel-motion';\nimport type { ClassValue } from '@fuf-stack/pixel-utils';\nimport type { FieldArrayFeatures } from '../types';\n\nimport { useState } from 'react';\n\nimport { useSortable } from '@dnd-kit/sortable';\nimport { CSS } from '@dnd-kit/utilities';\n\nimport { AnimatePresence, motion } from '@fuf-stack/pixel-motion';\nimport { cn } from '@fuf-stack/pixel-utils';\n\nimport { Grid } from '../../Grid';\nimport ElementActionsMenu from './ElementActionsMenu';\nimport ElementRemoveButton from './ElementRemoveButton';\nimport SortDragHandle from './SortDragHandle';\n\nexport interface FieldArrayElementMethods {\n /** Add new element at end */\n append: () => void;\n /** Clone current element */\n duplicate: () => void;\n /** Add new element after current */\n insert: () => void;\n /** Remove current element */\n remove: () => void;\n}\n\ninterface FieldArrayElementProps extends FieldArrayFeatures {\n /** Form elements to render inside array element */\n children: React.ReactNode;\n /** CSS class names for component parts */\n className: {\n /** Class of wrapper grid inside the li that wraps the rendered element fields directly */\n elementFieldsGrid?: ClassValue;\n /** Class for the li (performs motion animations) */\n listItem?: ClassValue;\n /** Class for the li inner div (wraps the rendered element fields) */\n listItemInner?: ClassValue;\n /** Class for the actions menu button */\n actionsMenuButton?: ClassValue;\n /** Class for the remove element button (when menu is not used) */\n removeButton?: ClassValue;\n /** Class for the drag handle when sorting enabled */\n sortDragHandle?: ClassValue;\n };\n /** Globally disable animations for this item (used for first render or prefers-reduced-motion) */\n disableAnimation?: boolean;\n /** Bottom margin for elements (for backwards compatibility) */\n elementMarginBottom?: React.CSSProperties['marginBottom'];\n /** All fields in the form array */\n fields: Record<'id', string>[];\n /** Unique identifier for drag/drop */\n id: string | number;\n /** Field index in array */\n index: number;\n /** Prevent deletion of last remaining element */\n lastNotDeletable?: boolean;\n /** Field array operation methods */\n methods: FieldArrayElementMethods;\n /** HTML data-testid of the element */\n testId?: string;\n}\n\n/**\n * Form array element component using react-hook-form with drag-drop sorting\n * and validation capabilities. Animations when elements are added or removed\n * improve the user experience and provide a better visual feedback.\n */\nconst FieldArrayElement = ({\n children,\n className,\n disableAnimation = false,\n duplicate = false,\n elementMarginBottom: _elementMarginBottom = undefined,\n fields,\n id,\n index: _index,\n insertAfter = false,\n lastNotDeletable = true,\n methods,\n sortable = false,\n testId = undefined,\n}: FieldArrayElementProps) => {\n // Apply transform styles when sortable is enabled for smooth drag animations\n // transform: handles the item's position during drag\n // transition: controls the animation timing when dropping\n const { setNodeRef, transform, transition, isDragging } = useSortable({ id });\n const sortingStyle = sortable\n ? {\n transform: CSS.Translate.toString(transform),\n transition,\n zIndex: isDragging ? 50 : undefined,\n }\n : undefined;\n\n // Local visibility to allow exit animation before removing from RHF state\n const [isVisible, setIsVisible] = useState(true);\n\n // Motion variants for the list item\n const listItemMotionVariants: MotionVariants = {\n hidden: { opacity: 0, height: 0, marginBottom: 0 },\n visible: {\n opacity: 1,\n height: 'auto',\n transition: { duration: 0.2, ease: 'circOut' },\n // push last visible item down to overlap with append button (hide double border)\n marginBottom: '-1px',\n },\n exit: {\n opacity: 0,\n height: 0,\n marginBottom: 0,\n transition: {\n // on exit first fade out, then shrink\n opacity: { duration: 0.1, ease: 'circOut' },\n height: { delay: 0.1, duration: 0.2, ease: 'circOut' },\n },\n },\n };\n\n // Height animation handled on <motion.li> using overflow hidden\n return (\n <AnimatePresence\n mode=\"wait\"\n // remove from RHF state after exit animation\n onExitComplete={() => {\n methods.remove();\n }}\n >\n {isVisible ? (\n <motion.li\n key={id}\n ref={setNodeRef}\n animate={disableAnimation ? undefined : 'visible'}\n className={cn(className.listItem)}\n data-dragging={isDragging}\n data-testid={`${testId}_element`}\n exit={disableAnimation ? undefined : 'exit'}\n initial={disableAnimation ? false : 'hidden'}\n style={sortingStyle}\n variants={disableAnimation ? undefined : listItemMotionVariants}\n >\n <div className={cn(className.listItemInner)}>\n {/** sorting drag handle */}\n {sortable ? (\n <SortDragHandle\n className={className.sortDragHandle}\n id={id}\n testId={`${testId}_sort_drag_handle`}\n />\n ) : null}\n\n {/** render element fields in Grid component */}\n <Grid\n className={cn(className.elementFieldsGrid)}\n testId={`${testId}_element_fields_grid`}\n >\n {/* render actual fields */}\n {children}\n </Grid>\n\n {/** actions menu when duplicate or insertAfter is enabled */}\n {duplicate || insertAfter ? (\n <ElementActionsMenu\n className={className.actionsMenuButton}\n duplicate={duplicate}\n insertAfter={insertAfter}\n showRemove={!(lastNotDeletable && fields.length === 1)}\n testId={`${testId}_actions_menu`}\n methods={{\n ...methods,\n remove: () => {\n if (disableAnimation) {\n methods.remove();\n } else {\n setIsVisible(false);\n }\n },\n }}\n />\n ) : (\n <>\n {/** remove element button (when menu is not used) */}\n <AnimatePresence initial={false}>\n {lastNotDeletable && fields.length === 1 ? null : (\n <ElementRemoveButton\n key=\"remove-button\"\n className={className.removeButton}\n disableAnimation={disableAnimation}\n testId={`${testId}_remove_button`}\n onClick={() => {\n if (disableAnimation) {\n methods.remove();\n } else {\n setIsVisible(false);\n }\n }}\n />\n )}\n </AnimatePresence>\n </>\n )}\n </div>\n </motion.li>\n ) : null}\n </AnimatePresence>\n );\n};\n\nexport default FieldArrayElement;\n","import type { ReactNode } from 'react';\n\nimport { cn } from '@fuf-stack/pixel-utils';\n\nimport { useUniformField } from '../../hooks/useUniformField';\n\nexport interface FieldArrayLabelProps {\n /** CSS class name */\n className?: string;\n /** Label content */\n label: ReactNode;\n /** Field name */\n name: string;\n}\n\n/**\n * Renders the label for a FieldArray component.\n *\n * This component handles displaying the array label with proper accessibility\n * attributes using the label props from useUniformField.\n */\nconst FieldArrayLabel = ({\n className = undefined,\n label: _label,\n name,\n}: FieldArrayLabelProps) => {\n const { error, getLabelProps, invalid, label } = useUniformField({\n name,\n label: _label,\n });\n\n // when no label is provided, don't render anything\n if (!_label) {\n return null;\n }\n\n // @ts-expect-error - error._errors exists but not typed\n const hasErrors = invalid && error?._errors;\n\n return (\n <div\n {...getLabelProps()}\n aria-level={3}\n role=\"heading\"\n className={cn(getLabelProps()?.className, className, {\n // when there are no array level errors, the label should have foreground color\n 'text-foreground!': !hasErrors,\n })}\n >\n {label}\n </div>\n );\n};\n\nexport default FieldArrayLabel;\n","import {\n AnimatePresence,\n motion,\n useReducedMotion,\n} from '@fuf-stack/pixel-motion';\nimport { cn } from '@fuf-stack/pixel-utils';\n\nimport { useUniformField } from '../../hooks/useUniformField';\nimport FieldValidationError from '../../partials/FieldValidationError/FieldValidationError';\n\nexport interface FieldArrayValidationErrorProps {\n /** Field name */\n name: string;\n}\n\n/**\n * Renders array-level validation errors for FieldArray.\n *\n * This component handles validation errors that apply to the entire array\n * (e.g., \"Array must contain at least 3 elements\", \"Array elements are not unique\"),\n * as opposed to field-level errors which apply to individual array elements.\n *\n * The component wraps errors in the proper accessibility markup and animates\n * them in/out using Framer Motion when they appear or are resolved.\n */\nconst FieldArrayValidationError = ({\n name,\n}: FieldArrayValidationErrorProps) => {\n const {\n error,\n getErrorMessageProps,\n getHelperWrapperProps,\n invalid,\n testId,\n } = useUniformField({\n name,\n });\n\n // disable all animation if user prefers reduced motion\n const disableAnimation = useReducedMotion();\n\n // @ts-expect-error - error._errors exists but not typed\n const hasErrors = invalid && error?._errors;\n\n return (\n <AnimatePresence initial={!disableAnimation}>\n {hasErrors ? (\n <motion.div\n key=\"field-array-errors\"\n exit={disableAnimation ? undefined : { opacity: 0, height: 0 }}\n initial={disableAnimation ? false : { height: 0, opacity: 0 }}\n style={{ overflow: 'hidden' }}\n transition={{ duration: 0.2, ease: 'circOut' }}\n animate={\n disableAnimation ? undefined : { opacity: 1, height: 'auto' }\n }\n >\n <div\n {...getHelperWrapperProps()}\n className={cn(\n getHelperWrapperProps()?.className,\n // force helper to be visible (for some reason it's hidden by default) and add padding\n 'block px-3 py-2',\n )}\n >\n <div {...getErrorMessageProps()}>\n <FieldValidationError\n // @ts-expect-error - error._errors exists but not typed\n error={error._errors}\n testId={testId}\n />\n </div>\n </div>\n </motion.div>\n ) : null}\n </AnimatePresence>\n );\n};\n\nexport default FieldArrayValidationError;\n","import type { DragEndEvent } from '@dnd-kit/core';\nimport type { ReactNode } from 'react';\nimport type { UseFieldArrayMove } from 'react-hook-form';\n\nimport { useFormContext } from 'react-hook-form';\n\nimport {\n closestCenter,\n DndContext,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n} from '@dnd-kit/core';\nimport {\n restrictToVerticalAxis,\n restrictToWindowEdges,\n} from '@dnd-kit/modifiers';\nimport {\n SortableContext,\n verticalListSortingStrategy,\n} from '@dnd-kit/sortable';\n\ninterface SortContextProps {\n /** child components */\n children: ReactNode;\n /** Array of objects containing unique IDs for sortable items */\n fields: Record<'id', string>[];\n /** name of the field array */\n name: string;\n /** react-hook-form's move function to update field array indices */\n move: UseFieldArrayMove;\n /** enable/disable sorting functionality */\n sortable: boolean;\n}\n\n/**\n * A wrapper component that provides drag-and-drop sorting functionality for field arrays\n * using dnd-kit and react-hook-form.\n *\n * This component integrates with react-hook-form's field arrays to enable vertical\n * drag-and-drop reordering of form fields. It supports both pointer (mouse/touch)\n * and keyboard interactions for accessibility.\n */\nconst SortContext = ({\n children,\n fields,\n move,\n name,\n sortable,\n}: SortContextProps): ReactNode => {\n const { trigger } = useFormContext();\n\n // Initialize sensors for both pointer (mouse/touch) and keyboard interactions\n const sensors = useSensors(\n useSensor(PointerSensor),\n useSensor(KeyboardSensor),\n );\n\n // Early return if sorting is disabled\n if (!sortable) {\n return children;\n }\n\n /**\n * Handles the end of a drag operation by updating field positions\n * @param event - The drag end event containing active and over elements\n */\n const handleDragEnd = (event: DragEndEvent) => {\n const { active, over } = event;\n\n // Only move if dropping over a different item\n if (active.id !== over?.id) {\n // Find the indices of the dragged item and drop target\n const oldIndex = fields.findIndex((field) => {\n return field.id === active.id;\n });\n const newIndex = fields.findIndex((field) => {\n return field.id === over?.id;\n });\n // Update the field array order using react-hook-form's move function\n move(oldIndex, newIndex);\n\n // Finally trigger validation for the array field,\n // so validation errors are updated for the new order\n trigger(name);\n }\n };\n\n return (\n <DndContext\n collisionDetection={closestCenter}\n modifiers={[restrictToVerticalAxis, restrictToWindowEdges]}\n onDragEnd={handleDragEnd}\n sensors={sensors}\n >\n <SortableContext\n strategy={verticalListSortingStrategy}\n items={fields.map((field) => {\n return field.id;\n })}\n >\n {children}\n </SortableContext>\n </DndContext>\n );\n};\n\nexport default SortContext;\n","import type { FieldArrayElementMethods } from './subcomponents/FieldArrayElement';\nimport type { FieldArrayProps } from './types';\n\nimport { cn, tv, variantsToClassNames } from '@fuf-stack/pixel-utils';\n\nimport { flatArrayKey } from '../helpers';\nimport { useUniformFieldArray } from '../hooks/useUniformFieldArray';\nimport ElementAppendButton from './subcomponents/ElementAppendButton';\nimport FieldArrayElement from './subcomponents/FieldArrayElement';\nimport FieldArrayLabel from './subcomponents/FieldArrayLabel';\nimport FieldArrayValidationError from './subcomponents/FieldArrayValidationError';\nimport SortContext from './subcomponents/SortContext';\n\nexport const fieldArrayVariants = tv({\n slots: {\n /** base class for the field array wrapper */\n base: [\n // base styles\n 'overflow-hidden rounded-small border border-divider bg-content1',\n // divider between items\n 'divide-y divide-divider',\n ],\n /** class for the actions menu button */\n actionsMenuButton: [\n // base styles\n 'flex items-center justify-center text-default-600',\n // fixed height/no round corners/center align\n 'h-full rounded-none',\n // focus styles - inset ring\n 'outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-focus',\n ],\n /** class for the append button */\n appendButton: [\n // base styles\n 'w-full justify-start rounded-b-small rounded-t-none font-semibold',\n // match label height (p-3 = 12px vertical padding + text-base line height)\n '!h-[48px] !min-h-0',\n // focus styles - inset ring with rounded bottom corners to match container\n 'outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-focus',\n ],\n /** class for the element fields grid */\n elementFieldsGrid: ['w-full grow p-3'],\n /** class for the label */\n label: [\n // override HeroUI label positioning and display\n 'pointer-events-auto! static! z-auto! block! w-full!',\n // reset any transforms or translations\n 'translate-x-0! translate-y-0! transform-none!',\n // card header styling - use text-medium (16px) instead of text-base for correct 48px height\n 'rounded-t-small p-3 font-semibold text-medium',\n ],\n /** class for the list */\n list: ['overflow-hidden'],\n /** class for the list wrapper */\n listWrapper: ['overflow-hidden'],\n /** class for the list item (performs motion animations) */\n listItem: [\n // base styles\n 'group relative flex flex-row',\n // overlap borders by shifting first item up 1px (similar to how last item overlaps with append button)\n 'first:-mt-px',\n ],\n /** class for the list item inner */\n listItemInner: [\n // base styles\n 'flex w-full flex-row items-stretch divide-divider bg-content1',\n // x division and borders\n 'divide-x divide-solid border-b border-t border-divider',\n ],\n /** class for the remove button */\n removeButton: [\n // base styles\n 'flex items-center justify-center',\n // fixed height/no round corners\n '!h-full !min-h-0 !rounded-none px-3',\n // focus styles - inset ring\n 'outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-focus',\n ],\n /** class for the sort drag handle */\n sortDragHandle: [\n // base styles\n 'flex cursor-grab items-center justify-center px-2 text-default-600 transition-colors',\n // hover and dragging state\n 'hover:bg-default-100 active:cursor-grabbing group-data-[dragging=true]:bg-default-100',\n // focus styles - inset ring\n 'outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-focus',\n ],\n },\n variants: {\n hasLabel: {\n false: {\n // focus styles - when there is no label, the first item actions menu button should have rounded top right corners\n actionsMenuButton:\n 'group-[:first-child]:!rounded-tr-small group-[:first-child]:group-data-[dragging=true]:!rounded-tr-none',\n // focus styles - when there is no label, the first item remove button focus ring should have rounded top right corners\n removeButton:\n 'group-[:first-child]:!rounded-tr-small group-[:first-child]:group-data-[dragging=true]:!rounded-tr-none',\n // focus styles - when there is no label, the first item sort drag handle focus ring should have rounded top left corners\n sortDragHandle:\n 'group-[:first-child]:rounded-tl-small group-[:first-child]:group-data-[dragging=true]:rounded-tl-none',\n },\n },\n },\n});\n\n/**\n * FieldArray component based in [RHF useFieldArray](https://react-hook-form.com/docs/usefieldarray)\n */\nconst FieldArray = ({\n appendButtonText = 'Add Element',\n children,\n className: _className = undefined,\n duplicate = false,\n elementInitialValue: _elementInitialValue = null,\n elementMarginBottom = undefined,\n flat = false,\n insertAfter = false,\n lastElementNotRemovable = false,\n name,\n sortable = false,\n ...uniformFieldProps\n}: FieldArrayProps) => {\n const {\n fields,\n append,\n remove,\n insert,\n move,\n disableAnimation,\n elementInitialValue,\n getValues,\n testId,\n } = useUniformFieldArray({\n name,\n flat,\n elementInitialValue: _elementInitialValue,\n lastElementNotRemovable,\n ...uniformFieldProps,\n });\n\n // className from slots\n const variants = fieldArrayVariants({ hasLabel: !!uniformFieldProps.label });\n const className = variantsToClassNames(variants, _className, 'base');\n\n return (\n <div className={className.base}>\n {/* field array label */}\n <FieldArrayLabel\n className={className.label}\n label={uniformFieldProps.label}\n name={name}\n />\n\n {fields.length ? (\n /* list wrapper */\n <div className={cn(className.listWrapper)}>\n {/* sortable context */}\n <SortContext\n fields={fields}\n move={move}\n name={name}\n sortable={sortable}\n >\n {/* list container */}\n <ul className={className.list} data-testid={testId}>\n {/* fields / list elements */}\n {fields.map((field, index) => {\n const elementName = flat\n ? `${name}.${index}.${flatArrayKey}`\n : `${name}.${index}`;\n const elementTestId = `${testId}_${index}`;\n\n // create methods for element\n const elementMethods: FieldArrayElementMethods = {\n append: () => {\n append(elementInitialValue);\n },\n duplicate: () => {\n const values = getValues(name);\n const currentValue = (values as unknown[])[index];\n const nextValue = flat\n ? { [flatArrayKey]: currentValue }\n : currentValue;\n insert(index + 1, nextValue);\n },\n insert: () => {\n insert(index + 1, elementInitialValue);\n },\n remove: () => {\n remove(index);\n },\n };\n\n return (\n <FieldArrayElement\n key={field.id}\n className={className}\n disableAnimation={disableAnimation}\n duplicate={duplicate}\n elementMarginBottom={elementMarginBottom}\n fields={fields}\n id={field.id}\n index={index}\n insertAfter={insertAfter}\n lastNotDeletable={lastElementNotRemovable}\n methods={elementMethods}\n sortable={sortable}\n testId={elementTestId}\n >\n {children({\n index,\n length: fields.length,\n methods: elementMethods,\n name: elementName,\n testId: elementTestId,\n })}\n </FieldArrayElement>\n );\n })}\n </ul>\n </SortContext>\n </div>\n ) : null}\n\n {/* top level field array errors */}\n <FieldArrayValidationError name={name} />\n\n {/* append elements button */}\n <ElementAppendButton\n appendButtonText={appendButtonText}\n className={className.appendButton}\n testId={`${testId}_append_button`}\n onClick={() => {\n append(elementInitialValue);\n }}\n />\n </div>\n );\n};\n\nexport default FieldArray;\n","import FieldArray from './FieldArray';\n\nexport type * from './types';\n\nexport { FieldArray };\n\nexport default FieldArray;\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FieldArray-D3iUaRLo.js","names":["menuItems: MenuItem[]","listItemMotionVariants: MotionVariants","SortDragHandle","Grid","ElementActionsMenu","ElementRemoveButton","FieldValidationError","FieldArrayLabel","SortContext","elementMethods: FieldArrayElementMethods","FieldArrayElement","FieldArrayValidationError","ElementAppendButton","FieldArray"],"sources":["../src/FieldArray/subcomponents/ElementAppendButton.tsx","../src/FieldArray/subcomponents/ElementActionsMenu.tsx","../src/FieldArray/subcomponents/ElementRemoveButton.tsx","../src/FieldArray/subcomponents/SortDragHandle.tsx","../src/FieldArray/subcomponents/FieldArrayElement.tsx","../src/FieldArray/subcomponents/FieldArrayLabel.tsx","../src/FieldArray/subcomponents/FieldArrayValidationError.tsx","../src/FieldArray/subcomponents/SortContext.tsx","../src/FieldArray/FieldArray.tsx","../src/FieldArray/index.ts"],"sourcesContent":["import type { ClassValue } from '@fuf-stack/pixel-utils';\n\nimport { FaPlus } from 'react-icons/fa';\n\nimport { cn } from '@fuf-stack/pixel-utils';\nimport { Button } from '@fuf-stack/pixels';\n\ninterface ElementAppendButtonProps {\n /** text of the append element button */\n appendButtonText?: string;\n /** CSS class name */\n className?: ClassValue;\n /** click handler */\n onClick: () => void;\n /** HTML data-testid attribute used in e2e tests */\n testId?: string;\n}\n\nconst ElementAppendButton = ({\n appendButtonText = 'Add Element',\n className = undefined,\n onClick,\n testId = undefined,\n}: ElementAppendButtonProps) => {\n return (\n <Button\n disableAnimation\n className={cn(className)}\n onClick={onClick}\n size=\"sm\"\n testId={testId}\n variant=\"light\"\n >\n <FaPlus />\n <span>{appendButtonText}</span>\n </Button>\n );\n};\n\nexport default ElementAppendButton;\n","import type { ClassValue } from '@fuf-stack/pixel-utils';\nimport type { MenuItem } from '@fuf-stack/pixels';\nimport type { Key } from 'react';\nimport type { FieldArrayElementMethods } from './FieldArrayElement';\n\nimport { FaCopy, FaTimes } from 'react-icons/fa';\nimport { VscInsert } from 'react-icons/vsc';\n\nimport { cn } from '@fuf-stack/pixel-utils';\nimport { Menu } from '@fuf-stack/pixels';\n\nexport interface ElementActionsMenuProps {\n /** CSS class name */\n className?: ClassValue;\n /** Whether duplicate action is available */\n duplicate?: boolean;\n /** Whether insert after action is available */\n insertAfter?: boolean;\n /** Whether to show remove button (false when last element is not deletable) */\n showRemove?: boolean;\n /** Field array operation methods */\n methods: FieldArrayElementMethods;\n /** HTML data-testid attribute used in e2e tests */\n testId?: string;\n}\n\n/**\n * Menu component for field array element actions (remove, duplicate, insert after)\n */\nconst ElementActionsMenu = ({\n className = undefined,\n duplicate = false,\n insertAfter = false,\n showRemove = true,\n methods,\n testId = undefined,\n}: ElementActionsMenuProps) => {\n const handleAction = (key: Key) => {\n switch (key) {\n case 'remove':\n methods.remove();\n break;\n case 'duplicate':\n methods.duplicate();\n break;\n case 'insertAfter':\n methods.insert();\n break;\n default:\n break;\n }\n };\n\n // Build menu items based on available actions\n const menuItems: MenuItem[] = [];\n\n if (duplicate) {\n menuItems.push({\n key: 'duplicate',\n label: 'Duplicate',\n icon: <FaCopy />,\n });\n }\n\n if (insertAfter) {\n menuItems.push({\n key: 'insertAfter',\n label: 'Insert After',\n icon: <VscInsert />,\n });\n }\n\n if (showRemove) {\n menuItems.push({\n key: 'remove',\n className: 'text-danger',\n label: 'Remove',\n icon: <FaTimes />,\n });\n }\n\n return (\n <Menu\n ariaLabel=\"Element actions\"\n items={menuItems}\n onAction={handleAction}\n placement=\"right\"\n testId={testId}\n triggerButtonProps={{\n className: cn(className),\n disableRipple: true,\n size: 'md',\n variant: 'light',\n }}\n />\n );\n};\n\nexport default ElementActionsMenu;\n","import type { ClassValue } from '@fuf-stack/pixel-utils';\n\nimport { FaTimes } from 'react-icons/fa';\n\nimport { motion } from '@fuf-stack/pixel-motion';\nimport { cn } from '@fuf-stack/pixel-utils';\nimport { Button } from '@fuf-stack/pixels';\n\ninterface ElementRemoveButtonProps {\n /** CSS class name */\n className?: ClassValue;\n /** Globally disable animations (used for first render or prefers-reduced-motion) */\n disableAnimation?: boolean;\n /** click handler */\n onClick: () => void;\n /** HTML data-testid attribute used in e2e tests */\n testId?: string;\n}\n\nconst ElementRemoveButton = ({\n className = undefined,\n disableAnimation = false,\n onClick,\n testId = undefined,\n}: ElementRemoveButtonProps) => {\n const button = (\n <Button\n ariaLabel=\"remove element\"\n className={cn(className)}\n color=\"danger\"\n icon={<FaTimes />}\n onClick={onClick}\n size=\"sm\"\n testId={testId}\n variant=\"light\"\n />\n );\n\n if (disableAnimation) {\n return button;\n }\n\n return (\n <motion.div\n animate={{ opacity: 1, width: 'auto' }}\n className=\"flex\"\n exit={{ opacity: 0, width: 0 }}\n initial={{ opacity: 0, width: 0 }}\n transition={{ duration: 0.2 }}\n >\n {button}\n </motion.div>\n );\n};\n\nexport default ElementRemoveButton;\n","import type { ClassValue } from '@fuf-stack/pixel-utils';\n\nimport { FaGripVertical } from 'react-icons/fa';\n\nimport { useSortable } from '@dnd-kit/sortable';\n\nimport { cn } from '@fuf-stack/pixel-utils';\n\ninterface SortDragHandleProps {\n /** Optional CSS class name */\n className?: ClassValue;\n /** Unique identifier for sortable item */\n id: string | number;\n /** HTML data-testid attribute used in e2e tests */\n testId?: string;\n}\n\n/**\n * Drag handle component that integrates with dnd-kit sortable functionality.\n * Renders a vertical grip icon that can be used to reorder items.\n */\nconst SortDragHandle = ({\n className = undefined,\n id,\n testId = undefined,\n}: SortDragHandleProps) => {\n // Get dnd-kit sortable attributes and listeners\n const { attributes, listeners } = useSortable({ id });\n\n return (\n <div\n className={cn(className)}\n data-testid={testId}\n {...attributes}\n {...listeners}\n >\n <FaGripVertical />\n </div>\n );\n};\n\nexport default SortDragHandle;\n","import type { Variants as MotionVariants } from '@fuf-stack/pixel-motion';\nimport type { ClassValue } from '@fuf-stack/pixel-utils';\nimport type { FieldArrayFeatures } from '../types';\n\nimport { useState } from 'react';\n\nimport { useSortable } from '@dnd-kit/sortable';\nimport { CSS } from '@dnd-kit/utilities';\n\nimport { AnimatePresence, motion } from '@fuf-stack/pixel-motion';\nimport { cn } from '@fuf-stack/pixel-utils';\n\nimport { Grid } from '../../Grid';\nimport ElementActionsMenu from './ElementActionsMenu';\nimport ElementRemoveButton from './ElementRemoveButton';\nimport SortDragHandle from './SortDragHandle';\n\nexport interface FieldArrayElementMethods {\n /** Add new element at end */\n append: () => void;\n /** Clone current element */\n duplicate: () => void;\n /** Add new element after current */\n insert: () => void;\n /** Remove current element */\n remove: () => void;\n}\n\ninterface FieldArrayElementProps extends FieldArrayFeatures {\n /** Form elements to render inside array element */\n children: React.ReactNode;\n /** CSS class names for component parts */\n className: {\n /** Class of wrapper grid inside the li that wraps the rendered element fields directly */\n elementFieldsGrid?: ClassValue;\n /** Class for the li (performs motion animations) */\n listItem?: ClassValue;\n /** Class for the li inner div (wraps the rendered element fields) */\n listItemInner?: ClassValue;\n /** Class for the actions menu button */\n actionsMenuButton?: ClassValue;\n /** Class for the remove element button (when menu is not used) */\n removeButton?: ClassValue;\n /** Class for the drag handle when sorting enabled */\n sortDragHandle?: ClassValue;\n };\n /** Globally disable animations for this item (used for first render or prefers-reduced-motion) */\n disableAnimation?: boolean;\n /** Bottom margin for elements (for backwards compatibility) */\n elementMarginBottom?: React.CSSProperties['marginBottom'];\n /** All fields in the form array */\n fields: Record<'id', string>[];\n /** Unique identifier for drag/drop */\n id: string | number;\n /** Field index in array */\n index: number;\n /** Prevent deletion of last remaining element */\n lastNotDeletable?: boolean;\n /** Field array operation methods */\n methods: FieldArrayElementMethods;\n /** HTML data-testid of the element */\n testId?: string;\n}\n\n/**\n * Form array element component using react-hook-form with drag-drop sorting\n * and validation capabilities. Animations when elements are added or removed\n * improve the user experience and provide a better visual feedback.\n */\nconst FieldArrayElement = ({\n children,\n className,\n disableAnimation = false,\n duplicate = false,\n elementMarginBottom: _elementMarginBottom = undefined,\n fields,\n id,\n index: _index,\n insertAfter = false,\n lastNotDeletable = true,\n methods,\n sortable = false,\n testId = undefined,\n}: FieldArrayElementProps) => {\n // Apply transform styles when sortable is enabled for smooth drag animations\n // transform: handles the item's position during drag\n // transition: controls the animation timing when dropping\n const { setNodeRef, transform, transition, isDragging } = useSortable({ id });\n const sortingStyle = sortable\n ? {\n transform: CSS.Translate.toString(transform),\n transition,\n zIndex: isDragging ? 50 : undefined,\n }\n : undefined;\n\n // Local visibility to allow exit animation before removing from RHF state\n const [isVisible, setIsVisible] = useState(true);\n\n // Motion variants for the list item\n const listItemMotionVariants: MotionVariants = {\n hidden: { opacity: 0, height: 0, marginBottom: 0 },\n visible: {\n opacity: 1,\n height: 'auto',\n transition: { duration: 0.2, ease: 'circOut' },\n // push last visible item down to overlap with append button (hide double border)\n marginBottom: '-1px',\n },\n exit: {\n opacity: 0,\n height: 0,\n marginBottom: 0,\n transition: {\n // on exit first fade out, then shrink\n opacity: { duration: 0.1, ease: 'circOut' },\n height: { delay: 0.1, duration: 0.2, ease: 'circOut' },\n },\n },\n };\n\n // Height animation handled on <motion.li> using overflow hidden\n return (\n <AnimatePresence\n mode=\"wait\"\n // remove from RHF state after exit animation\n onExitComplete={() => {\n methods.remove();\n }}\n >\n {isVisible ? (\n <motion.li\n key={id}\n ref={setNodeRef}\n animate={disableAnimation ? undefined : 'visible'}\n className={cn(className.listItem)}\n data-dragging={isDragging}\n data-testid={`${testId}_element`}\n exit={disableAnimation ? undefined : 'exit'}\n initial={disableAnimation ? false : 'hidden'}\n style={sortingStyle}\n variants={disableAnimation ? undefined : listItemMotionVariants}\n >\n <div className={cn(className.listItemInner)}>\n {/** sorting drag handle */}\n {sortable ? (\n <SortDragHandle\n className={className.sortDragHandle}\n id={id}\n testId={`${testId}_sort_drag_handle`}\n />\n ) : null}\n\n {/** render element fields in Grid component */}\n <Grid\n className={cn(className.elementFieldsGrid)}\n testId={`${testId}_element_fields_grid`}\n >\n {/* render actual fields */}\n {children}\n </Grid>\n\n {/** actions menu when duplicate or insertAfter is enabled */}\n {duplicate || insertAfter ? (\n <ElementActionsMenu\n className={className.actionsMenuButton}\n duplicate={duplicate}\n insertAfter={insertAfter}\n showRemove={!(lastNotDeletable && fields.length === 1)}\n testId={`${testId}_actions_menu`}\n methods={{\n ...methods,\n remove: () => {\n if (disableAnimation) {\n methods.remove();\n } else {\n setIsVisible(false);\n }\n },\n }}\n />\n ) : (\n <>\n {/** remove element button (when menu is not used) */}\n <AnimatePresence initial={false}>\n {lastNotDeletable && fields.length === 1 ? null : (\n <ElementRemoveButton\n key=\"remove-button\"\n className={className.removeButton}\n disableAnimation={disableAnimation}\n testId={`${testId}_remove_button`}\n onClick={() => {\n if (disableAnimation) {\n methods.remove();\n } else {\n setIsVisible(false);\n }\n }}\n />\n )}\n </AnimatePresence>\n </>\n )}\n </div>\n </motion.li>\n ) : null}\n </AnimatePresence>\n );\n};\n\nexport default FieldArrayElement;\n","import type { ReactNode } from 'react';\n\nimport { cn } from '@fuf-stack/pixel-utils';\n\nimport { useUniformField } from '../../hooks/useUniformField';\n\nexport interface FieldArrayLabelProps {\n /** CSS class name */\n className?: string;\n /** Label content */\n label: ReactNode;\n /** Field name */\n name: string;\n}\n\n/**\n * Renders the label for a FieldArray component.\n *\n * This component handles displaying the array label with proper accessibility\n * attributes using the label props from useUniformField.\n */\nconst FieldArrayLabel = ({\n className = undefined,\n label: _label,\n name,\n}: FieldArrayLabelProps) => {\n const { error, getLabelProps, invalid, label } = useUniformField({\n name,\n label: _label,\n });\n\n // when no label is provided, don't render anything\n if (!_label) {\n return null;\n }\n\n // @ts-expect-error - error._errors exists but not typed\n const hasErrors = invalid && error?._errors;\n\n return (\n <div\n {...getLabelProps()}\n aria-level={3}\n role=\"heading\"\n className={cn(getLabelProps()?.className, className, {\n // when there are no array level errors, the label should have foreground color\n 'text-foreground!': !hasErrors,\n })}\n >\n {label}\n </div>\n );\n};\n\nexport default FieldArrayLabel;\n","import {\n AnimatePresence,\n motion,\n useReducedMotion,\n} from '@fuf-stack/pixel-motion';\nimport { cn } from '@fuf-stack/pixel-utils';\n\nimport { useUniformField } from '../../hooks/useUniformField';\nimport FieldValidationError from '../../partials/FieldValidationError/FieldValidationError';\n\nexport interface FieldArrayValidationErrorProps {\n /** Field name */\n name: string;\n}\n\n/**\n * Renders array-level validation errors for FieldArray.\n *\n * This component handles validation errors that apply to the entire array\n * (e.g., \"Array must contain at least 3 elements\", \"Array elements are not unique\"),\n * as opposed to field-level errors which apply to individual array elements.\n *\n * The component wraps errors in the proper accessibility markup and animates\n * them in/out using Framer Motion when they appear or are resolved.\n */\nconst FieldArrayValidationError = ({\n name,\n}: FieldArrayValidationErrorProps) => {\n const {\n error,\n getErrorMessageProps,\n getHelperWrapperProps,\n invalid,\n testId,\n } = useUniformField({\n name,\n });\n\n // disable all animation if user prefers reduced motion\n const disableAnimation = useReducedMotion();\n\n // @ts-expect-error - error._errors exists but not typed\n const hasErrors = invalid && error?._errors;\n\n return (\n <AnimatePresence initial={!disableAnimation}>\n {hasErrors ? (\n <motion.div\n key=\"field-array-errors\"\n exit={disableAnimation ? undefined : { opacity: 0, height: 0 }}\n initial={disableAnimation ? false : { height: 0, opacity: 0 }}\n style={{ overflow: 'hidden' }}\n transition={{ duration: 0.2, ease: 'circOut' }}\n animate={\n disableAnimation ? undefined : { opacity: 1, height: 'auto' }\n }\n >\n <div\n {...getHelperWrapperProps()}\n className={cn(\n getHelperWrapperProps()?.className,\n // force helper to be visible (for some reason it's hidden by default) and add padding\n 'block px-3 py-2',\n )}\n >\n <div {...getErrorMessageProps()}>\n <FieldValidationError\n // @ts-expect-error - error._errors exists but not typed\n error={error._errors}\n testId={testId}\n />\n </div>\n </div>\n </motion.div>\n ) : null}\n </AnimatePresence>\n );\n};\n\nexport default FieldArrayValidationError;\n","import type { DragEndEvent } from '@dnd-kit/core';\nimport type { ReactNode } from 'react';\nimport type { UseFieldArrayMove } from 'react-hook-form';\n\nimport { useFormContext } from 'react-hook-form';\n\nimport {\n closestCenter,\n DndContext,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n} from '@dnd-kit/core';\nimport {\n restrictToVerticalAxis,\n restrictToWindowEdges,\n} from '@dnd-kit/modifiers';\nimport {\n SortableContext,\n verticalListSortingStrategy,\n} from '@dnd-kit/sortable';\n\ninterface SortContextProps {\n /** child components */\n children: ReactNode;\n /** Array of objects containing unique IDs for sortable items */\n fields: Record<'id', string>[];\n /** name of the field array */\n name: string;\n /** react-hook-form's move function to update field array indices */\n move: UseFieldArrayMove;\n /** enable/disable sorting functionality */\n sortable: boolean;\n}\n\n/**\n * A wrapper component that provides drag-and-drop sorting functionality for field arrays\n * using dnd-kit and react-hook-form.\n *\n * This component integrates with react-hook-form's field arrays to enable vertical\n * drag-and-drop reordering of form fields. It supports both pointer (mouse/touch)\n * and keyboard interactions for accessibility.\n */\nconst SortContext = ({\n children,\n fields,\n move,\n name,\n sortable,\n}: SortContextProps): ReactNode => {\n const { trigger } = useFormContext();\n\n // Initialize sensors for both pointer (mouse/touch) and keyboard interactions\n const sensors = useSensors(\n useSensor(PointerSensor),\n useSensor(KeyboardSensor),\n );\n\n // Early return if sorting is disabled\n if (!sortable) {\n return children;\n }\n\n /**\n * Handles the end of a drag operation by updating field positions\n * @param event - The drag end event containing active and over elements\n */\n const handleDragEnd = (event: DragEndEvent) => {\n const { active, over } = event;\n\n // Only move if dropping over a different item\n if (active.id !== over?.id) {\n // Find the indices of the dragged item and drop target\n const oldIndex = fields.findIndex((field) => {\n return field.id === active.id;\n });\n const newIndex = fields.findIndex((field) => {\n return field.id === over?.id;\n });\n // Update the field array order using react-hook-form's move function\n move(oldIndex, newIndex);\n\n // Finally trigger validation for the array field,\n // so validation errors are updated for the new order\n trigger(name);\n }\n };\n\n return (\n <DndContext\n collisionDetection={closestCenter}\n modifiers={[restrictToVerticalAxis, restrictToWindowEdges]}\n onDragEnd={handleDragEnd}\n sensors={sensors}\n >\n <SortableContext\n strategy={verticalListSortingStrategy}\n items={fields.map((field) => {\n return field.id;\n })}\n >\n {children}\n </SortableContext>\n </DndContext>\n );\n};\n\nexport default SortContext;\n","import type { FieldArrayElementMethods } from './subcomponents/FieldArrayElement';\nimport type { FieldArrayProps } from './types';\n\nimport { cn, tv, variantsToClassNames } from '@fuf-stack/pixel-utils';\n\nimport { flatArrayKey } from '../helpers';\nimport { useUniformFieldArray } from '../hooks/useUniformFieldArray';\nimport ElementAppendButton from './subcomponents/ElementAppendButton';\nimport FieldArrayElement from './subcomponents/FieldArrayElement';\nimport FieldArrayLabel from './subcomponents/FieldArrayLabel';\nimport FieldArrayValidationError from './subcomponents/FieldArrayValidationError';\nimport SortContext from './subcomponents/SortContext';\n\nexport const fieldArrayVariants = tv({\n slots: {\n /** base class for the field array wrapper */\n base: [\n // base styles\n 'overflow-hidden rounded-small border border-divider bg-content1',\n // divider between items\n 'divide-y divide-divider',\n ],\n /** class for the actions menu button */\n actionsMenuButton: [\n // base styles\n 'flex items-center justify-center text-default-600',\n // fixed height/no round corners/center align\n 'h-full rounded-none',\n // focus styles - inset ring\n 'outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-focus',\n ],\n /** class for the append button */\n appendButton: [\n // base styles\n 'w-full justify-start rounded-b-small rounded-t-none font-semibold',\n // match label height (p-3 = 12px vertical padding + text-base line height)\n '!h-[48px] !min-h-0',\n // focus styles - inset ring with rounded bottom corners to match container\n 'outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-focus',\n ],\n /** class for the element fields grid */\n elementFieldsGrid: ['w-full grow p-3'],\n /** class for the label */\n label: [\n // override HeroUI label positioning and display\n 'pointer-events-auto! static! z-auto! block! w-full!',\n // reset any transforms or translations\n 'translate-x-0! translate-y-0! transform-none!',\n // card header styling - use text-medium (16px) instead of text-base for correct 48px height\n 'rounded-t-small p-3 font-semibold text-medium',\n ],\n /** class for the list */\n list: ['overflow-hidden'],\n /** class for the list wrapper */\n listWrapper: ['overflow-hidden'],\n /** class for the list item (performs motion animations) */\n listItem: [\n // base styles\n 'group relative flex flex-row',\n // overlap borders by shifting first item up 1px (similar to how last item overlaps with append button)\n 'first:-mt-px',\n ],\n /** class for the list item inner */\n listItemInner: [\n // base styles\n 'flex w-full flex-row items-stretch divide-divider bg-content1',\n // x division and borders\n 'divide-x divide-solid border-b border-t border-divider',\n ],\n /** class for the remove button */\n removeButton: [\n // base styles\n 'flex items-center justify-center',\n // fixed height/no round corners\n '!h-full !min-h-0 !rounded-none px-3',\n // focus styles - inset ring\n 'outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-focus',\n ],\n /** class for the sort drag handle */\n sortDragHandle: [\n // base styles\n 'flex cursor-grab items-center justify-center px-2 text-default-600 transition-colors',\n // hover and dragging state\n 'hover:bg-default-100 active:cursor-grabbing group-data-[dragging=true]:bg-default-100',\n // focus styles - inset ring\n 'outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-focus',\n ],\n },\n variants: {\n hasLabel: {\n false: {\n // focus styles - when there is no label, the first item actions menu button should have rounded top right corners\n actionsMenuButton:\n 'group-[:first-child]:!rounded-tr-small group-[:first-child]:group-data-[dragging=true]:!rounded-tr-none',\n // focus styles - when there is no label, the first item remove button focus ring should have rounded top right corners\n removeButton:\n 'group-[:first-child]:!rounded-tr-small group-[:first-child]:group-data-[dragging=true]:!rounded-tr-none',\n // focus styles - when there is no label, the first item sort drag handle focus ring should have rounded top left corners\n sortDragHandle:\n 'group-[:first-child]:rounded-tl-small group-[:first-child]:group-data-[dragging=true]:rounded-tl-none',\n },\n },\n },\n});\n\n/**\n * FieldArray component based in [RHF useFieldArray](https://react-hook-form.com/docs/usefieldarray)\n */\nconst FieldArray = ({\n appendButtonText = 'Add Element',\n children,\n className: _className = undefined,\n duplicate = false,\n elementInitialValue: _elementInitialValue = null,\n elementMarginBottom = undefined,\n flat = false,\n insertAfter = false,\n lastElementNotRemovable = false,\n name,\n sortable = false,\n ...uniformFieldProps\n}: FieldArrayProps) => {\n const {\n fields,\n append,\n remove,\n insert,\n move,\n disableAnimation,\n elementInitialValue,\n getValues,\n testId,\n } = useUniformFieldArray({\n name,\n flat,\n elementInitialValue: _elementInitialValue,\n lastElementNotRemovable,\n ...uniformFieldProps,\n });\n\n // className from slots\n const variants = fieldArrayVariants({ hasLabel: !!uniformFieldProps.label });\n const className = variantsToClassNames(variants, _className, 'base');\n\n return (\n <div className={className.base}>\n {/* field array label */}\n <FieldArrayLabel\n className={className.label}\n label={uniformFieldProps.label}\n name={name}\n />\n\n {fields.length ? (\n /* list wrapper */\n <div className={cn(className.listWrapper)}>\n {/* sortable context */}\n <SortContext\n fields={fields}\n move={move}\n name={name}\n sortable={sortable}\n >\n {/* list container */}\n <ul className={className.list} data-testid={testId}>\n {/* fields / list elements */}\n {fields.map((field, index) => {\n const elementName = flat\n ? `${name}.${index}.${flatArrayKey}`\n : `${name}.${index}`;\n const elementTestId = `${testId}_${index}`;\n\n // create methods for element\n const elementMethods: FieldArrayElementMethods = {\n append: () => {\n append(elementInitialValue);\n },\n duplicate: () => {\n const values = getValues(name);\n const currentValue = (values as unknown[])[index];\n const nextValue = flat\n ? { [flatArrayKey]: currentValue }\n : currentValue;\n insert(index + 1, nextValue);\n },\n insert: () => {\n insert(index + 1, elementInitialValue);\n },\n remove: () => {\n remove(index);\n },\n };\n\n return (\n <FieldArrayElement\n key={field.id}\n className={className}\n disableAnimation={disableAnimation}\n duplicate={duplicate}\n elementMarginBottom={elementMarginBottom}\n fields={fields}\n id={field.id}\n index={index}\n insertAfter={insertAfter}\n lastNotDeletable={lastElementNotRemovable}\n methods={elementMethods}\n sortable={sortable}\n testId={elementTestId}\n >\n {children({\n index,\n length: fields.length,\n methods: elementMethods,\n name: elementName,\n testId: elementTestId,\n })}\n </FieldArrayElement>\n );\n })}\n </ul>\n </SortContext>\n </div>\n ) : null}\n\n {/* top level field array errors */}\n <FieldArrayValidationError name={name} />\n\n {/* append elements button */}\n <ElementAppendButton\n appendButtonText={appendButtonText}\n className={className.appendButton}\n testId={`${testId}_append_button`}\n onClick={() => {\n append(elementInitialValue);\n }}\n />\n </div>\n );\n};\n\nexport default FieldArray;\n","import FieldArray from './FieldArray';\n\nexport type * from './types';\n\nexport { FieldArray };\n\nexport default FieldArray;\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FormContext-C3GymQOA.cjs","names":["toValidationFormat","debug","React","FormProvider: React.FC<FormProviderProps>","toFormFormat","toValidationFormat","HookFormProvider"],"sources":["../src/Form/subcomponents/FormResolver.ts","../src/Form/subcomponents/FormContext.tsx"],"sourcesContent":["import type {\n VetoFormattedError,\n VetoInstance,\n VetoTypeAny,\n} from '@fuf-stack/veto';\nimport type { FieldValues } from 'react-hook-form';\n\nimport { useMemo, useRef, useState } from 'react';\n\nimport { and, veto } from '@fuf-stack/veto';\n\nimport { toValidationFormat } from '../../helpers';\n\n/**\n * Hook that manages client validation schemas state.\n *\n * Provides a centralized way to add/remove dynamic validation schemas\n * that can be combined with base form validation.\n *\n * @returns Object with client validation state and memoized setter function\n */\nexport const useClientValidationManager = () => {\n // Client validation schemas state\n const [clientValidationSchemas, setClientValidationSchemas] = useState<\n Record<string, VetoTypeAny>\n >({});\n\n // Memoized function to set/clear client validation schema\n const setClientValidationSchema = useMemo(() => {\n return (key: string, schema: VetoTypeAny | null) => {\n // update client validation schemas\n setClientValidationSchemas((prev) => {\n // if no schema and no existing client validation schema for this key, do nothing\n if (!prev[key] && !schema) {\n return prev;\n }\n // if no schema, remove the client validation schema for this key\n if (!schema) {\n const { [key]: _removed, ...rest } = prev;\n return rest;\n }\n // if schema, add or update the client validation schema for this key\n return { ...prev, [key]: schema };\n });\n };\n }, []);\n\n return {\n clientValidationSchemas,\n setClientValidationSchema,\n };\n};\n\n/**\n * Hook that creates an extended validation instance combining base Veto validation with dynamic client validation.\n *\n * @param baseValidation - Optional base Veto validation schema\n * @returns Combined validation instance and client schema setter\n */\nexport const useExtendedValidation = (baseValidation?: VetoInstance) => {\n // Setup client validation schemas\n const { clientValidationSchemas, setClientValidationSchema } =\n useClientValidationManager();\n\n // Create a stable dependency array from the client validation schemas\n const clientSchemaValues = useMemo(\n () => {\n const keys = Object.keys(clientValidationSchemas).sort();\n return keys\n .map((key) => {\n return clientValidationSchemas[key];\n })\n .filter(Boolean);\n },\n // Include the object identity to react to schema instance updates with same shape\n [clientValidationSchemas],\n );\n\n // Memoized extended validation instance\n const extendedValidation = useMemo(\n () => {\n const hasBaseValidation = !!baseValidation;\n const hasClientSchemas = clientSchemaValues.length > 0;\n\n // If no base validation and no client schemas, return undefined\n if (!hasBaseValidation && !hasClientSchemas) {\n return undefined;\n }\n\n // If no client schemas, return base validation\n if (!hasClientSchemas) {\n return baseValidation;\n }\n\n // Combine client validation schemas\n const clientSchemasCombined = clientSchemaValues.reduce(\n // @ts-expect-error is ok, because initially it is null\n (combined, clientSchema) => {\n return combined ? and(combined, clientSchema) : clientSchema;\n },\n null,\n );\n\n // return combined validation\n if (hasBaseValidation && clientSchemasCombined) {\n return veto(and(baseValidation.schema, clientSchemasCombined));\n }\n\n // If we only have client schemas, return them as a veto instance\n if (clientSchemasCombined) {\n return veto(clientSchemasCombined);\n }\n\n // This should not happen due to the conditions above, but just in case\n return baseValidation;\n },\n // Recompute when validation schema instances change\n [baseValidation, clientSchemaValues],\n );\n\n return {\n extendedValidation,\n setClientValidationSchema,\n };\n};\n\n/**\n * Hook that creates a React Hook Form resolver from an extended validation instance.\n *\n * @param extendedValidation - Extended validation instance from useExtendedValidation\n * @returns Object containing resolver function, current validation errors, and optimization hash\n */\nexport const useFormResolver = (extendedValidation?: VetoInstance) => {\n // Use ref to store validation errors without triggering re-renders\n const validationErrors = useRef<VetoFormattedError>(undefined);\n\n // Memoized resolver function for React Hook Form\n const resolver = useMemo(() => {\n if (!extendedValidation) {\n return undefined;\n }\n\n return async (values: FieldValues) => {\n const validationValues = toValidationFormat(values) ?? {};\n const result = await extendedValidation.validateAsync(validationValues);\n validationErrors.current = result.errors ?? undefined;\n\n // Transform veto result to React Hook Form format\n return {\n values: result.data ?? {},\n errors: result.errors ?? {},\n };\n };\n }, [extendedValidation]);\n\n // Hash for memo dependency optimization in consuming components\n const validationErrorsHash = JSON.stringify(validationErrors.current);\n\n return {\n resolver,\n validationErrors: validationErrors.current,\n validationErrorsHash,\n };\n};\n","import type {\n VetoFormattedError,\n VetoInstance,\n VetoTypeAny,\n} from '@fuf-stack/veto';\nimport type { BaseSyntheticEvent, ReactNode } from 'react';\nimport type { FieldValues, Path, SubmitHandler } from 'react-hook-form';\n\nimport React, { useCallback, useMemo, useRef, useState } from 'react';\nimport { FormProvider as HookFormProvider, useForm } from 'react-hook-form';\n\nimport createDebug from 'debug';\n\nimport { useLocalStorage } from '@fuf-stack/pixels';\n\nimport { toFormFormat, toValidationFormat } from '../../helpers';\nimport { useExtendedValidation, useFormResolver } from './FormResolver';\n\nconst debug = createDebug('uniform:FormContext');\n\ntype DebugMode = 'debug' | 'debug-testids' | 'off' | 'disabled';\n\nexport interface DebugModeSettings {\n /** disable form debug completely */\n disable?: boolean;\n /** custom localStorage key to save debug mode state */\n localStorageKey?: string;\n}\n\n/**\n * Listener function that gets called when a field changes due to user input\n */\nexport type UserChangeListener<TFieldValues extends object = object> = (\n fieldName: Path<TFieldValues>,\n value: unknown,\n) => void;\n\nconst DEBUG_MODE_LOCAL_STORAGE_KEY_DEFAULT = 'uniform:debug-mode';\n\n/**\n * The `UniformContext` provides control over the form's submission behavior and may optionally include\n * a Veto validation schema for form validation.\n *\n * Specifically, this context offers:\n * 1. **Form Submission Control**: The `preventSubmit` function allows components to enable or disable\n * form submissions.\n * 2. **Optional Validation Schema**: The `validation` property may hold a Veto validation schema instance\n * that can be used to validate form fields and handle validation logic.\n * 3. **Client Validation**: The `setClientValidationSchema` function allows setting dynamic client-side\n * validation schemas that complement the base Veto validation.\n * 4. **User Change Tracking**: The `userChange` property provides a pub/sub system for tracking\n * user-initiated field changes (typing, clicking, selecting) - NOT programmatic changes like\n * form.reset() or form.setValue(). Used by the `useWatchUserChange` hook to enable reactive\n * field dependencies.\n *\n * This context is useful for components that need to interact with or control the form submission state,\n * or access the validation schema for managing form validation logic.\n *\n * IMPORTANT: Context Singleton Pattern for HMR (Hot Module Replacement)\n * =====================================================================\n *\n * We use a global window variable to ensure only ONE context instance exists across\n * hot module reloads during development. This is critical because:\n *\n * **The Problem:**\n * When using Vite/Storybook with Fast Refresh (HMR), editing this file causes it to\n * be re-evaluated. Each re-evaluation runs `React.createContext()` again, creating a\n * NEW context instance. This leads to \"context instance mismatch\":\n *\n * 1. FormProvider (provider) loads and uses context instance A\n * 2. File is edited, HMR triggers\n * 3. SubmitButton (consumer) hot-reloads and imports context instance B\n * 4. Provider writes to instance A, Consumer reads from instance B\n * 5. Result: Consumer sees default values (triggerSubmit = () => undefined)\n * 6. Clicking submit does nothing because it calls the empty default function\n *\n * **The Solution:**\n * By storing the context in `window.__UNIFORM_CONTEXT__`, we ensure:\n * - First load: Create context and store in window\n * - Subsequent HMRs: Reuse the same context from window\n * - All components always reference the SAME context instance\n * - Provider and consumers can properly communicate\n *\n * **Why This Is Safe:**\n * - Only affects development (production has no HMR)\n * - Context type never changes (same interface)\n * - React handles cleanup on unmount normally\n * - No memory leaks (context is lightweight)\n *\n * Without this pattern, you'd need to restart the dev server after every edit\n * to FormContext.tsx to ensure all components use the same context instance.\n */\n\n// Define the context type\ninterface UniformContextType {\n /** Form debug mode enabled or not */\n debugMode: DebugMode;\n /** settings for from debug mode */\n debugModeSettings?: DebugModeSettings;\n /** Function to update if the form can currently be submitted */\n preventSubmit: (prevent: boolean) => void;\n /** Setter to enable or disable form debug mode */\n setDebugMode: (debugMode: DebugMode) => void;\n /** Function to trigger form submit programmatically */\n triggerSubmit: (e?: BaseSyntheticEvent) => Promise<void> | void;\n /** User change tracking (user input only, not programmatic changes) */\n userChange: {\n /**\n * Subscribe to user field changes.\n * Returns an unsubscribe function.\n */\n subscribe: (listener: UserChangeListener) => () => void;\n /**\n * Notify all subscribers about a user field change.\n * Called from useController when user interacts with a field.\n */\n notify: (fieldName: string, value: unknown) => void;\n };\n /** Form validation configuration */\n validation: {\n /** Base validation schema instance (without client validation) */\n baseInstance?: VetoInstance;\n /** Veto validation schema instance for form validation */\n instance?: VetoInstance;\n /** Current validation errors in form */\n errors?: VetoFormattedError;\n /** Function to set client validation schema for a specific key */\n setClientValidationSchema: (\n key: string,\n schema: VetoTypeAny | null,\n ) => void;\n };\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nif (!(window as any).__UNIFORM_CONTEXT__) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (window as any).__UNIFORM_CONTEXT__ = React.createContext<UniformContextType>(\n {\n debugMode: 'off',\n preventSubmit: () => {\n return undefined;\n },\n setDebugMode: () => {\n return undefined;\n },\n triggerSubmit: () => {\n return undefined;\n },\n userChange: {\n subscribe: () => {\n return () => {\n return undefined;\n };\n },\n notify: () => {\n return undefined;\n },\n },\n validation: {\n setClientValidationSchema: () => {\n return undefined;\n },\n },\n },\n );\n debug('Creating new UniformContext instance');\n} else {\n debug(\n 'Reusing existing UniformContext instance from window.__UNIFORM_CONTEXT__',\n );\n}\n\n// Export the singleton context instance from window\n// This ensures all imports get the same context, even after HMR\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const UniformContext = (window as any)\n .__UNIFORM_CONTEXT__ as React.Context<UniformContextType>;\n\ndebug('UniformContext exported', {\n contextExists: !!UniformContext,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n windowContextExists: !!(window as any).__UNIFORM_CONTEXT__,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n contextsMatch: UniformContext === (window as any).__UNIFORM_CONTEXT__,\n});\n\n// Define props for the FormProvider component, extending HookForm's props\ninterface FormProviderProps {\n /** children form render function */\n children: (childProps: {\n handleSubmit: (e?: BaseSyntheticEvent) => Promise<void>;\n isValid: boolean;\n }) => ReactNode;\n /** settings for from debug mode */\n debugModeSettings?: DebugModeSettings;\n /** initial form values */\n initialValues?: FieldValues;\n /** form submit handler */\n onSubmit: SubmitHandler<FieldValues>;\n /** Veto validation schema instance */\n validation?: VetoInstance;\n /** when the validation should be triggered */\n validationTrigger: 'onChange' | 'onBlur' | 'onSubmit' | 'onTouched' | 'all';\n}\n\n/**\n * FormProvider component provides:\n * - Veto validation schema context\n * - Client validation schema management\n * - Submit handler with automatic data conversion and submission control with preventSubmit\n * - Form Debug Mode state\n * - React Hook Form context\n */\nconst FormProvider: React.FC<FormProviderProps> = ({\n children,\n debugModeSettings = undefined,\n initialValues = undefined,\n onSubmit,\n validation: baseValidation = undefined,\n validationTrigger,\n}) => {\n // Form Debug mode state is handled in the form context\n const [debugMode, setDebugMode] = useLocalStorage<DebugMode>(\n debugModeSettings?.localStorageKey ?? DEBUG_MODE_LOCAL_STORAGE_KEY_DEFAULT,\n 'off',\n );\n\n // Create extended validation combining base + client validations\n const { extendedValidation, setClientValidationSchema } =\n useExtendedValidation(baseValidation);\n\n // Create resolver from extended validation + get current validation errors\n const { resolver, validationErrors, validationErrorsHash } =\n useFormResolver(extendedValidation);\n\n // Initialize react hook form with the resolver\n const methods = useForm({\n defaultValues: initialValues ? toFormFormat(initialValues) : initialValues,\n // set rhf mode\n // see: https://react-hook-form.com/docs/useform#mode\n mode: validationTrigger,\n resolver,\n });\n\n // Get isValid from React Hook Form's formState\n const isValid = methods.formState?.isValid;\n\n // Control if the form can currently be submitted\n const [preventSubmit, setPreventSubmit] = useState(false);\n\n // User change listener registry (stored in ref to avoid re-renders)\n const userChangeListenersRef = useRef<Set<UserChangeListener>>(new Set());\n\n // Subscribe to user changes\n const subscribeUserChange = useCallback(\n (listener: UserChangeListener): (() => void) => {\n userChangeListenersRef.current.add(listener);\n // Return cleanup function to unsubscribe\n return () => {\n userChangeListenersRef.current.delete(listener);\n };\n },\n [],\n );\n\n // Notify all subscribers about user change\n const notifyUserChange = useCallback(\n (fieldName: string, value: unknown): void => {\n // Notify all registered listeners\n userChangeListenersRef.current.forEach((listener) => {\n listener(fieldName as Path<object>, value);\n });\n },\n [],\n );\n\n // Create submit handler with automatic data conversion\n // eslint-disable-next-line consistent-return\n const handleSubmit = async (e?: React.BaseSyntheticEvent) => {\n debug('handleSubmit called', {\n preventSubmit,\n formStateIsValid: methods.formState.isValid,\n validationErrors: methods.formState.errors,\n validationTrigger,\n formValues: methods.getValues(),\n });\n\n // only prevent submit when form state is valid, because otherwise\n // submit will only trigger validation and add errors / focus invalid fields\n if (methods.formState.isValid && preventSubmit) {\n debug('⛔ Form submit PREVENTED', {\n formStateIsValid: methods.formState.isValid,\n preventSubmit,\n });\n console.warn(\n '[FormProvider] form submit was prevented because preventSubmit is true...',\n );\n e?.preventDefault();\n return Promise.resolve();\n }\n\n debug('✓ Form submit ALLOWED', {\n formStateIsValid: methods.formState.isValid,\n preventSubmit,\n reason: !methods.formState.isValid\n ? 'Form is invalid (will trigger validation and show errors)'\n : 'Form is valid and preventSubmit is false',\n });\n\n // Convert nullish strings and filter out empty values before submission\n const wrappedOnSubmit = (data: FieldValues, event?: BaseSyntheticEvent) => {\n const submitData = toValidationFormat(data) ?? {};\n debug('onSubmit callback called', { submitData });\n return onSubmit(submitData, event);\n };\n\n await methods.handleSubmit(wrappedOnSubmit)(e);\n\n debug('handleSubmit completed');\n };\n\n // Memoize the context value to prevent re-renders\n const contextValue = useMemo(\n () => {\n return {\n // set debugMode to disabled when debugModeSettings.disable is true\n // otherwise use current debug mode from localStorage\n debugMode: debugModeSettings?.disable ? 'disabled' : debugMode,\n preventSubmit: (prevent: boolean) => {\n debug('preventSubmit called', {\n previousValue: preventSubmit,\n newValue: prevent,\n formStateIsValid: methods.formState.isValid,\n validationErrors: methods.formState.errors,\n });\n setPreventSubmit(prevent);\n },\n setClientValidationSchema,\n setDebugMode,\n triggerSubmit: handleSubmit,\n userChange: {\n subscribe: subscribeUserChange,\n notify: notifyUserChange,\n },\n validation: {\n baseInstance: baseValidation,\n instance: extendedValidation,\n errors: validationErrors,\n setClientValidationSchema,\n },\n };\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [debugMode, debugModeSettings?.disable, validationErrorsHash],\n );\n\n return (\n <UniformContext.Provider value={contextValue}>\n {/* Spread all hook form props into HookFormProvider */}\n <HookFormProvider {...methods}>\n {children({ handleSubmit, isValid })}\n </HookFormProvider>\n </UniformContext.Provider>\n );\n};\n\nexport default FormProvider;\n"],"mappings":"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"}
|