@verbb/formie-browser 1.0.13 → 1.0.15
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 +80 -0
- package/dist/chunks/{address-country-Rx6GQTND.js → address-country-BcEQKw0T.js} +11 -5
- package/dist/chunks/{address-finder-k7_BXaRe.js → address-finder-BWGINCSA.js} +3 -3
- package/dist/chunks/address-state-DI3ndhMU.js +365 -0
- package/dist/chunks/{api-BUb6P-xu.js → api-BK9b340y.js} +93 -63
- package/dist/chunks/{api-DqpfkZWL.js → api-Dxl_CKw-.js} +202 -193
- package/dist/chunks/{api-sPqGbOww.js → api-ghNr2uxX.js} +15 -9
- package/dist/chunks/{async-nPFRNQ06.js → async-2GdXNFCE.js} +18 -1
- package/dist/chunks/{bpoint-Dlq34XH1.js → bpoint-BwtuyN_O.js} +3 -3
- package/dist/chunks/calculations-YEoVCG2q.js +310 -0
- package/dist/chunks/{captcha-eu-CGm8Lbrj.js → captcha-eu-DWLoQFKB.js} +6 -5
- package/dist/chunks/{checkbox-radio-BY2aTCOG.js → checkbox-radio-gsm8QPJg.js} +74 -75
- package/dist/chunks/{combobox-C0EuExSI.js → combobox-Ba08_cHL.js} +340 -328
- package/dist/chunks/conditions-Ceeg6ReZ.js +467 -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-F9BUBDSW.js → date-picker-DaPvMrop.js} +467 -443
- package/dist/chunks/{dist-D6i-VNgM.js → dist-ZLeW0zZ3.js} +1281 -453
- package/dist/chunks/{eway-D9_m8ooj.js → eway-uw0DzU-L.js} +5 -5
- package/dist/chunks/field-references.resolver-Ca8MguFv.js +104 -0
- package/dist/chunks/{file-upload-rqfZNqlH.js → file-upload-B8_mH012.js} +119 -99
- package/dist/chunks/friendly-captcha-v1-CVXaXgDO.js +34 -0
- package/dist/chunks/{friendly-captcha-v2-CLSAbkqx.js → friendly-captcha-v2-DkeIVTKI.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-c4wLJdOt.js} +2 -2
- package/dist/chunks/google-address-JHYvjwgN.js +168 -0
- package/dist/chunks/{hcaptcha-CGLAmgjO.js → hcaptcha-Dt3ELLlP.js} +4 -4
- 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-m51iPyO1.js} +3 -3
- package/dist/chunks/{mollie-Bibhl67p.js → mollie-Bn0PX173.js} +2 -2
- package/dist/chunks/{moneris-H2wSqk9h.js → moneris-BRbUvI4t.js} +3 -3
- package/dist/chunks/opayo-BwWdInEP.js +188 -0
- package/dist/chunks/{paddle-DkvIxQdG.js → paddle-CympHVvd.js} +4 -4
- package/dist/chunks/{password-validation-D06uH9va.js → password-validation-C8_uO_c_.js} +18 -12
- package/dist/chunks/{paypal-CQpAF7Ua.js → paypal-h75h6wae.js} +8 -6
- package/dist/chunks/{payway-CwDkC7YZ.js → payway-C9rHTCC_.js} +4 -4
- package/dist/chunks/{phone-country-D3ayr60L.js → phone-country-B8fv-L5_.js} +80 -63
- package/dist/chunks/{place-kit-BGHklIZ-.js → place-kit-BnZGQ-L1.js} +11 -11
- 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-CUs8BO6V.js} +4 -4
- package/dist/chunks/{recaptcha-shared-CLYJvojk.js → recaptcha-shared-DTbTw-MF.js} +2 -2
- package/dist/chunks/{recaptcha-v2-checkbox-Cy-0PEPc.js → recaptcha-v2-checkbox-P1McW4Pv.js} +4 -4
- package/dist/chunks/{recaptcha-v2-invisible-BwRH540O.js → recaptcha-v2-invisible-FGDqozSP.js} +4 -4
- package/dist/chunks/{recaptcha-v3-No4Ykrhk.js → recaptcha-v3-CflUHeZD.js} +4 -4
- package/dist/chunks/{repeater-BVnPUqTj.js → repeater-CyhDbozO.js} +60 -40
- 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/{scripts-CbQ7agX3.js → scripts-DrccjrFv.js} +1 -1
- 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-IOhuicje.js → signature-7cldFbqj.js} +138 -112
- package/dist/chunks/skip-CEW89ExY.js +7 -0
- package/dist/chunks/{snaptcha-DKx98oon.js → snaptcha-C3QLYxFT.js} +2 -2
- package/dist/chunks/{square-DwdcOI1G.js → square-C1z5DPVw.js} +9 -7
- package/dist/chunks/{stripe-DaoG2FT1.js → stripe-Dmkdkq1y.js} +11 -12
- package/dist/chunks/{summary-Dks0gXS3.js → summary-Bn-g5SDx.js} +48 -46
- 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-j7MlLLCc.js} +22 -16
- package/dist/chunks/{text-limit-BGaY0jhI.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-ptihQfLl.js} +4 -4
- package/dist/chunks/{upload-manager-W-QDgxKD.js → upload-manager-BW7l-BhF.js} +459 -387
- 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/forms/_form.css +5 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1779 -1415
- 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 +3 -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 +12 -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/async.d.ts +1 -0
- package/dist/js/utils/async.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/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 +132 -86
- 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 +51 -45
- package/src/js/core/submit-result-ui.ts +25 -68
- 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 +102 -40
- 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 +14 -8
- 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 +11 -9
- package/src/js/modules/fields/address-state.ts +94 -35
- 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 +28 -9
- package/src/js/modules/fields/conditions/config.ts +17 -20
- package/src/js/modules/fields/conditions/effects.ts +25 -29
- 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 +65 -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 -7
- package/src/js/modules/fields/file-upload.ts +62 -23
- 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 +35 -8
- package/src/js/modules/fields/repeater.ts +60 -7
- 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 +24 -4
- 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 +244 -67
- 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/async.ts +34 -0
- 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 +14 -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 +49 -61
- package/dist/chunks/address-state-BwE01m2_.js +0 -344
- package/dist/chunks/calculations-Dv3hYb8_.js +0 -299
- package/dist/chunks/conditions-CPH1snCx.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
|
@@ -1,14 +1,13 @@
|
|
|
1
|
+
import { getThemeClasses } from '#theme/theme-classes';
|
|
2
|
+
|
|
1
3
|
const CONDITION_DISABLED_ATTR = 'data-formie-conditions-disabled';
|
|
2
4
|
const PRESERVED_DISABLED_ATTR = 'data-formie-preserve-disabled';
|
|
3
5
|
const CONDITIONAL_HIDDEN_ATTR = 'data-formie-conditionally-hidden';
|
|
4
6
|
const PAGE_HIDDEN_ATTR = 'data-formie-page-hidden';
|
|
5
|
-
const CONDITIONAL_HIDDEN_CLASS = 'formie-conditionally-hidden';
|
|
6
7
|
const CP_MUTED_CLASS = 'fui-cp-muted-conditional-field';
|
|
7
8
|
const CP_MUTED_EXPANDED_CLASS = 'fui-cp-muted-conditional-field--expanded';
|
|
8
9
|
const CP_MUTED_ATTR = 'data-formie-cp-muted';
|
|
9
|
-
const PAGE_HIDDEN_CLASS = 'formie-page-hidden';
|
|
10
10
|
const ROW_HIDDEN_ATTR = 'data-formie-row-hidden';
|
|
11
|
-
const ROW_HIDDEN_CLASS = 'formie-row-hidden';
|
|
12
11
|
const FIELD_COUNT_ATTR = 'data-formie-field-count';
|
|
13
12
|
const ROW_SELECTOR = '[data-formie-row], [data-formie-subfield-row], [data-formie-nested-field-row]';
|
|
14
13
|
const FIELD_SELECTOR = ':scope > [data-formie-field]';
|
|
@@ -35,7 +34,7 @@ function clearConditionNodeValues(node: Element): void {
|
|
|
35
34
|
option.selected = false;
|
|
36
35
|
});
|
|
37
36
|
} else {
|
|
38
|
-
element.selectedIndex =
|
|
37
|
+
element.selectedIndex = -1;
|
|
39
38
|
}
|
|
40
39
|
}
|
|
41
40
|
|
|
@@ -43,12 +42,15 @@ function clearConditionNodeValues(node: Element): void {
|
|
|
43
42
|
element.value = '';
|
|
44
43
|
}
|
|
45
44
|
});
|
|
45
|
+
|
|
46
|
+
node.dispatchEvent(new CustomEvent('formie:field:clear', { bubbles: true }));
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
function setVisibilityState(node: Element, hidden: boolean): boolean {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const
|
|
50
|
+
// Navigation owns page-hidden. A matching condition must not reveal an
|
|
51
|
+
// inactive page, or clear its values just because the visitor moved on.
|
|
52
|
+
const hiddenAttr = CONDITIONAL_HIDDEN_ATTR;
|
|
53
|
+
const hiddenClasses = getThemeClasses(node, 'conditionalHidden');
|
|
52
54
|
const wasHidden = node.hasAttribute(hiddenAttr);
|
|
53
55
|
|
|
54
56
|
if (hidden) {
|
|
@@ -56,17 +58,13 @@ function setVisibilityState(node: Element, hidden: boolean): boolean {
|
|
|
56
58
|
node.setAttribute(hiddenAttr, 'true');
|
|
57
59
|
}
|
|
58
60
|
|
|
59
|
-
|
|
60
|
-
node.classList.add(hiddenClass);
|
|
61
|
-
}
|
|
61
|
+
node.classList.add(...hiddenClasses);
|
|
62
62
|
} else {
|
|
63
63
|
if (wasHidden) {
|
|
64
64
|
node.removeAttribute(hiddenAttr);
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
node.classList.remove(hiddenClass);
|
|
69
|
-
}
|
|
67
|
+
node.classList.remove(...hiddenClasses);
|
|
70
68
|
}
|
|
71
69
|
|
|
72
70
|
return wasHidden !== hidden;
|
|
@@ -152,6 +150,7 @@ function isFieldVisible(field: Element): boolean {
|
|
|
152
150
|
}
|
|
153
151
|
|
|
154
152
|
function syncRowState(row: Element): void {
|
|
153
|
+
const hiddenClasses = getThemeClasses(row, 'rowHidden');
|
|
155
154
|
const directFields = Array.from(row.querySelectorAll(FIELD_SELECTOR));
|
|
156
155
|
const visibleFieldCount = directFields.filter((field) => {
|
|
157
156
|
return isFieldVisible(field);
|
|
@@ -168,9 +167,7 @@ function syncRowState(row: Element): void {
|
|
|
168
167
|
row.removeAttribute(ROW_HIDDEN_ATTR);
|
|
169
168
|
}
|
|
170
169
|
|
|
171
|
-
|
|
172
|
-
row.classList.remove(ROW_HIDDEN_CLASS);
|
|
173
|
-
}
|
|
170
|
+
row.classList.remove(...hiddenClasses);
|
|
174
171
|
|
|
175
172
|
return;
|
|
176
173
|
}
|
|
@@ -183,9 +180,7 @@ function syncRowState(row: Element): void {
|
|
|
183
180
|
row.setAttribute(ROW_HIDDEN_ATTR, 'true');
|
|
184
181
|
}
|
|
185
182
|
|
|
186
|
-
|
|
187
|
-
row.classList.add(ROW_HIDDEN_CLASS);
|
|
188
|
-
}
|
|
183
|
+
row.classList.add(...hiddenClasses);
|
|
189
184
|
}
|
|
190
185
|
|
|
191
186
|
function clearCpMutedState(node: Element): void {
|
|
@@ -196,9 +191,7 @@ function clearCpMutedState(node: Element): void {
|
|
|
196
191
|
|
|
197
192
|
function clearHideState(node: Element): void {
|
|
198
193
|
node.removeAttribute(CONDITIONAL_HIDDEN_ATTR);
|
|
199
|
-
node.
|
|
200
|
-
node.classList.remove(CONDITIONAL_HIDDEN_CLASS);
|
|
201
|
-
node.classList.remove(PAGE_HIDDEN_CLASS);
|
|
194
|
+
node.classList.remove(...getThemeClasses(node, 'conditionalHidden'));
|
|
202
195
|
}
|
|
203
196
|
|
|
204
197
|
function syncAncestorRows(node: Element): void {
|
|
@@ -214,8 +207,15 @@ export function applyConditionVisibility(
|
|
|
214
207
|
node: Element,
|
|
215
208
|
hidden: boolean,
|
|
216
209
|
clearOnHide: boolean,
|
|
217
|
-
options: { displayMode?: 'hide' | 'muted' } = {},
|
|
210
|
+
options: { displayMode?: 'hide' | 'muted'; disabledOnly?: boolean } = {},
|
|
218
211
|
): boolean {
|
|
212
|
+
if (options.disabledOnly) {
|
|
213
|
+
const changed = node.hasAttribute('data-formie-conditionally-disabled') !== hidden;
|
|
214
|
+
node.toggleAttribute('data-formie-conditionally-disabled', hidden);
|
|
215
|
+
syncDisabledState(node, hidden);
|
|
216
|
+
if (hidden && clearOnHide && changed) clearConditionNodeValues(node);
|
|
217
|
+
return changed;
|
|
218
|
+
}
|
|
219
219
|
if (options.displayMode === 'muted') {
|
|
220
220
|
return applyMutedConditionVisibility(node, hidden);
|
|
221
221
|
}
|
|
@@ -246,9 +246,7 @@ function applyMutedConditionVisibility(node: Element, hidden: boolean): boolean
|
|
|
246
246
|
|
|
247
247
|
if (hidden) {
|
|
248
248
|
if (node.hasAttribute(CONDITIONAL_HIDDEN_ATTR)
|
|
249
|
-
|| node.hasAttribute(PAGE_HIDDEN_ATTR)
|
|
250
|
-
|| node.classList.contains(CONDITIONAL_HIDDEN_CLASS)
|
|
251
|
-
|| node.classList.contains(PAGE_HIDDEN_CLASS)) {
|
|
249
|
+
|| node.hasAttribute(PAGE_HIDDEN_ATTR)) {
|
|
252
250
|
clearHideState(node);
|
|
253
251
|
stateChanged = true;
|
|
254
252
|
}
|
|
@@ -271,9 +269,7 @@ function applyMutedConditionVisibility(node: Element, hidden: boolean): boolean
|
|
|
271
269
|
}
|
|
272
270
|
|
|
273
271
|
if (node.hasAttribute(CONDITIONAL_HIDDEN_ATTR)
|
|
274
|
-
|| node.hasAttribute(PAGE_HIDDEN_ATTR)
|
|
275
|
-
|| node.classList.contains(CONDITIONAL_HIDDEN_CLASS)
|
|
276
|
-
|| node.classList.contains(PAGE_HIDDEN_CLASS)) {
|
|
272
|
+
|| node.hasAttribute(PAGE_HIDDEN_ATTR)) {
|
|
277
273
|
clearHideState(node);
|
|
278
274
|
stateChanged = true;
|
|
279
275
|
}
|
|
@@ -1,43 +1,35 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { evaluateCondition, finalizeConditionEvaluation } from '@verbb/formie-core';
|
|
2
2
|
|
|
3
|
-
import type { ConditionDefinition, ParsedConditionSettings
|
|
3
|
+
import type { ConditionDefinition, ParsedConditionSettings } from '#modules/fields/conditions/types';
|
|
4
4
|
import { resolveConditionSource } from '#modules/fields/conditions/references';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
function isInputVisible(input: ConditionInput): boolean {
|
|
8
|
-
if (
|
|
9
|
-
input.closest('[data-formie-conditionally-hidden]')
|
|
10
|
-
|| input.closest('[data-formie-page-hidden]')
|
|
11
|
-
|| input.closest('[hidden]')
|
|
12
|
-
|| input.closest('[aria-hidden="true"]')
|
|
13
|
-
) {
|
|
14
|
-
return false;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return !!(input.offsetWidth || input.offsetHeight || input.getClientRects().length);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function getConditionVisibility(inputs: ConditionInput[]): boolean | null {
|
|
21
|
-
if (!inputs.length) {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return inputs.some((input) => {
|
|
26
|
-
return isInputVisible(input);
|
|
27
|
-
});
|
|
28
|
-
}
|
|
5
|
+
import { readSubmissionConditionValues } from '#modules/fields/conditions/submission-context';
|
|
6
|
+
import { readConditionValues, readConditionProjection } from '#modules/fields/conditions/values';
|
|
29
7
|
|
|
30
8
|
export function evaluateConditionSettings(
|
|
31
9
|
settings: ParsedConditionSettings,
|
|
32
10
|
getConditionInputs: (condition: ConditionDefinition) => Array<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>,
|
|
11
|
+
options: {
|
|
12
|
+
root?: Element;
|
|
13
|
+
from?: Element;
|
|
14
|
+
} = {},
|
|
33
15
|
): { finalResult: boolean; shouldHide: boolean } {
|
|
16
|
+
const root = options.root;
|
|
17
|
+
const from = options.from || root;
|
|
18
|
+
|
|
34
19
|
const groupedResults = settings.conditions.map((condition) => {
|
|
35
20
|
const inputs = getConditionInputs(condition);
|
|
36
21
|
const source = resolveConditionSource(condition);
|
|
37
22
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
23
|
+
// `{submission:*}` is not a DOM field — read the snapshot emitted on the form.
|
|
24
|
+
const actualValues = source?.target === 'submission' && root && from
|
|
25
|
+
? readSubmissionConditionValues(root, source, from)
|
|
26
|
+
: readConditionValues(inputs, source);
|
|
27
|
+
|
|
28
|
+
if (condition.browserSafe === false || Boolean(source?.transformerId) || source?.isValid === false || (!inputs.length && source?.target !== 'submission')) return { value: null, diagnostics: [{ code: 'unresolvedReference' }] };
|
|
29
|
+
const type = condition.valueType ?? (actualValues.length > 1 ? 'collection' : 'text');
|
|
30
|
+
const value = source?.target === 'submission' ? (type === 'collection' ? actualValues : actualValues[0] ?? null) : readConditionProjection(inputs, source, type, Number(from?.querySelector('input,select,textarea')?.getAttribute('name')?.match(/\[([0-9]+)\]/)?.[1]));
|
|
31
|
+
if (value && typeof value === 'object' && 'conditionDiagnostic' in value) return { value: null, diagnostics: [{ code: String(value.conditionDiagnostic) }] };
|
|
32
|
+
return evaluateCondition(condition.condition, value, condition.value, type);
|
|
41
33
|
});
|
|
42
34
|
|
|
43
35
|
return finalizeConditionEvaluation(settings, groupedResults);
|
|
@@ -33,7 +33,8 @@ function getRowScope(node: Element): Element | null {
|
|
|
33
33
|
|
|
34
34
|
function getFieldInputs(fieldNode: Element): ConditionInput[] {
|
|
35
35
|
return Array.from(fieldNode.querySelectorAll(CONDITION_INPUT_SELECTOR)).filter((element): element is ConditionInput => {
|
|
36
|
-
|
|
36
|
+
// Enhanced controls add unnamed search/display inputs that are not field values.
|
|
37
|
+
return isConditionInput(element) && Boolean(element.name);
|
|
37
38
|
});
|
|
38
39
|
}
|
|
39
40
|
|
|
@@ -93,7 +94,12 @@ function preferSameRow<TElement extends Element>(targetNode: Element, candidates
|
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
export function resolveConditionSource(condition: ConditionDefinition): ConditionSource | null {
|
|
96
|
-
if (condition.source?.target
|
|
97
|
+
if (!condition.source?.target || !condition.source.handle) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Field inputs + submission snapshot keys both use `source.handle`.
|
|
102
|
+
if (condition.source.target === 'field' || condition.source.target === 'submission') {
|
|
97
103
|
return condition.source;
|
|
98
104
|
}
|
|
99
105
|
|
|
@@ -112,10 +118,11 @@ export function queryConditionInputs(
|
|
|
112
118
|
}
|
|
113
119
|
|
|
114
120
|
const escapedFieldHandle = escapeSelectorValue(source.handle);
|
|
121
|
+
const explicitScope = Boolean(source.transformerParams.scope);
|
|
115
122
|
const fieldMatches = Array.from(root.querySelectorAll(`[data-formie-field-handle="${escapedFieldHandle}"]`));
|
|
116
123
|
|
|
117
124
|
if (fieldMatches.length) {
|
|
118
|
-
return preferSameRow(targetNode, fieldMatches).flatMap((fieldNode) => {
|
|
125
|
+
return (explicitScope ? fieldMatches : preferSameRow(targetNode, fieldMatches)).flatMap((fieldNode) => {
|
|
119
126
|
return filterInputsBySelector(getFieldInputs(fieldNode), source.selector);
|
|
120
127
|
});
|
|
121
128
|
}
|
|
@@ -130,7 +137,7 @@ export function queryConditionInputs(
|
|
|
130
137
|
});
|
|
131
138
|
|
|
132
139
|
if (direct.length || multi.length) {
|
|
133
|
-
return preferSameRow(targetNode, [...direct, ...multi]);
|
|
140
|
+
return explicitScope ? [...direct, ...multi] : preferSameRow(targetNode, [...direct, ...multi]);
|
|
134
141
|
}
|
|
135
142
|
|
|
136
143
|
if (!source.handle.includes('__ROW__')) {
|
|
@@ -139,7 +146,7 @@ export function queryConditionInputs(
|
|
|
139
146
|
|
|
140
147
|
const rowToken = getNodeRowToken(targetNode);
|
|
141
148
|
|
|
142
|
-
if (rowToken) {
|
|
149
|
+
if (rowToken && !explicitScope) {
|
|
143
150
|
const rowFieldName = fieldKeyToInputName(source.handle.replace(/__ROW__/g, rowToken));
|
|
144
151
|
const escapedRowFieldName = escapeSelectorValue(rowFieldName);
|
|
145
152
|
const rowDirect = Array.from(root.querySelectorAll(`[name="${escapedRowFieldName}"]`)).filter((element): element is ConditionInput => {
|
|
@@ -154,6 +161,10 @@ export function queryConditionInputs(
|
|
|
154
161
|
}
|
|
155
162
|
}
|
|
156
163
|
|
|
164
|
+
if (!explicitScope) {
|
|
165
|
+
return [];
|
|
166
|
+
}
|
|
167
|
+
|
|
157
168
|
const regexString = fieldKeyToInputName(source.handle)
|
|
158
169
|
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
159
170
|
.replace(/__ROW__/g, '\\d+');
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { ConditionSource } from '#modules/fields/conditions/types';
|
|
2
|
+
|
|
3
|
+
export const SUBMISSION_CONTEXT_ATTR = 'data-formie-submission';
|
|
4
|
+
export const SUBMISSION_CONTEXT_CHANGE_EVENT = 'formie:submission-context-change';
|
|
5
|
+
|
|
6
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
7
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Find the nearest form/host that carries the submission condition snapshot.
|
|
12
|
+
* Prefer ancestors of `from` (the conditioned node), then fall back to `root`.
|
|
13
|
+
*/
|
|
14
|
+
export function findSubmissionContextHost(root: Element, from: Element = root): Element | null {
|
|
15
|
+
const closest = from.closest(`[${SUBMISSION_CONTEXT_ATTR}]`);
|
|
16
|
+
|
|
17
|
+
if (closest) {
|
|
18
|
+
return closest;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (root instanceof Element && root.hasAttribute(SUBMISSION_CONTEXT_ATTR)) {
|
|
22
|
+
return root;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return root.querySelector(`[${SUBMISSION_CONTEXT_ATTR}]`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function readSubmissionContext(root: Element, from: Element = root): Record<string, string> {
|
|
29
|
+
const host = findSubmissionContextHost(root, from);
|
|
30
|
+
const raw = host?.getAttribute(SUBMISSION_CONTEXT_ATTR);
|
|
31
|
+
|
|
32
|
+
if (!raw) {
|
|
33
|
+
return {};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
const parsed = JSON.parse(raw) as unknown;
|
|
38
|
+
|
|
39
|
+
if (!isRecord(parsed)) {
|
|
40
|
+
return {};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return Object.fromEntries(Object.entries(parsed).map(([key, value]) => {
|
|
44
|
+
return [key, value == null ? '' : String(value)];
|
|
45
|
+
}));
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error('[formie] Invalid submission context JSON.', error);
|
|
48
|
+
return {};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Resolve `{submission:status}` (etc.) from the emitted snapshot.
|
|
54
|
+
* Handle is the property key from PHP (`status`, `title`, `formName`, …).
|
|
55
|
+
*/
|
|
56
|
+
export function readSubmissionConditionValues(
|
|
57
|
+
root: Element,
|
|
58
|
+
source: ConditionSource,
|
|
59
|
+
from: Element = root,
|
|
60
|
+
): string[] {
|
|
61
|
+
const context = readSubmissionContext(root, from);
|
|
62
|
+
const key = String(source.handle || '').trim();
|
|
63
|
+
let value = '';
|
|
64
|
+
|
|
65
|
+
if (key !== '') {
|
|
66
|
+
if (Object.prototype.hasOwnProperty.call(context, key)) {
|
|
67
|
+
value = context[key] ?? '';
|
|
68
|
+
} else {
|
|
69
|
+
// Variables map uses camelCase (`submissionStatus`); tolerate that alias.
|
|
70
|
+
const aliased = `submission${key.charAt(0).toUpperCase()}${key.slice(1)}`;
|
|
71
|
+
value = context[aliased] ?? '';
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (value === '' && source.defaultValue) {
|
|
76
|
+
value = source.defaultValue;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return [value];
|
|
80
|
+
}
|
|
@@ -15,11 +15,13 @@ export type ConditionDefinition = {
|
|
|
15
15
|
field: string;
|
|
16
16
|
source?: ConditionSource | null;
|
|
17
17
|
condition: string;
|
|
18
|
+
valueType?: import('@verbb/formie-core').ConditionValueType;
|
|
19
|
+
browserSafe?: boolean;
|
|
18
20
|
value?: unknown;
|
|
19
21
|
};
|
|
20
22
|
|
|
21
23
|
export type ParsedConditionSettings = {
|
|
22
|
-
showRule: 'show' | 'hide';
|
|
24
|
+
showRule: 'show' | 'hide' | 'enable' | 'disable';
|
|
23
25
|
conditionRule: 'all' | 'any';
|
|
24
26
|
clearOnHide: boolean;
|
|
25
27
|
isNested: boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { selectConditionRows } from '@verbb/formie-core';
|
|
2
2
|
import type { ConditionInput, ConditionSource } from '#modules/fields/conditions/types';
|
|
3
3
|
|
|
4
4
|
function getInputKey(input: ConditionInput, index: number): string {
|
|
@@ -105,11 +105,36 @@ export function readConditionValues(inputs: ConditionInput[], source: ConditionS
|
|
|
105
105
|
return readInputGroupValues(group, source?.selector || '');
|
|
106
106
|
});
|
|
107
107
|
|
|
108
|
-
return
|
|
108
|
+
return (rawValues.length === 0 || rawValues.every((value) => value === '')) && source?.defaultValue ? [source.defaultValue] : rawValues;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
// DOM controls adapt to the same normalized condition projection as client-rendered values.
|
|
112
|
+
export function readConditionProjection(inputs: ConditionInput[], source: ConditionSource | null, type: import('@verbb/formie-core').ConditionValueType, currentRow?: number): unknown {
|
|
113
|
+
if (source?.transformerParams.scope) {
|
|
114
|
+
const grouped = new Map<string, ConditionInput[]>();
|
|
115
|
+
for (const input of inputs) {
|
|
116
|
+
const row = input.name.match(/\[([0-9]+)\]/)?.[1];
|
|
117
|
+
if (row != null) grouped.set(row, [...(grouped.get(row) ?? []), input]);
|
|
118
|
+
}
|
|
119
|
+
const rows = [...grouped.values()].map((group) => readConditionProjection(group, { ...source, transformerParams: {} }, type === 'collection' ? (group.length > 1 ? 'collection' : 'text') : type));
|
|
120
|
+
const selected = selectConditionRows(rows, source.transformerParams, currentRow);
|
|
121
|
+
if (selected.diagnostic) return { conditionDiagnostic: selected.diagnostic };
|
|
122
|
+
return source.transformerParams.scope === 'rows' && !Array.isArray(selected.value) ? [selected.value] : selected.value;
|
|
123
|
+
}
|
|
124
|
+
if (type === 'boolean') {
|
|
125
|
+
const checkbox = inputs.find((input) => input instanceof HTMLInputElement && input.type === 'checkbox') as HTMLInputElement | undefined;
|
|
126
|
+
if (checkbox) return checkbox.checked;
|
|
127
|
+
}
|
|
128
|
+
if (['date', 'time', 'datetime'].includes(type)) {
|
|
129
|
+
const parts: Record<string, string> = {};
|
|
130
|
+
for (const input of inputs) {
|
|
131
|
+
const key = input.name.match(/\[(year|month|day|hour|minute|second|ampm|timezone)\]$/)?.[1];
|
|
132
|
+
if (key && input.value !== '') parts[key] = input.value;
|
|
133
|
+
}
|
|
134
|
+
if (Object.keys(parts).length) return parts;
|
|
135
|
+
}
|
|
136
|
+
const values = readConditionValues(inputs, source);
|
|
137
|
+
// Empty hidden companions let unchecked groups post a value, but are not
|
|
138
|
+
// selected answers in the server's normalized collection.
|
|
139
|
+
return type === 'collection' ? values.filter((value) => value !== '') : values[0] ?? null;
|
|
115
140
|
}
|
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BrowserModuleDefinition } from '#contracts/modules';
|
|
2
2
|
import { CONDITION_SELECTOR, getConditionNodes, parseConditionSettings } from '#modules/fields/conditions/config';
|
|
3
3
|
import { applyConditionVisibility } from '#modules/fields/conditions/effects';
|
|
4
4
|
import { evaluateConditionSettings } from '#modules/fields/conditions/evaluator';
|
|
5
5
|
import { queryConditionInputs } from '#modules/fields/conditions/references';
|
|
6
|
+
import {
|
|
7
|
+
SUBMISSION_CONTEXT_ATTR,
|
|
8
|
+
SUBMISSION_CONTEXT_CHANGE_EVENT,
|
|
9
|
+
} from '#modules/fields/conditions/submission-context';
|
|
6
10
|
import type { ConditionEntry, ConditionInput } from '#modules/fields/conditions/types';
|
|
7
11
|
import { getConditionInputEventNames } from '#modules/fields/conditions/values';
|
|
8
12
|
import { createDebug } from '#utils/debug';
|
|
13
|
+
import { getFormStateEventName } from '#utils/event-names';
|
|
9
14
|
|
|
10
|
-
const MAX_EVALUATION_PASSES = 4;
|
|
11
15
|
const debug = createDebug('conditions');
|
|
12
16
|
|
|
13
17
|
function uniqueConditionInputs(inputs: ConditionInput[]): ConditionInput[] {
|
|
@@ -23,9 +27,11 @@ function uniqueConditionInputs(inputs: ConditionInput[]): ConditionInput[] {
|
|
|
23
27
|
});
|
|
24
28
|
}
|
|
25
29
|
|
|
26
|
-
export const conditionsModule:
|
|
27
|
-
|
|
28
|
-
|
|
30
|
+
export const conditionsModule: BrowserModuleDefinition = {
|
|
31
|
+
moduleId: 'formie:conditions',
|
|
32
|
+
version: 2,
|
|
33
|
+
surfaces: ['server-rendered', 'client-rendered', 'cp-edit'],
|
|
34
|
+
kind: 'core',
|
|
29
35
|
match: (ctx) => {
|
|
30
36
|
return ctx.target instanceof HTMLElement && (
|
|
31
37
|
ctx.target.matches(CONDITION_SELECTOR) ||
|
|
@@ -42,6 +48,7 @@ export const conditionsModule: FormieModuleDefinition = {
|
|
|
42
48
|
|
|
43
49
|
const sourceUnbinds: Array<() => void> = [];
|
|
44
50
|
let entries: ConditionEntry[] = [];
|
|
51
|
+
let cycles = new Set<Element>();
|
|
45
52
|
let evaluationQueued = false;
|
|
46
53
|
let rebuildQueued = false;
|
|
47
54
|
|
|
@@ -56,7 +63,7 @@ export const conditionsModule: FormieModuleDefinition = {
|
|
|
56
63
|
return getConditionNodes(scopeRoot).flatMap((node) => {
|
|
57
64
|
const settings = parseConditionSettings(node);
|
|
58
65
|
|
|
59
|
-
if (!settings
|
|
66
|
+
if (!settings) {
|
|
60
67
|
return [];
|
|
61
68
|
}
|
|
62
69
|
|
|
@@ -72,6 +79,34 @@ export const conditionsModule: FormieModuleDefinition = {
|
|
|
72
79
|
});
|
|
73
80
|
};
|
|
74
81
|
|
|
82
|
+
const orderEntries = (items: ConditionEntry[]): ConditionEntry[] => {
|
|
83
|
+
const byNode = new Map(items.map((entry) => [entry.node, entry]));
|
|
84
|
+
const visited = new Set<Element>();
|
|
85
|
+
const visiting: Element[] = [];
|
|
86
|
+
const ordered: ConditionEntry[] = [];
|
|
87
|
+
cycles = new Set();
|
|
88
|
+
const visit = (entry: ConditionEntry): void => {
|
|
89
|
+
if (visited.has(entry.node)) return;
|
|
90
|
+
const index = visiting.indexOf(entry.node);
|
|
91
|
+
if (index >= 0) { visiting.slice(index).forEach((node) => cycles.add(node)); return; }
|
|
92
|
+
visiting.push(entry.node);
|
|
93
|
+
const ancestors = (node: Element | null) => {
|
|
94
|
+
for (let current = node?.closest(CONDITION_SELECTOR); current; current = current.parentElement?.closest(CONDITION_SELECTOR)) {
|
|
95
|
+
const dependency = byNode.get(current);
|
|
96
|
+
if (dependency) visit(dependency);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
ancestors(entry.node.parentElement);
|
|
100
|
+
entry.sourceInputs.forEach((input) => ancestors(input));
|
|
101
|
+
visiting.pop();
|
|
102
|
+
visited.add(entry.node);
|
|
103
|
+
ordered.push(entry);
|
|
104
|
+
};
|
|
105
|
+
items.forEach(visit);
|
|
106
|
+
if (cycles.size) debug.warn('Condition dependency cycle.', { count: cycles.size });
|
|
107
|
+
return ordered;
|
|
108
|
+
};
|
|
109
|
+
|
|
75
110
|
const cpDisplayMode = ctx.options?.cpDisplayMode === 'muted' ? 'muted' : 'hide';
|
|
76
111
|
let isApplyingConditions = false;
|
|
77
112
|
|
|
@@ -79,8 +114,11 @@ export const conditionsModule: FormieModuleDefinition = {
|
|
|
79
114
|
let hasStateChanges = false;
|
|
80
115
|
|
|
81
116
|
entries.forEach((entry) => {
|
|
82
|
-
const result = evaluateConditionSettings(entry.settings, (condition) => {
|
|
117
|
+
const result = cycles.has(entry.node) ? { finalResult: false, shouldHide: ['show', 'enable'].includes(entry.settings.showRule), diagnostics: [{ code: 'dependencyCycle' }] } : evaluateConditionSettings(entry.settings, (condition) => {
|
|
83
118
|
return queryConditionInputs(scopeRoot, entry.node, condition);
|
|
119
|
+
}, {
|
|
120
|
+
root: scopeRoot,
|
|
121
|
+
from: entry.node,
|
|
84
122
|
});
|
|
85
123
|
|
|
86
124
|
const displayMode = entry.node.hasAttribute('data-formie-page')
|
|
@@ -91,7 +129,7 @@ export const conditionsModule: FormieModuleDefinition = {
|
|
|
91
129
|
entry.node,
|
|
92
130
|
result.shouldHide,
|
|
93
131
|
entry.settings.clearOnHide,
|
|
94
|
-
{ displayMode },
|
|
132
|
+
{ displayMode, disabledOnly: ['enable', 'disable'].includes(entry.settings.showRule) },
|
|
95
133
|
);
|
|
96
134
|
hasStateChanges = hasStateChanges || stateChanged;
|
|
97
135
|
debug.log('Condition evaluated.', {
|
|
@@ -105,6 +143,7 @@ export const conditionsModule: FormieModuleDefinition = {
|
|
|
105
143
|
shouldHide: result.shouldHide,
|
|
106
144
|
finalResult: result.finalResult,
|
|
107
145
|
clearOnHide: entry.settings.clearOnHide,
|
|
146
|
+
diagnostics: cycles.has(entry.node) ? [{ code: 'dependencyCycle' }] : [],
|
|
108
147
|
});
|
|
109
148
|
});
|
|
110
149
|
|
|
@@ -119,15 +158,7 @@ export const conditionsModule: FormieModuleDefinition = {
|
|
|
119
158
|
isApplyingConditions = true;
|
|
120
159
|
|
|
121
160
|
try {
|
|
122
|
-
|
|
123
|
-
if (!runEvaluationPass()) {
|
|
124
|
-
break;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (pass === MAX_EVALUATION_PASSES - 1) {
|
|
128
|
-
debug.warn('Reached max evaluation passes.', { maxPasses: MAX_EVALUATION_PASSES });
|
|
129
|
-
}
|
|
130
|
-
}
|
|
161
|
+
runEvaluationPass();
|
|
131
162
|
} finally {
|
|
132
163
|
isApplyingConditions = false;
|
|
133
164
|
}
|
|
@@ -182,15 +213,30 @@ export const conditionsModule: FormieModuleDefinition = {
|
|
|
182
213
|
};
|
|
183
214
|
|
|
184
215
|
ctx.form.addEventListener('reset', resetHandler);
|
|
216
|
+
// Canonical resets have already restored values. Settle conditions
|
|
217
|
+
// before the unload guard captures the form's new clean state.
|
|
218
|
+
const stateResetEvent = getFormStateEventName('reset');
|
|
219
|
+
ctx.form.addEventListener(stateResetEvent, evaluateAll);
|
|
185
220
|
sourceUnbinds.push(() => {
|
|
186
221
|
ctx.form?.removeEventListener('reset', resetHandler);
|
|
222
|
+
ctx.form?.removeEventListener(stateResetEvent, evaluateAll);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
// CP status menu (etc.) updates `data-formie-submission` and fires this event.
|
|
226
|
+
const submissionContextHandler = () => {
|
|
227
|
+
scheduleEvaluateAll();
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
ctx.form.addEventListener(SUBMISSION_CONTEXT_CHANGE_EVENT, submissionContextHandler);
|
|
231
|
+
sourceUnbinds.push(() => {
|
|
232
|
+
ctx.form?.removeEventListener(SUBMISSION_CONTEXT_CHANGE_EVENT, submissionContextHandler);
|
|
187
233
|
});
|
|
188
234
|
}
|
|
189
235
|
};
|
|
190
236
|
|
|
191
237
|
const rebuild = (): void => {
|
|
192
238
|
cleanupSourceBindings();
|
|
193
|
-
entries = buildEntries();
|
|
239
|
+
entries = orderEntries(buildEntries());
|
|
194
240
|
bindSourceInputs();
|
|
195
241
|
debug.log('Rebuilt condition graph.', {
|
|
196
242
|
entryCount: entries.length,
|
|
@@ -249,6 +295,7 @@ export const conditionsModule: FormieModuleDefinition = {
|
|
|
249
295
|
'data-formie-conditionally-hidden',
|
|
250
296
|
'data-formie-page-hidden',
|
|
251
297
|
'data-formie-row-hidden',
|
|
298
|
+
SUBMISSION_CONTEXT_ATTR,
|
|
252
299
|
],
|
|
253
300
|
});
|
|
254
301
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BrowserModuleDefinition } from '#contracts/modules';
|
|
2
2
|
import { getModuleFieldTarget, observeMatchingElements } from '#modules/fields/shared';
|
|
3
3
|
|
|
4
4
|
const MODULE_ID = 'custom-google-maps';
|
|
@@ -390,8 +390,10 @@ function initCustomGoogleMaps(root: HTMLElement): () => void {
|
|
|
390
390
|
};
|
|
391
391
|
}
|
|
392
392
|
|
|
393
|
-
export const customGoogleMapsModule:
|
|
394
|
-
|
|
393
|
+
export const customGoogleMapsModule: BrowserModuleDefinition = {
|
|
394
|
+
moduleId: `formie:${MODULE_ID}`,
|
|
395
|
+
version: 2,
|
|
396
|
+
surfaces: ['server-rendered', 'client-rendered', 'cp-edit'],
|
|
395
397
|
kind: 'field',
|
|
396
398
|
match: ({ target }) => {
|
|
397
399
|
return target instanceof Element && (
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BrowserModuleDefinition } from '#contracts/modules';
|
|
2
2
|
import { getModuleFieldTarget, observeMatchingElements } from '#modules/fields/shared';
|
|
3
3
|
|
|
4
4
|
const MODULE_ID = 'custom-link';
|
|
@@ -69,8 +69,10 @@ function initCustomLink(link: HTMLElement): () => void {
|
|
|
69
69
|
};
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
export const customLinkModule:
|
|
73
|
-
|
|
72
|
+
export const customLinkModule: BrowserModuleDefinition = {
|
|
73
|
+
moduleId: `formie:${MODULE_ID}`,
|
|
74
|
+
version: 2,
|
|
75
|
+
surfaces: ['server-rendered', 'client-rendered', 'cp-edit'],
|
|
74
76
|
kind: 'field',
|
|
75
77
|
match: ({ target }) => {
|
|
76
78
|
return target instanceof Element && (
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BrowserModuleDefinition } from '#contracts/modules';
|
|
2
2
|
import type * as Leaflet from 'leaflet';
|
|
3
3
|
import leafletCss from 'leaflet/dist/leaflet.css?inline';
|
|
4
4
|
import { getModuleFieldTarget, observeMatchingElements } from '#modules/fields/shared';
|
|
@@ -313,8 +313,10 @@ function initCustomMaps(root: HTMLElement): () => void {
|
|
|
313
313
|
};
|
|
314
314
|
}
|
|
315
315
|
|
|
316
|
-
export const customMapsModule:
|
|
317
|
-
|
|
316
|
+
export const customMapsModule: BrowserModuleDefinition = {
|
|
317
|
+
moduleId: `formie:${MODULE_ID}`,
|
|
318
|
+
version: 2,
|
|
319
|
+
surfaces: ['server-rendered', 'client-rendered', 'cp-edit'],
|
|
318
320
|
kind: 'field',
|
|
319
321
|
match: ({ target }) => {
|
|
320
322
|
return target instanceof Element && (
|