@authhero/widget 0.34.0 → 0.34.2
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-52a70476.entry.js +1 -0
- package/dist/cjs/authhero-widget.cjs.entry.js +49 -2
- package/dist/cjs/authhero-widget.cjs.js +1 -1
- package/dist/cjs/index.cjs.js +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/collection/components/authhero-widget/authhero-widget.css +47 -0
- package/dist/collection/components/authhero-widget/authhero-widget.js +50 -2
- package/dist/components/authhero-widget.js +1 -1
- package/dist/components/index.js +1 -1
- package/dist/esm/authhero-widget.entry.js +49 -2
- package/dist/esm/authhero-widget.js +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/types/components/authhero-widget/authhero-widget.d.ts +10 -0
- package/hydrate/index.js +51 -3
- package/hydrate/index.mjs +51 -3
- package/package.json +2 -2
- package/dist/authhero-widget/p-5a319adc.entry.js +0 -1
|
@@ -514,8 +514,15 @@ function escapeAttr(value) {
|
|
|
514
514
|
.replace(/>/g, ">");
|
|
515
515
|
}
|
|
516
516
|
|
|
517
|
-
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)}.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{display:block;width:100%;min-height:100vh;background-color:var(--ah-color-bg, #ffffff)}.widget-container{box-shadow:none;border-radius:0;width:100%;margin:0}.widget-header{padding:24px 16px 16px}.widget-body{padding:0 16px 24px}}`;
|
|
517
|
+
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{display:block;width:100%;min-height:100vh;background-color:var(--ah-color-bg, #ffffff)}.widget-container{box-shadow:none;border-radius:0;width:100%;margin:0}.widget-header{padding:24px 16px 16px}.widget-body{padding:0 16px 24px}}`;
|
|
518
518
|
|
|
519
|
+
/**
|
|
520
|
+
* When a screen's field section is made up entirely of choice buttons
|
|
521
|
+
* (NEXT_BUTTON) and there are more than this many, the widget renders them as
|
|
522
|
+
* a scrollable list with a search box on top instead of a tall column of
|
|
523
|
+
* buttons. Used by long pick-one screens such as tenant selection.
|
|
524
|
+
*/
|
|
525
|
+
const CHOICE_LIST_SEARCH_THRESHOLD = 5;
|
|
519
526
|
const AuthheroWidget = class {
|
|
520
527
|
constructor(hostRef) {
|
|
521
528
|
registerInstance(this, hostRef);
|
|
@@ -628,6 +635,12 @@ const AuthheroWidget = class {
|
|
|
628
635
|
* Form data collected from inputs.
|
|
629
636
|
*/
|
|
630
637
|
formData = {};
|
|
638
|
+
/**
|
|
639
|
+
* Search query used to filter long choice-button lists (e.g. the
|
|
640
|
+
* tenant-select screen). Only applied when the screen is rendered as a
|
|
641
|
+
* searchable choice list — see CHOICE_LIST_SEARCH_THRESHOLD.
|
|
642
|
+
*/
|
|
643
|
+
listFilter = "";
|
|
631
644
|
/**
|
|
632
645
|
* AbortController for an in-flight conditional mediation request.
|
|
633
646
|
* Aborted on screen change or component disconnect.
|
|
@@ -688,6 +701,7 @@ const AuthheroWidget = class {
|
|
|
688
701
|
}
|
|
689
702
|
if (this._screen) {
|
|
690
703
|
this.formData = {};
|
|
704
|
+
this.listFilter = "";
|
|
691
705
|
this.initFormDataFromDefaults(this._screen);
|
|
692
706
|
this.screenChange.emit(this._screen);
|
|
693
707
|
this.updateDataScreenAttribute();
|
|
@@ -1131,6 +1145,8 @@ const AuthheroWidget = class {
|
|
|
1131
1145
|
this._screen = data;
|
|
1132
1146
|
}
|
|
1133
1147
|
if (this._screen) {
|
|
1148
|
+
// New screen fetched — drop any stale searchable-list filter.
|
|
1149
|
+
this.listFilter = "";
|
|
1134
1150
|
// If we fetched with a screenId override, update our stored screenId
|
|
1135
1151
|
if (currentScreenId && currentScreenId !== this.screenId) {
|
|
1136
1152
|
this.screenId = currentScreenId;
|
|
@@ -1248,6 +1264,7 @@ const AuthheroWidget = class {
|
|
|
1248
1264
|
// freeze a disabled button into the cross-fade.
|
|
1249
1265
|
this.loading = false;
|
|
1250
1266
|
this._screen = result.screen;
|
|
1267
|
+
this.listFilter = "";
|
|
1251
1268
|
this.initFormDataFromDefaults(result.screen);
|
|
1252
1269
|
this.screenChange.emit(result.screen);
|
|
1253
1270
|
this.updateDataScreenAttribute();
|
|
@@ -1261,6 +1278,7 @@ const AuthheroWidget = class {
|
|
|
1261
1278
|
// freeze a disabled button into the cross-fade.
|
|
1262
1279
|
this.loading = false;
|
|
1263
1280
|
this._screen = result.screen;
|
|
1281
|
+
this.listFilter = "";
|
|
1264
1282
|
this.formData = {};
|
|
1265
1283
|
this.initFormDataFromDefaults(result.screen);
|
|
1266
1284
|
this.screenChange.emit(result.screen);
|
|
@@ -1893,6 +1911,13 @@ const AuthheroWidget = class {
|
|
|
1893
1911
|
isDividerComponent(component) {
|
|
1894
1912
|
return component.type === "DIVIDER";
|
|
1895
1913
|
}
|
|
1914
|
+
/**
|
|
1915
|
+
* Visible label of a choice button, used to filter searchable choice lists.
|
|
1916
|
+
*/
|
|
1917
|
+
getChoiceButtonText(component) {
|
|
1918
|
+
const config = component.config;
|
|
1919
|
+
return config?.text ?? "";
|
|
1920
|
+
}
|
|
1896
1921
|
render() {
|
|
1897
1922
|
const screen = this._screen;
|
|
1898
1923
|
if (this.loading && !screen) {
|
|
@@ -1915,6 +1940,16 @@ const AuthheroWidget = class {
|
|
|
1915
1940
|
const dividerComponent = components.find((c) => this.isDividerComponent(c));
|
|
1916
1941
|
const hasDivider = !!dividerComponent;
|
|
1917
1942
|
const dividerText = dividerComponent?.config?.text || "Or";
|
|
1943
|
+
// A "choice list" screen is one whose entire field section is pick-one
|
|
1944
|
+
// buttons (e.g. tenant selection). When the list is long, render it as a
|
|
1945
|
+
// searchable, scrollable list instead of a tall column of buttons.
|
|
1946
|
+
const choiceButtons = fieldComponents.filter((c) => c.type === "NEXT_BUTTON");
|
|
1947
|
+
const isSearchableChoiceList = choiceButtons.length === fieldComponents.length &&
|
|
1948
|
+
choiceButtons.length > CHOICE_LIST_SEARCH_THRESHOLD;
|
|
1949
|
+
const filterQuery = this.listFilter.trim().toLowerCase();
|
|
1950
|
+
const visibleChoiceButtons = isSearchableChoiceList && filterQuery
|
|
1951
|
+
? choiceButtons.filter((c) => this.getChoiceButtonText(c).toLowerCase().includes(filterQuery))
|
|
1952
|
+
: choiceButtons;
|
|
1918
1953
|
// Build dynamic exportparts for social buttons including provider-specific parts
|
|
1919
1954
|
const getExportParts = (component) => {
|
|
1920
1955
|
const baseParts = [
|
|
@@ -1945,7 +1980,19 @@ const AuthheroWidget = class {
|
|
|
1945
1980
|
const logoUrl = this._theme?.widget?.logo_url || this._branding?.logo_url;
|
|
1946
1981
|
return (h("div", { class: "widget-container", part: "container", "data-authstack-container": true }, h("header", { class: "widget-header", part: "header" }, logoUrl && (h("div", { class: "logo-wrapper", part: "logo-wrapper" }, h("img", { class: "logo", part: "logo", src: logoUrl, alt: "Logo" }))), screen.title && (h("h1", { class: "title", part: "title", innerHTML: sanitizeHtml(screen.title) })), screen.description && (h("p", { class: "description", part: "description", innerHTML: sanitizeHtml(screen.description) }))), h("div", { class: "widget-body", part: "body" }, screenErrors.map((err) => (h("div", { class: "message message-error", part: "message message-error", key: err.id ?? err.text }, err.text))), screenSuccesses.map((msg) => (h("div", { class: "message message-success", part: "message message-success", key: msg.id ?? msg.text }, msg.text))), h("form", { onSubmit: this.handleSubmit, action: screen.action, method: screen.method || "POST", part: "form" }, hiddenComponents.map((c) => (h("input", { type: "hidden", name: c.id, id: c.id, key: c.id, value: this.formData[c.id] || "" }))), h("div", { class: "form-content" }, socialComponents.length > 0 && (h("div", { class: "social-section", part: "social-section" }, socialComponents.map((component) => (h("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, exportparts: getExportParts(component) }))))), socialComponents.length > 0 &&
|
|
1947
1982
|
fieldComponents.length > 0 &&
|
|
1948
|
-
hasDivider && (h("div", { class: "divider", part: "divider" }, h("span", { class: "divider-text" }, dividerText))), h("div", { class: "fields-section", part: "fields-section" },
|
|
1983
|
+
hasDivider && (h("div", { class: "divider", part: "divider" }, h("span", { class: "divider-text" }, dividerText))), h("div", { class: "fields-section", part: "fields-section" }, isSearchableChoiceList && (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) => {
|
|
1984
|
+
// The search box lives inside the form; Enter would
|
|
1985
|
+
// submit with no choice selected. Swallow it.
|
|
1986
|
+
if (e.key === "Enter")
|
|
1987
|
+
e.preventDefault();
|
|
1988
|
+
} })), h("div", { class: isSearchableChoiceList
|
|
1989
|
+
? "fields-list fields-list-scroll"
|
|
1990
|
+
: "fields-list", part: isSearchableChoiceList
|
|
1991
|
+
? "fields-list fields-list-scroll"
|
|
1992
|
+
: "fields-list" }, (isSearchableChoiceList
|
|
1993
|
+
? visibleChoiceButtons
|
|
1994
|
+
: fieldComponents).map((component) => (h("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 }))), isSearchableChoiceList &&
|
|
1995
|
+
visibleChoiceButtons.length === 0 && (h("div", { class: "choice-list-empty", part: "choice-list-empty" }, "No matches")))))), screen.links && screen.links.length > 0 && (h("div", { class: "links", part: "links" }, screen.links.map((link) => (h("span", { class: "link-wrapper", part: "link-wrapper", key: link.id ?? link.href }, link.linkText ? (h("span", null, link.text, " ", h("a", { href: link.href, class: "link", part: "link", onClick: (e) => this.handleLinkClick(e, {
|
|
1949
1996
|
id: link.id,
|
|
1950
1997
|
href: link.href,
|
|
1951
1998
|
text: link.linkText || link.text,
|
|
@@ -17,5 +17,5 @@ var patchBrowser = () => {
|
|
|
17
17
|
|
|
18
18
|
patchBrowser().then(async (options) => {
|
|
19
19
|
await globalScripts();
|
|
20
|
-
return bootstrapLazy([["authhero-node",[[513,"authhero-node",{"component":[16],"value":[1],"disabled":[4],"passwordVisible":[32],"selectedCountry":[32],"localPhoneNumber":[32],"countryDropdownOpen":[32],"telEmailMode":[32]},null,{"component":[{"componentChanged":0}],"value":[{"valueChanged":0}]}]]],["authhero-widget",[[513,"authhero-widget",{"screen":[1],"apiUrl":[1,"api-url"],"baseUrl":[1,"base-url"],"state":[1025],"screenId":[1025,"screen-id"],"authParams":[1,"auth-params"],"statePersistence":[1,"state-persistence"],"storageKey":[1,"storage-key"],"branding":[1],"theme":[1],"loading":[1028],"autoSubmit":[4,"auto-submit"],"autoNavigate":[4,"auto-navigate"],"_screen":[32],"_authParams":[32],"_branding":[32],"_theme":[32],"formData":[32]},null,{"screenId":[{"watchScreenId":0}],"screen":[{"watchScreen":0}],"branding":[{"watchBranding":0}],"theme":[{"watchTheme":0}],"authParams":[{"watchAuthParams":0}]}]]]], options);
|
|
20
|
+
return bootstrapLazy([["authhero-node",[[513,"authhero-node",{"component":[16],"value":[1],"disabled":[4],"passwordVisible":[32],"selectedCountry":[32],"localPhoneNumber":[32],"countryDropdownOpen":[32],"telEmailMode":[32]},null,{"component":[{"componentChanged":0}],"value":[{"valueChanged":0}]}]]],["authhero-widget",[[513,"authhero-widget",{"screen":[1],"apiUrl":[1,"api-url"],"baseUrl":[1,"base-url"],"state":[1025],"screenId":[1025,"screen-id"],"authParams":[1,"auth-params"],"statePersistence":[1,"state-persistence"],"storageKey":[1,"storage-key"],"branding":[1],"theme":[1],"loading":[1028],"autoSubmit":[4,"auto-submit"],"autoNavigate":[4,"auto-navigate"],"_screen":[32],"_authParams":[32],"_branding":[32],"_theme":[32],"formData":[32],"listFilter":[32]},null,{"screenId":[{"watchScreenId":0}],"screen":[{"watchScreen":0}],"branding":[{"watchBranding":0}],"theme":[{"watchTheme":0}],"authParams":[{"watchAuthParams":0}]}]]]], options);
|
|
21
21
|
});
|