@zitadel/components 0.1.0-alpha.14 → 0.1.0-alpha.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/atoms/index.d.mts +1 -1
- package/dist/atoms/index.mjs +1 -1
- package/dist/{atoms-BSwVl736.mjs → atoms-C-zXJjaz.mjs} +106 -10
- package/dist/{atoms-BSwVl736.mjs.map → atoms-C-zXJjaz.mjs.map} +1 -1
- package/dist/default-BoC3JEsO.mjs +6 -0
- package/dist/default-BoC3JEsO.mjs.map +1 -0
- package/dist/{index-EC-BnGsx.d.mts → index-BniwXaIC.d.mts} +3 -1
- package/dist/{index-EC-BnGsx.d.mts.map → index-BniwXaIC.d.mts.map} +1 -1
- package/dist/{index-Bypr00UG.d.mts → index-BwQLFs9R.d.mts} +362 -17
- package/dist/index-BwQLFs9R.d.mts.map +1 -0
- package/dist/{index-BP3l3mje.d.mts → index-D1eMaWbY.d.mts} +52 -5
- package/dist/index-D1eMaWbY.d.mts.map +1 -0
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +4 -4
- package/dist/manifests.mjs +1 -1
- package/dist/orchestrator/index.d.mts +2 -2
- package/dist/orchestrator/index.mjs +2 -2
- package/dist/{orchestrator-qkFBKFgJ.mjs → orchestrator-BN2nT9FZ.mjs} +317 -25
- package/dist/orchestrator-BN2nT9FZ.mjs.map +1 -0
- package/dist/standalone.mjs +423 -33
- package/dist/tokens/index.d.mts +1 -1
- package/dist/tokens/index.mjs +1 -1
- package/dist/{tokens-C0j4iCrs.mjs → tokens-CbH2s1jV.mjs} +6 -4
- package/dist/tokens-CbH2s1jV.mjs.map +1 -0
- package/package.json +5 -4
- package/dist/default-W5MwYLBc.mjs +0 -6
- package/dist/default-W5MwYLBc.mjs.map +0 -1
- package/dist/index-BP3l3mje.d.mts.map +0 -1
- package/dist/index-Bypr00UG.d.mts.map +0 -1
- package/dist/orchestrator-qkFBKFgJ.mjs.map +0 -1
- package/dist/tokens-C0j4iCrs.mjs.map +0 -1
package/dist/standalone.mjs
CHANGED
|
@@ -823,7 +823,8 @@ const tokens = {
|
|
|
823
823
|
"container": {
|
|
824
824
|
"authCard": "24rem",
|
|
825
825
|
"page": "80rem"
|
|
826
|
-
}
|
|
826
|
+
},
|
|
827
|
+
"layout": {}
|
|
827
828
|
};
|
|
828
829
|
const cssVars = {
|
|
829
830
|
"color": {
|
|
@@ -942,9 +943,10 @@ const cssVars = {
|
|
|
942
943
|
"container": {
|
|
943
944
|
"authCard": "var(--zl-container-auth-card)",
|
|
944
945
|
"page": "var(--zl-container-page)"
|
|
945
|
-
}
|
|
946
|
+
},
|
|
947
|
+
"layout": {}
|
|
946
948
|
};
|
|
947
|
-
const tokensCss = "/* AUTOGENERATED by packages/design-tokens/scripts/build.ts — do not edit by hand.\n Source: src/generated/figma.tokens.json + src/overrides.ts.\n Re-run: moon run design-tokens:generate */\n\n:root,\n[data-theme=\"dark\"] {\n --zl-color-surface-default-black: #0f0f11;\n --zl-color-surface-default-white: #f4f4f6;\n --zl-color-surface-default-primary-gray: #252528;\n --zl-color-surface-default-secondary-gray: #37373a;\n --zl-color-text-primary-white: #f4f4f6;\n --zl-color-text-secondary-gray: #bfbfcf;\n --zl-color-text-button-default: #0f0f11;\n --zl-color-text-button-invert: #f4f4f6;\n --zl-color-text-disabled: #686883;\n --zl-color-text-error: #ea4f70;\n --zl-color-text-success: #33a779;\n --zl-color-text-subtitle-pink: #f48aa0;\n --zl-color-text-subtitle-purple: #bba5e4;\n --zl-color-text-subtitle-gray: #bfbfcf;\n --zl-color-text-subtitle-orange: #f25543;\n --zl-color-icon-default-black: #0f0f11;\n --zl-color-icon-default-white: #f4f4f6;\n --zl-color-icon-default-gray: #bfbfcf;\n --zl-color-icon-default-pink: #f48aa0;\n --zl-color-icon-default-purple: #bba5e4;\n --zl-color-icon-default-orange: #f25543;\n --zl-color-icon-disabled: #686883;\n --zl-color-icon-error: #ea4f70;\n --zl-color-icon-success: #33a779;\n --zl-color-border-default-black: #252528;\n --zl-color-border-default-white: #f4f4f6;\n --zl-color-border-default-gray-100: #37373a;\n --zl-color-border-default-gray-200: #484a57;\n --zl-color-border-default-gray-300: #686883;\n --zl-color-border-default-gray-400: #82829c;\n --zl-color-border-error: #ea4f70;\n --zl-color-border-success: #33a779;\n --zl-color-gray-50: #0f0f11;\n --zl-color-gray-75: #252528;\n --zl-color-gray-100: #37373a;\n --zl-color-gray-200: #484a57;\n --zl-color-gray-300: #686883;\n --zl-color-gray-400: #82829c;\n --zl-color-gray-500: #9e9eb2;\n --zl-color-gray-600: #cfcfde;\n --zl-color-gray-700: #bfbfcf;\n --zl-color-gray-800: #e1e1e7;\n --zl-color-gray-900: #f4f4f6;\n --zl-spacing-01: 0.25rem;\n --zl-spacing-02: 0.5rem;\n --zl-spacing-03: 1rem;\n --zl-spacing-04: 1.5rem;\n --zl-spacing-05: 2rem;\n --zl-spacing-06: 1.5rem;\n --zl-spacing-07: 2.5rem;\n --zl-spacing-08: 3rem;\n --zl-spacing-09: 3.5rem;\n --zl-spacing-10: 4rem;\n --zl-spacing-11: 5rem;\n --zl-spacing-12: 5.5rem;\n --zl-spacing-13: 6rem;\n --zl-spacing-14: 6.5rem;\n --zl-spacing-15: 7rem;\n --zl-spacing-16: 7.5rem;\n --zl-radius-xs: 0.25rem;\n --zl-radius-s: 0.5rem;\n --zl-radius-m: 0.75rem;\n --zl-radius-l: 1rem;\n --zl-radius-xl: 1.5rem;\n --zl-font-family-sans: \"Arimo\", system-ui, -apple-system, \"Segoe UI\", Helvetica, Arial, sans-serif;\n --zl-font-family-heading: \"Arimo\", system-ui, -apple-system, \"Segoe UI\", Helvetica, Arial, sans-serif;\n --zl-font-family-mono: ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n --zl-duration-instant: 0ms;\n --zl-duration-fast: 120ms;\n --zl-duration-base: 200ms;\n --zl-duration-slow: 320ms;\n --zl-easing-standard: cubic-bezier(0.2, 0, 0, 1);\n --zl-easing-decelerate: cubic-bezier(0, 0, 0, 1);\n --zl-easing-accelerate: cubic-bezier(0.3, 0, 1, 1);\n --zl-focus-width: 2px;\n --zl-focus-offset: 2px;\n --zl-focus-color: #f4f4f6;\n --zl-breakpoint-xs: 26.5625rem;\n --zl-breakpoint-sm: 40rem;\n --zl-breakpoint-md: 48rem;\n --zl-breakpoint-lg: 64rem;\n --zl-breakpoint-xl: 80rem;\n --zl-breakpoint-2xl: 96rem;\n --zl-breakpoint-3xl: 120rem;\n --zl-breakpoint-4xl: 160rem;\n --zl-container-auth-card: 24rem;\n --zl-container-page: 80rem;\n}\n\n[data-theme=\"light\"] {\n
|
|
949
|
+
const tokensCss = "/* AUTOGENERATED by packages/design-tokens/scripts/build.ts — do not edit by hand.\n Source: src/generated/figma.tokens.json + src/overrides.ts.\n Re-run: moon run design-tokens:generate */\n\n:root,\n[data-theme=\"dark\"] {\n --zl-color-surface-default-black: #0f0f11;\n --zl-color-surface-default-white: #f4f4f6;\n --zl-color-surface-default-primary-gray: #252528;\n --zl-color-surface-default-secondary-gray: #37373a;\n --zl-color-text-primary-white: #f4f4f6;\n --zl-color-text-secondary-gray: #bfbfcf;\n --zl-color-text-button-default: #0f0f11;\n --zl-color-text-button-invert: #f4f4f6;\n --zl-color-text-disabled: #686883;\n --zl-color-text-error: #ea4f70;\n --zl-color-text-success: #33a779;\n --zl-color-text-subtitle-pink: #f48aa0;\n --zl-color-text-subtitle-purple: #bba5e4;\n --zl-color-text-subtitle-gray: #bfbfcf;\n --zl-color-text-subtitle-orange: #f25543;\n --zl-color-icon-default-black: #0f0f11;\n --zl-color-icon-default-white: #f4f4f6;\n --zl-color-icon-default-gray: #bfbfcf;\n --zl-color-icon-default-pink: #f48aa0;\n --zl-color-icon-default-purple: #bba5e4;\n --zl-color-icon-default-orange: #f25543;\n --zl-color-icon-disabled: #686883;\n --zl-color-icon-error: #ea4f70;\n --zl-color-icon-success: #33a779;\n --zl-color-border-default-black: #252528;\n --zl-color-border-default-white: #f4f4f6;\n --zl-color-border-default-gray-100: #37373a;\n --zl-color-border-default-gray-200: #484a57;\n --zl-color-border-default-gray-300: #686883;\n --zl-color-border-default-gray-400: #82829c;\n --zl-color-border-error: #ea4f70;\n --zl-color-border-success: #33a779;\n --zl-color-gray-50: #0f0f11;\n --zl-color-gray-75: #252528;\n --zl-color-gray-100: #37373a;\n --zl-color-gray-200: #484a57;\n --zl-color-gray-300: #686883;\n --zl-color-gray-400: #82829c;\n --zl-color-gray-500: #9e9eb2;\n --zl-color-gray-600: #cfcfde;\n --zl-color-gray-700: #bfbfcf;\n --zl-color-gray-800: #e1e1e7;\n --zl-color-gray-900: #f4f4f6;\n --zl-spacing-01: 0.25rem;\n --zl-spacing-02: 0.5rem;\n --zl-spacing-03: 1rem;\n --zl-spacing-04: 1.5rem;\n --zl-spacing-05: 2rem;\n --zl-spacing-06: 1.5rem;\n --zl-spacing-07: 2.5rem;\n --zl-spacing-08: 3rem;\n --zl-spacing-09: 3.5rem;\n --zl-spacing-10: 4rem;\n --zl-spacing-11: 5rem;\n --zl-spacing-12: 5.5rem;\n --zl-spacing-13: 6rem;\n --zl-spacing-14: 6.5rem;\n --zl-spacing-15: 7rem;\n --zl-spacing-16: 7.5rem;\n --zl-radius-xs: 0.25rem;\n --zl-radius-s: 0.5rem;\n --zl-radius-m: 0.75rem;\n --zl-radius-l: 1rem;\n --zl-radius-xl: 1.5rem;\n --zl-font-family-sans: \"Arimo\", system-ui, -apple-system, \"Segoe UI\", Helvetica, Arial, sans-serif;\n --zl-font-family-heading: \"Arimo\", system-ui, -apple-system, \"Segoe UI\", Helvetica, Arial, sans-serif;\n --zl-font-family-mono: ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n --zl-duration-instant: 0ms;\n --zl-duration-fast: 120ms;\n --zl-duration-base: 200ms;\n --zl-duration-slow: 320ms;\n --zl-easing-standard: cubic-bezier(0.2, 0, 0, 1);\n --zl-easing-decelerate: cubic-bezier(0, 0, 0, 1);\n --zl-easing-accelerate: cubic-bezier(0.3, 0, 1, 1);\n --zl-focus-width: 2px;\n --zl-focus-offset: 2px;\n --zl-focus-color: #f4f4f6;\n --zl-breakpoint-xs: 26.5625rem;\n --zl-breakpoint-sm: 40rem;\n --zl-breakpoint-md: 48rem;\n --zl-breakpoint-lg: 64rem;\n --zl-breakpoint-xl: 80rem;\n --zl-breakpoint-2xl: 96rem;\n --zl-breakpoint-3xl: 120rem;\n --zl-breakpoint-4xl: 160rem;\n --zl-container-auth-card: 24rem;\n --zl-container-page: 80rem;\n}\n\n[data-theme=\"light\"] {\n}\n";
|
|
948
950
|
//#endregion
|
|
949
951
|
//#region src/styles/tokens.ts
|
|
950
952
|
function wrap(node) {
|
|
@@ -2583,6 +2585,13 @@ function base64UrlToBuffer(base64url) {
|
|
|
2583
2585
|
}
|
|
2584
2586
|
//#endregion
|
|
2585
2587
|
//#region src/atoms/zl-passkey.ts
|
|
2588
|
+
/**
|
|
2589
|
+
* Slack subtracted from `options.timeout` when classifying a
|
|
2590
|
+
* `NotAllowedError` as a timeout: browsers clamp and fire the deadline
|
|
2591
|
+
* slightly early, so an exact comparison would label real timeouts as
|
|
2592
|
+
* user cancellations.
|
|
2593
|
+
*/
|
|
2594
|
+
const TIMEOUT_GRACE_MS = 1e3;
|
|
2586
2595
|
let ZlPasskey = class ZlPasskey extends i$2 {
|
|
2587
2596
|
#_ceremony_accessor_storage = "authenticate";
|
|
2588
2597
|
get ceremony() {
|
|
@@ -2619,7 +2628,37 @@ let ZlPasskey = class ZlPasskey extends i$2 {
|
|
|
2619
2628
|
set manual(value) {
|
|
2620
2629
|
this.#_manual_accessor_storage = value;
|
|
2621
2630
|
}
|
|
2631
|
+
#_pendingLabel_accessor_storage = "Waiting for your passkey…";
|
|
2632
|
+
get pendingLabel() {
|
|
2633
|
+
return this.#_pendingLabel_accessor_storage;
|
|
2634
|
+
}
|
|
2635
|
+
set pendingLabel(value) {
|
|
2636
|
+
this.#_pendingLabel_accessor_storage = value;
|
|
2637
|
+
}
|
|
2638
|
+
#_cancelLabel_accessor_storage = "Cancel";
|
|
2639
|
+
get cancelLabel() {
|
|
2640
|
+
return this.#_cancelLabel_accessor_storage;
|
|
2641
|
+
}
|
|
2642
|
+
set cancelLabel(value) {
|
|
2643
|
+
this.#_cancelLabel_accessor_storage = value;
|
|
2644
|
+
}
|
|
2645
|
+
#_silent_accessor_storage = false;
|
|
2646
|
+
get silent() {
|
|
2647
|
+
return this.#_silent_accessor_storage;
|
|
2648
|
+
}
|
|
2649
|
+
set silent(value) {
|
|
2650
|
+
this.#_silent_accessor_storage = value;
|
|
2651
|
+
}
|
|
2652
|
+
#_pending_accessor_storage = false;
|
|
2653
|
+
get pending() {
|
|
2654
|
+
return this.#_pending_accessor_storage;
|
|
2655
|
+
}
|
|
2656
|
+
set pending(value) {
|
|
2657
|
+
this.#_pending_accessor_storage = value;
|
|
2658
|
+
}
|
|
2622
2659
|
abortController = null;
|
|
2660
|
+
/** `Date.now()` at ceremony start, for timeout classification on reject. */
|
|
2661
|
+
startedAt = 0;
|
|
2623
2662
|
connectedCallback() {
|
|
2624
2663
|
super.connectedCallback();
|
|
2625
2664
|
if (!this.manual && this.options) this.startCeremony();
|
|
@@ -2630,11 +2669,14 @@ let ZlPasskey = class ZlPasskey extends i$2 {
|
|
|
2630
2669
|
}
|
|
2631
2670
|
/**
|
|
2632
2671
|
* Abort any in-flight WebAuthn ceremony. Called automatically when the
|
|
2633
|
-
* component disconnects (step change, page navigation)
|
|
2672
|
+
* component disconnects (step change, page navigation) and by the
|
|
2673
|
+
* pending UI's cancel button. Clears `pending` immediately — the
|
|
2674
|
+
* ceremony's own `finally` no longer owns it (its controller is gone).
|
|
2634
2675
|
*/
|
|
2635
2676
|
abort() {
|
|
2636
2677
|
this.abortController?.abort();
|
|
2637
2678
|
this.abortController = null;
|
|
2679
|
+
this.pending = false;
|
|
2638
2680
|
}
|
|
2639
2681
|
/**
|
|
2640
2682
|
* Trigger the WebAuthn ceremony. Resolves when the ceremony completes
|
|
@@ -2650,7 +2692,11 @@ let ZlPasskey = class ZlPasskey extends i$2 {
|
|
|
2650
2692
|
return;
|
|
2651
2693
|
}
|
|
2652
2694
|
this.abort();
|
|
2653
|
-
|
|
2695
|
+
const controller = new AbortController();
|
|
2696
|
+
this.abortController = controller;
|
|
2697
|
+
this.pending = true;
|
|
2698
|
+
this.startedAt = Date.now();
|
|
2699
|
+
this.emitStarted();
|
|
2654
2700
|
try {
|
|
2655
2701
|
const credential = this.ceremony === "register" ? await this.createCredential() : await this.getCredential();
|
|
2656
2702
|
if (!credential) {
|
|
@@ -2661,9 +2707,33 @@ let ZlPasskey = class ZlPasskey extends i$2 {
|
|
|
2661
2707
|
this.emitResult(proof);
|
|
2662
2708
|
} catch (error) {
|
|
2663
2709
|
const aborted = error instanceof DOMException && (error.name === "AbortError" || error.name === "NotAllowedError");
|
|
2664
|
-
|
|
2710
|
+
const timeoutMs = typeof this.options?.timeout === "number" ? this.options.timeout : null;
|
|
2711
|
+
const timedOut = error instanceof DOMException && error.name === "NotAllowedError" && timeoutMs !== null && Date.now() - this.startedAt >= timeoutMs - TIMEOUT_GRACE_MS;
|
|
2712
|
+
this.emitError(error instanceof Error ? error.message : "WebAuthn ceremony failed.", aborted, timedOut);
|
|
2713
|
+
} finally {
|
|
2714
|
+
if (this.abortController === controller) this.pending = false;
|
|
2665
2715
|
}
|
|
2666
2716
|
}
|
|
2717
|
+
handleCancelSubmit = (event) => {
|
|
2718
|
+
event.stopPropagation();
|
|
2719
|
+
this.abort();
|
|
2720
|
+
};
|
|
2721
|
+
render() {
|
|
2722
|
+
if (!this.pending || this.silent) return A;
|
|
2723
|
+
return b`
|
|
2724
|
+
<div class="zl-passkey-pending" data-testid="zitadel-passkey-pending">
|
|
2725
|
+
<zl-alert severity="info">${this.pendingLabel}</zl-alert>
|
|
2726
|
+
<zl-button
|
|
2727
|
+
hierarchy="secondary"
|
|
2728
|
+
type="button"
|
|
2729
|
+
block
|
|
2730
|
+
data-testid="zitadel-passkey-cancel"
|
|
2731
|
+
label=${this.cancelLabel}
|
|
2732
|
+
@zl-submit=${this.handleCancelSubmit}
|
|
2733
|
+
></zl-button>
|
|
2734
|
+
</div>
|
|
2735
|
+
`;
|
|
2736
|
+
}
|
|
2667
2737
|
/**
|
|
2668
2738
|
* `navigator.credentials.get()` — authentication ceremony.
|
|
2669
2739
|
*/
|
|
@@ -2765,11 +2835,12 @@ let ZlPasskey = class ZlPasskey extends i$2 {
|
|
|
2765
2835
|
detail
|
|
2766
2836
|
}));
|
|
2767
2837
|
}
|
|
2768
|
-
emitError(message, aborted) {
|
|
2838
|
+
emitError(message, aborted, timedOut = false) {
|
|
2769
2839
|
const detail = {
|
|
2770
2840
|
challenge_id: this.challengeId,
|
|
2771
2841
|
error: message,
|
|
2772
|
-
aborted
|
|
2842
|
+
aborted,
|
|
2843
|
+
timed_out: timedOut
|
|
2773
2844
|
};
|
|
2774
2845
|
this.dispatchEvent(new CustomEvent("zl-passkey-error", {
|
|
2775
2846
|
bubbles: true,
|
|
@@ -2777,7 +2848,23 @@ let ZlPasskey = class ZlPasskey extends i$2 {
|
|
|
2777
2848
|
detail
|
|
2778
2849
|
}));
|
|
2779
2850
|
}
|
|
2780
|
-
|
|
2851
|
+
emitStarted() {
|
|
2852
|
+
const detail = {
|
|
2853
|
+
challenge_id: this.challengeId,
|
|
2854
|
+
method: this.method
|
|
2855
|
+
};
|
|
2856
|
+
this.dispatchEvent(new CustomEvent("zl-passkey-started", {
|
|
2857
|
+
bubbles: true,
|
|
2858
|
+
composed: true,
|
|
2859
|
+
detail
|
|
2860
|
+
}));
|
|
2861
|
+
}
|
|
2862
|
+
/**
|
|
2863
|
+
* Light DOM on purpose: the pending UI must land inside the
|
|
2864
|
+
* orchestrator's shadow root (where the step's adopted styles apply)
|
|
2865
|
+
* without altering the `unsafeHTML` step markup — runtime children don't
|
|
2866
|
+
* participate in its string comparison, so the ceremony never restarts.
|
|
2867
|
+
*/
|
|
2781
2868
|
createRenderRoot() {
|
|
2782
2869
|
return this;
|
|
2783
2870
|
}
|
|
@@ -2802,6 +2889,10 @@ __decorate([n$1({
|
|
|
2802
2889
|
})], ZlPasskey.prototype, "options", null);
|
|
2803
2890
|
__decorate([n$1({ type: String })], ZlPasskey.prototype, "method", null);
|
|
2804
2891
|
__decorate([n$1({ type: Boolean })], ZlPasskey.prototype, "manual", null);
|
|
2892
|
+
__decorate([n$1({ attribute: "pending-label" })], ZlPasskey.prototype, "pendingLabel", null);
|
|
2893
|
+
__decorate([n$1({ attribute: "cancel-label" })], ZlPasskey.prototype, "cancelLabel", null);
|
|
2894
|
+
__decorate([n$1({ type: Boolean })], ZlPasskey.prototype, "silent", null);
|
|
2895
|
+
__decorate([r$1()], ZlPasskey.prototype, "pending", null);
|
|
2805
2896
|
ZlPasskey = __decorate([t$4("zl-passkey")], ZlPasskey);
|
|
2806
2897
|
const zlPasskeyManifest = {
|
|
2807
2898
|
tag: "zl-passkey",
|
|
@@ -2811,11 +2902,18 @@ const zlPasskeyManifest = {
|
|
|
2811
2902
|
"method",
|
|
2812
2903
|
"challenge-id",
|
|
2813
2904
|
"options",
|
|
2814
|
-
"manual"
|
|
2905
|
+
"manual",
|
|
2906
|
+
"pending-label",
|
|
2907
|
+
"cancel-label",
|
|
2908
|
+
"silent"
|
|
2815
2909
|
],
|
|
2816
2910
|
parts: [],
|
|
2817
2911
|
slots: [],
|
|
2818
|
-
events: [
|
|
2912
|
+
events: [
|
|
2913
|
+
"zl-passkey-result",
|
|
2914
|
+
"zl-passkey-error",
|
|
2915
|
+
"zl-passkey-started"
|
|
2916
|
+
]
|
|
2819
2917
|
};
|
|
2820
2918
|
//#endregion
|
|
2821
2919
|
//#region ../shared-component-styles/src/lit/pill-host.css?inline
|
|
@@ -3365,6 +3463,37 @@ function safeJsonParse(text) {
|
|
|
3365
3463
|
return { raw: text };
|
|
3366
3464
|
}
|
|
3367
3465
|
}
|
|
3466
|
+
/**
|
|
3467
|
+
* Extracts the server's `{code, message, details}` envelope from an
|
|
3468
|
+
* {@link ApiError} into a display string. Falls back to the fetch layer's
|
|
3469
|
+
* `"METHOD url returned N"` when the body isn't shaped like an envelope, so
|
|
3470
|
+
* transport-level failures (HTML from a proxy, empty 5xx) still say
|
|
3471
|
+
* something.
|
|
3472
|
+
*/
|
|
3473
|
+
function apiErrorMessage(error) {
|
|
3474
|
+
const body = error.body;
|
|
3475
|
+
if (!isRecord(body)) return error.message;
|
|
3476
|
+
const serverMessage = typeof body.message === "string" ? body.message : void 0;
|
|
3477
|
+
const detail = pickDetailString(body.details);
|
|
3478
|
+
if (!serverMessage) return error.message;
|
|
3479
|
+
return detail ? `${serverMessage}: ${detail}` : serverMessage;
|
|
3480
|
+
}
|
|
3481
|
+
/**
|
|
3482
|
+
* Reads the innermost human-readable string out of the spec's error
|
|
3483
|
+
* `details` field. Handles both `details: "..."` and the nested
|
|
3484
|
+
* `details: { details: "..." }` shape the platform emits for validation
|
|
3485
|
+
* failures.
|
|
3486
|
+
*/
|
|
3487
|
+
function pickDetailString(details) {
|
|
3488
|
+
if (typeof details === "string") return details;
|
|
3489
|
+
if (isRecord(details)) {
|
|
3490
|
+
if (typeof details.details === "string") return details.details;
|
|
3491
|
+
if (typeof details.message === "string") return details.message;
|
|
3492
|
+
}
|
|
3493
|
+
}
|
|
3494
|
+
function isRecord(value) {
|
|
3495
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3496
|
+
}
|
|
3368
3497
|
//#endregion
|
|
3369
3498
|
//#region src/orchestrator/api-client.ts
|
|
3370
3499
|
const apiRequestInit = { credentials: "include" };
|
|
@@ -3401,7 +3530,7 @@ async function exchangeSession(api, body, params) {
|
|
|
3401
3530
|
* orchestrator's signed-in surfaces to render the user's identity.
|
|
3402
3531
|
*/
|
|
3403
3532
|
async function getSession$1(api) {
|
|
3404
|
-
return
|
|
3533
|
+
return api.getMySession(apiRequestInit);
|
|
3405
3534
|
}
|
|
3406
3535
|
/**
|
|
3407
3536
|
* Revokes the current session (`DELETE /sessions/me`) with credentials. The
|
|
@@ -3505,7 +3634,9 @@ var zitadelNextGen_exports = /* @__PURE__ */ __exportAll({
|
|
|
3505
3634
|
getMySession: () => getMySession,
|
|
3506
3635
|
getMyUser: () => getMyUser,
|
|
3507
3636
|
getOpenIDConfiguration: () => getOpenIDConfiguration,
|
|
3637
|
+
getPatchProjectUrl: () => getPatchProjectUrl,
|
|
3508
3638
|
getProject: () => getProject,
|
|
3639
|
+
getQueryProjectsUrl: () => getQueryProjectsUrl,
|
|
3509
3640
|
getReady: () => getReady,
|
|
3510
3641
|
getRevokeMySessionUrl: () => getRevokeMySessionUrl,
|
|
3511
3642
|
getRevokeSessionUrl: () => getRevokeSessionUrl,
|
|
@@ -3527,6 +3658,8 @@ var zitadelNextGen_exports = /* @__PURE__ */ __exportAll({
|
|
|
3527
3658
|
listSchemas: () => listSchemas,
|
|
3528
3659
|
listSessions: () => listSessions,
|
|
3529
3660
|
listUsers: () => listUsers,
|
|
3661
|
+
patchProject: () => patchProject,
|
|
3662
|
+
queryProjects: () => queryProjects,
|
|
3530
3663
|
revokeMySession: () => revokeMySession,
|
|
3531
3664
|
revokeSession: () => revokeSession,
|
|
3532
3665
|
revokeToken: () => revokeToken,
|
|
@@ -4065,6 +4198,23 @@ const createProject = async (createProjectBody, options) => {
|
|
|
4065
4198
|
body: JSON.stringify(createProjectBody)
|
|
4066
4199
|
});
|
|
4067
4200
|
};
|
|
4201
|
+
const getQueryProjectsUrl = () => {
|
|
4202
|
+
return `${getProxyPath()}/projects/query`;
|
|
4203
|
+
};
|
|
4204
|
+
/**
|
|
4205
|
+
* @summary Query projects
|
|
4206
|
+
*/
|
|
4207
|
+
const queryProjects = async (queryProjectsBody, options) => {
|
|
4208
|
+
return customFetch(getQueryProjectsUrl(), {
|
|
4209
|
+
...options,
|
|
4210
|
+
method: "POST",
|
|
4211
|
+
headers: {
|
|
4212
|
+
"Content-Type": "application/json",
|
|
4213
|
+
...options?.headers
|
|
4214
|
+
},
|
|
4215
|
+
body: JSON.stringify(queryProjectsBody)
|
|
4216
|
+
});
|
|
4217
|
+
};
|
|
4068
4218
|
const getGetProjectUrl = (projectId) => {
|
|
4069
4219
|
return `${getProxyPath()}/projects/${projectId}`;
|
|
4070
4220
|
};
|
|
@@ -4079,6 +4229,25 @@ const getProject = async (projectId, options) => {
|
|
|
4079
4229
|
method: "GET"
|
|
4080
4230
|
});
|
|
4081
4231
|
};
|
|
4232
|
+
const getPatchProjectUrl = (projectId) => {
|
|
4233
|
+
return `${getProxyPath()}/projects/${projectId}`;
|
|
4234
|
+
};
|
|
4235
|
+
/**
|
|
4236
|
+
* Updates the state of a project.
|
|
4237
|
+
|
|
4238
|
+
* @summary Update project
|
|
4239
|
+
*/
|
|
4240
|
+
const patchProject = async (projectId, patchProjectBody, options) => {
|
|
4241
|
+
return customFetch(getPatchProjectUrl(projectId), {
|
|
4242
|
+
...options,
|
|
4243
|
+
method: "PATCH",
|
|
4244
|
+
headers: {
|
|
4245
|
+
"Content-Type": "application/json",
|
|
4246
|
+
...options?.headers
|
|
4247
|
+
},
|
|
4248
|
+
body: JSON.stringify(patchProjectBody)
|
|
4249
|
+
});
|
|
4250
|
+
};
|
|
4082
4251
|
const getCreateSessionUrl = () => {
|
|
4083
4252
|
return `${getProxyPath()}/sessions`;
|
|
4084
4253
|
};
|
|
@@ -9506,7 +9675,7 @@ function lookup(locale, key) {
|
|
|
9506
9675
|
}
|
|
9507
9676
|
//#endregion
|
|
9508
9677
|
//#region src/orchestrator/templates/default.liquid
|
|
9509
|
-
var default_default = "<zl-page-shell data-zl-template-root>\n {% if branding.logo_url %}\n <img slot=\"header\" class=\"zl-card-logo\" src=\"{{ branding.logo_url }}\" alt=\"\" />\n {% endif %}\n <zl-card>\n <h1 slot=\"header\" class=\"zl-card-title\">{{ step.texts.title_key | t: identity.display_name }}</h1>\n {% if step.texts.description_key %}\n {% assign card_subtitle = step.texts.description_key | t: identity.display_name %}\n {% if card_subtitle != \"\" %}\n <p slot=\"header\" class=\"zl-card-subtitle\">{{ card_subtitle }}</p>\n {% endif %}\n {% endif %}\n\n {% if errors and errors.size > 0 %}\n {% for err in errors %}\n {% if err | formLevelError %}\n {% assign alert_heading = err.text_key | alertHeading %}\n {% assign alert_body = err.text_key | alertBody %}\n <zl-alert severity=\"error\"{% if alert_heading != \"\" %} heading=\"{{ alert_heading | t }}\"{% endif %}>\n {% if alert_body != \"\" %}{{ alert_body | t }}{% elsif err.text_key %}{{ err.text_key | t }}{% else %}{{ err.message }}{% endif %}\n </zl-alert>\n {% endif %}\n {% endfor %}\n {% endif %}\n\n {% for f in fields %}\n {% assign field_placeholder = f.text_key | fieldPlaceholder %}\n {% assign field_help = f.text_key | fieldHelp %}\n {% assign field_err = f.name | fieldError: errors %}\n {% case f.type %}\n {% when 'checkbox' %}\n <zl-checkbox\n name=\"{{ f.name }}\"\n data-testid=\"zitadel-field-{{ f.name }}\"\n label=\"{{ f.text_key | t }}\"\n value=\"true\"\n {% if f.value %}checked{% endif %}\n {% if f.required %}required{% endif %}\n ></zl-checkbox>\n {% when 'select' %}\n <zl-select\n name=\"{{ f.name }}\"\n data-testid=\"zitadel-field-{{ f.name }}\"\n label=\"{{ f.text_key | t }}\"\n value=\"{{ f.value }}\"\n options='{{ f.validation.enum | selectOptions | json }}'\n {% if f.required %}required{% endif %}\n {% if field_placeholder != \"\" %}placeholder=\"{{ field_placeholder }}\"{% endif %}\n ></zl-select>\n {% else %}\n {% assign autocomplete_val = '' %}\n {% if f.name == 'email' %}\n {% assign autocomplete_val = 'email' %}\n {% elsif f.type == 'password' and step.name contains 'register' %}\n {% assign autocomplete_val = 'new-password' %}\n {% elsif f.type == 'password' %}\n {% assign autocomplete_val = 'current-password' %}\n {% endif %}\n <zl-field\n name=\"{{ f.name }}\"\n data-testid=\"zitadel-field-{{ f.name }}\"\n label=\"{{ f.text_key | t }}\"\n type=\"{{ f.type }}\"\n value=\"{{ f.value }}\"\n {% if autocomplete_val != '' %}autocomplete=\"{{ autocomplete_val }}\"{% endif %}\n {% if f.required %}required{% endif %}\n {% if field_placeholder != \"\" %}placeholder=\"{{ field_placeholder }}\"{% endif %}\n {% if field_err != \"\" %}invalid error=\"{{ field_err }}\"{% endif %}\n >\n {% if field_help != \"\" %}\n <span slot=\"help\">{{ field_help }}</span>\n {% endif %}\n </zl-field>\n {% endcase %}\n {% endfor %}\n\n {% assign recover = actions | where: \"name\", \"recover\" | first %}\n {% if recover %}\n <p class=\"zl-card-forgot\">\n <a href=\"#\" class=\"zl-card-forgot__link\" data-action=\"recover\">{{ recover.text_key | t }}</a>\n </p>\n {% endif %}\n\n {% for a in actions %}\n {% if a.primary %}\n <zl-button\n hierarchy=\"primary\"\n size=\"medium\"\n type=\"submit\"\n block\n action=\"{{ a.name }}\"\n data-testid=\"zitadel-action-{{ a.name }}\"\n label=\"{{ a.text_key | t }}\"\n {% if loading %}loading{% endif %}\n ></zl-button>\n {% endif %}\n {% endfor %}\n\n {% for a in actions %}\n {% unless a.primary or a.name == 'passkey' or a.name == 'register' or a.name == 'sign_in' or a.name == 'recover' %}\n <zl-button\n hierarchy=\"secondary\"\n size=\"medium\"\n type=\"button\"\n block\n action=\"{{ a.name }}\"\n data-testid=\"zitadel-action-{{ a.name }}\"\n label=\"{{ a.text_key | t }}\"\n ></zl-button>\n {% endunless %}\n {% endfor %}\n\n {% assign passkey = actions | where: \"name\", \"passkey\" | first %}\n {% if passkey %}\n <zl-button\n
|
|
9678
|
+
var default_default = "<zl-page-shell data-zl-template-root>\n {% if branding.logo_url %}\n <img slot=\"header\" class=\"zl-card-logo\" src=\"{{ branding.logo_url }}\" alt=\"\" />\n {% endif %}\n <zl-card>\n <h1 slot=\"header\" class=\"zl-card-title\">{{ step.texts.title_key | t: identity.display_name }}</h1>\n {% if step.texts.description_key %}\n {% assign card_subtitle = step.texts.description_key | t: identity.display_name %}\n {% if card_subtitle != \"\" %}\n <p slot=\"header\" class=\"zl-card-subtitle\">{{ card_subtitle }}</p>\n {% endif %}\n {% endif %}\n\n {% if errors and errors.size > 0 %}\n {% for err in errors %}\n {% if err | formLevelError %}\n {% assign alert_heading = err.text_key | alertHeading %}\n {% assign alert_body = err.text_key | alertBody %}\n <zl-alert severity=\"error\" dismissible data-zl-step-error{% if alert_heading != \"\" %} heading=\"{{ alert_heading | t }}\"{% endif %}>\n {% if alert_body != \"\" %}{{ alert_body | t }}{% elsif err.text_key %}{{ err.text_key | t }}{% else %}{{ err.message }}{% endif %}\n </zl-alert>\n {% endif %}\n {% endfor %}\n {% endif %}\n\n {% for f in fields %}\n {% assign field_placeholder = f.text_key | fieldPlaceholder %}\n {% assign field_help = f.text_key | fieldHelp %}\n {% assign field_err = f.name | fieldError: errors %}\n {% case f.type %}\n {% when 'checkbox' %}\n <zl-checkbox\n name=\"{{ f.name }}\"\n data-testid=\"zitadel-field-{{ f.name }}\"\n label=\"{{ f.text_key | t }}\"\n value=\"true\"\n {% if f.value %}checked{% endif %}\n {% if f.required %}required{% endif %}\n ></zl-checkbox>\n {% when 'select' %}\n <zl-select\n name=\"{{ f.name }}\"\n data-testid=\"zitadel-field-{{ f.name }}\"\n label=\"{{ f.text_key | t }}\"\n value=\"{{ f.value }}\"\n options='{{ f.validation.enum | selectOptions | json }}'\n {% if f.required %}required{% endif %}\n {% if field_placeholder != \"\" %}placeholder=\"{{ field_placeholder }}\"{% endif %}\n ></zl-select>\n {% else %}\n {% assign autocomplete_val = '' %}\n {% if f.name == 'email' %}\n {% assign autocomplete_val = 'email' %}\n {% elsif f.type == 'password' and step.name contains 'register' %}\n {% assign autocomplete_val = 'new-password' %}\n {% elsif f.type == 'password' %}\n {% assign autocomplete_val = 'current-password' %}\n {% endif %}\n <zl-field\n name=\"{{ f.name }}\"\n data-testid=\"zitadel-field-{{ f.name }}\"\n label=\"{{ f.text_key | t }}\"\n type=\"{{ f.type }}\"\n value=\"{{ f.value }}\"\n {% if autocomplete_val != '' %}autocomplete=\"{{ autocomplete_val }}\"{% endif %}\n {% if f.required %}required{% endif %}\n {% if field_placeholder != \"\" %}placeholder=\"{{ field_placeholder }}\"{% endif %}\n {% if field_err != \"\" %}invalid error=\"{{ field_err }}\"{% endif %}\n >\n {% if field_help != \"\" %}\n <span slot=\"help\">{{ field_help }}</span>\n {% endif %}\n </zl-field>\n {% endcase %}\n {% endfor %}\n\n {% assign recover = actions | where: \"name\", \"recover\" | first %}\n {% if recover %}\n <p class=\"zl-card-forgot\">\n <a href=\"#\" class=\"zl-card-forgot__link\" data-action=\"recover\">{{ recover.text_key | t }}</a>\n </p>\n {% endif %}\n\n {% for a in actions %}\n {% if a.primary %}\n <zl-button\n hierarchy=\"primary\"\n size=\"medium\"\n type=\"submit\"\n block\n action=\"{{ a.name }}\"\n data-testid=\"zitadel-action-{{ a.name }}\"\n label=\"{{ a.text_key | t }}\"\n {% if loading %}loading{% endif %}\n ></zl-button>\n {% endif %}\n {% endfor %}\n\n {% for a in actions %}\n {% unless a.primary or a.name == 'passkey' or a.name == 'register' or a.name == 'sign_in' or a.name == 'recover' %}\n <zl-button\n hierarchy=\"secondary\"\n size=\"medium\"\n type=\"button\"\n block\n action=\"{{ a.name }}\"\n data-testid=\"zitadel-action-{{ a.name }}\"\n label=\"{{ a.text_key | t }}\"\n ></zl-button>\n {% endunless %}\n {% endfor %}\n\n {% assign passkey = actions | where: \"name\", \"passkey\" | first %}\n {% if passkey %}\n {% unless passkey.primary %}\n <zl-button\n hierarchy=\"secondary\"\n size=\"medium\"\n block\n action=\"passkey\"\n data-testid=\"zitadel-action-passkey\"\n label=\"{{ passkey.text_key | t }}\"\n ></zl-button>\n {% endunless %}\n {% endif %}\n\n\n {% assign register = actions | where: \"name\", \"register\" | first %}\n {% if register %}\n <p class=\"zl-card-nav\">\n {{ 'identifier.action.register.lead' | t }}<a href=\"#\" class=\"zl-card-nav__link\" data-action=\"register\" data-testid=\"zitadel-action-register-link\">{{ 'identifier.action.register.link' | t }}</a>\n </p>\n {% endif %}\n\n {% assign sign_in = actions | where: \"name\", \"sign_in\" | first %}\n {% if sign_in %}\n <p class=\"zl-card-nav\">\n {{ 'register.action.sign_in.lead' | t }}<a href=\"#\" class=\"zl-card-nav__link\" data-action=\"sign_in\" data-testid=\"zitadel-action-sign_in-link\">{{ 'register.action.sign_in.link' | t }}</a>\n </p>\n {% endif %}\n\n {% if challenge %}\n {% if challenge.method == \"passkey\" or challenge.method == \"passkey_register\" %}\n {% assign ceremony = \"authenticate\" %}\n {% assign submit_method = challenge.method %}\n {% if challenge.method == \"passkey_register\" or challenge.options.user %}\n {% assign ceremony = \"register\" %}\n {% assign submit_method = \"passkey_register\" %}\n {% endif %}\n <zl-passkey\n ceremony=\"{{ ceremony }}\"\n method=\"{{ submit_method }}\"\n challenge-id=\"{{ challenge.challenge_id }}\"\n options='{{ challenge.options | json }}'\n pending-label=\"{{ 'passkey.pending.status' | t }}\"\n cancel-label=\"{{ 'action.cancel' | t }}\"\n ></zl-passkey>\n {% endif %}\n {% endif %}\n\n {% mandatory_gates %}\n </zl-card>\n</zl-page-shell>\n";
|
|
9510
9679
|
//#endregion
|
|
9511
9680
|
//#region src/orchestrator/liquid.ts
|
|
9512
9681
|
/**
|
|
@@ -9525,6 +9694,21 @@ var default_default = "<zl-page-shell data-zl-template-root>\n {% if branding.l
|
|
|
9525
9694
|
* - Partials are loaded from an in-memory map; no filesystem access.
|
|
9526
9695
|
*/
|
|
9527
9696
|
const TEMPLATE_NAMES$1 = { default: "default" };
|
|
9697
|
+
/**
|
|
9698
|
+
* Maps `error.*` text keys to a field name (Figma inline-error
|
|
9699
|
+
* annotations). Shared by the template filters (`fieldError` routes these
|
|
9700
|
+
* inline, `formLevelError` suppresses their banner) and by
|
|
9701
|
+
* {@link localiseFlowErrorKeys}, which must downgrade them to a banner
|
|
9702
|
+
* message when the step doesn't render the mapped field.
|
|
9703
|
+
*/
|
|
9704
|
+
const fieldErrorKeys = {
|
|
9705
|
+
"error.email_required": "email",
|
|
9706
|
+
"error.email_invalid": "email",
|
|
9707
|
+
"error.email_exists": "email",
|
|
9708
|
+
"error.password_required": "password",
|
|
9709
|
+
"error.password_incorrect": "password",
|
|
9710
|
+
"error.invalid_credentials": "password"
|
|
9711
|
+
};
|
|
9528
9712
|
function createLiquidEngine(options) {
|
|
9529
9713
|
const engine = new Liquid({
|
|
9530
9714
|
templates: {
|
|
@@ -9541,7 +9725,7 @@ function createLiquidEngine(options) {
|
|
|
9541
9725
|
engine.registerFilter("raw", (value) => stringify(value));
|
|
9542
9726
|
engine.registerFilter("t", function tFilter(key, ...args) {
|
|
9543
9727
|
const lookupKey = stringify(key);
|
|
9544
|
-
return interpolate(options.locale[lookupKey] ?? lookupKey, args.map(stringify));
|
|
9728
|
+
return interpolate(options.locale[lookupKey] ?? injectedKeyFallback(options.locale, lookupKey) ?? lookupKey, args.map(stringify));
|
|
9545
9729
|
});
|
|
9546
9730
|
/** Resolves `{text_key}.placeholder` — empty when undefined (not the raw key). */
|
|
9547
9731
|
engine.registerFilter("fieldPlaceholder", (textKey) => {
|
|
@@ -9569,15 +9753,6 @@ function createLiquidEngine(options) {
|
|
|
9569
9753
|
};
|
|
9570
9754
|
});
|
|
9571
9755
|
});
|
|
9572
|
-
/** Maps `error.*` text keys to a field name (Figma inline-error annotations). */
|
|
9573
|
-
const fieldErrorKeys = {
|
|
9574
|
-
"error.email_required": "email",
|
|
9575
|
-
"error.email_invalid": "email",
|
|
9576
|
-
"error.email_exists": "email",
|
|
9577
|
-
"error.password_required": "password",
|
|
9578
|
-
"error.password_incorrect": "password",
|
|
9579
|
-
"error.invalid_credentials": "password"
|
|
9580
|
-
};
|
|
9581
9756
|
/** Resolves `{text_key}.title` for form-level `<zl-alert heading>`. */
|
|
9582
9757
|
engine.registerFilter("alertHeading", (textKey) => {
|
|
9583
9758
|
const lookupKey = `${stringify(textKey)}.title`;
|
|
@@ -9611,6 +9786,105 @@ function createLiquidEngine(options) {
|
|
|
9611
9786
|
});
|
|
9612
9787
|
return engine;
|
|
9613
9788
|
}
|
|
9789
|
+
/**
|
|
9790
|
+
* Fallbacks for text keys the flow engine derives from tenant-chosen step
|
|
9791
|
+
* names (`<step>.action.back` for the injected back action — see
|
|
9792
|
+
* `internal/domain/flow_state_machine.go` `buildStep`). Step names are open,
|
|
9793
|
+
* so no dictionary can enumerate them; a missing step-specific key falls back
|
|
9794
|
+
* to its generic entry instead of leaking the raw key into the UI.
|
|
9795
|
+
*/
|
|
9796
|
+
const INJECTED_KEY_FALLBACKS = [{
|
|
9797
|
+
suffix: ".action.back",
|
|
9798
|
+
fallback: "action.back"
|
|
9799
|
+
}];
|
|
9800
|
+
function injectedKeyFallback(locale, key) {
|
|
9801
|
+
for (const { suffix, fallback } of INJECTED_KEY_FALLBACKS) if (key.endsWith(suffix)) return locale[fallback];
|
|
9802
|
+
}
|
|
9803
|
+
/**
|
|
9804
|
+
* Rule-suffix fallbacks for the server's field-validation keys
|
|
9805
|
+
* (`error.<field>_<rule>` — see `FlowFieldValidationError.TextKey` in
|
|
9806
|
+
* `internal/domain/flow_field_resolver.go`). Field names come from the
|
|
9807
|
+
* tenant's user schema, so no catalog can enumerate the specific keys;
|
|
9808
|
+
* a miss resolves to the rule's generic entry, interpolated with the
|
|
9809
|
+
* field's label (`{0}`). The server spells the format rule `_invalid`
|
|
9810
|
+
* (the catalog's existing convention, e.g. `error.email_invalid`), so
|
|
9811
|
+
* that suffix takes the format wording; `_unknown_field` (a submitted
|
|
9812
|
+
* name that is not a step field) takes the catch-all.
|
|
9813
|
+
*/
|
|
9814
|
+
const FLOW_ERROR_RULE_FALLBACKS = [
|
|
9815
|
+
{
|
|
9816
|
+
suffix: "_required",
|
|
9817
|
+
generic: "error.field_required"
|
|
9818
|
+
},
|
|
9819
|
+
{
|
|
9820
|
+
suffix: "_min_length",
|
|
9821
|
+
generic: "error.field_min_length"
|
|
9822
|
+
},
|
|
9823
|
+
{
|
|
9824
|
+
suffix: "_max_length",
|
|
9825
|
+
generic: "error.field_max_length"
|
|
9826
|
+
},
|
|
9827
|
+
{
|
|
9828
|
+
suffix: "_format",
|
|
9829
|
+
generic: "error.field_format"
|
|
9830
|
+
},
|
|
9831
|
+
{
|
|
9832
|
+
suffix: "_invalid",
|
|
9833
|
+
generic: "error.field_format"
|
|
9834
|
+
},
|
|
9835
|
+
{
|
|
9836
|
+
suffix: "_unknown_field",
|
|
9837
|
+
generic: "error.field_invalid"
|
|
9838
|
+
}
|
|
9839
|
+
];
|
|
9840
|
+
const FLOW_ERROR_CATCH_ALL_KEY = "error.field_invalid";
|
|
9841
|
+
/**
|
|
9842
|
+
* Localises a `step.error` payload of field-validation text keys.
|
|
9843
|
+
* Returns `null` unless EVERY `"; "`-joined segment is an `error.*` key
|
|
9844
|
+
* — the caller keeps other payloads (outcome names, `auth_attempt.*`
|
|
9845
|
+
* diagnostics) verbatim.
|
|
9846
|
+
*
|
|
9847
|
+
* Keys the locale knows pass through as `text_key` entries: the template
|
|
9848
|
+
* localises them via `| t`, and `fieldErrorKeys` routes the known ones
|
|
9849
|
+
* inline to their field. Unknown keys with a recognised rule suffix are
|
|
9850
|
+
* pre-localised here from their generic {@link FLOW_ERROR_RULE_FALLBACKS}
|
|
9851
|
+
* entry; unknown keys without one pass through as `text_key` (matching
|
|
9852
|
+
* `| t`'s behaviour for non-validation keys such as
|
|
9853
|
+
* `error.sign_in_server`, which localises via `.title`/`.body`).
|
|
9854
|
+
*/
|
|
9855
|
+
function localiseFlowErrorKeys(raw, ctx) {
|
|
9856
|
+
const segments = raw.split("; ");
|
|
9857
|
+
if (!segments.every((segment) => segment.startsWith("error."))) return null;
|
|
9858
|
+
return segments.map((key) => localiseFlowErrorKey(key, ctx));
|
|
9859
|
+
}
|
|
9860
|
+
function localiseFlowErrorKey(key, ctx) {
|
|
9861
|
+
const inlineField = fieldErrorKeys[key];
|
|
9862
|
+
const orphanedInline = inlineField !== void 0 && ctx.fields !== void 0 && !ctx.fields.includes(inlineField);
|
|
9863
|
+
if (!orphanedInline && ctx.locale[key] !== void 0) return { text_key: key };
|
|
9864
|
+
for (const { suffix, generic } of FLOW_ERROR_RULE_FALLBACKS) {
|
|
9865
|
+
if (!key.endsWith(suffix)) continue;
|
|
9866
|
+
const field = key.slice(6, key.length - suffix.length);
|
|
9867
|
+
if (field === "") break;
|
|
9868
|
+
return { message: capitaliseFirst(interpolate(ctx.locale[generic] ?? ctx.locale[FLOW_ERROR_CATCH_ALL_KEY] ?? "Please check {0}.", [fieldLabel(ctx, field)])) };
|
|
9869
|
+
}
|
|
9870
|
+
if (orphanedInline && ctx.locale[key] !== void 0) return { message: ctx.locale[key] };
|
|
9871
|
+
return { text_key: key };
|
|
9872
|
+
}
|
|
9873
|
+
/** `<step>.field.<name>` from the locale, else a humanised field name. */
|
|
9874
|
+
function fieldLabel(ctx, field) {
|
|
9875
|
+
return ctx.locale[`${ctx.stepName}.field.${field}`] ?? humaniseFieldName(field);
|
|
9876
|
+
}
|
|
9877
|
+
/**
|
|
9878
|
+
* `x-auth-methods#password` → "password", `givenName` → "given name",
|
|
9879
|
+
* `date_of_birth` → "date of birth".
|
|
9880
|
+
*/
|
|
9881
|
+
function humaniseFieldName(field) {
|
|
9882
|
+
return (field.includes("#") ? field.split("#").pop() : field).replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_.-]+/g, " ").trim().toLowerCase();
|
|
9883
|
+
}
|
|
9884
|
+
/** Messages may open with a lowercase field label; sentence-case them. */
|
|
9885
|
+
function capitaliseFirst(text) {
|
|
9886
|
+
return text.length > 0 ? text[0]?.toUpperCase() + text.slice(1) : text;
|
|
9887
|
+
}
|
|
9614
9888
|
function stringify(value) {
|
|
9615
9889
|
if (value == null) return "";
|
|
9616
9890
|
if (typeof value === "string") return value;
|
|
@@ -9621,6 +9895,11 @@ function stringify(value) {
|
|
|
9621
9895
|
return String(value);
|
|
9622
9896
|
}
|
|
9623
9897
|
}
|
|
9898
|
+
/**
|
|
9899
|
+
* Positional `{n}` substitution shared by the `| t` filter and the
|
|
9900
|
+
* pre-localising fallback in {@link localiseFlowErrorKeys}, so both
|
|
9901
|
+
* produce byte-identical output for the same template and args.
|
|
9902
|
+
*/
|
|
9624
9903
|
function interpolate(template, args) {
|
|
9625
9904
|
if (args.length === 0) return template;
|
|
9626
9905
|
return template.replace(/\{(\d+)\}/g, (match, index) => {
|
|
@@ -9738,6 +10017,10 @@ const en = {
|
|
|
9738
10017
|
"signed-in.continue": "Continue",
|
|
9739
10018
|
"signed-in.logout": "Sign out",
|
|
9740
10019
|
"passkey-login.title": "Sign in with your passkey",
|
|
10020
|
+
"passkey-first.title": "Sign in",
|
|
10021
|
+
"passkey-first.description": "Use your passkey to continue",
|
|
10022
|
+
"passkey-first.action.passkey": "Continue with passkey",
|
|
10023
|
+
"passkey-first.action.email_fallback": "Use email instead",
|
|
9741
10024
|
"recover.title": "Check your email",
|
|
9742
10025
|
"recover.description": "We sent a password reset link to your email address.",
|
|
9743
10026
|
"recover.action.back": "Back to sign in",
|
|
@@ -9745,8 +10028,11 @@ const en = {
|
|
|
9745
10028
|
"submit.signin": "Sign in",
|
|
9746
10029
|
"action.forgot_password": "Forgot password?",
|
|
9747
10030
|
"action.cancel": "Cancel",
|
|
10031
|
+
"action.back": "Back",
|
|
9748
10032
|
"sso.redirect.title": "Redirecting to your provider…",
|
|
9749
|
-
"
|
|
10033
|
+
"passkey.pending.status": "Waiting for your passkey…",
|
|
10034
|
+
"error.passkey_cancelled": "The passkey prompt was closed before completing.",
|
|
10035
|
+
"error.passkey_timeout": "The passkey request timed out. Please try again.",
|
|
9750
10036
|
"error.passkey_not_registered": "This passkey is not registered. Please sign in with your email and password.",
|
|
9751
10037
|
"error.passkey_setup_failed": "Passkey registration did not complete. Please try again.",
|
|
9752
10038
|
"error.passkey_unsupported": "This device does not support passkeys",
|
|
@@ -9759,6 +10045,11 @@ const en = {
|
|
|
9759
10045
|
/** Figma sign-in error `6602:180268` — inline on password field. */
|
|
9760
10046
|
"error.invalid_credentials": "Wrong email or password.",
|
|
9761
10047
|
"error.required": "This field is required.",
|
|
10048
|
+
"error.field_required": "{0} is required.",
|
|
10049
|
+
"error.field_format": "Please enter a valid {0}.",
|
|
10050
|
+
"error.field_min_length": "{0} is too short.",
|
|
10051
|
+
"error.field_max_length": "{0} is too long.",
|
|
10052
|
+
"error.field_invalid": "Please check {0}.",
|
|
9762
10053
|
"error.sign_in_server.title": "We couldn't complete your sign in.",
|
|
9763
10054
|
"error.sign_in_server.body": "Please try again in a few minutes"
|
|
9764
10055
|
};
|
|
@@ -9840,6 +10131,10 @@ const de = {
|
|
|
9840
10131
|
"signed-in.continue": "Weiter",
|
|
9841
10132
|
"signed-in.logout": "Abmelden",
|
|
9842
10133
|
"passkey-login.title": "Mit Passkey anmelden",
|
|
10134
|
+
"passkey-first.title": "Anmelden",
|
|
10135
|
+
"passkey-first.description": "Verwende deinen Passkey, um fortzufahren",
|
|
10136
|
+
"passkey-first.action.passkey": "Weiter mit Passkey",
|
|
10137
|
+
"passkey-first.action.email_fallback": "Stattdessen E-Mail verwenden",
|
|
9843
10138
|
"recover.title": "E-Mail prüfen",
|
|
9844
10139
|
"recover.description": "Wir haben einen Link zum Zurücksetzen des Passworts an deine E-Mail-Adresse gesendet.",
|
|
9845
10140
|
"recover.action.back": "Zurück zur Anmeldung",
|
|
@@ -9847,8 +10142,11 @@ const de = {
|
|
|
9847
10142
|
"submit.signin": "Anmelden",
|
|
9848
10143
|
"action.forgot_password": "Passwort vergessen?",
|
|
9849
10144
|
"action.cancel": "Abbrechen",
|
|
10145
|
+
"action.back": "Zurück",
|
|
9850
10146
|
"sso.redirect.title": "Weiterleitung zum Anbieter…",
|
|
9851
|
-
"
|
|
10147
|
+
"passkey.pending.status": "Warten auf deinen Passkey…",
|
|
10148
|
+
"error.passkey_cancelled": "Die Passkey-Abfrage wurde vorzeitig geschlossen.",
|
|
10149
|
+
"error.passkey_timeout": "Die Passkey-Anfrage hat zu lange gedauert. Bitte versuche es erneut.",
|
|
9852
10150
|
"error.passkey_not_registered": "Dieser Passkey ist nicht registriert. Bitte melde dich mit E-Mail und Passwort an.",
|
|
9853
10151
|
"error.passkey_setup_failed": "Passkey-Registrierung wurde nicht abgeschlossen. Bitte versuche es erneut.",
|
|
9854
10152
|
"error.passkey_unsupported": "Dieses Gerät unterstützt keine Passkeys",
|
|
@@ -9860,6 +10158,11 @@ const de = {
|
|
|
9860
10158
|
"error.email_exists": "Ein Konto mit dieser E-Mail-Adresse existiert bereits.",
|
|
9861
10159
|
"error.invalid_credentials": "Falsche E-Mail oder falsches Passwort.",
|
|
9862
10160
|
"error.required": "Dieses Feld ist erforderlich.",
|
|
10161
|
+
"error.field_required": "{0} ist erforderlich.",
|
|
10162
|
+
"error.field_format": "Bitte gib einen gültigen Wert für {0} ein.",
|
|
10163
|
+
"error.field_min_length": "{0} ist zu kurz.",
|
|
10164
|
+
"error.field_max_length": "{0} ist zu lang.",
|
|
10165
|
+
"error.field_invalid": "Bitte überprüfe {0}.",
|
|
9863
10166
|
"error.sign_in_server.title": "Anmeldung konnte nicht abgeschlossen werden.",
|
|
9864
10167
|
"error.sign_in_server.body": "Bitte versuche es in einigen Minuten erneut"
|
|
9865
10168
|
};
|
|
@@ -9944,6 +10247,10 @@ const builtinLocales = {
|
|
|
9944
10247
|
"signed-in.continue": "Continua",
|
|
9945
10248
|
"signed-in.logout": "Esci",
|
|
9946
10249
|
"passkey-login.title": "Accedi con la tua passkey",
|
|
10250
|
+
"passkey-first.title": "Accedi",
|
|
10251
|
+
"passkey-first.description": "Usa la tua passkey per continuare",
|
|
10252
|
+
"passkey-first.action.passkey": "Continua con passkey",
|
|
10253
|
+
"passkey-first.action.email_fallback": "Usa invece l'email",
|
|
9947
10254
|
"recover.title": "Controlla la tua e-mail",
|
|
9948
10255
|
"recover.description": "Abbiamo inviato un link per reimpostare la password al tuo indirizzo e-mail.",
|
|
9949
10256
|
"recover.action.back": "Torna all'accesso",
|
|
@@ -9951,8 +10258,11 @@ const builtinLocales = {
|
|
|
9951
10258
|
"submit.signin": "Accedi",
|
|
9952
10259
|
"action.forgot_password": "Password dimenticata?",
|
|
9953
10260
|
"action.cancel": "Annulla",
|
|
10261
|
+
"action.back": "Indietro",
|
|
9954
10262
|
"sso.redirect.title": "Reindirizzamento al provider…",
|
|
9955
|
-
"
|
|
10263
|
+
"passkey.pending.status": "In attesa della tua passkey…",
|
|
10264
|
+
"error.passkey_cancelled": "La richiesta della passkey è stata chiusa prima del completamento.",
|
|
10265
|
+
"error.passkey_timeout": "La richiesta della passkey è scaduta. Riprova.",
|
|
9956
10266
|
"error.passkey_not_registered": "Questa passkey non è registrata. Accedi con e-mail e password.",
|
|
9957
10267
|
"error.passkey_setup_failed": "La registrazione della passkey non è stata completata. Riprova.",
|
|
9958
10268
|
"error.passkey_unsupported": "Questo dispositivo non supporta le passkey",
|
|
@@ -9964,6 +10274,11 @@ const builtinLocales = {
|
|
|
9964
10274
|
"error.email_exists": "Esiste già un account con questo indirizzo e-mail.",
|
|
9965
10275
|
"error.invalid_credentials": "E-mail o password errata.",
|
|
9966
10276
|
"error.required": "Questo campo è obbligatorio.",
|
|
10277
|
+
"error.field_required": "{0} è obbligatorio.",
|
|
10278
|
+
"error.field_format": "Inserisci un valore valido per {0}.",
|
|
10279
|
+
"error.field_min_length": "{0} è troppo corto.",
|
|
10280
|
+
"error.field_max_length": "{0} è troppo lungo.",
|
|
10281
|
+
"error.field_invalid": "Controlla {0}.",
|
|
9967
10282
|
"error.sign_in_server.title": "Non è stato possibile completare l'accesso.",
|
|
9968
10283
|
"error.sign_in_server.body": "Riprova tra qualche minuto"
|
|
9969
10284
|
}
|
|
@@ -11897,6 +12212,13 @@ let ZitadelLogin = class ZitadelLogin extends i$2 {
|
|
|
11897
12212
|
set purpose(value) {
|
|
11898
12213
|
this.#_purpose_accessor_storage = value;
|
|
11899
12214
|
}
|
|
12215
|
+
#_flowName_accessor_storage = "";
|
|
12216
|
+
get flowName() {
|
|
12217
|
+
return this.#_flowName_accessor_storage;
|
|
12218
|
+
}
|
|
12219
|
+
set flowName(value) {
|
|
12220
|
+
this.#_flowName_accessor_storage = value;
|
|
12221
|
+
}
|
|
11900
12222
|
#_project_accessor_storage;
|
|
11901
12223
|
get project() {
|
|
11902
12224
|
return this.#_project_accessor_storage;
|
|
@@ -12004,6 +12326,8 @@ let ZitadelLogin = class ZitadelLogin extends i$2 {
|
|
|
12004
12326
|
sheet.replaceSync(layout_chrome_default);
|
|
12005
12327
|
root.adoptedStyleSheets = [...existing, sheet];
|
|
12006
12328
|
root.addEventListener("zl-input", this.handleAtomInput);
|
|
12329
|
+
root.addEventListener("zl-change", this.handleAtomEdited);
|
|
12330
|
+
root.addEventListener("zl-dismiss", this.handleAlertDismiss);
|
|
12007
12331
|
root.addEventListener("zl-submit", this.handleAtomSubmit);
|
|
12008
12332
|
root.addEventListener("click", this.handleDelegatedAction);
|
|
12009
12333
|
root.addEventListener("submit", this.handleFormSubmit);
|
|
@@ -12142,17 +12466,32 @@ let ZitadelLogin = class ZitadelLogin extends i$2 {
|
|
|
12142
12466
|
if (!cfg.projectId) throw new Error("<zitadel-login> requires a project id (the `project-id` attribute, `configureZitadel({ projectId })`, or a `project` handle) to start a flow.");
|
|
12143
12467
|
wire = await startFlow(api, {
|
|
12144
12468
|
project_id: cfg.projectId,
|
|
12145
|
-
purpose: this.purpose
|
|
12469
|
+
purpose: this.purpose,
|
|
12470
|
+
...this.flowName ? { flow_definition_name: this.flowName } : {}
|
|
12146
12471
|
});
|
|
12147
12472
|
}
|
|
12148
12473
|
this.applyResponse(wire);
|
|
12149
12474
|
} catch (error) {
|
|
12150
|
-
this.handleTransportError(error);
|
|
12475
|
+
this.handleTransportError(this.describeFlowSelectionError(error));
|
|
12151
12476
|
} finally {
|
|
12152
12477
|
this.loading = false;
|
|
12153
12478
|
}
|
|
12154
12479
|
}
|
|
12480
|
+
/**
|
|
12481
|
+
* When a `flow-name` lookup fails, the server's envelope only says
|
|
12482
|
+
* "not found" / "purpose mismatch" — it cannot know the name came from
|
|
12483
|
+
* an attribute. Rewrap those two codes with the attribute and the fix;
|
|
12484
|
+
* every other error passes through untouched.
|
|
12485
|
+
*/
|
|
12486
|
+
describeFlowSelectionError(error) {
|
|
12487
|
+
if (!this.flowName || !(error instanceof ApiError)) return error;
|
|
12488
|
+
const code = typeof error.body === "object" && error.body !== null && "code" in error.body ? String(error.body.code) : "";
|
|
12489
|
+
if (code === "flowdef.not_found") return /* @__PURE__ */ new Error(`<zitadel-login> flow-name="${this.flowName}" does not match any active flow definition in this project. Check the \`name\` in your flow file and that it has been applied (\`zitadel apply\`).`);
|
|
12490
|
+
if (code === "flowdef.purpose_mismatch") return /* @__PURE__ */ new Error(`<zitadel-login> flow-name="${this.flowName}" matched a flow definition that does not serve purpose "${this.purpose}".`);
|
|
12491
|
+
return error;
|
|
12492
|
+
}
|
|
12155
12493
|
applyResponse(wire) {
|
|
12494
|
+
this.stepErrorDismissed = false;
|
|
12156
12495
|
this.response = wire;
|
|
12157
12496
|
const { branding, issues } = validateBranding(wire.branding);
|
|
12158
12497
|
this.branding = branding;
|
|
@@ -12206,7 +12545,12 @@ let ZitadelLogin = class ZitadelLogin extends i$2 {
|
|
|
12206
12545
|
}
|
|
12207
12546
|
renderStep(step, engine) {
|
|
12208
12547
|
const tenantSource = typeof this.branding?.liquid_template === "string" && this.branding.liquid_template.length > 0 ? this.branding.liquid_template : null;
|
|
12209
|
-
const
|
|
12548
|
+
const rawErrors = step.error ? localiseFlowErrorKeys(step.error, {
|
|
12549
|
+
locale: this.resolveLocale(),
|
|
12550
|
+
stepName: step.name ?? "",
|
|
12551
|
+
fields: (step.fields ?? []).map((field) => field.name)
|
|
12552
|
+
}) ?? [{ message: step.error }] : [];
|
|
12553
|
+
const errors = this.loading && this.stepErrorDismissed ? [] : rawErrors;
|
|
12210
12554
|
const fields = step.fields ?? [];
|
|
12211
12555
|
const actions = step.actions ?? [];
|
|
12212
12556
|
const context = {
|
|
@@ -12300,6 +12644,17 @@ let ZitadelLogin = class ZitadelLogin extends i$2 {
|
|
|
12300
12644
|
if (native && native.value !== field.value) return native.value;
|
|
12301
12645
|
return typeof field.value === "string" ? field.value : void 0;
|
|
12302
12646
|
}
|
|
12647
|
+
/**
|
|
12648
|
+
* True once the user retired the current step error by editing a field or
|
|
12649
|
+
* dismissing the alert. Deliberately NON-reactive: consulting reactive
|
|
12650
|
+
* state in `renderStep` would change its output string on the first
|
|
12651
|
+
* post-dismiss keystroke, and `unsafeHTML` would rebuild the whole step
|
|
12652
|
+
* subtree — wiping typed values (`hydrateStepAfterRender` only re-applies
|
|
12653
|
+
* them on response changes) and reconnecting atoms. Reset on every new
|
|
12654
|
+
* response; consulted only by the `loading` re-render, which rebuilds
|
|
12655
|
+
* anyway.
|
|
12656
|
+
*/
|
|
12657
|
+
stepErrorDismissed = false;
|
|
12303
12658
|
handleAtomInput = (event) => {
|
|
12304
12659
|
if (!event.detail) return;
|
|
12305
12660
|
const { name, value } = event.detail;
|
|
@@ -12309,11 +12664,41 @@ let ZitadelLogin = class ZitadelLogin extends i$2 {
|
|
|
12309
12664
|
[name]: value
|
|
12310
12665
|
};
|
|
12311
12666
|
this.syncFieldElementValue(name, value);
|
|
12667
|
+
this.clearStaleErrors(name);
|
|
12312
12668
|
emit(this, "zitadel-flow-input", {
|
|
12313
12669
|
name,
|
|
12314
12670
|
value
|
|
12315
12671
|
});
|
|
12316
12672
|
};
|
|
12673
|
+
/** `zl-change` from <zl-checkbox>/<zl-select>: only error clearing. */
|
|
12674
|
+
handleAtomEdited = (event) => {
|
|
12675
|
+
const name = event.detail?.name;
|
|
12676
|
+
if (name) this.clearStaleErrors(name);
|
|
12677
|
+
};
|
|
12678
|
+
/** Explicit dismiss of the step-error alert (it removes itself). */
|
|
12679
|
+
handleAlertDismiss = (event) => {
|
|
12680
|
+
if (event.target?.matches?.("zl-alert[data-zl-step-error]")) this.stepErrorDismissed = true;
|
|
12681
|
+
};
|
|
12682
|
+
/**
|
|
12683
|
+
* Retire the current step error after the user edits `fieldName`:
|
|
12684
|
+
* remove the form-level alert(s) and clear the edited field's inline
|
|
12685
|
+
* error — other fields' inline errors stay until they are edited.
|
|
12686
|
+
* Imperative on purpose; see {@link stepErrorDismissed}.
|
|
12687
|
+
*/
|
|
12688
|
+
clearStaleErrors(fieldName) {
|
|
12689
|
+
if (!this.response?.step.error) return;
|
|
12690
|
+
const root = this.shadowRoot;
|
|
12691
|
+
if (!root) return;
|
|
12692
|
+
if (!this.stepErrorDismissed) {
|
|
12693
|
+
this.stepErrorDismissed = true;
|
|
12694
|
+
for (const alert of root.querySelectorAll("zl-alert[data-zl-step-error]")) alert.remove();
|
|
12695
|
+
}
|
|
12696
|
+
for (const field of root.querySelectorAll("zl-field")) {
|
|
12697
|
+
if (field.getAttribute("name") !== fieldName || !field.invalid) continue;
|
|
12698
|
+
field.invalid = false;
|
|
12699
|
+
field.error = "";
|
|
12700
|
+
}
|
|
12701
|
+
}
|
|
12317
12702
|
syncFieldElementValue(name, value) {
|
|
12318
12703
|
const root = this.shadowRoot;
|
|
12319
12704
|
if (!root) return;
|
|
@@ -12373,9 +12758,10 @@ let ZitadelLogin = class ZitadelLogin extends i$2 {
|
|
|
12373
12758
|
*/
|
|
12374
12759
|
handlePasskeyError = (event) => {
|
|
12375
12760
|
if (!this.response) return;
|
|
12376
|
-
const { error: message, aborted } = event.detail;
|
|
12377
|
-
const errorKey = aborted ? "error.passkey_cancelled" : "error.passkey_failed";
|
|
12761
|
+
const { error: message, aborted, timed_out: timedOut } = event.detail;
|
|
12762
|
+
const errorKey = timedOut ? "error.passkey_timeout" : aborted ? "error.passkey_cancelled" : "error.passkey_failed";
|
|
12378
12763
|
if (this.response.step.error === errorKey) return;
|
|
12764
|
+
this.stepErrorDismissed = false;
|
|
12379
12765
|
const { challenge: _dropped, ...stepWithoutChallenge } = this.response.step;
|
|
12380
12766
|
this.response = {
|
|
12381
12767
|
...this.response,
|
|
@@ -12384,7 +12770,7 @@ let ZitadelLogin = class ZitadelLogin extends i$2 {
|
|
|
12384
12770
|
error: errorKey
|
|
12385
12771
|
}
|
|
12386
12772
|
};
|
|
12387
|
-
console.warn(`[zitadel-login] passkey ceremony ${aborted ? "cancelled" : "failed"}: ${message}`);
|
|
12773
|
+
console.warn(`[zitadel-login] passkey ceremony ${timedOut ? "timed out" : aborted ? "cancelled" : "failed"}: ${message}`);
|
|
12388
12774
|
};
|
|
12389
12775
|
findPrimaryAction() {
|
|
12390
12776
|
const root = this.shadowRoot;
|
|
@@ -12426,13 +12812,17 @@ let ZitadelLogin = class ZitadelLogin extends i$2 {
|
|
|
12426
12812
|
}
|
|
12427
12813
|
}
|
|
12428
12814
|
handleTransportError(error) {
|
|
12429
|
-
const message = error instanceof Error ? error.message : "Unexpected error contacting the Flow API.";
|
|
12815
|
+
const message = error instanceof ApiError ? apiErrorMessage(error) : error instanceof Error ? error.message : "Unexpected error contacting the Flow API.";
|
|
12430
12816
|
this.startupError = message;
|
|
12431
12817
|
console.error("[zitadel-login]", error);
|
|
12432
12818
|
emit(this, "zitadel-flow-error", { message });
|
|
12433
12819
|
}
|
|
12434
12820
|
};
|
|
12435
12821
|
__decorate([n$1({ type: String })], ZitadelLogin.prototype, "purpose", null);
|
|
12822
|
+
__decorate([n$1({
|
|
12823
|
+
type: String,
|
|
12824
|
+
attribute: "flow-name"
|
|
12825
|
+
})], ZitadelLogin.prototype, "flowName", null);
|
|
12436
12826
|
__decorate([n$1({ attribute: false })], ZitadelLogin.prototype, "project", null);
|
|
12437
12827
|
__decorate([n$1({
|
|
12438
12828
|
type: String,
|