@authhero/widget 0.7.2 → 0.8.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/README.md +118 -66
- package/dist/authhero-widget/authhero-widget.esm.js +1 -1
- package/dist/authhero-widget/p-6e32b31d.entry.js +1 -0
- package/dist/cjs/authhero-widget.cjs.entry.js +311 -32
- package/dist/cjs/authhero-widget.cjs.js +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/collection/components/authhero-widget/authhero-widget.js +470 -34
- package/dist/components/authhero-widget.js +1 -1
- package/dist/esm/authhero-widget.entry.js +311 -32
- package/dist/esm/authhero-widget.js +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/types/components/authhero-widget/authhero-widget.d.ts +96 -4
- package/dist/types/components.d.ts +66 -4
- package/hydrate/index.js +319 -32
- package/hydrate/index.mjs +319 -32
- package/package.json +1 -1
- package/dist/authhero-widget/p-ea2660b2.entry.js +0 -1
package/hydrate/index.mjs
CHANGED
|
@@ -5614,8 +5614,43 @@ class AuthheroWidget {
|
|
|
5614
5614
|
/**
|
|
5615
5615
|
* API endpoint to fetch the initial screen from.
|
|
5616
5616
|
* If provided, the widget will fetch the screen on load.
|
|
5617
|
+
* Can include {screenId} placeholder which will be replaced with the current screen.
|
|
5618
|
+
* Example: "/u2/screen/{screenId}" or "https://auth.example.com/u2/screen/{screenId}"
|
|
5617
5619
|
*/
|
|
5618
5620
|
apiUrl;
|
|
5621
|
+
/**
|
|
5622
|
+
* Base URL for all API calls. Used when widget is embedded on a different domain.
|
|
5623
|
+
* If not provided, relative URLs are used.
|
|
5624
|
+
* Example: "https://auth.example.com"
|
|
5625
|
+
*/
|
|
5626
|
+
baseUrl;
|
|
5627
|
+
/**
|
|
5628
|
+
* Login session state token. Required for social login and maintaining session.
|
|
5629
|
+
*/
|
|
5630
|
+
state;
|
|
5631
|
+
/**
|
|
5632
|
+
* Current screen ID. Used with apiUrl to fetch screen configuration.
|
|
5633
|
+
* When statePersistence is 'url', this is synced with the URL.
|
|
5634
|
+
*/
|
|
5635
|
+
screenId;
|
|
5636
|
+
/**
|
|
5637
|
+
* OAuth/OIDC parameters for social login redirects.
|
|
5638
|
+
* Can be passed as a JSON string or object.
|
|
5639
|
+
*/
|
|
5640
|
+
authParams;
|
|
5641
|
+
/**
|
|
5642
|
+
* Where to persist state and screen ID.
|
|
5643
|
+
* - 'url': Updates URL path/query (default for standalone pages)
|
|
5644
|
+
* - 'session': Uses sessionStorage (for embedded widgets)
|
|
5645
|
+
* - 'memory': No persistence, state only in memory
|
|
5646
|
+
* @default 'memory'
|
|
5647
|
+
*/
|
|
5648
|
+
statePersistence = "memory";
|
|
5649
|
+
/**
|
|
5650
|
+
* Storage key prefix for session/local storage persistence.
|
|
5651
|
+
* @default 'authhero_widget'
|
|
5652
|
+
*/
|
|
5653
|
+
storageKey = "authhero_widget";
|
|
5619
5654
|
/**
|
|
5620
5655
|
* Branding configuration from AuthHero API.
|
|
5621
5656
|
* Controls logo, primary color, and page background.
|
|
@@ -5640,10 +5675,21 @@ class AuthheroWidget {
|
|
|
5640
5675
|
* @default false
|
|
5641
5676
|
*/
|
|
5642
5677
|
autoSubmit = false;
|
|
5678
|
+
/**
|
|
5679
|
+
* Whether the widget should handle navigation automatically.
|
|
5680
|
+
* When true, social login buttons redirect, links navigate, etc.
|
|
5681
|
+
* When false, only events are emitted.
|
|
5682
|
+
* @default false (same as autoSubmit when not specified)
|
|
5683
|
+
*/
|
|
5684
|
+
autoNavigate;
|
|
5643
5685
|
/**
|
|
5644
5686
|
* Internal parsed screen state.
|
|
5645
5687
|
*/
|
|
5646
5688
|
_screen;
|
|
5689
|
+
/**
|
|
5690
|
+
* Internal parsed auth params state.
|
|
5691
|
+
*/
|
|
5692
|
+
_authParams;
|
|
5647
5693
|
/**
|
|
5648
5694
|
* Internal parsed branding state.
|
|
5649
5695
|
*/
|
|
@@ -5690,12 +5736,12 @@ class AuthheroWidget {
|
|
|
5690
5736
|
*/
|
|
5691
5737
|
screenChange;
|
|
5692
5738
|
watchScreen(newValue) {
|
|
5693
|
-
if (typeof newValue ===
|
|
5739
|
+
if (typeof newValue === "string") {
|
|
5694
5740
|
try {
|
|
5695
5741
|
this._screen = JSON.parse(newValue);
|
|
5696
5742
|
}
|
|
5697
5743
|
catch {
|
|
5698
|
-
console.error(
|
|
5744
|
+
console.error("Failed to parse screen JSON");
|
|
5699
5745
|
}
|
|
5700
5746
|
}
|
|
5701
5747
|
else {
|
|
@@ -5706,12 +5752,12 @@ class AuthheroWidget {
|
|
|
5706
5752
|
}
|
|
5707
5753
|
}
|
|
5708
5754
|
watchBranding(newValue) {
|
|
5709
|
-
if (typeof newValue ===
|
|
5755
|
+
if (typeof newValue === "string") {
|
|
5710
5756
|
try {
|
|
5711
5757
|
this._branding = JSON.parse(newValue);
|
|
5712
5758
|
}
|
|
5713
5759
|
catch {
|
|
5714
|
-
console.error(
|
|
5760
|
+
console.error("Failed to parse branding JSON");
|
|
5715
5761
|
}
|
|
5716
5762
|
}
|
|
5717
5763
|
else {
|
|
@@ -5720,12 +5766,12 @@ class AuthheroWidget {
|
|
|
5720
5766
|
this.applyThemeStyles();
|
|
5721
5767
|
}
|
|
5722
5768
|
watchTheme(newValue) {
|
|
5723
|
-
if (typeof newValue ===
|
|
5769
|
+
if (typeof newValue === "string") {
|
|
5724
5770
|
try {
|
|
5725
5771
|
this._theme = JSON.parse(newValue);
|
|
5726
5772
|
}
|
|
5727
5773
|
catch {
|
|
5728
|
-
console.error(
|
|
5774
|
+
console.error("Failed to parse theme JSON");
|
|
5729
5775
|
}
|
|
5730
5776
|
}
|
|
5731
5777
|
else {
|
|
@@ -5733,6 +5779,19 @@ class AuthheroWidget {
|
|
|
5733
5779
|
}
|
|
5734
5780
|
this.applyThemeStyles();
|
|
5735
5781
|
}
|
|
5782
|
+
watchAuthParams(newValue) {
|
|
5783
|
+
if (typeof newValue === "string") {
|
|
5784
|
+
try {
|
|
5785
|
+
this._authParams = JSON.parse(newValue);
|
|
5786
|
+
}
|
|
5787
|
+
catch {
|
|
5788
|
+
console.error("Failed to parse authParams JSON");
|
|
5789
|
+
}
|
|
5790
|
+
}
|
|
5791
|
+
else {
|
|
5792
|
+
this._authParams = newValue;
|
|
5793
|
+
}
|
|
5794
|
+
}
|
|
5736
5795
|
/**
|
|
5737
5796
|
* Apply branding and theme as CSS custom properties
|
|
5738
5797
|
*/
|
|
@@ -5740,36 +5799,164 @@ class AuthheroWidget {
|
|
|
5740
5799
|
const vars = mergeThemeVars(this._branding, this._theme);
|
|
5741
5800
|
applyCssVars(this.el, vars);
|
|
5742
5801
|
}
|
|
5802
|
+
/**
|
|
5803
|
+
* Get the effective autoNavigate value (defaults to autoSubmit if not set)
|
|
5804
|
+
*/
|
|
5805
|
+
get shouldAutoNavigate() {
|
|
5806
|
+
return this.autoNavigate ?? this.autoSubmit;
|
|
5807
|
+
}
|
|
5808
|
+
/**
|
|
5809
|
+
* Build the full URL for API calls
|
|
5810
|
+
*/
|
|
5811
|
+
buildUrl(path) {
|
|
5812
|
+
if (this.baseUrl) {
|
|
5813
|
+
return new URL(path, this.baseUrl).toString();
|
|
5814
|
+
}
|
|
5815
|
+
return path;
|
|
5816
|
+
}
|
|
5817
|
+
/**
|
|
5818
|
+
* Load state from URL or storage based on statePersistence setting
|
|
5819
|
+
*/
|
|
5820
|
+
loadPersistedState() {
|
|
5821
|
+
if (this.statePersistence === "url") {
|
|
5822
|
+
const url = new URL(window.location.href);
|
|
5823
|
+
const stateParam = url.searchParams.get("state");
|
|
5824
|
+
if (stateParam && !this.state) {
|
|
5825
|
+
this.state = stateParam;
|
|
5826
|
+
}
|
|
5827
|
+
}
|
|
5828
|
+
else if (this.statePersistence === "session") {
|
|
5829
|
+
try {
|
|
5830
|
+
const stored = sessionStorage.getItem(`${this.storageKey}_state`);
|
|
5831
|
+
if (stored && !this.state) {
|
|
5832
|
+
this.state = stored;
|
|
5833
|
+
}
|
|
5834
|
+
const storedScreenId = sessionStorage.getItem(`${this.storageKey}_screenId`);
|
|
5835
|
+
if (storedScreenId && !this.screenId) {
|
|
5836
|
+
this.screenId = storedScreenId;
|
|
5837
|
+
}
|
|
5838
|
+
}
|
|
5839
|
+
catch {
|
|
5840
|
+
// sessionStorage not available
|
|
5841
|
+
}
|
|
5842
|
+
}
|
|
5843
|
+
}
|
|
5844
|
+
/**
|
|
5845
|
+
* Save state to URL or storage based on statePersistence setting
|
|
5846
|
+
*/
|
|
5847
|
+
persistState() {
|
|
5848
|
+
if (this.statePersistence === "url") {
|
|
5849
|
+
const url = new URL(window.location.href);
|
|
5850
|
+
if (this.state) {
|
|
5851
|
+
url.searchParams.set("state", this.state);
|
|
5852
|
+
}
|
|
5853
|
+
if (this.screenId) {
|
|
5854
|
+
url.searchParams.set("screen", this.screenId);
|
|
5855
|
+
}
|
|
5856
|
+
window.history.replaceState({}, "", url.toString());
|
|
5857
|
+
}
|
|
5858
|
+
else if (this.statePersistence === "session") {
|
|
5859
|
+
try {
|
|
5860
|
+
if (this.state) {
|
|
5861
|
+
sessionStorage.setItem(`${this.storageKey}_state`, this.state);
|
|
5862
|
+
}
|
|
5863
|
+
if (this.screenId) {
|
|
5864
|
+
sessionStorage.setItem(`${this.storageKey}_screenId`, this.screenId);
|
|
5865
|
+
}
|
|
5866
|
+
}
|
|
5867
|
+
catch {
|
|
5868
|
+
// sessionStorage not available
|
|
5869
|
+
}
|
|
5870
|
+
}
|
|
5871
|
+
}
|
|
5743
5872
|
async componentWillLoad() {
|
|
5744
5873
|
// Parse initial props
|
|
5745
5874
|
this.watchScreen(this.screen);
|
|
5746
5875
|
this.watchBranding(this.branding);
|
|
5747
5876
|
this.watchTheme(this.theme);
|
|
5877
|
+
this.watchAuthParams(this.authParams);
|
|
5878
|
+
// Load persisted state if available
|
|
5879
|
+
this.loadPersistedState();
|
|
5748
5880
|
// Fetch screen from API if URL provided and no screen prop
|
|
5749
5881
|
if (this.apiUrl && !this._screen) {
|
|
5750
|
-
await this.fetchScreen();
|
|
5882
|
+
await this.fetchScreen(this.screenId);
|
|
5751
5883
|
}
|
|
5752
5884
|
}
|
|
5753
|
-
|
|
5885
|
+
/**
|
|
5886
|
+
* Fetch screen configuration from the API
|
|
5887
|
+
* @param screenIdOverride Optional screen ID to fetch (overrides this.screenId)
|
|
5888
|
+
* @param nodeId Optional node ID for flow navigation
|
|
5889
|
+
*/
|
|
5890
|
+
async fetchScreen(screenIdOverride, nodeId) {
|
|
5754
5891
|
if (!this.apiUrl)
|
|
5755
5892
|
return;
|
|
5893
|
+
const currentScreenId = screenIdOverride || this.screenId;
|
|
5894
|
+
// Build the API URL, replacing {screenId} placeholder if present
|
|
5895
|
+
let url = this.apiUrl;
|
|
5896
|
+
if (currentScreenId && url.includes("{screenId}")) {
|
|
5897
|
+
url = url.replace("{screenId}", encodeURIComponent(currentScreenId));
|
|
5898
|
+
}
|
|
5899
|
+
// Add state and nodeId as query params
|
|
5900
|
+
const urlObj = new URL(url, this.baseUrl || window.location.origin);
|
|
5901
|
+
if (this.state) {
|
|
5902
|
+
urlObj.searchParams.set("state", this.state);
|
|
5903
|
+
}
|
|
5904
|
+
if (nodeId) {
|
|
5905
|
+
urlObj.searchParams.set("nodeId", nodeId);
|
|
5906
|
+
}
|
|
5756
5907
|
this.loading = true;
|
|
5757
5908
|
try {
|
|
5758
|
-
const response = await fetch(this.
|
|
5759
|
-
credentials:
|
|
5909
|
+
const response = await fetch(this.buildUrl(urlObj.pathname + urlObj.search), {
|
|
5910
|
+
credentials: "include",
|
|
5760
5911
|
headers: {
|
|
5761
|
-
Accept:
|
|
5912
|
+
Accept: "application/json",
|
|
5762
5913
|
},
|
|
5763
5914
|
});
|
|
5764
5915
|
if (response.ok) {
|
|
5765
|
-
|
|
5916
|
+
const data = await response.json();
|
|
5917
|
+
// Handle different response formats
|
|
5918
|
+
if (data.screen) {
|
|
5919
|
+
this._screen = data.screen;
|
|
5920
|
+
if (data.branding) {
|
|
5921
|
+
this._branding = data.branding;
|
|
5922
|
+
this.applyThemeStyles();
|
|
5923
|
+
}
|
|
5924
|
+
// Update state if returned
|
|
5925
|
+
if (data.state) {
|
|
5926
|
+
this.state = data.state;
|
|
5927
|
+
}
|
|
5928
|
+
// Update screenId if returned in response
|
|
5929
|
+
if (data.screenId) {
|
|
5930
|
+
this.screenId = data.screenId;
|
|
5931
|
+
}
|
|
5932
|
+
}
|
|
5933
|
+
else {
|
|
5934
|
+
// Response is the screen itself
|
|
5935
|
+
this._screen = data;
|
|
5936
|
+
}
|
|
5766
5937
|
if (this._screen) {
|
|
5938
|
+
// If we fetched with a screenId override, update our stored screenId
|
|
5939
|
+
if (currentScreenId && currentScreenId !== this.screenId) {
|
|
5940
|
+
this.screenId = currentScreenId;
|
|
5941
|
+
}
|
|
5767
5942
|
this.screenChange.emit(this._screen);
|
|
5943
|
+
this.persistState();
|
|
5768
5944
|
}
|
|
5769
5945
|
}
|
|
5946
|
+
else {
|
|
5947
|
+
const error = await response
|
|
5948
|
+
.json()
|
|
5949
|
+
.catch(() => ({ message: "Failed to load screen" }));
|
|
5950
|
+
this.flowError.emit({
|
|
5951
|
+
message: error.message || "Failed to load screen",
|
|
5952
|
+
});
|
|
5953
|
+
}
|
|
5770
5954
|
}
|
|
5771
5955
|
catch (error) {
|
|
5772
|
-
console.error(
|
|
5956
|
+
console.error("Failed to fetch screen:", error);
|
|
5957
|
+
this.flowError.emit({
|
|
5958
|
+
message: error instanceof Error ? error.message : "Failed to fetch screen",
|
|
5959
|
+
});
|
|
5773
5960
|
}
|
|
5774
5961
|
finally {
|
|
5775
5962
|
this.loading = false;
|
|
@@ -5797,17 +5984,17 @@ class AuthheroWidget {
|
|
|
5797
5984
|
// Submit to the server
|
|
5798
5985
|
this.loading = true;
|
|
5799
5986
|
try {
|
|
5800
|
-
const response = await fetch(this._screen.action, {
|
|
5987
|
+
const response = await fetch(this.buildUrl(this._screen.action), {
|
|
5801
5988
|
method: this._screen.method,
|
|
5802
|
-
credentials:
|
|
5989
|
+
credentials: "include",
|
|
5803
5990
|
headers: {
|
|
5804
|
-
|
|
5805
|
-
Accept:
|
|
5991
|
+
"Content-Type": "application/json",
|
|
5992
|
+
Accept: "application/json",
|
|
5806
5993
|
},
|
|
5807
5994
|
body: JSON.stringify({ data: this.formData }),
|
|
5808
5995
|
});
|
|
5809
|
-
const contentType = response.headers.get(
|
|
5810
|
-
if (contentType?.includes(
|
|
5996
|
+
const contentType = response.headers.get("content-type");
|
|
5997
|
+
if (contentType?.includes("application/json")) {
|
|
5811
5998
|
const result = await response.json();
|
|
5812
5999
|
// Handle different response types
|
|
5813
6000
|
if (result.redirect) {
|
|
@@ -5815,17 +6002,31 @@ class AuthheroWidget {
|
|
|
5815
6002
|
this.flowComplete.emit({ redirectUrl: result.redirect });
|
|
5816
6003
|
// Also emit navigate for backwards compatibility
|
|
5817
6004
|
this.navigate.emit({ url: result.redirect });
|
|
6005
|
+
// Auto-navigate if enabled
|
|
6006
|
+
if (this.shouldAutoNavigate) {
|
|
6007
|
+
window.location.href = result.redirect;
|
|
6008
|
+
}
|
|
5818
6009
|
}
|
|
5819
6010
|
else if (result.screen) {
|
|
5820
6011
|
// Next screen
|
|
5821
6012
|
this._screen = result.screen;
|
|
5822
6013
|
this.formData = {};
|
|
5823
6014
|
this.screenChange.emit(result.screen);
|
|
6015
|
+
// Update screenId if returned in response
|
|
6016
|
+
if (result.screenId) {
|
|
6017
|
+
this.screenId = result.screenId;
|
|
6018
|
+
}
|
|
6019
|
+
this.persistState();
|
|
5824
6020
|
// Apply branding if included
|
|
5825
6021
|
if (result.branding) {
|
|
5826
6022
|
this._branding = result.branding;
|
|
5827
6023
|
this.applyThemeStyles();
|
|
5828
6024
|
}
|
|
6025
|
+
// Update state if returned
|
|
6026
|
+
if (result.state) {
|
|
6027
|
+
this.state = result.state;
|
|
6028
|
+
this.persistState();
|
|
6029
|
+
}
|
|
5829
6030
|
}
|
|
5830
6031
|
else if (result.complete) {
|
|
5831
6032
|
// Flow complete without redirect
|
|
@@ -5839,9 +6040,9 @@ class AuthheroWidget {
|
|
|
5839
6040
|
}
|
|
5840
6041
|
}
|
|
5841
6042
|
catch (err) {
|
|
5842
|
-
console.error(
|
|
6043
|
+
console.error("Form submission failed:", err);
|
|
5843
6044
|
this.flowError.emit({
|
|
5844
|
-
message: err instanceof Error ? err.message :
|
|
6045
|
+
message: err instanceof Error ? err.message : "Form submission failed",
|
|
5845
6046
|
});
|
|
5846
6047
|
}
|
|
5847
6048
|
finally {
|
|
@@ -5850,14 +6051,79 @@ class AuthheroWidget {
|
|
|
5850
6051
|
};
|
|
5851
6052
|
handleButtonClick = (detail) => {
|
|
5852
6053
|
// If this is a submit button click, trigger form submission
|
|
5853
|
-
if (detail.type ===
|
|
6054
|
+
if (detail.type === "submit") {
|
|
5854
6055
|
// Create a synthetic submit event and call handleSubmit
|
|
5855
6056
|
const syntheticEvent = { preventDefault: () => { } };
|
|
5856
6057
|
this.handleSubmit(syntheticEvent);
|
|
5857
6058
|
return;
|
|
5858
6059
|
}
|
|
6060
|
+
// Always emit the event
|
|
5859
6061
|
this.buttonClick.emit(detail);
|
|
6062
|
+
// Handle social login if autoNavigate is enabled
|
|
6063
|
+
if (detail.type === "SOCIAL" && detail.value && this.shouldAutoNavigate) {
|
|
6064
|
+
this.handleSocialLogin(detail.value);
|
|
6065
|
+
return;
|
|
6066
|
+
}
|
|
6067
|
+
// Handle resend button
|
|
6068
|
+
if (detail.type === "RESEND_BUTTON" && this.shouldAutoNavigate) {
|
|
6069
|
+
this.handleResend();
|
|
6070
|
+
return;
|
|
6071
|
+
}
|
|
5860
6072
|
};
|
|
6073
|
+
/**
|
|
6074
|
+
* Handle social login redirect
|
|
6075
|
+
*/
|
|
6076
|
+
handleSocialLogin(connection) {
|
|
6077
|
+
const params = this._authParams || {};
|
|
6078
|
+
const queryParams = {
|
|
6079
|
+
connection,
|
|
6080
|
+
};
|
|
6081
|
+
// Add state
|
|
6082
|
+
if (this.state) {
|
|
6083
|
+
queryParams.state = this.state;
|
|
6084
|
+
}
|
|
6085
|
+
else if (params.state) {
|
|
6086
|
+
queryParams.state = params.state;
|
|
6087
|
+
}
|
|
6088
|
+
// Add client_id
|
|
6089
|
+
if (params.client_id) {
|
|
6090
|
+
queryParams.client_id = params.client_id;
|
|
6091
|
+
}
|
|
6092
|
+
// Add optional params
|
|
6093
|
+
if (params.redirect_uri)
|
|
6094
|
+
queryParams.redirect_uri = params.redirect_uri;
|
|
6095
|
+
if (params.scope)
|
|
6096
|
+
queryParams.scope = params.scope;
|
|
6097
|
+
if (params.audience)
|
|
6098
|
+
queryParams.audience = params.audience;
|
|
6099
|
+
if (params.nonce)
|
|
6100
|
+
queryParams.nonce = params.nonce;
|
|
6101
|
+
if (params.response_type)
|
|
6102
|
+
queryParams.response_type = params.response_type;
|
|
6103
|
+
const socialUrl = this.buildUrl("/authorize?" + new URLSearchParams(queryParams).toString());
|
|
6104
|
+
// Emit navigate event and redirect
|
|
6105
|
+
this.navigate.emit({ url: socialUrl });
|
|
6106
|
+
window.location.href = socialUrl;
|
|
6107
|
+
}
|
|
6108
|
+
/**
|
|
6109
|
+
* Handle resend button click (e.g., resend OTP code)
|
|
6110
|
+
*/
|
|
6111
|
+
async handleResend() {
|
|
6112
|
+
if (!this._screen?.action)
|
|
6113
|
+
return;
|
|
6114
|
+
try {
|
|
6115
|
+
const url = this._screen.action +
|
|
6116
|
+
(this._screen.action.includes("?") ? "&" : "?") +
|
|
6117
|
+
"action=resend";
|
|
6118
|
+
await fetch(this.buildUrl(url), {
|
|
6119
|
+
method: "POST",
|
|
6120
|
+
credentials: "include",
|
|
6121
|
+
});
|
|
6122
|
+
}
|
|
6123
|
+
catch (error) {
|
|
6124
|
+
console.error("Resend failed:", error);
|
|
6125
|
+
}
|
|
6126
|
+
}
|
|
5861
6127
|
handleLinkClick = (e, link) => {
|
|
5862
6128
|
// Emit the event so the consuming app can handle it
|
|
5863
6129
|
this.linkClick.emit({
|
|
@@ -5865,9 +6131,9 @@ class AuthheroWidget {
|
|
|
5865
6131
|
href: link.href,
|
|
5866
6132
|
text: link.text,
|
|
5867
6133
|
});
|
|
5868
|
-
// If
|
|
6134
|
+
// If autoNavigate is enabled, let the browser handle the navigation
|
|
5869
6135
|
// Otherwise, prevent default and let the app decide
|
|
5870
|
-
if (!this.
|
|
6136
|
+
if (!this.shouldAutoNavigate) {
|
|
5871
6137
|
e.preventDefault();
|
|
5872
6138
|
}
|
|
5873
6139
|
};
|
|
@@ -5875,13 +6141,13 @@ class AuthheroWidget {
|
|
|
5875
6141
|
* Get error messages from the screen-level messages array.
|
|
5876
6142
|
*/
|
|
5877
6143
|
getScreenErrors() {
|
|
5878
|
-
return this._screen?.messages?.filter((m) => m.type ===
|
|
6144
|
+
return this._screen?.messages?.filter((m) => m.type === "error") || [];
|
|
5879
6145
|
}
|
|
5880
6146
|
/**
|
|
5881
6147
|
* Get success messages from the screen-level messages array.
|
|
5882
6148
|
*/
|
|
5883
6149
|
getScreenSuccesses() {
|
|
5884
|
-
return this._screen?.messages?.filter((m) => m.type ===
|
|
6150
|
+
return this._screen?.messages?.filter((m) => m.type === "success") || [];
|
|
5885
6151
|
}
|
|
5886
6152
|
/**
|
|
5887
6153
|
* Sort components by order.
|
|
@@ -5899,13 +6165,13 @@ class AuthheroWidget {
|
|
|
5899
6165
|
isSocialComponent(component) {
|
|
5900
6166
|
// Check the type property directly - FormComponent has a 'type' field
|
|
5901
6167
|
// SocialField has type 'SOCIAL'
|
|
5902
|
-
return component.type ===
|
|
6168
|
+
return component.type === "SOCIAL";
|
|
5903
6169
|
}
|
|
5904
6170
|
/**
|
|
5905
6171
|
* Check if a component is a divider.
|
|
5906
6172
|
*/
|
|
5907
6173
|
isDividerComponent(component) {
|
|
5908
|
-
return component.type ===
|
|
6174
|
+
return component.type === "DIVIDER";
|
|
5909
6175
|
}
|
|
5910
6176
|
render() {
|
|
5911
6177
|
if (this.loading && !this._screen) {
|
|
@@ -5918,12 +6184,22 @@ class AuthheroWidget {
|
|
|
5918
6184
|
const screenSuccesses = this.getScreenSuccesses();
|
|
5919
6185
|
const components = this.getOrderedComponents();
|
|
5920
6186
|
// Separate social, divider, and field components for layout ordering
|
|
5921
|
-
const socialComponents = components.filter(c => this.isSocialComponent(c));
|
|
5922
|
-
const fieldComponents = components.filter(c => !this.isSocialComponent(c) && !this.isDividerComponent(c));
|
|
5923
|
-
const hasDivider = components.some(c => this.isDividerComponent(c));
|
|
6187
|
+
const socialComponents = components.filter((c) => this.isSocialComponent(c));
|
|
6188
|
+
const fieldComponents = components.filter((c) => !this.isSocialComponent(c) && !this.isDividerComponent(c));
|
|
6189
|
+
const hasDivider = components.some((c) => this.isDividerComponent(c));
|
|
5924
6190
|
// Get logo URL from theme.widget (takes precedence) or branding
|
|
5925
6191
|
const logoUrl = this._theme?.widget?.logo_url || this._branding?.logo_url;
|
|
5926
|
-
return (hAsync("div", { class: "widget-container", part: "container" }, hAsync("header", { class: "widget-header", part: "header" }, logoUrl && (hAsync("div", { class: "logo-wrapper", part: "logo-wrapper" }, hAsync("img", { class: "logo", part: "logo", src: logoUrl, alt: "Logo" }))), this._screen.title && (hAsync("h1", { class: "title", part: "title" }, this._screen.title)), this._screen.description && (hAsync("p", { class: "description", part: "description" }, this._screen.description))), hAsync("div", { class: "widget-body", part: "body" }, screenErrors.map((err) => (hAsync("div", { class: "message message-error", part: "message message-error", key: err.id ?? err.text }, err.text))), screenSuccesses.map((msg) => (hAsync("div", { class: "message message-success", part: "message message-success", key: msg.id ?? msg.text }, msg.text))), hAsync("form", { onSubmit: this.handleSubmit, part: "form" }, hAsync("div", { class: "form-content" }, socialComponents.length > 0 && (hAsync("div", { class: "social-section", part: "social-section" }, socialComponents.map((component) => (hAsync("authhero-node", { key: component.id, component: component, value: this.formData[component.id], onFieldChange: (e) => this.handleInputChange(e.detail.id, e.detail.value), onButtonClick: (e) => this.handleButtonClick(e.detail), disabled: this.loading }))))), socialComponents.length > 0 &&
|
|
6192
|
+
return (hAsync("div", { class: "widget-container", part: "container" }, hAsync("header", { class: "widget-header", part: "header" }, logoUrl && (hAsync("div", { class: "logo-wrapper", part: "logo-wrapper" }, hAsync("img", { class: "logo", part: "logo", src: logoUrl, alt: "Logo" }))), this._screen.title && (hAsync("h1", { class: "title", part: "title" }, this._screen.title)), this._screen.description && (hAsync("p", { class: "description", part: "description" }, this._screen.description))), hAsync("div", { class: "widget-body", part: "body" }, screenErrors.map((err) => (hAsync("div", { class: "message message-error", part: "message message-error", key: err.id ?? err.text }, err.text))), screenSuccesses.map((msg) => (hAsync("div", { class: "message message-success", part: "message message-success", key: msg.id ?? msg.text }, msg.text))), hAsync("form", { onSubmit: this.handleSubmit, part: "form" }, hAsync("div", { class: "form-content" }, socialComponents.length > 0 && (hAsync("div", { class: "social-section", part: "social-section" }, socialComponents.map((component) => (hAsync("authhero-node", { key: component.id, component: component, value: this.formData[component.id], onFieldChange: (e) => this.handleInputChange(e.detail.id, e.detail.value), onButtonClick: (e) => this.handleButtonClick(e.detail), disabled: this.loading }))))), socialComponents.length > 0 &&
|
|
6193
|
+
fieldComponents.length > 0 &&
|
|
6194
|
+
hasDivider && (hAsync("div", { class: "divider", part: "divider" }, hAsync("span", { class: "divider-text" }, "Or"))), hAsync("div", { class: "fields-section", part: "fields-section" }, fieldComponents.map((component) => (hAsync("authhero-node", { key: component.id, component: component, value: this.formData[component.id], onFieldChange: (e) => this.handleInputChange(e.detail.id, e.detail.value), onButtonClick: (e) => this.handleButtonClick(e.detail), disabled: this.loading })))))), this._screen.links && this._screen.links.length > 0 && (hAsync("div", { class: "links", part: "links" }, this._screen.links.map((link) => (hAsync("span", { class: "link-wrapper", part: "link-wrapper", key: link.id ?? link.href }, link.linkText ? (hAsync("span", null, link.text, " ", hAsync("a", { href: link.href, class: "link", part: "link", onClick: (e) => this.handleLinkClick(e, {
|
|
6195
|
+
id: link.id,
|
|
6196
|
+
href: link.href,
|
|
6197
|
+
text: link.linkText || link.text,
|
|
6198
|
+
}) }, link.linkText))) : (hAsync("a", { href: link.href, class: "link", part: "link", onClick: (e) => this.handleLinkClick(e, {
|
|
6199
|
+
id: link.id,
|
|
6200
|
+
href: link.href,
|
|
6201
|
+
text: link.text,
|
|
6202
|
+
}) }, link.text))))))))));
|
|
5927
6203
|
}
|
|
5928
6204
|
static get watchers() { return {
|
|
5929
6205
|
"screen": [{
|
|
@@ -5934,6 +6210,9 @@ class AuthheroWidget {
|
|
|
5934
6210
|
}],
|
|
5935
6211
|
"theme": [{
|
|
5936
6212
|
"watchTheme": 0
|
|
6213
|
+
}],
|
|
6214
|
+
"authParams": [{
|
|
6215
|
+
"watchAuthParams": 0
|
|
5937
6216
|
}]
|
|
5938
6217
|
}; }
|
|
5939
6218
|
static get style() { return authheroWidgetCss(); }
|
|
@@ -5943,11 +6222,19 @@ class AuthheroWidget {
|
|
|
5943
6222
|
"$members$": {
|
|
5944
6223
|
"screen": [1],
|
|
5945
6224
|
"apiUrl": [1, "api-url"],
|
|
6225
|
+
"baseUrl": [1, "base-url"],
|
|
6226
|
+
"state": [1025],
|
|
6227
|
+
"screenId": [1025, "screen-id"],
|
|
6228
|
+
"authParams": [1, "auth-params"],
|
|
6229
|
+
"statePersistence": [1, "state-persistence"],
|
|
6230
|
+
"storageKey": [1, "storage-key"],
|
|
5946
6231
|
"branding": [1],
|
|
5947
6232
|
"theme": [1],
|
|
5948
6233
|
"loading": [1028],
|
|
5949
6234
|
"autoSubmit": [4, "auto-submit"],
|
|
6235
|
+
"autoNavigate": [4, "auto-navigate"],
|
|
5950
6236
|
"_screen": [32],
|
|
6237
|
+
"_authParams": [32],
|
|
5951
6238
|
"_branding": [32],
|
|
5952
6239
|
"_theme": [32],
|
|
5953
6240
|
"formData": [32]
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as t,c as i,g as e,h as r}from"./p-BzFenraS.js";function s(t,i){if(void 0!==i)return`${i}px`;switch(t){case"pill":return"9999px";case"rounded":return"8px";case"sharp":return"0";default:return}}function a(t){if(!t)return{};const i={};if(t.colors?.primary&&(i["--ah-color-primary"]=t.colors.primary,i["--ah-color-primary-hover"]=t.colors.primary),t.colors?.page_background){const e=t.colors.page_background;"solid"===e.type&&e.start?i["--ah-page-bg"]=e.start:"gradient"===e.type&&e.start&&e.end&&(i["--ah-page-bg"]=`linear-gradient(${e.angle_deg??180}deg, ${e.start}, ${e.end})`)}return t.logo_url&&(i["--ah-logo-url"]=`url(${t.logo_url})`),t.font?.url&&(i["--ah-font-url"]=t.font.url),i}function o(t){if(!t)return{};const i={};if(t.borders){const e=t.borders;void 0!==e.widget_corner_radius&&(i["--ah-widget-radius"]=`${e.widget_corner_radius}px`),void 0!==e.widget_border_weight&&(i["--ah-widget-border-width"]=`${e.widget_border_weight}px`),!1===e.show_widget_shadow&&(i["--ah-widget-shadow"]="none");const r=s(e.buttons_style,e.button_border_radius);r&&(i["--ah-btn-radius"]=r),void 0!==e.button_border_weight&&(i["--ah-btn-border-width"]=`${e.button_border_weight}px`);const a=s(e.inputs_style,e.input_border_radius);a&&(i["--ah-input-radius"]=a),void 0!==e.input_border_weight&&(i["--ah-input-border-width"]=`${e.input_border_weight}px`)}if(t.colors){const e=t.colors;e.primary_button&&(i["--ah-color-primary"]=e.primary_button,i["--ah-color-primary-hover"]=e.primary_button),e.primary_button_label&&(i["--ah-btn-primary-text"]=e.primary_button_label),e.secondary_button_border&&(i["--ah-btn-secondary-border"]=e.secondary_button_border),e.secondary_button_label&&(i["--ah-btn-secondary-text"]=e.secondary_button_label),e.body_text&&(i["--ah-color-text"]=e.body_text),e.header&&(i["--ah-color-text-header"]=e.header),e.input_labels_placeholders&&(i["--ah-color-text-label"]=e.input_labels_placeholders,i["--ah-color-text-muted"]=e.input_labels_placeholders),e.input_filled_text&&(i["--ah-color-input-text"]=e.input_filled_text),e.widget_background&&(i["--ah-color-bg"]=e.widget_background),e.input_background&&(i["--ah-color-input-bg"]=e.input_background),e.widget_border&&(i["--ah-widget-border-color"]=e.widget_border),e.input_border&&(i["--ah-color-border"]=e.input_border),e.links_focused_components&&(i["--ah-color-link"]=e.links_focused_components),e.base_focus_color&&(i["--ah-color-focus-ring"]=e.base_focus_color),e.base_hover_color&&(i["--ah-color-primary-hover"]=e.base_hover_color),e.error&&(i["--ah-color-error"]=e.error),e.success&&(i["--ah-color-success"]=e.success),e.icons&&(i["--ah-color-icon"]=e.icons)}if(t.fonts){const e=t.fonts,r=e.reference_text_size||16;if(e.font_url&&(i["--ah-font-url"]=e.font_url),e.reference_text_size&&(i["--ah-font-size-base"]=`${e.reference_text_size}px`),e.title?.size){const t=Math.round(e.title.size/100*r);i["--ah-font-size-title"]=`${t}px`}if(e.subtitle?.size){const t=Math.round(e.subtitle.size/100*r);i["--ah-font-size-subtitle"]=`${t}px`}if(e.body_text?.size){const t=Math.round(e.body_text.size/100*r);i["--ah-font-size-body"]=`${t}px`}if(e.input_labels?.size){const t=Math.round(e.input_labels.size/100*r);i["--ah-font-size-label"]=`${t}px`}if(e.buttons_text?.size){const t=Math.round(e.buttons_text.size/100*r);i["--ah-font-size-btn"]=`${t}px`}if(e.links?.size){const t=Math.round(e.links.size/100*r);i["--ah-font-size-link"]=`${t}px`}"underlined"===e.links_style&&(i["--ah-link-decoration"]="underline"),void 0!==e.title?.bold&&(i["--ah-font-weight-title"]=e.title.bold?"700":"400"),void 0!==e.subtitle?.bold&&(i["--ah-font-weight-subtitle"]=e.subtitle.bold?"700":"400"),void 0!==e.body_text?.bold&&(i["--ah-font-weight-body"]=e.body_text.bold?"700":"400"),void 0!==e.input_labels?.bold&&(i["--ah-font-weight-label"]=e.input_labels.bold?"700":"400"),void 0!==e.buttons_text?.bold&&(i["--ah-font-weight-btn"]=e.buttons_text.bold?"600":"400"),void 0!==e.links?.bold&&(i["--ah-font-weight-link"]=e.links.bold?"700":"400")}if(t.widget){const e=t.widget;if(e.header_text_alignment&&(i["--ah-title-align"]=e.header_text_alignment),e.logo_height&&(i["--ah-logo-height"]=`${e.logo_height}px`),e.logo_position){const t={center:"center",left:"flex-start",right:"flex-end"};"none"===e.logo_position?i["--ah-logo-display"]="none":i["--ah-logo-align"]=t[e.logo_position]??"center"}e.social_buttons_layout&&("top"===e.social_buttons_layout?(i["--ah-social-order"]="0",i["--ah-divider-order"]="1",i["--ah-fields-order"]="2"):(i["--ah-social-order"]="2",i["--ah-divider-order"]="1",i["--ah-fields-order"]="0"))}if(t.page_background){const e=t.page_background;e.background_color&&(i["--ah-page-bg"]=e.background_color),e.background_image_url&&(i["--ah-page-bg-image"]=`url(${e.background_image_url})`)}return i}const n=class{constructor(e){t(this,e),this.formSubmit=i(this,"formSubmit"),this.buttonClick=i(this,"buttonClick"),this.linkClick=i(this,"linkClick"),this.navigate=i(this,"navigate"),this.flowComplete=i(this,"flowComplete"),this.flowError=i(this,"flowError"),this.screenChange=i(this,"screenChange")}get el(){return e(this)}screen;apiUrl;branding;theme;loading=!1;autoSubmit=!1;_screen;_branding;_theme;formData={};formSubmit;buttonClick;linkClick;navigate;flowComplete;flowError;screenChange;watchScreen(t){if("string"==typeof t)try{this._screen=JSON.parse(t)}catch{console.error("Failed to parse screen JSON")}else this._screen=t;this._screen&&this.screenChange.emit(this._screen)}watchBranding(t){if("string"==typeof t)try{this._branding=JSON.parse(t)}catch{console.error("Failed to parse branding JSON")}else this._branding=t;this.applyThemeStyles()}watchTheme(t){if("string"==typeof t)try{this._theme=JSON.parse(t)}catch{console.error("Failed to parse theme JSON")}else this._theme=t;this.applyThemeStyles()}applyThemeStyles(){const t=(i=this._theme,{...a(this._branding),...o(i)});var i;!function(t,i){Object.entries(i).forEach((([i,e])=>{t.style.setProperty(i,e)}))}(this.el,t)}async componentWillLoad(){this.watchScreen(this.screen),this.watchBranding(this.branding),this.watchTheme(this.theme),this.apiUrl&&!this._screen&&await this.fetchScreen()}async fetchScreen(){if(this.apiUrl){this.loading=!0;try{const t=await fetch(this.apiUrl,{credentials:"include",headers:{Accept:"application/json"}});t.ok&&(this._screen=await t.json(),this._screen&&this.screenChange.emit(this._screen))}catch(t){console.error("Failed to fetch screen:",t)}finally{this.loading=!1}}}handleInputChange=(t,i)=>{this.formData={...this.formData,[t]:i}};handleSubmit=async t=>{if(t.preventDefault(),this._screen&&(this.formSubmit.emit({screen:this._screen,data:this.formData}),this.autoSubmit)){this.loading=!0;try{const t=await fetch(this._screen.action,{method:this._screen.method,credentials:"include",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({data:this.formData})}),i=t.headers.get("content-type");if(i?.includes("application/json")){const i=await t.json();i.redirect?(this.flowComplete.emit({redirectUrl:i.redirect}),this.navigate.emit({url:i.redirect})):i.screen?(this._screen=i.screen,this.formData={},this.screenChange.emit(i.screen),i.branding&&(this._branding=i.branding,this.applyThemeStyles())):i.complete&&this.flowComplete.emit({}),!t.ok&&i.screen&&(this._screen=i.screen,this.screenChange.emit(i.screen))}}catch(t){console.error("Form submission failed:",t),this.flowError.emit({message:t instanceof Error?t.message:"Form submission failed"})}finally{this.loading=!1}}};handleButtonClick=t=>{"submit"!==t.type?this.buttonClick.emit(t):this.handleSubmit({preventDefault:()=>{}})};handleLinkClick=(t,i)=>{this.linkClick.emit({id:i.id,href:i.href,text:i.text}),this.autoSubmit||t.preventDefault()};getScreenErrors(){return this._screen?.messages?.filter((t=>"error"===t.type))||[]}getScreenSuccesses(){return this._screen?.messages?.filter((t=>"success"===t.type))||[]}getOrderedComponents(){return this._screen?[...this._screen.components].filter((t=>!1!==t.visible)).sort(((t,i)=>(t.order??0)-(i.order??0))):[]}isSocialComponent(t){return"SOCIAL"===t.type}isDividerComponent(t){return"DIVIDER"===t.type}render(){if(this.loading&&!this._screen)return r("div",{class:"widget-container"},r("div",{class:"loading-spinner"}));if(!this._screen)return r("div",{class:"widget-container"},r("div",{class:"error-message"},"No screen configuration provided"));const t=this.getScreenErrors(),i=this.getScreenSuccesses(),e=this.getOrderedComponents(),s=e.filter((t=>this.isSocialComponent(t))),a=e.filter((t=>!this.isSocialComponent(t)&&!this.isDividerComponent(t))),o=e.some((t=>this.isDividerComponent(t))),n=this._theme?.widget?.logo_url||this._branding?.logo_url;return r("div",{class:"widget-container",part:"container"},r("header",{class:"widget-header",part:"header"},n&&r("div",{class:"logo-wrapper",part:"logo-wrapper"},r("img",{class:"logo",part:"logo",src:n,alt:"Logo"})),this._screen.title&&r("h1",{class:"title",part:"title"},this._screen.title),this._screen.description&&r("p",{class:"description",part:"description"},this._screen.description)),r("div",{class:"widget-body",part:"body"},t.map((t=>r("div",{class:"message message-error",part:"message message-error",key:t.id??t.text},t.text))),i.map((t=>r("div",{class:"message message-success",part:"message message-success",key:t.id??t.text},t.text))),r("form",{onSubmit:this.handleSubmit,part:"form"},r("div",{class:"form-content"},s.length>0&&r("div",{class:"social-section",part:"social-section"},s.map((t=>r("authhero-node",{key:t.id,component:t,value:this.formData[t.id],onFieldChange:t=>this.handleInputChange(t.detail.id,t.detail.value),onButtonClick:t=>this.handleButtonClick(t.detail),disabled:this.loading})))),s.length>0&&a.length>0&&o&&r("div",{class:"divider",part:"divider"},r("span",{class:"divider-text"},"Or")),r("div",{class:"fields-section",part:"fields-section"},a.map((t=>r("authhero-node",{key:t.id,component:t,value:this.formData[t.id],onFieldChange:t=>this.handleInputChange(t.detail.id,t.detail.value),onButtonClick:t=>this.handleButtonClick(t.detail),disabled:this.loading})))))),this._screen.links&&this._screen.links.length>0&&r("div",{class:"links",part:"links"},this._screen.links.map((t=>r("span",{class:"link-wrapper",part:"link-wrapper",key:t.id??t.href},t.linkText?r("span",null,t.text," ",r("a",{href:t.href,class:"link",part:"link",onClick:i=>this.handleLinkClick(i,{id:t.id,href:t.href,text:t.linkText||t.text})},t.linkText)):r("a",{href:t.href,class:"link",part:"link",onClick:i=>this.handleLinkClick(i,{id:t.id,href:t.href,text:t.text})},t.text)))))))}static get watchers(){return{screen:[{watchScreen:0}],branding:[{watchBranding:0}],theme:[{watchTheme:0}]}}};n.style=":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 8px);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}.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}}";export{n as authhero_widget}
|