@zitadel/components 0.0.0 → 0.1.0-alpha.10
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 +76 -55
- package/dist/atoms/index.d.mts +1 -1
- package/dist/atoms/index.mjs +1 -1
- package/dist/{atoms-CmOTltTH.mjs → atoms-BaayzEsr.mjs} +246 -93
- package/dist/atoms-BaayzEsr.mjs.map +1 -0
- package/dist/default-Cpl78hQN.mjs +6 -0
- package/dist/default-Cpl78hQN.mjs.map +1 -0
- package/dist/{index-7FDHEpv5.d.mts → index-DB_JTtln.d.mts} +104 -100
- package/dist/index-DB_JTtln.d.mts.map +1 -0
- package/dist/{index-DIUFZjXw.d.mts → index-DVDCrfkv.d.mts} +1550 -850
- package/dist/index-DVDCrfkv.d.mts.map +1 -0
- package/dist/{index-DaOSCm0T.d.mts → index-EJengPPu.d.mts} +1 -1
- package/dist/{index-DaOSCm0T.d.mts.map → index-EJengPPu.d.mts.map} +1 -1
- package/dist/index.d.mts +6 -5
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +5 -4
- package/dist/{manifest-DCC2FxCE.d.mts → manifest-DN5Al_Ur.d.mts} +1 -1
- package/dist/{manifest-DCC2FxCE.d.mts.map → manifest-DN5Al_Ur.d.mts.map} +1 -1
- package/dist/manifests.d.mts +1 -1
- package/dist/manifests.mjs +1 -1
- package/dist/orchestrator/index.d.mts +3 -2
- package/dist/orchestrator/index.mjs +3 -2
- package/dist/{orchestrator-CNKo2WQG.mjs → orchestrator-BEvS2wA_.mjs} +667 -641
- package/dist/orchestrator-BEvS2wA_.mjs.map +1 -0
- package/dist/standalone.mjs +12156 -0
- package/dist/tokens/index.d.mts +1 -1
- package/dist/tokens/index.mjs +1 -1
- package/dist/{tokens-TXmurodq.mjs → tokens-BQ_augxi.mjs} +2 -2
- package/dist/{tokens-TXmurodq.mjs.map → tokens-BQ_augxi.mjs.map} +1 -1
- package/package.json +9 -17
- package/dist/atoms/index.d.ts +0 -9
- package/dist/atoms/index.d.ts.map +0 -1
- package/dist/atoms/zl-alert.d.ts +0 -56
- package/dist/atoms/zl-alert.d.ts.map +0 -1
- package/dist/atoms/zl-button.d.ts +0 -83
- package/dist/atoms/zl-button.d.ts.map +0 -1
- package/dist/atoms/zl-card.d.ts +0 -46
- package/dist/atoms/zl-card.d.ts.map +0 -1
- package/dist/atoms/zl-field.d.ts +0 -73
- package/dist/atoms/zl-field.d.ts.map +0 -1
- package/dist/atoms/zl-icon.d.ts +0 -48
- package/dist/atoms/zl-icon.d.ts.map +0 -1
- package/dist/atoms/zl-page-shell.d.ts +0 -42
- package/dist/atoms/zl-page-shell.d.ts.map +0 -1
- package/dist/atoms/zl-passkey.d.ts +0 -118
- package/dist/atoms/zl-passkey.d.ts.map +0 -1
- package/dist/atoms/zl-pill.d.ts +0 -55
- package/dist/atoms/zl-pill.d.ts.map +0 -1
- package/dist/atoms-CmOTltTH.mjs.map +0 -1
- package/dist/index-7FDHEpv5.d.mts.map +0 -1
- package/dist/index-DIUFZjXw.d.mts.map +0 -1
- package/dist/index-bZEvwHtq.d.mts +0 -996
- package/dist/index-bZEvwHtq.d.mts.map +0 -1
- package/dist/index.d.ts +0 -16
- package/dist/index.d.ts.map +0 -1
- package/dist/internal/base64url.d.ts +0 -18
- package/dist/internal/base64url.d.ts.map +0 -1
- package/dist/internal/unique-id.d.ts +0 -2
- package/dist/internal/unique-id.d.ts.map +0 -1
- package/dist/manifest.d.ts +0 -36
- package/dist/manifest.d.ts.map +0 -1
- package/dist/manifests.d.ts +0 -6
- package/dist/manifests.d.ts.map +0 -1
- package/dist/orchestrator/api-client.d.ts +0 -33
- package/dist/orchestrator/api-client.d.ts.map +0 -1
- package/dist/orchestrator/branding-to-tokens.d.ts +0 -28
- package/dist/orchestrator/branding-to-tokens.d.ts.map +0 -1
- package/dist/orchestrator/branding-validator.d.ts +0 -7
- package/dist/orchestrator/branding-validator.d.ts.map +0 -1
- package/dist/orchestrator/branding.d.ts +0 -76
- package/dist/orchestrator/branding.d.ts.map +0 -1
- package/dist/orchestrator/font-loader.d.ts +0 -2
- package/dist/orchestrator/font-loader.d.ts.map +0 -1
- package/dist/orchestrator/index.d.ts +0 -25
- package/dist/orchestrator/index.d.ts.map +0 -1
- package/dist/orchestrator/liquid.d.ts +0 -28
- package/dist/orchestrator/liquid.d.ts.map +0 -1
- package/dist/orchestrator/locales/de.d.ts +0 -9
- package/dist/orchestrator/locales/de.d.ts.map +0 -1
- package/dist/orchestrator/locales/en.d.ts +0 -13
- package/dist/orchestrator/locales/en.d.ts.map +0 -1
- package/dist/orchestrator/locales/index.d.ts +0 -12
- package/dist/orchestrator/locales/index.d.ts.map +0 -1
- package/dist/orchestrator/mandatory-gates.d.ts +0 -26
- package/dist/orchestrator/mandatory-gates.d.ts.map +0 -1
- package/dist/orchestrator/sanitiser.d.ts +0 -6
- package/dist/orchestrator/sanitiser.d.ts.map +0 -1
- package/dist/orchestrator/template-context.d.ts +0 -55
- package/dist/orchestrator/template-context.d.ts.map +0 -1
- package/dist/orchestrator/template-names.d.ts +0 -16
- package/dist/orchestrator/template-names.d.ts.map +0 -1
- package/dist/orchestrator/templates/auth-form.liquid.d.ts +0 -14
- package/dist/orchestrator/templates/auth-form.liquid.d.ts.map +0 -1
- package/dist/orchestrator/templates/default.liquid.d.ts +0 -23
- package/dist/orchestrator/templates/default.liquid.d.ts.map +0 -1
- package/dist/orchestrator/templates/passkey-upsell.liquid.d.ts +0 -15
- package/dist/orchestrator/templates/passkey-upsell.liquid.d.ts.map +0 -1
- package/dist/orchestrator/templates/signed-in.liquid.d.ts +0 -20
- package/dist/orchestrator/templates/signed-in.liquid.d.ts.map +0 -1
- package/dist/orchestrator/theme-controller.d.ts +0 -30
- package/dist/orchestrator/theme-controller.d.ts.map +0 -1
- package/dist/orchestrator/zitadel-login.d.ts +0 -182
- package/dist/orchestrator/zitadel-login.d.ts.map +0 -1
- package/dist/orchestrator/zitadel-logout.d.ts +0 -86
- package/dist/orchestrator/zitadel-logout.d.ts.map +0 -1
- package/dist/orchestrator-CNKo2WQG.mjs.map +0 -1
- package/dist/styles/base.d.ts +0 -7
- package/dist/styles/base.d.ts.map +0 -1
- package/dist/styles/focus-ring.d.ts +0 -7
- package/dist/styles/focus-ring.d.ts.map +0 -1
- package/dist/styles/index.d.ts +0 -5
- package/dist/styles/index.d.ts.map +0 -1
- package/dist/styles/surface.d.ts +0 -8
- package/dist/styles/surface.d.ts.map +0 -1
- package/dist/styles/tokens.d.ts +0 -11
- package/dist/styles/tokens.d.ts.map +0 -1
- package/dist/tokens/index.d.ts +0 -9
- package/dist/tokens/index.d.ts.map +0 -1
- package/dist/tsconfig.lib.tsbuildinfo +0 -1
|
@@ -1,20 +1,12 @@
|
|
|
1
|
-
import { _ as __decorate, b as t, v as focusVisibleStyles, y as baseHostStyles } from "./atoms-
|
|
2
|
-
import { r as tokensCss } from "./tokens-
|
|
1
|
+
import { _ as __decorate, b as t, v as focusVisibleStyles, x as emit, y as baseHostStyles } from "./atoms-BaayzEsr.mjs";
|
|
2
|
+
import { r as tokensCss } from "./tokens-BQ_augxi.mjs";
|
|
3
|
+
import { t as default_default } from "./default-Cpl78hQN.mjs";
|
|
3
4
|
import { manifestRegistry } from "./manifests.mjs";
|
|
4
5
|
import { LitElement, css, html, nothing } from "lit";
|
|
5
6
|
import { customElement, property, state } from "lit/decorators.js";
|
|
6
7
|
import { unsafeHTML } from "lit/directives/unsafe-html.js";
|
|
7
8
|
import { Liquid } from "liquidjs";
|
|
8
9
|
import DOMPurify from "dompurify";
|
|
9
|
-
//#region ../api/dist/runtime/base-url.mjs
|
|
10
|
-
let proxyPath = "";
|
|
11
|
-
function getProxyPath() {
|
|
12
|
-
return proxyPath;
|
|
13
|
-
}
|
|
14
|
-
function setProxyPath(path) {
|
|
15
|
-
proxyPath = path;
|
|
16
|
-
}
|
|
17
|
-
//#endregion
|
|
18
10
|
//#region ../api/dist/runtime/auth.mjs
|
|
19
11
|
/**
|
|
20
12
|
* Module-global bearer token used by the orval-generated client's
|
|
@@ -34,18 +26,6 @@ function setApiAuthToken(token) {
|
|
|
34
26
|
apiAuthToken = token;
|
|
35
27
|
}
|
|
36
28
|
//#endregion
|
|
37
|
-
//#region ../api/dist/chunk-CfYAbeIz.mjs
|
|
38
|
-
var __defProp = Object.defineProperty;
|
|
39
|
-
var __exportAll = (all, no_symbols) => {
|
|
40
|
-
let target = {};
|
|
41
|
-
for (var name in all) __defProp(target, name, {
|
|
42
|
-
get: all[name],
|
|
43
|
-
enumerable: true
|
|
44
|
-
});
|
|
45
|
-
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
46
|
-
return target;
|
|
47
|
-
};
|
|
48
|
-
//#endregion
|
|
49
29
|
//#region ../api/dist/runtime/fetch.mjs
|
|
50
30
|
/**
|
|
51
31
|
* Framework-neutral failure type the orval-generated client throws on
|
|
@@ -118,6 +98,57 @@ function safeJsonParse(text) {
|
|
|
118
98
|
}
|
|
119
99
|
}
|
|
120
100
|
//#endregion
|
|
101
|
+
//#region src/orchestrator/api-client.ts
|
|
102
|
+
const apiRequestInit = { credentials: "include" };
|
|
103
|
+
async function startFlow(api, input) {
|
|
104
|
+
return api.createFlow(input, apiRequestInit);
|
|
105
|
+
}
|
|
106
|
+
async function submitStep(api, id, body) {
|
|
107
|
+
try {
|
|
108
|
+
return await api.submitFlowStep(id, body, apiRequestInit);
|
|
109
|
+
} catch (error) {
|
|
110
|
+
if (error instanceof ApiError && error.status === 400 && isFlowResponse(error.body)) return error.body;
|
|
111
|
+
throw error;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function isFlowResponse(body) {
|
|
115
|
+
return typeof body === "object" && body !== null && "step" in body;
|
|
116
|
+
}
|
|
117
|
+
async function getCurrentStep(api, id) {
|
|
118
|
+
return api.getFlowStep(id, apiRequestInit);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Exchange a terminal-flow `handoff_token` for an authenticated session.
|
|
122
|
+
* The server sets the `__nextgen_session` HttpOnly cookie on success.
|
|
123
|
+
*
|
|
124
|
+
* Uses the generated `exchangeHandoff` client which handles the
|
|
125
|
+
* `project_id` query parameter via {@link ExchangeHandoffParams}.
|
|
126
|
+
*/
|
|
127
|
+
async function exchangeSession(api, body, params) {
|
|
128
|
+
return api.exchangeHandoff(body, params, apiRequestInit);
|
|
129
|
+
}
|
|
130
|
+
//#endregion
|
|
131
|
+
//#region ../api/dist/runtime/base-url.mjs
|
|
132
|
+
let proxyPath = "";
|
|
133
|
+
function getProxyPath() {
|
|
134
|
+
return proxyPath;
|
|
135
|
+
}
|
|
136
|
+
function setProxyPath(path) {
|
|
137
|
+
proxyPath = path;
|
|
138
|
+
}
|
|
139
|
+
//#endregion
|
|
140
|
+
//#region ../api/dist/chunk-CfYAbeIz.mjs
|
|
141
|
+
var __defProp = Object.defineProperty;
|
|
142
|
+
var __exportAll = (all, no_symbols) => {
|
|
143
|
+
let target = {};
|
|
144
|
+
for (var name in all) __defProp(target, name, {
|
|
145
|
+
get: all[name],
|
|
146
|
+
enumerable: true
|
|
147
|
+
});
|
|
148
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
149
|
+
return target;
|
|
150
|
+
};
|
|
151
|
+
//#endregion
|
|
121
152
|
//#region ../api/dist/generated/endpoints/zitadelNextGen.mjs
|
|
122
153
|
/**
|
|
123
154
|
* Generated by orval v8.10.0 🍺
|
|
@@ -165,6 +196,7 @@ var zitadelNextGen_exports = /* @__PURE__ */ __exportAll({
|
|
|
165
196
|
getGetKeysUrl: () => getGetKeysUrl,
|
|
166
197
|
getGetLiveUrl: () => getGetLiveUrl,
|
|
167
198
|
getGetMySessionUrl: () => getGetMySessionUrl,
|
|
199
|
+
getGetMyUserUrl: () => getGetMyUserUrl,
|
|
168
200
|
getGetOpenIDConfigurationUrl: () => getGetOpenIDConfigurationUrl,
|
|
169
201
|
getGetProjectUrl: () => getGetProjectUrl,
|
|
170
202
|
getGetReadyUrl: () => getGetReadyUrl,
|
|
@@ -183,6 +215,7 @@ var zitadelNextGen_exports = /* @__PURE__ */ __exportAll({
|
|
|
183
215
|
getListUsersUrl: () => getListUsersUrl,
|
|
184
216
|
getLive: () => getLive,
|
|
185
217
|
getMySession: () => getMySession,
|
|
218
|
+
getMyUser: () => getMyUser,
|
|
186
219
|
getOpenIDConfiguration: () => getOpenIDConfiguration,
|
|
187
220
|
getProject: () => getProject,
|
|
188
221
|
getReady: () => getReady,
|
|
@@ -191,6 +224,7 @@ var zitadelNextGen_exports = /* @__PURE__ */ __exportAll({
|
|
|
191
224
|
getRevokeTokenUrl: () => getRevokeTokenUrl,
|
|
192
225
|
getSchemaById: () => getSchemaById,
|
|
193
226
|
getSession: () => getSession,
|
|
227
|
+
getSetUserPasswordUrl: () => getSetUserPasswordUrl,
|
|
194
228
|
getSubmitFlowEventUrl: () => getSubmitFlowEventUrl,
|
|
195
229
|
getSubmitFlowStepUrl: () => getSubmitFlowStepUrl,
|
|
196
230
|
getTeam: () => getTeam,
|
|
@@ -207,6 +241,7 @@ var zitadelNextGen_exports = /* @__PURE__ */ __exportAll({
|
|
|
207
241
|
revokeMySession: () => revokeMySession,
|
|
208
242
|
revokeSession: () => revokeSession,
|
|
209
243
|
revokeToken: () => revokeToken,
|
|
244
|
+
setUserPassword: () => setUserPassword,
|
|
210
245
|
submitFlowEvent: () => submitFlowEvent,
|
|
211
246
|
submitFlowStep: () => submitFlowStep,
|
|
212
247
|
updateFlowDefinition: () => updateFlowDefinition,
|
|
@@ -411,7 +446,7 @@ const getCreateUserUrl = (params) => {
|
|
|
411
446
|
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : value.toString());
|
|
412
447
|
});
|
|
413
448
|
const stringifiedParams = normalizedParams.toString();
|
|
414
|
-
return stringifiedParams.length > 0 ? `${getProxyPath()}/
|
|
449
|
+
return stringifiedParams.length > 0 ? `${getProxyPath()}/users?${stringifiedParams}` : `${getProxyPath()}/users`;
|
|
415
450
|
};
|
|
416
451
|
/**
|
|
417
452
|
* @summary Create user
|
|
@@ -433,7 +468,7 @@ const getListUsersUrl = (params) => {
|
|
|
433
468
|
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : value.toString());
|
|
434
469
|
});
|
|
435
470
|
const stringifiedParams = normalizedParams.toString();
|
|
436
|
-
return stringifiedParams.length > 0 ? `${getProxyPath()}/
|
|
471
|
+
return stringifiedParams.length > 0 ? `${getProxyPath()}/users?${stringifiedParams}` : `${getProxyPath()}/users`;
|
|
437
472
|
};
|
|
438
473
|
/**
|
|
439
474
|
* @summary List users
|
|
@@ -450,7 +485,7 @@ const getGetUserByIDUrl = (userId, params) => {
|
|
|
450
485
|
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : value.toString());
|
|
451
486
|
});
|
|
452
487
|
const stringifiedParams = normalizedParams.toString();
|
|
453
|
-
return stringifiedParams.length > 0 ? `${getProxyPath()}/
|
|
488
|
+
return stringifiedParams.length > 0 ? `${getProxyPath()}/users/${userId}?${stringifiedParams}` : `${getProxyPath()}/users/${userId}`;
|
|
454
489
|
};
|
|
455
490
|
/**
|
|
456
491
|
* @summary Get user by ID
|
|
@@ -461,6 +496,40 @@ const getUserByID = async (userId, params, options) => {
|
|
|
461
496
|
method: "GET"
|
|
462
497
|
});
|
|
463
498
|
};
|
|
499
|
+
const getSetUserPasswordUrl = (userId, params) => {
|
|
500
|
+
const normalizedParams = new URLSearchParams();
|
|
501
|
+
Object.entries(params || {}).forEach(([key, value]) => {
|
|
502
|
+
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : value.toString());
|
|
503
|
+
});
|
|
504
|
+
const stringifiedParams = normalizedParams.toString();
|
|
505
|
+
return stringifiedParams.length > 0 ? `${getProxyPath()}/users/${userId}/password?${stringifiedParams}` : `${getProxyPath()}/users/${userId}/password`;
|
|
506
|
+
};
|
|
507
|
+
/**
|
|
508
|
+
* @summary Set user password
|
|
509
|
+
*/
|
|
510
|
+
const setUserPassword = async (userId, setUserPasswordBody, params, options) => {
|
|
511
|
+
return customFetch(getSetUserPasswordUrl(userId, params), {
|
|
512
|
+
...options,
|
|
513
|
+
method: "PUT",
|
|
514
|
+
headers: {
|
|
515
|
+
"Content-Type": "application/json",
|
|
516
|
+
...options?.headers
|
|
517
|
+
},
|
|
518
|
+
body: JSON.stringify(setUserPasswordBody)
|
|
519
|
+
});
|
|
520
|
+
};
|
|
521
|
+
const getGetMyUserUrl = () => {
|
|
522
|
+
return `${getProxyPath()}/users/me`;
|
|
523
|
+
};
|
|
524
|
+
/**
|
|
525
|
+
* @summary Get my user information
|
|
526
|
+
*/
|
|
527
|
+
const getMyUser = async (options) => {
|
|
528
|
+
return customFetch(getGetMyUserUrl(), {
|
|
529
|
+
...options,
|
|
530
|
+
method: "GET"
|
|
531
|
+
});
|
|
532
|
+
};
|
|
464
533
|
const getCreateFlowUrl = () => {
|
|
465
534
|
return `${getProxyPath()}/flow`;
|
|
466
535
|
};
|
|
@@ -985,28 +1054,38 @@ const listFlowDefinitions = async (params, options) => {
|
|
|
985
1054
|
method: "GET"
|
|
986
1055
|
});
|
|
987
1056
|
};
|
|
988
|
-
const getGetFlowDefinitionUrl = (id) => {
|
|
989
|
-
|
|
1057
|
+
const getGetFlowDefinitionUrl = (id, params) => {
|
|
1058
|
+
const normalizedParams = new URLSearchParams();
|
|
1059
|
+
Object.entries(params || {}).forEach(([key, value]) => {
|
|
1060
|
+
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : value.toString());
|
|
1061
|
+
});
|
|
1062
|
+
const stringifiedParams = normalizedParams.toString();
|
|
1063
|
+
return stringifiedParams.length > 0 ? `${getProxyPath()}/flow_definitions/${id}?${stringifiedParams}` : `${getProxyPath()}/flow_definitions/${id}`;
|
|
990
1064
|
};
|
|
991
1065
|
/**
|
|
992
1066
|
* Get a flow definition by id
|
|
993
1067
|
* @summary Get a flow definition by id
|
|
994
1068
|
*/
|
|
995
|
-
const getFlowDefinition = async (id, options) => {
|
|
996
|
-
return customFetch(getGetFlowDefinitionUrl(id), {
|
|
1069
|
+
const getFlowDefinition = async (id, params, options) => {
|
|
1070
|
+
return customFetch(getGetFlowDefinitionUrl(id, params), {
|
|
997
1071
|
...options,
|
|
998
1072
|
method: "GET"
|
|
999
1073
|
});
|
|
1000
1074
|
};
|
|
1001
|
-
const getUpdateFlowDefinitionUrl = (id) => {
|
|
1002
|
-
|
|
1075
|
+
const getUpdateFlowDefinitionUrl = (id, params) => {
|
|
1076
|
+
const normalizedParams = new URLSearchParams();
|
|
1077
|
+
Object.entries(params || {}).forEach(([key, value]) => {
|
|
1078
|
+
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : value.toString());
|
|
1079
|
+
});
|
|
1080
|
+
const stringifiedParams = normalizedParams.toString();
|
|
1081
|
+
return stringifiedParams.length > 0 ? `${getProxyPath()}/flow_definitions/${id}?${stringifiedParams}` : `${getProxyPath()}/flow_definitions/${id}`;
|
|
1003
1082
|
};
|
|
1004
1083
|
/**
|
|
1005
1084
|
* Update a flow definition by id
|
|
1006
1085
|
* @summary Update a flow definition by id
|
|
1007
1086
|
*/
|
|
1008
|
-
const updateFlowDefinition = async (id, updateFlowDefinitionBody, options) => {
|
|
1009
|
-
return customFetch(getUpdateFlowDefinitionUrl(id), {
|
|
1087
|
+
const updateFlowDefinition = async (id, updateFlowDefinitionBody, params, options) => {
|
|
1088
|
+
return customFetch(getUpdateFlowDefinitionUrl(id, params), {
|
|
1010
1089
|
...options,
|
|
1011
1090
|
method: "PATCH",
|
|
1012
1091
|
headers: {
|
|
@@ -1016,15 +1095,20 @@ const updateFlowDefinition = async (id, updateFlowDefinitionBody, options) => {
|
|
|
1016
1095
|
body: JSON.stringify(updateFlowDefinitionBody)
|
|
1017
1096
|
});
|
|
1018
1097
|
};
|
|
1019
|
-
const getDeleteFlowDefinitionUrl = (id) => {
|
|
1020
|
-
|
|
1098
|
+
const getDeleteFlowDefinitionUrl = (id, params) => {
|
|
1099
|
+
const normalizedParams = new URLSearchParams();
|
|
1100
|
+
Object.entries(params || {}).forEach(([key, value]) => {
|
|
1101
|
+
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : value.toString());
|
|
1102
|
+
});
|
|
1103
|
+
const stringifiedParams = normalizedParams.toString();
|
|
1104
|
+
return stringifiedParams.length > 0 ? `${getProxyPath()}/flow_definitions/${id}?${stringifiedParams}` : `${getProxyPath()}/flow_definitions/${id}`;
|
|
1021
1105
|
};
|
|
1022
1106
|
/**
|
|
1023
1107
|
* Delete a flow definition by id
|
|
1024
1108
|
* @summary Delete a flow definition by id
|
|
1025
1109
|
*/
|
|
1026
|
-
const deleteFlowDefinition = async (id, options) => {
|
|
1027
|
-
return customFetch(getDeleteFlowDefinitionUrl(id), {
|
|
1110
|
+
const deleteFlowDefinition = async (id, params, options) => {
|
|
1111
|
+
return customFetch(getDeleteFlowDefinitionUrl(id, params), {
|
|
1028
1112
|
...options,
|
|
1029
1113
|
method: "DELETE"
|
|
1030
1114
|
});
|
|
@@ -1122,10 +1206,29 @@ function createApi(apiBase) {
|
|
|
1122
1206
|
}
|
|
1123
1207
|
//#endregion
|
|
1124
1208
|
//#region ../api/dist/runtime/config.mjs
|
|
1125
|
-
|
|
1209
|
+
/**
|
|
1210
|
+
* Slot for the configured project, stored on `globalThis` under a
|
|
1211
|
+
* {@link Symbol.for} key. Every copy of this module evaluated in the
|
|
1212
|
+
* same JS realm resolves the symbol through the global symbol registry
|
|
1213
|
+
* to the same identity, so they all read and write a single slot —
|
|
1214
|
+
* needed because the standalone components bundle inlines its own copy
|
|
1215
|
+
* of this file, and dual-package hazards / monorepo duplicates can load
|
|
1216
|
+
* a second copy alongside the app's. With a module-local `let` each
|
|
1217
|
+
* instance kept its own singleton and `configureZitadel()` calls in one
|
|
1218
|
+
* were invisible to `getZitadelConfig()` calls in another. Sharing is
|
|
1219
|
+
* realm-scoped — separate realms (iframes, Node `vm` contexts, worker
|
|
1220
|
+
* threads) have their own registries and are not unified by this.
|
|
1221
|
+
*/
|
|
1222
|
+
const PROJECT_SLOT = Symbol.for("@zitadel/api/config:currentProject");
|
|
1223
|
+
function readSlot() {
|
|
1224
|
+
return globalThis[PROJECT_SLOT] ?? null;
|
|
1225
|
+
}
|
|
1126
1226
|
/**
|
|
1127
1227
|
* Per-project API client cache. Ensures `getApi(project)` returns the
|
|
1128
1228
|
* same instance for the same project handle — no re-wrapping on every call.
|
|
1229
|
+
* Module-local on purpose: keyed by the shared frozen `ZitadelProject`
|
|
1230
|
+
* object identity, so cross-instance reads still resolve through the
|
|
1231
|
+
* same key and at worst memoize once per module instance.
|
|
1129
1232
|
*/
|
|
1130
1233
|
const apiCache = /* @__PURE__ */ new WeakMap();
|
|
1131
1234
|
/**
|
|
@@ -1150,37 +1253,82 @@ function getApi(project) {
|
|
|
1150
1253
|
* has not been called yet.
|
|
1151
1254
|
*/
|
|
1152
1255
|
function getZitadelConfig() {
|
|
1153
|
-
return
|
|
1256
|
+
return readSlot();
|
|
1154
1257
|
}
|
|
1155
1258
|
//#endregion
|
|
1156
|
-
//#region src/orchestrator/api
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1259
|
+
//#region src/orchestrator/resolve-api.ts
|
|
1260
|
+
/** Matches the `configureZitadel()` default so attribute and JS config agree. */
|
|
1261
|
+
const DEFAULT_PROXY_PATH = "/__nextgen";
|
|
1262
|
+
/**
|
|
1263
|
+
* Cache of project handles synthesized from attributes, keyed by their value
|
|
1264
|
+
* tuple. `getApi()` caches its client in a `WeakMap` keyed by the project's
|
|
1265
|
+
* identity, so the same attribute values must yield the *same* frozen object
|
|
1266
|
+
* across the several `resolveApi()` calls a single flow makes — otherwise
|
|
1267
|
+
* every call misses the cache and re-wraps a fresh client. A real page uses a
|
|
1268
|
+
* handful of distinct configs at most; the FIFO bound below is just a guard so
|
|
1269
|
+
* a pathological page that churns through unique configs can't leak memory.
|
|
1270
|
+
*/
|
|
1271
|
+
const MAX_SYNTHETIC_PROJECTS = 32;
|
|
1272
|
+
const syntheticProjects = /* @__PURE__ */ new Map();
|
|
1273
|
+
/**
|
|
1274
|
+
* Builds a `ZitadelProject` from declarative attributes, or `undefined` when
|
|
1275
|
+
* no `project-id` was given (nothing to configure). Mirrors
|
|
1276
|
+
* `configureZitadel()`'s proxy-path defaulting so the two config paths are
|
|
1277
|
+
* interchangeable.
|
|
1278
|
+
*/
|
|
1279
|
+
function projectFromAttrs({ projectId, proxyPath, url }) {
|
|
1280
|
+
if (!projectId) return void 0;
|
|
1281
|
+
const resolvedProxyPath = proxyPath || DEFAULT_PROXY_PATH;
|
|
1282
|
+
const resolvedUrl = url || void 0;
|
|
1283
|
+
const key = JSON.stringify([
|
|
1284
|
+
projectId,
|
|
1285
|
+
resolvedProxyPath,
|
|
1286
|
+
resolvedUrl ?? ""
|
|
1287
|
+
]);
|
|
1288
|
+
let project = syntheticProjects.get(key);
|
|
1289
|
+
if (!project) {
|
|
1290
|
+
project = Object.freeze({
|
|
1291
|
+
projectId,
|
|
1292
|
+
proxyPath: resolvedProxyPath,
|
|
1293
|
+
url: resolvedUrl
|
|
1294
|
+
});
|
|
1295
|
+
if (syntheticProjects.size >= MAX_SYNTHETIC_PROJECTS) {
|
|
1296
|
+
const oldest = syntheticProjects.keys().next().value;
|
|
1297
|
+
if (oldest !== void 0) syntheticProjects.delete(oldest);
|
|
1298
|
+
}
|
|
1299
|
+
syntheticProjects.set(key, project);
|
|
1167
1300
|
}
|
|
1168
|
-
|
|
1169
|
-
function isFlowResponse(body) {
|
|
1170
|
-
return typeof body === "object" && body !== null && "step" in body;
|
|
1171
|
-
}
|
|
1172
|
-
async function getCurrentStep(api, id) {
|
|
1173
|
-
return api.getFlowStep(id, apiRequestInit);
|
|
1301
|
+
return project;
|
|
1174
1302
|
}
|
|
1175
1303
|
/**
|
|
1176
|
-
*
|
|
1177
|
-
*
|
|
1304
|
+
* Resolves the effective SDK project handle and its typed API client for an
|
|
1305
|
+
* orchestrator element. Precedence, highest first:
|
|
1178
1306
|
*
|
|
1179
|
-
*
|
|
1180
|
-
*
|
|
1307
|
+
* 1. the element's `project` property (an SDK handle set from JS / a framework),
|
|
1308
|
+
* 2. the global handle from `configureZitadel()`,
|
|
1309
|
+
* 3. the `project-id` / `proxy-path` / `url` attributes set declaratively in HTML.
|
|
1310
|
+
*
|
|
1311
|
+
* Both JS paths (property and global) win over the declarative attributes, so a
|
|
1312
|
+
* deliberate `configureZitadel()` is never silently overridden by fallback or
|
|
1313
|
+
* stale HTML attributes; the attributes are the no-JS fallback.
|
|
1314
|
+
*
|
|
1315
|
+
* Both `<zitadel-login>` and `<zitadel-logout>` need the same resolution and
|
|
1316
|
+
* the same "no config" failure, so it lives here rather than being copied
|
|
1317
|
+
* into each element. Callers run this inside their try/catch so a missing
|
|
1318
|
+
* configuration surfaces through the element's normal error path rather than
|
|
1319
|
+
* as an unhandled rejection.
|
|
1320
|
+
*
|
|
1321
|
+
* @param project Optional per-element override handle.
|
|
1322
|
+
* @param attrs Declarative config read from the element's attributes.
|
|
1323
|
+
* @param element Tag name used in the thrown error (e.g. `<zitadel-login>`).
|
|
1181
1324
|
*/
|
|
1182
|
-
|
|
1183
|
-
|
|
1325
|
+
function resolveApi(project, attrs, element) {
|
|
1326
|
+
const cfg = project ?? getZitadelConfig() ?? projectFromAttrs(attrs);
|
|
1327
|
+
if (!cfg) throw new Error(`${element} requires a configured project: set the \`project-id\` attribute, set the \`project\` property, or call configureZitadel().`);
|
|
1328
|
+
return {
|
|
1329
|
+
project: cfg,
|
|
1330
|
+
api: getApi(cfg)
|
|
1331
|
+
};
|
|
1184
1332
|
}
|
|
1185
1333
|
//#endregion
|
|
1186
1334
|
//#region src/orchestrator/branding-to-tokens.ts
|
|
@@ -1424,30 +1572,48 @@ function sanitiseUrl(value, field, issues) {
|
|
|
1424
1572
|
//#endregion
|
|
1425
1573
|
//#region src/orchestrator/font-loader.ts
|
|
1426
1574
|
/**
|
|
1427
|
-
* Inject `branding.font_url` as `<link rel="stylesheet">`
|
|
1428
|
-
* `<
|
|
1575
|
+
* Inject `branding.font_url` as `<link rel="stylesheet">` into the host
|
|
1576
|
+
* document's `<head>`. Per `docs/design/branding/templates.md`:
|
|
1429
1577
|
*
|
|
1430
1578
|
* "The `font_url` stylesheet is injected by the orchestrator; the template
|
|
1431
1579
|
* does not emit the `<link>` tag itself."
|
|
1432
1580
|
*
|
|
1581
|
+
* The link must live at document level, not inside the shadow root:
|
|
1582
|
+
* browsers ignore `@font-face` rules declared in shadow-tree stylesheets,
|
|
1583
|
+
* so a shadow-scoped link would never register the font faces and every
|
|
1584
|
+
* branded font silently falls back to the system stack. `font-family`
|
|
1585
|
+
* references inside the shadow tree resolve against document-level faces.
|
|
1586
|
+
*
|
|
1433
1587
|
* Idempotent: calling with the same URL is a no-op; calling with a new URL
|
|
1434
1588
|
* replaces the previous link. Calling with `null`/`undefined` removes any
|
|
1435
1589
|
* previously injected link.
|
|
1436
1590
|
*/
|
|
1437
1591
|
const LINK_ID = "zl-font-link";
|
|
1438
1592
|
function applyFontUrl(shadowRoot, fontUrl) {
|
|
1439
|
-
const
|
|
1593
|
+
const ownerDocument = shadowRoot.ownerDocument ?? document;
|
|
1594
|
+
const existing = ownerDocument.head.querySelector(`link#${LINK_ID}`);
|
|
1440
1595
|
if (!fontUrl) {
|
|
1441
1596
|
existing?.remove();
|
|
1442
1597
|
return;
|
|
1443
1598
|
}
|
|
1444
|
-
|
|
1445
|
-
existing?.remove();
|
|
1446
|
-
const link = (shadowRoot.ownerDocument ?? document).createElement("link");
|
|
1599
|
+
const link = existing ?? ownerDocument.createElement("link");
|
|
1447
1600
|
link.id = LINK_ID;
|
|
1448
1601
|
link.rel = "stylesheet";
|
|
1449
|
-
link.href = fontUrl;
|
|
1450
|
-
|
|
1602
|
+
if (link.href !== fontUrl) link.href = fontUrl;
|
|
1603
|
+
if (!existing) ownerDocument.head.appendChild(link);
|
|
1604
|
+
}
|
|
1605
|
+
//#endregion
|
|
1606
|
+
//#region src/internal/escape-html.ts
|
|
1607
|
+
/**
|
|
1608
|
+
* Escapes the five HTML-significant characters so a string is safe to
|
|
1609
|
+
* interpolate into either element text or a double-quoted attribute value.
|
|
1610
|
+
*
|
|
1611
|
+
* Used for the orchestrator-owned attribution markup, which is appended after
|
|
1612
|
+
* the Liquid output has already been sanitised — so it can't rely on the
|
|
1613
|
+
* DOMPurify pass and must escape its own (tenant-supplied) values.
|
|
1614
|
+
*/
|
|
1615
|
+
function escapeHtml(value) {
|
|
1616
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1451
1617
|
}
|
|
1452
1618
|
//#endregion
|
|
1453
1619
|
//#region src/orchestrator/mandatory-gates.ts
|
|
@@ -1467,17 +1633,14 @@ function patchMandatoryGates(html, step, locale) {
|
|
|
1467
1633
|
}
|
|
1468
1634
|
function collectMissingAtoms(fragment, step, locale) {
|
|
1469
1635
|
const additions = [];
|
|
1470
|
-
if (step.fields) for (const
|
|
1636
|
+
if (step.fields) for (const field of step.fields) {
|
|
1471
1637
|
if (!field.required) continue;
|
|
1472
|
-
if (hasFieldFor(fragment, name)) continue;
|
|
1473
|
-
additions.push(buildField(name, field.text_key, field.type, locale, field.required));
|
|
1638
|
+
if (hasFieldFor(fragment, field.name)) continue;
|
|
1639
|
+
additions.push(buildField(field.name, field.text_key, field.type, locale, field.required));
|
|
1474
1640
|
}
|
|
1475
1641
|
if (step.actions && !hasPrimaryButton(fragment)) {
|
|
1476
|
-
const primary =
|
|
1477
|
-
if (primary)
|
|
1478
|
-
const [name, action] = primary;
|
|
1479
|
-
additions.push(buildSubmit(name, action.text_key, locale));
|
|
1480
|
-
}
|
|
1642
|
+
const primary = step.actions.find((action) => action.primary);
|
|
1643
|
+
if (primary) additions.push(buildSubmit(primary.name, primary.text_key, locale));
|
|
1481
1644
|
}
|
|
1482
1645
|
return additions;
|
|
1483
1646
|
}
|
|
@@ -1519,458 +1682,6 @@ function lookup(locale, key) {
|
|
|
1519
1682
|
return locale[key] ?? key;
|
|
1520
1683
|
}
|
|
1521
1684
|
//#endregion
|
|
1522
|
-
//#region src/orchestrator/templates/auth-form.liquid.ts
|
|
1523
|
-
/**
|
|
1524
|
-
* `auth-form` partial — Sign in and Sign up screens (Figma screens file).
|
|
1525
|
-
*
|
|
1526
|
-
* Sign up 2xl frame: `6593:141741` (card `6593:141743`, attribution `6593:141767`).
|
|
1527
|
-
* Sign in 2xl frame: `6593:141983`, card `6593:141985`, stack `6593:141989`
|
|
1528
|
-
* (email + password + forgot link + CTAs on one step).
|
|
1529
|
-
* Sign-in errors: wrong credentials `6602:180268`, server alert `6594:125237`.
|
|
1530
|
-
*
|
|
1531
|
-
* Figma `Field+CTAs` stacks fields + CTAs in one column at 16px (`spacing-03`).
|
|
1532
|
-
* Primary/secondary are 48px buttons; register / sign_in are body copy with a
|
|
1533
|
-
* purple text link (24px row) — not `<zl-button hierarchy="text">`.
|
|
1534
|
-
*/
|
|
1535
|
-
const authFormTemplate = String.raw`
|
|
1536
|
-
<zl-page-shell data-zl-template-root>
|
|
1537
|
-
{% if branding.logo_url %}
|
|
1538
|
-
<img slot="header" class="zl-card-logo" src="{{ branding.logo_url }}" alt="" />
|
|
1539
|
-
{% endif %}
|
|
1540
|
-
<zl-card>
|
|
1541
|
-
<h1 slot="header" class="zl-card-title">{{ step.texts.title_key | t: identity.display_name }}</h1>
|
|
1542
|
-
{% if step.texts.description_key %}
|
|
1543
|
-
<p slot="header" class="zl-card-subtitle">{{ step.texts.description_key | t: identity.display_name }}</p>
|
|
1544
|
-
{% endif %}
|
|
1545
|
-
|
|
1546
|
-
{% if errors and errors.size > 0 %}
|
|
1547
|
-
{% for err in errors %}
|
|
1548
|
-
{% if err | formLevelError %}
|
|
1549
|
-
{% assign alert_heading = err.text_key | alertHeading %}
|
|
1550
|
-
{% assign alert_body = err.text_key | alertBody %}
|
|
1551
|
-
<zl-alert severity="error"{% if alert_heading != "" %} heading="{{ alert_heading | t }}"{% endif %}>
|
|
1552
|
-
{% if alert_body != "" %}{{ alert_body | t }}{% elsif err.text_key %}{{ err.text_key | t }}{% else %}{{ err.message }}{% endif %}
|
|
1553
|
-
</zl-alert>
|
|
1554
|
-
{% endif %}
|
|
1555
|
-
{% endfor %}
|
|
1556
|
-
{% endif %}
|
|
1557
|
-
|
|
1558
|
-
{% for entry in fields %}
|
|
1559
|
-
{% assign field_placeholder = entry[1].text_key | fieldPlaceholder %}
|
|
1560
|
-
{% assign field_help = entry[1].text_key | fieldHelp %}
|
|
1561
|
-
{% assign field_err = entry[0] | fieldError: errors %}
|
|
1562
|
-
{% assign autocomplete_val = '' %}
|
|
1563
|
-
{% if entry[0] == 'email' %}
|
|
1564
|
-
{% assign autocomplete_val = 'email' %}
|
|
1565
|
-
{% elsif entry[1].type == 'password' and step.name == 'register' %}
|
|
1566
|
-
{% assign autocomplete_val = 'new-password' %}
|
|
1567
|
-
{% elsif entry[1].type == 'password' %}
|
|
1568
|
-
{% assign autocomplete_val = 'current-password' %}
|
|
1569
|
-
{% endif %}
|
|
1570
|
-
<zl-field
|
|
1571
|
-
name="{{ entry[0] }}"
|
|
1572
|
-
label="{{ entry[1].text_key | t }}"
|
|
1573
|
-
type="{{ entry[1].type }}"
|
|
1574
|
-
value="{{ entry[1].value }}"
|
|
1575
|
-
{% if autocomplete_val != '' %}autocomplete="{{ autocomplete_val }}"{% endif %}
|
|
1576
|
-
{% if entry[1].required %}required{% endif %}
|
|
1577
|
-
{% if field_placeholder != "" %}placeholder="{{ field_placeholder }}"{% endif %}
|
|
1578
|
-
{% if field_err != "" %}invalid error="{{ field_err }}"{% endif %}
|
|
1579
|
-
>
|
|
1580
|
-
{% if field_help != "" %}
|
|
1581
|
-
<span slot="help">{{ field_help }}</span>
|
|
1582
|
-
{% endif %}
|
|
1583
|
-
</zl-field>
|
|
1584
|
-
{% endfor %}
|
|
1585
|
-
|
|
1586
|
-
{% if fields.email and fields.password and step.name == 'identifier' %}
|
|
1587
|
-
<p class="zl-card-forgot">
|
|
1588
|
-
<a href="#" class="zl-card-forgot__link" data-action="recover">{{ 'action.forgot_password' | t }}</a>
|
|
1589
|
-
</p>
|
|
1590
|
-
{% endif %}
|
|
1591
|
-
|
|
1592
|
-
{% for entry in actions %}
|
|
1593
|
-
{% if entry[1].primary %}
|
|
1594
|
-
<zl-button
|
|
1595
|
-
hierarchy="primary"
|
|
1596
|
-
size="medium"
|
|
1597
|
-
type="submit"
|
|
1598
|
-
block
|
|
1599
|
-
action="{{ entry[0] }}"
|
|
1600
|
-
label="{{ entry[1].text_key | t }}"
|
|
1601
|
-
{% if loading %}loading{% endif %}
|
|
1602
|
-
></zl-button>
|
|
1603
|
-
{% endif %}
|
|
1604
|
-
{% endfor %}
|
|
1605
|
-
|
|
1606
|
-
{% if actions.passkey %}
|
|
1607
|
-
<zl-button
|
|
1608
|
-
hierarchy="secondary"
|
|
1609
|
-
size="medium"
|
|
1610
|
-
block
|
|
1611
|
-
action="passkey"
|
|
1612
|
-
label="{{ actions.passkey.text_key | t }}"
|
|
1613
|
-
></zl-button>
|
|
1614
|
-
{% endif %}
|
|
1615
|
-
|
|
1616
|
-
{% if actions.register %}
|
|
1617
|
-
<p class="zl-card-nav">
|
|
1618
|
-
{{ 'identifier.action.register.lead' | t }}<a href="#" class="zl-card-nav__link" data-action="register">{{ 'identifier.action.register.link' | t }}</a>
|
|
1619
|
-
</p>
|
|
1620
|
-
{% endif %}
|
|
1621
|
-
|
|
1622
|
-
{% if actions.sign_in %}
|
|
1623
|
-
<p class="zl-card-nav">
|
|
1624
|
-
{{ 'register.action.sign_in.lead' | t }}<a href="#" class="zl-card-nav__link" data-action="sign_in">{{ 'register.action.sign_in.link' | t }}</a>
|
|
1625
|
-
</p>
|
|
1626
|
-
{% endif %}
|
|
1627
|
-
|
|
1628
|
-
{% if challenge and challenge.method == "passkey" %}
|
|
1629
|
-
<zl-passkey
|
|
1630
|
-
ceremony="{{ challenge.options.ceremony | default: 'authenticate' }}"
|
|
1631
|
-
challenge-id="{{ challenge.challenge_id }}"
|
|
1632
|
-
options='{{ challenge.options | json }}'
|
|
1633
|
-
></zl-passkey>
|
|
1634
|
-
{% endif %}
|
|
1635
|
-
|
|
1636
|
-
{% mandatory_gates %}
|
|
1637
|
-
</zl-card>
|
|
1638
|
-
</zl-page-shell>
|
|
1639
|
-
`;
|
|
1640
|
-
//#endregion
|
|
1641
|
-
//#region src/orchestrator/templates/default.liquid.ts
|
|
1642
|
-
/**
|
|
1643
|
-
* Bundled `default.liquid` master template.
|
|
1644
|
-
*
|
|
1645
|
-
* Renders the four target Figma auth screens (Sign in, Sign up, Passkey
|
|
1646
|
-
* upsell, Signed in) by including the appropriate partial based on
|
|
1647
|
-
* `step.name`. Tenant-specific layouts (`branding.layout`) replace the
|
|
1648
|
-
* outer chrome only — the per-step partials stay shared so atom output
|
|
1649
|
-
* tracks the design system without each tenant re-implementing it.
|
|
1650
|
-
*
|
|
1651
|
-
* Spec: docs/design/branding/templates.md.
|
|
1652
|
-
*/
|
|
1653
|
-
const defaultTemplate = String.raw`
|
|
1654
|
-
{%- if step.name == 'signed-in' or step.complete == 'show' -%}
|
|
1655
|
-
{%- include 'signed-in' -%}
|
|
1656
|
-
{%- elsif step.name == 'passkey' or step.name == 'passkey-upsell' or step.name == 'passkey-setup' or step.name == 'passkey-login' -%}
|
|
1657
|
-
{%- include 'passkey-upsell' -%}
|
|
1658
|
-
{%- else -%}
|
|
1659
|
-
{%- include 'auth-form' -%}
|
|
1660
|
-
{%- endif -%}
|
|
1661
|
-
`;
|
|
1662
|
-
/**
|
|
1663
|
-
* Layout chrome injected as an `adoptedStyleSheet` on the orchestrator's
|
|
1664
|
-
* shadow root. Provides the page background and the attribution-footer
|
|
1665
|
-
* positioning that lives *outside* any template — the rest of the visual
|
|
1666
|
-
* surface is owned by the `<zl-page-shell>` / `<zl-card>` atoms the
|
|
1667
|
-
* templates render. Token references resolve against the
|
|
1668
|
-
* `@zitadel/design-tokens` CSS variables that are present on
|
|
1669
|
-
* `:host` via the branding stylesheet.
|
|
1670
|
-
*/
|
|
1671
|
-
const layoutChromeCss = `
|
|
1672
|
-
:host {
|
|
1673
|
-
display: block;
|
|
1674
|
-
min-height: 100%;
|
|
1675
|
-
background: var(--zl-color-surface-default-black, #0f0f11);
|
|
1676
|
-
color: var(--zl-color-text-primary-white, #f4f4f6);
|
|
1677
|
-
font-family: var(--zl-font-family-sans, system-ui, sans-serif);
|
|
1678
|
-
}
|
|
1679
|
-
.zl-mount {
|
|
1680
|
-
display: flex;
|
|
1681
|
-
flex-direction: column;
|
|
1682
|
-
min-height: 100vh;
|
|
1683
|
-
background: inherit;
|
|
1684
|
-
color: inherit;
|
|
1685
|
-
}
|
|
1686
|
-
.zl-mount > zl-page-shell,
|
|
1687
|
-
.zl-mount > [data-zl-template-root] {
|
|
1688
|
-
flex: 1 1 auto;
|
|
1689
|
-
}
|
|
1690
|
-
.zl-attribution {
|
|
1691
|
-
display: flex;
|
|
1692
|
-
justify-content: center;
|
|
1693
|
-
align-items: center;
|
|
1694
|
-
background: transparent;
|
|
1695
|
-
}
|
|
1696
|
-
.zl-attribution[hidden] {
|
|
1697
|
-
display: none;
|
|
1698
|
-
}
|
|
1699
|
-
/* Card header typography — Figma "Desktop/Headings/Small" + "Body Small
|
|
1700
|
-
Regular" pattern shared by sign-in (6593:141740), passkey upsell
|
|
1701
|
-
(6594:89142 / 6594:12796), and signed-in (6596:132845). Templates
|
|
1702
|
-
slot raw <h1>/<p> elements into <zl-card>, which keeps them in the
|
|
1703
|
-
light DOM where the orchestrator's stylesheet can reach them — the
|
|
1704
|
-
atom intentionally doesn't dictate typography. */
|
|
1705
|
-
.zl-card-title {
|
|
1706
|
-
margin: 0;
|
|
1707
|
-
font-family: var(--zl-font-family-heading, var(--zl-font-family-sans, system-ui, sans-serif));
|
|
1708
|
-
font-size: 2rem;
|
|
1709
|
-
font-weight: 400;
|
|
1710
|
-
line-height: 2.5rem;
|
|
1711
|
-
letter-spacing: -0.02em;
|
|
1712
|
-
color: var(--zl-color-text-primary-white, #f4f4f6);
|
|
1713
|
-
text-align: left;
|
|
1714
|
-
}
|
|
1715
|
-
.zl-card-subtitle {
|
|
1716
|
-
margin: 0;
|
|
1717
|
-
font-family: var(--zl-font-family-sans, system-ui, sans-serif);
|
|
1718
|
-
font-size: 0.875rem;
|
|
1719
|
-
line-height: 1.25rem;
|
|
1720
|
-
font-weight: 400;
|
|
1721
|
-
color: var(--zl-color-text-primary-white, #f4f4f6);
|
|
1722
|
-
}
|
|
1723
|
-
/* Figma 6593:141989 / 6594:12882 — left-aligned in Field+CTAs (x=0, items-start). */
|
|
1724
|
-
.zl-card-nav {
|
|
1725
|
-
margin: 0;
|
|
1726
|
-
font-family: var(--zl-font-family-sans, system-ui, sans-serif);
|
|
1727
|
-
font-size: 1rem;
|
|
1728
|
-
line-height: 1.5rem;
|
|
1729
|
-
font-weight: 400;
|
|
1730
|
-
color: var(--zl-color-text-primary-white, #f4f4f6);
|
|
1731
|
-
text-align: left;
|
|
1732
|
-
}
|
|
1733
|
-
.zl-card-nav__link {
|
|
1734
|
-
display: inline;
|
|
1735
|
-
margin: 0;
|
|
1736
|
-
padding: 0;
|
|
1737
|
-
border: none;
|
|
1738
|
-
background: transparent;
|
|
1739
|
-
font: inherit;
|
|
1740
|
-
line-height: inherit;
|
|
1741
|
-
color: var(--zl-color-icon-default-purple, #bba5e4);
|
|
1742
|
-
text-decoration: none;
|
|
1743
|
-
cursor: pointer;
|
|
1744
|
-
}
|
|
1745
|
-
.zl-card-nav__link:hover {
|
|
1746
|
-
text-decoration: underline;
|
|
1747
|
-
}
|
|
1748
|
-
.zl-card-nav__link:focus-visible {
|
|
1749
|
-
outline: var(--zl-focus-width, 2px) solid var(--zl-focus-color, #f4f4f6);
|
|
1750
|
-
outline-offset: var(--zl-focus-offset, 2px);
|
|
1751
|
-
}
|
|
1752
|
-
/* Figma 6593:141989 — forgot password row (left-aligned, before CTAs). */
|
|
1753
|
-
.zl-card-forgot {
|
|
1754
|
-
margin: 0;
|
|
1755
|
-
text-align: left;
|
|
1756
|
-
}
|
|
1757
|
-
.zl-card-forgot__link {
|
|
1758
|
-
display: inline;
|
|
1759
|
-
margin: 0;
|
|
1760
|
-
padding: 0;
|
|
1761
|
-
border: none;
|
|
1762
|
-
background: transparent;
|
|
1763
|
-
font-family: var(--zl-font-family-sans, system-ui, sans-serif);
|
|
1764
|
-
font-size: 1rem;
|
|
1765
|
-
line-height: 1.5rem;
|
|
1766
|
-
font-weight: 400;
|
|
1767
|
-
color: var(--zl-color-icon-default-purple, #bba5e4);
|
|
1768
|
-
text-decoration: none;
|
|
1769
|
-
cursor: pointer;
|
|
1770
|
-
}
|
|
1771
|
-
.zl-card-forgot__link:hover {
|
|
1772
|
-
text-decoration: underline;
|
|
1773
|
-
}
|
|
1774
|
-
.zl-card-forgot__link:focus-visible {
|
|
1775
|
-
outline: var(--zl-focus-width, 2px) solid var(--zl-focus-color, #f4f4f6);
|
|
1776
|
-
outline-offset: var(--zl-focus-offset, 2px);
|
|
1777
|
-
}
|
|
1778
|
-
`;
|
|
1779
|
-
//#endregion
|
|
1780
|
-
//#region src/orchestrator/templates/passkey-upsell.liquid.ts
|
|
1781
|
-
/**
|
|
1782
|
-
* `passkey-upsell` partial — third Figma target screen (file
|
|
1783
|
-
* `xkvBjkOJ8ENuHdTGZHXezK`, node `6594:630`).
|
|
1784
|
-
*
|
|
1785
|
-
* Differs from `auth-form`:
|
|
1786
|
-
* - heading + subtitle live in a compact card (gap 24px instead of 32px),
|
|
1787
|
-
* - primary "Set up passkey" CTA carries a trailing 24px passkey icon
|
|
1788
|
-
* (Figma slots the icon to the right of the label, not above it),
|
|
1789
|
-
* - secondary "Skip for now" uses the dark secondary hierarchy, not the
|
|
1790
|
-
* `text` hierarchy — the Figma button has a solid #252528 background.
|
|
1791
|
-
*
|
|
1792
|
-
* Server-side errors land in a `<zl-alert>` the same way as the auth form.
|
|
1793
|
-
*/
|
|
1794
|
-
const passkeyUpsellTemplate = String.raw`
|
|
1795
|
-
<zl-page-shell data-zl-template-root>
|
|
1796
|
-
{% if branding.logo_url %}
|
|
1797
|
-
<img slot="header" class="zl-card-logo" src="{{ branding.logo_url }}" alt="" />
|
|
1798
|
-
{% endif %}
|
|
1799
|
-
<zl-card compact>
|
|
1800
|
-
<h1 slot="header" class="zl-card-title">{{ step.texts.title_key | t: identity.display_name }}</h1>
|
|
1801
|
-
<p slot="header" class="zl-card-subtitle">{{ 'passkey-upsell.description.line1' | t }}</p>
|
|
1802
|
-
<p slot="header" class="zl-card-subtitle">{{ 'passkey-upsell.description.line2' | t }}</p>
|
|
1803
|
-
|
|
1804
|
-
{% if errors and errors.size > 0 %}
|
|
1805
|
-
{% for err in errors %}
|
|
1806
|
-
{% if err | formLevelError %}
|
|
1807
|
-
<zl-alert severity="error">
|
|
1808
|
-
{% if err.text_key %}{{ err.text_key | t }}{% else %}{{ err.message }}{% endif %}
|
|
1809
|
-
</zl-alert>
|
|
1810
|
-
{% endif %}
|
|
1811
|
-
{% endfor %}
|
|
1812
|
-
{% endif %}
|
|
1813
|
-
|
|
1814
|
-
{% for entry in actions %}
|
|
1815
|
-
{% if entry[1].primary %}
|
|
1816
|
-
<zl-button
|
|
1817
|
-
slot="footer"
|
|
1818
|
-
hierarchy="primary"
|
|
1819
|
-
size="medium"
|
|
1820
|
-
type="submit"
|
|
1821
|
-
block
|
|
1822
|
-
action="{{ entry[0] }}"
|
|
1823
|
-
{% if loading %}loading disabled{% endif %}
|
|
1824
|
-
>
|
|
1825
|
-
{{ entry[1].text_key | t }}
|
|
1826
|
-
<zl-icon slot="trailing" name="passkey" size="24"></zl-icon>
|
|
1827
|
-
</zl-button>
|
|
1828
|
-
{% endif %}
|
|
1829
|
-
{% endfor %}
|
|
1830
|
-
|
|
1831
|
-
{% for entry in actions %}
|
|
1832
|
-
{% unless entry[1].primary %}
|
|
1833
|
-
<zl-button
|
|
1834
|
-
slot="footer"
|
|
1835
|
-
hierarchy="secondary"
|
|
1836
|
-
size="medium"
|
|
1837
|
-
type="button"
|
|
1838
|
-
block
|
|
1839
|
-
action="{{ entry[0] }}"
|
|
1840
|
-
label="{{ entry[1].text_key | t }}"
|
|
1841
|
-
></zl-button>
|
|
1842
|
-
{% endunless %}
|
|
1843
|
-
{% endfor %}
|
|
1844
|
-
|
|
1845
|
-
{% mandatory_gates %}
|
|
1846
|
-
|
|
1847
|
-
{% if challenge and challenge.method == "passkey" %}
|
|
1848
|
-
<zl-passkey
|
|
1849
|
-
ceremony="{{ challenge.options.ceremony | default: 'register' }}"
|
|
1850
|
-
challenge-id="{{ challenge.challenge_id }}"
|
|
1851
|
-
options='{{ challenge.options | json }}'
|
|
1852
|
-
></zl-passkey>
|
|
1853
|
-
{% endif %}
|
|
1854
|
-
</zl-card>
|
|
1855
|
-
</zl-page-shell>
|
|
1856
|
-
`;
|
|
1857
|
-
//#endregion
|
|
1858
|
-
//#region src/orchestrator/templates/signed-in.liquid.ts
|
|
1859
|
-
/**
|
|
1860
|
-
* `signed-in` partial — fourth Figma target screen (file
|
|
1861
|
-
* `xkvBjkOJ8ENuHdTGZHXezK`, node `6596:132844`).
|
|
1862
|
-
*
|
|
1863
|
-
* Figma layout:
|
|
1864
|
-
* - heading "You're signed in as" (left-aligned, full width)
|
|
1865
|
-
* - body line with the authenticated email address (Arimo Regular 16/24)
|
|
1866
|
-
* - "Continue" primary CTA
|
|
1867
|
-
* - "Logout" secondary CTA
|
|
1868
|
-
*
|
|
1869
|
-
* No avatar / identity hero glyph: the Figma frame is intentionally a
|
|
1870
|
-
* pure modal layover and dropping the avatar keeps the orchestrator
|
|
1871
|
-
* default in lockstep with the spec.
|
|
1872
|
-
*
|
|
1873
|
-
* Rendered when the flow returns a terminal step (`complete: "show"`)
|
|
1874
|
-
* and no `post-sign-in-url` is configured, so the user can confirm the
|
|
1875
|
-
* identity before the host SPA takes over.
|
|
1876
|
-
*/
|
|
1877
|
-
const signedInTemplate = String.raw`
|
|
1878
|
-
<zl-page-shell data-zl-template-root>
|
|
1879
|
-
{% if branding.logo_url %}
|
|
1880
|
-
<img slot="header" class="zl-card-logo" src="{{ branding.logo_url }}" alt="" />
|
|
1881
|
-
{% endif %}
|
|
1882
|
-
<zl-card compact>
|
|
1883
|
-
<h1 slot="header" class="zl-card-title">
|
|
1884
|
-
{{ step.texts.title_key | t: identity.display_name }}
|
|
1885
|
-
</h1>
|
|
1886
|
-
{% if identity.email_address or identity.display_name %}
|
|
1887
|
-
<p slot="header" class="zl-card-subtitle">
|
|
1888
|
-
{{ identity.email_address | default: identity.display_name }}
|
|
1889
|
-
</p>
|
|
1890
|
-
{% endif %}
|
|
1891
|
-
|
|
1892
|
-
{% if errors and errors.size > 0 %}
|
|
1893
|
-
{% for err in errors %}
|
|
1894
|
-
<zl-alert severity="error">{{ err.text_key | t }}</zl-alert>
|
|
1895
|
-
{% endfor %}
|
|
1896
|
-
{% endif %}
|
|
1897
|
-
|
|
1898
|
-
{% if actions and actions.size > 0 %}
|
|
1899
|
-
{% for entry in actions %}
|
|
1900
|
-
{% if entry[1].primary %}
|
|
1901
|
-
<zl-button
|
|
1902
|
-
slot="footer"
|
|
1903
|
-
hierarchy="primary"
|
|
1904
|
-
size="medium"
|
|
1905
|
-
type="submit"
|
|
1906
|
-
block
|
|
1907
|
-
action="{{ entry[0] }}"
|
|
1908
|
-
label="{{ entry[1].text_key | t }}"
|
|
1909
|
-
{% if loading %}loading{% endif %}
|
|
1910
|
-
></zl-button>
|
|
1911
|
-
{% endif %}
|
|
1912
|
-
{% endfor %}
|
|
1913
|
-
|
|
1914
|
-
{% for entry in actions %}
|
|
1915
|
-
{% unless entry[1].primary %}
|
|
1916
|
-
<zl-button
|
|
1917
|
-
slot="footer"
|
|
1918
|
-
hierarchy="secondary"
|
|
1919
|
-
size="medium"
|
|
1920
|
-
block
|
|
1921
|
-
action="{{ entry[0] }}"
|
|
1922
|
-
label="{{ entry[1].text_key | t }}"
|
|
1923
|
-
></zl-button>
|
|
1924
|
-
{% endunless %}
|
|
1925
|
-
{% endfor %}
|
|
1926
|
-
{% else %}
|
|
1927
|
-
{% comment %}
|
|
1928
|
-
Fallback when the API ships a terminal step with no actions —
|
|
1929
|
-
matches Figma node 6596:132844 which always renders Continue
|
|
1930
|
-
+ Logout. The orchestrator wires these to its built-in
|
|
1931
|
-
continue / logout handlers.
|
|
1932
|
-
{% endcomment %}
|
|
1933
|
-
<zl-button
|
|
1934
|
-
slot="footer"
|
|
1935
|
-
hierarchy="primary"
|
|
1936
|
-
size="medium"
|
|
1937
|
-
type="submit"
|
|
1938
|
-
block
|
|
1939
|
-
action="continue"
|
|
1940
|
-
label="{{ 'signed-in.continue' | t }}"
|
|
1941
|
-
></zl-button>
|
|
1942
|
-
<zl-button
|
|
1943
|
-
slot="footer"
|
|
1944
|
-
hierarchy="secondary"
|
|
1945
|
-
size="medium"
|
|
1946
|
-
block
|
|
1947
|
-
action="logout"
|
|
1948
|
-
label="{{ 'signed-in.logout' | t }}"
|
|
1949
|
-
></zl-button>
|
|
1950
|
-
{% endif %}
|
|
1951
|
-
|
|
1952
|
-
{% mandatory_gates %}
|
|
1953
|
-
</zl-card>
|
|
1954
|
-
</zl-page-shell>
|
|
1955
|
-
`;
|
|
1956
|
-
//#endregion
|
|
1957
|
-
//#region src/orchestrator/template-names.ts
|
|
1958
|
-
/**
|
|
1959
|
-
* Names of the bundled Liquid templates the `<zitadel-login>` orchestrator
|
|
1960
|
-
* registers.
|
|
1961
|
-
*
|
|
1962
|
-
* This lives in its own module — separate from `liquid.ts` — so the public
|
|
1963
|
-
* barrel can re-export `TEMPLATE_NAMES` without dragging LiquidJS' `Liquid`
|
|
1964
|
-
* type (and its Node ambient-type requirements) into the published
|
|
1965
|
-
* declaration surface. See `liquid.ts` / the orchestrator barrel.
|
|
1966
|
-
*/
|
|
1967
|
-
const TEMPLATE_NAMES = {
|
|
1968
|
-
default: "default",
|
|
1969
|
-
authForm: "auth-form",
|
|
1970
|
-
passkeyUpsell: "passkey-upsell",
|
|
1971
|
-
signedIn: "signed-in"
|
|
1972
|
-
};
|
|
1973
|
-
//#endregion
|
|
1974
1685
|
//#region src/orchestrator/liquid.ts
|
|
1975
1686
|
/**
|
|
1976
1687
|
* LiquidJS engine factory for the `<zitadel-login>` orchestrator.
|
|
@@ -1987,13 +1698,11 @@ const TEMPLATE_NAMES = {
|
|
|
1987
1698
|
* escapes (Layer 1 of the security pipeline).
|
|
1988
1699
|
* - Partials are loaded from an in-memory map; no filesystem access.
|
|
1989
1700
|
*/
|
|
1701
|
+
const TEMPLATE_NAMES$1 = { default: "default" };
|
|
1990
1702
|
function createLiquidEngine(options) {
|
|
1991
1703
|
const engine = new Liquid({
|
|
1992
1704
|
templates: {
|
|
1993
|
-
[TEMPLATE_NAMES.default]:
|
|
1994
|
-
[TEMPLATE_NAMES.authForm]: authFormTemplate,
|
|
1995
|
-
[TEMPLATE_NAMES.passkeyUpsell]: passkeyUpsellTemplate,
|
|
1996
|
-
[TEMPLATE_NAMES.signedIn]: signedInTemplate,
|
|
1705
|
+
[TEMPLATE_NAMES$1.default]: default_default,
|
|
1997
1706
|
...options.templates ?? {}
|
|
1998
1707
|
},
|
|
1999
1708
|
cache: true,
|
|
@@ -2077,6 +1786,23 @@ function interpolate(template, args) {
|
|
|
2077
1786
|
});
|
|
2078
1787
|
}
|
|
2079
1788
|
//#endregion
|
|
1789
|
+
//#region src/orchestrator/template-names.ts
|
|
1790
|
+
/**
|
|
1791
|
+
* Names of the bundled Liquid templates the `<zitadel-login>` orchestrator
|
|
1792
|
+
* registers.
|
|
1793
|
+
*
|
|
1794
|
+
* This lives in its own module — separate from `liquid.ts` — so the public
|
|
1795
|
+
* barrel can re-export `TEMPLATE_NAMES` without dragging LiquidJS' `Liquid`
|
|
1796
|
+
* type (and its Node ambient-type requirements) into the published
|
|
1797
|
+
* declaration surface. See `liquid.ts` / the orchestrator barrel.
|
|
1798
|
+
*/
|
|
1799
|
+
const TEMPLATE_NAMES = {
|
|
1800
|
+
default: "default",
|
|
1801
|
+
authForm: "auth-form",
|
|
1802
|
+
passkeyUpsell: "passkey-upsell",
|
|
1803
|
+
signedIn: "signed-in"
|
|
1804
|
+
};
|
|
1805
|
+
//#endregion
|
|
2080
1806
|
//#region src/orchestrator/locales/en.ts
|
|
2081
1807
|
/**
|
|
2082
1808
|
* Minimal English locale dictionary.
|
|
@@ -2085,53 +1811,103 @@ function interpolate(template, args) {
|
|
|
2085
1811
|
* to the raw key (matches the spec in
|
|
2086
1812
|
* `docs/design/flowengine/flow-engine-guide.md`).
|
|
2087
1813
|
*
|
|
1814
|
+
* Text keys are auto-generated by the server from the flow definition:
|
|
1815
|
+
* - Step titles: `<step>.title`
|
|
1816
|
+
* - Step descriptions: `<step>.description`
|
|
1817
|
+
* - Field labels: `<step>.field.<field>`
|
|
1818
|
+
* - Action labels: `<step>.action.<action>`
|
|
1819
|
+
*
|
|
2088
1820
|
* Copy aligned to Figma screens file `xkvBjkOJ8ENuHdTGZHXezK` (May 2026).
|
|
2089
1821
|
* MVP only — multi-locale support is deferred.
|
|
2090
1822
|
*/
|
|
2091
1823
|
const en = {
|
|
2092
1824
|
"identifier.title": "Sign in",
|
|
1825
|
+
"identifier.description": "Enter your email to continue",
|
|
2093
1826
|
"identifier.field.email": "Work email",
|
|
2094
1827
|
"identifier.field.email.placeholder": "you@company.com",
|
|
2095
1828
|
"identifier.field.password": "Password",
|
|
1829
|
+
"identifier.action.submit": "Sign in",
|
|
1830
|
+
"identifier.action.continue": "Sign in",
|
|
2096
1831
|
"identifier.action.passkey": "Sign in with a passkey",
|
|
2097
1832
|
"identifier.action.register.lead": "Don't have an account? ",
|
|
2098
1833
|
"identifier.action.register.link": "Sign up",
|
|
1834
|
+
"authenticate.title": "Sign in",
|
|
1835
|
+
"authenticate.description": "Enter your password",
|
|
1836
|
+
"authenticate.field.password": "Password",
|
|
1837
|
+
"authenticate.action.submit": "Sign in",
|
|
1838
|
+
"choose-register.title": "Create your account",
|
|
1839
|
+
"choose-register.description": "Choose how you'd like to sign up",
|
|
1840
|
+
"choose-register.action.register-with-password": "Sign up with password",
|
|
1841
|
+
"choose-register.action.register-with-passkey": "Sign up with passkey",
|
|
1842
|
+
"collect-credentials.title": "Create your account",
|
|
1843
|
+
"collect-credentials.description": "Set up your email and password",
|
|
1844
|
+
"collect-credentials.field.email": "Work email",
|
|
1845
|
+
"collect-credentials.field.email.placeholder": "you@company.com",
|
|
1846
|
+
"collect-credentials.field.password": "Password",
|
|
1847
|
+
"collect-credentials.field.password.help": "At least 8 characters, including a symbol and number.",
|
|
1848
|
+
"collect-credentials.action.submit": "Sign up",
|
|
1849
|
+
"register-password.title": "Create your password",
|
|
1850
|
+
"register-password.description": "Choose a secure password for your account",
|
|
1851
|
+
"register-password.field.password": "Password",
|
|
1852
|
+
"register-password.field.password.help": "At least 8 characters, including a symbol and number.",
|
|
1853
|
+
"register-password.action.submit": "Sign up",
|
|
1854
|
+
"passkey-upsell.title": "Sign in faster next time",
|
|
1855
|
+
"passkey-upsell.description": "No password needed ever again.",
|
|
1856
|
+
"passkey-upsell.description.line1": "No password needed ever again.",
|
|
1857
|
+
"passkey-upsell.description.line2": "Sign in with Face ID, Touch ID, or PIN.",
|
|
1858
|
+
"passkey-upsell.action.passkey_register": "Set up passkey",
|
|
1859
|
+
"passkey-upsell.action.skip": "Skip for now",
|
|
1860
|
+
"passkey-upsell.action.setup": "Set up passkey",
|
|
1861
|
+
"collect-passkey-email.title": "Create your account",
|
|
1862
|
+
"collect-passkey-email.description": "Enter your email to set up a passkey",
|
|
1863
|
+
"collect-passkey-email.field.email": "Work email",
|
|
1864
|
+
"collect-passkey-email.field.email.placeholder": "you@company.com",
|
|
1865
|
+
"collect-passkey-email.action.submit": "Continue",
|
|
1866
|
+
"passkey-enroll.title": "Set up your passkey",
|
|
1867
|
+
"passkey-enroll.description": "Use Face ID, Touch ID, or your device PIN to create a passkey.",
|
|
1868
|
+
"passkey-enroll.action.passkey_register": "Set up passkey",
|
|
1869
|
+
"done.title": "You're signed in as",
|
|
1870
|
+
"done.description": "",
|
|
2099
1871
|
"password.title": "Sign in",
|
|
1872
|
+
"password.description": "Enter your password",
|
|
2100
1873
|
"password.field.password": "Password",
|
|
1874
|
+
"password.action.signin": "Sign in",
|
|
2101
1875
|
"password.action.passkey": "Sign in with a passkey",
|
|
2102
1876
|
"password.action.register.lead": "Don't have an account? ",
|
|
2103
1877
|
"password.action.register.link": "Sign up",
|
|
2104
1878
|
"register.title": "Create your account",
|
|
1879
|
+
"register.description": "",
|
|
2105
1880
|
"register.field.email": "Work email",
|
|
2106
1881
|
"register.field.email.placeholder": "you@company.com",
|
|
2107
1882
|
"register.field.password": "Password",
|
|
2108
1883
|
"register.field.password.help": "At least 8 characters, including a symbol and number.",
|
|
1884
|
+
"register.field.givenName": "Given name",
|
|
1885
|
+
"register.field.familyName": "Family name",
|
|
1886
|
+
"register.field.dateOfBirth": "Date of birth",
|
|
1887
|
+
"register.field.dateOfBirth.placeholder": "YYYY-MM-DD",
|
|
1888
|
+
"register.field.dateOfBirth.help": "Use YYYY-MM-DD.",
|
|
1889
|
+
"register.action.password": "Continue with password",
|
|
1890
|
+
"register.action.passkey": "Continue with a passkey",
|
|
2109
1891
|
"register.action.submit": "Sign up",
|
|
2110
1892
|
"register.action.sign_in.lead": "Already have an account? ",
|
|
2111
1893
|
"register.action.sign_in.link": "Sign in",
|
|
2112
|
-
"passkey-upsell.title": "Sign in faster next time",
|
|
2113
|
-
"passkey-upsell.description.line1": "No password needed ever again.",
|
|
2114
|
-
"passkey-upsell.description.line2": "Sign in with Face ID, Touch ID, or PIN.",
|
|
2115
|
-
"passkey-upsell.action.setup": "Set up passkey",
|
|
2116
|
-
"passkey-upsell.action.skip": "Skip for now",
|
|
2117
|
-
/** Figma `6594:630` setup-passkey annotations — form-level `<zl-alert>`. */
|
|
2118
|
-
"error.passkey_cancelled": "Passkey setup was cancelled",
|
|
2119
|
-
"error.passkey_not_registered": "This passkey is not registered. Please sign in with your email and password.",
|
|
2120
|
-
"error.passkey_setup_failed": "Passkey registration did not complete. Please try again.",
|
|
2121
|
-
"error.passkey_unsupported": "This device does not support passkeys",
|
|
2122
|
-
"error.passkey_failed": "Something went wrong. Please try again.",
|
|
2123
1894
|
"complete.title": "You're signed in as",
|
|
2124
1895
|
"signed-in.continue": "Continue",
|
|
2125
1896
|
"signed-in.logout": "Logout",
|
|
1897
|
+
"passkey-login.title": "Sign in with your passkey",
|
|
2126
1898
|
"recover.title": "Check your email",
|
|
2127
1899
|
"recover.description": "We sent a password reset link to your email address.",
|
|
2128
1900
|
"recover.action.back": "Back to sign in",
|
|
2129
|
-
"passkey-login.title": "Sign in with your passkey",
|
|
2130
1901
|
"submit.continue": "Continue",
|
|
2131
1902
|
"submit.signin": "Sign in",
|
|
2132
1903
|
"action.forgot_password": "Forgot password?",
|
|
2133
1904
|
"action.cancel": "Cancel",
|
|
2134
1905
|
"sso.redirect.title": "Redirecting to your provider…",
|
|
1906
|
+
"error.passkey_cancelled": "Passkey setup was cancelled",
|
|
1907
|
+
"error.passkey_not_registered": "This passkey is not registered. Please sign in with your email and password.",
|
|
1908
|
+
"error.passkey_setup_failed": "Passkey registration did not complete. Please try again.",
|
|
1909
|
+
"error.passkey_unsupported": "This device does not support passkeys",
|
|
1910
|
+
"error.passkey_failed": "Something went wrong. Please try again.",
|
|
2135
1911
|
"error.email_required": "Please enter an email address",
|
|
2136
1912
|
"error.email_invalid": "Please enter a valid email",
|
|
2137
1913
|
"error.password_required": "Please enter a password",
|
|
@@ -2147,47 +1923,92 @@ const en = {
|
|
|
2147
1923
|
//#region src/orchestrator/locales/de.ts
|
|
2148
1924
|
const de = {
|
|
2149
1925
|
"identifier.title": "Anmelden",
|
|
1926
|
+
"identifier.description": "Gib deine E-Mail-Adresse ein, um fortzufahren",
|
|
2150
1927
|
"identifier.field.email": "E-Mail",
|
|
2151
1928
|
"identifier.field.email.placeholder": "du@unternehmen.com",
|
|
2152
1929
|
"identifier.field.password": "Passwort",
|
|
1930
|
+
"identifier.action.submit": "Anmelden",
|
|
1931
|
+
"identifier.action.continue": "Anmelden",
|
|
2153
1932
|
"identifier.action.passkey": "Mit Passkey anmelden",
|
|
2154
1933
|
"identifier.action.register.lead": "Noch kein Konto? ",
|
|
2155
1934
|
"identifier.action.register.link": "Registrieren",
|
|
1935
|
+
"authenticate.title": "Anmelden",
|
|
1936
|
+
"authenticate.description": "Gib dein Passwort ein",
|
|
1937
|
+
"authenticate.field.password": "Passwort",
|
|
1938
|
+
"authenticate.action.submit": "Anmelden",
|
|
1939
|
+
"choose-register.title": "Konto erstellen",
|
|
1940
|
+
"choose-register.description": "Wähle, wie du dich registrieren möchtest",
|
|
1941
|
+
"choose-register.action.register-with-password": "Mit Passwort registrieren",
|
|
1942
|
+
"choose-register.action.register-with-passkey": "Mit Passkey registrieren",
|
|
1943
|
+
"collect-credentials.title": "Konto erstellen",
|
|
1944
|
+
"collect-credentials.description": "Richte E-Mail und Passwort ein",
|
|
1945
|
+
"collect-credentials.field.email": "E-Mail",
|
|
1946
|
+
"collect-credentials.field.email.placeholder": "du@unternehmen.com",
|
|
1947
|
+
"collect-credentials.field.password": "Passwort",
|
|
1948
|
+
"collect-credentials.field.password.help": "Mindestens 8 Zeichen, einschließlich eines Sonderzeichens und einer Zahl.",
|
|
1949
|
+
"collect-credentials.action.submit": "Registrieren",
|
|
1950
|
+
"register-password.title": "Passwort erstellen",
|
|
1951
|
+
"register-password.description": "Wähle ein sicheres Passwort für dein Konto",
|
|
1952
|
+
"register-password.field.password": "Passwort",
|
|
1953
|
+
"register-password.field.password.help": "Mindestens 8 Zeichen, einschließlich eines Sonderzeichens und einer Zahl.",
|
|
1954
|
+
"register-password.action.submit": "Registrieren",
|
|
1955
|
+
"passkey-upsell.title": "Nächstes Mal schneller anmelden",
|
|
1956
|
+
"passkey-upsell.description": "Kein Passwort mehr nötig.",
|
|
1957
|
+
"passkey-upsell.description.line1": "Kein Passwort mehr nötig.",
|
|
1958
|
+
"passkey-upsell.description.line2": "Melde dich mit Face ID, Touch ID oder PIN an.",
|
|
1959
|
+
"passkey-upsell.action.passkey_register": "Passkey einrichten",
|
|
1960
|
+
"passkey-upsell.action.skip": "Vorerst überspringen",
|
|
1961
|
+
"passkey-upsell.action.setup": "Passkey einrichten",
|
|
1962
|
+
"collect-passkey-email.title": "Konto erstellen",
|
|
1963
|
+
"collect-passkey-email.description": "Gib deine E-Mail-Adresse ein, um einen Passkey einzurichten",
|
|
1964
|
+
"collect-passkey-email.field.email": "E-Mail",
|
|
1965
|
+
"collect-passkey-email.field.email.placeholder": "du@unternehmen.com",
|
|
1966
|
+
"collect-passkey-email.action.submit": "Weiter",
|
|
1967
|
+
"passkey-enroll.title": "Passkey einrichten",
|
|
1968
|
+
"passkey-enroll.description": "Verwende Face ID, Touch ID oder die Geräte-PIN, um einen Passkey zu erstellen.",
|
|
1969
|
+
"passkey-enroll.action.passkey_register": "Passkey einrichten",
|
|
1970
|
+
"done.title": "Du bist angemeldet als",
|
|
1971
|
+
"done.description": "",
|
|
2156
1972
|
"password.title": "Anmelden",
|
|
1973
|
+
"password.description": "Gib dein Passwort ein",
|
|
2157
1974
|
"password.field.password": "Passwort",
|
|
1975
|
+
"password.action.signin": "Anmelden",
|
|
2158
1976
|
"password.action.passkey": "Mit Passkey anmelden",
|
|
2159
1977
|
"password.action.register.lead": "Noch kein Konto? ",
|
|
2160
1978
|
"password.action.register.link": "Registrieren",
|
|
2161
1979
|
"register.title": "Konto erstellen",
|
|
1980
|
+
"register.description": "",
|
|
2162
1981
|
"register.field.email": "E-Mail",
|
|
2163
1982
|
"register.field.email.placeholder": "du@unternehmen.com",
|
|
2164
1983
|
"register.field.password": "Passwort",
|
|
2165
1984
|
"register.field.password.help": "Mindestens 8 Zeichen, einschließlich eines Sonderzeichens und einer Zahl.",
|
|
1985
|
+
"register.field.givenName": "Vorname",
|
|
1986
|
+
"register.field.familyName": "Nachname",
|
|
1987
|
+
"register.field.dateOfBirth": "Geburtsdatum",
|
|
1988
|
+
"register.field.dateOfBirth.placeholder": "JJJJ-MM-TT",
|
|
1989
|
+
"register.field.dateOfBirth.help": "Verwende JJJJ-MM-TT.",
|
|
1990
|
+
"register.action.password": "Mit Passwort fortfahren",
|
|
1991
|
+
"register.action.passkey": "Weiter mit Passkey",
|
|
2166
1992
|
"register.action.submit": "Registrieren",
|
|
2167
1993
|
"register.action.sign_in.lead": "Bereits ein Konto? ",
|
|
2168
1994
|
"register.action.sign_in.link": "Anmelden",
|
|
2169
|
-
"passkey-upsell.title": "Nächstes Mal schneller anmelden",
|
|
2170
|
-
"passkey-upsell.description.line1": "Kein Passwort mehr nötig.",
|
|
2171
|
-
"passkey-upsell.description.line2": "Melde dich mit Face ID, Touch ID oder PIN an.",
|
|
2172
|
-
"passkey-upsell.action.setup": "Passkey einrichten",
|
|
2173
|
-
"passkey-upsell.action.skip": "Vorerst überspringen",
|
|
2174
|
-
"error.passkey_cancelled": "Passkey-Einrichtung wurde abgebrochen",
|
|
2175
|
-
"error.passkey_not_registered": "Dieser Passkey ist nicht registriert. Bitte melde dich mit E-Mail und Passwort an.",
|
|
2176
|
-
"error.passkey_setup_failed": "Passkey-Registrierung wurde nicht abgeschlossen. Bitte versuche es erneut.",
|
|
2177
|
-
"error.passkey_unsupported": "Dieses Gerät unterstützt keine Passkeys",
|
|
2178
|
-
"error.passkey_failed": "Etwas ist schiefgelaufen. Bitte versuche es erneut.",
|
|
2179
1995
|
"complete.title": "Du bist angemeldet als",
|
|
2180
1996
|
"signed-in.continue": "Weiter",
|
|
2181
1997
|
"signed-in.logout": "Abmelden",
|
|
1998
|
+
"passkey-login.title": "Mit Passkey anmelden",
|
|
2182
1999
|
"recover.title": "E-Mail prüfen",
|
|
2183
2000
|
"recover.description": "Wir haben einen Link zum Zurücksetzen des Passworts an deine E-Mail-Adresse gesendet.",
|
|
2184
2001
|
"recover.action.back": "Zurück zur Anmeldung",
|
|
2185
|
-
"passkey-login.title": "Mit Passkey anmelden",
|
|
2186
2002
|
"submit.continue": "Weiter",
|
|
2187
2003
|
"submit.signin": "Anmelden",
|
|
2188
2004
|
"action.forgot_password": "Passwort vergessen?",
|
|
2189
2005
|
"action.cancel": "Abbrechen",
|
|
2190
2006
|
"sso.redirect.title": "Weiterleitung zum Anbieter…",
|
|
2007
|
+
"error.passkey_cancelled": "Passkey-Einrichtung wurde abgebrochen",
|
|
2008
|
+
"error.passkey_not_registered": "Dieser Passkey ist nicht registriert. Bitte melde dich mit E-Mail und Passwort an.",
|
|
2009
|
+
"error.passkey_setup_failed": "Passkey-Registrierung wurde nicht abgeschlossen. Bitte versuche es erneut.",
|
|
2010
|
+
"error.passkey_unsupported": "Dieses Gerät unterstützt keine Passkeys",
|
|
2011
|
+
"error.passkey_failed": "Etwas ist schiefgelaufen. Bitte versuche es erneut.",
|
|
2191
2012
|
"error.email_required": "Bitte gib eine E-Mail-Adresse ein",
|
|
2192
2013
|
"error.email_invalid": "Bitte gib eine gültige E-Mail-Adresse ein",
|
|
2193
2014
|
"error.password_required": "Bitte gib ein Passwort ein",
|
|
@@ -2199,10 +2020,111 @@ const de = {
|
|
|
2199
2020
|
"error.sign_in_server.body": "Bitte versuche es in einigen Minuten erneut"
|
|
2200
2021
|
};
|
|
2201
2022
|
//#endregion
|
|
2023
|
+
//#region src/orchestrator/locales/it.ts
|
|
2024
|
+
const it = {
|
|
2025
|
+
"identifier.title": "Accedi",
|
|
2026
|
+
"identifier.description": "Inserisci la tua e-mail per continuare",
|
|
2027
|
+
"identifier.field.email": "E-mail aziendale",
|
|
2028
|
+
"identifier.field.email.placeholder": "tu@azienda.com",
|
|
2029
|
+
"identifier.field.password": "Password",
|
|
2030
|
+
"identifier.action.submit": "Accedi",
|
|
2031
|
+
"identifier.action.continue": "Accedi",
|
|
2032
|
+
"identifier.action.passkey": "Accedi con passkey",
|
|
2033
|
+
"identifier.action.register.lead": "Non hai un account? ",
|
|
2034
|
+
"identifier.action.register.link": "Registrati",
|
|
2035
|
+
"authenticate.title": "Accedi",
|
|
2036
|
+
"authenticate.description": "Inserisci la tua password",
|
|
2037
|
+
"authenticate.field.password": "Password",
|
|
2038
|
+
"authenticate.action.submit": "Accedi",
|
|
2039
|
+
"choose-register.title": "Crea il tuo account",
|
|
2040
|
+
"choose-register.description": "Scegli come registrarti",
|
|
2041
|
+
"choose-register.action.register-with-password": "Registrati con password",
|
|
2042
|
+
"choose-register.action.register-with-passkey": "Registrati con passkey",
|
|
2043
|
+
"collect-credentials.title": "Crea il tuo account",
|
|
2044
|
+
"collect-credentials.description": "Configura e-mail e password",
|
|
2045
|
+
"collect-credentials.field.email": "E-mail aziendale",
|
|
2046
|
+
"collect-credentials.field.email.placeholder": "tu@azienda.com",
|
|
2047
|
+
"collect-credentials.field.password": "Password",
|
|
2048
|
+
"collect-credentials.field.password.help": "Almeno 8 caratteri, incluso un simbolo e un numero.",
|
|
2049
|
+
"collect-credentials.action.submit": "Registrati",
|
|
2050
|
+
"register-password.title": "Crea la tua password",
|
|
2051
|
+
"register-password.description": "Scegli una password sicura per il tuo account",
|
|
2052
|
+
"register-password.field.password": "Password",
|
|
2053
|
+
"register-password.field.password.help": "Almeno 8 caratteri, incluso un simbolo e un numero.",
|
|
2054
|
+
"register-password.action.submit": "Registrati",
|
|
2055
|
+
"passkey-upsell.title": "Accedi più velocemente la prossima volta",
|
|
2056
|
+
"passkey-upsell.description": "Nessuna password necessaria.",
|
|
2057
|
+
"passkey-upsell.description.line1": "Nessuna password necessaria.",
|
|
2058
|
+
"passkey-upsell.description.line2": "Accedi con Face ID, Touch ID o PIN.",
|
|
2059
|
+
"passkey-upsell.action.passkey_register": "Configura passkey",
|
|
2060
|
+
"passkey-upsell.action.skip": "Salta per ora",
|
|
2061
|
+
"passkey-upsell.action.setup": "Configura passkey",
|
|
2062
|
+
"collect-passkey-email.title": "Crea il tuo account",
|
|
2063
|
+
"collect-passkey-email.description": "Inserisci la tua e-mail per configurare una passkey",
|
|
2064
|
+
"collect-passkey-email.field.email": "E-mail aziendale",
|
|
2065
|
+
"collect-passkey-email.field.email.placeholder": "tu@azienda.com",
|
|
2066
|
+
"collect-passkey-email.action.submit": "Continua",
|
|
2067
|
+
"passkey-enroll.title": "Configura la tua passkey",
|
|
2068
|
+
"passkey-enroll.description": "Usa Face ID, Touch ID o il PIN del dispositivo per creare una passkey.",
|
|
2069
|
+
"passkey-enroll.action.passkey_register": "Configura passkey",
|
|
2070
|
+
"done.title": "Sei connesso come",
|
|
2071
|
+
"done.description": "",
|
|
2072
|
+
"password.title": "Accedi",
|
|
2073
|
+
"password.description": "Inserisci la tua password",
|
|
2074
|
+
"password.field.password": "Password",
|
|
2075
|
+
"password.action.signin": "Accedi",
|
|
2076
|
+
"password.action.passkey": "Accedi con passkey",
|
|
2077
|
+
"password.action.register.lead": "Non hai un account? ",
|
|
2078
|
+
"password.action.register.link": "Registrati",
|
|
2079
|
+
"register.title": "Crea il tuo account",
|
|
2080
|
+
"register.description": "",
|
|
2081
|
+
"register.field.email": "E-mail aziendale",
|
|
2082
|
+
"register.field.email.placeholder": "tu@azienda.com",
|
|
2083
|
+
"register.field.password": "Password",
|
|
2084
|
+
"register.field.password.help": "Almeno 8 caratteri, incluso un simbolo e un numero.",
|
|
2085
|
+
"register.field.givenName": "Nome",
|
|
2086
|
+
"register.field.familyName": "Cognome",
|
|
2087
|
+
"register.field.dateOfBirth": "Data di nascita",
|
|
2088
|
+
"register.field.dateOfBirth.placeholder": "AAAA-MM-GG",
|
|
2089
|
+
"register.field.dateOfBirth.help": "Usa AAAA-MM-GG.",
|
|
2090
|
+
"register.action.password": "Continua con password",
|
|
2091
|
+
"register.action.passkey": "Continua con passkey",
|
|
2092
|
+
"register.action.submit": "Registrati",
|
|
2093
|
+
"register.action.sign_in.lead": "Hai già un account? ",
|
|
2094
|
+
"register.action.sign_in.link": "Accedi",
|
|
2095
|
+
"complete.title": "Sei connesso come",
|
|
2096
|
+
"signed-in.continue": "Continua",
|
|
2097
|
+
"signed-in.logout": "Esci",
|
|
2098
|
+
"passkey-login.title": "Accedi con la tua passkey",
|
|
2099
|
+
"recover.title": "Controlla la tua e-mail",
|
|
2100
|
+
"recover.description": "Abbiamo inviato un link per reimpostare la password al tuo indirizzo e-mail.",
|
|
2101
|
+
"recover.action.back": "Torna all'accesso",
|
|
2102
|
+
"submit.continue": "Continua",
|
|
2103
|
+
"submit.signin": "Accedi",
|
|
2104
|
+
"action.forgot_password": "Password dimenticata?",
|
|
2105
|
+
"action.cancel": "Annulla",
|
|
2106
|
+
"sso.redirect.title": "Reindirizzamento al provider…",
|
|
2107
|
+
"error.passkey_cancelled": "La configurazione della passkey è stata annullata",
|
|
2108
|
+
"error.passkey_not_registered": "Questa passkey non è registrata. Accedi con e-mail e password.",
|
|
2109
|
+
"error.passkey_setup_failed": "La registrazione della passkey non è stata completata. Riprova.",
|
|
2110
|
+
"error.passkey_unsupported": "Questo dispositivo non supporta le passkey",
|
|
2111
|
+
"error.passkey_failed": "Qualcosa è andato storto. Riprova.",
|
|
2112
|
+
"error.email_required": "Inserisci un indirizzo e-mail",
|
|
2113
|
+
"error.email_invalid": "Inserisci un indirizzo e-mail valido",
|
|
2114
|
+
"error.password_required": "Inserisci una password",
|
|
2115
|
+
"error.password_incorrect": "E-mail o password errata.",
|
|
2116
|
+
"error.email_exists": "Esiste già un account con questo indirizzo e-mail.",
|
|
2117
|
+
"error.invalid_credentials": "E-mail o password errata.",
|
|
2118
|
+
"error.required": "Questo campo è obbligatorio.",
|
|
2119
|
+
"error.sign_in_server.title": "Non è stato possibile completare l'accesso.",
|
|
2120
|
+
"error.sign_in_server.body": "Riprova tra qualche minuto"
|
|
2121
|
+
};
|
|
2122
|
+
//#endregion
|
|
2202
2123
|
//#region src/orchestrator/locales/index.ts
|
|
2203
2124
|
const builtinLocales = {
|
|
2204
2125
|
en,
|
|
2205
|
-
de
|
|
2126
|
+
de,
|
|
2127
|
+
it
|
|
2206
2128
|
};
|
|
2207
2129
|
//#endregion
|
|
2208
2130
|
//#region ../shared-component-styles/dist/attribution-markup.mjs
|
|
@@ -2293,6 +2215,7 @@ const COMMON_ATTRS = [
|
|
|
2293
2215
|
"style",
|
|
2294
2216
|
"name",
|
|
2295
2217
|
"for",
|
|
2218
|
+
"data-testid",
|
|
2296
2219
|
"data-theme",
|
|
2297
2220
|
"hidden"
|
|
2298
2221
|
];
|
|
@@ -2349,6 +2272,9 @@ function createSanitiser() {
|
|
|
2349
2272
|
};
|
|
2350
2273
|
}
|
|
2351
2274
|
//#endregion
|
|
2275
|
+
//#region src/orchestrator/templates/layout-chrome.css?inline
|
|
2276
|
+
var layout_chrome_default = ":host {\n background: var(--zl-color-surface-default-black, #0f0f11);\n min-height: 100%;\n color: var(--zl-color-text-primary-white, #f4f4f6);\n font-family: var(--zl-font-family-sans, system-ui, sans-serif);\n display: block;\n}\n\n.zl-mount {\n background: inherit;\n min-height: 100vh;\n color: inherit;\n flex-direction: column;\n display: flex;\n}\n\n.zl-mount > zl-page-shell, .zl-mount > [data-zl-template-root] {\n flex: auto;\n}\n\n.zl-attribution {\n background: none;\n justify-content: center;\n align-items: center;\n display: flex;\n}\n\n.zl-attribution[hidden] {\n display: none;\n}\n\n.zl-card-title {\n font-family: var(--zl-font-family-heading, var(--zl-font-family-sans, system-ui, sans-serif));\n letter-spacing: -.02em;\n color: var(--zl-color-text-primary-white, #f4f4f6);\n text-align: left;\n margin: 0;\n font-size: 2rem;\n font-weight: 400;\n line-height: 2.5rem;\n}\n\n.zl-card-subtitle {\n font-family: var(--zl-font-family-sans, system-ui, sans-serif);\n color: var(--zl-color-text-primary-white, #f4f4f6);\n margin: 0;\n font-size: .875rem;\n font-weight: 400;\n line-height: 1.25rem;\n}\n\n.zl-card-nav {\n font-family: var(--zl-font-family-sans, system-ui, sans-serif);\n color: var(--zl-color-text-primary-white, #f4f4f6);\n text-align: left;\n margin: 0;\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5rem;\n}\n\n.zl-card-nav__link {\n font: inherit;\n line-height: inherit;\n color: var(--zl-color-icon-default-purple, #bba5e4);\n cursor: pointer;\n background: none;\n border: none;\n margin: 0;\n padding: 0;\n text-decoration: none;\n display: inline;\n}\n\n.zl-card-nav__link:hover {\n text-decoration: underline;\n}\n\n.zl-card-nav__link:focus-visible {\n outline: var(--zl-focus-width, 2px) solid var(--zl-focus-color, #f4f4f6);\n outline-offset: var(--zl-focus-offset, 2px);\n}\n\n.zl-card-forgot {\n text-align: left;\n margin: 0;\n}\n\n.zl-card-forgot__link {\n font-family: var(--zl-font-family-sans, system-ui, sans-serif);\n color: var(--zl-color-icon-default-purple, #bba5e4);\n cursor: pointer;\n background: none;\n border: none;\n margin: 0;\n padding: 0;\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5rem;\n text-decoration: none;\n display: inline;\n}\n\n.zl-card-forgot__link:hover {\n text-decoration: underline;\n}\n\n.zl-card-forgot__link:focus-visible {\n outline: var(--zl-focus-width, 2px) solid var(--zl-focus-color, #f4f4f6);\n outline-offset: var(--zl-focus-offset, 2px);\n}\n";
|
|
2277
|
+
//#endregion
|
|
2352
2278
|
//#region src/orchestrator/theme-controller.ts
|
|
2353
2279
|
const DARK_QUERY = "(prefers-color-scheme: dark)";
|
|
2354
2280
|
var ThemeController = class {
|
|
@@ -2430,6 +2356,27 @@ let ZitadelLogin = class ZitadelLogin extends LitElement {
|
|
|
2430
2356
|
set project(value) {
|
|
2431
2357
|
this.#_project_accessor_storage = value;
|
|
2432
2358
|
}
|
|
2359
|
+
#_projectId_accessor_storage = "";
|
|
2360
|
+
get projectId() {
|
|
2361
|
+
return this.#_projectId_accessor_storage;
|
|
2362
|
+
}
|
|
2363
|
+
set projectId(value) {
|
|
2364
|
+
this.#_projectId_accessor_storage = value;
|
|
2365
|
+
}
|
|
2366
|
+
#_proxyPath_accessor_storage = "";
|
|
2367
|
+
get proxyPath() {
|
|
2368
|
+
return this.#_proxyPath_accessor_storage;
|
|
2369
|
+
}
|
|
2370
|
+
set proxyPath(value) {
|
|
2371
|
+
this.#_proxyPath_accessor_storage = value;
|
|
2372
|
+
}
|
|
2373
|
+
#_url_accessor_storage = "";
|
|
2374
|
+
get url() {
|
|
2375
|
+
return this.#_url_accessor_storage;
|
|
2376
|
+
}
|
|
2377
|
+
set url(value) {
|
|
2378
|
+
this.#_url_accessor_storage = value;
|
|
2379
|
+
}
|
|
2433
2380
|
#_postSignInUrl_accessor_storage = "";
|
|
2434
2381
|
get postSignInUrl() {
|
|
2435
2382
|
return this.#_postSignInUrl_accessor_storage;
|
|
@@ -2506,7 +2453,7 @@ let ZitadelLogin = class ZitadelLogin extends LitElement {
|
|
|
2506
2453
|
if (root instanceof ShadowRoot) {
|
|
2507
2454
|
const existing = Array.isArray(root.adoptedStyleSheets) ? root.adoptedStyleSheets : [];
|
|
2508
2455
|
const sheet = new CSSStyleSheet();
|
|
2509
|
-
sheet.replaceSync(
|
|
2456
|
+
sheet.replaceSync(layout_chrome_default);
|
|
2510
2457
|
root.adoptedStyleSheets = [...existing, sheet];
|
|
2511
2458
|
root.addEventListener("zl-input", this.handleAtomInput);
|
|
2512
2459
|
root.addEventListener("zl-submit", this.handleAtomSubmit);
|
|
@@ -2535,9 +2482,12 @@ let ZitadelLogin = class ZitadelLogin extends LitElement {
|
|
|
2535
2482
|
* resolved language is used as the base; entries from the `locales` map (if
|
|
2536
2483
|
* set) are spread on top so partial overrides work without importing and
|
|
2537
2484
|
* spreading the full base dictionary.
|
|
2485
|
+
*
|
|
2486
|
+
* Priority: explicit `lang` attr → `navigator.language` (user preference)
|
|
2487
|
+
* → `document.documentElement.lang` (page default) → English fallback.
|
|
2538
2488
|
*/
|
|
2539
2489
|
resolveLocale() {
|
|
2540
|
-
const primary = ((this.lang || (typeof
|
|
2490
|
+
const primary = ((this.lang || (typeof navigator !== "undefined" ? navigator.language : "") || (typeof document !== "undefined" ? document.documentElement.lang : "")).split("-")[0] ?? "").toLowerCase();
|
|
2541
2491
|
const builtin = builtinLocales[primary] ?? en;
|
|
2542
2492
|
const custom = this.locales?.[primary];
|
|
2543
2493
|
return custom ? {
|
|
@@ -2559,10 +2509,21 @@ let ZitadelLogin = class ZitadelLogin extends LitElement {
|
|
|
2559
2509
|
}
|
|
2560
2510
|
updated(changed) {
|
|
2561
2511
|
if (!changed.has("response")) return;
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2512
|
+
this.hydrateStepAfterRender();
|
|
2513
|
+
}
|
|
2514
|
+
/**
|
|
2515
|
+
* Apply captured values and move focus once the new step has fully
|
|
2516
|
+
* rendered. This commit produces the step's `zl-field`/`zl-button` atoms,
|
|
2517
|
+
* but those render their own shadow DOM on a later microtask — so await
|
|
2518
|
+
* this element's update *and* the child atoms' first render before touching
|
|
2519
|
+
* them, rather than guessing a frame with `requestAnimationFrame`.
|
|
2520
|
+
*/
|
|
2521
|
+
async hydrateStepAfterRender() {
|
|
2522
|
+
await this.updateComplete;
|
|
2523
|
+
const atoms = this.shadowRoot?.querySelectorAll("zl-field, zl-button");
|
|
2524
|
+
if (atoms) await Promise.all(Array.from(atoms).map((atom) => atom.updateComplete));
|
|
2525
|
+
this.applyValuesToFields();
|
|
2526
|
+
this.moveFocusToFirstField();
|
|
2566
2527
|
}
|
|
2567
2528
|
render() {
|
|
2568
2529
|
if (this.startupError) return html`<form class="zl-mount" novalidate>
|
|
@@ -2586,6 +2547,10 @@ let ZitadelLogin = class ZitadelLogin extends LitElement {
|
|
|
2586
2547
|
* Figma sign-in frame where the pill sits 24px below the card, both
|
|
2587
2548
|
* centred on the page). It can't be a sibling of the page-shell because
|
|
2588
2549
|
* the page-shell already occupies the full viewport height.
|
|
2550
|
+
*
|
|
2551
|
+
* This markup is appended AFTER `renderStep` has sanitised the Liquid
|
|
2552
|
+
* output, so it is not run through DOMPurify. It is orchestrator-owned and
|
|
2553
|
+
* any tenant-supplied values (`custom_link`) are escaped via `escapeHtml`.
|
|
2589
2554
|
*/
|
|
2590
2555
|
injectAttribution(rendered) {
|
|
2591
2556
|
const html = this.renderAttributionHtml();
|
|
@@ -2605,23 +2570,28 @@ let ZitadelLogin = class ZitadelLogin extends LitElement {
|
|
|
2605
2570
|
const show = attribution?.show_zitadel !== false;
|
|
2606
2571
|
const custom = attribution?.custom_link;
|
|
2607
2572
|
if (!show && !custom) return "";
|
|
2608
|
-
if (custom) return `<div slot="footer" part="attribution" class="zl-attribution"><zl-pill tone="neutral" href="${String(custom.href)
|
|
2573
|
+
if (custom) return `<div slot="footer" part="attribution" class="zl-attribution"><zl-pill tone="neutral" href="${escapeHtml(String(custom.href))}">${escapeHtml(String(custom.label))}</zl-pill></div>`;
|
|
2609
2574
|
return `<div slot="footer" part="attribution" class="zl-attribution"><zl-pill tone="neutral" href="https://zitadel.com" part="attribution-pill" aria-label="Secured with Zitadel">${zitadelAttributionPillInnerHtml()}</zl-pill></div>`;
|
|
2610
2575
|
}
|
|
2576
|
+
/** Declarative config read from this element's attributes. */
|
|
2577
|
+
get projectAttrs() {
|
|
2578
|
+
return {
|
|
2579
|
+
projectId: this.projectId,
|
|
2580
|
+
proxyPath: this.proxyPath,
|
|
2581
|
+
url: this.url
|
|
2582
|
+
};
|
|
2583
|
+
}
|
|
2611
2584
|
async startFlow() {
|
|
2612
|
-
const cfg = this.project ?? getZitadelConfig();
|
|
2613
|
-
const projectId = cfg?.projectId || "";
|
|
2614
|
-
if (!cfg) throw new Error("<zitadel-login> requires a `config` prop (from configureZitadel()) or configureZitadel() must be called before use.");
|
|
2615
|
-
const api = getApi(cfg);
|
|
2616
2585
|
this.loading = true;
|
|
2617
2586
|
this.startupError = null;
|
|
2618
2587
|
try {
|
|
2588
|
+
const { project: cfg, api } = resolveApi(this.project, this.projectAttrs, "<zitadel-login>");
|
|
2619
2589
|
let wire;
|
|
2620
2590
|
if (this.resumeFlowId) wire = await getCurrentStep(api, this.resumeFlowId);
|
|
2621
2591
|
else {
|
|
2622
|
-
if (!projectId) throw new Error("<zitadel-login> requires a `project-id` attribute (or
|
|
2592
|
+
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.");
|
|
2623
2593
|
wire = await startFlow(api, {
|
|
2624
|
-
project_id: projectId,
|
|
2594
|
+
project_id: cfg.projectId,
|
|
2625
2595
|
purpose: this.purpose
|
|
2626
2596
|
});
|
|
2627
2597
|
}
|
|
@@ -2659,16 +2629,12 @@ let ZitadelLogin = class ZitadelLogin extends LitElement {
|
|
|
2659
2629
|
async maybeCompleteFlow(response) {
|
|
2660
2630
|
const behavior = response.step.complete;
|
|
2661
2631
|
if (!behavior) return;
|
|
2662
|
-
this
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
handoff_token: response.handoff_token,
|
|
2669
|
-
handoff_token_expires_at: response.handoff_token_expires_at
|
|
2670
|
-
}
|
|
2671
|
-
}));
|
|
2632
|
+
emit(this, "zitadel-flow-complete", {
|
|
2633
|
+
behavior,
|
|
2634
|
+
redirect_uri: response.redirect_uri,
|
|
2635
|
+
handoff_token: response.handoff_token,
|
|
2636
|
+
handoff_token_expires_at: response.handoff_token_expires_at
|
|
2637
|
+
});
|
|
2672
2638
|
if (typeof window === "undefined") return;
|
|
2673
2639
|
if (behavior === "redirect" && response.redirect_uri) {
|
|
2674
2640
|
window.location.assign(response.redirect_uri);
|
|
@@ -2678,9 +2644,8 @@ let ZitadelLogin = class ZitadelLogin extends LitElement {
|
|
|
2678
2644
|
if (behavior === "show" && handoffToken && this.postSignInUrl) {
|
|
2679
2645
|
this.loading = true;
|
|
2680
2646
|
try {
|
|
2681
|
-
const cfg = this.project
|
|
2682
|
-
|
|
2683
|
-
await exchangeSession(getApi(cfg), { handoff_token: handoffToken }, { project_id: cfg.projectId });
|
|
2647
|
+
const { project: cfg, api } = resolveApi(this.project, this.projectAttrs, "<zitadel-login>");
|
|
2648
|
+
await exchangeSession(api, { handoff_token: handoffToken }, { project_id: cfg.projectId });
|
|
2684
2649
|
window.location.assign(this.postSignInUrl);
|
|
2685
2650
|
} catch (error) {
|
|
2686
2651
|
this.handleTransportError(error);
|
|
@@ -2692,14 +2657,16 @@ let ZitadelLogin = class ZitadelLogin extends LitElement {
|
|
|
2692
2657
|
renderStep(step, engine) {
|
|
2693
2658
|
const tenantSource = typeof this.branding?.liquid_template === "string" && this.branding.liquid_template.length > 0 ? this.branding.liquid_template : null;
|
|
2694
2659
|
const errors = step.error ? step.error.startsWith("error.") ? [{ text_key: step.error }] : [{ message: step.error }] : [];
|
|
2660
|
+
const fields = step.fields ?? [];
|
|
2661
|
+
const actions = step.actions ?? [];
|
|
2695
2662
|
const context = {
|
|
2696
2663
|
step: {
|
|
2697
2664
|
name: step.name,
|
|
2698
2665
|
complete: step.complete,
|
|
2699
2666
|
texts: step.texts ?? {}
|
|
2700
2667
|
},
|
|
2701
|
-
fields
|
|
2702
|
-
actions
|
|
2668
|
+
fields,
|
|
2669
|
+
actions,
|
|
2703
2670
|
gates: step.gates ?? {},
|
|
2704
2671
|
sso_providers: step.sso_providers ?? [],
|
|
2705
2672
|
challenge: step.challenge ?? null,
|
|
@@ -2758,6 +2725,31 @@ let ZitadelLogin = class ZitadelLogin extends LitElement {
|
|
|
2758
2725
|
if (field.value !== next) field.value = next;
|
|
2759
2726
|
}
|
|
2760
2727
|
}
|
|
2728
|
+
captureValuesFromFields() {
|
|
2729
|
+
const root = this.shadowRoot;
|
|
2730
|
+
if (!root) return this.formValues;
|
|
2731
|
+
const fields = root.querySelectorAll("zl-field");
|
|
2732
|
+
if (fields.length === 0) return this.formValues;
|
|
2733
|
+
const next = { ...this.formValues };
|
|
2734
|
+
let changed = false;
|
|
2735
|
+
for (const field of fields) {
|
|
2736
|
+
const name = field.getAttribute("name");
|
|
2737
|
+
const value = this.currentFieldValue(field);
|
|
2738
|
+
if (!name || value === void 0) continue;
|
|
2739
|
+
if (field.value !== value) field.value = value;
|
|
2740
|
+
if (next[name] !== value) {
|
|
2741
|
+
next[name] = value;
|
|
2742
|
+
changed = true;
|
|
2743
|
+
}
|
|
2744
|
+
}
|
|
2745
|
+
if (changed) this.formValues = next;
|
|
2746
|
+
return next;
|
|
2747
|
+
}
|
|
2748
|
+
currentFieldValue(field) {
|
|
2749
|
+
const native = field.shadowRoot?.querySelector("input");
|
|
2750
|
+
if (native && native.value !== field.value) return native.value;
|
|
2751
|
+
return typeof field.value === "string" ? field.value : void 0;
|
|
2752
|
+
}
|
|
2761
2753
|
handleAtomInput = (event) => {
|
|
2762
2754
|
if (!event.detail) return;
|
|
2763
2755
|
const { name, value } = event.detail;
|
|
@@ -2766,15 +2758,23 @@ let ZitadelLogin = class ZitadelLogin extends LitElement {
|
|
|
2766
2758
|
...this.formValues,
|
|
2767
2759
|
[name]: value
|
|
2768
2760
|
};
|
|
2769
|
-
this.
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
value
|
|
2775
|
-
}
|
|
2776
|
-
}));
|
|
2761
|
+
this.syncFieldElementValue(name, value);
|
|
2762
|
+
emit(this, "zitadel-flow-input", {
|
|
2763
|
+
name,
|
|
2764
|
+
value
|
|
2765
|
+
});
|
|
2777
2766
|
};
|
|
2767
|
+
syncFieldElementValue(name, value) {
|
|
2768
|
+
const root = this.shadowRoot;
|
|
2769
|
+
if (!root) return;
|
|
2770
|
+
const fields = root.querySelectorAll("zl-field");
|
|
2771
|
+
for (const field of fields) {
|
|
2772
|
+
if (field.getAttribute("name") !== name) continue;
|
|
2773
|
+
if (field.value !== value) field.value = value;
|
|
2774
|
+
const native = field.shadowRoot?.querySelector("input");
|
|
2775
|
+
if (native && native.value !== value) native.value = value;
|
|
2776
|
+
}
|
|
2777
|
+
}
|
|
2778
2778
|
handleAtomSubmit = (event) => {
|
|
2779
2779
|
if (this.loading) return;
|
|
2780
2780
|
this.submit(event.detail?.action ?? null);
|
|
@@ -2802,7 +2802,7 @@ let ZitadelLogin = class ZitadelLogin extends LitElement {
|
|
|
2802
2802
|
handlePasskeyResult = (event) => {
|
|
2803
2803
|
if (this.loading) return;
|
|
2804
2804
|
const { challenge_id, method, proof } = event.detail;
|
|
2805
|
-
this.submit(
|
|
2805
|
+
this.submit(method, {
|
|
2806
2806
|
challenge_id,
|
|
2807
2807
|
method,
|
|
2808
2808
|
proof
|
|
@@ -2844,21 +2844,20 @@ let ZitadelLogin = class ZitadelLogin extends LitElement {
|
|
|
2844
2844
|
moveFocusToFirstField() {
|
|
2845
2845
|
const root = this.shadowRoot;
|
|
2846
2846
|
if (!root) return;
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
Array.from(focusables).find((el) => !el.hasAttribute("disabled"))?.focus();
|
|
2850
|
-
});
|
|
2847
|
+
const focusables = root.querySelectorAll("zl-field, zl-button");
|
|
2848
|
+
Array.from(focusables).find((el) => !el.hasAttribute("disabled"))?.focus();
|
|
2851
2849
|
}
|
|
2852
2850
|
async submit(action, challengeResponse) {
|
|
2853
2851
|
if (!this.response || this.loading) return;
|
|
2854
2852
|
const { id, session_token } = this.response;
|
|
2855
2853
|
this.loading = true;
|
|
2856
2854
|
try {
|
|
2857
|
-
const
|
|
2855
|
+
const formValues = this.captureValuesFromFields();
|
|
2856
|
+
const stepFields = this.response.step.fields ?? [];
|
|
2858
2857
|
const fields = {};
|
|
2859
|
-
for (const
|
|
2860
|
-
const value =
|
|
2861
|
-
if (value !== void 0) fields[
|
|
2858
|
+
for (const f of stepFields) {
|
|
2859
|
+
const value = formValues[f.name];
|
|
2860
|
+
if (value !== void 0) fields[f.name] = value;
|
|
2862
2861
|
}
|
|
2863
2862
|
const body = {
|
|
2864
2863
|
session_token,
|
|
@@ -2866,15 +2865,10 @@ let ZitadelLogin = class ZitadelLogin extends LitElement {
|
|
|
2866
2865
|
fields,
|
|
2867
2866
|
...challengeResponse ? { challenge_response: challengeResponse } : {}
|
|
2868
2867
|
};
|
|
2869
|
-
const
|
|
2870
|
-
|
|
2871
|
-
const wire = await submitStep(getApi(cfg), id, body);
|
|
2868
|
+
const { api } = resolveApi(this.project, this.projectAttrs, "<zitadel-login>");
|
|
2869
|
+
const wire = await submitStep(api, id, body);
|
|
2872
2870
|
this.applyResponse(wire);
|
|
2873
|
-
this
|
|
2874
|
-
bubbles: true,
|
|
2875
|
-
composed: true,
|
|
2876
|
-
detail: { step: wire.step }
|
|
2877
|
-
}));
|
|
2871
|
+
emit(this, "zitadel-flow-step", { step: wire.step });
|
|
2878
2872
|
} catch (error) {
|
|
2879
2873
|
this.handleTransportError(error);
|
|
2880
2874
|
} finally {
|
|
@@ -2885,15 +2879,20 @@ let ZitadelLogin = class ZitadelLogin extends LitElement {
|
|
|
2885
2879
|
const message = error instanceof Error ? error.message : "Unexpected error contacting the Flow API.";
|
|
2886
2880
|
this.startupError = message;
|
|
2887
2881
|
console.error("[zitadel-login]", error);
|
|
2888
|
-
this
|
|
2889
|
-
bubbles: true,
|
|
2890
|
-
composed: true,
|
|
2891
|
-
detail: { message }
|
|
2892
|
-
}));
|
|
2882
|
+
emit(this, "zitadel-flow-error", { message });
|
|
2893
2883
|
}
|
|
2894
2884
|
};
|
|
2895
2885
|
__decorate([property({ type: String })], ZitadelLogin.prototype, "purpose", null);
|
|
2896
2886
|
__decorate([property({ attribute: false })], ZitadelLogin.prototype, "project", null);
|
|
2887
|
+
__decorate([property({
|
|
2888
|
+
type: String,
|
|
2889
|
+
attribute: "project-id"
|
|
2890
|
+
})], ZitadelLogin.prototype, "projectId", null);
|
|
2891
|
+
__decorate([property({
|
|
2892
|
+
type: String,
|
|
2893
|
+
attribute: "proxy-path"
|
|
2894
|
+
})], ZitadelLogin.prototype, "proxyPath", null);
|
|
2895
|
+
__decorate([property({ type: String })], ZitadelLogin.prototype, "url", null);
|
|
2897
2896
|
__decorate([property({
|
|
2898
2897
|
type: String,
|
|
2899
2898
|
attribute: "post-sign-in-url"
|
|
@@ -2913,7 +2912,7 @@ ZitadelLogin = __decorate([customElement("zitadel-login")], ZitadelLogin);
|
|
|
2913
2912
|
function collectInitialValues(step) {
|
|
2914
2913
|
const values = {};
|
|
2915
2914
|
if (!step.fields) return values;
|
|
2916
|
-
for (const
|
|
2915
|
+
for (const field of step.fields) values[field.name] = typeof field.value === "string" ? field.value : "";
|
|
2917
2916
|
return values;
|
|
2918
2917
|
}
|
|
2919
2918
|
//#endregion
|
|
@@ -3064,6 +3063,27 @@ let ZitadelLogout = class ZitadelLogout extends LitElement {
|
|
|
3064
3063
|
set project(value) {
|
|
3065
3064
|
this.#_project_accessor_storage = value;
|
|
3066
3065
|
}
|
|
3066
|
+
#_projectId_accessor_storage = "";
|
|
3067
|
+
get projectId() {
|
|
3068
|
+
return this.#_projectId_accessor_storage;
|
|
3069
|
+
}
|
|
3070
|
+
set projectId(value) {
|
|
3071
|
+
this.#_projectId_accessor_storage = value;
|
|
3072
|
+
}
|
|
3073
|
+
#_proxyPath_accessor_storage = "";
|
|
3074
|
+
get proxyPath() {
|
|
3075
|
+
return this.#_proxyPath_accessor_storage;
|
|
3076
|
+
}
|
|
3077
|
+
set proxyPath(value) {
|
|
3078
|
+
this.#_proxyPath_accessor_storage = value;
|
|
3079
|
+
}
|
|
3080
|
+
#_url_accessor_storage = "";
|
|
3081
|
+
get url() {
|
|
3082
|
+
return this.#_url_accessor_storage;
|
|
3083
|
+
}
|
|
3084
|
+
set url(value) {
|
|
3085
|
+
this.#_url_accessor_storage = value;
|
|
3086
|
+
}
|
|
3067
3087
|
#_postSignOutUrl_accessor_storage = "";
|
|
3068
3088
|
get postSignOutUrl() {
|
|
3069
3089
|
return this.#_postSignOutUrl_accessor_storage;
|
|
@@ -3190,22 +3210,25 @@ let ZitadelLogout = class ZitadelLogout extends LitElement {
|
|
|
3190
3210
|
this.errorMessage = "";
|
|
3191
3211
|
}
|
|
3192
3212
|
/**
|
|
3193
|
-
* Calls
|
|
3194
|
-
*
|
|
3195
|
-
* `Set-Cookie: Max-Age=0
|
|
3196
|
-
* and optionally navigates to `postSignOutUrl`.
|
|
3213
|
+
* Calls `DELETE /sessions/me` (`revokeMySession`) with `credentials: "include"`.
|
|
3214
|
+
* The server validates the `__nextgen_session` cookie, deletes the session, and
|
|
3215
|
+
* clears the cookie via `Set-Cookie: Max-Age=0`. On success this element fires
|
|
3216
|
+
* `zitadel-signout` and optionally navigates to `postSignOutUrl`.
|
|
3197
3217
|
*/
|
|
3218
|
+
/** Declarative config read from this element's attributes. */
|
|
3219
|
+
get projectAttrs() {
|
|
3220
|
+
return {
|
|
3221
|
+
projectId: this.projectId,
|
|
3222
|
+
proxyPath: this.proxyPath,
|
|
3223
|
+
url: this.url
|
|
3224
|
+
};
|
|
3225
|
+
}
|
|
3198
3226
|
async doLogout() {
|
|
3199
3227
|
this.loading = true;
|
|
3200
3228
|
this.errorMessage = "";
|
|
3201
|
-
const params = {
|
|
3202
|
-
...this.clientId ? { client_id: this.clientId } : {},
|
|
3203
|
-
...this.postSignOutUrl ? { post_logout_redirect_uri: this.postSignOutUrl } : {}
|
|
3204
|
-
};
|
|
3205
3229
|
try {
|
|
3206
|
-
const
|
|
3207
|
-
|
|
3208
|
-
await getApi(cfg).endSession(params, { credentials: "include" });
|
|
3230
|
+
const { api } = resolveApi(this.project, this.projectAttrs, "<zitadel-logout>");
|
|
3231
|
+
await api.revokeMySession({ credentials: "include" });
|
|
3209
3232
|
} catch (error) {
|
|
3210
3233
|
const message = error instanceof Error ? error.message : "";
|
|
3211
3234
|
this.errorMessage = message || "Sign-out failed. Please try again.";
|
|
@@ -3214,15 +3237,10 @@ let ZitadelLogout = class ZitadelLogout extends LitElement {
|
|
|
3214
3237
|
}
|
|
3215
3238
|
this.open = false;
|
|
3216
3239
|
this.loading = false;
|
|
3217
|
-
|
|
3240
|
+
emit(this, "zitadel-signout", {
|
|
3218
3241
|
name: this.displayName,
|
|
3219
3242
|
email: this.displayEmail
|
|
3220
|
-
};
|
|
3221
|
-
this.dispatchEvent(new CustomEvent("zitadel-signout", {
|
|
3222
|
-
bubbles: true,
|
|
3223
|
-
composed: true,
|
|
3224
|
-
detail
|
|
3225
|
-
}));
|
|
3243
|
+
});
|
|
3226
3244
|
if (this.postSignOutUrl && typeof window !== "undefined") window.location.href = this.postSignOutUrl;
|
|
3227
3245
|
}
|
|
3228
3246
|
/**
|
|
@@ -3236,9 +3254,8 @@ let ZitadelLogout = class ZitadelLogout extends LitElement {
|
|
|
3236
3254
|
...this.clientId ? { client_id: this.clientId } : {},
|
|
3237
3255
|
...this.postSignOutUrl ? { post_logout_redirect_uri: this.postSignOutUrl } : {}
|
|
3238
3256
|
};
|
|
3239
|
-
const
|
|
3240
|
-
|
|
3241
|
-
return getApi(cfg).getEndSessionUrl(params);
|
|
3257
|
+
const { api } = resolveApi(this.project, this.projectAttrs, "<zitadel-logout>");
|
|
3258
|
+
return api.getEndSessionUrl(params);
|
|
3242
3259
|
}
|
|
3243
3260
|
handleSignOutClick(event) {
|
|
3244
3261
|
event.preventDefault();
|
|
@@ -3303,6 +3320,15 @@ let ZitadelLogout = class ZitadelLogout extends LitElement {
|
|
|
3303
3320
|
}
|
|
3304
3321
|
};
|
|
3305
3322
|
__decorate([property({ attribute: false })], ZitadelLogout.prototype, "project", null);
|
|
3323
|
+
__decorate([property({
|
|
3324
|
+
type: String,
|
|
3325
|
+
attribute: "project-id"
|
|
3326
|
+
})], ZitadelLogout.prototype, "projectId", null);
|
|
3327
|
+
__decorate([property({
|
|
3328
|
+
type: String,
|
|
3329
|
+
attribute: "proxy-path"
|
|
3330
|
+
})], ZitadelLogout.prototype, "proxyPath", null);
|
|
3331
|
+
__decorate([property({ type: String })], ZitadelLogout.prototype, "url", null);
|
|
3306
3332
|
__decorate([property({
|
|
3307
3333
|
type: String,
|
|
3308
3334
|
attribute: "post-sign-out-url"
|
|
@@ -3331,6 +3357,6 @@ function fillTemplateTokens(fragment, name, email, initial) {
|
|
|
3331
3357
|
}
|
|
3332
3358
|
}
|
|
3333
3359
|
//#endregion
|
|
3334
|
-
export {
|
|
3360
|
+
export { buildBrandingStylesheet as _, createSanitiser as a, startFlow as b, de as c, MANDATORY_GATES_MARKER as d, mandatoryGatesMarkerComment as f, applyBrandingTokens as g, validateBranding as h, layout_chrome_default as i, en as l, applyFontUrl as m, ZitadelLogin as n, builtinLocales as o, patchMandatoryGates as p, ThemeController as r, it as s, ZitadelLogout as t, TEMPLATE_NAMES as u, resolveTheme as v, submitStep as x, getCurrentStep as y };
|
|
3335
3361
|
|
|
3336
|
-
//# sourceMappingURL=orchestrator-
|
|
3362
|
+
//# sourceMappingURL=orchestrator-BEvS2wA_.mjs.map
|