@authhero/widget 0.32.42 → 0.34.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-5f7b7943.entry.js → p-5a319adc.entry.js} +1 -1
- package/dist/authhero-widget/p-f6babd26.entry.js +1 -0
- package/dist/cjs/authhero-node.cjs.entry.js +82 -5
- package/dist/cjs/authhero-widget.cjs.entry.js +133 -35
- package/dist/cjs/index.cjs.js +1 -1
- package/dist/collection/components/authhero-node/authhero-node.css +116 -1
- package/dist/collection/components/authhero-node/authhero-node.js +84 -2
- package/dist/collection/components/authhero-widget/authhero-widget.js +135 -37
- package/dist/components/authhero-node.js +1 -1
- package/dist/components/authhero-widget.js +1 -1
- package/dist/components/index.js +1 -1
- package/dist/components/p-BqdJX4cC.js +1 -0
- package/dist/esm/authhero-node.entry.js +83 -6
- package/dist/esm/authhero-widget.entry.js +133 -35
- package/dist/esm/index.js +1 -1
- package/dist/types/components/authhero-node/authhero-node.d.ts +12 -0
- package/dist/types/components/authhero-widget/authhero-widget.d.ts +26 -0
- package/dist/types/components.d.ts +0 -6
- package/dist/types/types/components.d.ts +1 -1
- package/hydrate/index.js +215 -40
- package/hydrate/index.mjs +215 -40
- package/package.json +2 -2
- package/dist/authhero-widget/p-1fc7fcdb.entry.js +0 -1
- package/dist/components/p-BzbxtmOP.js +0 -1
|
@@ -855,6 +855,94 @@ const AuthheroWidget = class {
|
|
|
855
855
|
}
|
|
856
856
|
});
|
|
857
857
|
}
|
|
858
|
+
/**
|
|
859
|
+
* Pending resolvers awaiting the next render, flushed by
|
|
860
|
+
* `componentDidRender`. Lets `swapScreen` wait until the new screen is
|
|
861
|
+
* actually in the DOM before measuring its height.
|
|
862
|
+
*/
|
|
863
|
+
pendingRenderResolvers = [];
|
|
864
|
+
componentDidRender() {
|
|
865
|
+
if (this.pendingRenderResolvers.length === 0)
|
|
866
|
+
return;
|
|
867
|
+
const resolvers = this.pendingRenderResolvers;
|
|
868
|
+
this.pendingRenderResolvers = [];
|
|
869
|
+
resolvers.forEach((resolve) => resolve());
|
|
870
|
+
}
|
|
871
|
+
/**
|
|
872
|
+
* Resolves after Stencil flushes the next render, so `swapScreen` waits for
|
|
873
|
+
* the new screen to be in the DOM before measuring its height.
|
|
874
|
+
*/
|
|
875
|
+
nextRender() {
|
|
876
|
+
return new Promise((resolve) => {
|
|
877
|
+
let settled = false;
|
|
878
|
+
const done = () => {
|
|
879
|
+
if (settled)
|
|
880
|
+
return;
|
|
881
|
+
settled = true;
|
|
882
|
+
resolve();
|
|
883
|
+
};
|
|
884
|
+
this.pendingRenderResolvers.push(done);
|
|
885
|
+
// Safety net: a screen swap always triggers a render here, but never
|
|
886
|
+
// hang the swap if one somehow doesn't fire — resolve after a couple of
|
|
887
|
+
// frames at the latest.
|
|
888
|
+
requestAnimationFrame(() => requestAnimationFrame(done));
|
|
889
|
+
});
|
|
890
|
+
}
|
|
891
|
+
/**
|
|
892
|
+
* Apply a screen swap, animating the widget card's height to the next
|
|
893
|
+
* screen's size (Stripe-style): lock the current height, swap the content,
|
|
894
|
+
* measure the new natural height, then animate between them. The content
|
|
895
|
+
* itself doesn't fade — the card just resizes.
|
|
896
|
+
*
|
|
897
|
+
* The card (.widget-container) is animated rather than the host because it
|
|
898
|
+
* carries the background, so its resize is visible; clipping its content
|
|
899
|
+
* (not the host) also keeps the card's drop-shadow intact.
|
|
900
|
+
*
|
|
901
|
+
* Degrades to an immediate swap when the Web Animations API is unavailable
|
|
902
|
+
* or the user prefers reduced motion.
|
|
903
|
+
*/
|
|
904
|
+
async swapScreen(apply) {
|
|
905
|
+
const card = this.el.shadowRoot?.querySelector(".widget-container");
|
|
906
|
+
const prefersReducedMotion = typeof window.matchMedia === "function" &&
|
|
907
|
+
window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
908
|
+
if (!card || typeof card.animate !== "function" || prefersReducedMotion) {
|
|
909
|
+
apply();
|
|
910
|
+
return;
|
|
911
|
+
}
|
|
912
|
+
// Lock the current height and clip, so swapping the content doesn't jump
|
|
913
|
+
// before the animation runs.
|
|
914
|
+
const startHeight = card.getBoundingClientRect().height;
|
|
915
|
+
card.style.height = `${startHeight}px`;
|
|
916
|
+
card.style.overflow = "hidden";
|
|
917
|
+
apply();
|
|
918
|
+
// Wait for the new screen to render before measuring its height.
|
|
919
|
+
await this.nextRender();
|
|
920
|
+
const cleanup = () => {
|
|
921
|
+
card.style.height = "";
|
|
922
|
+
card.style.overflow = "";
|
|
923
|
+
};
|
|
924
|
+
// Measure the new content's natural height without painting: toggle to
|
|
925
|
+
// auto, read, restore — all synchronous, so there's no visible jump.
|
|
926
|
+
card.style.height = "auto";
|
|
927
|
+
const endHeight = card.getBoundingClientRect().height;
|
|
928
|
+
card.style.height = `${startHeight}px`;
|
|
929
|
+
card.getBoundingClientRect(); // force reflow from startHeight
|
|
930
|
+
if (Math.abs(endHeight - startHeight) < 1) {
|
|
931
|
+
cleanup();
|
|
932
|
+
return;
|
|
933
|
+
}
|
|
934
|
+
const animation = card.animate([{ height: `${startHeight}px` }, { height: `${endHeight}px` }], { duration: 520, easing: "cubic-bezier(0.22, 1, 0.36, 1)" });
|
|
935
|
+
try {
|
|
936
|
+
await animation.finished;
|
|
937
|
+
}
|
|
938
|
+
catch {
|
|
939
|
+
// Animation cancelled (e.g. superseded by a newer swap); the final
|
|
940
|
+
// DOM state is already correct, so just fall through to cleanup.
|
|
941
|
+
}
|
|
942
|
+
finally {
|
|
943
|
+
cleanup();
|
|
944
|
+
}
|
|
945
|
+
}
|
|
858
946
|
/**
|
|
859
947
|
* Get the effective autoNavigate value (defaults to autoSubmit if not set)
|
|
860
948
|
*/
|
|
@@ -1157,45 +1245,55 @@ const AuthheroWidget = class {
|
|
|
1157
1245
|
}
|
|
1158
1246
|
else if (!response.ok && result.screen) {
|
|
1159
1247
|
// Handle validation errors (400 response) — preserve user input
|
|
1160
|
-
this.
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1248
|
+
await this.swapScreen(() => {
|
|
1249
|
+
// Clear loading first so the captured "after" snapshot doesn't
|
|
1250
|
+
// freeze a disabled button into the cross-fade.
|
|
1251
|
+
this.loading = false;
|
|
1252
|
+
this._screen = result.screen;
|
|
1253
|
+
this.initFormDataFromDefaults(result.screen);
|
|
1254
|
+
this.screenChange.emit(result.screen);
|
|
1255
|
+
this.updateDataScreenAttribute();
|
|
1256
|
+
this.focusFirstInput();
|
|
1257
|
+
});
|
|
1165
1258
|
}
|
|
1166
1259
|
else if (result.screen) {
|
|
1167
1260
|
// Next screen (success)
|
|
1168
|
-
this.
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
this.
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
}
|
|
1183
|
-
// Apply branding if included
|
|
1184
|
-
if (result.branding) {
|
|
1185
|
-
this._branding = result.branding;
|
|
1186
|
-
this.applyThemeStyles();
|
|
1187
|
-
}
|
|
1188
|
-
// Update state if returned
|
|
1189
|
-
if (result.state) {
|
|
1190
|
-
this.state = result.state;
|
|
1261
|
+
await this.swapScreen(() => {
|
|
1262
|
+
// Clear loading first so the captured "after" snapshot doesn't
|
|
1263
|
+
// freeze a disabled button into the cross-fade.
|
|
1264
|
+
this.loading = false;
|
|
1265
|
+
this._screen = result.screen;
|
|
1266
|
+
this.formData = {};
|
|
1267
|
+
this.initFormDataFromDefaults(result.screen);
|
|
1268
|
+
this.screenChange.emit(result.screen);
|
|
1269
|
+
this.updateDataScreenAttribute();
|
|
1270
|
+
// Update screenId if returned in response
|
|
1271
|
+
if (result.screenId) {
|
|
1272
|
+
this.screenId = result.screenId;
|
|
1273
|
+
}
|
|
1274
|
+
// Persist state (especially for session storage mode)
|
|
1191
1275
|
this.persistState();
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1276
|
+
// Update URL path if navigateUrl is provided (client-side navigation)
|
|
1277
|
+
if (result.navigateUrl && this.shouldAutoNavigate) {
|
|
1278
|
+
window.history.pushState({ screen: result.screenId, state: this.state }, "", result.navigateUrl);
|
|
1279
|
+
}
|
|
1280
|
+
// Apply branding if included
|
|
1281
|
+
if (result.branding) {
|
|
1282
|
+
this._branding = result.branding;
|
|
1283
|
+
this.applyThemeStyles();
|
|
1284
|
+
}
|
|
1285
|
+
// Update state if returned
|
|
1286
|
+
if (result.state) {
|
|
1287
|
+
this.state = result.state;
|
|
1288
|
+
this.persistState();
|
|
1289
|
+
}
|
|
1290
|
+
// Perform WebAuthn ceremony if present (structured data, not script)
|
|
1291
|
+
if (result.ceremony) {
|
|
1292
|
+
this.performWebAuthnCeremony(result.ceremony);
|
|
1293
|
+
}
|
|
1294
|
+
// Focus first input on new screen
|
|
1295
|
+
this.focusFirstInput();
|
|
1296
|
+
});
|
|
1199
1297
|
}
|
|
1200
1298
|
else if (result.complete) {
|
|
1201
1299
|
// Flow complete without redirect
|