@authhero/widget 0.19.2 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/authhero-widget/authhero-widget.esm.js +1 -1
- package/dist/authhero-widget/index.esm.js +1 -1
- package/dist/authhero-widget/{p-5hZ8Vbm9.js → p-BFP_5sHV.js} +1 -1
- package/dist/authhero-widget/p-c03e5b57.entry.js +1 -0
- package/dist/authhero-widget/p-f3a92b50.entry.js +1 -0
- package/dist/cjs/authhero-node.cjs.entry.js +448 -5
- package/dist/cjs/authhero-widget.cjs.entry.js +200 -21
- package/dist/cjs/authhero-widget.cjs.js +2 -2
- package/dist/cjs/{index-vX5cgLV-.js → index-CUBT14z-.js} +21 -0
- package/dist/cjs/index.cjs.js +1 -1
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/collection/components/authhero-node/authhero-node.css +74 -0
- package/dist/collection/components/authhero-node/authhero-node.js +219 -6
- package/dist/collection/components/authhero-widget/authhero-widget.css +2 -2
- package/dist/collection/components/authhero-widget/authhero-widget.js +102 -5
- package/dist/collection/utils/branding.js +98 -16
- package/dist/collection/utils/country-data.js +235 -0
- package/dist/components/authhero-node.js +1 -1
- package/dist/components/authhero-widget.js +1 -1
- package/dist/components/index.js +1 -1
- package/dist/components/p-D9Clv9VJ.js +1 -0
- package/dist/components/{p-EokuR0qI.js → p-DpfoRsj0.js} +1 -1
- package/dist/esm/authhero-node.entry.js +448 -5
- package/dist/esm/authhero-widget.entry.js +200 -21
- package/dist/esm/authhero-widget.js +3 -3
- package/dist/esm/{index-5hZ8Vbm9.js → index-BFP_5sHV.js} +21 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/loader.js +3 -3
- package/dist/types/components/authhero-node/authhero-node.d.ts +36 -0
- package/dist/types/components/authhero-widget/authhero-widget.d.ts +20 -1
- package/dist/types/utils/country-data.d.ts +23 -0
- package/hydrate/index.js +668 -25
- package/hydrate/index.mjs +668 -25
- package/package.json +2 -2
- package/dist/authhero-widget/p-18d0a438.entry.js +0 -1
- package/dist/authhero-widget/p-bb3657ce.entry.js +0 -1
- 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
|
-
|
|
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,155 @@ 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
|
|
5364
|
+
.replace(/[^+\d\s\-()]/g, "")
|
|
5365
|
+
.replace(/\+/g, "");
|
|
5366
|
+
target.value = cleanedLocal;
|
|
5367
|
+
this.localPhoneNumber = cleanedLocal;
|
|
5368
|
+
const fullNumber = `${this.selectedCountry.dialCode}${cleanedLocal}`;
|
|
5369
|
+
this.fieldChange.emit({ id: this.component.id, value: fullNumber });
|
|
5370
|
+
}
|
|
5371
|
+
else {
|
|
5372
|
+
// No dial code — strip non-phone chars and '+' (picker provides the prefix)
|
|
5373
|
+
const cleaned = value.replace(/[^+\d\s\-()]/g, "").replace(/\+/g, "");
|
|
5374
|
+
if (cleaned !== value) {
|
|
5375
|
+
target.value = cleaned;
|
|
5376
|
+
}
|
|
5377
|
+
this.localPhoneNumber = cleaned;
|
|
5378
|
+
const fullNumber = cleaned
|
|
5379
|
+
? `${this.selectedCountry.dialCode}${cleaned}`
|
|
5380
|
+
: "";
|
|
5381
|
+
this.fieldChange.emit({ id: this.component.id, value: fullNumber });
|
|
5382
|
+
}
|
|
5383
|
+
}
|
|
5384
|
+
else {
|
|
5385
|
+
// Email or text — emit as-is
|
|
5386
|
+
this.localPhoneNumber = value;
|
|
5387
|
+
this.fieldChange.emit({ id: this.component.id, value });
|
|
5388
|
+
}
|
|
5389
|
+
return;
|
|
5390
|
+
}
|
|
5391
|
+
// Standard phone-only mode — strip '+' since the picker provides the prefix
|
|
5392
|
+
const cleaned = value.replace(/[^\d\s\-()]/g, "");
|
|
5393
|
+
if (cleaned !== value) {
|
|
5394
|
+
target.value = cleaned;
|
|
5395
|
+
}
|
|
5396
|
+
this.localPhoneNumber = cleaned;
|
|
5397
|
+
const fullNumber = cleaned
|
|
5398
|
+
? `${this.selectedCountry.dialCode}${cleaned}`
|
|
5399
|
+
: "";
|
|
5400
|
+
this.fieldChange.emit({ id: this.component.id, value: fullNumber });
|
|
5401
|
+
};
|
|
4983
5402
|
handleInput = (e) => {
|
|
4984
5403
|
const target = e.target;
|
|
4985
5404
|
this.fieldChange.emit({ id: this.component.id, value: target.value });
|
|
@@ -4989,6 +5408,16 @@ class AuthheroNode {
|
|
|
4989
5408
|
e.preventDefault();
|
|
4990
5409
|
this.buttonClick.emit({ id: "submit", type: "submit", value: "next" });
|
|
4991
5410
|
}
|
|
5411
|
+
// In combined TEL+email mode, backspace on an empty field exits phone mode
|
|
5412
|
+
if (e.key === "Backspace" && !this.telEmailMode) {
|
|
5413
|
+
const target = e.target;
|
|
5414
|
+
const config = this.component.config;
|
|
5415
|
+
if (config?.allow_email === true && target.value.length === 0) {
|
|
5416
|
+
this.telEmailMode = true;
|
|
5417
|
+
this.localPhoneNumber = "";
|
|
5418
|
+
this.fieldChange.emit({ id: this.component.id, value: "" });
|
|
5419
|
+
}
|
|
5420
|
+
}
|
|
4992
5421
|
};
|
|
4993
5422
|
handleCheckbox = (e) => {
|
|
4994
5423
|
const target = e.target;
|
|
@@ -5161,8 +5590,17 @@ class AuthheroNode {
|
|
|
5161
5590
|
renderTelField(component) {
|
|
5162
5591
|
const inputId = `input-${component.id}`;
|
|
5163
5592
|
const errors = this.getErrors();
|
|
5164
|
-
const
|
|
5165
|
-
|
|
5593
|
+
const config = component.config;
|
|
5594
|
+
const allowEmail = config?.allow_email === true;
|
|
5595
|
+
const hasValue = this.localPhoneNumber.length > 0;
|
|
5596
|
+
// In allow_email mode, show the country picker only when the user is typing a phone number
|
|
5597
|
+
const showCountryPicker = allowEmail ? !this.telEmailMode : true;
|
|
5598
|
+
// Calculate dynamic width: flag + space + dial code + small padding for dropdown arrow
|
|
5599
|
+
const selectedText = `${this.selectedCountry.flag} ${this.selectedCountry.dialCode}`;
|
|
5600
|
+
const selectWidth = `${selectedText.length + 1}ch`;
|
|
5601
|
+
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;
|
|
5602
|
+
const inputType = allowEmail && this.telEmailMode ? "text" : "tel";
|
|
5603
|
+
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
5604
|
}
|
|
5167
5605
|
renderUrlField(component) {
|
|
5168
5606
|
const inputId = `input-${component.id}`;
|
|
@@ -5239,7 +5677,21 @@ class AuthheroNode {
|
|
|
5239
5677
|
const safeProvider = this.sanitizeForCssToken(provider);
|
|
5240
5678
|
const strategy = getProviderStrategy(provider);
|
|
5241
5679
|
const icon = getProviderIcon(provider);
|
|
5242
|
-
|
|
5680
|
+
const details = detailsMap.get(provider);
|
|
5681
|
+
const btnClass = `btn btn-secondary btn-social btn-social-${safeProvider}${icon ? "" : " no-icon"}`;
|
|
5682
|
+
const btnPart = `button button-secondary button-social button-social-${safeProvider}`;
|
|
5683
|
+
const content = [
|
|
5684
|
+
icon,
|
|
5685
|
+
hAsync("span", { class: "btn-social-content", part: `button-social-content button-social-content-${safeProvider}` }, hAsync("span", { part: `button-social-text button-social-text-${safeProvider}` }, getButtonText(provider)), hAsync("span", { class: "btn-social-subtitle", part: `button-social-subtitle button-social-subtitle-${safeProvider}` })),
|
|
5686
|
+
];
|
|
5687
|
+
if (details?.href) {
|
|
5688
|
+
return (hAsync("a", { href: this.disabled ? undefined : details.href, class: btnClass, part: btnPart, "data-connection-name": provider, "data-strategy": strategy, key: provider, "aria-disabled": this.disabled ? "true" : undefined, tabindex: this.disabled ? -1 : undefined, onClick: (e) => {
|
|
5689
|
+
if (this.disabled) {
|
|
5690
|
+
e.preventDefault();
|
|
5691
|
+
}
|
|
5692
|
+
} }, content));
|
|
5693
|
+
}
|
|
5694
|
+
return (hAsync("button", { type: "button", class: btnClass, part: btnPart, "data-connection-name": provider, "data-strategy": strategy, disabled: this.disabled, onClick: (e) => this.handleButtonClick(e, "SOCIAL", provider), key: provider }, content));
|
|
5243
5695
|
})));
|
|
5244
5696
|
}
|
|
5245
5697
|
// ===========================================================================
|
|
@@ -5314,6 +5766,14 @@ class AuthheroNode {
|
|
|
5314
5766
|
return null;
|
|
5315
5767
|
}
|
|
5316
5768
|
}
|
|
5769
|
+
static get watchers() { return {
|
|
5770
|
+
"component": [{
|
|
5771
|
+
"componentChanged": 0
|
|
5772
|
+
}],
|
|
5773
|
+
"value": [{
|
|
5774
|
+
"valueChanged": 0
|
|
5775
|
+
}]
|
|
5776
|
+
}; }
|
|
5317
5777
|
static get style() { return authheroNodeCss(); }
|
|
5318
5778
|
static get cmpMeta() { return {
|
|
5319
5779
|
"$flags$": 521,
|
|
@@ -5322,7 +5782,11 @@ class AuthheroNode {
|
|
|
5322
5782
|
"component": [16],
|
|
5323
5783
|
"value": [1],
|
|
5324
5784
|
"disabled": [4],
|
|
5325
|
-
"passwordVisible": [32]
|
|
5785
|
+
"passwordVisible": [32],
|
|
5786
|
+
"selectedCountry": [32],
|
|
5787
|
+
"localPhoneNumber": [32],
|
|
5788
|
+
"countryDropdownOpen": [32],
|
|
5789
|
+
"telEmailMode": [32]
|
|
5326
5790
|
},
|
|
5327
5791
|
"$listeners$": undefined,
|
|
5328
5792
|
"$lazyBundleId$": "-",
|
|
@@ -5335,6 +5799,76 @@ class AuthheroNode {
|
|
|
5335
5799
|
*
|
|
5336
5800
|
* Converts AuthHero branding and theme configurations to CSS custom properties.
|
|
5337
5801
|
*/
|
|
5802
|
+
// --- Inline WCAG contrast utilities (small footprint, no external deps) ---
|
|
5803
|
+
function parseHexColor(hex) {
|
|
5804
|
+
const match = hex.match(/^#([0-9a-f]{3})$/i) || hex.match(/^#([0-9a-f]{6})$/i);
|
|
5805
|
+
if (!match)
|
|
5806
|
+
return null;
|
|
5807
|
+
let clean = match[1];
|
|
5808
|
+
if (clean.length === 3) {
|
|
5809
|
+
clean = clean[0] + clean[0] + clean[1] + clean[1] + clean[2] + clean[2];
|
|
5810
|
+
}
|
|
5811
|
+
const num = parseInt(clean, 16);
|
|
5812
|
+
return [(num >> 16) & 255, (num >> 8) & 255, num & 255];
|
|
5813
|
+
}
|
|
5814
|
+
function srgbLuminance(hex) {
|
|
5815
|
+
const rgb = parseHexColor(hex);
|
|
5816
|
+
if (!rgb)
|
|
5817
|
+
return NaN;
|
|
5818
|
+
const [r, g, b] = rgb.map((c) => {
|
|
5819
|
+
const s = c / 255;
|
|
5820
|
+
return s <= 0.04045 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);
|
|
5821
|
+
});
|
|
5822
|
+
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
5823
|
+
}
|
|
5824
|
+
function wcagContrastRatio(hex1, hex2) {
|
|
5825
|
+
const l1 = srgbLuminance(hex1);
|
|
5826
|
+
const l2 = srgbLuminance(hex2);
|
|
5827
|
+
if (isNaN(l1) || isNaN(l2))
|
|
5828
|
+
return NaN;
|
|
5829
|
+
return (Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05);
|
|
5830
|
+
}
|
|
5831
|
+
function autoTextColor(backgroundHex, mode = "light") {
|
|
5832
|
+
const blackContrast = wcagContrastRatio(backgroundHex, "#000000");
|
|
5833
|
+
const whiteContrast = wcagContrastRatio(backgroundHex, "#ffffff");
|
|
5834
|
+
const BIAS = 1.35;
|
|
5835
|
+
if (mode === "light") {
|
|
5836
|
+
return blackContrast > whiteContrast * BIAS ? "#000000" : "#ffffff";
|
|
5837
|
+
}
|
|
5838
|
+
return blackContrast * BIAS > whiteContrast ? "#000000" : "#ffffff";
|
|
5839
|
+
}
|
|
5840
|
+
function darkenHex(hex, percent) {
|
|
5841
|
+
const rgb = parseHexColor(hex);
|
|
5842
|
+
if (!rgb)
|
|
5843
|
+
return hex;
|
|
5844
|
+
const [r, g, b] = rgb;
|
|
5845
|
+
const toHex = (v) => Math.max(0, Math.round(v * (1 - percent)))
|
|
5846
|
+
.toString(16)
|
|
5847
|
+
.padStart(2, "0");
|
|
5848
|
+
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
5849
|
+
}
|
|
5850
|
+
function lightenHex(hex, percent) {
|
|
5851
|
+
const rgb = parseHexColor(hex);
|
|
5852
|
+
if (!rgb)
|
|
5853
|
+
return hex;
|
|
5854
|
+
const [r, g, b] = rgb;
|
|
5855
|
+
const toHex = (v) => Math.min(255, Math.round(v + (255 - v) * percent))
|
|
5856
|
+
.toString(16)
|
|
5857
|
+
.padStart(2, "0");
|
|
5858
|
+
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
5859
|
+
}
|
|
5860
|
+
function ensureContrastColor(fg, bg, minRatio = 4.5) {
|
|
5861
|
+
if (wcagContrastRatio(fg, bg) >= minRatio)
|
|
5862
|
+
return fg;
|
|
5863
|
+
const shouldDarken = srgbLuminance(bg) > 0.5;
|
|
5864
|
+
let adjusted = fg;
|
|
5865
|
+
for (let i = 1; i <= 10; i++) {
|
|
5866
|
+
adjusted = shouldDarken ? darkenHex(fg, i * 0.1) : lightenHex(fg, i * 0.1);
|
|
5867
|
+
if (wcagContrastRatio(adjusted, bg) >= minRatio)
|
|
5868
|
+
return adjusted;
|
|
5869
|
+
}
|
|
5870
|
+
return shouldDarken ? "#000000" : "#ffffff";
|
|
5871
|
+
}
|
|
5338
5872
|
/**
|
|
5339
5873
|
* Convert a style enum to border radius value
|
|
5340
5874
|
*/
|
|
@@ -5431,9 +5965,22 @@ function themeToCssVars(theme) {
|
|
|
5431
5965
|
if (c.primary_button) {
|
|
5432
5966
|
vars["--ah-color-primary"] = c.primary_button;
|
|
5433
5967
|
vars["--ah-color-primary-hover"] = c.primary_button;
|
|
5968
|
+
// Auto-compute text-on-primary for contrast
|
|
5969
|
+
const hasGoodExplicit = c.primary_button_label &&
|
|
5970
|
+
wcagContrastRatio(c.primary_button_label, c.primary_button) >= 4.5;
|
|
5971
|
+
if (hasGoodExplicit) {
|
|
5972
|
+
vars["--ah-color-text-on-primary"] = c.primary_button_label;
|
|
5973
|
+
}
|
|
5974
|
+
else {
|
|
5975
|
+
vars["--ah-color-text-on-primary"] = autoTextColor(c.primary_button, "light");
|
|
5976
|
+
const darkText = autoTextColor(c.primary_button, "dark");
|
|
5977
|
+
if (darkText !== vars["--ah-color-text-on-primary"]) {
|
|
5978
|
+
vars["--ah-color-text-on-primary-dark"] = darkText;
|
|
5979
|
+
}
|
|
5980
|
+
}
|
|
5434
5981
|
}
|
|
5435
|
-
if (c.primary_button_label) {
|
|
5436
|
-
vars["--ah-
|
|
5982
|
+
else if (c.primary_button_label) {
|
|
5983
|
+
vars["--ah-color-text-on-primary"] = c.primary_button_label;
|
|
5437
5984
|
}
|
|
5438
5985
|
// Secondary button
|
|
5439
5986
|
if (c.secondary_button_border) {
|
|
@@ -5470,9 +6017,10 @@ function themeToCssVars(theme) {
|
|
|
5470
6017
|
if (c.input_border) {
|
|
5471
6018
|
vars["--ah-color-border"] = c.input_border;
|
|
5472
6019
|
}
|
|
5473
|
-
// Links
|
|
6020
|
+
// Links — ensure contrast against widget background
|
|
5474
6021
|
if (c.links_focused_components) {
|
|
5475
|
-
|
|
6022
|
+
const widgetBg = c.widget_background || "#ffffff";
|
|
6023
|
+
vars["--ah-color-link"] = ensureContrastColor(c.links_focused_components, widgetBg);
|
|
5476
6024
|
}
|
|
5477
6025
|
// Focus/hover
|
|
5478
6026
|
if (c.base_focus_color) {
|
|
@@ -5498,6 +6046,10 @@ function themeToCssVars(theme) {
|
|
|
5498
6046
|
const f = theme.fonts;
|
|
5499
6047
|
// reference_text_size is the base font size in pixels (default 16px)
|
|
5500
6048
|
const baseSize = f.reference_text_size || 16;
|
|
6049
|
+
// Font sizes can be stored as percentages (Auth0 convention, e.g. 150 = 150% of base)
|
|
6050
|
+
// or as absolute pixel values (e.g. 24 = 24px). Values >= 50 are treated as
|
|
6051
|
+
// percentages; values < 50 are treated as direct pixel values.
|
|
6052
|
+
const fontSizePx = (size) => size >= 50 ? Math.round((size / 100) * baseSize) : size;
|
|
5501
6053
|
if (f.font_url) {
|
|
5502
6054
|
vars["--ah-font-url"] = f.font_url;
|
|
5503
6055
|
}
|
|
@@ -5506,28 +6058,22 @@ function themeToCssVars(theme) {
|
|
|
5506
6058
|
}
|
|
5507
6059
|
// Title, subtitle, etc. sizes are percentages of the base size
|
|
5508
6060
|
if (f.title?.size) {
|
|
5509
|
-
|
|
5510
|
-
vars["--ah-font-size-title"] = `${titlePx}px`;
|
|
6061
|
+
vars["--ah-font-size-title"] = `${fontSizePx(f.title.size)}px`;
|
|
5511
6062
|
}
|
|
5512
6063
|
if (f.subtitle?.size) {
|
|
5513
|
-
|
|
5514
|
-
vars["--ah-font-size-subtitle"] = `${subtitlePx}px`;
|
|
6064
|
+
vars["--ah-font-size-subtitle"] = `${fontSizePx(f.subtitle.size)}px`;
|
|
5515
6065
|
}
|
|
5516
6066
|
if (f.body_text?.size) {
|
|
5517
|
-
|
|
5518
|
-
vars["--ah-font-size-body"] = `${bodyPx}px`;
|
|
6067
|
+
vars["--ah-font-size-body"] = `${fontSizePx(f.body_text.size)}px`;
|
|
5519
6068
|
}
|
|
5520
6069
|
if (f.input_labels?.size) {
|
|
5521
|
-
|
|
5522
|
-
vars["--ah-font-size-label"] = `${labelPx}px`;
|
|
6070
|
+
vars["--ah-font-size-label"] = `${fontSizePx(f.input_labels.size)}px`;
|
|
5523
6071
|
}
|
|
5524
6072
|
if (f.buttons_text?.size) {
|
|
5525
|
-
|
|
5526
|
-
vars["--ah-font-size-btn"] = `${btnPx}px`;
|
|
6073
|
+
vars["--ah-font-size-btn"] = `${fontSizePx(f.buttons_text.size)}px`;
|
|
5527
6074
|
}
|
|
5528
6075
|
if (f.links?.size) {
|
|
5529
|
-
|
|
5530
|
-
vars["--ah-font-size-link"] = `${linkPx}px`;
|
|
6076
|
+
vars["--ah-font-size-link"] = `${fontSizePx(f.links.size)}px`;
|
|
5531
6077
|
}
|
|
5532
6078
|
if (f.links_style === "underlined") {
|
|
5533
6079
|
vars["--ah-link-decoration"] = "underline";
|
|
@@ -5752,7 +6298,7 @@ function escapeAttr(value) {
|
|
|
5752
6298
|
.replace(/>/g, ">");
|
|
5753
6299
|
}
|
|
5754
6300
|
|
|
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,
|
|
6301
|
+
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
6302
|
|
|
5757
6303
|
class AuthheroWidget {
|
|
5758
6304
|
constructor(hostRef) {
|
|
@@ -6115,6 +6661,25 @@ class AuthheroWidget {
|
|
|
6115
6661
|
}
|
|
6116
6662
|
}
|
|
6117
6663
|
}
|
|
6664
|
+
handlePopState = (event) => {
|
|
6665
|
+
if (!this.apiUrl)
|
|
6666
|
+
return;
|
|
6667
|
+
// Restore the widget state token from history if present
|
|
6668
|
+
if (event.state?.state) {
|
|
6669
|
+
this.state = event.state.state;
|
|
6670
|
+
}
|
|
6671
|
+
// Derive screen from history state or from the current URL
|
|
6672
|
+
const screen = event.state?.screen ?? this.extractScreenIdFromHref(location.href);
|
|
6673
|
+
if (screen) {
|
|
6674
|
+
this.fetchScreen(screen);
|
|
6675
|
+
}
|
|
6676
|
+
};
|
|
6677
|
+
connectedCallback() {
|
|
6678
|
+
window.addEventListener("popstate", this.handlePopState);
|
|
6679
|
+
}
|
|
6680
|
+
disconnectedCallback() {
|
|
6681
|
+
window.removeEventListener("popstate", this.handlePopState);
|
|
6682
|
+
}
|
|
6118
6683
|
async componentWillLoad() {
|
|
6119
6684
|
// Parse initial props - this prevents unnecessary state changes during hydration that cause flashes
|
|
6120
6685
|
// Also check the element attribute as a fallback for hydration scenarios
|
|
@@ -6147,7 +6712,7 @@ class AuthheroWidget {
|
|
|
6147
6712
|
*/
|
|
6148
6713
|
async fetchScreen(screenIdOverride, nodeId) {
|
|
6149
6714
|
if (!this.apiUrl)
|
|
6150
|
-
return;
|
|
6715
|
+
return false;
|
|
6151
6716
|
const currentScreenId = screenIdOverride || this.screenId;
|
|
6152
6717
|
// Build the API URL, replacing {screenId} placeholder if present
|
|
6153
6718
|
let url = this.apiUrl;
|
|
@@ -6202,6 +6767,7 @@ class AuthheroWidget {
|
|
|
6202
6767
|
this.updateDataScreenAttribute();
|
|
6203
6768
|
this.persistState();
|
|
6204
6769
|
this.focusFirstInput();
|
|
6770
|
+
return true;
|
|
6205
6771
|
}
|
|
6206
6772
|
}
|
|
6207
6773
|
else {
|
|
@@ -6222,6 +6788,7 @@ class AuthheroWidget {
|
|
|
6222
6788
|
finally {
|
|
6223
6789
|
this.loading = false;
|
|
6224
6790
|
}
|
|
6791
|
+
return false;
|
|
6225
6792
|
}
|
|
6226
6793
|
handleInputChange = (name, value) => {
|
|
6227
6794
|
this.formData = {
|
|
@@ -6334,6 +6901,18 @@ class AuthheroWidget {
|
|
|
6334
6901
|
this.buttonClick.emit(detail);
|
|
6335
6902
|
// Handle social login if autoNavigate is enabled
|
|
6336
6903
|
if (detail.type === "SOCIAL" && detail.value && this.shouldAutoNavigate) {
|
|
6904
|
+
// Check if this provider has an href (e.g. passwordless connections)
|
|
6905
|
+
const providerHref = this.getProviderHref(detail.value);
|
|
6906
|
+
if (providerHref) {
|
|
6907
|
+
const screenId = this.extractScreenIdFromHref(providerHref);
|
|
6908
|
+
if (screenId && this.apiUrl) {
|
|
6909
|
+
this.navigateToScreen(screenId, providerHref);
|
|
6910
|
+
}
|
|
6911
|
+
else {
|
|
6912
|
+
window.location.href = providerHref;
|
|
6913
|
+
}
|
|
6914
|
+
return;
|
|
6915
|
+
}
|
|
6337
6916
|
this.handleSocialLogin(detail.value);
|
|
6338
6917
|
return;
|
|
6339
6918
|
}
|
|
@@ -6397,6 +6976,30 @@ class AuthheroWidget {
|
|
|
6397
6976
|
console.error("Resend failed:", error);
|
|
6398
6977
|
}
|
|
6399
6978
|
}
|
|
6979
|
+
/**
|
|
6980
|
+
* Extract screen ID from a u2 link href.
|
|
6981
|
+
* Handles patterns like /u2/login/{screenId}?state=... and /u2/{screenId}?state=...
|
|
6982
|
+
* Returns the screen ID or null if the href doesn't match a known pattern.
|
|
6983
|
+
*/
|
|
6984
|
+
extractScreenIdFromHref(href) {
|
|
6985
|
+
try {
|
|
6986
|
+
const url = new URL(href, window.location.origin);
|
|
6987
|
+
const path = url.pathname;
|
|
6988
|
+
// Match /u2/login/{screenId} (e.g., /u2/login/identifier)
|
|
6989
|
+
const loginMatch = path.match(/\/u2\/login\/([^/]+)$/);
|
|
6990
|
+
if (loginMatch)
|
|
6991
|
+
return loginMatch[1];
|
|
6992
|
+
// Match /u2/{screenId} (e.g., /u2/signup, /u2/enter-password)
|
|
6993
|
+
const u2Match = path.match(/\/u2\/([^/]+)$/);
|
|
6994
|
+
if (u2Match && u2Match[1] !== "login" && u2Match[1] !== "screen") {
|
|
6995
|
+
return u2Match[1];
|
|
6996
|
+
}
|
|
6997
|
+
return null;
|
|
6998
|
+
}
|
|
6999
|
+
catch {
|
|
7000
|
+
return null;
|
|
7001
|
+
}
|
|
7002
|
+
}
|
|
6400
7003
|
handleLinkClick = (e, link) => {
|
|
6401
7004
|
// Emit the event so the consuming app can handle it
|
|
6402
7005
|
this.linkClick.emit({
|
|
@@ -6404,12 +7007,52 @@ class AuthheroWidget {
|
|
|
6404
7007
|
href: link.href,
|
|
6405
7008
|
text: link.text,
|
|
6406
7009
|
});
|
|
6407
|
-
// If autoNavigate is enabled,
|
|
6408
|
-
// Otherwise, prevent default and let the app decide
|
|
7010
|
+
// If autoNavigate is not enabled, prevent default and let the app decide
|
|
6409
7011
|
if (!this.shouldAutoNavigate) {
|
|
6410
7012
|
e.preventDefault();
|
|
7013
|
+
return;
|
|
6411
7014
|
}
|
|
7015
|
+
// Try client-side navigation: extract screen ID and fetch via API
|
|
7016
|
+
const screenId = this.extractScreenIdFromHref(link.href);
|
|
7017
|
+
if (screenId && this.apiUrl) {
|
|
7018
|
+
e.preventDefault();
|
|
7019
|
+
this.navigateToScreen(screenId, link.href);
|
|
7020
|
+
return;
|
|
7021
|
+
}
|
|
7022
|
+
// Fall back to browser navigation for non-u2 links
|
|
6412
7023
|
};
|
|
7024
|
+
/**
|
|
7025
|
+
* Navigate to a screen client-side by fetching it from the API.
|
|
7026
|
+
* Updates the widget state and browser URL without a full page reload.
|
|
7027
|
+
*/
|
|
7028
|
+
async navigateToScreen(screenId, displayUrl) {
|
|
7029
|
+
const success = await this.fetchScreen(screenId);
|
|
7030
|
+
if (success) {
|
|
7031
|
+
// Push browser history so back/forward works
|
|
7032
|
+
window.history.pushState({ screen: screenId, state: this.state }, "", displayUrl);
|
|
7033
|
+
}
|
|
7034
|
+
else {
|
|
7035
|
+
// On failure, fall back to hard navigation
|
|
7036
|
+
window.location.href = displayUrl;
|
|
7037
|
+
}
|
|
7038
|
+
}
|
|
7039
|
+
/**
|
|
7040
|
+
* Look up the href for a social provider from the current screen's SOCIAL components.
|
|
7041
|
+
* Returns the href if found (e.g. for passwordless connections), or null.
|
|
7042
|
+
*/
|
|
7043
|
+
getProviderHref(connectionName) {
|
|
7044
|
+
if (!this._screen)
|
|
7045
|
+
return null;
|
|
7046
|
+
for (const comp of this._screen.components) {
|
|
7047
|
+
const c = comp;
|
|
7048
|
+
if (c.type === "SOCIAL" && c.config?.provider_details) {
|
|
7049
|
+
const match = c.config.provider_details.find((d) => d.name === connectionName);
|
|
7050
|
+
if (match?.href)
|
|
7051
|
+
return match.href;
|
|
7052
|
+
}
|
|
7053
|
+
}
|
|
7054
|
+
return null;
|
|
7055
|
+
}
|
|
6413
7056
|
/**
|
|
6414
7057
|
* Check if a component is a social button.
|
|
6415
7058
|
*/
|