@verbb/formie-browser 1.0.3 → 1.0.5
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 +65 -17
- package/dist/chunks/address-country-Rx6GQTND.js +68 -0
- package/dist/chunks/address-finder-yXU5yMjG.js +30 -0
- package/dist/chunks/address-state-BQ0xGV9n.js +344 -0
- package/dist/chunks/api-CmwLRq_n.js +780 -0
- package/dist/chunks/api-DMK8NSUI.js +407 -0
- package/dist/chunks/api-sPqGbOww.js +125 -0
- package/dist/chunks/async-nPFRNQ06.js +25 -0
- package/dist/chunks/bpoint-DSjqRv63.js +24 -0
- package/dist/chunks/calculations-CgVJcQ2P.js +299 -0
- package/dist/chunks/captcha-eu-CWJb64_j.js +31 -0
- package/dist/chunks/checkbox-radio-DQ0H67Tj.js +125 -0
- package/dist/chunks/chunk-3b4jIN3o.js +13 -0
- package/dist/chunks/combobox-D-2b42wn.js +1954 -0
- package/dist/chunks/conditions-CZ3FU5QO.js +412 -0
- package/dist/chunks/constants-DVcJAvc5.js +38 -0
- package/dist/chunks/country-from-ip-BwxKaBuJ.js +26 -0
- package/dist/chunks/custom-google-maps-BsaSirEZ.js +194 -0
- package/dist/chunks/custom-link-CJ1-FjEM.js +46 -0
- package/dist/chunks/custom-maps-DYW_pBid.js +161 -0
- package/dist/chunks/date-picker-5CA_-zGb.js +5311 -0
- package/dist/chunks/debug-BV0DvdHx.js +41 -0
- package/dist/chunks/dist-BF5GU3_9.js +2674 -0
- package/dist/chunks/event-names-BCI2FLD8.js +51 -0
- package/dist/chunks/eway-D3ctTbEk.js +70 -0
- package/dist/chunks/field-references.keys-58ZSTrCW.js +21 -0
- package/dist/chunks/field-references.resolver-CHwn0G0L.js +145 -0
- package/dist/chunks/file-upload-D49m8-DR.js +287 -0
- package/dist/chunks/friendly-captcha-v1-ByXzENYZ.js +31 -0
- package/dist/chunks/friendly-captcha-v2-BPdlmhQu.js +36 -0
- package/dist/chunks/friendly-challenge-8uPatWqk.js +832 -0
- package/dist/chunks/go-cardless-BwASSYSK.js +23 -0
- package/dist/chunks/google-address-OhKilPWE.js +161 -0
- package/dist/chunks/hcaptcha-CdCd9oEi.js +54 -0
- package/dist/chunks/hidden-D7_Ch-QN.js +26 -0
- package/dist/chunks/http-D-JExro7.js +27 -0
- package/dist/chunks/i18n-BY1ds1BL.js +121 -0
- package/dist/chunks/leaflet-src-j-lHNmhR.js +4585 -0
- package/dist/chunks/loqate-Cp2zvwpE.js +76 -0
- package/dist/chunks/mollie-COG-ko2D.js +23 -0
- package/dist/chunks/moneris-CMH8PlRc.js +117 -0
- package/dist/chunks/opayo-D2jsR5vh.js +113 -0
- package/dist/chunks/paddle-DxF88RfC.js +55 -0
- package/dist/chunks/paypal-b5pnwrA2.js +95 -0
- package/dist/chunks/payway-BJYu9DIR.js +55 -0
- package/dist/chunks/phone-country-D3ayr60L.js +2645 -0
- package/dist/chunks/place-kit-BGHklIZ-.js +48 -0
- package/dist/chunks/placekit-autocomplete.esm-DWVabQlq.js +1236 -0
- package/dist/chunks/recaptcha-enterprise-BSwi8IVX.js +65 -0
- package/dist/chunks/recaptcha-shared-B4zAescW.js +15 -0
- package/dist/chunks/recaptcha-v2-checkbox-CnDQmsKa.js +40 -0
- package/dist/chunks/recaptcha-v2-invisible-Cz5uIlp-.js +53 -0
- package/dist/chunks/recaptcha-v3-BtbbP111.js +27 -0
- package/dist/chunks/repeater-B5leVxZU.js +102 -0
- package/dist/chunks/rich-text-Cv8ADyk-.js +349 -0
- package/dist/chunks/scripts-6CYSUGKQ.js +24 -0
- package/dist/chunks/sdk-BhHAYgga.js +1397 -0
- package/dist/chunks/shared-Bx9s0i0P.js +100 -0
- package/dist/chunks/signature-CpgqHCEx.js +463 -0
- package/dist/chunks/snaptcha-vz1RnZ15.js +8 -0
- package/dist/chunks/square-BP8RWAKB.js +40 -0
- package/dist/chunks/stripe-MihN63uC.js +184 -0
- package/dist/chunks/styles-BfoIZwJp.js +19 -0
- package/dist/chunks/summary-D3AjxpYN.js +114 -0
- package/dist/chunks/table-C-lkQN6I.js +78 -0
- package/dist/chunks/text-limit-B09elPDB.js +125 -0
- package/dist/chunks/theme-classes-Tv7q7ToE.js +44 -0
- package/dist/chunks/turnstile-D_Pi1CKM.js +58 -0
- package/dist/chunks/utils-Vqp8i_RM.js +49401 -0
- package/dist/css/formie-theme.css +2 -0
- package/dist/css/theme/fields/_address-state.css +94 -0
- package/dist/css/theme/fields/_combobox.css +246 -0
- package/dist/css/theme/fields/_select.css +13 -0
- package/dist/index.js +2447 -39
- package/dist/js/core/create-formie-client.d.ts.map +1 -1
- package/dist/js/core/field-error-container.d.ts +4 -0
- package/dist/js/core/field-error-container.d.ts.map +1 -0
- package/dist/js/core/submit-result-state.d.ts.map +1 -1
- package/dist/js/core/submit-result-ui.d.ts.map +1 -1
- package/dist/js/core/validation-focus.d.ts +4 -0
- package/dist/js/core/validation-focus.d.ts.map +1 -0
- package/dist/js/modules/address/api.d.ts +1 -0
- package/dist/js/modules/address/api.d.ts.map +1 -1
- package/dist/js/modules/address/constants.d.ts +22 -1
- package/dist/js/modules/address/constants.d.ts.map +1 -1
- package/dist/js/modules/address/host.d.ts +2 -2
- package/dist/js/modules/address/host.d.ts.map +1 -1
- package/dist/js/modules/address/loqate.d.ts.map +1 -1
- package/dist/js/modules/fields/address-country.d.ts +3 -0
- package/dist/js/modules/fields/address-country.d.ts.map +1 -0
- package/dist/js/modules/fields/address-state.d.ts +3 -0
- package/dist/js/modules/fields/address-state.d.ts.map +1 -0
- package/dist/js/modules/fields/calculations.d.ts.map +1 -1
- package/dist/js/modules/fields/checkbox-radio.d.ts.map +1 -1
- package/dist/js/modules/fields/combobox.d.ts +17 -0
- package/dist/js/modules/fields/combobox.d.ts.map +1 -0
- package/dist/js/modules/fields/custom-google-maps.d.ts +64 -0
- package/dist/js/modules/fields/custom-google-maps.d.ts.map +1 -0
- package/dist/js/modules/fields/custom-link.d.ts +3 -0
- package/dist/js/modules/fields/custom-link.d.ts.map +1 -0
- package/dist/js/modules/fields/custom-maps.d.ts +3 -0
- package/dist/js/modules/fields/custom-maps.d.ts.map +1 -0
- package/dist/js/modules/fields/date-picker.d.ts.map +1 -1
- package/dist/js/modules/fields/file-upload.d.ts.map +1 -1
- package/dist/js/modules/fields/index.d.ts.map +1 -1
- package/dist/js/modules/fields/phone-country.d.ts.map +1 -1
- package/dist/js/modules/fields/text-limit.d.ts.map +1 -1
- package/dist/js/submit/pipeline.d.ts.map +1 -1
- package/dist/js/utils/country-from-ip.d.ts +7 -0
- package/dist/js/utils/country-from-ip.d.ts.map +1 -0
- package/dist/js/utils/field-references.d.ts +1 -0
- package/dist/js/utils/field-references.d.ts.map +1 -1
- package/dist/js/utils/field-references.row-scope.d.ts +11 -0
- package/dist/js/utils/field-references.row-scope.d.ts.map +1 -0
- package/dist/js/utils/i18n.d.ts.map +1 -1
- package/dist/js/validation/rules/email.d.ts.map +1 -1
- package/dist/js/validation/rules/number.d.ts.map +1 -1
- package/dist/js/validation/validator.d.ts.map +1 -1
- package/package.json +6 -3
- package/src/css/formie-theme.css +2 -0
- package/src/css/theme/fields/_address-state.css +94 -0
- package/src/css/theme/fields/_combobox.css +246 -0
- package/src/css/theme/fields/_select.css +13 -0
- package/src/js/core/create-formie-client.ts +27 -0
- package/src/js/core/field-error-container.ts +39 -0
- package/src/js/core/submit-result-state.ts +12 -2
- package/src/js/core/submit-result-ui.ts +7 -13
- package/src/js/core/validation-focus.ts +117 -0
- package/src/js/modules/address/api.ts +7 -0
- package/src/js/modules/address/constants.ts +82 -2
- package/src/js/modules/address/host.ts +16 -6
- package/src/js/modules/address/loqate.ts +3 -17
- package/src/js/modules/fields/address-country.ts +156 -0
- package/src/js/modules/fields/address-state.ts +946 -0
- package/src/js/modules/fields/calculations.ts +32 -0
- package/src/js/modules/fields/checkbox-radio.ts +21 -15
- package/src/js/modules/fields/combobox.ts +188 -0
- package/src/js/modules/fields/custom-google-maps.ts +416 -0
- package/src/js/modules/fields/custom-link.ts +95 -0
- package/src/js/modules/fields/custom-maps.ts +339 -0
- package/src/js/modules/fields/date-picker.ts +96 -3
- package/src/js/modules/fields/file-upload.ts +12 -9
- package/src/js/modules/fields/index.ts +6 -0
- package/src/js/modules/fields/phone-country.ts +6 -0
- package/src/js/modules/fields/text-limit.ts +87 -22
- package/src/js/submit/pipeline.ts +11 -1
- package/src/js/utils/country-from-ip.ts +54 -0
- package/src/js/utils/field-references.row-scope.ts +303 -0
- package/src/js/utils/field-references.ts +1 -0
- package/src/js/utils/i18n.ts +184 -5
- package/src/js/validation/rules/email.ts +3 -2
- package/src/js/validation/rules/match.ts +2 -2
- package/src/js/validation/rules/minmax.ts +4 -4
- package/src/js/validation/rules/number.ts +9 -5
- package/src/js/validation/rules/pattern.ts +4 -4
- package/src/js/validation/rules/required.ts +1 -1
- package/src/js/validation/rules/url.ts +1 -1
- package/src/js/validation/validator.ts +7 -7
- package/dist/chunks/address-finder-BjMuEiwF.js +0 -37
- package/dist/chunks/bpoint-KudsBCo2.js +0 -26
- package/dist/chunks/calculations-DlGSkQ3W.js +0 -147
- package/dist/chunks/captcha-eu-CterYFok.js +0 -34
- package/dist/chunks/checkbox-radio-CBvgk3hR.js +0 -136
- package/dist/chunks/conditions-DYy1-Hwt.js +0 -459
- package/dist/chunks/date-picker-BlD--zfe.js +0 -4994
- package/dist/chunks/eway-qwc-B5Us.js +0 -74
- package/dist/chunks/file-upload-CIgHrXfp.js +0 -316
- package/dist/chunks/friendly-captcha-v1-EDFac33c.js +0 -33
- package/dist/chunks/friendly-captcha-v2-BDpSvFGR.js +0 -38
- package/dist/chunks/go-cardless-DuDMVsnz.js +0 -24
- package/dist/chunks/google-address-Bmjp01pH.js +0 -181
- package/dist/chunks/hcaptcha-BTQ6An6g.js +0 -56
- package/dist/chunks/hidden-DbPdOxKb.js +0 -31
- package/dist/chunks/index-BEsfee-D.js +0 -1839
- package/dist/chunks/index-BP7Unm5Y.js +0 -863
- package/dist/chunks/index-BcqwpPNE.js +0 -4314
- package/dist/chunks/loqate-BdNGv93o.js +0 -55
- package/dist/chunks/mollie-DFOjTuGX.js +0 -24
- package/dist/chunks/moneris-BbFfl-EL.js +0 -101
- package/dist/chunks/opayo-CmgYa9ya.js +0 -122
- package/dist/chunks/paddle-BUi7w1_o.js +0 -60
- package/dist/chunks/paypal-A-ePfh6k.js +0 -100
- package/dist/chunks/payway-BqFCbhyo.js +0 -56
- package/dist/chunks/phone-country-DPMiqk4L.js +0 -3765
- package/dist/chunks/place-kit-CX7tamAg.js +0 -42
- package/dist/chunks/placekit-autocomplete.esm-LAwfbPZl.js +0 -1299
- package/dist/chunks/recaptcha-enterprise-DxF6cW95.js +0 -71
- package/dist/chunks/recaptcha-shared-DhGcbiaq.js +0 -15
- package/dist/chunks/recaptcha-v2-checkbox-R9EfbZ4k.js +0 -41
- package/dist/chunks/recaptcha-v2-invisible-DV9hswAp.js +0 -59
- package/dist/chunks/recaptcha-v3-V0xc-Edh.js +0 -28
- package/dist/chunks/repeater-DKUT6TGI.js +0 -124
- package/dist/chunks/rich-text-SH7KiaKH.js +0 -304
- package/dist/chunks/scripts-D9N2d5rN.js +0 -36
- package/dist/chunks/sdk-3SicTWby.js +0 -1559
- package/dist/chunks/shared-BmntPmnW.js +0 -80
- package/dist/chunks/signature-BA3tQsGT.js +0 -550
- package/dist/chunks/snaptcha-DV7p6J9k.js +0 -8
- package/dist/chunks/square-Bs-ndqYK.js +0 -46
- package/dist/chunks/stripe-DkZAHxtn.js +0 -202
- package/dist/chunks/styles-C3aqgtek.js +0 -21
- package/dist/chunks/summary-Dq2i9TQk.js +0 -126
- package/dist/chunks/table-Cu4WfVcw.js +0 -95
- package/dist/chunks/text-limit-2ycmB-Ae.js +0 -135
- package/dist/chunks/turnstile-CId90tRr.js +0 -59
- package/dist/chunks/utils-BntI3W4S.js +0 -6149
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Combobox styles are intentionally unlayered. The combobox module injects this
|
|
3
|
+
* sheet at runtime, and unlayered third-party CSS would otherwise win over
|
|
4
|
+
* @layer formie-theme rules.
|
|
5
|
+
*
|
|
6
|
+
* Tom Select default CSS is not imported; these rules provide the minimum
|
|
7
|
+
* structure plus Formie theme styling for searchable dropdowns.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
.formie-field .ts-wrapper.formie-combobox {
|
|
11
|
+
width: 100%;
|
|
12
|
+
display: block;
|
|
13
|
+
position: relative;
|
|
14
|
+
min-height: 0;
|
|
15
|
+
border: 0;
|
|
16
|
+
padding: 0;
|
|
17
|
+
background: none;
|
|
18
|
+
box-shadow: none;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.formie-field select[data-formie-combobox-input].tomselected,
|
|
22
|
+
.formie-field select[data-formie-combobox-input].ts-hidden-accessible {
|
|
23
|
+
display: none !important;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.formie-field .ts-wrapper.formie-combobox .ts-control {
|
|
27
|
+
box-sizing: border-box;
|
|
28
|
+
display: flex;
|
|
29
|
+
flex-wrap: wrap;
|
|
30
|
+
align-items: center;
|
|
31
|
+
position: relative;
|
|
32
|
+
overflow: hidden;
|
|
33
|
+
z-index: 1;
|
|
34
|
+
width: 100%;
|
|
35
|
+
border: var(--formie-border-width) solid var(--formie-color-border);
|
|
36
|
+
border-radius: var(--formie-radius-sm);
|
|
37
|
+
background-color: var(--formie-color-surface);
|
|
38
|
+
background-image: none;
|
|
39
|
+
min-height: var(--formie-control-height);
|
|
40
|
+
padding: calc(var(--formie-control-padding-y) - 1px) var(--formie-control-padding-x);
|
|
41
|
+
box-shadow: none;
|
|
42
|
+
font-size: var(--formie-control-font-size);
|
|
43
|
+
line-height: var(--formie-line-height-tight);
|
|
44
|
+
color: var(--formie-color-text);
|
|
45
|
+
transition: border-color 150ms ease, box-shadow 150ms ease, background-color 150ms ease;
|
|
46
|
+
gap: var(--formie-space-1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.formie-field .ts-wrapper.formie-combobox.single .ts-control {
|
|
50
|
+
--ts-pr-min: var(--formie-control-padding-x);
|
|
51
|
+
--ts-pr-caret: calc(var(--formie-select-indicator-size) + var(--formie-space-1));
|
|
52
|
+
padding-right: calc(var(--formie-control-padding-x) + var(--formie-select-indicator-size) + var(--formie-space-2)) !important;
|
|
53
|
+
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M7 7l3-3 3 3m0 6l-3 3-3-3' stroke='%239CA3AF' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
|
|
54
|
+
background-position: right var(--formie-space-2) center;
|
|
55
|
+
background-repeat: no-repeat;
|
|
56
|
+
background-size: var(--formie-select-indicator-size) var(--formie-select-indicator-size);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.formie-field .ts-wrapper.formie-combobox.single .ts-control::after {
|
|
60
|
+
display: none;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.formie-field .ts-wrapper.formie-combobox.multi .ts-control {
|
|
64
|
+
padding: calc(var(--formie-control-padding-y) - 2px) var(--formie-control-padding-x) calc(var(--formie-control-padding-y) - 4px);
|
|
65
|
+
--ts-pr-min: var(--formie-control-padding-x);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.formie-field .ts-wrapper.formie-combobox.multi.has-items .ts-control {
|
|
69
|
+
padding-left: var(--formie-control-padding-x);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.formie-field .ts-wrapper.formie-combobox .ts-control > input {
|
|
73
|
+
flex: 1 1 auto;
|
|
74
|
+
min-width: 7rem;
|
|
75
|
+
max-width: 100%;
|
|
76
|
+
margin: 0 !important;
|
|
77
|
+
padding: 0 !important;
|
|
78
|
+
min-height: 0 !important;
|
|
79
|
+
max-height: none !important;
|
|
80
|
+
border: 0 !important;
|
|
81
|
+
background: none !important;
|
|
82
|
+
box-shadow: none !important;
|
|
83
|
+
color: var(--formie-color-text);
|
|
84
|
+
font: inherit;
|
|
85
|
+
font-size: var(--formie-control-font-size);
|
|
86
|
+
line-height: inherit;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.formie-field .ts-wrapper.formie-combobox .ts-control > input:focus {
|
|
90
|
+
outline: none !important;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.formie-field .ts-wrapper.formie-combobox.has-items .ts-control > input {
|
|
94
|
+
margin: 0 var(--formie-space-1) !important;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.formie-field .ts-wrapper.formie-combobox.input-hidden .ts-control > input {
|
|
98
|
+
opacity: 0;
|
|
99
|
+
position: absolute;
|
|
100
|
+
left: -10000px;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.formie-field .ts-wrapper.formie-combobox.single .ts-control,
|
|
104
|
+
.formie-field .ts-wrapper.formie-combobox.single .ts-control > input {
|
|
105
|
+
cursor: pointer;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.formie-field .ts-wrapper.formie-combobox.single.input-active .ts-control,
|
|
109
|
+
.formie-field .ts-wrapper.formie-combobox.single.input-active .ts-control > input {
|
|
110
|
+
cursor: text;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.formie-field .ts-wrapper.formie-combobox .ts-control .items-placeholder {
|
|
114
|
+
color: var(--formie-color-text-muted);
|
|
115
|
+
font: inherit;
|
|
116
|
+
font-size: var(--formie-control-font-size);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.formie-field .ts-wrapper.formie-combobox .ts-control > input::placeholder {
|
|
120
|
+
color: var(--formie-color-text-muted);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.formie-field .ts-wrapper.formie-combobox.focus .ts-control,
|
|
124
|
+
.formie-field .ts-wrapper.formie-combobox .ts-control:focus-within,
|
|
125
|
+
.formie-field .ts-wrapper.formie-combobox.dropdown-active .ts-control {
|
|
126
|
+
outline: 0;
|
|
127
|
+
border-color: var(--formie-color-focus-ring);
|
|
128
|
+
box-shadow: var(--formie-shadow-focus);
|
|
129
|
+
border-radius: var(--formie-radius-sm);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.formie-field-has-error .ts-wrapper.formie-combobox .ts-control {
|
|
133
|
+
border-color: var(--formie-color-danger);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.formie-field-has-error .ts-wrapper.formie-combobox.focus .ts-control,
|
|
137
|
+
.formie-field-has-error .ts-wrapper.formie-combobox .ts-control:focus-within,
|
|
138
|
+
.formie-field-has-error .ts-wrapper.formie-combobox.dropdown-active .ts-control {
|
|
139
|
+
border-color: var(--formie-color-danger);
|
|
140
|
+
box-shadow: var(--formie-shadow-danger-focus);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.formie-field .ts-wrapper.formie-combobox.multi .ts-control > .item,
|
|
144
|
+
.formie-field .ts-wrapper.formie-combobox.multi .ts-control [data-value] {
|
|
145
|
+
display: inline-flex;
|
|
146
|
+
align-items: center;
|
|
147
|
+
gap: var(--formie-space-1);
|
|
148
|
+
margin: 0 var(--formie-space-1) var(--formie-space-1) 0;
|
|
149
|
+
padding: 0 var(--formie-space-2);
|
|
150
|
+
background: var(--formie-color-surface-muted, rgba(15, 23, 42, 0.06));
|
|
151
|
+
background-image: none;
|
|
152
|
+
border: var(--formie-border-width) solid var(--formie-color-border);
|
|
153
|
+
border-radius: var(--formie-radius-sm);
|
|
154
|
+
box-shadow: none;
|
|
155
|
+
color: var(--formie-color-text);
|
|
156
|
+
text-shadow: none;
|
|
157
|
+
line-height: calc(var(--formie-control-height) - var(--formie-space-3));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.formie-field .ts-wrapper.formie-combobox.multi .ts-control > .item.active,
|
|
161
|
+
.formie-field .ts-wrapper.formie-combobox.multi .ts-control [data-value].active {
|
|
162
|
+
background: var(--formie-color-surface-muted, rgba(15, 23, 42, 0.06));
|
|
163
|
+
color: var(--formie-color-text);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.formie-field .ts-wrapper.formie-combobox.plugin-remove_button .item {
|
|
167
|
+
display: inline-flex;
|
|
168
|
+
align-items: center;
|
|
169
|
+
gap: var(--formie-space-1);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.formie-field .ts-wrapper.formie-combobox.plugin-remove_button:not(.rtl) .item {
|
|
173
|
+
padding-right: var(--formie-space-2) !important;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.formie-field .ts-wrapper.formie-combobox.plugin-remove_button .item .remove {
|
|
177
|
+
display: inline-flex;
|
|
178
|
+
align-items: center;
|
|
179
|
+
justify-content: center;
|
|
180
|
+
margin: 0;
|
|
181
|
+
padding: 0;
|
|
182
|
+
border: 0;
|
|
183
|
+
background: none;
|
|
184
|
+
box-shadow: none;
|
|
185
|
+
text-decoration: none;
|
|
186
|
+
color: var(--formie-color-text-muted);
|
|
187
|
+
font-size: 1.125em;
|
|
188
|
+
line-height: 1;
|
|
189
|
+
cursor: pointer;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.formie-field .ts-wrapper.formie-combobox.plugin-remove_button .item .remove:hover,
|
|
193
|
+
.formie-field .ts-wrapper.formie-combobox.plugin-remove_button .item .remove:focus {
|
|
194
|
+
background: none;
|
|
195
|
+
text-decoration: none;
|
|
196
|
+
color: var(--formie-color-text);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.formie-field .ts-wrapper.formie-combobox .ts-dropdown {
|
|
200
|
+
position: absolute;
|
|
201
|
+
top: 100%;
|
|
202
|
+
left: 0;
|
|
203
|
+
width: 100%;
|
|
204
|
+
z-index: var(--formie-z-popover, 30);
|
|
205
|
+
border: var(--formie-border-width) solid var(--formie-color-border);
|
|
206
|
+
border-radius: var(--formie-radius-sm);
|
|
207
|
+
background: var(--formie-color-surface);
|
|
208
|
+
box-shadow: var(--formie-shadow-popover, 0 8px 24px rgba(15, 23, 42, 0.12));
|
|
209
|
+
margin-top: var(--formie-space-1);
|
|
210
|
+
box-sizing: border-box;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.formie-field .ts-wrapper.formie-combobox .ts-dropdown-content {
|
|
214
|
+
overflow: hidden auto;
|
|
215
|
+
max-height: 200px;
|
|
216
|
+
scroll-behavior: smooth;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.formie-field .ts-wrapper.formie-combobox .ts-dropdown .option,
|
|
220
|
+
.formie-field .ts-wrapper.formie-combobox .ts-dropdown .optgroup-header,
|
|
221
|
+
.formie-field .ts-wrapper.formie-combobox .ts-dropdown .no-results {
|
|
222
|
+
color: var(--formie-color-text);
|
|
223
|
+
padding: var(--formie-space-2) var(--formie-control-padding-x);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.formie-field .ts-wrapper.formie-combobox .ts-dropdown [data-selectable] {
|
|
227
|
+
cursor: pointer;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.formie-field .ts-wrapper.formie-combobox .ts-dropdown .option.active,
|
|
231
|
+
.formie-field .ts-wrapper.formie-combobox .ts-dropdown .option:hover,
|
|
232
|
+
.formie-field .ts-wrapper.formie-combobox .ts-dropdown .active {
|
|
233
|
+
background: var(--formie-color-surface-muted, rgba(15, 23, 42, 0.05));
|
|
234
|
+
color: var(--formie-color-text);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.formie-field .ts-wrapper.formie-combobox .ts-dropdown .highlight {
|
|
238
|
+
background: rgba(59, 130, 246, 0.18);
|
|
239
|
+
border-radius: 2px;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.formie-field .ts-wrapper.formie-combobox.disabled .ts-control {
|
|
243
|
+
opacity: 0.6;
|
|
244
|
+
background-color: var(--formie-color-surface-muted, rgba(15, 23, 42, 0.04));
|
|
245
|
+
cursor: not-allowed;
|
|
246
|
+
}
|
|
@@ -34,4 +34,17 @@
|
|
|
34
34
|
border-color: var(--formie-color-danger);
|
|
35
35
|
box-shadow: var(--formie-shadow-danger-focus);
|
|
36
36
|
}
|
|
37
|
+
|
|
38
|
+
/* Tom Select copies native select classes onto its wrapper; keep combobox chrome on .ts-control only. */
|
|
39
|
+
.formie-field .ts-wrapper.formie-combobox,
|
|
40
|
+
.formie-field .ts-wrapper.formie-combobox.formie-select,
|
|
41
|
+
.formie-field .ts-wrapper.formie-combobox.formie-dropdown-input {
|
|
42
|
+
border: 0;
|
|
43
|
+
padding: 0;
|
|
44
|
+
min-height: 0;
|
|
45
|
+
background: none;
|
|
46
|
+
background-image: none;
|
|
47
|
+
box-shadow: none;
|
|
48
|
+
appearance: none;
|
|
49
|
+
}
|
|
37
50
|
}
|
|
@@ -13,6 +13,11 @@ import type { ThemeClassMap } from '#contracts/theme';
|
|
|
13
13
|
import { dispatchFormieDomEvent } from '#core/dom-events';
|
|
14
14
|
import { dispatchPageClientEventForSubmit } from '#core/page-client-event';
|
|
15
15
|
import { syncPageTabErrors } from '#core/page-tab-errors';
|
|
16
|
+
import {
|
|
17
|
+
enhanceServerRenderedFieldErrors,
|
|
18
|
+
focusFirstValidationError,
|
|
19
|
+
hasServerRenderedValidationErrors,
|
|
20
|
+
} from '#core/validation-focus';
|
|
16
21
|
import { clearSubmitFeedback, executeAjaxSubmitFlow, shouldKeepSubmitLoading } from '#core/submit-flow';
|
|
17
22
|
import { applySubmitResultUi } from '#core/submit-result-ui';
|
|
18
23
|
import { applyPageState, clearSubmitLoading, setSubmitLoading } from '#core/submit-result-state';
|
|
@@ -24,6 +29,7 @@ import { runSubmitPipeline } from '#submit/pipeline';
|
|
|
24
29
|
import { clearSubmissionOnUnload, requestGraphqlRender, requestRefreshTokens, requestRender, requestSetPage } from '#transport/forms-api';
|
|
25
30
|
import { createDebug } from '#utils/debug';
|
|
26
31
|
import { createFormUnloadWarningGuard } from '#utils/unload-warning';
|
|
32
|
+
import { getValidationScope } from '#validation/scope';
|
|
27
33
|
import { FormieValidator } from '#validation/validator';
|
|
28
34
|
import { bindSubmitReadiness } from '#validation/submit-readiness';
|
|
29
35
|
|
|
@@ -745,6 +751,22 @@ function bindFormEvents(
|
|
|
745
751
|
allowNativeSubmit = false;
|
|
746
752
|
clearInternalNavigation(form);
|
|
747
753
|
clearSubmitLoading(form);
|
|
754
|
+
|
|
755
|
+
if (validator && shouldValidateOnSubmit(form)) {
|
|
756
|
+
const { scope, final } = getValidationScope(form);
|
|
757
|
+
const validationErrors = validator.submit(final ? form : scope, { final });
|
|
758
|
+
|
|
759
|
+
if (validationErrors.length > 0) {
|
|
760
|
+
applySubmitResultUi(form, {
|
|
761
|
+
ok: false,
|
|
762
|
+
stage: 'validate',
|
|
763
|
+
code: 'VALIDATION_FAILED',
|
|
764
|
+
message: validator.config.errorMessage || 'Validation failed.',
|
|
765
|
+
fieldErrors: validator.getFieldErrors(validationErrors),
|
|
766
|
+
formErrors: [validator.config.errorMessage || 'Validation failed.'],
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
}
|
|
748
770
|
};
|
|
749
771
|
|
|
750
772
|
if (typeof form.requestSubmit === 'function') {
|
|
@@ -996,6 +1018,11 @@ export function createFormieClient(): FormieClient {
|
|
|
996
1018
|
normalizeHeadlessManagedUrls(target, form, normalizedOptions);
|
|
997
1019
|
}
|
|
998
1020
|
|
|
1021
|
+
if (normalizedOptions.mode === 'server-rendered' && hasServerRenderedValidationErrors(form)) {
|
|
1022
|
+
enhanceServerRenderedFieldErrors(form);
|
|
1023
|
+
focusFirstValidationError(form);
|
|
1024
|
+
}
|
|
1025
|
+
|
|
999
1026
|
syncPageTabErrors(form);
|
|
1000
1027
|
}
|
|
1001
1028
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export type FieldErrorPosition = 'above' | 'below';
|
|
2
|
+
|
|
3
|
+
export function getFieldErrorPosition(fieldNode: Element): FieldErrorPosition {
|
|
4
|
+
const layout = fieldNode.querySelector('[data-formie-field-layout]');
|
|
5
|
+
const position = layout?.getAttribute('data-formie-error-position')?.trim();
|
|
6
|
+
|
|
7
|
+
return position === 'above' ? 'above' : 'below';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function ensureFieldErrorContainer(
|
|
11
|
+
fieldNode: Element,
|
|
12
|
+
applyTheme?: (container: HTMLElement) => void,
|
|
13
|
+
): HTMLElement {
|
|
14
|
+
const existing = fieldNode.querySelector('[data-formie-field-errors]') as HTMLElement | null;
|
|
15
|
+
|
|
16
|
+
if (existing) {
|
|
17
|
+
return existing;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const content = fieldNode.querySelector('[data-formie-field-content]') as HTMLElement | null;
|
|
21
|
+
const control = fieldNode.querySelector('[data-formie-field-control]') as HTMLElement | null;
|
|
22
|
+
const position = getFieldErrorPosition(fieldNode);
|
|
23
|
+
const container = document.createElement('div');
|
|
24
|
+
|
|
25
|
+
container.setAttribute('data-formie-field-errors', 'true');
|
|
26
|
+
applyTheme?.(container);
|
|
27
|
+
|
|
28
|
+
if (content && control) {
|
|
29
|
+
if (position === 'above') {
|
|
30
|
+
content.insertBefore(container, control);
|
|
31
|
+
} else {
|
|
32
|
+
content.appendChild(container);
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
fieldNode.appendChild(container);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return container;
|
|
39
|
+
}
|
|
@@ -102,6 +102,16 @@ function getConfiguredSubmitAction(form: HTMLFormElement): string {
|
|
|
102
102
|
return (form.dataset.formieSubmitAction || '').trim();
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
function getResolvedSubmitAction(form: HTMLFormElement, result: FormSubmitResult): string {
|
|
106
|
+
const fromResponse = result.meta?.effectiveSubmitAction;
|
|
107
|
+
|
|
108
|
+
if (typeof fromResponse === 'string' && fromResponse.trim() !== '') {
|
|
109
|
+
return fromResponse.trim();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return getConfiguredSubmitAction(form);
|
|
113
|
+
}
|
|
114
|
+
|
|
105
115
|
function shouldHideFormOnSuccess(form: HTMLFormElement): boolean {
|
|
106
116
|
const rawValue = form.dataset.formieSubmitActionFormHide;
|
|
107
117
|
|
|
@@ -580,7 +590,7 @@ export function applySubmitResultState(form: HTMLFormElement, result: FormSubmit
|
|
|
580
590
|
}
|
|
581
591
|
|
|
582
592
|
if (action === 'submit' && !result.redirect?.url) {
|
|
583
|
-
const configuredSubmitAction =
|
|
593
|
+
const configuredSubmitAction = getResolvedSubmitAction(form, result);
|
|
584
594
|
const preserveHiddenState = configuredSubmitAction === 'message' && shouldHideFormOnSuccess(form);
|
|
585
595
|
|
|
586
596
|
if (configuredSubmitAction === 'reload') {
|
|
@@ -603,7 +613,7 @@ export function applySubmitResultState(form: HTMLFormElement, result: FormSubmit
|
|
|
603
613
|
}
|
|
604
614
|
|
|
605
615
|
if (action === 'submit' && result.redirect?.url && result.redirect.target === 'new-tab') {
|
|
606
|
-
const configuredSubmitAction =
|
|
616
|
+
const configuredSubmitAction = getResolvedSubmitAction(form, result);
|
|
607
617
|
const preserveHiddenState = configuredSubmitAction === 'message' && shouldHideFormOnSuccess(form);
|
|
608
618
|
clearPendingFinalSubmitReset(form);
|
|
609
619
|
resetSubmissionState(form, { preserveHiddenState });
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { FormSubmitResult } from '#contracts/schema';
|
|
2
|
+
import { ensureFieldErrorContainer as resolveFieldErrorContainer } from '#core/field-error-container';
|
|
2
3
|
import { syncPageTabErrors } from '#core/page-tab-errors';
|
|
4
|
+
import { focusFirstValidationError } from '#core/validation-focus';
|
|
3
5
|
import { setFormHiddenState } from '#core/submit-result-state';
|
|
4
6
|
import { addThemeClasses, removeThemeClasses } from '#theme/theme-classes';
|
|
5
7
|
|
|
@@ -150,16 +152,9 @@ function ensureFormSuccessContainer(form: HTMLFormElement, position: string): HT
|
|
|
150
152
|
}
|
|
151
153
|
|
|
152
154
|
function ensureFieldErrorContainer(fieldNode: Element): HTMLElement {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
if (!container) {
|
|
156
|
-
container = document.createElement('div');
|
|
157
|
-
container.setAttribute('data-formie-field-errors', 'true');
|
|
155
|
+
return resolveFieldErrorContainer(fieldNode, (container) => {
|
|
158
156
|
addThemeClasses(container, fieldNode, 'fieldErrors');
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
return container;
|
|
157
|
+
});
|
|
163
158
|
}
|
|
164
159
|
|
|
165
160
|
function removeDescribedBy(input: HTMLElement, describedById: string): void {
|
|
@@ -439,10 +434,9 @@ export function applySubmitResultUi(form: HTMLFormElement, result: FormSubmitRes
|
|
|
439
434
|
|
|
440
435
|
if (result.formErrors?.length) {
|
|
441
436
|
renderFormErrors(form, result.formErrors);
|
|
442
|
-
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
if (!result.fieldErrors && result.message) {
|
|
437
|
+
} else if (!result.fieldErrors && result.message) {
|
|
446
438
|
renderFormErrors(form, [result.message]);
|
|
447
439
|
}
|
|
440
|
+
|
|
441
|
+
focusFirstValidationError(form);
|
|
448
442
|
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { addThemeClasses } from '#theme/theme-classes';
|
|
2
|
+
|
|
3
|
+
function appendDescribedBy(input: HTMLElement, describedById: string): void {
|
|
4
|
+
const current = (input.getAttribute('aria-describedby') || '').trim();
|
|
5
|
+
const items = current ? current.split(/\s+/) : [];
|
|
6
|
+
|
|
7
|
+
if (!items.includes(describedById)) {
|
|
8
|
+
items.push(describedById);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
input.setAttribute('aria-describedby', items.join(' ').trim());
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function getFirstErroredField(form: HTMLFormElement): HTMLElement | null {
|
|
15
|
+
const fields = Array.from(form.querySelectorAll('[data-formie-field-handle]')) as HTMLElement[];
|
|
16
|
+
|
|
17
|
+
return fields.find((field) => {
|
|
18
|
+
if (field.getAttribute('data-formie-field-has-error') === 'true') {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return field.querySelector('[data-formie-field-error]') !== null;
|
|
23
|
+
}) || null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function getFieldFocusTarget(field: HTMLElement): HTMLElement | null {
|
|
27
|
+
const invalidControl = field.querySelector('[aria-invalid="true"]') as HTMLElement | null;
|
|
28
|
+
|
|
29
|
+
if (invalidControl) {
|
|
30
|
+
return invalidControl;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return field.querySelector(
|
|
34
|
+
'input:not([type="hidden"]):not([disabled]), select:not([disabled]), textarea:not([disabled])',
|
|
35
|
+
) as HTMLElement | null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function getFormLevelErrorTarget(form: HTMLFormElement): HTMLElement | null {
|
|
39
|
+
return form.querySelector(
|
|
40
|
+
'[data-formie-message-error], [data-formie-error-container], [data-formie-errors]',
|
|
41
|
+
) as HTMLElement | null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function enhanceServerRenderedFieldErrors(form: HTMLFormElement): void {
|
|
45
|
+
form.querySelectorAll('[data-formie-field-handle]').forEach((fieldNode) => {
|
|
46
|
+
const field = fieldNode as HTMLElement;
|
|
47
|
+
const hasServerError = field.getAttribute('data-formie-field-has-error') === 'true'
|
|
48
|
+
|| field.querySelector('[data-formie-field-error]') !== null;
|
|
49
|
+
|
|
50
|
+
if (!hasServerError) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
field.setAttribute('data-formie-field-has-error', 'true');
|
|
55
|
+
addThemeClasses(field, form, 'fieldLayoutError');
|
|
56
|
+
|
|
57
|
+
const errorContainer = field.querySelector('[data-formie-field-errors]') as HTMLElement | null;
|
|
58
|
+
const errorContainerId = errorContainer?.id || '';
|
|
59
|
+
const primaryError = field.querySelector('[data-formie-field-error]') as HTMLElement | null;
|
|
60
|
+
const primaryErrorId = primaryError?.id || '';
|
|
61
|
+
|
|
62
|
+
field.querySelectorAll('input, select, textarea').forEach((input) => {
|
|
63
|
+
const element = input as HTMLElement;
|
|
64
|
+
element.setAttribute('aria-invalid', 'true');
|
|
65
|
+
addThemeClasses(element, form, 'fieldControlError');
|
|
66
|
+
element.setAttribute('data-formie-input-has-error', 'true');
|
|
67
|
+
|
|
68
|
+
if (errorContainerId) {
|
|
69
|
+
appendDescribedBy(element, errorContainerId);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (primaryErrorId) {
|
|
73
|
+
element.setAttribute('aria-errormessage', primaryErrorId);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function hasServerRenderedValidationErrors(form: HTMLFormElement): boolean {
|
|
80
|
+
return !!getFirstErroredField(form) || !!getFormLevelErrorTarget(form);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function focusFirstValidationError(form: HTMLFormElement): boolean {
|
|
84
|
+
const field = getFirstErroredField(form);
|
|
85
|
+
|
|
86
|
+
if (field) {
|
|
87
|
+
const target = getFieldFocusTarget(field);
|
|
88
|
+
|
|
89
|
+
if (target) {
|
|
90
|
+
target.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
91
|
+
|
|
92
|
+
if (typeof target.focus === 'function') {
|
|
93
|
+
try {
|
|
94
|
+
target.focus({ preventScroll: true });
|
|
95
|
+
} catch {
|
|
96
|
+
target.focus();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
field.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
104
|
+
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const formError = getFormLevelErrorTarget(form);
|
|
109
|
+
|
|
110
|
+
if (!formError) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
formError.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
115
|
+
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
@@ -8,6 +8,13 @@ import type {
|
|
|
8
8
|
AddressModuleOptions as AddressModuleManifestOptions,
|
|
9
9
|
} from '#modules/address/host';
|
|
10
10
|
|
|
11
|
+
export {
|
|
12
|
+
ADDRESS_LEGACY_SELECTORS,
|
|
13
|
+
ADDRESS_SELECTORS,
|
|
14
|
+
findAddressFieldInput,
|
|
15
|
+
type AddressFieldInputKey,
|
|
16
|
+
} from '#modules/address/constants';
|
|
17
|
+
|
|
11
18
|
// This file is the intended authoring surface for address providers.
|
|
12
19
|
// Built-in providers import from here so third-party authors can follow the same patterns.
|
|
13
20
|
export const defineAddressModule = createManagedAddressModule;
|
|
@@ -2,7 +2,21 @@
|
|
|
2
2
|
export const DEFAULT_AUTOCOMPLETE_SELECTOR = '[data-formie-address-autocomplete-input]';
|
|
3
3
|
export const ADDRESS_LOCATION_SELECTOR = '[data-formie-address-location]';
|
|
4
4
|
|
|
5
|
-
/**
|
|
5
|
+
/** Keys for address sub-field inputs targeted by provider modules. */
|
|
6
|
+
export type AddressFieldInputKey =
|
|
7
|
+
| 'autoComplete'
|
|
8
|
+
| 'address1'
|
|
9
|
+
| 'address2'
|
|
10
|
+
| 'address3'
|
|
11
|
+
| 'city'
|
|
12
|
+
| 'state'
|
|
13
|
+
| 'zip'
|
|
14
|
+
| 'country';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Canonical address sub-field selectors (PHP output, UI reference, provider modules).
|
|
18
|
+
* All address-owned runtime hooks use the `data-formie-address-*` namespace.
|
|
19
|
+
*/
|
|
6
20
|
export const ADDRESS_SELECTORS = {
|
|
7
21
|
autoComplete: '[data-formie-address-autocomplete-input]',
|
|
8
22
|
address1: '[data-formie-address-line1-input]',
|
|
@@ -12,4 +26,70 @@ export const ADDRESS_SELECTORS = {
|
|
|
12
26
|
state: '[data-formie-address-state-input]',
|
|
13
27
|
zip: '[data-formie-address-zip-input]',
|
|
14
28
|
country: '[data-formie-address-country-input]',
|
|
15
|
-
} as const
|
|
29
|
+
} as const satisfies Record<AddressFieldInputKey, string>;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Legacy bare hooks still present on forms saved before the selector normalization.
|
|
33
|
+
* `findAddressFieldInput()` checks canonical selectors first, then these.
|
|
34
|
+
*/
|
|
35
|
+
export const ADDRESS_LEGACY_SELECTORS = {
|
|
36
|
+
autoComplete: '[data-formie-address-autocomplete-input]',
|
|
37
|
+
address1: '[data-address1]',
|
|
38
|
+
address2: '[data-address2]',
|
|
39
|
+
address3: '[data-address3]',
|
|
40
|
+
city: '[data-city]',
|
|
41
|
+
state: '[data-state]',
|
|
42
|
+
zip: '[data-zip]',
|
|
43
|
+
country: '[data-country]',
|
|
44
|
+
} as const satisfies Record<AddressFieldInputKey, string>;
|
|
45
|
+
|
|
46
|
+
const ADDRESS_FIELD_INPUT_SELECTOR_ORDER: Record<AddressFieldInputKey, readonly string[]> = {
|
|
47
|
+
autoComplete: [
|
|
48
|
+
ADDRESS_SELECTORS.autoComplete,
|
|
49
|
+
ADDRESS_LEGACY_SELECTORS.autoComplete,
|
|
50
|
+
],
|
|
51
|
+
address1: [
|
|
52
|
+
ADDRESS_SELECTORS.address1,
|
|
53
|
+
ADDRESS_LEGACY_SELECTORS.address1,
|
|
54
|
+
],
|
|
55
|
+
address2: [
|
|
56
|
+
ADDRESS_SELECTORS.address2,
|
|
57
|
+
ADDRESS_LEGACY_SELECTORS.address2,
|
|
58
|
+
],
|
|
59
|
+
address3: [
|
|
60
|
+
ADDRESS_SELECTORS.address3,
|
|
61
|
+
ADDRESS_LEGACY_SELECTORS.address3,
|
|
62
|
+
],
|
|
63
|
+
city: [
|
|
64
|
+
ADDRESS_SELECTORS.city,
|
|
65
|
+
ADDRESS_LEGACY_SELECTORS.city,
|
|
66
|
+
],
|
|
67
|
+
state: [
|
|
68
|
+
ADDRESS_SELECTORS.state,
|
|
69
|
+
ADDRESS_LEGACY_SELECTORS.state,
|
|
70
|
+
],
|
|
71
|
+
zip: [
|
|
72
|
+
ADDRESS_SELECTORS.zip,
|
|
73
|
+
ADDRESS_LEGACY_SELECTORS.zip,
|
|
74
|
+
],
|
|
75
|
+
country: [
|
|
76
|
+
ADDRESS_SELECTORS.country,
|
|
77
|
+
ADDRESS_LEGACY_SELECTORS.country,
|
|
78
|
+
],
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/** Resolve an address sub-field input against canonical and legacy selectors. */
|
|
82
|
+
export function findAddressFieldInput(
|
|
83
|
+
scope: ParentNode,
|
|
84
|
+
key: AddressFieldInputKey,
|
|
85
|
+
): HTMLInputElement | HTMLSelectElement | null {
|
|
86
|
+
for (const selector of ADDRESS_FIELD_INPUT_SELECTOR_ORDER[key]) {
|
|
87
|
+
const candidate = scope.querySelector(selector);
|
|
88
|
+
|
|
89
|
+
if (candidate instanceof HTMLInputElement || candidate instanceof HTMLSelectElement) {
|
|
90
|
+
return candidate;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return null;
|
|
95
|
+
}
|