@verbb/formie-browser 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/LICENSE.md +40 -0
- package/README.md +34 -0
- package/dist/chunks/address-finder-DfMCiW89.js +47 -0
- package/dist/chunks/api-CbqEMQT5.js +181 -0
- package/dist/chunks/api-DE7LfK-R.js +960 -0
- package/dist/chunks/api-DOfDzYC_.js +538 -0
- package/dist/chunks/async-B3DUf1GZ.js +26 -0
- package/dist/chunks/bpoint-Ciy3yY9Q.js +34 -0
- package/dist/chunks/calculations-CkYAqO_-.js +197 -0
- package/dist/chunks/captcha-eu-DnOWhMwr.js +43 -0
- package/dist/chunks/checkbox-radio-0x7Tc0br.js +197 -0
- package/dist/chunks/chunk-K6L4z4UQ.js +24 -0
- package/dist/chunks/conditions-4fXKhEJS.js +609 -0
- package/dist/chunks/date-picker-B6iZkjHS.js +6204 -0
- package/dist/chunks/debug-KnZeKYBI.js +39 -0
- package/dist/chunks/dist-D09GnXMW.js +2663 -0
- package/dist/chunks/event-names-DamGPtXR.js +51 -0
- package/dist/chunks/eway-DEAYcwT0.js +86 -0
- package/dist/chunks/field-references.keys-BpBZ_quS.js +24 -0
- package/dist/chunks/field-references.resolver-Ba6xhiJC.js +183 -0
- package/dist/chunks/file-upload-Bh63PQSE.js +430 -0
- package/dist/chunks/friendly-captcha-v1-CqO4WVre.js +40 -0
- package/dist/chunks/friendly-captcha-v2-CyykcJcM.js +47 -0
- package/dist/chunks/friendly-challenge-Dg8XkStd.js +1101 -0
- package/dist/chunks/go-cardless-CuND59rR.js +26 -0
- package/dist/chunks/google-address--uR8WDSm.js +208 -0
- package/dist/chunks/hcaptcha-CmaFUesv.js +72 -0
- package/dist/chunks/hidden-CYnZYple.js +36 -0
- package/dist/chunks/http-18nn97DZ.js +29 -0
- package/dist/chunks/i18n-vUh-KGiH.js +55 -0
- package/dist/chunks/loqate-BICNJlVK.js +97 -0
- package/dist/chunks/mollie-DwlsgHZ1.js +26 -0
- package/dist/chunks/moneris-B_IFZFTx.js +159 -0
- package/dist/chunks/opayo-U2x_TOII.js +192 -0
- package/dist/chunks/paddle-BqXFrc79.js +75 -0
- package/dist/chunks/paypal-Cn_DYGDb.js +121 -0
- package/dist/chunks/payway-Rnq796eC.js +75 -0
- package/dist/chunks/phone-country-B6Me4lK0.js +3317 -0
- package/dist/chunks/place-kit-ldUl-u9w.js +56 -0
- package/dist/chunks/placekit-autocomplete.esm-D-lGeaZl.js +1771 -0
- package/dist/chunks/recaptcha-enterprise-DPJNyv1X.js +72 -0
- package/dist/chunks/recaptcha-shared-DTI4qWVR.js +22 -0
- package/dist/chunks/recaptcha-v2-checkbox-zFjpvJ5c.js +49 -0
- package/dist/chunks/recaptcha-v2-invisible-CnYtkNvz.js +62 -0
- package/dist/chunks/recaptcha-v3-EAlWhnkX.js +33 -0
- package/dist/chunks/repeater-CXD1eLSn.js +151 -0
- package/dist/chunks/rich-text-DkmZRhGj.js +442 -0
- package/dist/chunks/scripts-BGD_iU_6.js +41 -0
- package/dist/chunks/sdk-B7u9fTlP.js +2103 -0
- package/dist/chunks/shared-DC6_1u8X.js +85 -0
- package/dist/chunks/signature-E9KyYXS1.js +765 -0
- package/dist/chunks/snaptcha-CCDunGeb.js +8 -0
- package/dist/chunks/square-BLqK51rS.js +61 -0
- package/dist/chunks/stripe-B8gHpZNC.js +273 -0
- package/dist/chunks/styles-BIh6g7V_.js +22 -0
- package/dist/chunks/summary-EcNE0cvg.js +191 -0
- package/dist/chunks/table-yxEDL6kA.js +124 -0
- package/dist/chunks/text-limit-D0H_Ca2c.js +179 -0
- package/dist/chunks/theme-classes-vSHpdCUO.js +59 -0
- package/dist/chunks/turnstile-DP0bdR7T.js +68 -0
- package/dist/chunks/utils-ByrEVYrJ.js +49584 -0
- package/dist/css/formie-base.css +78 -0
- package/dist/css/formie-theme.css +19 -0
- package/dist/css/formie.css +2 -0
- package/dist/css/theme/_buttons.css +249 -0
- package/dist/css/theme/_loading.css +37 -0
- package/dist/css/theme/_messages.css +39 -0
- package/dist/css/theme/_progress.css +62 -0
- package/dist/css/theme/_tokens.css +361 -0
- package/dist/css/theme/_typography.css +70 -0
- package/dist/css/theme/fields/_address.css +17 -0
- package/dist/css/theme/fields/_check-radio.css +108 -0
- package/dist/css/theme/fields/_file.css +58 -0
- package/dist/css/theme/fields/_group.css +13 -0
- package/dist/css/theme/fields/_input.css +48 -0
- package/dist/css/theme/fields/_nested.css +19 -0
- package/dist/css/theme/fields/_repeater.css +69 -0
- package/dist/css/theme/fields/_rich-text.css +201 -0
- package/dist/css/theme/fields/_select.css +37 -0
- package/dist/css/theme/fields/_signature.css +39 -0
- package/dist/css/theme/fields/_summary.css +53 -0
- package/dist/css/theme/fields/_table.css +121 -0
- package/dist/css/theme/fields/_text-limit.css +10 -0
- package/dist/css/theme/forms/_field.css +62 -0
- package/dist/css/theme/forms/_form.css +166 -0
- package/dist/css/theme/integrations/_payment-modal.css +32 -0
- package/dist/css/theme/integrations/_paypal.css +10 -0
- package/dist/css/theme/integrations/_payway.css +10 -0
- package/dist/css/theme/integrations/_stripe.css +24 -0
- package/dist/css/theme/utilities/_accessibility.css +13 -0
- package/dist/css/theme-base/_controls.css +41 -0
- package/dist/css/theme-base/_primitives.css +34 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3206 -0
- package/dist/js/compatibility/dom-adapter.d.ts +12 -0
- package/dist/js/compatibility/dom-adapter.d.ts.map +1 -0
- package/dist/js/compatibility/event-map.d.ts +25 -0
- package/dist/js/compatibility/event-map.d.ts.map +1 -0
- package/dist/js/compatibility/validator-adapter.d.ts +17 -0
- package/dist/js/compatibility/validator-adapter.d.ts.map +1 -0
- package/dist/js/contracts/client.d.ts +40 -0
- package/dist/js/contracts/client.d.ts.map +1 -0
- package/dist/js/contracts/common.d.ts +5 -0
- package/dist/js/contracts/common.d.ts.map +1 -0
- package/dist/js/contracts/modules.d.ts +47 -0
- package/dist/js/contracts/modules.d.ts.map +1 -0
- package/dist/js/contracts/schema.d.ts +79 -0
- package/dist/js/contracts/schema.d.ts.map +1 -0
- package/dist/js/contracts/theme.d.ts +2 -0
- package/dist/js/contracts/theme.d.ts.map +1 -0
- package/dist/js/core/create-formie-client.d.ts +3 -0
- package/dist/js/core/create-formie-client.d.ts.map +1 -0
- package/dist/js/core/dom-events.d.ts +2 -0
- package/dist/js/core/dom-events.d.ts.map +1 -0
- package/dist/js/core/formie.d.ts +27 -0
- package/dist/js/core/formie.d.ts.map +1 -0
- package/dist/js/core/hydrate-modules.d.ts +22 -0
- package/dist/js/core/hydrate-modules.d.ts.map +1 -0
- package/dist/js/core/page-client-event.d.ts +9 -0
- package/dist/js/core/page-client-event.d.ts.map +1 -0
- package/dist/js/core/page-tab-errors.d.ts +2 -0
- package/dist/js/core/page-tab-errors.d.ts.map +1 -0
- package/dist/js/core/submit-flow.d.ts +21 -0
- package/dist/js/core/submit-flow.d.ts.map +1 -0
- package/dist/js/core/submit-result-state.d.ts +8 -0
- package/dist/js/core/submit-result-state.d.ts.map +1 -0
- package/dist/js/core/submit-result-ui.d.ts +10 -0
- package/dist/js/core/submit-result-ui.d.ts.map +1 -0
- package/dist/js/events/event-bus.d.ts +21 -0
- package/dist/js/events/event-bus.d.ts.map +1 -0
- package/dist/js/modules/address/address-finder.d.ts +2 -0
- package/dist/js/modules/address/address-finder.d.ts.map +1 -0
- package/dist/js/modules/address/api.d.ts +8 -0
- package/dist/js/modules/address/api.d.ts.map +1 -0
- package/dist/js/modules/address/constants.d.ts +15 -0
- package/dist/js/modules/address/constants.d.ts.map +1 -0
- package/dist/js/modules/address/factories.d.ts +35 -0
- package/dist/js/modules/address/factories.d.ts.map +1 -0
- package/dist/js/modules/address/google-address.d.ts +2 -0
- package/dist/js/modules/address/google-address.d.ts.map +1 -0
- package/dist/js/modules/address/host.d.ts +30 -0
- package/dist/js/modules/address/host.d.ts.map +1 -0
- package/dist/js/modules/address/index.d.ts +3 -0
- package/dist/js/modules/address/index.d.ts.map +1 -0
- package/dist/js/modules/address/loqate.d.ts +2 -0
- package/dist/js/modules/address/loqate.d.ts.map +1 -0
- package/dist/js/modules/address/place-kit.d.ts +2 -0
- package/dist/js/modules/address/place-kit.d.ts.map +1 -0
- package/dist/js/modules/captchas/api.d.ts +9 -0
- package/dist/js/modules/captchas/api.d.ts.map +1 -0
- package/dist/js/modules/captchas/captcha-eu.d.ts +2 -0
- package/dist/js/modules/captchas/captcha-eu.d.ts.map +1 -0
- package/dist/js/modules/captchas/constants.d.ts +5 -0
- package/dist/js/modules/captchas/constants.d.ts.map +1 -0
- package/dist/js/modules/captchas/factories.d.ts +63 -0
- package/dist/js/modules/captchas/factories.d.ts.map +1 -0
- package/dist/js/modules/captchas/friendly-captcha-v1.d.ts +2 -0
- package/dist/js/modules/captchas/friendly-captcha-v1.d.ts.map +1 -0
- package/dist/js/modules/captchas/friendly-captcha-v2.d.ts +2 -0
- package/dist/js/modules/captchas/friendly-captcha-v2.d.ts.map +1 -0
- package/dist/js/modules/captchas/hcaptcha.d.ts +2 -0
- package/dist/js/modules/captchas/hcaptcha.d.ts.map +1 -0
- package/dist/js/modules/captchas/host.d.ts +78 -0
- package/dist/js/modules/captchas/host.d.ts.map +1 -0
- package/dist/js/modules/captchas/index.d.ts +3 -0
- package/dist/js/modules/captchas/index.d.ts.map +1 -0
- package/dist/js/modules/captchas/recaptcha-enterprise.d.ts +2 -0
- package/dist/js/modules/captchas/recaptcha-enterprise.d.ts.map +1 -0
- package/dist/js/modules/captchas/recaptcha-shared.d.ts +26 -0
- package/dist/js/modules/captchas/recaptcha-shared.d.ts.map +1 -0
- package/dist/js/modules/captchas/recaptcha-v2-checkbox.d.ts +2 -0
- package/dist/js/modules/captchas/recaptcha-v2-checkbox.d.ts.map +1 -0
- package/dist/js/modules/captchas/recaptcha-v2-invisible.d.ts +2 -0
- package/dist/js/modules/captchas/recaptcha-v2-invisible.d.ts.map +1 -0
- package/dist/js/modules/captchas/recaptcha-v3.d.ts +2 -0
- package/dist/js/modules/captchas/recaptcha-v3.d.ts.map +1 -0
- package/dist/js/modules/captchas/snaptcha.d.ts +2 -0
- package/dist/js/modules/captchas/snaptcha.d.ts.map +1 -0
- package/dist/js/modules/captchas/turnstile.d.ts +2 -0
- package/dist/js/modules/captchas/turnstile.d.ts.map +1 -0
- package/dist/js/modules/captchas/utils.d.ts +13 -0
- package/dist/js/modules/captchas/utils.d.ts.map +1 -0
- package/dist/js/modules/fields/calculations.d.ts +3 -0
- package/dist/js/modules/fields/calculations.d.ts.map +1 -0
- package/dist/js/modules/fields/checkbox-radio.d.ts +3 -0
- package/dist/js/modules/fields/checkbox-radio.d.ts.map +1 -0
- package/dist/js/modules/fields/conditions/config.d.ts +5 -0
- package/dist/js/modules/fields/conditions/config.d.ts.map +1 -0
- package/dist/js/modules/fields/conditions/effects.d.ts +2 -0
- package/dist/js/modules/fields/conditions/effects.d.ts.map +1 -0
- package/dist/js/modules/fields/conditions/evaluator.d.ts +6 -0
- package/dist/js/modules/fields/conditions/evaluator.d.ts.map +1 -0
- package/dist/js/modules/fields/conditions/references.d.ts +5 -0
- package/dist/js/modules/fields/conditions/references.d.ts.map +1 -0
- package/dist/js/modules/fields/conditions/transforms.d.ts +3 -0
- package/dist/js/modules/fields/conditions/transforms.d.ts.map +1 -0
- package/dist/js/modules/fields/conditions/types.d.ts +30 -0
- package/dist/js/modules/fields/conditions/types.d.ts.map +1 -0
- package/dist/js/modules/fields/conditions/values.d.ts +5 -0
- package/dist/js/modules/fields/conditions/values.d.ts.map +1 -0
- package/dist/js/modules/fields/conditions.d.ts +3 -0
- package/dist/js/modules/fields/conditions.d.ts.map +1 -0
- package/dist/js/modules/fields/date-picker.d.ts +3 -0
- package/dist/js/modules/fields/date-picker.d.ts.map +1 -0
- package/dist/js/modules/fields/file-upload.d.ts +3 -0
- package/dist/js/modules/fields/file-upload.d.ts.map +1 -0
- package/dist/js/modules/fields/hidden.d.ts +3 -0
- package/dist/js/modules/fields/hidden.d.ts.map +1 -0
- package/dist/js/modules/fields/index.d.ts +3 -0
- package/dist/js/modules/fields/index.d.ts.map +1 -0
- package/dist/js/modules/fields/phone-country.d.ts +3 -0
- package/dist/js/modules/fields/phone-country.d.ts.map +1 -0
- package/dist/js/modules/fields/repeater.d.ts +3 -0
- package/dist/js/modules/fields/repeater.d.ts.map +1 -0
- package/dist/js/modules/fields/rich-text.d.ts +3 -0
- package/dist/js/modules/fields/rich-text.d.ts.map +1 -0
- package/dist/js/modules/fields/shared.d.ts +20 -0
- package/dist/js/modules/fields/shared.d.ts.map +1 -0
- package/dist/js/modules/fields/signature.d.ts +3 -0
- package/dist/js/modules/fields/signature.d.ts.map +1 -0
- package/dist/js/modules/fields/summary.d.ts +3 -0
- package/dist/js/modules/fields/summary.d.ts.map +1 -0
- package/dist/js/modules/fields/table.d.ts +3 -0
- package/dist/js/modules/fields/table.d.ts.map +1 -0
- package/dist/js/modules/fields/text-limit.d.ts +3 -0
- package/dist/js/modules/fields/text-limit.d.ts.map +1 -0
- package/dist/js/modules/loader.d.ts +11 -0
- package/dist/js/modules/loader.d.ts.map +1 -0
- package/dist/js/modules/payments/api.d.ts +8 -0
- package/dist/js/modules/payments/api.d.ts.map +1 -0
- package/dist/js/modules/payments/bpoint.d.ts +2 -0
- package/dist/js/modules/payments/bpoint.d.ts.map +1 -0
- package/dist/js/modules/payments/constants.d.ts +5 -0
- package/dist/js/modules/payments/constants.d.ts.map +1 -0
- package/dist/js/modules/payments/eway.d.ts +9 -0
- package/dist/js/modules/payments/eway.d.ts.map +1 -0
- package/dist/js/modules/payments/factories.d.ts +54 -0
- package/dist/js/modules/payments/factories.d.ts.map +1 -0
- package/dist/js/modules/payments/go-cardless.d.ts +2 -0
- package/dist/js/modules/payments/go-cardless.d.ts.map +1 -0
- package/dist/js/modules/payments/host.d.ts +70 -0
- package/dist/js/modules/payments/host.d.ts.map +1 -0
- package/dist/js/modules/payments/index.d.ts +3 -0
- package/dist/js/modules/payments/index.d.ts.map +1 -0
- package/dist/js/modules/payments/mollie.d.ts +2 -0
- package/dist/js/modules/payments/mollie.d.ts.map +1 -0
- package/dist/js/modules/payments/moneris.d.ts +2 -0
- package/dist/js/modules/payments/moneris.d.ts.map +1 -0
- package/dist/js/modules/payments/opayo.d.ts +25 -0
- package/dist/js/modules/payments/opayo.d.ts.map +1 -0
- package/dist/js/modules/payments/paddle.d.ts +2 -0
- package/dist/js/modules/payments/paddle.d.ts.map +1 -0
- package/dist/js/modules/payments/paypal.d.ts +2 -0
- package/dist/js/modules/payments/paypal.d.ts.map +1 -0
- package/dist/js/modules/payments/payway.d.ts +2 -0
- package/dist/js/modules/payments/payway.d.ts.map +1 -0
- package/dist/js/modules/payments/square.d.ts +2 -0
- package/dist/js/modules/payments/square.d.ts.map +1 -0
- package/dist/js/modules/payments/stripe.d.ts +2 -0
- package/dist/js/modules/payments/stripe.d.ts.map +1 -0
- package/dist/js/modules/payments/utils.d.ts +17 -0
- package/dist/js/modules/payments/utils.d.ts.map +1 -0
- package/dist/js/modules/registry.d.ts +9 -0
- package/dist/js/modules/registry.d.ts.map +1 -0
- package/dist/js/modules/styles.d.ts +2 -0
- package/dist/js/modules/styles.d.ts.map +1 -0
- package/dist/js/submit/pipeline.d.ts +18 -0
- package/dist/js/submit/pipeline.d.ts.map +1 -0
- package/dist/js/theme/theme-classes.d.ts +10 -0
- package/dist/js/theme/theme-classes.d.ts.map +1 -0
- package/dist/js/transport/forms-api.d.ts +11 -0
- package/dist/js/transport/forms-api.d.ts.map +1 -0
- package/dist/js/utils/async.d.ts +8 -0
- package/dist/js/utils/async.d.ts.map +1 -0
- package/dist/js/utils/debug.d.ts +10 -0
- package/dist/js/utils/debug.d.ts.map +1 -0
- package/dist/js/utils/event-names.d.ts +13 -0
- package/dist/js/utils/event-names.d.ts.map +1 -0
- package/dist/js/utils/field-references.d.ts +6 -0
- package/dist/js/utils/field-references.d.ts.map +1 -0
- package/dist/js/utils/field-references.keys.d.ts +4 -0
- package/dist/js/utils/field-references.keys.d.ts.map +1 -0
- package/dist/js/utils/field-references.parser.d.ts +3 -0
- package/dist/js/utils/field-references.parser.d.ts.map +1 -0
- package/dist/js/utils/field-references.registry.d.ts +3 -0
- package/dist/js/utils/field-references.registry.d.ts.map +1 -0
- package/dist/js/utils/field-references.resolver.d.ts +4 -0
- package/dist/js/utils/field-references.resolver.d.ts.map +1 -0
- package/dist/js/utils/field-references.types.d.ts +27 -0
- package/dist/js/utils/field-references.types.d.ts.map +1 -0
- package/dist/js/utils/fields.d.ts +5 -0
- package/dist/js/utils/fields.d.ts.map +1 -0
- package/dist/js/utils/http.d.ts +9 -0
- package/dist/js/utils/http.d.ts.map +1 -0
- package/dist/js/utils/i18n.d.ts +7 -0
- package/dist/js/utils/i18n.d.ts.map +1 -0
- package/dist/js/utils/scripts.d.ts +13 -0
- package/dist/js/utils/scripts.d.ts.map +1 -0
- package/dist/js/utils/unload-warning.d.ts +10 -0
- package/dist/js/utils/unload-warning.d.ts.map +1 -0
- package/dist/js/validation/rules/email.d.ts +4 -0
- package/dist/js/validation/rules/email.d.ts.map +1 -0
- package/dist/js/validation/rules/match.d.ts +4 -0
- package/dist/js/validation/rules/match.d.ts.map +1 -0
- package/dist/js/validation/rules/number.d.ts +4 -0
- package/dist/js/validation/rules/number.d.ts.map +1 -0
- package/dist/js/validation/rules/required.d.ts +4 -0
- package/dist/js/validation/rules/required.d.ts.map +1 -0
- package/dist/js/validation/rules/shared.d.ts +7 -0
- package/dist/js/validation/rules/shared.d.ts.map +1 -0
- package/dist/js/validation/rules/url.d.ts +4 -0
- package/dist/js/validation/rules/url.d.ts.map +1 -0
- package/dist/js/validation/rules.d.ts +10 -0
- package/dist/js/validation/rules.d.ts.map +1 -0
- package/dist/js/validation/types.d.ts +44 -0
- package/dist/js/validation/types.d.ts.map +1 -0
- package/dist/js/validation/validator.d.ts +53 -0
- package/dist/js/validation/validator.d.ts.map +1 -0
- package/package.json +78 -0
- package/src/css/formie-base.css +78 -0
- package/src/css/formie-theme.css +19 -0
- package/src/css/formie.css +2 -0
- package/src/css/theme/_buttons.css +249 -0
- package/src/css/theme/_loading.css +37 -0
- package/src/css/theme/_messages.css +39 -0
- package/src/css/theme/_progress.css +62 -0
- package/src/css/theme/_tokens.css +361 -0
- package/src/css/theme/_typography.css +70 -0
- package/src/css/theme/fields/_address.css +17 -0
- package/src/css/theme/fields/_check-radio.css +108 -0
- package/src/css/theme/fields/_file.css +58 -0
- package/src/css/theme/fields/_group.css +13 -0
- package/src/css/theme/fields/_input.css +48 -0
- package/src/css/theme/fields/_nested.css +19 -0
- package/src/css/theme/fields/_repeater.css +69 -0
- package/src/css/theme/fields/_rich-text.css +201 -0
- package/src/css/theme/fields/_select.css +37 -0
- package/src/css/theme/fields/_signature.css +39 -0
- package/src/css/theme/fields/_summary.css +53 -0
- package/src/css/theme/fields/_table.css +121 -0
- package/src/css/theme/fields/_text-limit.css +10 -0
- package/src/css/theme/forms/_field.css +62 -0
- package/src/css/theme/forms/_form.css +166 -0
- package/src/css/theme/integrations/_payment-modal.css +32 -0
- package/src/css/theme/integrations/_paypal.css +10 -0
- package/src/css/theme/integrations/_payway.css +10 -0
- package/src/css/theme/integrations/_stripe.css +24 -0
- package/src/css/theme/utilities/_accessibility.css +13 -0
- package/src/css/theme-base/_controls.css +41 -0
- package/src/css/theme-base/_primitives.css +34 -0
- package/src/icons/rich-text/aligncenter.svg +6 -0
- package/src/icons/rich-text/alignleft.svg +6 -0
- package/src/icons/rich-text/alignright.svg +6 -0
- package/src/icons/rich-text/bold.svg +4 -0
- package/src/icons/rich-text/clear.svg +6 -0
- package/src/icons/rich-text/code.svg +4 -0
- package/src/icons/rich-text/heading1.svg +3 -0
- package/src/icons/rich-text/heading2.svg +3 -0
- package/src/icons/rich-text/image.svg +6 -0
- package/src/icons/rich-text/italic.svg +5 -0
- package/src/icons/rich-text/line.svg +3 -0
- package/src/icons/rich-text/link.svg +4 -0
- package/src/icons/rich-text/olist.svg +8 -0
- package/src/icons/rich-text/paragraph.svg +3 -0
- package/src/icons/rich-text/quote.svg +4 -0
- package/src/icons/rich-text/strikethrough.svg +4 -0
- package/src/icons/rich-text/ulist.svg +8 -0
- package/src/icons/rich-text/underline.svg +4 -0
- package/src/index.ts +125 -0
- package/src/js/compatibility/dom-adapter.ts +129 -0
- package/src/js/compatibility/event-map.ts +72 -0
- package/src/js/compatibility/validator-adapter.ts +105 -0
- package/src/js/contracts/client.ts +43 -0
- package/src/js/contracts/common.ts +14 -0
- package/src/js/contracts/modules.ts +53 -0
- package/src/js/contracts/schema.ts +83 -0
- package/src/js/contracts/theme.ts +1 -0
- package/src/js/core/create-formie-client.ts +1519 -0
- package/src/js/core/dom-events.ts +8 -0
- package/src/js/core/formie.ts +242 -0
- package/src/js/core/hydrate-modules.ts +102 -0
- package/src/js/core/page-client-event.ts +129 -0
- package/src/js/core/page-tab-errors.ts +37 -0
- package/src/js/core/submit-flow.ts +120 -0
- package/src/js/core/submit-result-state.ts +597 -0
- package/src/js/core/submit-result-ui.ts +448 -0
- package/src/js/events/event-bus.ts +109 -0
- package/src/js/modules/address/address-finder.ts +85 -0
- package/src/js/modules/address/api.ts +22 -0
- package/src/js/modules/address/constants.ts +15 -0
- package/src/js/modules/address/factories.ts +203 -0
- package/src/js/modules/address/google-address.ts +345 -0
- package/src/js/modules/address/host.ts +137 -0
- package/src/js/modules/address/index.ts +10 -0
- package/src/js/modules/address/loqate.ts +128 -0
- package/src/js/modules/address/place-kit.ts +94 -0
- package/src/js/modules/captchas/api.ts +25 -0
- package/src/js/modules/captchas/captcha-eu.ts +86 -0
- package/src/js/modules/captchas/constants.ts +4 -0
- package/src/js/modules/captchas/factories.ts +485 -0
- package/src/js/modules/captchas/friendly-captcha-v1.ts +65 -0
- package/src/js/modules/captchas/friendly-captcha-v2.ts +84 -0
- package/src/js/modules/captchas/hcaptcha.ts +153 -0
- package/src/js/modules/captchas/host.ts +448 -0
- package/src/js/modules/captchas/index.ts +16 -0
- package/src/js/modules/captchas/recaptcha-enterprise.ts +138 -0
- package/src/js/modules/captchas/recaptcha-shared.ts +69 -0
- package/src/js/modules/captchas/recaptcha-v2-checkbox.ts +72 -0
- package/src/js/modules/captchas/recaptcha-v2-invisible.ts +108 -0
- package/src/js/modules/captchas/recaptcha-v3.ts +62 -0
- package/src/js/modules/captchas/snaptcha.ts +10 -0
- package/src/js/modules/captchas/turnstile.ts +131 -0
- package/src/js/modules/captchas/utils.ts +85 -0
- package/src/js/modules/fields/calculations.ts +273 -0
- package/src/js/modules/fields/checkbox-radio.ts +295 -0
- package/src/js/modules/fields/conditions/config.ts +79 -0
- package/src/js/modules/fields/conditions/effects.ts +166 -0
- package/src/js/modules/fields/conditions/evaluator.ts +44 -0
- package/src/js/modules/fields/conditions/references.ts +165 -0
- package/src/js/modules/fields/conditions/transforms.ts +206 -0
- package/src/js/modules/fields/conditions/types.ts +33 -0
- package/src/js/modules/fields/conditions/values.ts +115 -0
- package/src/js/modules/fields/conditions.ts +229 -0
- package/src/js/modules/fields/date-picker.ts +272 -0
- package/src/js/modules/fields/file-upload.ts +628 -0
- package/src/js/modules/fields/hidden.ts +58 -0
- package/src/js/modules/fields/index.ts +19 -0
- package/src/js/modules/fields/phone-country.ts +226 -0
- package/src/js/modules/fields/repeater.ts +231 -0
- package/src/js/modules/fields/rich-text.ts +217 -0
- package/src/js/modules/fields/shared.ts +238 -0
- package/src/js/modules/fields/signature.ts +202 -0
- package/src/js/modules/fields/summary.ts +272 -0
- package/src/js/modules/fields/table.ts +197 -0
- package/src/js/modules/fields/text-limit.ts +280 -0
- package/src/js/modules/loader.ts +331 -0
- package/src/js/modules/payments/api.ts +20 -0
- package/src/js/modules/payments/bpoint.ts +48 -0
- package/src/js/modules/payments/constants.ts +17 -0
- package/src/js/modules/payments/eway.ts +132 -0
- package/src/js/modules/payments/factories.ts +332 -0
- package/src/js/modules/payments/go-cardless.ts +37 -0
- package/src/js/modules/payments/host.ts +459 -0
- package/src/js/modules/payments/index.ts +17 -0
- package/src/js/modules/payments/mollie.ts +38 -0
- package/src/js/modules/payments/moneris.ts +216 -0
- package/src/js/modules/payments/opayo.ts +272 -0
- package/src/js/modules/payments/paddle.ts +111 -0
- package/src/js/modules/payments/payment.ts +183 -0
- package/src/js/modules/payments/paypal.ts +214 -0
- package/src/js/modules/payments/payway.ts +114 -0
- package/src/js/modules/payments/square.ts +106 -0
- package/src/js/modules/payments/stripe.ts +426 -0
- package/src/js/modules/payments/stub-payment-module.ts +87 -0
- package/src/js/modules/payments/utils.ts +60 -0
- package/src/js/modules/registry.ts +38 -0
- package/src/js/modules/styles.ts +29 -0
- package/src/js/submit/pipeline.ts +514 -0
- package/src/js/theme/theme-classes.ts +106 -0
- package/src/js/transport/forms-api.ts +345 -0
- package/src/js/utils/async.ts +81 -0
- package/src/js/utils/debug.ts +59 -0
- package/src/js/utils/event-names.ts +60 -0
- package/src/js/utils/field-references.keys.ts +47 -0
- package/src/js/utils/field-references.parser.ts +121 -0
- package/src/js/utils/field-references.registry.ts +50 -0
- package/src/js/utils/field-references.resolver.ts +115 -0
- package/src/js/utils/field-references.ts +11 -0
- package/src/js/utils/field-references.types.ts +31 -0
- package/src/js/utils/fields.ts +58 -0
- package/src/js/utils/http.ts +51 -0
- package/src/js/utils/i18n.ts +98 -0
- package/src/js/utils/scripts.ts +84 -0
- package/src/js/utils/unload-warning.ts +190 -0
- package/src/js/validation/rules/email.ts +18 -0
- package/src/js/validation/rules/match.ts +26 -0
- package/src/js/validation/rules/minmax.ts +47 -0
- package/src/js/validation/rules/number.ts +55 -0
- package/src/js/validation/rules/pattern.ts +29 -0
- package/src/js/validation/rules/required.ts +30 -0
- package/src/js/validation/rules/shared.ts +47 -0
- package/src/js/validation/rules/url.ts +23 -0
- package/src/js/validation/rules.ts +16 -0
- package/src/js/validation/types.ts +50 -0
- package/src/js/validation/validator.ts +643 -0
- package/src/vendor.d.ts +100 -0
- package/src/vite-env.d.ts +22 -0
- package/vite-dev.mjs +22 -0
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
import type { FormAction, SubmitStage } from '#contracts/common';
|
|
2
|
+
import type { FormSubmitResult } from '#contracts/schema';
|
|
3
|
+
import { EventBus } from '#events/event-bus';
|
|
4
|
+
import { submitForm } from '#transport/forms-api';
|
|
5
|
+
import { createDebug } from '#utils/debug';
|
|
6
|
+
import type { FormieValidator } from '#validation/validator';
|
|
7
|
+
|
|
8
|
+
export type SubmitPipelineContext = {
|
|
9
|
+
form: HTMLFormElement;
|
|
10
|
+
action: FormAction;
|
|
11
|
+
formData: FormData;
|
|
12
|
+
abort: (reason?: string) => void;
|
|
13
|
+
isAborted: () => boolean;
|
|
14
|
+
abortReason: () => string | undefined;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
type StageRunner = (ctx: SubmitPipelineContext) => Promise<FormSubmitResult | null>;
|
|
18
|
+
|
|
19
|
+
const STAGES: SubmitStage[] = ['prepare', 'normalize', 'validate', 'screen', 'authorize', 'dispatch', 'finalize'];
|
|
20
|
+
const PREFLIGHT_STAGES: SubmitStage[] = ['prepare', 'normalize', 'validate', 'screen', 'authorize'];
|
|
21
|
+
const debug = createDebug('general', 'pipeline');
|
|
22
|
+
|
|
23
|
+
function getAbortedResult(stage: SubmitStage, reason?: string): FormSubmitResult {
|
|
24
|
+
return {
|
|
25
|
+
ok: false,
|
|
26
|
+
stage,
|
|
27
|
+
code: 'ABORTED',
|
|
28
|
+
message: reason || 'Submission aborted.',
|
|
29
|
+
formErrors: [reason || 'Submission aborted.'],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function getPages(form: HTMLFormElement): HTMLElement[] {
|
|
34
|
+
return Array.from(form.querySelectorAll('[data-formie-page]')) as HTMLElement[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function getValidationScope(form: HTMLFormElement): { scope: Element; final: boolean } {
|
|
38
|
+
const pages = getPages(form);
|
|
39
|
+
|
|
40
|
+
if (!pages.length) {
|
|
41
|
+
return {
|
|
42
|
+
scope: form,
|
|
43
|
+
final: true,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Multi-page submits validate the visible page until the user reaches the
|
|
48
|
+
// final step, where hidden earlier pages are included again.
|
|
49
|
+
const currentPage = pages.find((page) => {
|
|
50
|
+
return !page.hasAttribute('data-formie-page-hidden');
|
|
51
|
+
}) || pages[pages.length - 1];
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
scope: currentPage,
|
|
55
|
+
final: currentPage === pages[pages.length - 1],
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function isSubmittableControl(element: Element): element is HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement {
|
|
60
|
+
return element instanceof HTMLInputElement
|
|
61
|
+
|| element instanceof HTMLSelectElement
|
|
62
|
+
|| element instanceof HTMLTextAreaElement;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function shouldIncludeControl(control: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement): boolean {
|
|
66
|
+
if (!control.name || control.disabled) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (control instanceof HTMLInputElement) {
|
|
71
|
+
if (control.type === 'submit' || control.type === 'button' || control.type === 'reset' || control.type === 'image') {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if ((control.type === 'checkbox' || control.type === 'radio') && !control.checked) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (control.type === 'file' && (!control.files || control.files.length === 0)) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function appendControlValue(
|
|
88
|
+
formData: FormData,
|
|
89
|
+
control: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement,
|
|
90
|
+
): void {
|
|
91
|
+
if (control instanceof HTMLInputElement) {
|
|
92
|
+
if (control.type === 'file') {
|
|
93
|
+
Array.from(control.files || []).forEach((file) => {
|
|
94
|
+
formData.append(control.name, file);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
formData.append(control.name, control.value);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (control instanceof HTMLSelectElement && control.multiple) {
|
|
105
|
+
Array.from(control.selectedOptions).forEach((option) => {
|
|
106
|
+
formData.append(control.name, option.value);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
formData.append(control.name, control.value);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function appendControlsFromRoot(formData: FormData, form: HTMLFormElement): void {
|
|
116
|
+
form.querySelectorAll('input, select, textarea').forEach((node) => {
|
|
117
|
+
const control = isSubmittableControl(node) ? node : null;
|
|
118
|
+
|
|
119
|
+
// Form-level transport inputs live outside page wrappers and must always
|
|
120
|
+
// ride along, even when the visible page payload is partial.
|
|
121
|
+
if (!control || control.closest('[data-formie-page]')) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (!shouldIncludeControl(control)) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
appendControlValue(formData, control);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function appendControlsFromPage(formData: FormData, page: HTMLElement): Set<string> {
|
|
134
|
+
const fieldNames = new Set<string>();
|
|
135
|
+
|
|
136
|
+
page.querySelectorAll('input, select, textarea').forEach((node) => {
|
|
137
|
+
const control = isSubmittableControl(node) ? node : null;
|
|
138
|
+
|
|
139
|
+
if (!control || !control.name || control.disabled) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (
|
|
144
|
+
control instanceof HTMLInputElement
|
|
145
|
+
&& (control.type === 'submit' || control.type === 'button' || control.type === 'reset' || control.type === 'image')
|
|
146
|
+
) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (control.name.startsWith('fields[')) {
|
|
151
|
+
fieldNames.add(control.name);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (!shouldIncludeControl(control)) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
appendControlValue(formData, control);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
return fieldNames;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function appendMissingFieldClears(formData: FormData, fieldNames: Set<string>): void {
|
|
165
|
+
fieldNames.forEach((name) => {
|
|
166
|
+
// Unchecked checkbox/radio groups disappear from FormData by default.
|
|
167
|
+
// Appending an empty value lets the backend treat them as an intentional clear.
|
|
168
|
+
if (!formData.has(name)) {
|
|
169
|
+
formData.append(name, '');
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function buildSubmitFormData(form: HTMLFormElement, action: FormAction): FormData {
|
|
175
|
+
const pages = getPages(form);
|
|
176
|
+
const currentPage = pages.find((page) => {
|
|
177
|
+
return !page.hasAttribute('data-formie-page-hidden');
|
|
178
|
+
}) || null;
|
|
179
|
+
|
|
180
|
+
if (!pages.length || !currentPage) {
|
|
181
|
+
const formData = new FormData(form);
|
|
182
|
+
formData.set('submitAction', action);
|
|
183
|
+
|
|
184
|
+
return formData;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Multi-page AJAX submits only send the current page plus root transport
|
|
188
|
+
// inputs so page transitions behave like the server-rendered workflow.
|
|
189
|
+
const formData = new FormData();
|
|
190
|
+
appendControlsFromRoot(formData, form);
|
|
191
|
+
const fieldNames = appendControlsFromPage(formData, currentPage);
|
|
192
|
+
appendMissingFieldClears(formData, fieldNames);
|
|
193
|
+
formData.set('submitAction', action);
|
|
194
|
+
|
|
195
|
+
return formData;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function isFinalSubmitAttempt(form: HTMLFormElement, action: FormAction): boolean {
|
|
199
|
+
if (action !== 'submit') {
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const pages = getPages(form);
|
|
204
|
+
|
|
205
|
+
if (!pages.length) {
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const currentPage = pages.find((page) => {
|
|
210
|
+
return !page.hasAttribute('data-formie-page-hidden');
|
|
211
|
+
}) || pages[pages.length - 1];
|
|
212
|
+
|
|
213
|
+
return currentPage === pages[pages.length - 1];
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export async function runSubmitPipeline(
|
|
217
|
+
form: HTMLFormElement,
|
|
218
|
+
action: FormAction,
|
|
219
|
+
bus: EventBus,
|
|
220
|
+
options: {
|
|
221
|
+
validator?: FormieValidator | null;
|
|
222
|
+
validateOnSubmit?: boolean;
|
|
223
|
+
preflightOnly?: boolean;
|
|
224
|
+
} = {},
|
|
225
|
+
): Promise<FormSubmitResult> {
|
|
226
|
+
debug.log('Starting submit pipeline.', {
|
|
227
|
+
action,
|
|
228
|
+
preflightOnly: options.preflightOnly === true,
|
|
229
|
+
});
|
|
230
|
+
let aborted = false;
|
|
231
|
+
let abortReason: string | undefined;
|
|
232
|
+
let dispatchResult: FormSubmitResult | null = null;
|
|
233
|
+
const finalSubmitAttempt = isFinalSubmitAttempt(form, action);
|
|
234
|
+
|
|
235
|
+
const context: SubmitPipelineContext = {
|
|
236
|
+
form,
|
|
237
|
+
action,
|
|
238
|
+
formData: buildSubmitFormData(form, action),
|
|
239
|
+
abort: (reason?: string) => {
|
|
240
|
+
aborted = true;
|
|
241
|
+
abortReason = reason;
|
|
242
|
+
debug.warn('Pipeline aborted.', { reason });
|
|
243
|
+
},
|
|
244
|
+
isAborted: () => aborted,
|
|
245
|
+
abortReason: () => abortReason,
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
const runners: Record<SubmitStage, StageRunner> = {
|
|
249
|
+
prepare: async(ctx) => {
|
|
250
|
+
const submitAction = ctx.form.querySelector('input[name="submitAction"]') as HTMLInputElement | null;
|
|
251
|
+
|
|
252
|
+
if (submitAction) {
|
|
253
|
+
submitAction.value = ctx.action;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
ctx.formData.set('submitAction', ctx.action);
|
|
257
|
+
return null;
|
|
258
|
+
},
|
|
259
|
+
normalize: async() => {
|
|
260
|
+
return null;
|
|
261
|
+
},
|
|
262
|
+
validate: async(ctx) => {
|
|
263
|
+
if (ctx.action !== 'submit') {
|
|
264
|
+
// Back/save actions bypass final validation so they can persist
|
|
265
|
+
// navigation intent without forcing the whole form valid.
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (options.validateOnSubmit === false) {
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (options.validator) {
|
|
274
|
+
const { scope, final } = getValidationScope(ctx.form);
|
|
275
|
+
const errors = options.validator.submit(final ? ctx.form : scope, { final });
|
|
276
|
+
|
|
277
|
+
if (errors.length > 0) {
|
|
278
|
+
errors[0]?.input.focus();
|
|
279
|
+
|
|
280
|
+
return {
|
|
281
|
+
ok: false,
|
|
282
|
+
stage: 'validate',
|
|
283
|
+
code: 'VALIDATION_FAILED',
|
|
284
|
+
message: options.validator.config.errorMessage || 'Validation failed.',
|
|
285
|
+
fieldErrors: options.validator.getFieldErrors(errors),
|
|
286
|
+
formErrors: [options.validator.config.errorMessage || 'Validation failed.'],
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (!ctx.form.checkValidity()) {
|
|
294
|
+
const invalidField = ctx.form.querySelector(':invalid') as HTMLElement | null;
|
|
295
|
+
invalidField?.focus();
|
|
296
|
+
|
|
297
|
+
return {
|
|
298
|
+
ok: false,
|
|
299
|
+
stage: 'validate',
|
|
300
|
+
code: 'VALIDATION_FAILED',
|
|
301
|
+
message: 'Validation failed.',
|
|
302
|
+
formErrors: ['Validation failed.'],
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return null;
|
|
307
|
+
},
|
|
308
|
+
screen: async() => {
|
|
309
|
+
return null;
|
|
310
|
+
},
|
|
311
|
+
authorize: async() => {
|
|
312
|
+
return null;
|
|
313
|
+
},
|
|
314
|
+
dispatch: async(ctx) => {
|
|
315
|
+
// Rehydrate just-in-time so provider hooks can mutate hidden inputs
|
|
316
|
+
// during `screen` / `authorize` and still be submitted.
|
|
317
|
+
ctx.formData = buildSubmitFormData(ctx.form, ctx.action);
|
|
318
|
+
const result = await submitForm(ctx.form, ctx.formData);
|
|
319
|
+
dispatchResult = result;
|
|
320
|
+
// Always return dispatch result so stage after-hooks can react to both
|
|
321
|
+
// success and failure outcomes (e.g. provider token/element resets).
|
|
322
|
+
return result;
|
|
323
|
+
},
|
|
324
|
+
finalize: async(resultCtx) => {
|
|
325
|
+
if (!dispatchResult) {
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Redirects happen after the dispatch response is normalized so the
|
|
330
|
+
// rest of the browser client can react to one result shape first.
|
|
331
|
+
if (dispatchResult.ok && dispatchResult.redirect?.url) {
|
|
332
|
+
if (dispatchResult.redirect.target === 'new-tab') {
|
|
333
|
+
window.open(dispatchResult.redirect.url, '_blank');
|
|
334
|
+
} else {
|
|
335
|
+
window.location.href = dispatchResult.redirect.url;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return null;
|
|
340
|
+
},
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
{
|
|
344
|
+
const emitReport = await bus.emitSafe('formie:submit:before', context);
|
|
345
|
+
if (emitReport.failed.length > 0) {
|
|
346
|
+
debug.warn('Submit before listeners failed.', {
|
|
347
|
+
eventName: emitReport.eventName,
|
|
348
|
+
failed: emitReport.failed.length,
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
if (finalSubmitAttempt) {
|
|
354
|
+
const emitReport = await bus.emitSafe('formie:submit:final:before', context);
|
|
355
|
+
if (emitReport.failed.length > 0) {
|
|
356
|
+
debug.warn('Final submit before listeners failed.', {
|
|
357
|
+
eventName: emitReport.eventName,
|
|
358
|
+
failed: emitReport.failed.length,
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const stages = options.preflightOnly ? PREFLIGHT_STAGES : STAGES;
|
|
364
|
+
|
|
365
|
+
for (const stage of stages) {
|
|
366
|
+
debug.log('Stage start.', { stage, action });
|
|
367
|
+
if (aborted) {
|
|
368
|
+
debug.warn('Stage skipped due to abort.', { stage, reason: abortReason });
|
|
369
|
+
return getAbortedResult(stage, abortReason);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
{
|
|
373
|
+
const emitReport = await bus.emitSafe(`formie:stage:${stage}:before`, {
|
|
374
|
+
...context,
|
|
375
|
+
stage,
|
|
376
|
+
});
|
|
377
|
+
if (emitReport.failed.length > 0) {
|
|
378
|
+
debug.warn('Stage before listeners failed.', {
|
|
379
|
+
stage,
|
|
380
|
+
failed: emitReport.failed.length,
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (aborted) {
|
|
386
|
+
const abortedResult = getAbortedResult(stage, abortReason);
|
|
387
|
+
{
|
|
388
|
+
const emitReport = await bus.emitSafe('formie:submit:after', abortedResult);
|
|
389
|
+
if (emitReport.failed.length > 0) {
|
|
390
|
+
debug.warn('Submit after listeners failed (abort before stage).', {
|
|
391
|
+
stage,
|
|
392
|
+
failed: emitReport.failed.length,
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
if (finalSubmitAttempt) {
|
|
397
|
+
const emitReport = await bus.emitSafe('formie:submit:final:after', abortedResult);
|
|
398
|
+
if (emitReport.failed.length > 0) {
|
|
399
|
+
debug.warn('Final submit after listeners failed (abort before stage).', {
|
|
400
|
+
stage,
|
|
401
|
+
failed: emitReport.failed.length,
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
debug.warn('Aborted after stage before-hooks.', { stage, reason: abortReason });
|
|
406
|
+
return abortedResult;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
const stageResult = await runners[stage](context);
|
|
410
|
+
debug.log('Stage runner complete.', {
|
|
411
|
+
stage,
|
|
412
|
+
hasResult: !!stageResult,
|
|
413
|
+
ok: stageResult ? stageResult.ok : undefined,
|
|
414
|
+
code: stageResult?.code,
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
{
|
|
418
|
+
const emitReport = await bus.emitSafe(`formie:stage:${stage}:after`, {
|
|
419
|
+
...context,
|
|
420
|
+
stage,
|
|
421
|
+
result: stageResult,
|
|
422
|
+
});
|
|
423
|
+
if (emitReport.failed.length > 0) {
|
|
424
|
+
debug.warn('Stage after listeners failed.', {
|
|
425
|
+
stage,
|
|
426
|
+
failed: emitReport.failed.length,
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
if (aborted) {
|
|
432
|
+
const abortedResult = getAbortedResult(stage, abortReason);
|
|
433
|
+
{
|
|
434
|
+
const emitReport = await bus.emitSafe('formie:submit:after', abortedResult);
|
|
435
|
+
if (emitReport.failed.length > 0) {
|
|
436
|
+
debug.warn('Submit after listeners failed (abort after stage).', {
|
|
437
|
+
stage,
|
|
438
|
+
failed: emitReport.failed.length,
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
if (finalSubmitAttempt) {
|
|
443
|
+
const emitReport = await bus.emitSafe('formie:submit:final:after', abortedResult);
|
|
444
|
+
if (emitReport.failed.length > 0) {
|
|
445
|
+
debug.warn('Final submit after listeners failed (abort after stage).', {
|
|
446
|
+
stage,
|
|
447
|
+
failed: emitReport.failed.length,
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
debug.warn('Aborted after stage after-hooks.', { stage, reason: abortReason });
|
|
452
|
+
return abortedResult;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// The first failing stage short-circuits the pipeline but still emits the
|
|
456
|
+
// matching stage after-hook so modules can clean up their own state.
|
|
457
|
+
if (stageResult && !stageResult.ok) {
|
|
458
|
+
{
|
|
459
|
+
const emitReport = await bus.emitSafe('formie:submit:after', stageResult);
|
|
460
|
+
if (emitReport.failed.length > 0) {
|
|
461
|
+
debug.warn('Submit after listeners failed (failed stage).', {
|
|
462
|
+
stage,
|
|
463
|
+
failed: emitReport.failed.length,
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
if (finalSubmitAttempt) {
|
|
468
|
+
const emitReport = await bus.emitSafe('formie:submit:final:after', stageResult);
|
|
469
|
+
if (emitReport.failed.length > 0) {
|
|
470
|
+
debug.warn('Final submit after listeners failed (failed stage).', {
|
|
471
|
+
stage,
|
|
472
|
+
failed: emitReport.failed.length,
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
debug.warn('Pipeline short-circuited by failed stage.', {
|
|
477
|
+
stage,
|
|
478
|
+
code: stageResult.code,
|
|
479
|
+
message: stageResult.message,
|
|
480
|
+
});
|
|
481
|
+
return stageResult;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
const successResult: FormSubmitResult = dispatchResult || {
|
|
486
|
+
ok: true,
|
|
487
|
+
stage: options.preflightOnly ? 'authorize' : 'finalize',
|
|
488
|
+
message: options.preflightOnly ? 'Submission preflight completed.' : 'Submission completed.',
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
{
|
|
492
|
+
const emitReport = await bus.emitSafe('formie:submit:after', successResult);
|
|
493
|
+
if (emitReport.failed.length > 0) {
|
|
494
|
+
debug.warn('Submit after listeners failed (success).', {
|
|
495
|
+
failed: emitReport.failed.length,
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
if (finalSubmitAttempt) {
|
|
500
|
+
const emitReport = await bus.emitSafe('formie:submit:final:after', successResult);
|
|
501
|
+
if (emitReport.failed.length > 0) {
|
|
502
|
+
debug.warn('Final submit after listeners failed (success).', {
|
|
503
|
+
failed: emitReport.failed.length,
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
debug.log('Pipeline completed.', {
|
|
508
|
+
ok: successResult.ok,
|
|
509
|
+
stage: successResult.stage,
|
|
510
|
+
code: successResult.code,
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
return successResult;
|
|
514
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { ThemeClassMap } from '#contracts/theme';
|
|
2
|
+
|
|
3
|
+
type NormalizedThemeClassMap = Record<string, string[]>;
|
|
4
|
+
|
|
5
|
+
const themeRegistry = new WeakMap<Element, NormalizedThemeClassMap>();
|
|
6
|
+
const THEME_ROOT_SELECTORS = '[data-formie-form], [data-formie], form';
|
|
7
|
+
|
|
8
|
+
function splitClasses(value: string[] | string | null | undefined): string[] {
|
|
9
|
+
if (!value) {
|
|
10
|
+
return [];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const parts = Array.isArray(value) ? value : [value];
|
|
14
|
+
|
|
15
|
+
return parts
|
|
16
|
+
.flatMap((item) => {
|
|
17
|
+
return String(item).split(/\s+/);
|
|
18
|
+
})
|
|
19
|
+
.map((item) => {
|
|
20
|
+
return item.trim();
|
|
21
|
+
})
|
|
22
|
+
.filter(Boolean);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function uniqueClasses(classes: string[]): string[] {
|
|
26
|
+
return Array.from(new Set(classes));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function resolveThemeClassMap(source: Element | null): NormalizedThemeClassMap {
|
|
30
|
+
if (!source) {
|
|
31
|
+
return {};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const directMatch = themeRegistry.get(source);
|
|
35
|
+
if (directMatch) {
|
|
36
|
+
return directMatch;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Most browser helpers only know the current field/page node, so theme lookup
|
|
40
|
+
// walks back to the registered form root and reuses its flat class map.
|
|
41
|
+
const root = source.closest(THEME_ROOT_SELECTORS);
|
|
42
|
+
if (!root) {
|
|
43
|
+
return {};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return themeRegistry.get(root) || {};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function normalizeThemeClassMap(theme?: ThemeClassMap | null): NormalizedThemeClassMap {
|
|
50
|
+
const normalized: NormalizedThemeClassMap = {};
|
|
51
|
+
|
|
52
|
+
Object.entries(theme || {}).forEach(([key, value]) => {
|
|
53
|
+
const classes = uniqueClasses(splitClasses(value));
|
|
54
|
+
|
|
55
|
+
if (classes.length) {
|
|
56
|
+
normalized[key] = classes;
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
return normalized;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function registerThemeClassMap(target: Element, theme?: ThemeClassMap | null, form?: HTMLFormElement | null): NormalizedThemeClassMap {
|
|
64
|
+
const normalized = normalizeThemeClassMap(theme);
|
|
65
|
+
const resolvedForm = form || (target instanceof HTMLFormElement ? target : target.querySelector('form'));
|
|
66
|
+
|
|
67
|
+
// Store the same normalized map against both the mount target and the actual
|
|
68
|
+
// form element so browser helpers can resolve classes from either surface.
|
|
69
|
+
themeRegistry.set(target, normalized);
|
|
70
|
+
|
|
71
|
+
if (resolvedForm) {
|
|
72
|
+
themeRegistry.set(resolvedForm, normalized);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return normalized;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function getThemeClasses(source: Element | null, key: string): string[] {
|
|
79
|
+
return resolveThemeClassMap(source)[key] || [];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function addThemeClasses(target: Element, source: Element | null, ...keys: string[]): void {
|
|
83
|
+
const classes = uniqueClasses(keys.flatMap((key) => {
|
|
84
|
+
return getThemeClasses(source, key);
|
|
85
|
+
}));
|
|
86
|
+
|
|
87
|
+
if (classes.length) {
|
|
88
|
+
target.classList.add(...classes);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function removeThemeClasses(target: Element, source: Element | null, ...keys: string[]): void {
|
|
93
|
+
const classes = uniqueClasses(keys.flatMap((key) => {
|
|
94
|
+
return getThemeClasses(source, key);
|
|
95
|
+
}));
|
|
96
|
+
|
|
97
|
+
if (classes.length) {
|
|
98
|
+
target.classList.remove(...classes);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function toggleThemeClasses(target: Element, source: Element | null, key: string, enabled: boolean): void {
|
|
103
|
+
getThemeClasses(source, key).forEach((className) => {
|
|
104
|
+
target.classList.toggle(className, enabled);
|
|
105
|
+
});
|
|
106
|
+
}
|