@authhero/widget 0.40.2 → 0.41.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-8b981cd0.entry.js +1 -0
- package/dist/cjs/authhero-widget.cjs.entry.js +158 -20
- package/dist/cjs/index.cjs.js +1 -1
- package/dist/collection/components/authhero-widget/authhero-widget.css +121 -0
- package/dist/collection/components/authhero-widget/authhero-widget.js +160 -22
- package/dist/components/authhero-widget.js +1 -1
- package/dist/components/index.js +1 -1
- package/dist/esm/authhero-widget.entry.js +158 -20
- package/dist/esm/index.js +1 -1
- package/dist/types/components/authhero-widget/authhero-widget.d.ts +24 -2
- package/hydrate/index.js +152 -20
- package/hydrate/index.mjs +152 -20
- package/package.json +3 -3
- package/dist/authhero-widget/p-36898e2d.entry.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as t,c as e,g as i,h as o}from"./p-FUW5zvoZ.js";import{s as r}from"./p-Che3Wd7J.js";function n(t){const e=t.match(/^#([0-9a-f]{3})$/i)||t.match(/^#([0-9a-f]{6})$/i);if(!e)return null;let i=e[1];3===i.length&&(i=i[0]+i[0]+i[1]+i[1]+i[2]+i[2]);const o=parseInt(i,16);return[o>>16&255,o>>8&255,255&o]}function a(t){const e=n(t);if(!e)return NaN;const[i,o,r]=e.map((t=>{const e=t/255;return e<=.04045?e/12.92:Math.pow((e+.055)/1.055,2.4)}));return.2126*i+.7152*o+.0722*r}function s(t,e){const i=a(t),o=a(e);return isNaN(i)||isNaN(o)?NaN:(Math.max(i,o)+.05)/(Math.min(i,o)+.05)}function c(t,e="light"){const i=s(t,"#000000"),o=s(t,"#ffffff");return"light"===e?i>1.35*o?"#000000":"#ffffff":1.35*i>o?"#000000":"#ffffff"}function l(t,e){const i=n(t);if(!i)return t;const[o,r,a]=i,s=t=>Math.max(0,Math.round(t*(1-e))).toString(16).padStart(2,"0");return`#${s(o)}${s(r)}${s(a)}`}function h(t,e){const i=n(t);if(!i)return t;const[o,r,a]=i,s=t=>Math.min(255,Math.round(t+(255-t)*e)).toString(16).padStart(2,"0");return`#${s(o)}${s(r)}${s(a)}`}function d(t,e,i=4.5){if(s(t,e)>=i)return t;const o=a(e)>.5;let r=t;for(let n=1;n<=10;n++)if(r=o?l(t,.1*n):h(t,.1*n),s(r,e)>=i)return r;return o?"#000000":"#ffffff"}function p(t,e){if(void 0!==e)return`${e}px`;switch(t){case"pill":return"9999px";case"rounded":return"8px";case"sharp":return"0";default:return}}function f(t){if(!t)return{};const e={};if(t.colors?.primary&&(e["--ah-color-primary"]=t.colors.primary),t.colors?.page_background){const i=t.colors.page_background;"solid"===i.type&&i.start?e["--ah-page-bg"]=i.start:"gradient"===i.type&&i.start&&i.end&&(e["--ah-page-bg"]=`linear-gradient(${i.angle_deg??180}deg, ${i.start}, ${i.end})`)}return t.logo_url&&(e["--ah-logo-url"]=`url(${t.logo_url})`),t.font?.url&&(e["--ah-font-url"]=t.font.url),e}function u(t){if(!t)return{};const e={};if(t.borders){const i=t.borders;void 0!==i.widget_corner_radius&&(e["--ah-widget-radius"]=`${i.widget_corner_radius}px`),void 0!==i.widget_border_weight&&(e["--ah-widget-border-width"]=`${i.widget_border_weight}px`),!1===i.show_widget_shadow&&(e["--ah-widget-shadow"]="none");const o=p(i.buttons_style,i.button_border_radius);o&&(e["--ah-btn-radius"]=o),void 0!==i.button_border_weight&&(e["--ah-btn-border-width"]=`${i.button_border_weight}px`);const r=p(i.inputs_style,i.input_border_radius);r&&(e["--ah-input-radius"]=r),void 0!==i.input_border_weight&&(e["--ah-input-border-width"]=`${i.input_border_weight}px`)}if(t.colors){const i=t.colors;if(i.primary_button)if(e["--ah-color-primary"]=i.primary_button,i.primary_button_label)e["--ah-color-text-on-primary"]=i.primary_button_label;else{e["--ah-color-text-on-primary"]=c(i.primary_button,"light");const t=c(i.primary_button,"dark");t!==e["--ah-color-text-on-primary"]&&(e["--ah-color-text-on-primary-dark"]=t)}else i.primary_button_label&&(e["--ah-color-text-on-primary"]=i.primary_button_label);i.secondary_button_border&&(e["--ah-btn-secondary-border"]=i.secondary_button_border),i.secondary_button_label&&(e["--ah-btn-secondary-text"]=i.secondary_button_label),i.body_text&&(e["--ah-color-text"]=i.body_text),i.header&&(e["--ah-color-text-header"]=i.header),i.input_labels_placeholders&&(e["--ah-color-text-label"]=i.input_labels_placeholders,e["--ah-color-text-muted"]=i.input_labels_placeholders),i.input_filled_text&&(e["--ah-color-input-text"]=i.input_filled_text),i.widget_background&&(e["--ah-color-bg"]=i.widget_background),i.input_background&&(e["--ah-color-input-bg"]=i.input_background),i.widget_border&&(e["--ah-widget-border-color"]=i.widget_border),i.input_border&&(e["--ah-color-border"]=i.input_border),i.links_focused_components&&(e["--ah-color-link"]=d(i.links_focused_components,i.widget_background||"#ffffff")),i.base_focus_color&&(e["--ah-color-focus-ring"]=i.base_focus_color),i.base_hover_color&&(e["--ah-color-primary-hover"]=i.base_hover_color),i.error&&(e["--ah-color-error"]=i.error),i.success&&(e["--ah-color-success"]=i.success),i.icons&&(e["--ah-color-icon"]=i.icons);const o=i.widget_background||"#ffffff",r=i.input_background||o,n=e["--ah-color-border"]||i.input_border||"#c9cace",a=s(n,o),l=s(n,r);Math.min(a,l)<3&&(e["--ah-color-border"]=d(n,a<l?o:r,3))}if(t.fonts){const i=t.fonts,o=i.reference_text_size||16,r=t=>t>=50?Math.round(t/100*o):t;i.font_url&&(e["--ah-font-url"]=i.font_url),i.reference_text_size&&(e["--ah-font-size-base"]=`${i.reference_text_size}px`),i.title?.size&&(e["--ah-font-size-title"]=`${r(i.title.size)}px`),i.subtitle?.size&&(e["--ah-font-size-subtitle"]=`${r(i.subtitle.size)}px`),i.body_text?.size&&(e["--ah-font-size-body"]=`${r(i.body_text.size)}px`),i.input_labels?.size&&(e["--ah-font-size-label"]=`${r(i.input_labels.size)}px`),i.buttons_text?.size&&(e["--ah-font-size-btn"]=`${r(i.buttons_text.size)}px`),i.links?.size&&(e["--ah-font-size-link"]=`${r(i.links.size)}px`),"underlined"===i.links_style&&(e["--ah-link-decoration"]="underline"),void 0!==i.title?.bold&&(e["--ah-font-weight-title"]=i.title.bold?"700":"400"),void 0!==i.subtitle?.bold&&(e["--ah-font-weight-subtitle"]=i.subtitle.bold?"700":"400"),void 0!==i.body_text?.bold&&(e["--ah-font-weight-body"]=i.body_text.bold?"700":"400"),void 0!==i.input_labels?.bold&&(e["--ah-font-weight-label"]=i.input_labels.bold?"700":"400"),void 0!==i.buttons_text?.bold&&(e["--ah-font-weight-btn"]=i.buttons_text.bold?"600":"400"),void 0!==i.links?.bold&&(e["--ah-font-weight-link"]=i.links.bold?"700":"400")}if(t.widget){const i=t.widget;if(i.header_text_alignment&&(e["--ah-title-align"]=i.header_text_alignment),i.logo_height&&(e["--ah-logo-height"]=`${i.logo_height}px`),i.logo_position){const t={center:"center",left:"flex-start",right:"flex-end"};"none"===i.logo_position?e["--ah-logo-display"]="none":e["--ah-logo-align"]=t[i.logo_position]??"center"}i.social_buttons_layout&&("top"===i.social_buttons_layout?(e["--ah-social-order"]="0",e["--ah-divider-order"]="1",e["--ah-fields-order"]="2"):(e["--ah-social-order"]="2",e["--ah-divider-order"]="1",e["--ah-fields-order"]="0"))}if(t.page_background){const i=t.page_background;i.background_color&&(e["--ah-page-bg"]=i.background_color),i.background_image_url&&(e["--ah-page-bg-image"]=`url(${i.background_image_url})`)}return e}const g={br:[],em:[],i:[],strong:[],b:[],u:[],span:["class"],a:["href","class"]};function m(t){if(!t)return"";if(!t.includes("<"))return t;let e=t;e=e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'");for(const[t,i]of Object.entries(g)){if("br"===t){e=e.replace(/<br\s*\/?>/gi,"<br>");continue}const o=new RegExp(`<${t}((?:\\s+[a-z-]+(?:="[^&]*"|='[^&]*')?)*)\\s*>`,"gi");e=e.replace(o,((e,o)=>{const r=[];if(o){const t=o.replace(/"/g,'"').replace(/'/g,"'").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"),e=/([a-z-]+)=["']([^"']*)["']/gi;let n;for(;null!==(n=e.exec(t));){const[,t,e]=n;t&&i.includes(t.toLowerCase())&&("href"===t.toLowerCase()?b(e||"")&&r.push(`${t}="${x(e||"")}"`):r.push(`${t}="${x(e||"")}"`))}}"a"===t&&(r.push('target="_blank"'),r.push('rel="noopener noreferrer"'));const n=r.length?" "+r.join(" "):"";return`<${t}${n}>`}));const r=new RegExp(`</${t}>`,"gi");e=e.replace(r,`</${t}>`)}return e}function b(t){if(!t)return!1;if(t.startsWith("/")||t.startsWith("#")||t.startsWith("?"))return!0;try{const e=new URL(t,"https://example.com");return"http:"===e.protocol||"https:"===e.protocol}catch{return!1}}function x(t){return t.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}const v=new Set(["TEXT","EMAIL","CODE","PASSWORD","NUMBER","URL"]),w=new Set(["TEXT","EMAIL","CODE","PASSWORD","NUMBER","TEL","URL","DATE","BOOLEAN","LEGAL","COUNTRY","DROPDOWN","CHOICE"]),y=class{constructor(i){t(this,i),this.formSubmit=e(this,"formSubmit"),this.buttonClick=e(this,"buttonClick"),this.linkClick=e(this,"linkClick"),this.navigate=e(this,"navigate"),this.flowComplete=e(this,"flowComplete"),this.flowError=e(this,"flowError"),this.screenChange=e(this,"screenChange")}get el(){return i(this)}screen;apiUrl;baseUrl;state;screenId;watchScreenId(){this.updateDataScreenAttribute()}authParams;statePersistence="memory";storageKey="authhero_widget";branding;theme;loading=!1;autoSubmit=!1;autoNavigate;locale;_screen;_authParams;_branding;_theme;formData={};listFilter="";conditionalMediationAbort;loadedFontUrl;formSubmit;buttonClick;linkClick;navigate;flowComplete;flowError;screenChange;watchScreen(t){if(this.conditionalMediationAbort?.abort(),this.conditionalMediationAbort=void 0,"string"==typeof t)try{this._screen=JSON.parse(t)}catch{console.error("Failed to parse screen JSON")}else this._screen=t;this._screen&&(this.formData={},this.listFilter="",this.initFormDataFromDefaults(this._screen),this.screenChange.emit(this._screen),this.updateDataScreenAttribute())}initFormDataFromDefaults(t){const e={};for(const i of t.components||[]){if(!("config"in i)||!i.config)continue;if(!("default_value"in i.config))continue;const t=i.config.default_value;"string"==typeof t&&""!==t?e[i.id]=t:"boolean"==typeof t&&(e[i.id]=t?"true":"false")}Object.keys(e).length>0&&(this.formData={...e,...this.formData})}updateDataScreenAttribute(){const t=this._screen?.name||this.screenId;t?this.el.setAttribute("data-screen",t):this.el.removeAttribute("data-screen");const e=this.el.closest("[data-authhero-widget-container]");e&&(t?e.setAttribute("data-screen",t):e.removeAttribute("data-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()}watchAuthParams(t){if("string"==typeof t)try{this._authParams=JSON.parse(t)}catch{console.error("Failed to parse authParams JSON")}else this._authParams=t}applyThemeStyles(){const t=(e=this._theme,{...f(this._branding),...u(e)});var e;!function(t,e){Object.entries(e).forEach((([e,i])=>{t.style.setProperty(e,i)}))}(this.el,t),this.loadCustomFont()}loadCustomFont(){if("undefined"==typeof document)return;const t=this._theme?.fonts?.font_url||this._branding?.font?.url;if(t===this.loadedFontUrl)return;for(const t of Array.from(document.head.querySelectorAll("link[data-authhero-font]")))t.remove();if(this.loadedFontUrl=void 0,!t)return;const e=document.createElement("link");e.rel="stylesheet",e.href=t,e.setAttribute("data-authhero-font",t),document.head.appendChild(e),this.loadedFontUrl=t}focusFirstInput(){requestAnimationFrame((()=>{const t=this.el.shadowRoot;if(!t)return;const e=t.querySelectorAll("authhero-node");for(const t of Array.from(e)){const e=t.shadowRoot;if(e){const t=e.querySelector('input:not([type="hidden"]):not([type="checkbox"]):not([disabled]), textarea:not([disabled])');if(t)return void t.focus()}}}))}pendingRenderResolvers=[];activeSwaps=0;updateReadyAttribute(){this.el.toggleAttribute("data-ready",!this.loading&&0===this.activeSwaps)}componentDidRender(){if(this.updateReadyAttribute(),0===this.pendingRenderResolvers.length)return;const t=this.pendingRenderResolvers;this.pendingRenderResolvers=[],t.forEach((t=>t()))}nextRender(){return new Promise((t=>{let e=!1;const i=()=>{e||(e=!0,t())};this.pendingRenderResolvers.push(i),requestAnimationFrame((()=>requestAnimationFrame(i)))}))}async swapScreen(t){const e=this.el.shadowRoot?.querySelector(".widget-container"),i="function"==typeof window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches;if(e&&"function"==typeof e.animate&&!i){this.activeSwaps++;try{await this.animateSwap(e,t)}finally{this.activeSwaps--,this.updateReadyAttribute()}}else t()}async animateSwap(t,e){const i=t.getBoundingClientRect().height;t.style.height=`${i}px`,t.style.overflow="hidden",e(),await this.nextRender();const o=()=>{t.style.height="",t.style.overflow=""};t.style.height="auto";const r=t.getBoundingClientRect().height;if(t.style.height=`${i}px`,t.getBoundingClientRect(),Math.abs(r-i)<1)return void o();const n=t.animate([{height:`${i}px`},{height:`${r}px`}],{duration:520,easing:"cubic-bezier(0.22, 1, 0.36, 1)"});try{await n.finished}catch{}finally{o()}}get shouldAutoNavigate(){return this.autoNavigate??this.autoSubmit}buildUrl(t){return this.baseUrl?new URL(t,this.baseUrl).toString():t}loadPersistedState(){if("url"===this.statePersistence){const t=new URL(window.location.href).searchParams.get("state");t&&!this.state&&(this.state=t)}else if("session"===this.statePersistence)try{const t=sessionStorage.getItem(`${this.storageKey}_state`);t&&!this.state&&(this.state=t);const e=sessionStorage.getItem(`${this.storageKey}_screenId`);e&&!this.screenId&&(this.screenId=e)}catch{}}persistState(){if("url"===this.statePersistence){const t=new URL(window.location.href);this.state&&t.searchParams.set("state",this.state),this.screenId&&t.searchParams.set("screen",this.screenId),window.history.replaceState({},"",t.toString())}else if("session"===this.statePersistence)try{this.state&&sessionStorage.setItem(`${this.storageKey}_state`,this.state),this.screenId&&sessionStorage.setItem(`${this.storageKey}_screenId`,this.screenId)}catch{}}handlePopState=t=>{if(!this.apiUrl)return;t.state?.state&&(this.state=t.state.state);const e=t.state?.screen??this.extractScreenIdFromHref(location.href);e&&this.fetchScreen(e)};connectedCallback(){window.addEventListener("popstate",this.handlePopState)}disconnectedCallback(){window.removeEventListener("popstate",this.handlePopState),this.conditionalMediationAbort?.abort(),this.conditionalMediationAbort=void 0}readJsonScript(t){if(!this.el)return;const e=this.el.querySelector(`script[type="application/json"][data-authhero="${t}"]`);return e?.textContent??void 0}async componentWillLoad(){if(!this._screen){const t=this.screen||this.readJsonScript("screen")||this.el?.getAttribute("screen");t&&this.watchScreen(t)}this._branding||this.watchBranding(this.branding??this.readJsonScript("branding")),this._theme||this.watchTheme(this.theme??this.readJsonScript("theme")),this._authParams||this.watchAuthParams(this.authParams??this.readJsonScript("auth-params")),this._screen&&this.adoptPrehydrationValues(this._screen),this.loadPersistedState(),this.apiUrl&&!this._screen&&await this.fetchScreen(this.screenId)}adoptPrehydrationValues(t){const e=this.el.shadowRoot;if(!e)return;const i=[e];e.querySelectorAll("authhero-node").forEach((t=>{t.shadowRoot&&i.push(t.shadowRoot)}));const o={};for(const e of t.components??[])if(v.has(e.type))for(const t of i){const i=Array.from(t.querySelectorAll("input[name]")).find((t=>t.name===e.id&&"hidden"!==t.type));if(i){o[e.id]=i.value;break}}Object.keys(o).length>0&&(this.formData={...this.formData,...o})}async fetchScreen(t,e){if(!this.apiUrl)return!1;const i=t||this.screenId;let o=this.apiUrl;i&&o.includes("{screenId}")&&(o=o.replace("{screenId}",encodeURIComponent(i)));const r=new URL(o,this.baseUrl||window.location.origin);this.state&&r.searchParams.set("state",this.state),e&&r.searchParams.set("nodeId",e),this.loading=!0;try{const t=await fetch(this.buildUrl(r.pathname+r.search),{credentials:"include",headers:{Accept:"application/json"}});if(t.ok){const e=await t.json();if(e.screen?(this._screen=e.screen,e.branding&&(this._branding=e.branding,this.applyThemeStyles()),e.state&&(this.state=e.state),e.screenId&&(this.screenId=e.screenId)):this._screen=e,this._screen)return this.listFilter="",i&&i!==this.screenId&&(this.screenId=i),this.initFormDataFromDefaults(this._screen),this.screenChange.emit(this._screen),this.updateDataScreenAttribute(),this.persistState(),this.focusFirstInput(),e.ceremony&&this.performWebAuthnCeremony(e.ceremony),!0}else{const e=await t.json().catch((()=>({message:"Failed to load screen"})));this.flowError.emit({message:e.message||"Failed to load screen"})}}catch(t){console.error("Failed to fetch screen:",t),this.flowError.emit({message:t instanceof Error?t.message:"Failed to fetch screen"})}finally{this.loading=!1}return!1}handleInputChange=(t,e)=>{this.formData={...this.formData,[t]:e}};handleSubmit=async(t,e)=>{if(t.preventDefault(),!this._screen||this.loading)return;const i=this.el.shadowRoot?.querySelector("form");if(this._screen.partials&&i?.reportValidity&&!i.reportValidity())return;const o={...this.formData,...e||{}},r=new Set;if(i&&this._screen.partials){const t={};new FormData(i).forEach(((e,i)=>{"string"==typeof e&&i.startsWith("ulp-")&&(t[i]??=[]).push(e)}));for(const[e,i]of Object.entries(t))r.add(e),o[e]=i.length>1?i:i[0]}if(i&&i.querySelectorAll('input[type="hidden"]').forEach((t=>{t.name&&t.value&&!t.disabled&&!r.has(t.name)&&(o[t.name]=t.value)})),this.formSubmit.emit({screen:this._screen,data:o}),this.autoSubmit)if(this._screen.method&&"GET"!==this._screen.method.toUpperCase()){this.loading=!0;try{const t=await fetch(this.buildUrl(this._screen.action),{method:this._screen.method,credentials:"include",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({data:o})}),e=t.headers.get("content-type");if(e?.includes("text/html")){const e=await t.text();return document.open(),document.write(e),void document.close()}if(e?.includes("application/json")){const e=await t.json();if(e.redirect){this.flowComplete.emit({redirectUrl:e.redirect});const t=this.navigate.emit({url:e.redirect});this.shouldAutoNavigate&&!t.defaultPrevented&&(window.location.href=e.redirect)}else!t.ok&&e.screen?await this.swapScreen((()=>{this.loading=!1,this._screen=e.screen,this.listFilter="",this.initFormDataFromDefaults(e.screen),this.screenChange.emit(e.screen),this.updateDataScreenAttribute(),this.focusFirstInput()})):e.screen?await this.swapScreen((()=>{this.loading=!1,this._screen=e.screen,this.listFilter="",this.formData={},this.initFormDataFromDefaults(e.screen),this.screenChange.emit(e.screen),this.updateDataScreenAttribute(),e.screenId&&(this.screenId=e.screenId),this.persistState(),e.navigateUrl&&this.shouldAutoNavigate&&window.history.pushState({screen:e.screenId,state:this.state},"",e.navigateUrl),e.branding&&(this._branding=e.branding,this.applyThemeStyles()),e.state&&(this.state=e.state,this.persistState()),e.ceremony&&this.performWebAuthnCeremony(e.ceremony),this.focusFirstInput()})):e.complete?this.flowComplete.emit({}):!t.ok&&e.error&&(this._screen&&(this._screen={...this._screen,messages:[...this._screen.messages||[],{text:e.error,type:"error"}]}),this.flowError.emit({message:e.error}))}}catch(t){console.error("Form submission failed:",t),this.flowError.emit({message:t instanceof Error?t.message:"Form submission failed"})}finally{this.loading=!1}}else window.location.href=this.buildUrl(this._screen.action)};overrideFormSubmit(){const t=this.el.shadowRoot;if(!t)return;const e=t.querySelector("form");e&&(e.submit=()=>{if(this._screen?.partials&&e.reportValidity&&!e.reportValidity())return;const t=new FormData(e),i={};t.forEach(((t,e)=>{"string"==typeof t&&(i[e]=t)})),this.handleSubmit({preventDefault:()=>{}},i)})}performWebAuthnCeremony(t){this.isValidWebAuthnCeremony(t)?"webauthn-authentication-conditional"!==t.type?requestAnimationFrame((()=>{this.overrideFormSubmit(),"webauthn-authentication"===t.type?this.executeWebAuthnAuthentication(t):this.executeWebAuthnRegistration(t)})):this.executeWebAuthnConditionalMediation(t):console.error("Invalid WebAuthn ceremony payload",t)}isValidWebAuthnCeremony(t){if("object"!=typeof t||null===t)return!1;const e=t;if("string"!=typeof e.successAction)return!1;const i=e.options;if("object"!=typeof i||null===i)return!1;if("string"!=typeof i.challenge)return!1;if("webauthn-registration"===e.type){const t=i.rp;if("object"!=typeof t||null===t)return!1;if("string"!=typeof t.id||"string"!=typeof t.name)return!1;const e=i.user;return"object"==typeof e&&null!==e&&("string"==typeof e.id&&"string"==typeof e.name&&"string"==typeof e.displayName&&!!Array.isArray(i.pubKeyCredParams))}return"webauthn-authentication"===e.type||"webauthn-authentication-conditional"===e.type}async executeWebAuthnRegistration(t){const e=t.options,i=t=>{for(t=t.replace(/-/g,"+").replace(/_/g,"/");t.length%4;)t+="=";const e=atob(t),i=new Uint8Array(e.length);for(let t=0;t<e.length;t++)i[t]=e.charCodeAt(t);return i.buffer},o=t=>{const e=new Uint8Array(t);let i="";for(let t=0;t<e.length;t++)i+=String.fromCharCode(e[t]);return btoa(i).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")},r=()=>{const t=this.el?.shadowRoot;if(t){const e=t.querySelector("form");if(e)return e}return document.querySelector("form")};try{const n={challenge:i(e.challenge),rp:{id:e.rp.id,name:e.rp.name},user:{id:i(e.user.id),name:e.user.name,displayName:e.user.displayName},pubKeyCredParams:e.pubKeyCredParams.map((t=>({alg:t.alg,type:t.type}))),timeout:e.timeout,attestation:e.attestation||"none",authenticatorSelection:e.authenticatorSelection?{residentKey:e.authenticatorSelection.residentKey||"preferred",userVerification:e.authenticatorSelection.userVerification||"preferred"}:void 0};e.excludeCredentials?.length&&(n.excludeCredentials=e.excludeCredentials.map((t=>({id:i(t.id),type:t.type,transports:t.transports||[]}))));const a=await navigator.credentials.create({publicKey:n}),s=a.response,c={id:a.id,rawId:o(a.rawId),type:a.type,response:{attestationObject:o(s.attestationObject),clientDataJSON:o(s.clientDataJSON)},clientExtensionResults:a.getClientExtensionResults(),authenticatorAttachment:a.authenticatorAttachment||void 0};"function"==typeof s.getTransports&&(c.response.transports=s.getTransports());const l=r();if(l){const e=l.querySelector('[name="credential-field"]')||l.querySelector("#credential-field"),i=l.querySelector('[name="action-field"]')||l.querySelector("#action-field");e&&(e.value=JSON.stringify(c)),i&&(i.value=t.successAction),l.submit()}}catch(t){console.error("WebAuthn registration error:",t);const e=r();if(e){const t=e.querySelector('[name="action-field"]')||e.querySelector("#action-field");t&&(t.value="error"),e.submit()}}}async executeWebAuthnAuthentication(t){const e=t.options,i=t=>{for(t=t.replace(/-/g,"+").replace(/_/g,"/");t.length%4;)t+="=";const e=atob(t),i=new Uint8Array(e.length);for(let t=0;t<e.length;t++)i[t]=e.charCodeAt(t);return i.buffer},o=t=>{const e=new Uint8Array(t);let i="";for(let t=0;t<e.length;t++)i+=String.fromCharCode(e[t]);return btoa(i).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")},r=()=>{const t=this.el?.shadowRoot;if(t){const e=t.querySelector("form");if(e)return e}return document.querySelector("form")};try{const n={challenge:i(e.challenge),rpId:e.rpId,timeout:e.timeout,userVerification:e.userVerification||"preferred"};e.allowCredentials?.length&&(n.allowCredentials=e.allowCredentials.map((t=>({id:i(t.id),type:t.type,transports:t.transports||[]}))));const a=await navigator.credentials.get({publicKey:n}),s=a.response,c={id:a.id,rawId:o(a.rawId),type:a.type,response:{authenticatorData:o(s.authenticatorData),clientDataJSON:o(s.clientDataJSON),signature:o(s.signature)},clientExtensionResults:a.getClientExtensionResults(),authenticatorAttachment:a.authenticatorAttachment||void 0};s.userHandle&&(c.response.userHandle=o(s.userHandle));const l=r();if(l){const e=l.querySelector('[name="credential-field"]')||l.querySelector("#credential-field"),i=l.querySelector('[name="action-field"]')||l.querySelector("#action-field");e&&(e.value=JSON.stringify(c)),i&&(i.value=t.successAction),l.submit()}}catch(t){console.error("WebAuthn authentication error:",t);const e=r();if(e){const t=e.querySelector('[name="action-field"]')||e.querySelector("#action-field");t&&(t.value="error"),e.submit()}}}async executeWebAuthnConditionalMediation(t){if(!window.PublicKeyCredential||!PublicKeyCredential.isConditionalMediationAvailable)return;if(!await PublicKeyCredential.isConditionalMediationAvailable())return;this.conditionalMediationAbort?.abort();const e=new AbortController;this.conditionalMediationAbort=e;const i=t.options,o=t=>{for(t=t.replace(/-/g,"+").replace(/_/g,"/");t.length%4;)t+="=";const e=atob(t),i=new Uint8Array(e.length);for(let t=0;t<e.length;t++)i[t]=e.charCodeAt(t);return i.buffer},r=t=>{const e=new Uint8Array(t);let i="";for(let t=0;t<e.length;t++)i+=String.fromCharCode(e[t]);return btoa(i).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")};try{const n=await navigator.credentials.get({mediation:"conditional",signal:e.signal,publicKey:{challenge:o(i.challenge),rpId:i.rpId,timeout:i.timeout,userVerification:i.userVerification||"preferred"}}),a=n.response,s={id:n.id,rawId:r(n.rawId),type:n.type,response:{authenticatorData:r(a.authenticatorData),clientDataJSON:r(a.clientDataJSON),signature:r(a.signature)},clientExtensionResults:n.getClientExtensionResults(),authenticatorAttachment:n.authenticatorAttachment||void 0};a.userHandle&&(s.response.userHandle=r(a.userHandle)),this.formData["credential-field"]=JSON.stringify(s),this.formData["action-field"]=t.successAction,this.overrideFormSubmit();const c=this.el?.shadowRoot,l=c?.querySelector("form");if(l){const e=l.querySelector('[name="credential-field"]')||l.querySelector("#credential-field"),i=l.querySelector('[name="action-field"]')||l.querySelector("#action-field");e&&(e.value=JSON.stringify(s)),i&&(i.value=t.successAction),l.submit()}}catch(t){if("AbortError"===t?.name||"NotAllowedError"===t?.name)return;console.error("Conditional mediation error:",t)}}handleButtonClick=t=>{if("submit"!==t.type)if(this.buttonClick.emit(t),"SOCIAL"===t.type&&t.value&&this.shouldAutoNavigate){const e=this.getProviderHref(t.value);if(e){const t=this.extractScreenIdFromHref(e);return void(t&&this.apiUrl?this.navigateToScreen(t,e):window.location.href=e)}this.handleSocialLogin(t.value)}else"RESEND_BUTTON"===t.type&&this.shouldAutoNavigate&&this.handleResend();else{const e=this._screen?.components?.find((e=>e.id===t.id));if(this._screen&&("NEXT_BUTTON"!==e?.type||!0!==e.config?.skip_validation)&&this.hasUnfilledRequiredFields(this._screen))return;if((!this._screen?.method||"GET"===this._screen.method.toUpperCase())&&this._screen?.action)return void(window.location.href=this.buildUrl(this._screen.action));const i={...this.formData,[t.id]:"true"};this.formData=i,this.handleSubmit({preventDefault:()=>{}},i)}};handleSocialLogin(t){const e=this._authParams||{},i={connection:t};this.state?i.state=this.state:e.state&&(i.state=e.state),e.client_id&&(i.client_id=e.client_id),e.redirect_uri&&(i.redirect_uri=e.redirect_uri),e.scope&&(i.scope=e.scope),e.audience&&(i.audience=e.audience),e.nonce&&(i.nonce=e.nonce),e.response_type&&(i.response_type=e.response_type);const o=this.buildUrl("/authorize?"+new URLSearchParams(i).toString());this.navigate.emit({url:o}).defaultPrevented||(window.location.href=o)}async handleResend(){if(this._screen?.action)try{const t=this._screen.action+(this._screen.action.includes("?")?"&":"?")+"action=resend";await fetch(this.buildUrl(t),{method:"POST",credentials:"include"})}catch(t){console.error("Resend failed:",t)}}extractScreenIdFromHref(t){try{const e=new URL(t,window.location.origin).pathname,i=e.match(/\/u2\/login\/([^/]+)$/);if(i)return i[1];const o=e.match(/\/u2\/([^/]+)$/);return o&&"login"!==o[1]&&"screen"!==o[1]?o[1]:null}catch{return null}}handleLinkClick=(t,e)=>{if(this.linkClick.emit({id:e.id,href:e.href,text:e.text}),!this.shouldAutoNavigate)return void t.preventDefault();const i=this.extractScreenIdFromHref(e.href);return i&&this.apiUrl?(t.preventDefault(),void this.navigateToScreen(i,e.href)):void 0};async navigateToScreen(t,e){await this.fetchScreen(t)?window.history.pushState({screen:t,state:this.state},"",e):window.location.href=e}getProviderHref(t){if(!this._screen)return null;for(const e of this._screen.components){const i=e;if("SOCIAL"===i.type&&i.config?.provider_details){const e=i.config.provider_details.find((e=>e.name===t));if(e?.href)return e.href}}return null}isSocialComponent(t){return"SOCIAL"===t.type}isDividerComponent(t){return"DIVIDER"===t.type}isRequiredFieldFilled(t){const e=this.formData[t.id];return"BOOLEAN"===t.type||"LEGAL"===t.type?"true"===e:"string"==typeof e&&""!==e.trim()}hasUnfilledRequiredFields(t){return(t.components??[]).some((t=>!1!==t.visible&&"required"in t&&!0===t.required&&w.has(t.type)&&!this.isRequiredFieldFilled(t)))}getChoiceButtonText(t){const e=t.config;return e?.text??""}renderPromptPartial(t,e){const i=t.partials?.[e];return i?o("div",{class:`prompt-partial prompt-partial-${e}`,part:`prompt-partial prompt-partial-${e}`,"data-insertion-point":e,innerHTML:i}):null}renderScreenLinks(t){return t.links?.length?o("div",{class:"links",part:"links"},t.links.map((t=>o("span",{class:"link-wrapper",part:"link-wrapper",key:t.id??t.href},t.linkText?o("span",null,t.text," ",o("a",{href:t.href,class:"link",part:"link",onClick:e=>this.handleLinkClick(e,{id:t.id,href:t.href,text:t.linkText||t.text})},t.linkText)):o("a",{href:t.href,class:"link",part:"link",onClick:e=>this.handleLinkClick(e,{id:t.id,href:t.href,text:t.text})},t.text))))):null}render(){const t=this._screen;if(this.loading&&!t)return o("div",{class:"widget-container"},o("div",{class:"loading-spinner"}));if(!t)return o("div",{class:"widget-container"},o("div",{class:"error-message"},"No screen configuration provided"));const e=t.messages?.filter((t=>"error"===t.type))||[],i=t.messages?.filter((t=>"success"===t.type))||[],n=[...t.components??[]],a=n.filter((t=>!1!==t.visible)).sort(((t,e)=>(t.order??0)-(e.order??0))),s=n.filter((t=>!1===t.visible)),c=a.filter((t=>this.isSocialComponent(t))),l=c.length>0?a.find((t=>this.isDividerComponent(t))):void 0,h=a.filter((t=>!this.isSocialComponent(t)&&t!==l)),d=Object.values(t.partials??{}).some((t=>!!t)),p=d?h.filter((t=>"submit"===t.id&&"NEXT_BUTTON"===t.type)):[],f=d?h.filter((t=>!p.includes(t))):h,u=!!l,g=l?.config?.text||"Or",b=f.filter((t=>"NEXT_BUTTON"===t.type)),x=b.length===f.length&&b.length>5,v=this.hasUnfilledRequiredFields(t),w=this.listFilter.trim().toLowerCase(),y=x&&w?b.filter((t=>this.getChoiceButtonText(t).toLowerCase().includes(w))):b,k=t=>{const e=t.config;return["social-buttons","button","button-secondary","button-social","button-social-content","button-social-text","button-social-text-short","button-social-subtitle","button-social-badge","social-icon",...(e?.providers??[]).flatMap((t=>{const e=r(t);return[`button-social-${e}`,`button-social-content-${e}`,`button-social-text-${e}`,`button-social-text-short-${e}`,`button-social-subtitle-${e}`,`button-social-badge-${e}`,`social-icon-${e}`]}))].join(", ")},S=this._theme?.widget?.logo_url||this._branding?.logo_url;return o("div",{class:"widget-container",part:"container","data-authstack-container":!0},o("header",{class:"widget-header",part:"header"},S&&o("div",{class:"logo-wrapper",part:"logo-wrapper"},o("img",{class:"logo",part:"logo",src:S,alt:"Logo"})),t.title&&o("h1",{class:"title",part:"title",innerHTML:m(t.title)}),t.description&&o("p",{class:"description",part:"description",innerHTML:m(t.description)})),o("div",{class:"widget-body",part:"body"},e.map((t=>o("div",{class:"message message-error",part:"message message-error",key:t.id??t.text},t.text))),i.map((t=>o("div",{class:"message message-success",part:"message message-success",key:t.id??t.text},t.text))),o("form",{onSubmit:this.handleSubmit,action:t.action,method:t.method||"POST",part:"form"},s.map((t=>o("input",{type:"hidden",name:t.id,id:t.id,key:t.id,value:this.formData[t.id]||""}))),o("div",{class:"form-content"},this.renderPromptPartial(t,"form-content-start"),c.length>0&&o("div",{class:"social-section",part:"social-section"},c.map((t=>o("authhero-node",{key:t.id,component:t,locale:this.locale,value:this.formData[t.id],onFieldChange:t=>this.handleInputChange(t.detail.id,t.detail.value),onButtonClick:t=>this.handleButtonClick(t.detail),disabled:this.loading,exportparts:k(t)})))),c.length>0&&h.length>0&&u&&o("div",{class:"divider",part:"divider"},o("span",{class:"divider-text"},g)),o("div",{class:"fields-section",part:"fields-section"},x&&o("input",{type:"text",class:"choice-list-search",part:"choice-list-search",placeholder:"Search","aria-label":"Search",autocomplete:"off",value:this.listFilter,onInput:t=>this.listFilter=t.target.value,onKeyDown:t=>{"Enter"===t.key&&t.preventDefault()}}),o("div",{class:x?"fields-list fields-list-scroll":"fields-list",part:x?"fields-list fields-list-scroll":"fields-list"},(x?y:f).map((t=>o("authhero-node",{key:t.id,component:t,locale:this.locale,value:this.formData[t.id],onFieldChange:t=>this.handleInputChange(t.detail.id,t.detail.value),onButtonClick:t=>this.handleButtonClick(t.detail),disabled:this.loading||"NEXT_BUTTON"===t.type&&!0!==t.config?.skip_validation&&v}))),x&&0===y.length&&o("div",{class:"choice-list-empty",part:"choice-list-empty"},"No matches"))),this.renderPromptPartial(t,"form-content-end"),d&&o("div",{class:"form-footer",part:"form-footer"},this.renderPromptPartial(t,"form-footer-start"),p.map((t=>o("authhero-node",{key:t.id,component:t,locale:this.locale,value:this.formData[t.id],onFieldChange:t=>this.handleInputChange(t.detail.id,t.detail.value),onButtonClick:t=>this.handleButtonClick(t.detail),disabled:this.loading||"NEXT_BUTTON"===t.type&&!0!==t.config?.skip_validation&&v}))),this.renderPromptPartial(t,"form-footer-end"))),d&&o("div",{class:"secondary-actions",part:"secondary-actions"},this.renderPromptPartial(t,"secondary-actions-start"),this.renderScreenLinks(t),this.renderPromptPartial(t,"secondary-actions-end"))),!d&&this.renderScreenLinks(t),t.footer&&o("div",{class:"widget-footer",part:"footer",innerHTML:m(t.footer)})))}static get watchers(){return{screenId:[{watchScreenId:0}],screen:[{watchScreen:0}],branding:[{watchBranding:0}],theme:[{watchTheme:0}],authParams:[{watchAuthParams:0}]}}};y.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, 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{width:var(--ah-widget-max-width, 400px);margin:0 auto;background-color:var(--ah-color-bg, #ffffff);border-radius:var(--ah-widget-radius, 5px);border:var(--ah-widget-border-width, 0) solid var(--ah-widget-border-color, transparent);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-text-header, var(--ah-color-header, #1e212a));line-height:1.2}.description{font-size:var(--ah-font-size-subtitle, 16px);font-weight:var(--ah-font-weight-subtitle, 400);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-footer,.secondary-actions,.prompt-partial{display:flex;flex-direction:column}.prompt-partial .ulp-field{display:flex;flex-direction:column;gap:6px;position:relative;margin-top:8px;margin-bottom:16px}.prompt-partial label{font-size:var(--ah-font-size-label, 14px);font-weight:var(--ah-font-weight-label, 400);color:var(--ah-color-text, #1e212a)}.prompt-partial .ulp-error input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]),.prompt-partial .ulp-error select,.prompt-partial .ulp-error textarea{border-color:var(--ah-color-error, #d03c38)}.prompt-partial .ulp-error input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):focus,.prompt-partial .ulp-error select:focus,.prompt-partial .ulp-error textarea:focus{box-shadow:inset 0 0 0 1px var(--ah-color-error, #d03c38)}.prompt-partial .ulp-error-info{font-size:12px;color:var(--ah-color-error, #d03c38);margin-top:-2px;line-height:1.4}.prompt-partial .required{color:var(--ah-color-error, #d03c38);margin-left:2px}.prompt-partial .ulp-field>input+label,.prompt-partial .ulp-field>select+label,.prompt-partial .ulp-field>textarea+label{position:absolute;left:16px;top:50%;z-index:1;padding:0;background-color:transparent;color:var(--ah-color-text-muted, #65676e);pointer-events:none;transform:translateY(-50%);transition:all 0.15s ease-out}.prompt-partial .ulp-field>input:focus+label,.prompt-partial .ulp-field>input:not(:placeholder-shown)+label,.prompt-partial .ulp-field>select+label,.prompt-partial .ulp-field>textarea:focus+label,.prompt-partial .ulp-field>textarea:not(:placeholder-shown)+label{top:-8px;left:12px;padding:0 4px;background-color:var(--ah-color-bg, #ffffff);color:var(--ah-color-text-muted, #65676e);font-size:12px;transform:translateY(0)}.prompt-partial .ulp-field>input:focus+label,.prompt-partial .ulp-field>select:focus+label,.prompt-partial .ulp-field>textarea:focus+label{color:var(--ah-color-primary, #635dff)}.prompt-partial input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]),.prompt-partial select,.prompt-partial textarea{width:100%;padding:16px;font-size:16px;font-family:inherit;color:var(--ah-color-input-text, var(--ah-color-text, #1e212a));background-color:var(--ah-color-input-bg, #ffffff);border:var(--ah-input-border-width, 1px) solid var(--ah-color-border, #c9cace);border-radius:var(--ah-input-radius, 3px);outline:none;box-sizing:border-box;transition:border-color 0.15s ease-out, box-shadow 0.15s ease-out}.prompt-partial input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):hover,.prompt-partial select:hover,.prompt-partial textarea:hover{border-color:var(--ah-color-border-hover, #65676e)}.prompt-partial input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):focus,.prompt-partial select:focus,.prompt-partial textarea:focus{border-color:var(--ah-color-primary, #635dff);box-shadow:inset 0 0 0 1px var(--ah-color-primary, #635dff)}.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)}.fields-list{display:flex;flex-direction:column}.fields-list-scroll{max-height:var(--ah-choice-list-max-height, 320px);overflow-y:auto;gap:var(--ah-choice-list-gap, 8px);padding-right:4px}.choice-list-search{width:100%;padding:16px;margin-bottom:12px;font-size:16px;font-family:inherit;color:var(--ah-color-input-text, var(--ah-color-text, #1e212a));background-color:var(--ah-color-input-bg, #ffffff);border:var(--ah-input-border-width, 1px) solid var(--ah-color-border, #c9cace);border-radius:var(--ah-input-radius, 3px);outline:none;box-sizing:border-box;transition:border-color 0.15s ease-out, box-shadow 0.15s ease-out}.choice-list-search:hover{border-color:var(--ah-color-border-hover, #65676e)}.choice-list-search:focus{border-color:var(--ah-color-primary, var(--ah-color-link, #635dff))}.choice-list-empty{padding:16px;text-align:center;font-size:14px;color:var(--ah-color-text-muted, #65676e)}.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:var(--ah-font-size-body, 14px);font-weight:var(--ah-font-weight-body, 400);color:var(--ah-color-text, #1e212a)}.link{color:var(--ah-color-link, #635dff);text-decoration:var(--ah-link-decoration, none);font-size:var(--ah-font-size-link, 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-focus-ring, 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-focus-ring, 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(:not([floating])){display:block;width:100%;min-height:100vh;background-color:var(--ah-color-bg, #ffffff)}:host(:not([floating])) .widget-container{box-shadow:none;border-radius:0;border:0;width:100%;margin:0}:host([floating]) .widget-container{width:100%;margin:0}.widget-header{padding:24px 16px 16px}.widget-body{padding:0 16px 24px}}';export{y as authhero_widget}
|
|
@@ -517,7 +517,7 @@ function escapeAttr(value) {
|
|
|
517
517
|
.replace(/>/g, ">");
|
|
518
518
|
}
|
|
519
519
|
|
|
520
|
-
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{width:var(--ah-widget-max-width, 400px);margin:0 auto;background-color:var(--ah-color-bg, #ffffff);border-radius:var(--ah-widget-radius, 5px);border:var(--ah-widget-border-width, 0) solid var(--ah-widget-border-color, transparent);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-text-header, var(--ah-color-header, #1e212a));line-height:1.2}.description{font-size:var(--ah-font-size-subtitle, 16px);font-weight:var(--ah-font-weight-subtitle, 400);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)}.fields-list{display:flex;flex-direction:column}.fields-list-scroll{max-height:var(--ah-choice-list-max-height, 320px);overflow-y:auto;gap:var(--ah-choice-list-gap, 8px);padding-right:4px}.choice-list-search{width:100%;padding:16px;margin-bottom:12px;font-size:16px;font-family:inherit;color:var(--ah-color-input-text, var(--ah-color-text, #1e212a));background-color:var(--ah-color-input-bg, #ffffff);border:var(--ah-input-border-width, 1px) solid var(--ah-color-border, #c9cace);border-radius:var(--ah-input-radius, 3px);outline:none;box-sizing:border-box;transition:border-color 0.15s ease-out, box-shadow 0.15s ease-out}.choice-list-search:hover{border-color:var(--ah-color-border-hover, #65676e)}.choice-list-search:focus{border-color:var(--ah-color-primary, var(--ah-color-link, #635dff))}.choice-list-empty{padding:16px;text-align:center;font-size:14px;color:var(--ah-color-text-muted, #65676e)}.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:var(--ah-font-size-body, 14px);font-weight:var(--ah-font-weight-body, 400);color:var(--ah-color-text, #1e212a)}.link{color:var(--ah-color-link, #635dff);text-decoration:var(--ah-link-decoration, none);font-size:var(--ah-font-size-link, 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-focus-ring, 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-focus-ring, 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(:not([floating])){display:block;width:100%;min-height:100vh;background-color:var(--ah-color-bg, #ffffff)}:host(:not([floating])) .widget-container{box-shadow:none;border-radius:0;border:0;width:100%;margin:0}:host([floating]) .widget-container{width:100%;margin:0}.widget-header{padding:24px 16px 16px}.widget-body{padding:0 16px 24px}}`;
|
|
520
|
+
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{width:var(--ah-widget-max-width, 400px);margin:0 auto;background-color:var(--ah-color-bg, #ffffff);border-radius:var(--ah-widget-radius, 5px);border:var(--ah-widget-border-width, 0) solid var(--ah-widget-border-color, transparent);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-text-header, var(--ah-color-header, #1e212a));line-height:1.2}.description{font-size:var(--ah-font-size-subtitle, 16px);font-weight:var(--ah-font-weight-subtitle, 400);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-footer,.secondary-actions,.prompt-partial{display:flex;flex-direction:column}.prompt-partial .ulp-field{display:flex;flex-direction:column;gap:6px;position:relative;margin-top:8px;margin-bottom:16px}.prompt-partial label{font-size:var(--ah-font-size-label, 14px);font-weight:var(--ah-font-weight-label, 400);color:var(--ah-color-text, #1e212a)}.prompt-partial .ulp-error input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]),.prompt-partial .ulp-error select,.prompt-partial .ulp-error textarea{border-color:var(--ah-color-error, #d03c38)}.prompt-partial .ulp-error input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):focus,.prompt-partial .ulp-error select:focus,.prompt-partial .ulp-error textarea:focus{box-shadow:inset 0 0 0 1px var(--ah-color-error, #d03c38)}.prompt-partial .ulp-error-info{font-size:12px;color:var(--ah-color-error, #d03c38);margin-top:-2px;line-height:1.4}.prompt-partial .required{color:var(--ah-color-error, #d03c38);margin-left:2px}.prompt-partial .ulp-field>input+label,.prompt-partial .ulp-field>select+label,.prompt-partial .ulp-field>textarea+label{position:absolute;left:16px;top:50%;z-index:1;padding:0;background-color:transparent;color:var(--ah-color-text-muted, #65676e);pointer-events:none;transform:translateY(-50%);transition:all 0.15s ease-out}.prompt-partial .ulp-field>input:focus+label,.prompt-partial .ulp-field>input:not(:placeholder-shown)+label,.prompt-partial .ulp-field>select+label,.prompt-partial .ulp-field>textarea:focus+label,.prompt-partial .ulp-field>textarea:not(:placeholder-shown)+label{top:-8px;left:12px;padding:0 4px;background-color:var(--ah-color-bg, #ffffff);color:var(--ah-color-text-muted, #65676e);font-size:12px;transform:translateY(0)}.prompt-partial .ulp-field>input:focus+label,.prompt-partial .ulp-field>select:focus+label,.prompt-partial .ulp-field>textarea:focus+label{color:var(--ah-color-primary, #635dff)}.prompt-partial input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]),.prompt-partial select,.prompt-partial textarea{width:100%;padding:16px;font-size:16px;font-family:inherit;color:var(--ah-color-input-text, var(--ah-color-text, #1e212a));background-color:var(--ah-color-input-bg, #ffffff);border:var(--ah-input-border-width, 1px) solid var(--ah-color-border, #c9cace);border-radius:var(--ah-input-radius, 3px);outline:none;box-sizing:border-box;transition:border-color 0.15s ease-out, box-shadow 0.15s ease-out}.prompt-partial input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):hover,.prompt-partial select:hover,.prompt-partial textarea:hover{border-color:var(--ah-color-border-hover, #65676e)}.prompt-partial input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):focus,.prompt-partial select:focus,.prompt-partial textarea:focus{border-color:var(--ah-color-primary, #635dff);box-shadow:inset 0 0 0 1px var(--ah-color-primary, #635dff)}.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)}.fields-list{display:flex;flex-direction:column}.fields-list-scroll{max-height:var(--ah-choice-list-max-height, 320px);overflow-y:auto;gap:var(--ah-choice-list-gap, 8px);padding-right:4px}.choice-list-search{width:100%;padding:16px;margin-bottom:12px;font-size:16px;font-family:inherit;color:var(--ah-color-input-text, var(--ah-color-text, #1e212a));background-color:var(--ah-color-input-bg, #ffffff);border:var(--ah-input-border-width, 1px) solid var(--ah-color-border, #c9cace);border-radius:var(--ah-input-radius, 3px);outline:none;box-sizing:border-box;transition:border-color 0.15s ease-out, box-shadow 0.15s ease-out}.choice-list-search:hover{border-color:var(--ah-color-border-hover, #65676e)}.choice-list-search:focus{border-color:var(--ah-color-primary, var(--ah-color-link, #635dff))}.choice-list-empty{padding:16px;text-align:center;font-size:14px;color:var(--ah-color-text-muted, #65676e)}.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:var(--ah-font-size-body, 14px);font-weight:var(--ah-font-weight-body, 400);color:var(--ah-color-text, #1e212a)}.link{color:var(--ah-color-link, #635dff);text-decoration:var(--ah-link-decoration, none);font-size:var(--ah-font-size-link, 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-focus-ring, 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-focus-ring, 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(:not([floating])){display:block;width:100%;min-height:100vh;background-color:var(--ah-color-bg, #ffffff)}:host(:not([floating])) .widget-container{box-shadow:none;border-radius:0;border:0;width:100%;margin:0}:host([floating]) .widget-container{width:100%;margin:0}.widget-header{padding:24px 16px 16px}.widget-body{padding:0 16px 24px}}`;
|
|
521
521
|
|
|
522
522
|
/**
|
|
523
523
|
* When a screen's field section is made up entirely of choice buttons
|
|
@@ -532,6 +532,19 @@ const CHOICE_LIST_SEARCH_THRESHOLD = 5;
|
|
|
532
532
|
* (CARDS, FILE, RECAPTCHA, …) can carry `required` in the schema too, and
|
|
533
533
|
* gating on them would leave Continue disabled with no way to satisfy it.
|
|
534
534
|
*/
|
|
535
|
+
/**
|
|
536
|
+
* Field types rendered as a single plain text input whose value maps 1:1 to
|
|
537
|
+
* formData. Composite fields (TEL, DATE) and choice/checkbox fields keep
|
|
538
|
+
* internal state, so they're not adopted from pre-hydration markup.
|
|
539
|
+
*/
|
|
540
|
+
const PREHYDRATION_TEXT_TYPES = new Set([
|
|
541
|
+
"TEXT",
|
|
542
|
+
"EMAIL",
|
|
543
|
+
"CODE",
|
|
544
|
+
"PASSWORD",
|
|
545
|
+
"NUMBER",
|
|
546
|
+
"URL",
|
|
547
|
+
]);
|
|
535
548
|
const FILLABLE_FIELD_TYPES = new Set([
|
|
536
549
|
"TEXT",
|
|
537
550
|
"EMAIL",
|
|
@@ -912,7 +925,24 @@ const AuthheroWidget = class {
|
|
|
912
925
|
* actually in the DOM before measuring its height.
|
|
913
926
|
*/
|
|
914
927
|
pendingRenderResolvers = [];
|
|
928
|
+
/**
|
|
929
|
+
* Number of `swapScreen` calls still running (rendering or animating the
|
|
930
|
+
* card height). A counter rather than a flag because a newer swap can start
|
|
931
|
+
* before a superseded one has settled.
|
|
932
|
+
*/
|
|
933
|
+
activeSwaps = 0;
|
|
934
|
+
updateReadyAttribute() {
|
|
935
|
+
{
|
|
936
|
+
this.el.toggleAttribute("data-ready", !this.loading && this.activeSwaps === 0);
|
|
937
|
+
}
|
|
938
|
+
}
|
|
915
939
|
componentDidRender() {
|
|
940
|
+
// `data-ready` marks the widget as interactive: hydrated in the browser
|
|
941
|
+
// (the SSR markup already carries Stencil's `hydrated` class, so that
|
|
942
|
+
// can't tell server and client apart) and not mid-submit or mid-swap.
|
|
943
|
+
// Stencil defers this hook until child nodes have rendered, so the
|
|
944
|
+
// fields are live too. E2E tests wait on `authhero-widget[data-ready]`.
|
|
945
|
+
this.updateReadyAttribute();
|
|
916
946
|
if (this.pendingRenderResolvers.length === 0)
|
|
917
947
|
return;
|
|
918
948
|
const resolvers = this.pendingRenderResolvers;
|
|
@@ -960,6 +990,18 @@ const AuthheroWidget = class {
|
|
|
960
990
|
apply();
|
|
961
991
|
return;
|
|
962
992
|
}
|
|
993
|
+
// Hold `data-ready` off until the new screen has rendered and the height
|
|
994
|
+
// animation has finished; `apply()` clears `loading` before either.
|
|
995
|
+
this.activeSwaps++;
|
|
996
|
+
try {
|
|
997
|
+
await this.animateSwap(card, apply);
|
|
998
|
+
}
|
|
999
|
+
finally {
|
|
1000
|
+
this.activeSwaps--;
|
|
1001
|
+
this.updateReadyAttribute();
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
async animateSwap(card, apply) {
|
|
963
1005
|
// Lock the current height and clip, so swapping the content doesn't jump
|
|
964
1006
|
// before the animation runs.
|
|
965
1007
|
const startHeight = card.getBoundingClientRect().height;
|
|
@@ -1124,6 +1166,9 @@ const AuthheroWidget = class {
|
|
|
1124
1166
|
if (!this._authParams) {
|
|
1125
1167
|
this.watchAuthParams(this.authParams ?? this.readJsonScript("auth-params"));
|
|
1126
1168
|
}
|
|
1169
|
+
if (this._screen) {
|
|
1170
|
+
this.adoptPrehydrationValues(this._screen);
|
|
1171
|
+
}
|
|
1127
1172
|
// Load persisted state if available
|
|
1128
1173
|
this.loadPersistedState();
|
|
1129
1174
|
// Fetch screen from API if URL provided and no screen prop
|
|
@@ -1131,6 +1176,41 @@ const AuthheroWidget = class {
|
|
|
1131
1176
|
await this.fetchScreen(this.screenId);
|
|
1132
1177
|
}
|
|
1133
1178
|
}
|
|
1179
|
+
/**
|
|
1180
|
+
* Carry over text the user (or a password manager, or a test driver) put
|
|
1181
|
+
* into the server-rendered inputs before the client bundle loaded. Those
|
|
1182
|
+
* inputs had no `onInput` handler yet, so `formData` never saw the value:
|
|
1183
|
+
* the first client render would reset them to "" and keep the submit
|
|
1184
|
+
* button disabled. The declarative shadow roots are still the SSR ones
|
|
1185
|
+
* here — `componentWillLoad` runs before the first client render.
|
|
1186
|
+
*/
|
|
1187
|
+
adoptPrehydrationValues(screen) {
|
|
1188
|
+
const root = this.el.shadowRoot;
|
|
1189
|
+
if (!root)
|
|
1190
|
+
return;
|
|
1191
|
+
const roots = [root];
|
|
1192
|
+
root.querySelectorAll("authhero-node").forEach((node) => {
|
|
1193
|
+
if (node.shadowRoot)
|
|
1194
|
+
roots.push(node.shadowRoot);
|
|
1195
|
+
});
|
|
1196
|
+
const adopted = {};
|
|
1197
|
+
for (const component of screen.components ?? []) {
|
|
1198
|
+
if (!PREHYDRATION_TEXT_TYPES.has(component.type))
|
|
1199
|
+
continue;
|
|
1200
|
+
for (const r of roots) {
|
|
1201
|
+
const input = Array.from(r.querySelectorAll("input[name]")).find((el) => el.name === component.id && el.type !== "hidden");
|
|
1202
|
+
// Adopt "" too: a prefilled default the user cleared before
|
|
1203
|
+
// hydration must not be restored by the client render.
|
|
1204
|
+
if (input) {
|
|
1205
|
+
adopted[component.id] = input.value;
|
|
1206
|
+
break;
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
if (Object.keys(adopted).length > 0) {
|
|
1211
|
+
this.formData = { ...this.formData, ...adopted };
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1134
1214
|
/**
|
|
1135
1215
|
* Fetch screen configuration from the API
|
|
1136
1216
|
* @param screenIdOverride Optional screen ID to fetch (overrides this.screenId)
|
|
@@ -1232,14 +1312,44 @@ const AuthheroWidget = class {
|
|
|
1232
1312
|
e.preventDefault();
|
|
1233
1313
|
if (!this._screen || this.loading)
|
|
1234
1314
|
return;
|
|
1235
|
-
let submitData = { ...this.formData, ...(overrideData || {}) };
|
|
1236
|
-
// Merge hidden input values from DOM (may have been set programmatically
|
|
1237
|
-
// by inline scripts, e.g. passkey management buttons)
|
|
1238
1315
|
const form = this.el.shadowRoot?.querySelector("form");
|
|
1316
|
+
if (this._screen.partials &&
|
|
1317
|
+
form?.reportValidity &&
|
|
1318
|
+
!form.reportValidity()) {
|
|
1319
|
+
return;
|
|
1320
|
+
}
|
|
1321
|
+
const submitData = {
|
|
1322
|
+
...this.formData,
|
|
1323
|
+
...(overrideData || {}),
|
|
1324
|
+
};
|
|
1325
|
+
// Native fields in prompt partials are direct descendants of this form,
|
|
1326
|
+
// unlike authhero-node inputs in nested shadow roots. Read them through
|
|
1327
|
+
// FormData so standard HTML controls and successful-control semantics are
|
|
1328
|
+
// preserved (disabled controls are skipped, repeated names are kept as
|
|
1329
|
+
// arrays). FormData also covers enabled hidden inputs for ulp-* names.
|
|
1330
|
+
const nativeNames = new Set();
|
|
1331
|
+
if (form && this._screen.partials) {
|
|
1332
|
+
const nativeValues = {};
|
|
1333
|
+
new FormData(form).forEach((value, key) => {
|
|
1334
|
+
if (typeof value === "string" && key.startsWith("ulp-")) {
|
|
1335
|
+
(nativeValues[key] ??= []).push(value);
|
|
1336
|
+
}
|
|
1337
|
+
});
|
|
1338
|
+
for (const [key, values] of Object.entries(nativeValues)) {
|
|
1339
|
+
nativeNames.add(key);
|
|
1340
|
+
submitData[key] = values.length > 1 ? values : values[0];
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
// Legacy behaviour for inline scripts that fill hidden inputs: merge
|
|
1344
|
+
// enabled ones, but never overwrite what FormData already collected.
|
|
1239
1345
|
if (form) {
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1346
|
+
form
|
|
1347
|
+
.querySelectorAll('input[type="hidden"]')
|
|
1348
|
+
.forEach((input) => {
|
|
1349
|
+
if (input.name &&
|
|
1350
|
+
input.value &&
|
|
1351
|
+
!input.disabled &&
|
|
1352
|
+
!nativeNames.has(input.name)) {
|
|
1243
1353
|
submitData[input.name] = input.value;
|
|
1244
1354
|
}
|
|
1245
1355
|
});
|
|
@@ -1393,6 +1503,11 @@ const AuthheroWidget = class {
|
|
|
1393
1503
|
if (!form)
|
|
1394
1504
|
return;
|
|
1395
1505
|
form.submit = () => {
|
|
1506
|
+
if (this._screen?.partials &&
|
|
1507
|
+
form.reportValidity &&
|
|
1508
|
+
!form.reportValidity()) {
|
|
1509
|
+
return;
|
|
1510
|
+
}
|
|
1396
1511
|
const formData = new FormData(form);
|
|
1397
1512
|
const data = {};
|
|
1398
1513
|
formData.forEach((value, key) => {
|
|
@@ -1997,6 +2112,27 @@ const AuthheroWidget = class {
|
|
|
1997
2112
|
const config = component.config;
|
|
1998
2113
|
return config?.text ?? "";
|
|
1999
2114
|
}
|
|
2115
|
+
renderPromptPartial(screen, insertionPoint) {
|
|
2116
|
+
const html = screen.partials?.[insertionPoint];
|
|
2117
|
+
if (!html)
|
|
2118
|
+
return null;
|
|
2119
|
+
// Prompt partials intentionally contain tenant-authored form controls, so
|
|
2120
|
+
// the widget must keep their input attributes intact.
|
|
2121
|
+
return (index.h("div", { class: `prompt-partial prompt-partial-${insertionPoint}`, part: `prompt-partial prompt-partial-${insertionPoint}`, "data-insertion-point": insertionPoint, innerHTML: html }));
|
|
2122
|
+
}
|
|
2123
|
+
renderScreenLinks(screen) {
|
|
2124
|
+
if (!screen.links?.length)
|
|
2125
|
+
return null;
|
|
2126
|
+
return (index.h("div", { class: "links", part: "links" }, screen.links.map((link) => (index.h("span", { class: "link-wrapper", part: "link-wrapper", key: link.id ?? link.href }, link.linkText ? (index.h("span", null, link.text, " ", index.h("a", { href: link.href, class: "link", part: "link", onClick: (e) => this.handleLinkClick(e, {
|
|
2127
|
+
id: link.id,
|
|
2128
|
+
href: link.href,
|
|
2129
|
+
text: link.linkText || link.text,
|
|
2130
|
+
}) }, link.linkText))) : (index.h("a", { href: link.href, class: "link", part: "link", onClick: (e) => this.handleLinkClick(e, {
|
|
2131
|
+
id: link.id,
|
|
2132
|
+
href: link.href,
|
|
2133
|
+
text: link.text,
|
|
2134
|
+
}) }, link.text)))))));
|
|
2135
|
+
}
|
|
2000
2136
|
render() {
|
|
2001
2137
|
const screen = this._screen;
|
|
2002
2138
|
if (this.loading && !screen) {
|
|
@@ -2023,13 +2159,20 @@ const AuthheroWidget = class {
|
|
|
2023
2159
|
? components.find((c) => this.isDividerComponent(c))
|
|
2024
2160
|
: undefined;
|
|
2025
2161
|
const fieldComponents = components.filter((c) => !this.isSocialComponent(c) && c !== dividerComponent);
|
|
2162
|
+
const hasPromptPartials = Object.values(screen.partials ?? {}).some((html) => !!html);
|
|
2163
|
+
const footerComponents = hasPromptPartials
|
|
2164
|
+
? fieldComponents.filter((component) => component.id === "submit" && component.type === "NEXT_BUTTON")
|
|
2165
|
+
: [];
|
|
2166
|
+
const contentFieldComponents = hasPromptPartials
|
|
2167
|
+
? fieldComponents.filter((component) => !footerComponents.includes(component))
|
|
2168
|
+
: fieldComponents;
|
|
2026
2169
|
const hasDivider = !!dividerComponent;
|
|
2027
2170
|
const dividerText = dividerComponent?.config?.text || "Or";
|
|
2028
2171
|
// A "choice list" screen is one whose entire field section is pick-one
|
|
2029
2172
|
// buttons (e.g. tenant selection). When the list is long, render it as a
|
|
2030
2173
|
// searchable, scrollable list instead of a tall column of buttons.
|
|
2031
|
-
const choiceButtons =
|
|
2032
|
-
const isSearchableChoiceList = choiceButtons.length ===
|
|
2174
|
+
const choiceButtons = contentFieldComponents.filter((c) => c.type === "NEXT_BUTTON");
|
|
2175
|
+
const isSearchableChoiceList = choiceButtons.length === contentFieldComponents.length &&
|
|
2033
2176
|
choiceButtons.length > CHOICE_LIST_SEARCH_THRESHOLD;
|
|
2034
2177
|
// Hold the primary action button disabled until every required field has
|
|
2035
2178
|
// a value.
|
|
@@ -2070,7 +2213,7 @@ const AuthheroWidget = class {
|
|
|
2070
2213
|
};
|
|
2071
2214
|
// Get logo URL from theme.widget (takes precedence) or branding
|
|
2072
2215
|
const logoUrl = this._theme?.widget?.logo_url || this._branding?.logo_url;
|
|
2073
|
-
return (index.h("div", { class: "widget-container", part: "container", "data-authstack-container": true }, index.h("header", { class: "widget-header", part: "header" }, logoUrl && (index.h("div", { class: "logo-wrapper", part: "logo-wrapper" }, index.h("img", { class: "logo", part: "logo", src: logoUrl, alt: "Logo" }))), screen.title && (index.h("h1", { class: "title", part: "title", innerHTML: sanitizeHtml(screen.title) })), screen.description && (index.h("p", { class: "description", part: "description", innerHTML: sanitizeHtml(screen.description) }))), index.h("div", { class: "widget-body", part: "body" }, screenErrors.map((err) => (index.h("div", { class: "message message-error", part: "message message-error", key: err.id ?? err.text }, err.text))), screenSuccesses.map((msg) => (index.h("div", { class: "message message-success", part: "message message-success", key: msg.id ?? msg.text }, msg.text))), index.h("form", { onSubmit: this.handleSubmit, action: screen.action, method: screen.method || "POST", part: "form" }, hiddenComponents.map((c) => (index.h("input", { type: "hidden", name: c.id, id: c.id, key: c.id, value: this.formData[c.id] || "" }))), index.h("div", { class: "form-content" }, socialComponents.length > 0 && (index.h("div", { class: "social-section", part: "social-section" }, socialComponents.map((component) => (index.h("authhero-node", { key: component.id, component: component, locale: this.locale, value: this.formData[component.id], onFieldChange: (e) => this.handleInputChange(e.detail.id, e.detail.value), onButtonClick: (e) => this.handleButtonClick(e.detail), disabled: this.loading, exportparts: getExportParts(component) }))))), socialComponents.length > 0 &&
|
|
2216
|
+
return (index.h("div", { class: "widget-container", part: "container", "data-authstack-container": true }, index.h("header", { class: "widget-header", part: "header" }, logoUrl && (index.h("div", { class: "logo-wrapper", part: "logo-wrapper" }, index.h("img", { class: "logo", part: "logo", src: logoUrl, alt: "Logo" }))), screen.title && (index.h("h1", { class: "title", part: "title", innerHTML: sanitizeHtml(screen.title) })), screen.description && (index.h("p", { class: "description", part: "description", innerHTML: sanitizeHtml(screen.description) }))), index.h("div", { class: "widget-body", part: "body" }, screenErrors.map((err) => (index.h("div", { class: "message message-error", part: "message message-error", key: err.id ?? err.text }, err.text))), screenSuccesses.map((msg) => (index.h("div", { class: "message message-success", part: "message message-success", key: msg.id ?? msg.text }, msg.text))), index.h("form", { onSubmit: this.handleSubmit, action: screen.action, method: screen.method || "POST", part: "form" }, hiddenComponents.map((c) => (index.h("input", { type: "hidden", name: c.id, id: c.id, key: c.id, value: this.formData[c.id] || "" }))), index.h("div", { class: "form-content" }, this.renderPromptPartial(screen, "form-content-start"), socialComponents.length > 0 && (index.h("div", { class: "social-section", part: "social-section" }, socialComponents.map((component) => (index.h("authhero-node", { key: component.id, component: component, locale: this.locale, value: this.formData[component.id], onFieldChange: (e) => this.handleInputChange(e.detail.id, e.detail.value), onButtonClick: (e) => this.handleButtonClick(e.detail), disabled: this.loading, exportparts: getExportParts(component) }))))), socialComponents.length > 0 &&
|
|
2074
2217
|
fieldComponents.length > 0 &&
|
|
2075
2218
|
hasDivider && (index.h("div", { class: "divider", part: "divider" }, index.h("span", { class: "divider-text" }, dividerText))), index.h("div", { class: "fields-section", part: "fields-section" }, isSearchableChoiceList && (index.h("input", { type: "text", class: "choice-list-search", part: "choice-list-search", placeholder: "Search", "aria-label": "Search", autocomplete: "off", value: this.listFilter, onInput: (e) => (this.listFilter = e.target.value), onKeyDown: (e) => {
|
|
2076
2219
|
// The search box lives inside the form; Enter would
|
|
@@ -2083,19 +2226,14 @@ const AuthheroWidget = class {
|
|
|
2083
2226
|
? "fields-list fields-list-scroll"
|
|
2084
2227
|
: "fields-list" }, (isSearchableChoiceList
|
|
2085
2228
|
? visibleChoiceButtons
|
|
2086
|
-
:
|
|
2229
|
+
: contentFieldComponents).map((component) => (index.h("authhero-node", { key: component.id, component: component, locale: this.locale, value: this.formData[component.id], onFieldChange: (e) => this.handleInputChange(e.detail.id, e.detail.value), onButtonClick: (e) => this.handleButtonClick(e.detail), disabled: this.loading ||
|
|
2087
2230
|
(component.type === "NEXT_BUTTON" &&
|
|
2088
2231
|
component.config?.skip_validation !== true &&
|
|
2089
2232
|
requiredFieldsMissing) }))), isSearchableChoiceList &&
|
|
2090
|
-
visibleChoiceButtons.length === 0 && (index.h("div", { class: "choice-list-empty", part: "choice-list-empty" }, "No matches"))))
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
}) }, link.linkText))) : (index.h("a", { href: link.href, class: "link", part: "link", onClick: (e) => this.handleLinkClick(e, {
|
|
2095
|
-
id: link.id,
|
|
2096
|
-
href: link.href,
|
|
2097
|
-
text: link.text,
|
|
2098
|
-
}) }, link.text))))))), screen.footer && (index.h("div", { class: "widget-footer", part: "footer", innerHTML: sanitizeHtml(screen.footer) })))));
|
|
2233
|
+
visibleChoiceButtons.length === 0 && (index.h("div", { class: "choice-list-empty", part: "choice-list-empty" }, "No matches")))), this.renderPromptPartial(screen, "form-content-end"), hasPromptPartials && (index.h("div", { class: "form-footer", part: "form-footer" }, this.renderPromptPartial(screen, "form-footer-start"), footerComponents.map((component) => (index.h("authhero-node", { key: component.id, component: component, locale: this.locale, value: this.formData[component.id], onFieldChange: (e) => this.handleInputChange(e.detail.id, e.detail.value), onButtonClick: (e) => this.handleButtonClick(e.detail), disabled: this.loading ||
|
|
2234
|
+
(component.type === "NEXT_BUTTON" &&
|
|
2235
|
+
component.config?.skip_validation !== true &&
|
|
2236
|
+
requiredFieldsMissing) }))), this.renderPromptPartial(screen, "form-footer-end")))), hasPromptPartials && (index.h("div", { class: "secondary-actions", part: "secondary-actions" }, this.renderPromptPartial(screen, "secondary-actions-start"), this.renderScreenLinks(screen), this.renderPromptPartial(screen, "secondary-actions-end")))), !hasPromptPartials && this.renderScreenLinks(screen), screen.footer && (index.h("div", { class: "widget-footer", part: "footer", innerHTML: sanitizeHtml(screen.footer) })))));
|
|
2099
2237
|
}
|
|
2100
2238
|
static get watchers() { return {
|
|
2101
2239
|
"screenId": [{
|