@authhero/widget 0.19.1 → 0.20.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.
Files changed (36) hide show
  1. package/dist/authhero-widget/authhero-widget.esm.js +1 -1
  2. package/dist/authhero-widget/index.esm.js +1 -1
  3. package/dist/authhero-widget/p-59cbb196.entry.js +1 -0
  4. package/dist/authhero-widget/{p-5hZ8Vbm9.js → p-BFP_5sHV.js} +1 -1
  5. package/dist/authhero-widget/p-a92fa18e.entry.js +1 -0
  6. package/dist/cjs/authhero-node.cjs.entry.js +431 -4
  7. package/dist/cjs/authhero-widget.cjs.entry.js +73 -5
  8. package/dist/cjs/authhero-widget.cjs.js +2 -2
  9. package/dist/cjs/{index-vX5cgLV-.js → index-CUBT14z-.js} +21 -0
  10. package/dist/cjs/index.cjs.js +1 -1
  11. package/dist/cjs/loader.cjs.js +2 -2
  12. package/dist/collection/components/authhero-node/authhero-node.css +74 -0
  13. package/dist/collection/components/authhero-node/authhero-node.js +201 -4
  14. package/dist/collection/components/authhero-widget/authhero-widget.css +2 -2
  15. package/dist/collection/components/authhero-widget/authhero-widget.js +73 -5
  16. package/dist/collection/utils/country-data.js +235 -0
  17. package/dist/components/authhero-node.js +1 -1
  18. package/dist/components/authhero-widget.js +1 -1
  19. package/dist/components/index.js +1 -1
  20. package/dist/components/{p-EokuR0qI.js → p-DpfoRsj0.js} +1 -1
  21. package/dist/components/p-_nTdqfom.js +1 -0
  22. package/dist/esm/authhero-node.entry.js +431 -4
  23. package/dist/esm/authhero-widget.entry.js +73 -5
  24. package/dist/esm/authhero-widget.js +3 -3
  25. package/dist/esm/{index-5hZ8Vbm9.js → index-BFP_5sHV.js} +21 -0
  26. package/dist/esm/index.js +1 -1
  27. package/dist/esm/loader.js +3 -3
  28. package/dist/types/components/authhero-node/authhero-node.d.ts +36 -0
  29. package/dist/types/components/authhero-widget/authhero-widget.d.ts +15 -1
  30. package/dist/types/utils/country-data.d.ts +23 -0
  31. package/hydrate/index.js +524 -8
  32. package/hydrate/index.mjs +524 -8
  33. package/package.json +2 -2
  34. package/dist/authhero-widget/p-18d0a438.entry.js +0 -1
  35. package/dist/authhero-widget/p-bb3657ce.entry.js +0 -1
  36. package/dist/components/p-NKUIiiOq.js +0 -1
package/hydrate/index.mjs CHANGED
@@ -3262,6 +3262,23 @@ var setAccessor = (elm, memberName, oldValue, newValue, isSvg, flags, initialRen
3262
3262
  classList.remove(...oldClasses.filter((c) => c && !newClasses.includes(c)));
3263
3263
  classList.add(...newClasses.filter((c) => c && !oldClasses.includes(c)));
3264
3264
  }
3265
+ } else if (memberName === "style") {
3266
+ {
3267
+ for (const prop in oldValue) {
3268
+ if (!newValue || newValue[prop] == null) {
3269
+ {
3270
+ elm.style[prop] = "";
3271
+ }
3272
+ }
3273
+ }
3274
+ }
3275
+ for (const prop in newValue) {
3276
+ if (!oldValue || newValue[prop] !== oldValue[prop]) {
3277
+ {
3278
+ elm.style[prop] = newValue[prop];
3279
+ }
3280
+ }
3281
+ }
3265
3282
  } else if (memberName === "key") ; else if ((!isProp ) && memberName[0] === "o" && memberName[1] === "n") {
3266
3283
  if (memberName[2] === "-") {
3267
3284
  memberName = memberName.slice(3);
@@ -4945,7 +4962,243 @@ var setScopedSSR = (opts) => {
4945
4962
  var needsScopedSSR = () => scopedSSR;
4946
4963
  var scopedSSR = false;
4947
4964
 
4948
- const authheroNodeCss = () => `:host{display:block}.input-wrapper{display:flex;flex-direction:column;position:relative;margin-top:8px;margin-bottom:16px}.input-container{position:relative;width:100%}.input-label{position:absolute;left:16px;top:50%;transform:translateY(-50%);font-size:16px;font-weight:var(--ah-font-weight-label, 400);color:var(--ah-color-text-muted, #65676e);pointer-events:none;transition:all 0.15s ease-out;background-color:transparent;padding:0;z-index:1}.input-label.floating,.input-field:focus+.input-label,.input-field:not(:placeholder-shown)+.input-label,select.input-field+.input-label,input[type="date"].input-field+.input-label{top:-8px;transform:translateY(0);font-size:12px;background-color:var(--ah-color-bg, #ffffff);padding:0 4px;left:12px;color:var(--ah-color-text-muted, #65676e)}.input-field:focus+.input-label{color:var(--ah-color-primary, #635dff)}.required{color:var(--ah-color-error, #d03c38);margin-left:2px}.input-field{width:100%;padding:16px;font-size:16px;font-family:inherit;color:var(--ah-color-text, #1e212a);background-color:var(--ah-color-input-bg, #ffffff);border:1px solid var(--ah-color-border, #c9cace);border-radius:var(--ah-input-radius, 3px);outline:none;transition:border-color 0.15s ease-out,\\n box-shadow 0.15s ease-out;box-sizing:border-box}.input-field::placeholder{color:transparent}.input-field:hover{border-color:var(--ah-color-border-hover, #65676e)}.input-field:focus{border-color:var(--ah-color-primary, #635dff);box-shadow:inset 0 0 0 1px var(--ah-color-primary, #635dff)}.input-field.has-error{border-color:var(--ah-color-error, #d03c38)}.input-field.has-error:focus{box-shadow:inset 0 0 0 1px var(--ah-color-error, #d03c38)}.input-field:disabled{background-color:var(--ah-color-bg-disabled, #f5f5f5);border-color:var(--ah-color-border-disabled, #e0e1e3);cursor:not-allowed;opacity:0.7}.password-container{position:relative;display:flex;align-items:center}.password-container .input-field{padding-right:48px}.password-toggle{position:absolute;right:12px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;padding:4px;display:flex;align-items:center;justify-content:center;color:var(--ah-color-text-muted, #65676e);transition:color 0.15s ease}.password-toggle:hover{color:var(--ah-color-text, #1e212a)}.password-toggle svg{width:20px;height:20px}.error-text{font-size:12px;color:var(--ah-color-error, #d03c38);margin-top:4px;line-height:1.4}.helper-text{font-size:12px;color:var(--ah-color-text-muted, #65676e);margin-top:4px;line-height:1.4}.field-link{display:block;text-align:left;margin-top:8px;margin-bottom:16px}.field-link a{color:var(--ah-color-link, #635dff);text-decoration:var(--ah-link-decoration, none);font-size:14px;font-weight:var(--ah-font-weight-link, 400)}.field-link a:hover{text-decoration:underline}.checkbox-wrapper{display:flex;align-items:flex-start;gap:10px;cursor:pointer;margin-bottom:16px}.checkbox-wrapper input[type="checkbox"]{width:18px;height:18px;margin:0;accent-color:var(--ah-color-primary, #635dff);cursor:pointer;flex-shrink:0}.checkbox-label{font-size:14px;color:var(--ah-color-text, #1e212a);line-height:1.5}.btn{display:inline-flex;align-items:center;justify-content:center;gap:10px;width:100%;padding:14px 20px;font-size:16px;font-weight:var(--ah-font-weight-btn, 400);font-family:inherit;line-height:1.25;text-align:center;text-decoration:none;border:none;border-radius:var(--ah-btn-radius, 3px);cursor:pointer;transition:background-color 0.15s ease,\\n border-color 0.15s ease,\\n transform 0.1s ease;box-sizing:border-box}.btn:disabled{opacity:0.6;cursor:not-allowed}.btn:not(:disabled):active{transform:scale(0.98)}.btn:focus-visible{outline:2px solid var(--ah-color-primary, #635dff);outline-offset:2px}.btn-primary{background-color:var(--ah-color-primary, #635dff);color:var(--ah-color-text-on-primary, #ffffff);margin-top:12px}.btn-primary:not(:disabled):hover{filter:brightness(0.85)}.btn-secondary{background-color:var(--ah-color-bg, #ffffff);color:var(--ah-color-text, #1e212a);border:1px solid var(--ah-color-border, #c9cace)}.btn-secondary:not(:disabled):hover{background-color:var(--ah-color-bg-hover, #f5f5f5);border-color:var(--ah-color-border-hover, #65676e)}.btn-link{background:none;border:none;color:var(--ah-color-link, #635dff);padding:8px 0;font-weight:var(--ah-font-weight-link, 400);text-decoration:none}.btn-link:hover{text-decoration:underline}.social-buttons{display:flex;flex-direction:column;gap:12px}.btn-social{display:flex;align-items:center;justify-content:center;gap:12px}.btn-social-content{display:flex;flex-direction:column;align-items:center;text-align:center}.btn-social-subtitle{font-size:12px;font-style:italic;opacity:0.8;margin-top:2px}.btn-social-subtitle:empty{display:none}.social-icon{width:20px;height:20px;flex-shrink:0}@media (max-width: 480px){.social-buttons:has(.btn-social:nth-child(3)){flex-direction:row;flex-wrap:nowrap;justify-content:stretch;gap:8px}.social-buttons:has(.btn-social:nth-child(3)) .btn-social{width:auto;min-width:0;padding:12px;flex:1 1 0}.social-buttons:has(.btn-social:nth-child(3)) .btn-social span{display:none}.social-buttons:has(.btn-social:nth-child(3)) .social-icon{width:24px;height:24px}}.btn-icon{width:20px;height:20px;flex-shrink:0}.btn-icon img{width:100%;height:100%;object-fit:contain}.text-title{font-size:20px;font-weight:400;color:var(--ah-color-text, #1e212a);margin:8px 0;line-height:1.3}.text-title.text-success{color:var(--ah-color-success, #13a769)}.text-description{font-size:14px;color:var(--ah-color-text-muted, #65676e);margin:4px 0;line-height:1.5}.image{display:block;max-width:100%;height:auto;border-radius:4px}.image-centered{margin:0 auto 16px;width:52px;height:52px;object-fit:contain}.link{color:var(--ah-color-link, #635dff);text-decoration:var(--ah-link-decoration, none);font-size:14px;transition:color 0.15s ease}.link:hover{text-decoration:underline}.link:focus-visible{outline:2px solid var(--ah-color-link, #635dff);outline-offset:2px;border-radius:2px}.node-error{padding:12px 16px;background-color:var(--ah-color-error-bg, #ffeaea);color:var(--ah-color-error, #d03c38);border-left:3px solid var(--ah-color-error, #d03c38);border-radius:0;font-size:14px;margin-bottom:16px}.node-success{padding:12px 16px;background-color:var(--ah-color-success-bg, #e6f9f1);color:var(--ah-color-success, #13a769);border-left:3px solid var(--ah-color-success, #13a769);border-radius:0;font-size:14px;margin-bottom:16px}.divider{display:flex;align-items:center;text-align:center;margin:16px 0}.divider::before,.divider::after{content:"";flex:1;border-bottom:1px solid var(--ah-color-border-muted, #c9cace)}.divider-text{padding:0 10px;font-size:12px;font-weight:400;color:var(--ah-color-text-muted, #65676e);text-transform:uppercase;letter-spacing:0.5px}.rich-text{font-size:14px;line-height:1.5;color:var(--ah-color-text, #1e212a)}.rich-text a{color:var(--ah-color-link, #635dff);text-decoration:var(--ah-link-decoration, none);transition:color 0.15s ease}.rich-text a:hover{text-decoration:underline}.rich-text .terms-text{margin-top:16px;text-align:center;font-size:12px;color:var(--ah-color-text-muted, #65676e)}.rich-text .terms-text a{font-size:12px}.rich-text .forgot-password-link{text-align:right;font-size:13px;margin-top:4px}.rich-text .forgot-password-link a{font-size:13px;color:var(--ah-color-link, #635dff)}.rich-text .signup-link{margin-top:16px;text-align:center;font-size:14px;color:var(--ah-color-text, #1e212a)}`;
4965
+ /**
4966
+ * Country data for phone number input with country code selector.
4967
+ * Each entry contains:
4968
+ * - code: ISO 3166-1 alpha-2 country code
4969
+ * - dialCode: International dialing prefix
4970
+ * - flag: Unicode flag emoji
4971
+ * - name: Country name in English
4972
+ */
4973
+ /**
4974
+ * Get flag emoji from ISO 3166-1 alpha-2 country code.
4975
+ * Uses Unicode Regional Indicator Symbol Letters.
4976
+ */
4977
+ function flagEmoji(code) {
4978
+ return String.fromCodePoint(...code
4979
+ .toUpperCase()
4980
+ .split("")
4981
+ .map((c) => 0x1f1e6 - 65 + c.charCodeAt(0)));
4982
+ }
4983
+ /**
4984
+ * Full list of countries with dial codes, sorted by dial code (numerically)
4985
+ * with secondary sort by country code for ties.
4986
+ */
4987
+ const countries = [
4988
+ { code: "US", dialCode: "+1", name: "United States" },
4989
+ { code: "CA", dialCode: "+1", name: "Canada" },
4990
+ { code: "AG", dialCode: "+1", name: "Antigua and Barbuda" },
4991
+ { code: "BS", dialCode: "+1", name: "Bahamas" },
4992
+ { code: "BB", dialCode: "+1", name: "Barbados" },
4993
+ { code: "DM", dialCode: "+1", name: "Dominica" },
4994
+ { code: "DO", dialCode: "+1", name: "Dominican Republic" },
4995
+ { code: "GD", dialCode: "+1", name: "Grenada" },
4996
+ { code: "JM", dialCode: "+1", name: "Jamaica" },
4997
+ { code: "KN", dialCode: "+1", name: "Saint Kitts and Nevis" },
4998
+ { code: "LC", dialCode: "+1", name: "Saint Lucia" },
4999
+ { code: "VC", dialCode: "+1", name: "Saint Vincent and the Grenadines" },
5000
+ { code: "TT", dialCode: "+1", name: "Trinidad and Tobago" },
5001
+ { code: "PR", dialCode: "+1", name: "Puerto Rico" },
5002
+ { code: "KZ", dialCode: "+7", name: "Kazakhstan" },
5003
+ { code: "RU", dialCode: "+7", name: "Russia" },
5004
+ { code: "EG", dialCode: "+20", name: "Egypt" },
5005
+ { code: "ZA", dialCode: "+27", name: "South Africa" },
5006
+ { code: "GR", dialCode: "+30", name: "Greece" },
5007
+ { code: "NL", dialCode: "+31", name: "Netherlands" },
5008
+ { code: "BE", dialCode: "+32", name: "Belgium" },
5009
+ { code: "FR", dialCode: "+33", name: "France" },
5010
+ { code: "ES", dialCode: "+34", name: "Spain" },
5011
+ { code: "HU", dialCode: "+36", name: "Hungary" },
5012
+ { code: "IT", dialCode: "+39", name: "Italy" },
5013
+ { code: "RO", dialCode: "+40", name: "Romania" },
5014
+ { code: "CH", dialCode: "+41", name: "Switzerland" },
5015
+ { code: "AT", dialCode: "+43", name: "Austria" },
5016
+ { code: "GB", dialCode: "+44", name: "United Kingdom" },
5017
+ { code: "DK", dialCode: "+45", name: "Denmark" },
5018
+ { code: "SE", dialCode: "+46", name: "Sweden" },
5019
+ { code: "NO", dialCode: "+47", name: "Norway" },
5020
+ { code: "PL", dialCode: "+48", name: "Poland" },
5021
+ { code: "DE", dialCode: "+49", name: "Germany" },
5022
+ { code: "PE", dialCode: "+51", name: "Peru" },
5023
+ { code: "MX", dialCode: "+52", name: "Mexico" },
5024
+ { code: "CU", dialCode: "+53", name: "Cuba" },
5025
+ { code: "AR", dialCode: "+54", name: "Argentina" },
5026
+ { code: "BR", dialCode: "+55", name: "Brazil" },
5027
+ { code: "CL", dialCode: "+56", name: "Chile" },
5028
+ { code: "CO", dialCode: "+57", name: "Colombia" },
5029
+ { code: "VE", dialCode: "+58", name: "Venezuela" },
5030
+ { code: "MY", dialCode: "+60", name: "Malaysia" },
5031
+ { code: "AU", dialCode: "+61", name: "Australia" },
5032
+ { code: "ID", dialCode: "+62", name: "Indonesia" },
5033
+ { code: "PH", dialCode: "+63", name: "Philippines" },
5034
+ { code: "NZ", dialCode: "+64", name: "New Zealand" },
5035
+ { code: "SG", dialCode: "+65", name: "Singapore" },
5036
+ { code: "TH", dialCode: "+66", name: "Thailand" },
5037
+ { code: "JP", dialCode: "+81", name: "Japan" },
5038
+ { code: "KR", dialCode: "+82", name: "South Korea" },
5039
+ { code: "VN", dialCode: "+84", name: "Vietnam" },
5040
+ { code: "CN", dialCode: "+86", name: "China" },
5041
+ { code: "TR", dialCode: "+90", name: "Turkey" },
5042
+ { code: "IN", dialCode: "+91", name: "India" },
5043
+ { code: "PK", dialCode: "+92", name: "Pakistan" },
5044
+ { code: "AF", dialCode: "+93", name: "Afghanistan" },
5045
+ { code: "LK", dialCode: "+94", name: "Sri Lanka" },
5046
+ { code: "MM", dialCode: "+95", name: "Myanmar" },
5047
+ { code: "IR", dialCode: "+98", name: "Iran" },
5048
+ { code: "SS", dialCode: "+211", name: "South Sudan" },
5049
+ { code: "MA", dialCode: "+212", name: "Morocco" },
5050
+ { code: "DZ", dialCode: "+213", name: "Algeria" },
5051
+ { code: "TN", dialCode: "+216", name: "Tunisia" },
5052
+ { code: "LY", dialCode: "+218", name: "Libya" },
5053
+ { code: "GM", dialCode: "+220", name: "Gambia" },
5054
+ { code: "SN", dialCode: "+221", name: "Senegal" },
5055
+ { code: "MR", dialCode: "+222", name: "Mauritania" },
5056
+ { code: "ML", dialCode: "+223", name: "Mali" },
5057
+ { code: "GN", dialCode: "+224", name: "Guinea" },
5058
+ { code: "CI", dialCode: "+225", name: "Ivory Coast" },
5059
+ { code: "BF", dialCode: "+226", name: "Burkina Faso" },
5060
+ { code: "NE", dialCode: "+227", name: "Niger" },
5061
+ { code: "TG", dialCode: "+228", name: "Togo" },
5062
+ { code: "BJ", dialCode: "+229", name: "Benin" },
5063
+ { code: "MU", dialCode: "+230", name: "Mauritius" },
5064
+ { code: "LR", dialCode: "+231", name: "Liberia" },
5065
+ { code: "SL", dialCode: "+232", name: "Sierra Leone" },
5066
+ { code: "GH", dialCode: "+233", name: "Ghana" },
5067
+ { code: "NG", dialCode: "+234", name: "Nigeria" },
5068
+ { code: "TD", dialCode: "+235", name: "Chad" },
5069
+ { code: "CF", dialCode: "+236", name: "Central African Republic" },
5070
+ { code: "CM", dialCode: "+237", name: "Cameroon" },
5071
+ { code: "CV", dialCode: "+238", name: "Cape Verde" },
5072
+ { code: "ST", dialCode: "+239", name: "São Tomé and Príncipe" },
5073
+ { code: "GQ", dialCode: "+240", name: "Equatorial Guinea" },
5074
+ { code: "GA", dialCode: "+241", name: "Gabon" },
5075
+ { code: "CG", dialCode: "+242", name: "Congo" },
5076
+ { code: "CD", dialCode: "+243", name: "Congo (DRC)" },
5077
+ { code: "AO", dialCode: "+244", name: "Angola" },
5078
+ { code: "GW", dialCode: "+245", name: "Guinea-Bissau" },
5079
+ { code: "SC", dialCode: "+248", name: "Seychelles" },
5080
+ { code: "SD", dialCode: "+249", name: "Sudan" },
5081
+ { code: "RW", dialCode: "+250", name: "Rwanda" },
5082
+ { code: "ET", dialCode: "+251", name: "Ethiopia" },
5083
+ { code: "SO", dialCode: "+252", name: "Somalia" },
5084
+ { code: "DJ", dialCode: "+253", name: "Djibouti" },
5085
+ { code: "KE", dialCode: "+254", name: "Kenya" },
5086
+ { code: "TZ", dialCode: "+255", name: "Tanzania" },
5087
+ { code: "UG", dialCode: "+256", name: "Uganda" },
5088
+ { code: "BI", dialCode: "+257", name: "Burundi" },
5089
+ { code: "MZ", dialCode: "+258", name: "Mozambique" },
5090
+ { code: "ZM", dialCode: "+260", name: "Zambia" },
5091
+ { code: "MG", dialCode: "+261", name: "Madagascar" },
5092
+ { code: "RE", dialCode: "+262", name: "Réunion" },
5093
+ { code: "ZW", dialCode: "+263", name: "Zimbabwe" },
5094
+ { code: "NA", dialCode: "+264", name: "Namibia" },
5095
+ { code: "MW", dialCode: "+265", name: "Malawi" },
5096
+ { code: "LS", dialCode: "+266", name: "Lesotho" },
5097
+ { code: "BW", dialCode: "+267", name: "Botswana" },
5098
+ { code: "SZ", dialCode: "+268", name: "Eswatini" },
5099
+ { code: "KM", dialCode: "+269", name: "Comoros" },
5100
+ { code: "ER", dialCode: "+291", name: "Eritrea" },
5101
+ { code: "PT", dialCode: "+351", name: "Portugal" },
5102
+ { code: "LU", dialCode: "+352", name: "Luxembourg" },
5103
+ { code: "IE", dialCode: "+353", name: "Ireland" },
5104
+ { code: "IS", dialCode: "+354", name: "Iceland" },
5105
+ { code: "AL", dialCode: "+355", name: "Albania" },
5106
+ { code: "MT", dialCode: "+356", name: "Malta" },
5107
+ { code: "CY", dialCode: "+357", name: "Cyprus" },
5108
+ { code: "FI", dialCode: "+358", name: "Finland" },
5109
+ { code: "BG", dialCode: "+359", name: "Bulgaria" },
5110
+ { code: "LT", dialCode: "+370", name: "Lithuania" },
5111
+ { code: "LV", dialCode: "+371", name: "Latvia" },
5112
+ { code: "EE", dialCode: "+372", name: "Estonia" },
5113
+ { code: "MD", dialCode: "+373", name: "Moldova" },
5114
+ { code: "AM", dialCode: "+374", name: "Armenia" },
5115
+ { code: "BY", dialCode: "+375", name: "Belarus" },
5116
+ { code: "AD", dialCode: "+376", name: "Andorra" },
5117
+ { code: "MC", dialCode: "+377", name: "Monaco" },
5118
+ { code: "SM", dialCode: "+378", name: "San Marino" },
5119
+ { code: "UA", dialCode: "+380", name: "Ukraine" },
5120
+ { code: "RS", dialCode: "+381", name: "Serbia" },
5121
+ { code: "ME", dialCode: "+382", name: "Montenegro" },
5122
+ { code: "XK", dialCode: "+383", name: "Kosovo" },
5123
+ { code: "HR", dialCode: "+385", name: "Croatia" },
5124
+ { code: "SI", dialCode: "+386", name: "Slovenia" },
5125
+ { code: "BA", dialCode: "+387", name: "Bosnia and Herzegovina" },
5126
+ { code: "MK", dialCode: "+389", name: "North Macedonia" },
5127
+ { code: "CZ", dialCode: "+420", name: "Czech Republic" },
5128
+ { code: "SK", dialCode: "+421", name: "Slovakia" },
5129
+ { code: "LI", dialCode: "+423", name: "Liechtenstein" },
5130
+ { code: "FK", dialCode: "+500", name: "Falkland Islands" },
5131
+ { code: "BZ", dialCode: "+501", name: "Belize" },
5132
+ { code: "GT", dialCode: "+502", name: "Guatemala" },
5133
+ { code: "SV", dialCode: "+503", name: "El Salvador" },
5134
+ { code: "HN", dialCode: "+504", name: "Honduras" },
5135
+ { code: "NI", dialCode: "+505", name: "Nicaragua" },
5136
+ { code: "CR", dialCode: "+506", name: "Costa Rica" },
5137
+ { code: "PA", dialCode: "+507", name: "Panama" },
5138
+ { code: "HT", dialCode: "+509", name: "Haiti" },
5139
+ { code: "GP", dialCode: "+590", name: "Guadeloupe" },
5140
+ { code: "BO", dialCode: "+591", name: "Bolivia" },
5141
+ { code: "GY", dialCode: "+592", name: "Guyana" },
5142
+ { code: "EC", dialCode: "+593", name: "Ecuador" },
5143
+ { code: "GF", dialCode: "+594", name: "French Guiana" },
5144
+ { code: "PY", dialCode: "+595", name: "Paraguay" },
5145
+ { code: "MQ", dialCode: "+596", name: "Martinique" },
5146
+ { code: "SR", dialCode: "+597", name: "Suriname" },
5147
+ { code: "UY", dialCode: "+598", name: "Uruguay" },
5148
+ { code: "TL", dialCode: "+670", name: "Timor-Leste" },
5149
+ { code: "BN", dialCode: "+673", name: "Brunei" },
5150
+ { code: "NR", dialCode: "+674", name: "Nauru" },
5151
+ { code: "PG", dialCode: "+675", name: "Papua New Guinea" },
5152
+ { code: "TO", dialCode: "+676", name: "Tonga" },
5153
+ { code: "SB", dialCode: "+677", name: "Solomon Islands" },
5154
+ { code: "VU", dialCode: "+678", name: "Vanuatu" },
5155
+ { code: "FJ", dialCode: "+679", name: "Fiji" },
5156
+ { code: "PW", dialCode: "+680", name: "Palau" },
5157
+ { code: "WS", dialCode: "+685", name: "Samoa" },
5158
+ { code: "KI", dialCode: "+686", name: "Kiribati" },
5159
+ { code: "FM", dialCode: "+691", name: "Micronesia" },
5160
+ { code: "MH", dialCode: "+692", name: "Marshall Islands" },
5161
+ { code: "KP", dialCode: "+850", name: "North Korea" },
5162
+ { code: "HK", dialCode: "+852", name: "Hong Kong" },
5163
+ { code: "MO", dialCode: "+853", name: "Macau" },
5164
+ { code: "KH", dialCode: "+855", name: "Cambodia" },
5165
+ { code: "LA", dialCode: "+856", name: "Laos" },
5166
+ { code: "BD", dialCode: "+880", name: "Bangladesh" },
5167
+ { code: "TW", dialCode: "+886", name: "Taiwan" },
5168
+ { code: "MV", dialCode: "+960", name: "Maldives" },
5169
+ { code: "LB", dialCode: "+961", name: "Lebanon" },
5170
+ { code: "JO", dialCode: "+962", name: "Jordan" },
5171
+ { code: "SY", dialCode: "+963", name: "Syria" },
5172
+ { code: "IQ", dialCode: "+964", name: "Iraq" },
5173
+ { code: "KW", dialCode: "+965", name: "Kuwait" },
5174
+ { code: "SA", dialCode: "+966", name: "Saudi Arabia" },
5175
+ { code: "YE", dialCode: "+967", name: "Yemen" },
5176
+ { code: "OM", dialCode: "+968", name: "Oman" },
5177
+ { code: "PS", dialCode: "+970", name: "Palestine" },
5178
+ { code: "AE", dialCode: "+971", name: "United Arab Emirates" },
5179
+ { code: "IL", dialCode: "+972", name: "Israel" },
5180
+ { code: "BH", dialCode: "+973", name: "Bahrain" },
5181
+ { code: "QA", dialCode: "+974", name: "Qatar" },
5182
+ { code: "BT", dialCode: "+975", name: "Bhutan" },
5183
+ { code: "MN", dialCode: "+976", name: "Mongolia" },
5184
+ { code: "NP", dialCode: "+977", name: "Nepal" },
5185
+ { code: "TJ", dialCode: "+992", name: "Tajikistan" },
5186
+ { code: "TM", dialCode: "+993", name: "Turkmenistan" },
5187
+ { code: "AZ", dialCode: "+994", name: "Azerbaijan" },
5188
+ { code: "GE", dialCode: "+995", name: "Georgia" },
5189
+ { code: "KG", dialCode: "+996", name: "Kyrgyzstan" },
5190
+ { code: "UZ", dialCode: "+998", name: "Uzbekistan" },
5191
+ ].map((c) => ({ ...c, flag: flagEmoji(c.code) }));
5192
+ /**
5193
+ * Find a country by its ISO code, defaulting to US.
5194
+ */
5195
+ function getCountryByCode(code) {
5196
+ const upper = code.toUpperCase();
5197
+ return (countries.find((c) => c.code === upper) ||
5198
+ countries.find((c) => c.code === "US"));
5199
+ }
5200
+
5201
+ const authheroNodeCss = () => `:host{display:block}.input-wrapper{display:flex;flex-direction:column;position:relative;margin-top:8px;margin-bottom:16px}.input-container{position:relative;width:100%}.input-label{position:absolute;left:16px;top:50%;transform:translateY(-50%);font-size:16px;font-weight:var(--ah-font-weight-label, 400);color:var(--ah-color-text-muted, #65676e);pointer-events:none;transition:all 0.15s ease-out;background-color:transparent;padding:0;z-index:1}.input-label.floating,.input-field:focus+.input-label,.input-field:not(:placeholder-shown)+.input-label,select.input-field+.input-label,input[type="date"].input-field+.input-label{top:-8px;transform:translateY(0);font-size:12px;background-color:var(--ah-color-bg, #ffffff);padding:0 4px;left:12px;color:var(--ah-color-text-muted, #65676e)}.input-field:focus+.input-label{color:var(--ah-color-primary, #635dff)}.required{color:var(--ah-color-error, #d03c38);margin-left:2px}.input-field{width:100%;padding:16px;font-size:16px;font-family:inherit;color:var(--ah-color-text, #1e212a);background-color:var(--ah-color-input-bg, #ffffff);border:1px solid var(--ah-color-border, #c9cace);border-radius:var(--ah-input-radius, 3px);outline:none;transition:border-color 0.15s ease-out,\\n box-shadow 0.15s ease-out;box-sizing:border-box}.input-field::placeholder{color:transparent}.input-field:hover{border-color:var(--ah-color-border-hover, #65676e)}.input-field:focus{border-color:var(--ah-color-primary, #635dff);box-shadow:inset 0 0 0 1px var(--ah-color-primary, #635dff)}.input-field.has-error{border-color:var(--ah-color-error, #d03c38)}.input-field.has-error:focus{box-shadow:inset 0 0 0 1px var(--ah-color-error, #d03c38)}.input-field:disabled{background-color:var(--ah-color-bg-disabled, #f5f5f5);border-color:var(--ah-color-border-disabled, #e0e1e3);cursor:not-allowed;opacity:0.7}.password-container{position:relative;display:flex;align-items:center}.password-container .input-field{padding-right:48px}.password-toggle{position:absolute;right:12px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;padding:4px;display:flex;align-items:center;justify-content:center;color:var(--ah-color-text-muted, #65676e);transition:color 0.15s ease}.password-toggle:hover{color:var(--ah-color-text, #1e212a)}.password-toggle svg{width:20px;height:20px}.error-text{font-size:12px;color:var(--ah-color-error, #d03c38);margin-top:4px;line-height:1.4}.helper-text{font-size:12px;color:var(--ah-color-text-muted, #65676e);margin-top:4px;line-height:1.4}.field-link{display:block;text-align:left;margin-top:8px;margin-bottom:16px}.field-link a{color:var(--ah-color-link, #635dff);text-decoration:var(--ah-link-decoration, none);font-size:14px;font-weight:var(--ah-font-weight-link, 400)}.field-link a:hover{text-decoration:underline}.checkbox-wrapper{display:flex;align-items:flex-start;gap:10px;cursor:pointer;margin-bottom:16px}.checkbox-wrapper input[type="checkbox"]{width:18px;height:18px;margin:0;accent-color:var(--ah-color-primary, #635dff);cursor:pointer;flex-shrink:0}.checkbox-label{font-size:14px;color:var(--ah-color-text, #1e212a);line-height:1.5}.btn{display:inline-flex;align-items:center;justify-content:center;gap:10px;width:100%;padding:14px 20px;font-size:16px;font-weight:var(--ah-font-weight-btn, 400);font-family:inherit;line-height:1.25;text-align:center;text-decoration:none;border:none;border-radius:var(--ah-btn-radius, 3px);cursor:pointer;transition:background-color 0.15s ease,\\n border-color 0.15s ease,\\n transform 0.1s ease;box-sizing:border-box}.btn:disabled{opacity:0.6;cursor:not-allowed}.btn:not(:disabled):active{transform:scale(0.98)}.btn:focus-visible{outline:2px solid var(--ah-color-primary, #635dff);outline-offset:2px}.btn-primary{background-color:var(--ah-color-primary, #635dff);color:var(--ah-color-text-on-primary, #ffffff);margin-top:12px}.btn-primary:not(:disabled):hover{filter:brightness(0.85)}.btn-secondary{background-color:var(--ah-color-bg, #ffffff);color:var(--ah-color-text, #1e212a);border:1px solid var(--ah-color-border, #c9cace)}.btn-secondary:not(:disabled):hover{background-color:var(--ah-color-bg-hover, #f5f5f5);border-color:var(--ah-color-border-hover, #65676e)}.btn-link{background:none;border:none;color:var(--ah-color-link, #635dff);padding:8px 0;font-weight:var(--ah-font-weight-link, 400);text-decoration:none}.btn-link:hover{text-decoration:underline}.phone-input-wrapper{display:flex;align-items:stretch;gap:0;width:100%}.country-select{flex-shrink:0;width:auto;padding:12px 8px;font-size:var(--ah-font-size-body, 16px);font-family:var(--ah-font-family, inherit);border:1px solid var(--ah-color-border, #c9cace);border-right:none;border-radius:var(--ah-border-radius-input, 4px) 0 0 var(--ah-border-radius-input, 4px);background-color:var(--ah-color-surface, #fff);color:var(--ah-color-text, #1e212a);cursor:pointer;appearance:none;-webkit-appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 6px center;padding-right:22px}.country-select:focus{outline:none;border-color:var(--ah-color-primary, #635dff);box-shadow:0 0 0 1px var(--ah-color-primary, #635dff)}.country-select:disabled{opacity:0.5;cursor:not-allowed}.phone-input-wrapper .input-container{flex:1;min-width:0}.phone-input-wrapper .input-field{border-radius:0 var(--ah-border-radius-input, 4px) var(--ah-border-radius-input, 4px) 0}.phone-input-wrapper .input-label.floating,.phone-input-wrapper .input-field:focus+.input-label,.phone-input-wrapper .input-field:not(:placeholder-shown)+.input-label{left:8px}.social-buttons{display:flex;flex-direction:column;gap:12px}.btn-social{display:flex;align-items:center;justify-content:center;gap:12px}.btn-social-content{display:flex;flex-direction:column;align-items:center;text-align:center}.btn-social-subtitle{font-size:12px;font-style:italic;opacity:0.8;margin-top:2px}.btn-social-subtitle:empty{display:none}.social-icon{width:20px;height:20px;flex-shrink:0}@media (max-width: 480px){.social-buttons:has(.btn-social:nth-child(3)){flex-direction:row;flex-wrap:nowrap;justify-content:stretch;gap:8px}.social-buttons:has(.btn-social:nth-child(3)) .btn-social{width:auto;min-width:0;padding:12px;flex:1 1 0}.social-buttons:has(.btn-social:nth-child(3)) .btn-social span{display:none}.social-buttons:has(.btn-social:nth-child(3)) .social-icon{width:24px;height:24px}}.btn-icon{width:20px;height:20px;flex-shrink:0}.btn-icon img{width:100%;height:100%;object-fit:contain}.text-title{font-size:20px;font-weight:400;color:var(--ah-color-text, #1e212a);margin:8px 0;line-height:1.3}.text-title.text-success{color:var(--ah-color-success, #13a769)}.text-description{font-size:14px;color:var(--ah-color-text-muted, #65676e);margin:4px 0;line-height:1.5}.image{display:block;max-width:100%;height:auto;border-radius:4px}.image-centered{margin:0 auto 16px;width:52px;height:52px;object-fit:contain}.link{color:var(--ah-color-link, #635dff);text-decoration:var(--ah-link-decoration, none);font-size:14px;transition:color 0.15s ease}.link:hover{text-decoration:underline}.link:focus-visible{outline:2px solid var(--ah-color-link, #635dff);outline-offset:2px;border-radius:2px}.node-error{padding:12px 16px;background-color:var(--ah-color-error-bg, #ffeaea);color:var(--ah-color-error, #d03c38);border-left:3px solid var(--ah-color-error, #d03c38);border-radius:0;font-size:14px;margin-bottom:16px}.node-success{padding:12px 16px;background-color:var(--ah-color-success-bg, #e6f9f1);color:var(--ah-color-success, #13a769);border-left:3px solid var(--ah-color-success, #13a769);border-radius:0;font-size:14px;margin-bottom:16px}.divider{display:flex;align-items:center;text-align:center;margin:16px 0}.divider::before,.divider::after{content:"";flex:1;border-bottom:1px solid var(--ah-color-border-muted, #c9cace)}.divider-text{padding:0 10px;font-size:12px;font-weight:400;color:var(--ah-color-text-muted, #65676e);text-transform:uppercase;letter-spacing:0.5px}.rich-text{font-size:14px;line-height:1.5;color:var(--ah-color-text, #1e212a)}.rich-text a{color:var(--ah-color-link, #635dff);text-decoration:var(--ah-link-decoration, none);transition:color 0.15s ease}.rich-text a:hover{text-decoration:underline}.rich-text .terms-text{margin-top:16px;text-align:center;font-size:12px;color:var(--ah-color-text-muted, #65676e)}.rich-text .terms-text a{font-size:12px}.rich-text .forgot-password-link{text-align:right;font-size:13px;margin-top:4px}.rich-text .forgot-password-link a{font-size:13px;color:var(--ah-color-link, #635dff)}.rich-text .passwordless-link{margin-top:16px;text-align:center;font-size:14px}.rich-text .passwordless-link a{color:var(--ah-color-link, #635dff);text-decoration:var(--ah-link-decoration, none)}.rich-text .passwordless-link a:hover{text-decoration:underline}.rich-text .signup-link{margin-top:16px;text-align:center;font-size:14px;color:var(--ah-color-text, #1e212a)}`;
4949
5202
 
4950
5203
  class AuthheroNode {
4951
5204
  constructor(hostRef) {
@@ -4970,6 +5223,23 @@ class AuthheroNode {
4970
5223
  * Whether the password field is visible.
4971
5224
  */
4972
5225
  passwordVisible = false;
5226
+ /**
5227
+ * Selected country for TEL input with country selector.
5228
+ */
5229
+ selectedCountry = getCountryByCode("US");
5230
+ /**
5231
+ * Local phone number (without dial code) for TEL input.
5232
+ */
5233
+ localPhoneNumber = "";
5234
+ /**
5235
+ * Whether the country dropdown is open.
5236
+ */
5237
+ countryDropdownOpen = false;
5238
+ /**
5239
+ * Whether the TEL field is currently in email mode (allow_email config).
5240
+ * When true, the value is emitted as-is without dial code prefix.
5241
+ */
5242
+ telEmailMode = false;
4973
5243
  /**
4974
5244
  * Emitted when a field value changes.
4975
5245
  */
@@ -4978,6 +5248,153 @@ class AuthheroNode {
4978
5248
  * Emitted when a button is clicked.
4979
5249
  */
4980
5250
  buttonClick;
5251
+ componentChanged() {
5252
+ this.initCountryFromConfig();
5253
+ this.initTelValue();
5254
+ }
5255
+ valueChanged() {
5256
+ this.initTelValue();
5257
+ }
5258
+ componentWillLoad() {
5259
+ this.initCountryFromConfig();
5260
+ this.initTelValue();
5261
+ }
5262
+ initCountryFromConfig() {
5263
+ if (this.component?.type === "TEL") {
5264
+ const config = this.component.config;
5265
+ const defaultCountry = config?.default_country;
5266
+ if (defaultCountry) {
5267
+ this.selectedCountry = getCountryByCode(defaultCountry);
5268
+ }
5269
+ // For allow_email mode, start in email/text mode (no country picker)
5270
+ // until the user starts typing digits
5271
+ if (config?.allow_email === true) {
5272
+ this.telEmailMode = true;
5273
+ }
5274
+ }
5275
+ }
5276
+ /**
5277
+ * Hydrate localPhoneNumber (and selectedCountry) from the effective value
5278
+ * for TEL fields. The full value is stored as `{dialCode}{localNumber}`,
5279
+ * e.g. "+15551234567".
5280
+ */
5281
+ initTelValue() {
5282
+ if (this.component?.type !== "TEL")
5283
+ return;
5284
+ const config = this.component.config;
5285
+ const allowEmail = config?.allow_email === true;
5286
+ const fullValue = this.getEffectiveValue();
5287
+ if (!fullValue) {
5288
+ this.localPhoneNumber = "";
5289
+ if (allowEmail) {
5290
+ this.telEmailMode = true;
5291
+ }
5292
+ return;
5293
+ }
5294
+ // Try to match a country by dial code (longest match first)
5295
+ if (fullValue.startsWith("+")) {
5296
+ const sorted = [...countries].sort((a, b) => b.dialCode.length - a.dialCode.length);
5297
+ for (const country of sorted) {
5298
+ if (fullValue.startsWith(country.dialCode)) {
5299
+ this.selectedCountry = country;
5300
+ this.localPhoneNumber = fullValue.slice(country.dialCode.length);
5301
+ if (allowEmail) {
5302
+ this.telEmailMode = false;
5303
+ }
5304
+ return;
5305
+ }
5306
+ }
5307
+ }
5308
+ // No dial code match — check if it looks like an email or a phone number
5309
+ this.localPhoneNumber = fullValue;
5310
+ if (allowEmail) {
5311
+ const looksLikePhone = /^[+\d]/.test(fullValue);
5312
+ this.telEmailMode = !looksLikePhone;
5313
+ }
5314
+ }
5315
+ handleCountryChange = (e) => {
5316
+ const target = e.target;
5317
+ this.selectedCountry = getCountryByCode(target.value);
5318
+ // Re-emit the full phone number with new dial code
5319
+ const fullNumber = this.localPhoneNumber
5320
+ ? `${this.selectedCountry.dialCode}${this.localPhoneNumber}`
5321
+ : "";
5322
+ this.fieldChange.emit({ id: this.component.id, value: fullNumber });
5323
+ };
5324
+ /**
5325
+ * Try to detect a dial code prefix in the raw input (e.g. "+46", "0046")
5326
+ * and update selectedCountry accordingly. Returns the local number portion
5327
+ * (after the dial code) if a match was found, or null if no match.
5328
+ */
5329
+ detectDialCodeFromInput(raw) {
5330
+ // Normalise "00" international prefix to "+"
5331
+ const normalized = raw.startsWith("00") ? "+" + raw.slice(2) : raw;
5332
+ if (!normalized.startsWith("+"))
5333
+ return null;
5334
+ // Match longest dial code first
5335
+ const sorted = [...countries].sort((a, b) => b.dialCode.length - a.dialCode.length);
5336
+ for (const country of sorted) {
5337
+ if (normalized.startsWith(country.dialCode)) {
5338
+ this.selectedCountry = country;
5339
+ return normalized.slice(country.dialCode.length);
5340
+ }
5341
+ }
5342
+ return null;
5343
+ }
5344
+ handlePhoneInput = (e) => {
5345
+ const target = e.target;
5346
+ const value = target.value;
5347
+ const config = this.component.config;
5348
+ const allowEmail = config?.allow_email === true;
5349
+ if (allowEmail) {
5350
+ // Detect phone mode: value starts with digit or '+', and no '@'.
5351
+ // When the field is empty, revert to neutral (email) mode so the
5352
+ // country picker disappears and the user can start fresh.
5353
+ const looksLikePhone = value.length > 0 && /^[+\d]/.test(value) && !value.includes("@");
5354
+ this.telEmailMode = !looksLikePhone;
5355
+ if (!this.telEmailMode) {
5356
+ // Phone mode — first try dial code detection before stripping '+'
5357
+ // so that typing +46 or 0046 can match a country
5358
+ const dialLocal = this.detectDialCodeFromInput(value);
5359
+ if (dialLocal !== null) {
5360
+ // Dial code matched — strip it from the input and show only local part
5361
+ const cleanedLocal = dialLocal.replace(/[^+\d\s\-()]/g, "").replace(/\+/g, "");
5362
+ target.value = cleanedLocal;
5363
+ this.localPhoneNumber = cleanedLocal;
5364
+ const fullNumber = `${this.selectedCountry.dialCode}${cleanedLocal}`;
5365
+ this.fieldChange.emit({ id: this.component.id, value: fullNumber });
5366
+ }
5367
+ else {
5368
+ // No dial code — strip non-phone chars and '+' (picker provides the prefix)
5369
+ const cleaned = value.replace(/[^+\d\s\-()]/g, "").replace(/\+/g, "");
5370
+ if (cleaned !== value) {
5371
+ target.value = cleaned;
5372
+ }
5373
+ this.localPhoneNumber = cleaned;
5374
+ const fullNumber = cleaned
5375
+ ? `${this.selectedCountry.dialCode}${cleaned}`
5376
+ : "";
5377
+ this.fieldChange.emit({ id: this.component.id, value: fullNumber });
5378
+ }
5379
+ }
5380
+ else {
5381
+ // Email or text — emit as-is
5382
+ this.localPhoneNumber = value;
5383
+ this.fieldChange.emit({ id: this.component.id, value });
5384
+ }
5385
+ return;
5386
+ }
5387
+ // Standard phone-only mode — strip '+' since the picker provides the prefix
5388
+ const cleaned = value.replace(/[^\d\s\-()]/g, "");
5389
+ if (cleaned !== value) {
5390
+ target.value = cleaned;
5391
+ }
5392
+ this.localPhoneNumber = cleaned;
5393
+ const fullNumber = cleaned
5394
+ ? `${this.selectedCountry.dialCode}${cleaned}`
5395
+ : "";
5396
+ this.fieldChange.emit({ id: this.component.id, value: fullNumber });
5397
+ };
4981
5398
  handleInput = (e) => {
4982
5399
  const target = e.target;
4983
5400
  this.fieldChange.emit({ id: this.component.id, value: target.value });
@@ -4987,6 +5404,16 @@ class AuthheroNode {
4987
5404
  e.preventDefault();
4988
5405
  this.buttonClick.emit({ id: "submit", type: "submit", value: "next" });
4989
5406
  }
5407
+ // In combined TEL+email mode, backspace on an empty field exits phone mode
5408
+ if (e.key === "Backspace" && !this.telEmailMode) {
5409
+ const target = e.target;
5410
+ const config = this.component.config;
5411
+ if (config?.allow_email === true && target.value.length === 0) {
5412
+ this.telEmailMode = true;
5413
+ this.localPhoneNumber = "";
5414
+ this.fieldChange.emit({ id: this.component.id, value: "" });
5415
+ }
5416
+ }
4990
5417
  };
4991
5418
  handleCheckbox = (e) => {
4992
5419
  const target = e.target;
@@ -5159,8 +5586,17 @@ class AuthheroNode {
5159
5586
  renderTelField(component) {
5160
5587
  const inputId = `input-${component.id}`;
5161
5588
  const errors = this.getErrors();
5162
- const effectiveValue = this.getEffectiveValue();
5163
- return (hAsync("div", { class: "input-wrapper", part: "input-wrapper" }, this.renderLabel(component.label, inputId, component.required), hAsync("input", { id: inputId, class: this.getInputFieldClass(errors.length > 0), part: "input", type: "tel", name: component.id, value: effectiveValue ?? "", placeholder: component.config?.placeholder, required: component.required, disabled: this.disabled, autocomplete: "tel", onInput: this.handleInput, onKeyDown: this.handleKeyDown }), this.renderErrors(), errors.length === 0 && this.renderHint(component.hint)));
5589
+ const config = component.config;
5590
+ const allowEmail = config?.allow_email === true;
5591
+ const hasValue = this.localPhoneNumber.length > 0;
5592
+ // In allow_email mode, show the country picker only when the user is typing a phone number
5593
+ const showCountryPicker = allowEmail ? !this.telEmailMode : true;
5594
+ // Calculate dynamic width: flag + space + dial code + small padding for dropdown arrow
5595
+ const selectedText = `${this.selectedCountry.flag} ${this.selectedCountry.dialCode}`;
5596
+ const selectWidth = `${selectedText.length + 1}ch`;
5597
+ const countrySelect = showCountryPicker ? (hAsync("select", { class: "country-select", part: "country-select", style: { width: selectWidth, minWidth: "0" }, onChange: this.handleCountryChange, disabled: this.disabled, "aria-label": "Country code" }, countries.map((country) => (hAsync("option", { value: country.code, selected: this.selectedCountry.code === country.code, key: country.code }, country.flag, " ", country.dialCode))))) : null;
5598
+ const inputType = allowEmail && this.telEmailMode ? "text" : "tel";
5599
+ return (hAsync("div", { class: "input-wrapper", part: "input-wrapper" }, hAsync("div", { class: showCountryPicker ? "phone-input-wrapper" : "", part: "phone-input-wrapper" }, countrySelect, hAsync("div", { class: "input-container" }, hAsync("input", { id: inputId, class: this.getInputFieldClass(errors.length > 0), part: "input", type: inputType, name: component.id, "data-input-name": component.id, value: this.localPhoneNumber, placeholder: " ", required: component.required, disabled: this.disabled, autocomplete: allowEmail && this.telEmailMode ? "email" : "tel-national", onInput: this.handlePhoneInput, onKeyDown: this.handleKeyDown }), this.renderFloatingLabel(component.label, inputId, component.required, hasValue))), this.renderErrors(), errors.length === 0 && this.renderHint(component.hint)));
5164
5600
  }
5165
5601
  renderUrlField(component) {
5166
5602
  const inputId = `input-${component.id}`;
@@ -5312,6 +5748,14 @@ class AuthheroNode {
5312
5748
  return null;
5313
5749
  }
5314
5750
  }
5751
+ static get watchers() { return {
5752
+ "component": [{
5753
+ "componentChanged": 0
5754
+ }],
5755
+ "value": [{
5756
+ "valueChanged": 0
5757
+ }]
5758
+ }; }
5315
5759
  static get style() { return authheroNodeCss(); }
5316
5760
  static get cmpMeta() { return {
5317
5761
  "$flags$": 521,
@@ -5320,7 +5764,11 @@ class AuthheroNode {
5320
5764
  "component": [16],
5321
5765
  "value": [1],
5322
5766
  "disabled": [4],
5323
- "passwordVisible": [32]
5767
+ "passwordVisible": [32],
5768
+ "selectedCountry": [32],
5769
+ "localPhoneNumber": [32],
5770
+ "countryDropdownOpen": [32],
5771
+ "telEmailMode": [32]
5324
5772
  },
5325
5773
  "$listeners$": undefined,
5326
5774
  "$lazyBundleId$": "-",
@@ -5750,7 +6198,7 @@ function escapeAttr(value) {
5750
6198
  .replace(/>/g, ">");
5751
6199
  }
5752
6200
 
5753
- const authheroWidgetCss = () => `:host{display:block;font-family:var(--ah-font-family, 'ulp-font', -apple-system, BlinkMacSystemFont, Roboto, Helvetica, sans-serif);font-size:var(--ah-font-size-base, 14px);line-height:var(--ah-line-height-base, 1.5);color:var(--ah-color-text, #1e212a);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.widget-container{max-width:var(--ah-widget-max-width, 400px);width:100%;margin:0 auto;background-color:var(--ah-color-bg, #ffffff);border-radius:var(--ah-widget-radius, 5px);box-shadow:var(--ah-widget-shadow, 0 4px 22px 0 rgba(0, 0, 0, 0.11));box-sizing:border-box}.widget-header{padding:var(--ah-header-padding, 40px 48px 24px)}.widget-body{padding:var(--ah-body-padding, 0 48px 40px)}.logo-wrapper{display:var(--ah-logo-display, flex);justify-content:var(--ah-logo-align, center);margin-bottom:8px}.logo{display:block;height:var(--ah-logo-height, 52px);max-width:100%;width:auto;object-fit:contain}.title{font-size:var(--ah-font-size-title, 24px);font-weight:var(--ah-font-weight-title, 700);text-align:var(--ah-title-align, center);margin:var(--ah-title-margin, 24px 0 24px);color:var(--ah-color-header, #1e212a);line-height:1.2}.description{font-size:var(--ah-font-size-description, 14px);text-align:var(--ah-title-align, center);margin:var(--ah-description-margin, 0 0 8px);color:var(--ah-color-text, #1e212a);line-height:1.5}.message{padding:12px 16px;border-radius:4px;margin-bottom:16px;font-size:14px;line-height:1.5}.message-error{background-color:var(--ah-color-error-bg, #ffeaea);color:var(--ah-color-error, #d03c38);border-left:3px solid var(--ah-color-error, #d03c38)}.message-success{background-color:var(--ah-color-success-bg, #e6f9f1);color:var(--ah-color-success, #13a769);border-left:3px solid var(--ah-color-success, #13a769)}form{display:flex;flex-direction:column}.form-content{display:flex;flex-direction:column}.social-section{display:flex;flex-direction:column;gap:8px;order:var(--ah-social-order, 2)}.fields-section{display:flex;flex-direction:column;order:var(--ah-fields-order, 0)}.divider{display:flex;align-items:center;text-align:center;margin:16px 0;order:var(--ah-divider-order, 1)}.divider::before,.divider::after{content:'';flex:1;border-bottom:1px solid var(--ah-color-border-muted, #c9cace)}.divider-text{padding:0 10px;font-size:12px;font-weight:400;color:var(--ah-color-text-muted, #65676e);text-transform:uppercase;letter-spacing:0}.links{display:flex;flex-direction:column;align-items:center;gap:8px;margin-top:16px}.link-wrapper{font-size:14px;color:var(--ah-color-text, #1e212a)}.link{color:var(--ah-color-link, #635dff);text-decoration:var(--ah-link-decoration, none);font-size:14px;font-weight:var(--ah-font-weight-link, 400);transition:color 150ms ease}.link:hover{text-decoration:underline}.link:focus-visible{outline:2px solid var(--ah-color-link, #635dff);outline-offset:2px;border-radius:2px}.widget-footer{margin-top:16px;text-align:center;font-size:12px;color:var(--ah-color-text-muted, #65676e)}.widget-footer a{color:var(--ah-color-link, #635dff);text-decoration:var(--ah-link-decoration, none);font-size:12px;transition:color 150ms ease}.widget-footer a:hover{text-decoration:underline}.widget-footer a:focus-visible{outline:2px solid var(--ah-color-link, #635dff);outline-offset:2px;border-radius:2px}.loading-spinner{width:32px;height:32px;margin:24px auto;border:3px solid var(--ah-color-border-muted, #e0e1e3);border-top-color:var(--ah-color-primary, #635dff);border-radius:50%;animation:spin 0.8s linear infinite}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.error-message{text-align:center;color:var(--ah-color-error, #d03c38);padding:16px;font-size:14px}@media (max-width: 480px){:host{display:block;width:100%;min-height:100vh;background-color:var(--ah-color-bg, #ffffff)}.widget-container{box-shadow:none;border-radius:0;max-width:none;width:100%;margin:0}.widget-header{padding:24px 16px 16px}.widget-body{padding:0 16px 24px}}`;
6201
+ const authheroWidgetCss = () => `:host{display:block;font-family:var(--ah-font-family, 'ulp-font', -apple-system, BlinkMacSystemFont, Roboto, Helvetica, sans-serif);font-size:var(--ah-font-size-base, 16px);line-height:var(--ah-line-height-base, 1.5);color:var(--ah-color-text, #1e212a);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.widget-container{max-width:var(--ah-widget-max-width, 400px);width:100%;margin:0 auto;background-color:var(--ah-color-bg, #ffffff);border-radius:var(--ah-widget-radius, 5px);box-shadow:var(--ah-widget-shadow, 0 4px 22px 0 rgba(0, 0, 0, 0.11));box-sizing:border-box}.widget-header{padding:var(--ah-header-padding, 40px 48px 24px)}.widget-body{padding:var(--ah-body-padding, 0 48px 40px)}.logo-wrapper{display:var(--ah-logo-display, flex);justify-content:var(--ah-logo-align, center);margin-bottom:8px}.logo{display:block;height:var(--ah-logo-height, 52px);max-width:100%;width:auto;object-fit:contain}.title{font-size:var(--ah-font-size-title, 24px);font-weight:var(--ah-font-weight-title, 700);text-align:var(--ah-title-align, center);margin:var(--ah-title-margin, 24px 0 24px);color:var(--ah-color-header, #1e212a);line-height:1.2}.description{font-size:var(--ah-font-size-subtitle, 16px);text-align:var(--ah-title-align, center);margin:var(--ah-description-margin, 0 0 8px);color:var(--ah-color-text, #1e212a);line-height:1.5}.message{padding:12px 16px;border-radius:4px;margin-bottom:16px;font-size:14px;line-height:1.5}.message-error{background-color:var(--ah-color-error-bg, #ffeaea);color:var(--ah-color-error, #d03c38);border-left:3px solid var(--ah-color-error, #d03c38)}.message-success{background-color:var(--ah-color-success-bg, #e6f9f1);color:var(--ah-color-success, #13a769);border-left:3px solid var(--ah-color-success, #13a769)}form{display:flex;flex-direction:column}.form-content{display:flex;flex-direction:column}.social-section{display:flex;flex-direction:column;gap:8px;order:var(--ah-social-order, 2)}.fields-section{display:flex;flex-direction:column;order:var(--ah-fields-order, 0)}.divider{display:flex;align-items:center;text-align:center;margin:16px 0;order:var(--ah-divider-order, 1)}.divider::before,.divider::after{content:'';flex:1;border-bottom:1px solid var(--ah-color-border-muted, #c9cace)}.divider-text{padding:0 10px;font-size:12px;font-weight:400;color:var(--ah-color-text-muted, #65676e);text-transform:uppercase;letter-spacing:0}.links{display:flex;flex-direction:column;align-items:center;gap:8px;margin-top:16px}.link-wrapper{font-size:14px;color:var(--ah-color-text, #1e212a)}.link{color:var(--ah-color-link, #635dff);text-decoration:var(--ah-link-decoration, none);font-size:14px;font-weight:var(--ah-font-weight-link, 400);transition:color 150ms ease}.link:hover{text-decoration:underline}.link:focus-visible{outline:2px solid var(--ah-color-link, #635dff);outline-offset:2px;border-radius:2px}.widget-footer{margin-top:16px;text-align:center;font-size:12px;color:var(--ah-color-text-muted, #65676e)}.widget-footer a{color:var(--ah-color-link, #635dff);text-decoration:var(--ah-link-decoration, none);font-size:12px;transition:color 150ms ease}.widget-footer a:hover{text-decoration:underline}.widget-footer a:focus-visible{outline:2px solid var(--ah-color-link, #635dff);outline-offset:2px;border-radius:2px}.loading-spinner{width:32px;height:32px;margin:24px auto;border:3px solid var(--ah-color-border-muted, #e0e1e3);border-top-color:var(--ah-color-primary, #635dff);border-radius:50%;animation:spin 0.8s linear infinite}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.error-message{text-align:center;color:var(--ah-color-error, #d03c38);padding:16px;font-size:14px}@media (max-width: 480px){:host{display:block;width:100%;min-height:100vh;background-color:var(--ah-color-bg, #ffffff)}.widget-container{box-shadow:none;border-radius:0;max-width:none;width:100%;margin:0}.widget-header{padding:24px 16px 16px}.widget-body{padding:0 16px 24px}}`;
5754
6202
 
5755
6203
  class AuthheroWidget {
5756
6204
  constructor(hostRef) {
@@ -6113,6 +6561,25 @@ class AuthheroWidget {
6113
6561
  }
6114
6562
  }
6115
6563
  }
6564
+ handlePopState = (event) => {
6565
+ if (!this.apiUrl)
6566
+ return;
6567
+ // Restore the widget state token from history if present
6568
+ if (event.state?.state) {
6569
+ this.state = event.state.state;
6570
+ }
6571
+ // Derive screen from history state or from the current URL
6572
+ const screen = event.state?.screen ?? this.extractScreenIdFromHref(location.href);
6573
+ if (screen) {
6574
+ this.fetchScreen(screen);
6575
+ }
6576
+ };
6577
+ connectedCallback() {
6578
+ window.addEventListener("popstate", this.handlePopState);
6579
+ }
6580
+ disconnectedCallback() {
6581
+ window.removeEventListener("popstate", this.handlePopState);
6582
+ }
6116
6583
  async componentWillLoad() {
6117
6584
  // Parse initial props - this prevents unnecessary state changes during hydration that cause flashes
6118
6585
  // Also check the element attribute as a fallback for hydration scenarios
@@ -6145,7 +6612,7 @@ class AuthheroWidget {
6145
6612
  */
6146
6613
  async fetchScreen(screenIdOverride, nodeId) {
6147
6614
  if (!this.apiUrl)
6148
- return;
6615
+ return false;
6149
6616
  const currentScreenId = screenIdOverride || this.screenId;
6150
6617
  // Build the API URL, replacing {screenId} placeholder if present
6151
6618
  let url = this.apiUrl;
@@ -6200,6 +6667,7 @@ class AuthheroWidget {
6200
6667
  this.updateDataScreenAttribute();
6201
6668
  this.persistState();
6202
6669
  this.focusFirstInput();
6670
+ return true;
6203
6671
  }
6204
6672
  }
6205
6673
  else {
@@ -6220,6 +6688,7 @@ class AuthheroWidget {
6220
6688
  finally {
6221
6689
  this.loading = false;
6222
6690
  }
6691
+ return false;
6223
6692
  }
6224
6693
  handleInputChange = (name, value) => {
6225
6694
  this.formData = {
@@ -6395,6 +6864,30 @@ class AuthheroWidget {
6395
6864
  console.error("Resend failed:", error);
6396
6865
  }
6397
6866
  }
6867
+ /**
6868
+ * Extract screen ID from a u2 link href.
6869
+ * Handles patterns like /u2/login/{screenId}?state=... and /u2/{screenId}?state=...
6870
+ * Returns the screen ID or null if the href doesn't match a known pattern.
6871
+ */
6872
+ extractScreenIdFromHref(href) {
6873
+ try {
6874
+ const url = new URL(href, window.location.origin);
6875
+ const path = url.pathname;
6876
+ // Match /u2/login/{screenId} (e.g., /u2/login/identifier)
6877
+ const loginMatch = path.match(/\/u2\/login\/([^/]+)$/);
6878
+ if (loginMatch)
6879
+ return loginMatch[1];
6880
+ // Match /u2/{screenId} (e.g., /u2/signup, /u2/enter-password)
6881
+ const u2Match = path.match(/\/u2\/([^/]+)$/);
6882
+ if (u2Match && u2Match[1] !== "login" && u2Match[1] !== "screen") {
6883
+ return u2Match[1];
6884
+ }
6885
+ return null;
6886
+ }
6887
+ catch {
6888
+ return null;
6889
+ }
6890
+ }
6398
6891
  handleLinkClick = (e, link) => {
6399
6892
  // Emit the event so the consuming app can handle it
6400
6893
  this.linkClick.emit({
@@ -6402,12 +6895,35 @@ class AuthheroWidget {
6402
6895
  href: link.href,
6403
6896
  text: link.text,
6404
6897
  });
6405
- // If autoNavigate is enabled, let the browser handle the navigation
6406
- // Otherwise, prevent default and let the app decide
6898
+ // If autoNavigate is not enabled, prevent default and let the app decide
6407
6899
  if (!this.shouldAutoNavigate) {
6408
6900
  e.preventDefault();
6901
+ return;
6902
+ }
6903
+ // Try client-side navigation: extract screen ID and fetch via API
6904
+ const screenId = this.extractScreenIdFromHref(link.href);
6905
+ if (screenId && this.apiUrl) {
6906
+ e.preventDefault();
6907
+ this.navigateToScreen(screenId, link.href);
6908
+ return;
6409
6909
  }
6910
+ // Fall back to browser navigation for non-u2 links
6410
6911
  };
6912
+ /**
6913
+ * Navigate to a screen client-side by fetching it from the API.
6914
+ * Updates the widget state and browser URL without a full page reload.
6915
+ */
6916
+ async navigateToScreen(screenId, displayUrl) {
6917
+ const success = await this.fetchScreen(screenId);
6918
+ if (success) {
6919
+ // Push browser history so back/forward works
6920
+ window.history.pushState({ screen: screenId, state: this.state }, "", displayUrl);
6921
+ }
6922
+ else {
6923
+ // On failure, fall back to hard navigation
6924
+ window.location.href = displayUrl;
6925
+ }
6926
+ }
6411
6927
  /**
6412
6928
  * Check if a component is a social button.
6413
6929
  */