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