@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,11 +1,14 @@
|
|
|
1
|
+
import { browserRequestHeaders, type BrowserRequestOptions } from '@verbb/formie-core';
|
|
1
2
|
import Uppy from '@uppy/core';
|
|
2
3
|
import XHRUpload from '@uppy/xhr-upload';
|
|
3
4
|
import uploadManagerCss from '#theme-css/fields/_upload-manager.css?inline';
|
|
4
5
|
|
|
5
|
-
import type {
|
|
6
|
+
import type { BrowserModuleDefinition } from '#contracts/modules';
|
|
6
7
|
import { dispatchFieldEvent, releaseFormValidators, retainFormValidators } from '#modules/fields/shared';
|
|
7
8
|
import { ensureModuleStyles } from '#modules/styles';
|
|
8
9
|
import { getFieldModuleEventName, getFormStateEventName } from '#utils/event-names';
|
|
10
|
+
import { applyFormCsrfToRecord, appendFormCsrfToFormData, getFormCsrfToken } from '#utils/csrf';
|
|
11
|
+
import { fieldKeyToInputName } from '#utils/field-references';
|
|
9
12
|
import { requestJson } from '#utils/http';
|
|
10
13
|
import { createDebug } from '#utils/debug';
|
|
11
14
|
|
|
@@ -20,6 +23,8 @@ const SORT_UP_SELECTOR = '[data-formie-upload-manager-sort="up"]';
|
|
|
20
23
|
const SORT_DOWN_SELECTOR = '[data-formie-upload-manager-sort="down"]';
|
|
21
24
|
const HIDDEN_INPUT_ANCHOR_ATTR = 'data-formie-file-upload-anchor';
|
|
22
25
|
const HIDDEN_INPUT_VALUE_ATTR = 'data-formie-file-upload-asset-id';
|
|
26
|
+
const HIDDEN_INPUT_TOKEN_ATTR = 'data-formie-file-upload-token';
|
|
27
|
+
const HIDDEN_INPUT_ENTRY_ATTR = 'data-formie-file-upload-entry';
|
|
23
28
|
const FORM_RESET_EVENT = getFormStateEventName('reset');
|
|
24
29
|
const REPEATER_INIT_ROW_EVENT = getFieldModuleEventName('repeater', 'init-row');
|
|
25
30
|
const MODULE_ID = 'upload-manager';
|
|
@@ -37,9 +42,9 @@ type UploadManagerOptions = {
|
|
|
37
42
|
uploadEndpoint?: string;
|
|
38
43
|
deleteEndpoint?: string;
|
|
39
44
|
hydrateEndpoint?: string;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
maxFiles?: number | null;
|
|
46
|
+
minFileSize?: number | null;
|
|
47
|
+
maxFileSize?: number | null;
|
|
43
48
|
accept?: string | null;
|
|
44
49
|
restrictFiles?: boolean;
|
|
45
50
|
};
|
|
@@ -49,6 +54,10 @@ type UploadResponse = {
|
|
|
49
54
|
assetId?: number;
|
|
50
55
|
filename?: string;
|
|
51
56
|
url?: string | null;
|
|
57
|
+
uploadToken?: string | null;
|
|
58
|
+
deleteToken?: string | null;
|
|
59
|
+
uploadUid?: string | null;
|
|
60
|
+
attachToken?: string | null;
|
|
52
61
|
errors?: Record<string, string[]>;
|
|
53
62
|
};
|
|
54
63
|
|
|
@@ -62,11 +71,19 @@ type HydrateResponse = {
|
|
|
62
71
|
assetId?: number;
|
|
63
72
|
filename?: string;
|
|
64
73
|
url?: string | null;
|
|
74
|
+
uploadToken?: string | null;
|
|
75
|
+
deleteToken?: string | null;
|
|
76
|
+
uploadUid?: string | null;
|
|
77
|
+
attachToken?: string | null;
|
|
65
78
|
}>;
|
|
66
79
|
};
|
|
67
80
|
|
|
68
81
|
type ManagedFile = {
|
|
69
82
|
assetId: number | null;
|
|
83
|
+
uploadToken: string | null;
|
|
84
|
+
deleteToken?: string | null;
|
|
85
|
+
uploadUid: string | null;
|
|
86
|
+
attachToken: string | null;
|
|
70
87
|
filename: string;
|
|
71
88
|
uppyFileId: string | null;
|
|
72
89
|
listItem: HTMLElement;
|
|
@@ -144,33 +161,85 @@ function getAnchorInput(field: HTMLElement, assetInputName: string): HTMLInputEl
|
|
|
144
161
|
|
|
145
162
|
function getUploadedAssetInputs(field: HTMLElement, assetInputName: string): HTMLInputElement[] {
|
|
146
163
|
return getHiddenInputs(field).filter((hiddenInput) => {
|
|
147
|
-
return hiddenInput.
|
|
164
|
+
return hiddenInput.hasAttribute(HIDDEN_INPUT_VALUE_ATTR)
|
|
165
|
+
|| (hiddenInput.name === assetInputName && hiddenInput.value.trim() !== '');
|
|
148
166
|
});
|
|
149
167
|
}
|
|
150
168
|
|
|
151
169
|
function readAssetIdsFromDom(field: HTMLElement, assetInputName: string): number[] {
|
|
152
170
|
return getUploadedAssetInputs(field, assetInputName).map((input) => {
|
|
153
|
-
return toPositiveInt(input.value);
|
|
171
|
+
return toPositiveInt(input.getAttribute(HIDDEN_INPUT_VALUE_ATTR)) ?? toPositiveInt(input.value);
|
|
154
172
|
}).filter((assetId): assetId is number => {
|
|
155
173
|
return assetId !== null;
|
|
156
174
|
});
|
|
157
175
|
}
|
|
158
176
|
|
|
159
|
-
function
|
|
177
|
+
function readUploadTokensFromDom(field: HTMLElement, assetInputName: string): Record<number, string> {
|
|
178
|
+
const tokens: Record<number, string> = {};
|
|
179
|
+
|
|
180
|
+
getUploadedAssetInputs(field, assetInputName).forEach((input) => {
|
|
181
|
+
const assetId = toPositiveInt(input.getAttribute(HIDDEN_INPUT_VALUE_ATTR)) ?? toPositiveInt(input.value);
|
|
182
|
+
const token = input.getAttribute(HIDDEN_INPUT_TOKEN_ATTR)?.trim() || '';
|
|
183
|
+
|
|
184
|
+
if (assetId && token) {
|
|
185
|
+
tokens[assetId] = token;
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
return tokens;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function syncHiddenAssetInputs(
|
|
193
|
+
field: HTMLElement,
|
|
194
|
+
anchorInput: HTMLInputElement,
|
|
195
|
+
assetInputName: string,
|
|
196
|
+
assets: Array<{
|
|
197
|
+
assetId: number;
|
|
198
|
+
uploadToken: string | null;
|
|
199
|
+
uploadUid: string | null;
|
|
200
|
+
attachToken: string | null;
|
|
201
|
+
}>,
|
|
202
|
+
): void {
|
|
160
203
|
let insertionPoint: HTMLInputElement = anchorInput;
|
|
204
|
+
const baseName = assetInputName.endsWith('[]') ? assetInputName.slice(0, -2) : assetInputName;
|
|
161
205
|
|
|
162
|
-
|
|
206
|
+
getHiddenInputs(field).filter((hiddenInput) => {
|
|
207
|
+
return hiddenInput.hasAttribute(HIDDEN_INPUT_ENTRY_ATTR)
|
|
208
|
+
|| (hiddenInput.name === assetInputName && hiddenInput.value.trim() !== '');
|
|
209
|
+
}).forEach((hiddenInput) => {
|
|
163
210
|
hiddenInput.remove();
|
|
164
211
|
});
|
|
165
212
|
|
|
166
|
-
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
213
|
+
assets.forEach(({ assetId, uploadToken, uploadUid, attachToken }, index) => {
|
|
214
|
+
const primaryInput = document.createElement('input');
|
|
215
|
+
primaryInput.type = 'hidden';
|
|
216
|
+
primaryInput.setAttribute(HIDDEN_INPUT_ENTRY_ATTR, 'true');
|
|
217
|
+
primaryInput.setAttribute(HIDDEN_INPUT_VALUE_ATTR, String(assetId));
|
|
218
|
+
|
|
219
|
+
if (uploadUid && attachToken) {
|
|
220
|
+
primaryInput.name = `${baseName}[${index}][uploadUid]`;
|
|
221
|
+
primaryInput.value = uploadUid;
|
|
222
|
+
} else {
|
|
223
|
+
primaryInput.name = `${baseName}[${index}][assetId]`;
|
|
224
|
+
primaryInput.value = String(assetId);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (uploadToken) {
|
|
228
|
+
primaryInput.setAttribute(HIDDEN_INPUT_TOKEN_ATTR, uploadToken);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
insertionPoint.insertAdjacentElement('afterend', primaryInput);
|
|
232
|
+
insertionPoint = primaryInput;
|
|
233
|
+
|
|
234
|
+
if (uploadUid && attachToken) {
|
|
235
|
+
const capabilityInput = document.createElement('input');
|
|
236
|
+
capabilityInput.type = 'hidden';
|
|
237
|
+
capabilityInput.name = `${baseName}[${index}][attachToken]`;
|
|
238
|
+
capabilityInput.value = attachToken;
|
|
239
|
+
capabilityInput.setAttribute(HIDDEN_INPUT_ENTRY_ATTR, 'true');
|
|
240
|
+
insertionPoint.insertAdjacentElement('afterend', capabilityInput);
|
|
241
|
+
insertionPoint = capabilityInput;
|
|
242
|
+
}
|
|
174
243
|
});
|
|
175
244
|
}
|
|
176
245
|
|
|
@@ -189,7 +258,7 @@ function getUploadContext(form: HTMLFormElement | null, field: HTMLElement, drop
|
|
|
189
258
|
return context;
|
|
190
259
|
}
|
|
191
260
|
|
|
192
|
-
const passthroughNames = ['renderId', 'draftContextToken', 'draftContext', 'submissionId'] as const;
|
|
261
|
+
const passthroughNames = ['renderId', 'draftContextToken', 'draftContext', 'submissionId', 'siteId', 'submissionEditToken', 'resumeToken', 'submissionUid', 'uploadCreateToken'] as const;
|
|
193
262
|
|
|
194
263
|
passthroughNames.forEach((name) => {
|
|
195
264
|
const input = form.querySelector(`input[name="${name}"]`);
|
|
@@ -199,16 +268,18 @@ function getUploadContext(form: HTMLFormElement | null, field: HTMLElement, drop
|
|
|
199
268
|
}
|
|
200
269
|
});
|
|
201
270
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if (csrfInput instanceof HTMLInputElement && csrfInput.value.trim()) {
|
|
205
|
-
context.CRAFT_CSRF_TOKEN = csrfInput.value.trim();
|
|
206
|
-
}
|
|
271
|
+
// Honour custom Craft csrfTokenName values from the rendered form.
|
|
272
|
+
applyFormCsrfToRecord(context, form);
|
|
207
273
|
|
|
208
274
|
return context;
|
|
209
275
|
}
|
|
210
276
|
|
|
211
|
-
function buildHydrateFormData(
|
|
277
|
+
function buildHydrateFormData(
|
|
278
|
+
form: HTMLFormElement | null,
|
|
279
|
+
field: HTMLElement,
|
|
280
|
+
assetIds: number[],
|
|
281
|
+
uploadTokens: Record<number, string> = {},
|
|
282
|
+
): FormData {
|
|
212
283
|
const body = new FormData();
|
|
213
284
|
const handle = getFormHandle(form);
|
|
214
285
|
const fieldHandle = getFieldHandle(field);
|
|
@@ -221,16 +292,28 @@ function buildHydrateFormData(form: HTMLFormElement | null, field: HTMLElement,
|
|
|
221
292
|
body.append('fieldHandle', fieldHandle);
|
|
222
293
|
}
|
|
223
294
|
|
|
224
|
-
const
|
|
295
|
+
const passthroughNames = ['submissionUid', 'resumeToken', 'submissionEditToken', 'siteId', 'renderId', 'draftContext', 'draftContextToken'] as const;
|
|
225
296
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
297
|
+
passthroughNames.forEach((name) => {
|
|
298
|
+
const input = form?.querySelector(`input[name="${name}"]`);
|
|
299
|
+
|
|
300
|
+
if (input instanceof HTMLInputElement && input.value.trim()) {
|
|
301
|
+
body.append(name, input.value.trim());
|
|
302
|
+
}
|
|
303
|
+
});
|
|
229
304
|
|
|
230
305
|
assetIds.forEach((assetId) => {
|
|
231
306
|
body.append('assetIds[]', String(assetId));
|
|
307
|
+
|
|
308
|
+
const token = uploadTokens[assetId];
|
|
309
|
+
|
|
310
|
+
if (token) {
|
|
311
|
+
body.append(`uploadTokens[${assetId}]`, token);
|
|
312
|
+
}
|
|
232
313
|
});
|
|
233
314
|
|
|
315
|
+
appendFormCsrfToFormData(body, form);
|
|
316
|
+
|
|
234
317
|
return body;
|
|
235
318
|
}
|
|
236
319
|
|
|
@@ -425,6 +508,19 @@ function markUploadComplete(listItem: HTMLElement): void {
|
|
|
425
508
|
}, UPLOAD_COMPLETE_DISPLAY_MS);
|
|
426
509
|
}
|
|
427
510
|
|
|
511
|
+
function markUploadFailed(listItem: HTMLElement): void {
|
|
512
|
+
const { track, bar, label } = getProgressElements(listItem);
|
|
513
|
+
|
|
514
|
+
listItem.classList.add('is-error');
|
|
515
|
+
listItem.classList.remove('is-uploading', 'is-upload-complete', 'is-processing', 'is-preparing');
|
|
516
|
+
track?.setAttribute('data-indeterminate', 'false');
|
|
517
|
+
bar?.setAttribute('data-progress', 'error');
|
|
518
|
+
|
|
519
|
+
if (label) {
|
|
520
|
+
label.textContent = 'Upload failed';
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
428
524
|
function createSortButton(direction: 'up' | 'down'): HTMLButtonElement {
|
|
429
525
|
const label = direction === 'up' ? 'Move file up' : 'Move file down';
|
|
430
526
|
const button = document.createElement('button');
|
|
@@ -524,17 +620,20 @@ function createListItem(field: HTMLElement, filename: string): {
|
|
|
524
620
|
}
|
|
525
621
|
|
|
526
622
|
function getAssetInputName(field: HTMLElement): string {
|
|
527
|
-
|
|
528
|
-
|
|
623
|
+
// Prefer the template anchor name — nested Group/Repeater fields use
|
|
624
|
+
// `fields[group][upload][]`, not a dotted `fields[group.upload][]`.
|
|
625
|
+
const anchorInput = getHiddenInputs(field).find((input) => {
|
|
626
|
+
return input.hasAttribute(HIDDEN_INPUT_ANCHOR_ATTR);
|
|
529
627
|
});
|
|
530
628
|
|
|
531
|
-
if (
|
|
532
|
-
return
|
|
629
|
+
if (anchorInput?.name) {
|
|
630
|
+
return anchorInput.name.endsWith('[]') ? anchorInput.name : `${anchorInput.name}[]`;
|
|
533
631
|
}
|
|
534
632
|
|
|
535
633
|
const fieldHandle = getFieldHandle(field);
|
|
634
|
+
const inputName = fieldHandle ? fieldKeyToInputName(fieldHandle) : '';
|
|
536
635
|
|
|
537
|
-
return
|
|
636
|
+
return inputName ? `${inputName}[]` : 'fields[fileUpload][]';
|
|
538
637
|
}
|
|
539
638
|
|
|
540
639
|
function countManagedAssets(state: UploadManagerState): number {
|
|
@@ -544,27 +643,31 @@ function countManagedAssets(state: UploadManagerState): number {
|
|
|
544
643
|
}
|
|
545
644
|
|
|
546
645
|
function syncUploadedAssetsEvent(state: UploadManagerState): void {
|
|
547
|
-
const
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
646
|
+
const assets = state.files
|
|
647
|
+
.filter((file): file is ManagedFile & { assetId: number } => {
|
|
648
|
+
return file.assetId !== null;
|
|
649
|
+
})
|
|
650
|
+
.map((file) => {
|
|
651
|
+
return {
|
|
652
|
+
assetId: file.assetId,
|
|
653
|
+
uploadToken: file.uploadToken,
|
|
654
|
+
uploadUid: file.uploadUid,
|
|
655
|
+
attachToken: file.attachToken,
|
|
656
|
+
filename: file.filename,
|
|
657
|
+
};
|
|
658
|
+
});
|
|
552
659
|
|
|
553
|
-
syncHiddenAssetInputs(state.field, state.anchorInput, state.assetInputName,
|
|
660
|
+
syncHiddenAssetInputs(state.field, state.anchorInput, state.assetInputName, assets);
|
|
554
661
|
|
|
555
662
|
if (state.statusInput) {
|
|
556
|
-
state.statusInput.value =
|
|
663
|
+
state.statusInput.value = assets.length ? 'uploaded' : '';
|
|
557
664
|
}
|
|
558
665
|
|
|
559
666
|
dispatchFieldEvent(state.field, 'file-upload', 'uploaded-assets-sync', {
|
|
560
|
-
assets:
|
|
561
|
-
const managed = state.files.find((file) => {
|
|
562
|
-
return file.assetId === assetId;
|
|
563
|
-
});
|
|
564
|
-
|
|
667
|
+
assets: assets.map(({ assetId, filename }) => {
|
|
565
668
|
return {
|
|
566
669
|
assetId,
|
|
567
|
-
filename
|
|
670
|
+
filename,
|
|
568
671
|
};
|
|
569
672
|
}),
|
|
570
673
|
});
|
|
@@ -673,9 +776,9 @@ function bindUploadManagerField(field: HTMLElement, form: HTMLFormElement | null
|
|
|
673
776
|
const uploadEndpoint = getEndpoint(dropzone, options.uploadEndpoint, 'data-formie-file-upload-upload-endpoint', '/actions/formie/file-upload/upload');
|
|
674
777
|
const deleteEndpoint = getEndpoint(dropzone, options.deleteEndpoint, 'data-formie-file-upload-delete-endpoint', '/actions/formie/file-upload/delete');
|
|
675
778
|
const hydrateEndpoint = getEndpoint(dropzone, options.hydrateEndpoint, 'data-formie-file-upload-hydrate-endpoint', '/actions/formie/file-upload/hydrate');
|
|
676
|
-
const
|
|
677
|
-
const
|
|
678
|
-
const
|
|
779
|
+
const maxFiles = options.maxFiles ?? toPositiveInt(dropzone.getAttribute('data-formie-file-limit'));
|
|
780
|
+
const maxFileSize = options.maxFileSize ?? parseFloat(dropzone.getAttribute('data-formie-size-max-limit') || '');
|
|
781
|
+
const minFileSize = options.minFileSize ?? parseFloat(dropzone.getAttribute('data-formie-size-min-limit') || '');
|
|
679
782
|
const accept = options.accept ?? dropzone.getAttribute('accept') ?? browseInput.accept;
|
|
680
783
|
const allowedFileTypes = parseAcceptTypes(accept);
|
|
681
784
|
|
|
@@ -686,16 +789,16 @@ function bindUploadManagerField(field: HTMLElement, form: HTMLFormElement | null
|
|
|
686
789
|
allowedFileTypes?: string[] | null;
|
|
687
790
|
} = {};
|
|
688
791
|
|
|
689
|
-
if (
|
|
690
|
-
restrictions.maxNumberOfFiles =
|
|
792
|
+
if (maxFiles) {
|
|
793
|
+
restrictions.maxNumberOfFiles = maxFiles;
|
|
691
794
|
}
|
|
692
795
|
|
|
693
|
-
if (
|
|
694
|
-
restrictions.maxFileSize =
|
|
796
|
+
if (maxFileSize) {
|
|
797
|
+
restrictions.maxFileSize = maxFileSize * 1000 * 1000;
|
|
695
798
|
}
|
|
696
799
|
|
|
697
|
-
if (
|
|
698
|
-
restrictions.minFileSize =
|
|
800
|
+
if (minFileSize) {
|
|
801
|
+
restrictions.minFileSize = minFileSize * 1000 * 1000;
|
|
699
802
|
}
|
|
700
803
|
|
|
701
804
|
if (allowedFileTypes) {
|
|
@@ -707,11 +810,36 @@ function bindUploadManagerField(field: HTMLElement, form: HTMLFormElement | null
|
|
|
707
810
|
restrictions,
|
|
708
811
|
});
|
|
709
812
|
|
|
813
|
+
const selectionError = document.createElement('div');
|
|
814
|
+
selectionError.className = 'formie-upload-manager-error';
|
|
815
|
+
selectionError.setAttribute('role', 'alert');
|
|
816
|
+
selectionError.hidden = true;
|
|
817
|
+
root.append(selectionError);
|
|
818
|
+
|
|
819
|
+
// Uppy stores restriction messages for UI plugins; this custom UI must render them.
|
|
820
|
+
uppy.on('info-visible', () => {
|
|
821
|
+
const messages = uppy.getState().info.filter((info) => info.type === 'error');
|
|
822
|
+
|
|
823
|
+
if (messages.length) {
|
|
824
|
+
selectionError.textContent = [...new Set(messages.map((info) => info.message))].join(' ');
|
|
825
|
+
selectionError.hidden = false;
|
|
826
|
+
}
|
|
827
|
+
});
|
|
828
|
+
|
|
829
|
+
const clearSelectionError = () => {
|
|
830
|
+
selectionError.textContent = '';
|
|
831
|
+
selectionError.hidden = true;
|
|
832
|
+
};
|
|
833
|
+
|
|
834
|
+
// Resolve once for Uppy's allow-list; per-request meta/header refresh
|
|
835
|
+
// still re-reads the live form token (including custom csrfTokenName).
|
|
836
|
+
const initialCsrf = getFormCsrfToken(resolvedForm);
|
|
837
|
+
|
|
710
838
|
uppy.use(XHRUpload, {
|
|
711
839
|
endpoint: uploadEndpoint,
|
|
712
840
|
fieldName: 'file',
|
|
713
841
|
formData: true,
|
|
714
|
-
withCredentials:
|
|
842
|
+
withCredentials: resolvedForm?.dataset.formieRequestProfile !== 'cross-origin-public',
|
|
715
843
|
timeout: UPLOAD_XHR_TIMEOUT_MS,
|
|
716
844
|
shouldRetry: shouldRetryUpload,
|
|
717
845
|
headers: {
|
|
@@ -725,7 +853,11 @@ function bindUploadManagerField(field: HTMLElement, form: HTMLFormElement | null
|
|
|
725
853
|
'draftContextToken',
|
|
726
854
|
'draftContext',
|
|
727
855
|
'submissionId',
|
|
728
|
-
'
|
|
856
|
+
'siteId',
|
|
857
|
+
'submissionEditToken',
|
|
858
|
+
'resumeToken',
|
|
859
|
+
'uploadCreateToken',
|
|
860
|
+
...(initialCsrf ? [initialCsrf.name] : []),
|
|
729
861
|
],
|
|
730
862
|
getResponseData(xhr) {
|
|
731
863
|
try {
|
|
@@ -735,6 +867,14 @@ function bindUploadManagerField(field: HTMLElement, form: HTMLFormElement | null
|
|
|
735
867
|
}
|
|
736
868
|
},
|
|
737
869
|
onBeforeRequest(xhr, _retryCount, files) {
|
|
870
|
+
browserRequestHeaders(uploadEndpoint, { profile: resolvedForm?.dataset.formieRequestProfile as BrowserRequestOptions['profile'] }).forEach((value, name) => xhr.setRequestHeader(name, value));
|
|
871
|
+
// Header works regardless of csrfTokenName / allowedMetaFields.
|
|
872
|
+
const csrf = getFormCsrfToken(resolvedForm);
|
|
873
|
+
|
|
874
|
+
if (csrf) {
|
|
875
|
+
xhr.setRequestHeader('X-CSRF-Token', csrf.value);
|
|
876
|
+
}
|
|
877
|
+
|
|
738
878
|
const uppyFile = files[0];
|
|
739
879
|
|
|
740
880
|
if (!uppyFile?.id || !uppyFile.size) {
|
|
@@ -780,11 +920,11 @@ function bindUploadManagerField(field: HTMLElement, form: HTMLFormElement | null
|
|
|
780
920
|
};
|
|
781
921
|
|
|
782
922
|
const remainingUploadCapacity = (): number | null => {
|
|
783
|
-
if (!
|
|
923
|
+
if (!maxFiles) {
|
|
784
924
|
return null;
|
|
785
925
|
}
|
|
786
926
|
|
|
787
|
-
return Math.max(0,
|
|
927
|
+
return Math.max(0, maxFiles - countManagedAssets(state));
|
|
788
928
|
};
|
|
789
929
|
|
|
790
930
|
const setDropzoneActive = (active: boolean) => {
|
|
@@ -888,8 +1028,13 @@ function bindUploadManagerField(field: HTMLElement, form: HTMLFormElement | null
|
|
|
888
1028
|
|
|
889
1029
|
body.append('assetId', String(managedFile.assetId));
|
|
890
1030
|
|
|
1031
|
+
if (managedFile.uploadToken) {
|
|
1032
|
+
body.append('uploadToken', managedFile.deleteToken || '');
|
|
1033
|
+
}
|
|
1034
|
+
|
|
891
1035
|
try {
|
|
892
1036
|
await requestJson<DeleteResponse>(deleteEndpoint, {
|
|
1037
|
+
profile: resolvedForm?.dataset.formieRequestProfile as BrowserRequestOptions['profile'],
|
|
893
1038
|
method: 'POST',
|
|
894
1039
|
body,
|
|
895
1040
|
});
|
|
@@ -906,13 +1051,24 @@ function bindUploadManagerField(field: HTMLElement, form: HTMLFormElement | null
|
|
|
906
1051
|
syncSortControls();
|
|
907
1052
|
};
|
|
908
1053
|
|
|
909
|
-
const addManagedFileFromAsset = (
|
|
1054
|
+
const addManagedFileFromAsset = (
|
|
1055
|
+
assetId: number,
|
|
1056
|
+
filename: string,
|
|
1057
|
+
uploadToken: string | null = null,
|
|
1058
|
+
deleteToken: string | null = null,
|
|
1059
|
+
uploadUid: string | null = null,
|
|
1060
|
+
attachToken: string | null = null,
|
|
1061
|
+
) => {
|
|
910
1062
|
const { listItem, removeButton, sortUpButton, sortDownButton } = createListItem(field, filename);
|
|
911
1063
|
listItem.classList.add('is-complete');
|
|
912
1064
|
fileList.append(listItem);
|
|
913
1065
|
|
|
914
1066
|
const managedFile: ManagedFile = {
|
|
915
1067
|
assetId,
|
|
1068
|
+
uploadToken,
|
|
1069
|
+
deleteToken,
|
|
1070
|
+
uploadUid,
|
|
1071
|
+
attachToken,
|
|
916
1072
|
filename,
|
|
917
1073
|
uppyFileId: null,
|
|
918
1074
|
listItem,
|
|
@@ -930,10 +1086,13 @@ function bindUploadManagerField(field: HTMLElement, form: HTMLFormElement | null
|
|
|
930
1086
|
return;
|
|
931
1087
|
}
|
|
932
1088
|
|
|
1089
|
+
const uploadTokens = readUploadTokensFromDom(field, assetInputName);
|
|
1090
|
+
|
|
933
1091
|
try {
|
|
934
1092
|
const response = await requestJson<HydrateResponse>(hydrateEndpoint, {
|
|
1093
|
+
profile: resolvedForm?.dataset.formieRequestProfile as BrowserRequestOptions['profile'],
|
|
935
1094
|
method: 'POST',
|
|
936
|
-
body: buildHydrateFormData(resolvedForm, field, assetIds),
|
|
1095
|
+
body: buildHydrateFormData(resolvedForm, field, assetIds, uploadTokens),
|
|
937
1096
|
});
|
|
938
1097
|
|
|
939
1098
|
const assets = response.assets || [];
|
|
@@ -956,7 +1115,14 @@ function bindUploadManagerField(field: HTMLElement, form: HTMLFormElement | null
|
|
|
956
1115
|
return;
|
|
957
1116
|
}
|
|
958
1117
|
|
|
959
|
-
addManagedFileFromAsset(
|
|
1118
|
+
addManagedFileFromAsset(
|
|
1119
|
+
assetId,
|
|
1120
|
+
asset.filename || `Asset #${assetId}`,
|
|
1121
|
+
toTrimmedString(asset.uploadToken) || uploadTokens[assetId] || null,
|
|
1122
|
+
toTrimmedString(asset.deleteToken) || null,
|
|
1123
|
+
toTrimmedString(asset.uploadUid) || null,
|
|
1124
|
+
toTrimmedString(asset.attachToken) || null,
|
|
1125
|
+
);
|
|
960
1126
|
});
|
|
961
1127
|
|
|
962
1128
|
syncUploadedAssetsEvent(state);
|
|
@@ -1015,8 +1181,7 @@ function bindUploadManagerField(field: HTMLElement, form: HTMLFormElement | null
|
|
|
1015
1181
|
const assetId = toPositiveInt(body.assetId);
|
|
1016
1182
|
|
|
1017
1183
|
if (!body.success || !assetId) {
|
|
1018
|
-
managedFile.listItem
|
|
1019
|
-
managedFile.listItem.classList.remove('is-uploading', 'is-upload-complete', 'is-processing', 'is-preparing');
|
|
1184
|
+
markUploadFailed(managedFile.listItem);
|
|
1020
1185
|
|
|
1021
1186
|
if (errorEl instanceof HTMLElement) {
|
|
1022
1187
|
errorEl.hidden = false;
|
|
@@ -1034,6 +1199,10 @@ function bindUploadManagerField(field: HTMLElement, form: HTMLFormElement | null
|
|
|
1034
1199
|
}
|
|
1035
1200
|
|
|
1036
1201
|
managedFile.assetId = assetId;
|
|
1202
|
+
managedFile.uploadToken = toTrimmedString(body.uploadToken) || null;
|
|
1203
|
+
managedFile.deleteToken = toTrimmedString(body.deleteToken) || null;
|
|
1204
|
+
managedFile.uploadUid = toTrimmedString(body.uploadUid) || null;
|
|
1205
|
+
managedFile.attachToken = toTrimmedString(body.attachToken) || null;
|
|
1037
1206
|
managedFile.filename = body.filename || managedFile.filename;
|
|
1038
1207
|
markUploadComplete(managedFile.listItem);
|
|
1039
1208
|
syncUploadedAssetsEvent(state);
|
|
@@ -1048,8 +1217,7 @@ function bindUploadManagerField(field: HTMLElement, form: HTMLFormElement | null
|
|
|
1048
1217
|
}
|
|
1049
1218
|
|
|
1050
1219
|
const errorEl = managedFile.listItem.querySelector('[data-formie-upload-manager-error]');
|
|
1051
|
-
managedFile.listItem
|
|
1052
|
-
managedFile.listItem.classList.remove('is-uploading', 'is-upload-complete', 'is-processing', 'is-preparing');
|
|
1220
|
+
markUploadFailed(managedFile.listItem);
|
|
1053
1221
|
|
|
1054
1222
|
if (errorEl instanceof HTMLElement) {
|
|
1055
1223
|
errorEl.hidden = false;
|
|
@@ -1073,6 +1241,9 @@ function bindUploadManagerField(field: HTMLElement, form: HTMLFormElement | null
|
|
|
1073
1241
|
|
|
1074
1242
|
const managedFile: ManagedFile = {
|
|
1075
1243
|
assetId: null,
|
|
1244
|
+
uploadToken: null,
|
|
1245
|
+
uploadUid: null,
|
|
1246
|
+
attachToken: null,
|
|
1076
1247
|
filename: file.name || 'Upload',
|
|
1077
1248
|
uppyFileId: file.id,
|
|
1078
1249
|
listItem,
|
|
@@ -1115,6 +1286,7 @@ function bindUploadManagerField(field: HTMLElement, form: HTMLFormElement | null
|
|
|
1115
1286
|
|
|
1116
1287
|
const files = Array.from(browseInput.files);
|
|
1117
1288
|
browseInput.value = '';
|
|
1289
|
+
clearSelectionError();
|
|
1118
1290
|
|
|
1119
1291
|
try {
|
|
1120
1292
|
uppy.addFiles(files.map((file) => {
|
|
@@ -1155,6 +1327,7 @@ function bindUploadManagerField(field: HTMLElement, form: HTMLFormElement | null
|
|
|
1155
1327
|
}
|
|
1156
1328
|
|
|
1157
1329
|
const files = Array.from(transfer.files);
|
|
1330
|
+
clearSelectionError();
|
|
1158
1331
|
|
|
1159
1332
|
try {
|
|
1160
1333
|
uppy.addFiles(files.map((file) => {
|
|
@@ -1172,6 +1345,7 @@ function bindUploadManagerField(field: HTMLElement, form: HTMLFormElement | null
|
|
|
1172
1345
|
});
|
|
1173
1346
|
|
|
1174
1347
|
const resetHandler = () => {
|
|
1348
|
+
clearSelectionError();
|
|
1175
1349
|
state.files.forEach((managedFile) => {
|
|
1176
1350
|
managedFile.listItem.remove();
|
|
1177
1351
|
});
|
|
@@ -1187,12 +1361,15 @@ function bindUploadManagerField(field: HTMLElement, form: HTMLFormElement | null
|
|
|
1187
1361
|
return () => {
|
|
1188
1362
|
resolvedForm?.removeEventListener(FORM_RESET_EVENT, resetHandler);
|
|
1189
1363
|
uppy.destroy();
|
|
1364
|
+
selectionError.remove();
|
|
1190
1365
|
state.files = [];
|
|
1191
1366
|
};
|
|
1192
1367
|
}
|
|
1193
1368
|
|
|
1194
|
-
export const uploadManagerModule:
|
|
1195
|
-
|
|
1369
|
+
export const uploadManagerModule: BrowserModuleDefinition = {
|
|
1370
|
+
moduleId: `formie:${MODULE_ID}`,
|
|
1371
|
+
version: 2,
|
|
1372
|
+
surfaces: ['server-rendered', 'client-rendered', 'cp-edit'],
|
|
1196
1373
|
kind: 'field',
|
|
1197
1374
|
match: (ctx) => {
|
|
1198
1375
|
return !!ctx.target.querySelector(ROOT_SELECTOR);
|