@verbb/formie-browser 1.0.12 → 1.0.14
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/CHANGELOG.md +57 -0
- package/dist/chunks/{address-country-Rx6GQTND.js → address-country-Dn71jroa.js} +10 -4
- package/dist/chunks/{address-finder-k7_BXaRe.js → address-finder-O49uDRoR.js} +2 -2
- package/dist/chunks/{address-state-BwE01m2_.js → address-state-ByYatUur.js} +154 -143
- package/dist/chunks/{api-DqpfkZWL.js → api-D6kJ7kXZ.js} +183 -179
- package/dist/chunks/{api-BUb6P-xu.js → api-DYYsVIub.js} +77 -47
- package/dist/chunks/{api-sPqGbOww.js → api-ghNr2uxX.js} +15 -9
- package/dist/chunks/{bpoint-Dlq34XH1.js → bpoint-D0RKFM4F.js} +3 -3
- package/dist/chunks/calculations-YEoVCG2q.js +310 -0
- package/dist/chunks/{captcha-eu-CGm8Lbrj.js → captcha-eu-DERJbXnH.js} +5 -4
- package/dist/chunks/{checkbox-radio-BY2aTCOG.js → checkbox-radio-gsm8QPJg.js} +74 -75
- package/dist/chunks/{combobox-C0EuExSI.js → combobox-CWNdx4Fk.js} +290 -279
- package/dist/chunks/conditions-DqNHLTbN.js +464 -0
- package/dist/chunks/country-from-ip-DDj_mFki.js +29 -0
- package/dist/chunks/csrf-DxHg_ZYt.js +61 -0
- package/dist/chunks/{custom-google-maps-BsaSirEZ.js → custom-google-maps-C4l2S3GO.js} +9 -3
- package/dist/chunks/{custom-link-CJ1-FjEM.js → custom-link-CLazgKYH.js} +8 -2
- package/dist/chunks/{custom-maps-DYW_pBid.js → custom-maps-DqcAlD0v.js} +10 -4
- package/dist/chunks/{date-picker-5CA_-zGb.js → date-picker-RUnevF7l.js} +456 -430
- package/dist/chunks/{dist-BdUy8m_p.js → dist-ZLeW0zZ3.js} +1280 -452
- package/dist/chunks/{eway-D9_m8ooj.js → eway-or6dtjoT.js} +3 -3
- package/dist/chunks/field-references.resolver-Ca8MguFv.js +104 -0
- package/dist/chunks/{file-upload-rqfZNqlH.js → file-upload-Bm-TXyNB.js} +104 -96
- package/dist/chunks/friendly-captcha-v1-GFqCt1Mh.js +34 -0
- package/dist/chunks/{friendly-captcha-v2-CLSAbkqx.js → friendly-captcha-v2-WoW246JG.js} +6 -5
- package/dist/chunks/{friendly-challenge-8uPatWqk.js → friendly-challenge-DPG9MJb1.js} +111 -102
- package/dist/chunks/{go-cardless-DAT3ZaQf.js → go-cardless-DzJ-0FKg.js} +2 -2
- package/dist/chunks/google-address-C1P1nTDM.js +163 -0
- package/dist/chunks/{hcaptcha-CGLAmgjO.js → hcaptcha-D0T8aIHz.js} +3 -3
- package/dist/chunks/{hidden-D7_Ch-QN.js → hidden-BZhXnNPe.js} +8 -2
- package/dist/chunks/http-C2QdHuWO.js +27 -0
- package/dist/chunks/{leaflet-src-j-lHNmhR.js → leaflet-src-DE6rv6M-.js} +42 -46
- package/dist/chunks/{loqate-CJPzBmSm.js → loqate-DD1S7PY9.js} +2 -2
- package/dist/chunks/{mollie-Bibhl67p.js → mollie-DG8Ju83x.js} +2 -2
- package/dist/chunks/{moneris-H2wSqk9h.js → moneris-C8m3Fvqu.js} +3 -3
- package/dist/chunks/opayo-B3EvrVxw.js +188 -0
- package/dist/chunks/{paddle-DkvIxQdG.js → paddle-BIYR9Um3.js} +3 -3
- package/dist/chunks/{password-validation-T0vDQPCr.js → password-validation-C8_uO_c_.js} +18 -12
- package/dist/chunks/{paypal-CQpAF7Ua.js → paypal-B_yxIo2d.js} +7 -5
- package/dist/chunks/{payway-CwDkC7YZ.js → payway-CeOzS0sL.js} +3 -3
- package/dist/chunks/{phone-country-D3ayr60L.js → phone-country-bAqje17P.js} +80 -63
- package/dist/chunks/{place-kit-BGHklIZ-.js → place-kit-BE5gi3vo.js} +3 -3
- package/dist/chunks/{placekit-autocomplete.esm-DWVabQlq.js → placekit-autocomplete.esm-CZZERYur.js} +11 -15
- package/dist/chunks/{recaptcha-enterprise-XPId5-bS.js → recaptcha-enterprise-CruXddZq.js} +4 -4
- package/dist/chunks/{recaptcha-shared-CLYJvojk.js → recaptcha-shared-AQRMDMme.js} +1 -1
- package/dist/chunks/{recaptcha-v2-checkbox-Cy-0PEPc.js → recaptcha-v2-checkbox-CCnJYCnG.js} +4 -4
- package/dist/chunks/{recaptcha-v2-invisible-BwRH540O.js → recaptcha-v2-invisible-BuVqRRYn.js} +4 -4
- package/dist/chunks/{recaptcha-v3-No4Ykrhk.js → recaptcha-v3-CloqhO2A.js} +4 -4
- package/dist/chunks/{repeater-BVnPUqTj.js → repeater-DwE27jI1.js} +25 -19
- package/dist/chunks/request-profile-DhwkeCpS.js +10 -0
- package/dist/chunks/rich-text-uV4o_pGk.js +361 -0
- package/dist/chunks/{chunk-3b4jIN3o.js → rolldown-runtime-DtPi1Y-2.js} +2 -2
- package/dist/chunks/{sdk-BhHAYgga.js → sdk-lkwSvlpM.js} +282 -234
- package/dist/chunks/{shared-Bx9s0i0P.js → shared-OKhSay59.js} +27 -21
- package/dist/chunks/{signature-xz4QO7CR.js → signature-7cldFbqj.js} +160 -112
- package/dist/chunks/{snaptcha-DKx98oon.js → snaptcha-C04kNGYQ.js} +2 -2
- package/dist/chunks/{square-DwdcOI1G.js → square-DEzxv9D9.js} +8 -6
- package/dist/chunks/{stripe-DaoG2FT1.js → stripe-CVPQGDz3.js} +10 -11
- package/dist/chunks/{summary-Dks0gXS3.js → summary-BF_8mrXI.js} +47 -45
- package/dist/chunks/{survey-likert-DkE6bR7B.js → survey-likert-fk1hUPff.js} +7 -1
- package/dist/chunks/{survey-rank-DN6x4IZM.js → survey-rank-BsLGl2LX.js} +37 -25
- package/dist/chunks/{survey-rating-BnsNL9U5.js → survey-rating-DVS6e6fM.js} +17 -5
- package/dist/chunks/{table-CAjCJHrL.js → table-DnIBdeKF.js} +21 -15
- package/dist/chunks/{text-limit-Bn18WrPU.js → text-limit-LGMPhFuC.js} +40 -34
- package/dist/chunks/{theme-classes-Tv7q7ToE.js → theme-classes-DAQuEqdP.js} +1 -1
- package/dist/chunks/{turnstile-DJakPzQD.js → turnstile-n9DNyPxi.js} +3 -3
- package/dist/chunks/{upload-manager-W-QDgxKD.js → upload-manager-BbiUosZq.js} +410 -350
- package/dist/chunks/{utils-Vqp8i_RM.js → utils-DpUBPadZ.js} +20 -14
- package/dist/css/formie-base.css +104 -1
- package/dist/css/theme/_messages.css +2 -0
- package/dist/css/theme/_tokens.css +31 -25
- package/dist/css/theme/fields/_signature.css +2 -1
- package/dist/css/theme/forms/_form.css +5 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1778 -1425
- package/dist/js/contracts/client.d.ts +5 -3
- package/dist/js/contracts/client.d.ts.map +1 -1
- package/dist/js/contracts/common.d.ts +2 -2
- package/dist/js/contracts/common.d.ts.map +1 -1
- package/dist/js/contracts/modules.d.ts +37 -12
- package/dist/js/contracts/modules.d.ts.map +1 -1
- package/dist/js/contracts/schema.d.ts +20 -38
- package/dist/js/contracts/schema.d.ts.map +1 -1
- package/dist/js/contracts/theme.d.ts +4 -1
- package/dist/js/contracts/theme.d.ts.map +1 -1
- package/dist/js/core/client-rendered-modules.d.ts +17 -0
- package/dist/js/core/client-rendered-modules.d.ts.map +1 -0
- package/dist/js/core/create-formie-client.d.ts.map +1 -1
- package/dist/js/core/field-error-aria.d.ts +23 -0
- package/dist/js/core/field-error-aria.d.ts.map +1 -0
- package/dist/js/core/hydrate-modules.d.ts +10 -8
- package/dist/js/core/hydrate-modules.d.ts.map +1 -1
- package/dist/js/core/submit-result-state.d.ts.map +1 -1
- package/dist/js/core/submit-result-ui.d.ts.map +1 -1
- package/dist/js/core/validation-focus.d.ts.map +1 -1
- package/dist/js/modules/address/address-finder.d.ts +1 -1
- package/dist/js/modules/address/address-finder.d.ts.map +1 -1
- package/dist/js/modules/address/factories.d.ts +3 -3
- package/dist/js/modules/address/factories.d.ts.map +1 -1
- package/dist/js/modules/address/google-address.d.ts +2 -1
- package/dist/js/modules/address/google-address.d.ts.map +1 -1
- package/dist/js/modules/address/index.d.ts +2 -2
- package/dist/js/modules/address/index.d.ts.map +1 -1
- package/dist/js/modules/address/loqate.d.ts +1 -1
- package/dist/js/modules/address/loqate.d.ts.map +1 -1
- package/dist/js/modules/address/place-kit.d.ts +1 -1
- package/dist/js/modules/address/place-kit.d.ts.map +1 -1
- package/dist/js/modules/captchas/captcha-eu.d.ts +1 -1
- package/dist/js/modules/captchas/captcha-eu.d.ts.map +1 -1
- package/dist/js/modules/captchas/factories.d.ts +11 -11
- package/dist/js/modules/captchas/factories.d.ts.map +1 -1
- package/dist/js/modules/captchas/friendly-captcha-v1.d.ts +1 -1
- package/dist/js/modules/captchas/friendly-captcha-v1.d.ts.map +1 -1
- package/dist/js/modules/captchas/friendly-captcha-v2.d.ts +1 -1
- package/dist/js/modules/captchas/friendly-captcha-v2.d.ts.map +1 -1
- package/dist/js/modules/captchas/hcaptcha.d.ts +1 -1
- package/dist/js/modules/captchas/hcaptcha.d.ts.map +1 -1
- package/dist/js/modules/captchas/index.d.ts +2 -2
- package/dist/js/modules/captchas/index.d.ts.map +1 -1
- package/dist/js/modules/captchas/recaptcha-enterprise.d.ts +1 -1
- package/dist/js/modules/captchas/recaptcha-enterprise.d.ts.map +1 -1
- package/dist/js/modules/captchas/recaptcha-v2-checkbox.d.ts +1 -1
- package/dist/js/modules/captchas/recaptcha-v2-checkbox.d.ts.map +1 -1
- package/dist/js/modules/captchas/recaptcha-v2-invisible.d.ts +1 -1
- package/dist/js/modules/captchas/recaptcha-v2-invisible.d.ts.map +1 -1
- package/dist/js/modules/captchas/recaptcha-v3.d.ts +1 -1
- package/dist/js/modules/captchas/recaptcha-v3.d.ts.map +1 -1
- package/dist/js/modules/captchas/snaptcha.d.ts +1 -1
- package/dist/js/modules/captchas/snaptcha.d.ts.map +1 -1
- package/dist/js/modules/captchas/turnstile.d.ts +1 -1
- package/dist/js/modules/captchas/turnstile.d.ts.map +1 -1
- package/dist/js/modules/fields/address-country.d.ts +2 -2
- package/dist/js/modules/fields/address-country.d.ts.map +1 -1
- package/dist/js/modules/fields/address-state.d.ts +2 -2
- package/dist/js/modules/fields/address-state.d.ts.map +1 -1
- package/dist/js/modules/fields/calculations.d.ts +2 -2
- package/dist/js/modules/fields/calculations.d.ts.map +1 -1
- package/dist/js/modules/fields/checkbox-radio.d.ts +2 -2
- package/dist/js/modules/fields/checkbox-radio.d.ts.map +1 -1
- package/dist/js/modules/fields/combobox.d.ts +2 -2
- package/dist/js/modules/fields/combobox.d.ts.map +1 -1
- package/dist/js/modules/fields/conditions/config.d.ts.map +1 -1
- package/dist/js/modules/fields/conditions/effects.d.ts +1 -0
- package/dist/js/modules/fields/conditions/effects.d.ts.map +1 -1
- package/dist/js/modules/fields/conditions/evaluator.d.ts +4 -1
- package/dist/js/modules/fields/conditions/evaluator.d.ts.map +1 -1
- package/dist/js/modules/fields/conditions/references.d.ts.map +1 -1
- package/dist/js/modules/fields/conditions/submission-context.d.ts +15 -0
- package/dist/js/modules/fields/conditions/submission-context.d.ts.map +1 -0
- package/dist/js/modules/fields/conditions/types.d.ts +3 -1
- package/dist/js/modules/fields/conditions/types.d.ts.map +1 -1
- package/dist/js/modules/fields/conditions/values.d.ts +1 -1
- package/dist/js/modules/fields/conditions/values.d.ts.map +1 -1
- package/dist/js/modules/fields/conditions.d.ts +2 -2
- package/dist/js/modules/fields/conditions.d.ts.map +1 -1
- package/dist/js/modules/fields/custom-google-maps.d.ts +2 -2
- package/dist/js/modules/fields/custom-google-maps.d.ts.map +1 -1
- package/dist/js/modules/fields/custom-link.d.ts +2 -2
- package/dist/js/modules/fields/custom-link.d.ts.map +1 -1
- package/dist/js/modules/fields/custom-maps.d.ts +2 -2
- package/dist/js/modules/fields/custom-maps.d.ts.map +1 -1
- package/dist/js/modules/fields/date-picker.d.ts +2 -2
- package/dist/js/modules/fields/date-picker.d.ts.map +1 -1
- package/dist/js/modules/fields/file-upload.d.ts +2 -2
- package/dist/js/modules/fields/file-upload.d.ts.map +1 -1
- package/dist/js/modules/fields/hidden.d.ts +2 -2
- package/dist/js/modules/fields/hidden.d.ts.map +1 -1
- package/dist/js/modules/fields/index.d.ts +2 -2
- package/dist/js/modules/fields/index.d.ts.map +1 -1
- package/dist/js/modules/fields/password-validation.d.ts +2 -2
- package/dist/js/modules/fields/password-validation.d.ts.map +1 -1
- package/dist/js/modules/fields/phone-country.d.ts +2 -2
- package/dist/js/modules/fields/phone-country.d.ts.map +1 -1
- package/dist/js/modules/fields/repeater.d.ts +2 -2
- package/dist/js/modules/fields/repeater.d.ts.map +1 -1
- package/dist/js/modules/fields/rich-text.d.ts +2 -2
- package/dist/js/modules/fields/rich-text.d.ts.map +1 -1
- package/dist/js/modules/fields/shared.d.ts +1 -0
- package/dist/js/modules/fields/shared.d.ts.map +1 -1
- package/dist/js/modules/fields/signature.d.ts +2 -2
- package/dist/js/modules/fields/signature.d.ts.map +1 -1
- package/dist/js/modules/fields/summary.d.ts +2 -2
- package/dist/js/modules/fields/summary.d.ts.map +1 -1
- package/dist/js/modules/fields/survey-likert.d.ts +2 -2
- package/dist/js/modules/fields/survey-likert.d.ts.map +1 -1
- package/dist/js/modules/fields/survey-rank.d.ts +2 -2
- package/dist/js/modules/fields/survey-rank.d.ts.map +1 -1
- package/dist/js/modules/fields/survey-rating.d.ts +2 -2
- package/dist/js/modules/fields/survey-rating.d.ts.map +1 -1
- package/dist/js/modules/fields/table.d.ts +2 -2
- package/dist/js/modules/fields/table.d.ts.map +1 -1
- package/dist/js/modules/fields/text-limit.d.ts +2 -2
- package/dist/js/modules/fields/text-limit.d.ts.map +1 -1
- package/dist/js/modules/fields/upload-manager.d.ts +2 -2
- package/dist/js/modules/fields/upload-manager.d.ts.map +1 -1
- package/dist/js/modules/loader.d.ts +10 -4
- package/dist/js/modules/loader.d.ts.map +1 -1
- package/dist/js/modules/payments/bpoint.d.ts +1 -1
- package/dist/js/modules/payments/bpoint.d.ts.map +1 -1
- package/dist/js/modules/payments/eway.d.ts +1 -1
- package/dist/js/modules/payments/eway.d.ts.map +1 -1
- package/dist/js/modules/payments/factories.d.ts +7 -7
- package/dist/js/modules/payments/factories.d.ts.map +1 -1
- package/dist/js/modules/payments/go-cardless.d.ts +1 -1
- package/dist/js/modules/payments/go-cardless.d.ts.map +1 -1
- package/dist/js/modules/payments/index.d.ts +2 -2
- package/dist/js/modules/payments/index.d.ts.map +1 -1
- package/dist/js/modules/payments/mollie.d.ts +1 -1
- package/dist/js/modules/payments/mollie.d.ts.map +1 -1
- package/dist/js/modules/payments/moneris.d.ts +1 -1
- package/dist/js/modules/payments/moneris.d.ts.map +1 -1
- package/dist/js/modules/payments/opayo.d.ts +1 -1
- package/dist/js/modules/payments/opayo.d.ts.map +1 -1
- package/dist/js/modules/payments/paddle.d.ts +1 -1
- package/dist/js/modules/payments/paddle.d.ts.map +1 -1
- package/dist/js/modules/payments/paypal.d.ts +1 -1
- package/dist/js/modules/payments/paypal.d.ts.map +1 -1
- package/dist/js/modules/payments/payway.d.ts +1 -1
- package/dist/js/modules/payments/payway.d.ts.map +1 -1
- package/dist/js/modules/payments/square.d.ts +1 -1
- package/dist/js/modules/payments/square.d.ts.map +1 -1
- package/dist/js/modules/payments/stripe.d.ts +1 -1
- package/dist/js/modules/payments/stripe.d.ts.map +1 -1
- package/dist/js/modules/payments/utils.d.ts +6 -0
- package/dist/js/modules/payments/utils.d.ts.map +1 -1
- package/dist/js/modules/registry.d.ts +6 -4
- package/dist/js/modules/registry.d.ts.map +1 -1
- package/dist/js/submit/pipeline.d.ts.map +1 -1
- package/dist/js/theme/browser-theme-state.generated.d.ts +24 -0
- package/dist/js/theme/browser-theme-state.generated.d.ts.map +1 -0
- package/dist/js/theme/theme-classes.d.ts +3 -3
- package/dist/js/theme/theme-classes.d.ts.map +1 -1
- package/dist/js/transport/forms-api.d.ts +5 -3
- package/dist/js/transport/forms-api.d.ts.map +1 -1
- package/dist/js/utils/country-from-ip.d.ts +2 -2
- package/dist/js/utils/country-from-ip.d.ts.map +1 -1
- package/dist/js/utils/csrf.d.ts +17 -0
- package/dist/js/utils/csrf.d.ts.map +1 -0
- package/dist/js/utils/field-references.parser.d.ts +1 -0
- package/dist/js/utils/field-references.parser.d.ts.map +1 -1
- package/dist/js/utils/field-references.resolver.d.ts.map +1 -1
- package/dist/js/utils/field-references.types.d.ts +1 -0
- package/dist/js/utils/field-references.types.d.ts.map +1 -1
- package/dist/js/utils/http.d.ts +3 -1
- package/dist/js/utils/http.d.ts.map +1 -1
- package/dist/js/utils/request-profile.d.ts +4 -0
- package/dist/js/utils/request-profile.d.ts.map +1 -0
- package/dist/js/utils/unload-warning.d.ts.map +1 -1
- package/dist/js/validation/rules/email.d.ts.map +1 -1
- package/dist/js/validation/rules/match.d.ts.map +1 -1
- package/dist/js/validation/rules/number.d.ts.map +1 -1
- package/dist/js/validation/rules/required.d.ts.map +1 -1
- package/dist/js/validation/rules/shared.d.ts.map +1 -1
- package/dist/js/validation/rules/url.d.ts.map +1 -1
- package/dist/js/validation/skip.d.ts +7 -0
- package/dist/js/validation/skip.d.ts.map +1 -0
- package/dist/js/validation/submit-readiness.d.ts.map +1 -1
- package/dist/js/validation/validator.d.ts.map +1 -1
- package/package.json +43 -12
- package/src/css/formie-base.css +104 -1
- package/src/css/theme/_messages.css +2 -0
- package/src/css/theme/_tokens.css +31 -25
- package/src/css/theme/fields/_signature.css +2 -1
- package/src/css/theme/forms/_form.css +5 -1
- package/src/index.ts +13 -8
- package/src/js/contracts/client.ts +5 -3
- package/src/js/contracts/common.ts +5 -6
- package/src/js/contracts/modules.ts +41 -12
- package/src/js/contracts/schema.ts +21 -43
- package/src/js/contracts/theme.ts +6 -1
- package/src/js/core/client-rendered-modules.ts +69 -0
- package/src/js/core/create-formie-client.ts +119 -73
- package/src/js/core/field-error-aria.ts +93 -0
- package/src/js/core/hydrate-modules.ts +54 -29
- package/src/js/core/submit-result-state.ts +34 -45
- package/src/js/core/submit-result-ui.ts +21 -65
- package/src/js/core/validation-focus.ts +20 -20
- package/src/js/modules/address/address-finder.ts +1 -1
- package/src/js/modules/address/factories.ts +15 -13
- package/src/js/modules/address/google-address.ts +10 -6
- package/src/js/modules/address/index.ts +2 -2
- package/src/js/modules/address/loqate.ts +1 -1
- package/src/js/modules/address/place-kit.ts +1 -1
- package/src/js/modules/captchas/captcha-eu.ts +2 -2
- package/src/js/modules/captchas/factories.ts +66 -42
- package/src/js/modules/captchas/friendly-captcha-v1.ts +12 -2
- package/src/js/modules/captchas/friendly-captcha-v2.ts +4 -2
- package/src/js/modules/captchas/hcaptcha.ts +5 -5
- package/src/js/modules/captchas/index.ts +2 -2
- package/src/js/modules/captchas/recaptcha-enterprise.ts +2 -2
- package/src/js/modules/captchas/recaptcha-v2-checkbox.ts +3 -3
- package/src/js/modules/captchas/recaptcha-v2-invisible.ts +2 -2
- package/src/js/modules/captchas/recaptcha-v3.ts +2 -2
- package/src/js/modules/captchas/snaptcha.ts +1 -1
- package/src/js/modules/captchas/turnstile.ts +3 -3
- package/src/js/modules/fields/address-country.ts +6 -4
- package/src/js/modules/fields/address-state.ts +20 -12
- package/src/js/modules/fields/calculations.ts +5 -3
- package/src/js/modules/fields/checkbox-radio.ts +24 -42
- package/src/js/modules/fields/combobox.ts +25 -9
- package/src/js/modules/fields/conditions/config.ts +17 -20
- package/src/js/modules/fields/conditions/effects.ts +23 -26
- package/src/js/modules/fields/conditions/evaluator.ts +21 -29
- package/src/js/modules/fields/conditions/references.ts +16 -5
- package/src/js/modules/fields/conditions/submission-context.ts +80 -0
- package/src/js/modules/fields/conditions/types.ts +3 -1
- package/src/js/modules/fields/conditions/values.ts +31 -6
- package/src/js/modules/fields/conditions.ts +59 -18
- package/src/js/modules/fields/custom-google-maps.ts +5 -3
- package/src/js/modules/fields/custom-link.ts +5 -3
- package/src/js/modules/fields/custom-maps.ts +5 -3
- package/src/js/modules/fields/date-picker.ts +40 -4
- package/src/js/modules/fields/file-upload.ts +19 -10
- package/src/js/modules/fields/hidden.ts +5 -3
- package/src/js/modules/fields/index.ts +2 -2
- package/src/js/modules/fields/password-validation.ts +5 -3
- package/src/js/modules/fields/phone-country.ts +33 -6
- package/src/js/modules/fields/repeater.ts +5 -3
- package/src/js/modules/fields/rich-text.ts +20 -4
- package/src/js/modules/fields/shared.ts +13 -0
- package/src/js/modules/fields/signature.ts +64 -6
- package/src/js/modules/fields/summary.ts +8 -20
- package/src/js/modules/fields/survey-likert.ts +5 -3
- package/src/js/modules/fields/survey-rank.ts +21 -3
- package/src/js/modules/fields/survey-rating.ts +17 -3
- package/src/js/modules/fields/table.ts +5 -3
- package/src/js/modules/fields/text-limit.ts +5 -3
- package/src/js/modules/fields/upload-manager.ts +190 -49
- package/src/js/modules/loader.ts +345 -281
- package/src/js/modules/payments/bpoint.ts +2 -2
- package/src/js/modules/payments/eway.ts +2 -2
- package/src/js/modules/payments/factories.ts +53 -52
- package/src/js/modules/payments/go-cardless.ts +1 -1
- package/src/js/modules/payments/index.ts +2 -2
- package/src/js/modules/payments/mollie.ts +1 -1
- package/src/js/modules/payments/moneris.ts +2 -2
- package/src/js/modules/payments/opayo.ts +21 -8
- package/src/js/modules/payments/paddle.ts +10 -6
- package/src/js/modules/payments/payment.ts +22 -18
- package/src/js/modules/payments/paypal.ts +1 -1
- package/src/js/modules/payments/payway.ts +2 -2
- package/src/js/modules/payments/square.ts +2 -2
- package/src/js/modules/payments/stripe.ts +5 -5
- package/src/js/modules/payments/utils.ts +14 -0
- package/src/js/modules/registry.ts +19 -11
- package/src/js/submit/pipeline.ts +10 -11
- package/src/js/theme/browser-theme-state.generated.ts +25 -0
- package/src/js/theme/theme-classes.ts +3 -3
- package/src/js/transport/forms-api.ts +66 -67
- package/src/js/utils/country-from-ip.ts +14 -9
- package/src/js/utils/csrf.ts +136 -0
- package/src/js/utils/field-references.parser.ts +13 -113
- package/src/js/utils/field-references.resolver.ts +27 -64
- package/src/js/utils/field-references.row-scope.ts +1 -1
- package/src/js/utils/field-references.types.ts +1 -0
- package/src/js/utils/http.ts +5 -5
- package/src/js/utils/request-profile.ts +10 -0
- package/src/js/utils/unload-warning.ts +12 -4
- package/src/js/validation/rules/email.ts +3 -5
- package/src/js/validation/rules/match.ts +2 -1
- package/src/js/validation/rules/minmax.ts +4 -43
- package/src/js/validation/rules/number.ts +3 -47
- package/src/js/validation/rules/pattern.ts +3 -8
- package/src/js/validation/rules/required.ts +2 -1
- package/src/js/validation/rules/shared.ts +5 -1
- package/src/js/validation/rules/url.ts +3 -10
- package/src/js/validation/skip.ts +9 -0
- package/src/js/validation/submit-readiness.ts +9 -2
- package/src/js/validation/validator.ts +35 -59
- package/dist/chunks/calculations-DERi2xaC.js +0 -299
- package/dist/chunks/conditions-65kBcFWW.js +0 -424
- package/dist/chunks/country-from-ip-BwxKaBuJ.js +0 -26
- package/dist/chunks/field-references.resolver-CHwn0G0L.js +0 -145
- package/dist/chunks/friendly-captcha-v1-C_2reOXr.js +0 -31
- package/dist/chunks/google-address-BH3Zhi06.js +0 -161
- package/dist/chunks/http-D-JExro7.js +0 -27
- package/dist/chunks/opayo-CR0DtsLa.js +0 -179
- package/dist/chunks/rich-text-Bg_--4TG.js +0 -349
- package/dist/js/modules/fields/conditions/transforms.d.ts +0 -3
- package/dist/js/modules/fields/conditions/transforms.d.ts.map +0 -1
- package/src/js/modules/fields/conditions/transforms.ts +0 -206
- package/src/js/modules/payments/stub-payment-module.ts +0 -87
|
@@ -2,8 +2,8 @@ import flatpickr from 'flatpickr';
|
|
|
2
2
|
import * as flatpickrLocales from 'flatpickr/dist/l10n/index.js';
|
|
3
3
|
import flatpickrCss from 'flatpickr/dist/flatpickr.css?inline';
|
|
4
4
|
|
|
5
|
-
import type {
|
|
6
|
-
import { dispatchFieldEvent, getModuleFieldContainers } from '#modules/fields/shared';
|
|
5
|
+
import type { BrowserModuleDefinition } from '#contracts/modules';
|
|
6
|
+
import { bindConditionalClear, dispatchFieldEvent, getModuleFieldContainers } from '#modules/fields/shared';
|
|
7
7
|
import { ensureModuleStyles } from '#modules/styles';
|
|
8
8
|
import { createDebug } from '#utils/debug';
|
|
9
9
|
|
|
@@ -30,6 +30,8 @@ type DatePickerOptions = {
|
|
|
30
30
|
|
|
31
31
|
type FlatpickrInstanceLike = {
|
|
32
32
|
destroy: () => void;
|
|
33
|
+
selectedDates: Date[];
|
|
34
|
+
setDate: (dates: Date[], triggerChange?: boolean) => void;
|
|
33
35
|
};
|
|
34
36
|
|
|
35
37
|
type FlatpickrInput = HTMLInputElement & {
|
|
@@ -43,6 +45,7 @@ type FlatpickrChangeInstance = {
|
|
|
43
45
|
|
|
44
46
|
function attributesPlugin() {
|
|
45
47
|
return (instance: { input: HTMLInputElement; altInput?: HTMLInputElement | undefined; loadedPlugins: string[] }) => {
|
|
48
|
+
const originalAttributes = new Map<string, string>();
|
|
46
49
|
return {
|
|
47
50
|
onReady: () => {
|
|
48
51
|
if (!instance.altInput) {
|
|
@@ -60,6 +63,7 @@ function attributesPlugin() {
|
|
|
60
63
|
|
|
61
64
|
const value = instance.input.getAttribute(attribute);
|
|
62
65
|
if (value !== null) {
|
|
66
|
+
originalAttributes.set(attribute, value);
|
|
63
67
|
instance.altInput?.setAttribute(attribute, value);
|
|
64
68
|
}
|
|
65
69
|
|
|
@@ -68,6 +72,15 @@ function attributesPlugin() {
|
|
|
68
72
|
|
|
69
73
|
instance.loadedPlugins.push('formie-attributes');
|
|
70
74
|
},
|
|
75
|
+
onDestroy: () => {
|
|
76
|
+
// Conditional fields and page navigation can mount this input again.
|
|
77
|
+
// Restore the markers and labels moved onto the temporary alt input.
|
|
78
|
+
originalAttributes.forEach((value, attribute) => {
|
|
79
|
+
if (!instance.input.hasAttribute(attribute)) {
|
|
80
|
+
instance.input.setAttribute(attribute, value);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
},
|
|
71
84
|
};
|
|
72
85
|
};
|
|
73
86
|
}
|
|
@@ -285,6 +298,12 @@ function initDatePicker(input: FlatpickrInput, options: DatePickerOptions): () =
|
|
|
285
298
|
if (startDate) {
|
|
286
299
|
defaultOptions.defaultDate = endDate ? [startDate, endDate] : [startDate];
|
|
287
300
|
}
|
|
301
|
+
} else if (input.value) {
|
|
302
|
+
const defaultDate = parseSubmissionDate(input.value);
|
|
303
|
+
|
|
304
|
+
if (defaultDate) {
|
|
305
|
+
defaultOptions.defaultDate = defaultDate;
|
|
306
|
+
}
|
|
288
307
|
}
|
|
289
308
|
|
|
290
309
|
const mergedOptions = {
|
|
@@ -303,6 +322,19 @@ function initDatePicker(input: FlatpickrInput, options: DatePickerOptions): () =
|
|
|
303
322
|
|
|
304
323
|
const instance = flatpickr(input, mergedOptions) as FlatpickrInstanceLike;
|
|
305
324
|
input._formieFlatpickr = instance;
|
|
325
|
+
const initialDates = instance.selectedDates.map((date) => new Date(date.getTime()));
|
|
326
|
+
const form = input.form;
|
|
327
|
+
const onReset = (event: Event) => {
|
|
328
|
+
// Flatpickr uses hidden transport inputs, whose values survive native reset.
|
|
329
|
+
// Restore the picker and its range inputs together after the native controls.
|
|
330
|
+
queueMicrotask(() => {
|
|
331
|
+
if (!event.defaultPrevented) {
|
|
332
|
+
instance.setDate(initialDates, true);
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
};
|
|
336
|
+
form?.addEventListener('reset', onReset);
|
|
337
|
+
const unbindConditionalClear = bindConditionalClear(input, () => instance.setDate([], true));
|
|
306
338
|
debug.log('Initialized.', {
|
|
307
339
|
inputName: input.name,
|
|
308
340
|
isRange,
|
|
@@ -314,6 +346,8 @@ function initDatePicker(input: FlatpickrInput, options: DatePickerOptions): () =
|
|
|
314
346
|
});
|
|
315
347
|
|
|
316
348
|
return () => {
|
|
349
|
+
unbindConditionalClear();
|
|
350
|
+
form?.removeEventListener('reset', onReset);
|
|
317
351
|
instance.destroy();
|
|
318
352
|
delete input._formieFlatpickr;
|
|
319
353
|
debug.log('Destroyed.', {
|
|
@@ -322,8 +356,10 @@ function initDatePicker(input: FlatpickrInput, options: DatePickerOptions): () =
|
|
|
322
356
|
};
|
|
323
357
|
}
|
|
324
358
|
|
|
325
|
-
export const datePickerModule:
|
|
326
|
-
|
|
359
|
+
export const datePickerModule: BrowserModuleDefinition = {
|
|
360
|
+
moduleId: `formie:${MODULE_ID}`,
|
|
361
|
+
version: 2,
|
|
362
|
+
surfaces: ['server-rendered', 'client-rendered', 'cp-edit'],
|
|
327
363
|
kind: 'field',
|
|
328
364
|
match: (ctx) => {
|
|
329
365
|
return !!ctx.target.querySelector(INPUT_SELECTOR);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fileUploadCss from '#theme-css/fields/_file.css?inline';
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { BrowserModuleDefinition } from '#contracts/modules';
|
|
4
4
|
import { dispatchFieldEvent, releaseFormValidators, retainFormValidators } from '#modules/fields/shared';
|
|
5
5
|
import { ensureModuleStyles } from '#modules/styles';
|
|
6
6
|
import { getFieldModuleEventName, getFileUploadEventName, getFormStateEventName } from '#utils/event-names';
|
|
@@ -13,6 +13,7 @@ const FILE_UPLOAD_KEY_ATTR = 'data-formie-file-upload-key';
|
|
|
13
13
|
const HYDRATE_ENDPOINT_ATTR = 'data-formie-file-upload-hydrate-endpoint';
|
|
14
14
|
const HIDDEN_INPUT_ANCHOR_ATTR = 'data-formie-file-upload-anchor';
|
|
15
15
|
const HIDDEN_INPUT_VALUE_ATTR = 'data-formie-file-upload-asset-id';
|
|
16
|
+
const HIDDEN_INPUT_ENTRY_ATTR = 'data-formie-file-upload-entry';
|
|
16
17
|
const FILE_VALIDATORS = [
|
|
17
18
|
'fileLimit',
|
|
18
19
|
'fileSizeMinLimit',
|
|
@@ -93,7 +94,8 @@ function getUploadedAssetInputs(field: HTMLElement, input: HTMLInputElement): HT
|
|
|
93
94
|
const assetInputName = getUploadedAssetInputName(input);
|
|
94
95
|
|
|
95
96
|
return getHiddenInputs(field).filter((hiddenInput) => {
|
|
96
|
-
return hiddenInput.
|
|
97
|
+
return hiddenInput.hasAttribute(HIDDEN_INPUT_VALUE_ATTR)
|
|
98
|
+
|| (hiddenInput.name === assetInputName && hiddenInput.value.trim() !== '');
|
|
97
99
|
});
|
|
98
100
|
}
|
|
99
101
|
|
|
@@ -186,7 +188,7 @@ function readSummaryItems(summaryRoot: HTMLElement | null): UploadedAsset[] {
|
|
|
186
188
|
function readUploadedAssetsFromHiddenInputs(field: HTMLElement, input: HTMLInputElement): UploadedAsset[] {
|
|
187
189
|
return getUploadedAssetInputs(field, input).map((hiddenInput) => {
|
|
188
190
|
return {
|
|
189
|
-
assetId: toPositiveInt(hiddenInput.value),
|
|
191
|
+
assetId: toPositiveInt(hiddenInput.getAttribute(HIDDEN_INPUT_VALUE_ATTR)) ?? toPositiveInt(hiddenInput.value),
|
|
190
192
|
filename: '',
|
|
191
193
|
};
|
|
192
194
|
}).filter((asset) => {
|
|
@@ -349,21 +351,25 @@ function updateUploadedAssetInputs(field: HTMLElement, input: HTMLInputElement,
|
|
|
349
351
|
let insertionPoint: HTMLInputElement = anchor;
|
|
350
352
|
// The upload event returns persisted asset ids; convert those back into the
|
|
351
353
|
// hidden-input shape the backend expects on subsequent submit/save actions.
|
|
352
|
-
const
|
|
353
|
-
|
|
354
|
+
const baseName = getFileValueName(input);
|
|
355
|
+
getHiddenInputs(field).filter((hiddenInput) => {
|
|
356
|
+
return hiddenInput.hasAttribute(HIDDEN_INPUT_ENTRY_ATTR)
|
|
357
|
+
|| (hiddenInput.name === `${baseName}[]` && hiddenInput.value.trim() !== '');
|
|
358
|
+
}).forEach((hiddenInput) => {
|
|
354
359
|
hiddenInput.remove();
|
|
355
360
|
});
|
|
356
361
|
|
|
357
|
-
uploadedAssets.forEach((asset) => {
|
|
362
|
+
uploadedAssets.forEach((asset, index) => {
|
|
358
363
|
if (!asset.assetId) {
|
|
359
364
|
return;
|
|
360
365
|
}
|
|
361
366
|
|
|
362
367
|
const hiddenInput = document.createElement('input');
|
|
363
368
|
hiddenInput.type = 'hidden';
|
|
364
|
-
hiddenInput.name =
|
|
369
|
+
hiddenInput.name = `${baseName}[${index}][assetId]`;
|
|
365
370
|
hiddenInput.value = String(asset.assetId);
|
|
366
|
-
hiddenInput.setAttribute(
|
|
371
|
+
hiddenInput.setAttribute(HIDDEN_INPUT_ENTRY_ATTR, 'true');
|
|
372
|
+
hiddenInput.setAttribute(HIDDEN_INPUT_VALUE_ATTR, String(asset.assetId));
|
|
367
373
|
insertionPoint.insertAdjacentElement('afterend', hiddenInput);
|
|
368
374
|
insertionPoint = hiddenInput;
|
|
369
375
|
});
|
|
@@ -425,6 +431,7 @@ async function hydrateUploadedAssets(field: HTMLElement, input: HTMLInputElement
|
|
|
425
431
|
|
|
426
432
|
const hydrateEndpoint = input.getAttribute(HYDRATE_ENDPOINT_ATTR)?.trim() || '/actions/formie/file-upload/hydrate';
|
|
427
433
|
const response = await requestJson<FileUploadHydrateResponse>(hydrateEndpoint, {
|
|
434
|
+
profile: field.closest('form')?.dataset.formieRequestProfile as import('@verbb/formie-core').BrowserRequestOptions['profile'],
|
|
428
435
|
method: 'POST',
|
|
429
436
|
body: buildHydrateFormData(field, input, assetIds),
|
|
430
437
|
});
|
|
@@ -657,8 +664,10 @@ function bindFileUploadInput(field: HTMLElement, input: HTMLInputElement, form:
|
|
|
657
664
|
};
|
|
658
665
|
}
|
|
659
666
|
|
|
660
|
-
export const fileUploadModule:
|
|
661
|
-
|
|
667
|
+
export const fileUploadModule: BrowserModuleDefinition = {
|
|
668
|
+
moduleId: `formie:${MODULE_ID}`,
|
|
669
|
+
version: 2,
|
|
670
|
+
surfaces: ['server-rendered', 'client-rendered', 'cp-edit'],
|
|
662
671
|
kind: 'field',
|
|
663
672
|
match: (ctx) => {
|
|
664
673
|
return !!ctx.target.querySelector(INPUT_SELECTOR);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BrowserModuleDefinition } from '#contracts/modules';
|
|
2
2
|
import { getModuleFieldContainers } from '#modules/fields/shared';
|
|
3
3
|
|
|
4
4
|
const INPUT_SELECTOR = 'input[data-formie-hidden-input]';
|
|
@@ -22,8 +22,10 @@ function getCookieValue(name: string): string | null {
|
|
|
22
22
|
return null;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
export const hiddenModule:
|
|
26
|
-
|
|
25
|
+
export const hiddenModule: BrowserModuleDefinition = {
|
|
26
|
+
moduleId: 'formie:hidden',
|
|
27
|
+
version: 2,
|
|
28
|
+
surfaces: ['server-rendered', 'client-rendered', 'cp-edit'],
|
|
27
29
|
kind: 'field',
|
|
28
30
|
match: (ctx) => {
|
|
29
31
|
return !!ctx.target.querySelector(INPUT_SELECTOR);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BrowserModuleDefinition } from '#contracts/modules';
|
|
2
2
|
|
|
3
|
-
export const builtinFieldModuleLoaders: Record<string, () => Promise<
|
|
3
|
+
export const builtinFieldModuleLoaders: Record<string, () => Promise<BrowserModuleDefinition>> = {
|
|
4
4
|
// Keep the builtin map flat and explicit so manifest ids remain the source of
|
|
5
5
|
// truth for lazy-loading first-party field enhancements.
|
|
6
6
|
'calculations': () => import('#modules/fields/calculations').then((module) => module.calculationsModule),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getTextLimitMetrics } from '@verbb/formie-core';
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { BrowserModuleDefinition } from '#contracts/modules';
|
|
4
4
|
import { getModuleFieldTarget, releaseFormValidators, retainFormValidators } from '#modules/fields/shared';
|
|
5
5
|
|
|
6
6
|
const INPUT_SELECTOR = 'input[data-formie-password-input]';
|
|
@@ -104,8 +104,10 @@ function unregisterValidators(form: HTMLFormElement | null): void {
|
|
|
104
104
|
releaseFormValidators(form, VALIDATOR_SCOPE, PASSWORD_VALIDATORS);
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
export const passwordValidationModule:
|
|
108
|
-
|
|
107
|
+
export const passwordValidationModule: BrowserModuleDefinition = {
|
|
108
|
+
moduleId: 'formie:password-validation',
|
|
109
|
+
version: 2,
|
|
110
|
+
surfaces: ['server-rendered', 'client-rendered', 'cp-edit'],
|
|
109
111
|
kind: 'field',
|
|
110
112
|
match: (ctx) => {
|
|
111
113
|
return !!ctx.target.querySelector(`${INPUT_SELECTOR}[data-formie-password-min-length], ${INPUT_SELECTOR}[data-formie-password-require-uppercase], ${INPUT_SELECTOR}[data-formie-password-require-lowercase], ${INPUT_SELECTOR}[data-formie-password-require-special-character]`);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import intlTelInput from 'intl-tel-input';
|
|
2
2
|
import intlTelInputCss from 'intl-tel-input/styles?inline';
|
|
3
3
|
|
|
4
|
-
import type {
|
|
4
|
+
import type { BrowserModuleDefinition } from '#contracts/modules';
|
|
5
5
|
import { dispatchFieldEvent, getModuleFieldContainers, releaseFormValidators, retainFormValidators } from '#modules/fields/shared';
|
|
6
6
|
import { ensureModuleStyles } from '#modules/styles';
|
|
7
7
|
import { createGeoIpLookup } from '#utils/country-from-ip';
|
|
@@ -81,7 +81,7 @@ function unregisterValidators(form: HTMLFormElement | null): void {
|
|
|
81
81
|
releaseFormValidators(form, VALIDATOR_SCOPE, [PHONE_COUNTRY_VALIDATOR]);
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
function buildOptions(options: PhoneCountryOptions): Record<string, unknown> {
|
|
84
|
+
function buildOptions(options: PhoneCountryOptions, form: HTMLFormElement | null): Record<string, unknown> {
|
|
85
85
|
const intlOptions: Record<string, unknown> = {
|
|
86
86
|
allowDropdown: true,
|
|
87
87
|
nationalMode: false,
|
|
@@ -116,7 +116,7 @@ function buildOptions(options: PhoneCountryOptions): Record<string, unknown> {
|
|
|
116
116
|
intlOptions.initialCountry = options.countryDefaultValue.toLowerCase();
|
|
117
117
|
} else if (options.countryPreselectFromIp) {
|
|
118
118
|
intlOptions.initialCountry = 'auto';
|
|
119
|
-
intlOptions.geoIpLookup = createGeoIpLookup(options.countryFromIpAction);
|
|
119
|
+
intlOptions.geoIpLookup = createGeoIpLookup(options.countryFromIpAction, form);
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
if (Array.isArray(intlOptions.onlyCountries) && typeof intlOptions.initialCountry === 'string') {
|
|
@@ -130,7 +130,7 @@ function buildOptions(options: PhoneCountryOptions): Record<string, unknown> {
|
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
function initPhoneField(phoneInput: PhoneInput, countryInput: HTMLInputElement, options: PhoneCountryOptions): () => void {
|
|
133
|
-
const intlOptions = buildOptions(options);
|
|
133
|
+
const intlOptions = buildOptions(options, phoneInput.closest('form'));
|
|
134
134
|
|
|
135
135
|
dispatchFieldEvent(phoneInput, MODULE_ID, 'before-init', {
|
|
136
136
|
phoneCountry: phoneInput,
|
|
@@ -163,6 +163,30 @@ function initPhoneField(phoneInput: PhoneInput, countryInput: HTMLInputElement,
|
|
|
163
163
|
phoneInput.addEventListener('countrychange', syncCountry);
|
|
164
164
|
phoneInput.addEventListener('blur', syncCountry);
|
|
165
165
|
syncCountry();
|
|
166
|
+
|
|
167
|
+
// Keep the country dropdown button in sync when the tel input is enabled/disabled after
|
|
168
|
+
// init (multi-page page-hidden, or conditions). intl-tel-input disables the button to match
|
|
169
|
+
// a disabled input at init, but won't re-enable it when `disabled` is later removed.
|
|
170
|
+
const syncCountryButton = () => {
|
|
171
|
+
const button = phoneInput.closest('.iti')?.querySelector('.iti__selected-country');
|
|
172
|
+
|
|
173
|
+
if (!(button instanceof HTMLElement)) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (phoneInput.disabled) {
|
|
178
|
+
button.setAttribute('disabled', 'true');
|
|
179
|
+
} else {
|
|
180
|
+
button.removeAttribute('disabled');
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
syncCountryButton();
|
|
185
|
+
const countryButtonObserver = new MutationObserver(() => {
|
|
186
|
+
syncCountryButton();
|
|
187
|
+
});
|
|
188
|
+
countryButtonObserver.observe(phoneInput, { attributes: true, attributeFilter: ['disabled'] });
|
|
189
|
+
|
|
166
190
|
debug.log('Initialized.', {
|
|
167
191
|
inputName: phoneInput.name,
|
|
168
192
|
restrictedCountries: phoneInput.restrictedCountries,
|
|
@@ -177,6 +201,7 @@ function initPhoneField(phoneInput: PhoneInput, countryInput: HTMLInputElement,
|
|
|
177
201
|
return () => {
|
|
178
202
|
phoneInput.removeEventListener('countrychange', syncCountry);
|
|
179
203
|
phoneInput.removeEventListener('blur', syncCountry);
|
|
204
|
+
countryButtonObserver.disconnect();
|
|
180
205
|
validator.destroy();
|
|
181
206
|
delete phoneInput.allowedCountries;
|
|
182
207
|
delete phoneInput.validator;
|
|
@@ -188,8 +213,10 @@ function initPhoneField(phoneInput: PhoneInput, countryInput: HTMLInputElement,
|
|
|
188
213
|
};
|
|
189
214
|
}
|
|
190
215
|
|
|
191
|
-
export const phoneCountryModule:
|
|
192
|
-
|
|
216
|
+
export const phoneCountryModule: BrowserModuleDefinition = {
|
|
217
|
+
moduleId: `formie:${MODULE_ID}`,
|
|
218
|
+
version: 2,
|
|
219
|
+
surfaces: ['server-rendered', 'client-rendered', 'cp-edit'],
|
|
193
220
|
kind: 'field',
|
|
194
221
|
match: (ctx) => {
|
|
195
222
|
return !!ctx.target.querySelector(PHONE_SELECTOR);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import repeaterCss from '#theme-css/fields/_repeater.css?inline';
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { BrowserModuleDefinition } from '#contracts/modules';
|
|
4
4
|
import { dispatchFieldEvent, getTemplateSource, getTemplateSourceHtml } from '#modules/fields/shared';
|
|
5
5
|
import { ensureModuleStyles } from '#modules/styles';
|
|
6
6
|
import { sleep } from '#utils/async';
|
|
@@ -188,8 +188,10 @@ function bindRepeaterField(field: HTMLElement): () => void {
|
|
|
188
188
|
};
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
export const repeaterModule:
|
|
192
|
-
|
|
191
|
+
export const repeaterModule: BrowserModuleDefinition = {
|
|
192
|
+
moduleId: `formie:${MODULE_ID}`,
|
|
193
|
+
version: 2,
|
|
194
|
+
surfaces: ['server-rendered', 'client-rendered', 'cp-edit'],
|
|
193
195
|
kind: 'field',
|
|
194
196
|
match: (ctx) => {
|
|
195
197
|
return ctx.target instanceof HTMLElement && (
|
|
@@ -21,7 +21,7 @@ import strikethroughIcon from '#icons/rich-text/strikethrough.svg?raw';
|
|
|
21
21
|
import ulistIcon from '#icons/rich-text/ulist.svg?raw';
|
|
22
22
|
import underlineIcon from '#icons/rich-text/underline.svg?raw';
|
|
23
23
|
|
|
24
|
-
import type {
|
|
24
|
+
import type { BrowserModuleDefinition } from '#contracts/modules';
|
|
25
25
|
import { dispatchFieldEvent, getModuleFieldContainers } from '#modules/fields/shared';
|
|
26
26
|
import { ensureModuleStyles } from '#modules/styles';
|
|
27
27
|
|
|
@@ -141,7 +141,9 @@ function initRichTextField(container: HTMLElement, input: RichTextInput, options
|
|
|
141
141
|
actions: getActions(options.buttons),
|
|
142
142
|
onChange: (html: string) => {
|
|
143
143
|
const emptyParagraph = '<p><br></p>';
|
|
144
|
-
|
|
144
|
+
// Treat Pell's empty document as blank so required validation matches
|
|
145
|
+
// a never-touched textarea (and so clearing the editor can fail required).
|
|
146
|
+
input.value = (!html || html === emptyParagraph) ? '' : html;
|
|
145
147
|
// Bubble both generic input and a namespaced rich-text change hook.
|
|
146
148
|
input.dispatchEvent(new Event('input', { bubbles: true }));
|
|
147
149
|
dispatchFieldEvent(input, MODULE_ID, 'populate', {
|
|
@@ -166,6 +168,17 @@ function initRichTextField(container: HTMLElement, input: RichTextInput, options
|
|
|
166
168
|
input.richText = editor;
|
|
167
169
|
editor.content.innerHTML = input.value || '';
|
|
168
170
|
|
|
171
|
+
const form = input.form;
|
|
172
|
+
const onReset = (event: Event) => {
|
|
173
|
+
// Wait for the textarea to regain its default value before updating Pell.
|
|
174
|
+
queueMicrotask(() => {
|
|
175
|
+
if (!event.defaultPrevented) {
|
|
176
|
+
editor.content.innerHTML = input.value || '';
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
form?.addEventListener('reset', onReset);
|
|
181
|
+
|
|
169
182
|
if (input.placeholder) {
|
|
170
183
|
editor.content.setAttribute('data-placeholder', input.placeholder);
|
|
171
184
|
}
|
|
@@ -175,13 +188,16 @@ function initRichTextField(container: HTMLElement, input: RichTextInput, options
|
|
|
175
188
|
});
|
|
176
189
|
|
|
177
190
|
return () => {
|
|
191
|
+
form?.removeEventListener('reset', onReset);
|
|
178
192
|
container.innerHTML = '';
|
|
179
193
|
delete input.richText;
|
|
180
194
|
};
|
|
181
195
|
}
|
|
182
196
|
|
|
183
|
-
export const richTextModule:
|
|
184
|
-
|
|
197
|
+
export const richTextModule: BrowserModuleDefinition = {
|
|
198
|
+
moduleId: `formie:${MODULE_ID}`,
|
|
199
|
+
version: 2,
|
|
200
|
+
surfaces: ['server-rendered', 'client-rendered', 'cp-edit'],
|
|
185
201
|
kind: 'field',
|
|
186
202
|
match: (ctx) => {
|
|
187
203
|
return ctx.target instanceof HTMLElement && hasRichTextField(ctx.target);
|
|
@@ -17,6 +17,19 @@ const fallbackCssEscape = (value: string): string => {
|
|
|
17
17
|
};
|
|
18
18
|
const validatorRegistrations = new WeakMap<HTMLFormElement, Map<string, number>>();
|
|
19
19
|
|
|
20
|
+
// Conditions clear ordinary controls directly. Enhanced controls also need to
|
|
21
|
+
// clear their hidden transport values before their modules are unmounted.
|
|
22
|
+
export function bindConditionalClear(input: HTMLElement, clear: () => void): () => void {
|
|
23
|
+
const root = input.getRootNode();
|
|
24
|
+
const handler = (event: Event) => {
|
|
25
|
+
if (event.target instanceof Element && event.target.contains(input)) {
|
|
26
|
+
clear();
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
root.addEventListener('formie:field:clear', handler);
|
|
30
|
+
return () => root.removeEventListener('formie:field:clear', handler);
|
|
31
|
+
}
|
|
32
|
+
|
|
20
33
|
export function escapeSelectorValue(value: string): string {
|
|
21
34
|
if (typeof window.CSS?.escape === 'function') {
|
|
22
35
|
return window.CSS.escape(value);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import SignaturePad from 'signature_pad';
|
|
2
2
|
import signatureCss from '#theme-css/fields/_signature.css?inline';
|
|
3
3
|
|
|
4
|
-
import type {
|
|
5
|
-
import { dispatchFieldEvent, getModuleFieldContainers } from '#modules/fields/shared';
|
|
4
|
+
import type { BrowserModuleDefinition } from '#contracts/modules';
|
|
5
|
+
import { bindConditionalClear, dispatchFieldEvent, getModuleFieldContainers } from '#modules/fields/shared';
|
|
6
6
|
import { ensureModuleStyles } from '#modules/styles';
|
|
7
7
|
|
|
8
8
|
const INPUT_SELECTOR = 'input[data-formie-signature-input]';
|
|
@@ -111,11 +111,45 @@ function drawValueOnCanvas(canvas: HTMLCanvasElement, value: string): void {
|
|
|
111
111
|
};
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
function getImageDimensions(dataUrl: string): Promise<{ width: number; height: number } | null> {
|
|
115
|
+
return new Promise((resolve) => {
|
|
116
|
+
const image = new Image();
|
|
117
|
+
image.onload = () => {
|
|
118
|
+
resolve({
|
|
119
|
+
width: image.naturalWidth,
|
|
120
|
+
height: image.naturalHeight,
|
|
121
|
+
});
|
|
122
|
+
};
|
|
123
|
+
image.onerror = () => resolve(null);
|
|
124
|
+
image.src = dataUrl;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function syncCanvasHeightToSignatureValue(canvas: HTMLCanvasElement, value: string): Promise<void> {
|
|
129
|
+
const dimensions = await getImageDimensions(value);
|
|
130
|
+
|
|
131
|
+
if (!dimensions?.width || !dimensions?.height) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const { width: containerWidth } = getCanvasSize(canvas);
|
|
136
|
+
|
|
137
|
+
if (!(containerWidth > 0)) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Match the stored PNG aspect ratio so restored signatures are not vertically stretched.
|
|
142
|
+
const aspectHeight = Math.max(1, Math.round(containerWidth * (dimensions.height / dimensions.width)));
|
|
143
|
+
canvas.style.height = `${aspectHeight}px`;
|
|
144
|
+
}
|
|
145
|
+
|
|
114
146
|
async function restoreSignatureValue(signaturePad: SignaturePad, canvas: HTMLCanvasElement, value: string): Promise<void> {
|
|
115
147
|
if (!value) {
|
|
116
148
|
return;
|
|
117
149
|
}
|
|
118
150
|
|
|
151
|
+
await syncCanvasHeightToSignatureValue(canvas, value);
|
|
152
|
+
|
|
119
153
|
try {
|
|
120
154
|
await signaturePad.fromDataURL(value);
|
|
121
155
|
} catch {
|
|
@@ -131,6 +165,8 @@ function initSignatureField(
|
|
|
131
165
|
clearButton: HTMLElement | null,
|
|
132
166
|
options: SignatureOptions,
|
|
133
167
|
): () => void {
|
|
168
|
+
const initialValue = input.value;
|
|
169
|
+
const form = input.form;
|
|
134
170
|
const messages = getSignatureMessages(field);
|
|
135
171
|
|
|
136
172
|
if (!supportsCanvas()) {
|
|
@@ -184,6 +220,12 @@ function initSignatureField(
|
|
|
184
220
|
};
|
|
185
221
|
|
|
186
222
|
const resizeCanvas = async(): Promise<boolean> => {
|
|
223
|
+
const existingValue = input.value || (signaturePad.isEmpty() ? '' : signaturePad.toDataURL());
|
|
224
|
+
|
|
225
|
+
if (existingValue) {
|
|
226
|
+
await syncCanvasHeightToSignatureValue(canvas, existingValue);
|
|
227
|
+
}
|
|
228
|
+
|
|
187
229
|
const { width, height } = getCanvasSize(canvas);
|
|
188
230
|
|
|
189
231
|
if (!(width > 0) || !(height > 0)) {
|
|
@@ -196,8 +238,6 @@ function initSignatureField(
|
|
|
196
238
|
return false;
|
|
197
239
|
}
|
|
198
240
|
|
|
199
|
-
const existingValue = input.value || (signaturePad.isEmpty() ? '' : signaturePad.toDataURL());
|
|
200
|
-
|
|
201
241
|
canvas.width = width * ratio;
|
|
202
242
|
canvas.height = height * ratio;
|
|
203
243
|
context.setTransform(1, 0, 0, 1, 0, 0);
|
|
@@ -311,6 +351,20 @@ function initSignatureField(
|
|
|
311
351
|
syncInputValue('');
|
|
312
352
|
};
|
|
313
353
|
|
|
354
|
+
const onReset = (event: Event) => {
|
|
355
|
+
// Hidden inputs do not restore an earlier value through native reset.
|
|
356
|
+
// Reset both the submitted signature and the pad to their initial state.
|
|
357
|
+
queueMicrotask(() => {
|
|
358
|
+
if (!event.defaultPrevented) {
|
|
359
|
+
signaturePad.clear();
|
|
360
|
+
syncInputValue(initialValue);
|
|
361
|
+
void restoreSignatureValue(signaturePad, canvas, initialValue);
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
};
|
|
365
|
+
form?.addEventListener('reset', onReset);
|
|
366
|
+
|
|
367
|
+
const unbindConditionalClear = bindConditionalClear(input, clearSignature);
|
|
314
368
|
signaturePad.addEventListener('endStroke', syncValue);
|
|
315
369
|
window.addEventListener('resize', resizeHandler);
|
|
316
370
|
root.addEventListener('formie:page:navigate:after', pageNavigateHandler as EventListener);
|
|
@@ -327,6 +381,8 @@ function initSignatureField(
|
|
|
327
381
|
|
|
328
382
|
return () => {
|
|
329
383
|
clearSizeRetry();
|
|
384
|
+
unbindConditionalClear();
|
|
385
|
+
form?.removeEventListener('reset', onReset);
|
|
330
386
|
signaturePad.removeEventListener('endStroke', syncValue);
|
|
331
387
|
window.removeEventListener('resize', resizeHandler);
|
|
332
388
|
root.removeEventListener('formie:page:navigate:after', pageNavigateHandler as EventListener);
|
|
@@ -340,8 +396,10 @@ function initSignatureField(
|
|
|
340
396
|
};
|
|
341
397
|
}
|
|
342
398
|
|
|
343
|
-
export const signatureModule:
|
|
344
|
-
|
|
399
|
+
export const signatureModule: BrowserModuleDefinition = {
|
|
400
|
+
moduleId: `formie:${MODULE_ID}`,
|
|
401
|
+
version: 2,
|
|
402
|
+
surfaces: ['server-rendered', 'client-rendered', 'cp-edit'],
|
|
345
403
|
kind: 'field',
|
|
346
404
|
match: (ctx) => {
|
|
347
405
|
return !!ctx.target.querySelector(CANVAS_SELECTOR);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import summaryCss from '#theme-css/fields/_summary.css?inline';
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { BrowserModuleDefinition } from '#contracts/modules';
|
|
4
4
|
import { dispatchFieldEvent, getModuleFieldContainers } from '#modules/fields/shared';
|
|
5
5
|
import { ensureModuleStyles } from '#modules/styles';
|
|
6
6
|
import { toggleThemeClasses } from '#theme/theme-classes';
|
|
@@ -11,8 +11,6 @@ import { requestText } from '#utils/http';
|
|
|
11
11
|
const BLOCKS_SELECTOR = '[data-formie-summary-blocks]';
|
|
12
12
|
const CONTAINER_SELECTOR = '[data-formie-summary-container]';
|
|
13
13
|
const SUMMARY_ACTION = 'formie/fields/get-summary-html';
|
|
14
|
-
const THEME_CONFIG_ATTR = 'data-formie-theme-config';
|
|
15
|
-
const FRONTEND_THEME_ATTR = 'data-formie-frontend-theme';
|
|
16
14
|
const MODULE_ID = 'summary';
|
|
17
15
|
const debug = createDebug('fields', 'summary');
|
|
18
16
|
|
|
@@ -20,8 +18,6 @@ ensureModuleStyles(MODULE_ID, [summaryCss]);
|
|
|
20
18
|
|
|
21
19
|
type SummaryRequestState = {
|
|
22
20
|
accessToken: string | null;
|
|
23
|
-
themeConfig: string | null;
|
|
24
|
-
frontendTheme: string | null;
|
|
25
21
|
};
|
|
26
22
|
|
|
27
23
|
function getSummaryRequestUrl(): string {
|
|
@@ -31,14 +27,12 @@ function getSummaryRequestUrl(): string {
|
|
|
31
27
|
return url.toString();
|
|
32
28
|
}
|
|
33
29
|
|
|
34
|
-
function getSummaryRequestState(field: HTMLElement
|
|
30
|
+
function getSummaryRequestState(field: HTMLElement): SummaryRequestState {
|
|
35
31
|
const summaryTokenInput = field.querySelector('[data-formie-summary-token]') as HTMLInputElement | null;
|
|
36
32
|
const accessToken = summaryTokenInput?.value?.trim() || null;
|
|
37
33
|
|
|
38
34
|
return {
|
|
39
35
|
accessToken,
|
|
40
|
-
themeConfig: form.getAttribute(THEME_CONFIG_ATTR)?.trim() || null,
|
|
41
|
-
frontendTheme: form.getAttribute(FRONTEND_THEME_ATTR)?.trim() || null,
|
|
42
36
|
};
|
|
43
37
|
}
|
|
44
38
|
|
|
@@ -53,14 +47,6 @@ async function requestSummaryHtml(form: HTMLFormElement, state: SummaryRequestSt
|
|
|
53
47
|
formData.set('action', SUMMARY_ACTION);
|
|
54
48
|
formData.set('accessToken', state.accessToken);
|
|
55
49
|
|
|
56
|
-
if (state.themeConfig) {
|
|
57
|
-
formData.set('themeConfig', state.themeConfig);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (state.frontendTheme) {
|
|
61
|
-
formData.set('frontendTheme', state.frontendTheme);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
50
|
return requestText(getSummaryRequestUrl(), {
|
|
65
51
|
method: 'POST',
|
|
66
52
|
body: formData,
|
|
@@ -115,7 +101,7 @@ function initSummaryField(field: HTMLElement, root: Element): () => void {
|
|
|
115
101
|
toggleThemeClasses(blocks, form, 'loading', false);
|
|
116
102
|
};
|
|
117
103
|
|
|
118
|
-
const initialState = getSummaryRequestState(field
|
|
104
|
+
const initialState = getSummaryRequestState(field);
|
|
119
105
|
setLoadingState(!!initialState.accessToken);
|
|
120
106
|
|
|
121
107
|
const queueFetch = (): void => {
|
|
@@ -128,7 +114,7 @@ function initSummaryField(field: HTMLElement, root: Element): () => void {
|
|
|
128
114
|
};
|
|
129
115
|
|
|
130
116
|
const fetchSummary = debounce(async() => {
|
|
131
|
-
const state = getSummaryRequestState(field
|
|
117
|
+
const state = getSummaryRequestState(field);
|
|
132
118
|
|
|
133
119
|
if (!getBlocks() || !state.accessToken) {
|
|
134
120
|
debug.warn('Missing state for fetch.', state);
|
|
@@ -256,8 +242,10 @@ function initSummaryField(field: HTMLElement, root: Element): () => void {
|
|
|
256
242
|
};
|
|
257
243
|
}
|
|
258
244
|
|
|
259
|
-
export const summaryModule:
|
|
260
|
-
|
|
245
|
+
export const summaryModule: BrowserModuleDefinition = {
|
|
246
|
+
moduleId: `formie:${MODULE_ID}`,
|
|
247
|
+
version: 2,
|
|
248
|
+
surfaces: ['server-rendered', 'client-rendered', 'cp-edit'],
|
|
261
249
|
kind: 'field',
|
|
262
250
|
match: (ctx) => {
|
|
263
251
|
return !!ctx.target.querySelector(BLOCKS_SELECTOR);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import surveyPresentationsCss from '#theme-css/fields/_survey-presentations.css?inline';
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { BrowserModuleDefinition } from '#contracts/modules';
|
|
4
4
|
import { ensureModuleStyles } from '#modules/styles';
|
|
5
5
|
import { createDebug } from '#utils/debug';
|
|
6
6
|
|
|
@@ -10,8 +10,10 @@ const debug = createDebug('fields', 'survey-likert');
|
|
|
10
10
|
|
|
11
11
|
ensureModuleStyles(MODULE_ID, [surveyPresentationsCss]);
|
|
12
12
|
|
|
13
|
-
export const surveyLikertModule:
|
|
14
|
-
|
|
13
|
+
export const surveyLikertModule: BrowserModuleDefinition = {
|
|
14
|
+
moduleId: `formie:${MODULE_ID}`,
|
|
15
|
+
version: 2,
|
|
16
|
+
surfaces: ['server-rendered', 'client-rendered', 'cp-edit'],
|
|
15
17
|
kind: 'field',
|
|
16
18
|
match: (ctx) => {
|
|
17
19
|
return ctx.target instanceof HTMLElement && (
|