@zitadel/components 1.0.0-alpha.21 → 1.0.0-alpha.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/atoms/index.d.mts +1 -1
- package/dist/atoms/index.mjs +1 -1
- package/dist/{atoms-DSxjEHca.mjs → atoms-DbcPXAO0.mjs} +3 -2
- package/dist/atoms-DbcPXAO0.mjs.map +1 -0
- package/dist/{index-DFdR16-D.d.mts → index-1PzVwdYA.d.mts} +329 -100
- package/dist/index-1PzVwdYA.d.mts.map +1 -0
- package/dist/{index-Dx8rvpNs.d.mts → index-BRd9vg2q.d.mts} +12923 -6043
- package/dist/index-BRd9vg2q.d.mts.map +1 -0
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +3 -3
- package/dist/manifests.mjs +1 -1
- package/dist/orchestrator/index.d.mts +2 -2
- package/dist/orchestrator/index.mjs +2 -2
- package/dist/{orchestrator-DG-YwFFE.mjs → orchestrator-BVmKaCqz.mjs} +699 -125
- package/dist/orchestrator-BVmKaCqz.mjs.map +1 -0
- package/dist/standalone.mjs +701 -126
- package/package.json +4 -4
- package/dist/atoms-DSxjEHca.mjs.map +0 -1
- package/dist/index-DFdR16-D.d.mts.map +0 -1
- package/dist/index-Dx8rvpNs.d.mts.map +0 -1
- package/dist/orchestrator-DG-YwFFE.mjs.map +0 -1
package/dist/standalone.mjs
CHANGED
|
@@ -681,7 +681,7 @@ const e$5 = (e, t, c) => (c.configurable = !0, c.enumerable = !0, Reflect.decora
|
|
|
681
681
|
}
|
|
682
682
|
//#endregion
|
|
683
683
|
//#region src/atoms/zl-alert.css?inline
|
|
684
|
-
var zl_alert_default = ":host {\n display: block;\n}\n\n.zr-alert {\n align-items: flex-start;\n gap: var(--zl-spacing-2);\n padding-block: var(--zl-spacing-3);\n padding-inline: var(--zl-spacing-4);\n background: var(--zl-muted);\n color: var(--zl-foreground);\n border: 1px solid var(--zl-border);\n border-radius: var(--zl-radius-lg);\n font-family: var(--zl-font-family-sans);\n font-size: var(--zl-text-sm-size);\n line-height: var(--zl-text-sm-leading);\n display: flex;\n}\n\n.zr-alert__icon {\n color: currentColor;\n flex-shrink: 0;\n
|
|
684
|
+
var zl_alert_default = ":host {\n display: block;\n}\n\n.zr-alert {\n align-items: flex-start;\n gap: var(--zl-spacing-2);\n padding-block: var(--zl-spacing-3);\n padding-inline: var(--zl-spacing-4);\n background: var(--zl-muted);\n color: var(--zl-foreground);\n border: 1px solid var(--zl-border);\n border-radius: var(--zl-radius-lg);\n font-family: var(--zl-font-family-sans);\n font-size: var(--zl-text-sm-size);\n line-height: var(--zl-text-sm-leading);\n display: flex;\n}\n\n.zr-alert__icon {\n height: var(--zl-text-sm-leading);\n color: currentColor;\n flex-shrink: 0;\n align-items: center;\n display: inline-flex;\n}\n\n.zr-alert__body {\n gap: var(--zl-spacing-0-5);\n flex-direction: column;\n flex: auto;\n min-width: 0;\n display: flex;\n}\n\n.zr-alert__title {\n font-family: var(--zl-font-family-heading);\n color: var(--zl-foreground);\n}\n\n.zr-alert__message {\n color: var(--zl-muted-foreground);\n margin: 0;\n}\n\n.zr-alert:not(:has(.zr-alert__title)) .zr-alert__message {\n color: var(--zl-foreground);\n}\n\n.zr-alert--error {\n color: var(--zl-destructive);\n}\n\n.zr-alert--success .zr-alert__icon {\n color: var(--zl-success);\n}\n\n.zr-alert--warning .zr-alert__icon, .zr-alert--info .zr-alert__icon {\n color: var(--zl-muted-foreground);\n}\n\n.zr-alert__close {\n all: unset;\n width: var(--zl-spacing-6);\n height: var(--zl-spacing-6);\n border-radius: var(--zl-radius-md);\n color: var(--zl-muted-foreground);\n cursor: pointer;\n transition: background-color var(--zl-duration-fast) var(--zl-easing-standard);\n flex-shrink: 0;\n justify-content: center;\n align-items: center;\n display: inline-flex;\n}\n\n.zr-alert__close zl-icon {\n flex-shrink: 0;\n display: inline-flex;\n}\n\n.zr-alert__close:hover {\n background: var(--zl-accent);\n color: var(--zl-accent-foreground);\n}\n\n.zr-alert__close:focus-visible {\n outline: var(--zl-focus-width) solid var(--zl-ring);\n outline-offset: var(--zl-focus-offset);\n}\n";
|
|
685
685
|
//#endregion
|
|
686
686
|
//#region src/internal/emit.ts
|
|
687
687
|
/**
|
|
@@ -2638,6 +2638,7 @@ let ZlField = class ZlField extends i$2 {
|
|
|
2638
2638
|
class="zr-field__trailing-action"
|
|
2639
2639
|
part="trailing-action"
|
|
2640
2640
|
aria-label="Clear"
|
|
2641
|
+
tabindex="-1"
|
|
2641
2642
|
?disabled=${this.disabled}
|
|
2642
2643
|
@click=${this.handleClear}
|
|
2643
2644
|
>
|
|
@@ -4023,18 +4024,28 @@ function validateBranding(input, context = {}) {
|
|
|
4023
4024
|
out.layout = CreateFlow201BrandingLayout.centered;
|
|
4024
4025
|
}
|
|
4025
4026
|
out.logo_url = sanitiseUrl(out.logo_url, "logo_url", issues, { allowed: allowLoopbackHttp });
|
|
4026
|
-
out.font_url
|
|
4027
|
+
if (out.typography?.font_url) out.typography = {
|
|
4028
|
+
...out.typography,
|
|
4029
|
+
font_url: sanitiseUrl(out.typography.font_url, "typography.font_url", issues)
|
|
4030
|
+
};
|
|
4027
4031
|
out.hero_url = sanitiseUrl(out.hero_url, "hero_url", issues, { allowed: allowLoopbackHttp });
|
|
4028
|
-
if (out.
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
+
if (out.theme?.light || out.theme?.dark) out.theme = {
|
|
4033
|
+
...out.theme,
|
|
4034
|
+
...sanitiseSideLogo(out.theme.light, "light", issues, allowLoopbackHttp),
|
|
4035
|
+
...sanitiseSideLogo(out.theme.dark, "dark", issues, allowLoopbackHttp)
|
|
4032
4036
|
};
|
|
4033
4037
|
return {
|
|
4034
4038
|
branding: out,
|
|
4035
4039
|
issues
|
|
4036
4040
|
};
|
|
4037
4041
|
}
|
|
4042
|
+
function sanitiseSideLogo(side, name, issues, allowLoopbackHttp) {
|
|
4043
|
+
if (!side) return {};
|
|
4044
|
+
return { [name]: {
|
|
4045
|
+
...side,
|
|
4046
|
+
logo_url: sanitiseUrl(side.logo_url, `theme.${name}.logo_url`, issues, { allowed: allowLoopbackHttp })
|
|
4047
|
+
} };
|
|
4048
|
+
}
|
|
4038
4049
|
function sanitiseUrl(value, field, issues, loopbackHttp) {
|
|
4039
4050
|
if (value == null || value === "") return;
|
|
4040
4051
|
try {
|
|
@@ -4052,6 +4063,34 @@ function sanitiseUrl(value, field, issues, loopbackHttp) {
|
|
|
4052
4063
|
}
|
|
4053
4064
|
}
|
|
4054
4065
|
//#endregion
|
|
4066
|
+
//#region src/orchestrator/branding.ts
|
|
4067
|
+
/**
|
|
4068
|
+
* Which sides the revision actually publishes. A side is published when the
|
|
4069
|
+
* revision names it at all — an empty side object still says "this surface is
|
|
4070
|
+
* mine", it just takes the maintained defaults for every key.
|
|
4071
|
+
*/
|
|
4072
|
+
function publishedSides(branding) {
|
|
4073
|
+
const theme = branding?.theme;
|
|
4074
|
+
const sides = [];
|
|
4075
|
+
if (theme?.light) sides.push("light");
|
|
4076
|
+
if (theme?.dark) sides.push("dark");
|
|
4077
|
+
return sides;
|
|
4078
|
+
}
|
|
4079
|
+
/**
|
|
4080
|
+
* The mark for the resolved surface. A logo is pixels and is never recoloured,
|
|
4081
|
+
* so a side without its own file shows no mark rather than borrowing the other
|
|
4082
|
+
* side's. The legacy top-level `logo_url` is a single-mark fallback and applies
|
|
4083
|
+
* only when neither side names one.
|
|
4084
|
+
*/
|
|
4085
|
+
function resolveLogoUrl(branding, theme) {
|
|
4086
|
+
if (!branding) return void 0;
|
|
4087
|
+
const sides = branding.theme;
|
|
4088
|
+
const sideLogo = theme === "light" ? sides?.light?.logo_url : sides?.dark?.logo_url;
|
|
4089
|
+
if (sideLogo) return sideLogo;
|
|
4090
|
+
if (sides?.light?.logo_url || sides?.dark?.logo_url) return void 0;
|
|
4091
|
+
return branding.logo_url;
|
|
4092
|
+
}
|
|
4093
|
+
//#endregion
|
|
4055
4094
|
//#region src/manifests.ts
|
|
4056
4095
|
/**
|
|
4057
4096
|
* Aggregate registry of every shipped `<zl-*>` atom's manifest.
|
|
@@ -6982,7 +7021,7 @@ const minus = argumentsToNumber((v, arg) => v - arg);
|
|
|
6982
7021
|
const plus = argumentsToNumber((lhs, rhs) => lhs + rhs);
|
|
6983
7022
|
const modulo = argumentsToNumber((v, arg) => (v % arg + arg) % arg);
|
|
6984
7023
|
const times = argumentsToNumber((v, arg) => v * arg);
|
|
6985
|
-
function round(v, arg = 0) {
|
|
7024
|
+
function round$1(v, arg = 0) {
|
|
6986
7025
|
v = toNumber(v);
|
|
6987
7026
|
arg = toNumber(arg);
|
|
6988
7027
|
const amp = Math.pow(10, arg);
|
|
@@ -7001,7 +7040,7 @@ var mathFilters = /* @__PURE__ */ Object.freeze({
|
|
|
7001
7040
|
plus,
|
|
7002
7041
|
modulo,
|
|
7003
7042
|
times,
|
|
7004
|
-
round
|
|
7043
|
+
round: round$1
|
|
7005
7044
|
});
|
|
7006
7045
|
const url_decode = (x) => decodeURIComponent(stringify$1(x)).replace(/\+/g, " ");
|
|
7007
7046
|
const url_encode = (x) => encodeURIComponent(stringify$1(x)).replace(/%20/g, "+");
|
|
@@ -9039,7 +9078,7 @@ const en = {
|
|
|
9039
9078
|
"password.action.register.lead": "Don't have an account? ",
|
|
9040
9079
|
"password.action.register.link": "Sign up",
|
|
9041
9080
|
"register.title": "Create your account",
|
|
9042
|
-
"register.description": "",
|
|
9081
|
+
"register.description": "Enter your details to get started",
|
|
9043
9082
|
"register.field.email": "Email",
|
|
9044
9083
|
"register.field.email.placeholder": "you@example.com",
|
|
9045
9084
|
"register.field.password": "Password",
|
|
@@ -9087,7 +9126,7 @@ const en = {
|
|
|
9087
9126
|
"error.password_required": "Please enter a password",
|
|
9088
9127
|
"error.password_incorrect": "Wrong email or password.",
|
|
9089
9128
|
"error.email_exists": "An account with this email already exists.",
|
|
9090
|
-
/**
|
|
9129
|
+
/** Sign-in error, inline on the password field. */
|
|
9091
9130
|
"error.invalid_credentials": "Wrong email or password.",
|
|
9092
9131
|
"error.required": "This field is required.",
|
|
9093
9132
|
"error.field_required": "{0} is required.",
|
|
@@ -9156,7 +9195,7 @@ const de = {
|
|
|
9156
9195
|
"password.action.register.lead": "Noch kein Konto? ",
|
|
9157
9196
|
"password.action.register.link": "Registrieren",
|
|
9158
9197
|
"register.title": "Konto erstellen",
|
|
9159
|
-
"register.description": "",
|
|
9198
|
+
"register.description": "Gib deine Daten ein, um loszulegen",
|
|
9160
9199
|
"register.field.email": "E-Mail",
|
|
9161
9200
|
"register.field.email.placeholder": "du@beispiel.de",
|
|
9162
9201
|
"register.field.password": "Passwort",
|
|
@@ -9272,7 +9311,7 @@ const it = {
|
|
|
9272
9311
|
"password.action.register.lead": "Non hai un account? ",
|
|
9273
9312
|
"password.action.register.link": "Registrati",
|
|
9274
9313
|
"register.title": "Crea il tuo account",
|
|
9275
|
-
"register.description": "",
|
|
9314
|
+
"register.description": "Inserisci i tuoi dati per iniziare",
|
|
9276
9315
|
"register.field.email": "E-mail",
|
|
9277
9316
|
"register.field.email.placeholder": "tu@esempio.com",
|
|
9278
9317
|
"register.field.password": "Password",
|
|
@@ -9410,22 +9449,24 @@ var zitadelNextGen_exports = /* @__PURE__ */ __exportAll({
|
|
|
9410
9449
|
createFlowDefinition: () => createFlowDefinition,
|
|
9411
9450
|
createGrant: () => createGrant,
|
|
9412
9451
|
createHandoff: () => createHandoff,
|
|
9452
|
+
createIdp: () => createIdp,
|
|
9413
9453
|
createProject: () => createProject,
|
|
9414
9454
|
createRelease: () => createRelease,
|
|
9415
9455
|
createSchema: () => createSchema,
|
|
9416
9456
|
createSession: () => createSession,
|
|
9417
9457
|
createTeam: () => createTeam,
|
|
9418
9458
|
createUser: () => createUser,
|
|
9419
|
-
deleteFlowDefinition: () => deleteFlowDefinition,
|
|
9420
9459
|
deleteGrant: () => deleteGrant,
|
|
9421
9460
|
deleteTeam: () => deleteTeam,
|
|
9422
9461
|
deleteUserByID: () => deleteUserByID,
|
|
9462
|
+
deleteVariable: () => deleteVariable,
|
|
9423
9463
|
exchangeHandoff: () => exchangeHandoff,
|
|
9424
9464
|
finishUserPasskeyRegistration: () => finishUserPasskeyRegistration,
|
|
9425
9465
|
getAuthAttempt: () => getAuthAttempt,
|
|
9426
9466
|
getBeginUserPasskeyRegistrationUrl: () => getBeginUserPasskeyRegistrationUrl,
|
|
9427
9467
|
getBrandingById: () => getBrandingById,
|
|
9428
9468
|
getClaimStatus: () => getClaimStatus,
|
|
9469
|
+
getClaimWindow: () => getClaimWindow,
|
|
9429
9470
|
getCompleteClaimUrl: () => getCompleteClaimUrl,
|
|
9430
9471
|
getCreateAuthAttemptUrl: () => getCreateAuthAttemptUrl,
|
|
9431
9472
|
getCreateBrandingUrl: () => getCreateBrandingUrl,
|
|
@@ -9433,16 +9474,17 @@ var zitadelNextGen_exports = /* @__PURE__ */ __exportAll({
|
|
|
9433
9474
|
getCreateFlowUrl: () => getCreateFlowUrl,
|
|
9434
9475
|
getCreateGrantUrl: () => getCreateGrantUrl,
|
|
9435
9476
|
getCreateHandoffUrl: () => getCreateHandoffUrl,
|
|
9477
|
+
getCreateIdpUrl: () => getCreateIdpUrl,
|
|
9436
9478
|
getCreateProjectUrl: () => getCreateProjectUrl,
|
|
9437
9479
|
getCreateReleaseUrl: () => getCreateReleaseUrl,
|
|
9438
9480
|
getCreateSchemaUrl: () => getCreateSchemaUrl,
|
|
9439
9481
|
getCreateSessionUrl: () => getCreateSessionUrl,
|
|
9440
9482
|
getCreateTeamUrl: () => getCreateTeamUrl,
|
|
9441
9483
|
getCreateUserUrl: () => getCreateUserUrl,
|
|
9442
|
-
getDeleteFlowDefinitionUrl: () => getDeleteFlowDefinitionUrl,
|
|
9443
9484
|
getDeleteGrantUrl: () => getDeleteGrantUrl,
|
|
9444
9485
|
getDeleteTeamUrl: () => getDeleteTeamUrl,
|
|
9445
9486
|
getDeleteUserByIDUrl: () => getDeleteUserByIDUrl,
|
|
9487
|
+
getDeleteVariableUrl: () => getDeleteVariableUrl,
|
|
9446
9488
|
getEnvironmentByName: () => getEnvironmentByName,
|
|
9447
9489
|
getEvent: () => getEvent,
|
|
9448
9490
|
getExchangeHandoffUrl: () => getExchangeHandoffUrl,
|
|
@@ -9452,12 +9494,15 @@ var zitadelNextGen_exports = /* @__PURE__ */ __exportAll({
|
|
|
9452
9494
|
getGetAuthAttemptUrl: () => getGetAuthAttemptUrl,
|
|
9453
9495
|
getGetBrandingByIdUrl: () => getGetBrandingByIdUrl,
|
|
9454
9496
|
getGetClaimStatusUrl: () => getGetClaimStatusUrl,
|
|
9497
|
+
getGetClaimWindowUrl: () => getGetClaimWindowUrl,
|
|
9455
9498
|
getGetEnvironmentByNameUrl: () => getGetEnvironmentByNameUrl,
|
|
9456
9499
|
getGetEventUrl: () => getGetEventUrl,
|
|
9457
9500
|
getGetFlowDefinitionUrl: () => getGetFlowDefinitionUrl,
|
|
9458
9501
|
getGetFlowStepUrl: () => getGetFlowStepUrl,
|
|
9459
9502
|
getGetGrantUrl: () => getGetGrantUrl,
|
|
9460
9503
|
getGetHealthUrl: () => getGetHealthUrl,
|
|
9504
|
+
getGetIdpByIdUrl: () => getGetIdpByIdUrl,
|
|
9505
|
+
getGetIdpRevisionByIdUrl: () => getGetIdpRevisionByIdUrl,
|
|
9461
9506
|
getGetLiveUrl: () => getGetLiveUrl,
|
|
9462
9507
|
getGetMySessionUrl: () => getGetMySessionUrl,
|
|
9463
9508
|
getGetMyUserUrl: () => getGetMyUserUrl,
|
|
@@ -9468,14 +9513,20 @@ var zitadelNextGen_exports = /* @__PURE__ */ __exportAll({
|
|
|
9468
9513
|
getGetSessionUrl: () => getGetSessionUrl,
|
|
9469
9514
|
getGetTeamUrl: () => getGetTeamUrl,
|
|
9470
9515
|
getGetUserByIDUrl: () => getGetUserByIDUrl,
|
|
9516
|
+
getGetVariableUrl: () => getGetVariableUrl,
|
|
9517
|
+
getGetVariablesUrl: () => getGetVariablesUrl,
|
|
9471
9518
|
getGrant: () => getGrant,
|
|
9472
9519
|
getHealth: () => getHealth,
|
|
9520
|
+
getIdpById: () => getIdpById,
|
|
9521
|
+
getIdpRevisionById: () => getIdpRevisionById,
|
|
9473
9522
|
getInitClaimUrl: () => getInitClaimUrl,
|
|
9474
9523
|
getIssueChallengeUrl: () => getIssueChallengeUrl,
|
|
9475
9524
|
getListBrandingUrl: () => getListBrandingUrl,
|
|
9476
9525
|
getListEnvironmentsUrl: () => getListEnvironmentsUrl,
|
|
9477
9526
|
getListEventsUrl: () => getListEventsUrl,
|
|
9478
9527
|
getListFlowDefinitionsUrl: () => getListFlowDefinitionsUrl,
|
|
9528
|
+
getListIdpRevisionsUrl: () => getListIdpRevisionsUrl,
|
|
9529
|
+
getListMyProjectsUrl: () => getListMyProjectsUrl,
|
|
9479
9530
|
getListReleasesUrl: () => getListReleasesUrl,
|
|
9480
9531
|
getListSchemasUrl: () => getListSchemasUrl,
|
|
9481
9532
|
getListUserPasskeysUrl: () => getListUserPasskeysUrl,
|
|
@@ -9483,8 +9534,12 @@ var zitadelNextGen_exports = /* @__PURE__ */ __exportAll({
|
|
|
9483
9534
|
getLive: () => getLive,
|
|
9484
9535
|
getMySession: () => getMySession,
|
|
9485
9536
|
getMyUser: () => getMyUser,
|
|
9537
|
+
getPatchMyUserUrl: () => getPatchMyUserUrl,
|
|
9486
9538
|
getPatchProjectUrl: () => getPatchProjectUrl,
|
|
9539
|
+
getPatchUserByIDUrl: () => getPatchUserByIDUrl,
|
|
9487
9540
|
getProject: () => getProject,
|
|
9541
|
+
getQueryGrantsUrl: () => getQueryGrantsUrl,
|
|
9542
|
+
getQueryIdpsUrl: () => getQueryIdpsUrl,
|
|
9488
9543
|
getQueryProjectsUrl: () => getQueryProjectsUrl,
|
|
9489
9544
|
getQuerySessionsUrl: () => getQuerySessionsUrl,
|
|
9490
9545
|
getQueryTeamsUrl: () => getQueryTeamsUrl,
|
|
@@ -9498,9 +9553,11 @@ var zitadelNextGen_exports = /* @__PURE__ */ __exportAll({
|
|
|
9498
9553
|
getSetUserPasswordUrl: () => getSetUserPasswordUrl,
|
|
9499
9554
|
getSubmitFlowStepUrl: () => getSubmitFlowStepUrl,
|
|
9500
9555
|
getTeam: () => getTeam,
|
|
9501
|
-
getUpdateFlowDefinitionUrl: () => getUpdateFlowDefinitionUrl,
|
|
9502
9556
|
getUpdateTeamUrl: () => getUpdateTeamUrl,
|
|
9557
|
+
getUpdateVariablesUrl: () => getUpdateVariablesUrl,
|
|
9503
9558
|
getUserByID: () => getUserByID,
|
|
9559
|
+
getVariable: () => getVariable,
|
|
9560
|
+
getVariables: () => getVariables,
|
|
9504
9561
|
getVerifyChallengeProofUrl: () => getVerifyChallengeProofUrl,
|
|
9505
9562
|
initClaim: () => initClaim,
|
|
9506
9563
|
issueChallenge: () => issueChallenge,
|
|
@@ -9508,11 +9565,17 @@ var zitadelNextGen_exports = /* @__PURE__ */ __exportAll({
|
|
|
9508
9565
|
listEnvironments: () => listEnvironments,
|
|
9509
9566
|
listEvents: () => listEvents,
|
|
9510
9567
|
listFlowDefinitions: () => listFlowDefinitions,
|
|
9568
|
+
listIdpRevisions: () => listIdpRevisions,
|
|
9569
|
+
listMyProjects: () => listMyProjects,
|
|
9511
9570
|
listReleases: () => listReleases,
|
|
9512
9571
|
listSchemas: () => listSchemas,
|
|
9513
9572
|
listUserPasskeys: () => listUserPasskeys,
|
|
9514
9573
|
listUserTeams: () => listUserTeams,
|
|
9574
|
+
patchMyUser: () => patchMyUser,
|
|
9515
9575
|
patchProject: () => patchProject,
|
|
9576
|
+
patchUserByID: () => patchUserByID,
|
|
9577
|
+
queryGrants: () => queryGrants,
|
|
9578
|
+
queryIdps: () => queryIdps,
|
|
9516
9579
|
queryProjects: () => queryProjects,
|
|
9517
9580
|
querySessions: () => querySessions,
|
|
9518
9581
|
queryTeams: () => queryTeams,
|
|
@@ -9521,8 +9584,8 @@ var zitadelNextGen_exports = /* @__PURE__ */ __exportAll({
|
|
|
9521
9584
|
revokeSession: () => revokeSession,
|
|
9522
9585
|
setUserPassword: () => setUserPassword,
|
|
9523
9586
|
submitFlowStep: () => submitFlowStep,
|
|
9524
|
-
updateFlowDefinition: () => updateFlowDefinition,
|
|
9525
9587
|
updateTeam: () => updateTeam,
|
|
9588
|
+
updateVariables: () => updateVariables,
|
|
9526
9589
|
verifyChallengeProof: () => verifyChallengeProof
|
|
9527
9590
|
});
|
|
9528
9591
|
const getGetHealthUrl = () => {
|
|
@@ -9592,9 +9655,14 @@ const getQueryUsersUrl = () => {
|
|
|
9592
9655
|
/**
|
|
9593
9656
|
* Returns the users of a project, paginated with a cursor.
|
|
9594
9657
|
|
|
9595
|
-
The project comes from the credential, not from a parameter: the
|
|
9596
|
-
is bound to the
|
|
9597
|
-
|
|
9658
|
+
The project comes from the credential, not from a parameter: the
|
|
9659
|
+
operation is bound to the credential's home project by construction
|
|
9660
|
+
(oauth2 secret or user-bound session). This is why it takes no
|
|
9661
|
+
`project_id`, unlike the other query endpoints.
|
|
9662
|
+
|
|
9663
|
+
Accepts either a project secret (`oauth2`) or a user-bound Console
|
|
9664
|
+
session cookie (`nextgenSession`). CSRF/Origin for cookie mutations
|
|
9665
|
+
is a follow-up (#1140).
|
|
9598
9666
|
|
|
9599
9667
|
* @summary Query users
|
|
9600
9668
|
*/
|
|
@@ -9626,6 +9694,28 @@ const getUserByID = async (userId, params, options) => {
|
|
|
9626
9694
|
method: "GET"
|
|
9627
9695
|
});
|
|
9628
9696
|
};
|
|
9697
|
+
const getPatchUserByIDUrl = (userId) => {
|
|
9698
|
+
return `${getProxyPath()}/users/${userId}`;
|
|
9699
|
+
};
|
|
9700
|
+
/**
|
|
9701
|
+
* Partially updates a user's schema-defined attributes, and optionally
|
|
9702
|
+
moves the user to another registered schema. The merged result is
|
|
9703
|
+
validated against the schema before commit. Concurrent writes are
|
|
9704
|
+
last-write-wins.
|
|
9705
|
+
|
|
9706
|
+
* @summary Update user by ID
|
|
9707
|
+
*/
|
|
9708
|
+
const patchUserByID = async (userId, patchUserByIDBody, options) => {
|
|
9709
|
+
return customFetch(getPatchUserByIDUrl(userId), {
|
|
9710
|
+
...options,
|
|
9711
|
+
method: "PATCH",
|
|
9712
|
+
headers: {
|
|
9713
|
+
"Content-Type": "application/json",
|
|
9714
|
+
...options?.headers
|
|
9715
|
+
},
|
|
9716
|
+
body: JSON.stringify(patchUserByIDBody)
|
|
9717
|
+
});
|
|
9718
|
+
};
|
|
9629
9719
|
const getDeleteUserByIDUrl = (userId) => {
|
|
9630
9720
|
return `${getProxyPath()}/users/${userId}`;
|
|
9631
9721
|
};
|
|
@@ -9756,6 +9846,52 @@ const getMyUser = async (options) => {
|
|
|
9756
9846
|
method: "GET"
|
|
9757
9847
|
});
|
|
9758
9848
|
};
|
|
9849
|
+
const getPatchMyUserUrl = () => {
|
|
9850
|
+
return `${getProxyPath()}/users/me`;
|
|
9851
|
+
};
|
|
9852
|
+
/**
|
|
9853
|
+
* Partially updates the caller's own schema-defined attributes. The merged
|
|
9854
|
+
result is validated against the user's schema before commit. Concurrent
|
|
9855
|
+
writes are last-write-wins.
|
|
9856
|
+
|
|
9857
|
+
* @summary Update my user information
|
|
9858
|
+
*/
|
|
9859
|
+
const patchMyUser = async (patchMyUserBody, options) => {
|
|
9860
|
+
return customFetch(getPatchMyUserUrl(), {
|
|
9861
|
+
...options,
|
|
9862
|
+
method: "PATCH",
|
|
9863
|
+
headers: {
|
|
9864
|
+
"Content-Type": "application/json",
|
|
9865
|
+
...options?.headers
|
|
9866
|
+
},
|
|
9867
|
+
body: JSON.stringify(patchMyUserBody)
|
|
9868
|
+
});
|
|
9869
|
+
};
|
|
9870
|
+
const getListMyProjectsUrl = (params) => {
|
|
9871
|
+
const normalizedParams = new URLSearchParams();
|
|
9872
|
+
Object.entries(params || {}).forEach(([key, value]) => {
|
|
9873
|
+
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : value.toString());
|
|
9874
|
+
});
|
|
9875
|
+
const stringifiedParams = normalizedParams.toString();
|
|
9876
|
+
return stringifiedParams.length > 0 ? `${getProxyPath()}/users/me/projects?${stringifiedParams}` : `${getProxyPath()}/users/me/projects`;
|
|
9877
|
+
};
|
|
9878
|
+
/**
|
|
9879
|
+
* The projects the signed-in user holds an active grant on, either directly or
|
|
9880
|
+
through a team they are a member of. Ordered by project id and paged with an
|
|
9881
|
+
opaque cursor.
|
|
9882
|
+
|
|
9883
|
+
This is not the same question as `queryProjects`, which answers with the one
|
|
9884
|
+
project the calling credential is bound to. Here the session is the caller
|
|
9885
|
+
and the grants are the answer, so the list spans projects.
|
|
9886
|
+
|
|
9887
|
+
* @summary List the projects I can act on
|
|
9888
|
+
*/
|
|
9889
|
+
const listMyProjects = async (params, options) => {
|
|
9890
|
+
return customFetch(getListMyProjectsUrl(params), {
|
|
9891
|
+
...options,
|
|
9892
|
+
method: "GET"
|
|
9893
|
+
});
|
|
9894
|
+
};
|
|
9759
9895
|
const getCreateFlowUrl = () => {
|
|
9760
9896
|
return `${getProxyPath()}/flow`;
|
|
9761
9897
|
};
|
|
@@ -10062,7 +10198,11 @@ const getGetClaimStatusUrl = (projectId, params) => {
|
|
|
10062
10198
|
* Polled by the CLI while a browser completes the claim. Authorized by the
|
|
10063
10199
|
project secret that initiated the challenge. Returns `pending`, or
|
|
10064
10200
|
`completed` with the owning team, the claim timestamp, and the dashboard
|
|
10065
|
-
URL once the
|
|
10201
|
+
URL once the project is claimed. The claim grant, not the polled
|
|
10202
|
+
challenge, is the source of truth: a project claimed through another
|
|
10203
|
+
concurrent challenge also reports `completed`, and a completed claim
|
|
10204
|
+
keeps reporting `completed` past this challenge's expiry and past the
|
|
10205
|
+
project's claim window.
|
|
10066
10206
|
|
|
10067
10207
|
* @summary Get claim status
|
|
10068
10208
|
*/
|
|
@@ -10094,6 +10234,30 @@ const completeClaim = async (projectId, completeClaimBody, options) => {
|
|
|
10094
10234
|
body: JSON.stringify(completeClaimBody)
|
|
10095
10235
|
});
|
|
10096
10236
|
};
|
|
10237
|
+
const getGetClaimWindowUrl = (projectId, params) => {
|
|
10238
|
+
const normalizedParams = new URLSearchParams();
|
|
10239
|
+
Object.entries(params || {}).forEach(([key, value]) => {
|
|
10240
|
+
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : value.toString());
|
|
10241
|
+
});
|
|
10242
|
+
const stringifiedParams = normalizedParams.toString();
|
|
10243
|
+
return stringifiedParams.length > 0 ? `${getProxyPath()}/projects/${projectId}/claim/window?${stringifiedParams}` : `${getProxyPath()}/projects/${projectId}/claim/window`;
|
|
10244
|
+
};
|
|
10245
|
+
/**
|
|
10246
|
+
* Read by the claim page in the browser to show how long is left to claim the
|
|
10247
|
+
project. Unauthenticated by design: the claim page runs this before the
|
|
10248
|
+
developer has signed in, and holding the `challenge_id` from the claim URL
|
|
10249
|
+
is the authorization — the same capability `claim/complete` accepts. It
|
|
10250
|
+
reveals only the window, never the project itself, and unlike
|
|
10251
|
+
`claim/complete` it spends nothing, so a reload is free.
|
|
10252
|
+
|
|
10253
|
+
* @summary Get the claim window for a project
|
|
10254
|
+
*/
|
|
10255
|
+
const getClaimWindow = async (projectId, params, options) => {
|
|
10256
|
+
return customFetch(getGetClaimWindowUrl(projectId, params), {
|
|
10257
|
+
...options,
|
|
10258
|
+
method: "GET"
|
|
10259
|
+
});
|
|
10260
|
+
};
|
|
10097
10261
|
const getCreateSessionUrl = () => {
|
|
10098
10262
|
return `${getProxyPath()}/sessions`;
|
|
10099
10263
|
};
|
|
@@ -10355,12 +10519,17 @@ const getCreateFlowDefinitionUrl = () => {
|
|
|
10355
10519
|
return `${getProxyPath()}/flow_definitions`;
|
|
10356
10520
|
};
|
|
10357
10521
|
/**
|
|
10358
|
-
*
|
|
10522
|
+
* Publishes a new flow definition revision.
|
|
10359
10523
|
Flow definitions are templates that define the sequence of steps (capabilities)
|
|
10360
10524
|
for a particular user journey (e.g., registration, login, password reset).
|
|
10361
10525
|
|
|
10362
10526
|
Flow definitions are created based on the flow definition schema, which includes the flow's purpose, audience, and the steps involved.
|
|
10363
10527
|
|
|
10528
|
+
Every call allocates a new opaque id. Revisions of one flow share its
|
|
10529
|
+
`name`; posting a definition under an existing `name` publishes a new
|
|
10530
|
+
revision of that flow, it is not a conflict. List with `name` to see a
|
|
10531
|
+
flow's revisions, newest by creation time first.
|
|
10532
|
+
|
|
10364
10533
|
* @summary Create a new flow definition
|
|
10365
10534
|
*/
|
|
10366
10535
|
const createFlowDefinition = async (createFlowDefinitionBody, options) => {
|
|
@@ -10383,8 +10552,9 @@ const getListFlowDefinitionsUrl = (params) => {
|
|
|
10383
10552
|
return stringifiedParams.length > 0 ? `${getProxyPath()}/flow_definitions?${stringifiedParams}` : `${getProxyPath()}/flow_definitions`;
|
|
10384
10553
|
};
|
|
10385
10554
|
/**
|
|
10386
|
-
* Retrieves a list of all flow definitions.
|
|
10555
|
+
* Retrieves a list of all flow definitions, newest by creation time first.
|
|
10387
10556
|
This endpoint can be used to view existing flow definitions and their configurations.
|
|
10557
|
+
Filter by `name` to list the revisions of one flow.
|
|
10388
10558
|
|
|
10389
10559
|
* @summary List flow definitions
|
|
10390
10560
|
*/
|
|
@@ -10407,42 +10577,6 @@ const getFlowDefinition = async (id, options) => {
|
|
|
10407
10577
|
method: "GET"
|
|
10408
10578
|
});
|
|
10409
10579
|
};
|
|
10410
|
-
const getUpdateFlowDefinitionUrl = (id) => {
|
|
10411
|
-
return `${getProxyPath()}/flow_definitions/${id}`;
|
|
10412
|
-
};
|
|
10413
|
-
/**
|
|
10414
|
-
* Update a flow definition by id. This endpoint replaces the existing flow definition.
|
|
10415
|
-
If `flow_definition.status` is omitted, the current status is preserved
|
|
10416
|
-
|
|
10417
|
-
* @summary Update a flow definition by id
|
|
10418
|
-
*/
|
|
10419
|
-
const updateFlowDefinition = async (id, updateFlowDefinitionBody, options) => {
|
|
10420
|
-
return customFetch(getUpdateFlowDefinitionUrl(id), {
|
|
10421
|
-
...options,
|
|
10422
|
-
method: "PUT",
|
|
10423
|
-
headers: {
|
|
10424
|
-
"Content-Type": "application/json",
|
|
10425
|
-
...options?.headers
|
|
10426
|
-
},
|
|
10427
|
-
body: JSON.stringify(updateFlowDefinitionBody)
|
|
10428
|
-
});
|
|
10429
|
-
};
|
|
10430
|
-
const getDeleteFlowDefinitionUrl = (id) => {
|
|
10431
|
-
return `${getProxyPath()}/flow_definitions/${id}`;
|
|
10432
|
-
};
|
|
10433
|
-
/**
|
|
10434
|
-
* Delete a flow definition by id.
|
|
10435
|
-
If the flow definition is currently being used by a flow, the deletion will fail.
|
|
10436
|
-
If the flow definition is the last active flow definition for a given purpose, the deletion will fail to prevent disruption of new flows being started for that purpose.
|
|
10437
|
-
|
|
10438
|
-
* @summary Delete a flow definition by id
|
|
10439
|
-
*/
|
|
10440
|
-
const deleteFlowDefinition = async (id, options) => {
|
|
10441
|
-
return customFetch(getDeleteFlowDefinitionUrl(id), {
|
|
10442
|
-
...options,
|
|
10443
|
-
method: "DELETE"
|
|
10444
|
-
});
|
|
10445
|
-
};
|
|
10446
10580
|
const getCreateTeamUrl = (params) => {
|
|
10447
10581
|
const normalizedParams = new URLSearchParams();
|
|
10448
10582
|
Object.entries(params || {}).forEach(([key, value]) => {
|
|
@@ -10516,6 +10650,11 @@ users whose lifecycle it owns are deactivated with it.
|
|
|
10516
10650
|
The request is idempotent. Deleting a team that is already deactivated
|
|
10517
10651
|
or doesn't exist succeeds without changing anything.
|
|
10518
10652
|
|
|
10653
|
+
A team that still owns a project is refused with `409
|
|
10654
|
+
team.owns_project`: deactivating it would leave the project owned by a
|
|
10655
|
+
dead team and so unmanageable. No endpoint releases that ownership yet,
|
|
10656
|
+
so such a team cannot currently be deactivated through the API.
|
|
10657
|
+
|
|
10519
10658
|
* @summary Delete team
|
|
10520
10659
|
*/
|
|
10521
10660
|
const deleteTeam = async (teamId, options) => {
|
|
@@ -10595,8 +10734,7 @@ const getCreateBrandingUrl = (params) => {
|
|
|
10595
10734
|
/**
|
|
10596
10735
|
* Publishes a new immutable branding revision for the project. Branding
|
|
10597
10736
|
revisions cannot be updated or deleted; every edit publishes a new
|
|
10598
|
-
revision, and flow responses resolve the latest revision per project
|
|
10599
|
-
(see ADR 040).
|
|
10737
|
+
revision, and flow responses resolve the latest revision per project.
|
|
10600
10738
|
|
|
10601
10739
|
The `liquid_template` is validated lexically on save (size, encoding,
|
|
10602
10740
|
banned patterns such as `<script>` tags, inline event handlers, and the
|
|
@@ -10627,9 +10765,9 @@ const getListBrandingUrl = (params) => {
|
|
|
10627
10765
|
/**
|
|
10628
10766
|
* Lists branding revisions for the project, newest first, capped at the
|
|
10629
10767
|
100 most recent. The first entry is the revision flow responses
|
|
10630
|
-
currently resolve. Deliberately unpaginated in v1 — list endpoints
|
|
10631
|
-
|
|
10632
|
-
|
|
10768
|
+
currently resolve. Deliberately unpaginated in v1 — list endpoints gain a
|
|
10769
|
+
real query mechanism together; advertising pagination parameters the
|
|
10770
|
+
server ignores would be worse than none.
|
|
10633
10771
|
|
|
10634
10772
|
* @summary List branding revisions
|
|
10635
10773
|
*/
|
|
@@ -10652,6 +10790,142 @@ const getBrandingById = async (id, options) => {
|
|
|
10652
10790
|
method: "GET"
|
|
10653
10791
|
});
|
|
10654
10792
|
};
|
|
10793
|
+
const getCreateIdpUrl = (params) => {
|
|
10794
|
+
const normalizedParams = new URLSearchParams();
|
|
10795
|
+
Object.entries(params || {}).forEach(([key, value]) => {
|
|
10796
|
+
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : value.toString());
|
|
10797
|
+
});
|
|
10798
|
+
const stringifiedParams = normalizedParams.toString();
|
|
10799
|
+
return stringifiedParams.length > 0 ? `${getProxyPath()}/idps?${stringifiedParams}` : `${getProxyPath()}/idps`;
|
|
10800
|
+
};
|
|
10801
|
+
/**
|
|
10802
|
+
* Creates or revises a connection document. If the slug does not already
|
|
10803
|
+
exist, a new connection is created. If a connection with that slug already
|
|
10804
|
+
exists, a revision is created.
|
|
10805
|
+
|
|
10806
|
+
A revision gets a new `revision_id` and does not modify the connection
|
|
10807
|
+
`id`, so identity links that reference the connection keep resolving while
|
|
10808
|
+
releases and auth attempts stay pinned to the revision they captured.
|
|
10809
|
+
|
|
10810
|
+
Identity fields are fixed for the life of the connection and a revision
|
|
10811
|
+
that changes one is rejected: `protocol`, `subject_claim`, and the
|
|
10812
|
+
endpoints that name the authority (`issuer` for OIDC, `token_endpoint`
|
|
10813
|
+
and `userinfo_endpoint` for OAuth 2.0). Their values decide which provider
|
|
10814
|
+
account a stored subject belongs to, so changing one would silently
|
|
10815
|
+
repoint existing identities at a different provider.
|
|
10816
|
+
|
|
10817
|
+
`subject_claim` is optional for OIDC and required for OAuth 2.0. For an
|
|
10818
|
+
OIDC connection, `sub` is used as the default value. If a revision updates
|
|
10819
|
+
`subject_claim` to a different value than the one set during creation, the
|
|
10820
|
+
request is rejected.
|
|
10821
|
+
|
|
10822
|
+
The document is validated against the `idp-connection.json` schema before
|
|
10823
|
+
anything is stored.
|
|
10824
|
+
|
|
10825
|
+
* @summary Create or revise an identity provider connection
|
|
10826
|
+
*/
|
|
10827
|
+
const createIdp = async (createIdpBody, params, options) => {
|
|
10828
|
+
return customFetch(getCreateIdpUrl(params), {
|
|
10829
|
+
...options,
|
|
10830
|
+
method: "POST",
|
|
10831
|
+
headers: {
|
|
10832
|
+
"Content-Type": "application/json",
|
|
10833
|
+
...options?.headers
|
|
10834
|
+
},
|
|
10835
|
+
body: JSON.stringify(createIdpBody)
|
|
10836
|
+
});
|
|
10837
|
+
};
|
|
10838
|
+
const getQueryIdpsUrl = (params) => {
|
|
10839
|
+
const normalizedParams = new URLSearchParams();
|
|
10840
|
+
Object.entries(params || {}).forEach(([key, value]) => {
|
|
10841
|
+
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : value.toString());
|
|
10842
|
+
});
|
|
10843
|
+
const stringifiedParams = normalizedParams.toString();
|
|
10844
|
+
return stringifiedParams.length > 0 ? `${getProxyPath()}/idps/query?${stringifiedParams}` : `${getProxyPath()}/idps/query`;
|
|
10845
|
+
};
|
|
10846
|
+
/**
|
|
10847
|
+
* Returns the identity provider connections of a project, paginated with a
|
|
10848
|
+
cursor. One row per connection, carrying its newest revision.
|
|
10849
|
+
|
|
10850
|
+
* @summary Query identity provider connections
|
|
10851
|
+
*/
|
|
10852
|
+
const queryIdps = async (queryIdpsBody, params, options) => {
|
|
10853
|
+
return customFetch(getQueryIdpsUrl(params), {
|
|
10854
|
+
...options,
|
|
10855
|
+
method: "POST",
|
|
10856
|
+
headers: {
|
|
10857
|
+
"Content-Type": "application/json",
|
|
10858
|
+
...options?.headers
|
|
10859
|
+
},
|
|
10860
|
+
body: JSON.stringify(queryIdpsBody)
|
|
10861
|
+
});
|
|
10862
|
+
};
|
|
10863
|
+
const getGetIdpByIdUrl = (id, params) => {
|
|
10864
|
+
const normalizedParams = new URLSearchParams();
|
|
10865
|
+
Object.entries(params || {}).forEach(([key, value]) => {
|
|
10866
|
+
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : value.toString());
|
|
10867
|
+
});
|
|
10868
|
+
const stringifiedParams = normalizedParams.toString();
|
|
10869
|
+
return stringifiedParams.length > 0 ? `${getProxyPath()}/idps/${id}?${stringifiedParams}` : `${getProxyPath()}/idps/${id}`;
|
|
10870
|
+
};
|
|
10871
|
+
/**
|
|
10872
|
+
* Reads a connection by its id, at its newest revision.
|
|
10873
|
+
`GET /idps/{id}/revisions` lists every revision of the connection.
|
|
10874
|
+
|
|
10875
|
+
The lookup is scoped to the project in `project_id`.
|
|
10876
|
+
|
|
10877
|
+
* @summary Get an identity provider connection by id
|
|
10878
|
+
*/
|
|
10879
|
+
const getIdpById = async (id, params, options) => {
|
|
10880
|
+
return customFetch(getGetIdpByIdUrl(id, params), {
|
|
10881
|
+
...options,
|
|
10882
|
+
method: "GET"
|
|
10883
|
+
});
|
|
10884
|
+
};
|
|
10885
|
+
const getListIdpRevisionsUrl = (id, params) => {
|
|
10886
|
+
const normalizedParams = new URLSearchParams();
|
|
10887
|
+
Object.entries(params || {}).forEach(([key, value]) => {
|
|
10888
|
+
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : value.toString());
|
|
10889
|
+
});
|
|
10890
|
+
const stringifiedParams = normalizedParams.toString();
|
|
10891
|
+
return stringifiedParams.length > 0 ? `${getProxyPath()}/idps/${id}/revisions?${stringifiedParams}` : `${getProxyPath()}/idps/${id}/revisions`;
|
|
10892
|
+
};
|
|
10893
|
+
/**
|
|
10894
|
+
* Returns every revision of one connection, newest first, paginated with a
|
|
10895
|
+
cursor. The order is fixed, so there is no `sorting`.
|
|
10896
|
+
|
|
10897
|
+
The lookup is scoped to the project in `project_id`.
|
|
10898
|
+
|
|
10899
|
+
* @summary List the revisions of an identity provider connection
|
|
10900
|
+
*/
|
|
10901
|
+
const listIdpRevisions = async (id, params, options) => {
|
|
10902
|
+
return customFetch(getListIdpRevisionsUrl(id, params), {
|
|
10903
|
+
...options,
|
|
10904
|
+
method: "GET"
|
|
10905
|
+
});
|
|
10906
|
+
};
|
|
10907
|
+
const getGetIdpRevisionByIdUrl = (revisionId, params) => {
|
|
10908
|
+
const normalizedParams = new URLSearchParams();
|
|
10909
|
+
Object.entries(params || {}).forEach(([key, value]) => {
|
|
10910
|
+
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : value.toString());
|
|
10911
|
+
});
|
|
10912
|
+
const stringifiedParams = normalizedParams.toString();
|
|
10913
|
+
return stringifiedParams.length > 0 ? `${getProxyPath()}/idps/revisions/${revisionId}?${stringifiedParams}` : `${getProxyPath()}/idps/revisions/${revisionId}`;
|
|
10914
|
+
};
|
|
10915
|
+
/**
|
|
10916
|
+
* Reads one revision of a connection by its `revision_id`, the value an auth
|
|
10917
|
+
attempt or a release pins.
|
|
10918
|
+
|
|
10919
|
+
The lookup is scoped to the project in `project_id`.
|
|
10920
|
+
|
|
10921
|
+
* @summary Get one revision of an identity provider connection
|
|
10922
|
+
*/
|
|
10923
|
+
const getIdpRevisionById = async (revisionId, params, options) => {
|
|
10924
|
+
return customFetch(getGetIdpRevisionByIdUrl(revisionId, params), {
|
|
10925
|
+
...options,
|
|
10926
|
+
method: "GET"
|
|
10927
|
+
});
|
|
10928
|
+
};
|
|
10655
10929
|
const getCreateReleaseUrl = (params) => {
|
|
10656
10930
|
const normalizedParams = new URLSearchParams();
|
|
10657
10931
|
Object.entries(params || {}).forEach(([key, value]) => {
|
|
@@ -10751,10 +11025,23 @@ const getCreateGrantUrl = (params) => {
|
|
|
10751
11025
|
/**
|
|
10752
11026
|
* Bind a user or team to `project.viewer`, `project.editor`, or
|
|
10753
11027
|
`project.admin` on the project identified by the `project-id` header.
|
|
10754
|
-
|
|
10755
|
-
|
|
10756
|
-
|
|
10757
|
-
|
|
11028
|
+
Name the principal with `user` (`user_id` or `identifier`) or `team`
|
|
11029
|
+
(`team_id` or `name`). IDs are `asgn_<opaque>`. Owning-team
|
|
11030
|
+
(`project.team`) grants are not created here — claim owns that path. An
|
|
11031
|
+
unrevoked grant with the same principal and relation occupies the unique
|
|
11032
|
+
key even after `expires_at`; DELETE it before re-creating.
|
|
11033
|
+
Create does not accept `expand`. The `user_id` and team locators
|
|
11034
|
+
return 201, whose `user` / `team` carry only `user_id` / `team_id`,
|
|
11035
|
+
and still 404 / 409 when the principal is missing or the tuple
|
|
11036
|
+
already exists. Creating by `user.identifier` answers 202 with no
|
|
11037
|
+
body on every outcome. Granting the session caller's own user is
|
|
11038
|
+
`grant.invalid` on either user locator. Read the grant back for
|
|
11039
|
+
identifier and display.
|
|
11040
|
+
|
|
11041
|
+
Accepts either a project secret (`oauth2`) or a user-bound Console
|
|
11042
|
+
session cookie (`nextgenSession`). Session callers are authorized as
|
|
11043
|
+
the human against the target project (home may differ). CSRF/Origin
|
|
11044
|
+
for cookie mutations is a follow-up (#1140).
|
|
10758
11045
|
|
|
10759
11046
|
* @summary Create grant
|
|
10760
11047
|
*/
|
|
@@ -10769,6 +11056,45 @@ const createGrant = async (createGrantBody, params, options) => {
|
|
|
10769
11056
|
body: JSON.stringify(createGrantBody)
|
|
10770
11057
|
});
|
|
10771
11058
|
};
|
|
11059
|
+
const getQueryGrantsUrl = (params) => {
|
|
11060
|
+
const normalizedParams = new URLSearchParams();
|
|
11061
|
+
Object.entries(params || {}).forEach(([key, value]) => {
|
|
11062
|
+
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : value.toString());
|
|
11063
|
+
});
|
|
11064
|
+
const stringifiedParams = normalizedParams.toString();
|
|
11065
|
+
return stringifiedParams.length > 0 ? `${getProxyPath()}/grants/query?${stringifiedParams}` : `${getProxyPath()}/grants/query`;
|
|
11066
|
+
};
|
|
11067
|
+
/**
|
|
11068
|
+
* Returns the collaboration grants of a project, paginated with a cursor.
|
|
11069
|
+
Only unrevoked grants this API manages are listed (user or team bound to
|
|
11070
|
+
viewer, editor, or admin), including expired grants so a client can
|
|
11071
|
+
DELETE before re-granting. Project-secret setup (`sk_proj`) and
|
|
11072
|
+
owning-team (`relation=team`) rows are not returned. Grants are not in
|
|
11073
|
+
`resource_scope_index`; project scope is required on the query (same as
|
|
11074
|
+
get). Requires `project.read`. `expand: ["principal"]` adds envelope
|
|
11075
|
+
fields on `user` / `team` and additionally requires `user.read` and
|
|
11076
|
+
`team.read` for project secrets (documented on the expand enum; those
|
|
11077
|
+
scopes cannot be ANDed onto this security block because they are
|
|
11078
|
+
body-conditional). A user-bound Console session that already passed
|
|
11079
|
+
the project Check may expand without those scopes.
|
|
11080
|
+
|
|
11081
|
+
Accepts either a project secret (`oauth2`) or a user-bound Console
|
|
11082
|
+
session cookie (`nextgenSession`). CSRF/Origin for cookie mutations
|
|
11083
|
+
is a follow-up (#1140).
|
|
11084
|
+
|
|
11085
|
+
* @summary Query grants
|
|
11086
|
+
*/
|
|
11087
|
+
const queryGrants = async (queryGrantsBody, params, options) => {
|
|
11088
|
+
return customFetch(getQueryGrantsUrl(params), {
|
|
11089
|
+
...options,
|
|
11090
|
+
method: "POST",
|
|
11091
|
+
headers: {
|
|
11092
|
+
"Content-Type": "application/json",
|
|
11093
|
+
...options?.headers
|
|
11094
|
+
},
|
|
11095
|
+
body: JSON.stringify(queryGrantsBody)
|
|
11096
|
+
});
|
|
11097
|
+
};
|
|
10772
11098
|
const getGetGrantUrl = (id, params) => {
|
|
10773
11099
|
const normalizedParams = new URLSearchParams();
|
|
10774
11100
|
Object.entries(params || {}).forEach(([key, value]) => {
|
|
@@ -10786,6 +11112,14 @@ still ignores expired grants. Grants are not registered in
|
|
|
10786
11112
|
`resource_scope_index`; project scope is required on the query (same as
|
|
10787
11113
|
events). Misses, revoked rows, project-secret setup (`sk_proj`),
|
|
10788
11114
|
owning-team (`relation=team`) rows, and cross-project ids return 404.
|
|
11115
|
+
`expand=principal` adds envelope fields on `user` or `team` and requires
|
|
11116
|
+
`user.read` and `team.read` in addition to `project.read` for project
|
|
11117
|
+
secrets. A user-bound Console session that already passed the project
|
|
11118
|
+
Check may expand without those scopes.
|
|
11119
|
+
|
|
11120
|
+
Accepts either a project secret (`oauth2`) or a user-bound Console
|
|
11121
|
+
session cookie (`nextgenSession`). CSRF/Origin for cookie mutations
|
|
11122
|
+
is a follow-up (#1140).
|
|
10789
11123
|
|
|
10790
11124
|
* @summary Get grant
|
|
10791
11125
|
*/
|
|
@@ -10809,6 +11143,10 @@ Already-revoked, missing, project-secret setup, and owning-team grants
|
|
|
10809
11143
|
return 404. The row is not un-revoked. Expired grants can still be
|
|
10810
11144
|
revoked so the unique binding can be reused.
|
|
10811
11145
|
|
|
11146
|
+
Accepts either a project secret (`oauth2`) or a user-bound Console
|
|
11147
|
+
session cookie (`nextgenSession`). CSRF/Origin for cookie mutations
|
|
11148
|
+
is a follow-up (#1140).
|
|
11149
|
+
|
|
10812
11150
|
* @summary Revoke grant
|
|
10813
11151
|
*/
|
|
10814
11152
|
const deleteGrant = async (id, params, options) => {
|
|
@@ -10875,6 +11213,122 @@ const getEvent = async (id, params, options) => {
|
|
|
10875
11213
|
method: "GET"
|
|
10876
11214
|
});
|
|
10877
11215
|
};
|
|
11216
|
+
const getGetVariablesUrl = (params) => {
|
|
11217
|
+
const normalizedParams = new URLSearchParams();
|
|
11218
|
+
Object.entries(params || {}).forEach(([key, value]) => {
|
|
11219
|
+
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : value.toString());
|
|
11220
|
+
});
|
|
11221
|
+
const stringifiedParams = normalizedParams.toString();
|
|
11222
|
+
return stringifiedParams.length > 0 ? `${getProxyPath()}/variables?${stringifiedParams}` : `${getProxyPath()}/variables`;
|
|
11223
|
+
};
|
|
11224
|
+
/**
|
|
11225
|
+
* Returns the variables entered at the owner this request addresses, keyed by
|
|
11226
|
+
name — one environment of the project with `environment_name`, the project
|
|
11227
|
+
level itself without it.
|
|
11228
|
+
|
|
11229
|
+
Owners are separate, not a ladder: an environment does not inherit the
|
|
11230
|
+
project's variables and the project does not see its environments'. Reading
|
|
11231
|
+
everything a project holds therefore means reading each owner in turn.
|
|
11232
|
+
|
|
11233
|
+
Secret values are not returned. A secret appears as `{"secret": true}`,
|
|
11234
|
+
which says a value is held without disclosing it.
|
|
11235
|
+
|
|
11236
|
+
* @summary Get variables
|
|
11237
|
+
*/
|
|
11238
|
+
const getVariables = async (params, options) => {
|
|
11239
|
+
return customFetch(getGetVariablesUrl(params), {
|
|
11240
|
+
...options,
|
|
11241
|
+
method: "GET"
|
|
11242
|
+
});
|
|
11243
|
+
};
|
|
11244
|
+
const getUpdateVariablesUrl = (params) => {
|
|
11245
|
+
const normalizedParams = new URLSearchParams();
|
|
11246
|
+
Object.entries(params || {}).forEach(([key, value]) => {
|
|
11247
|
+
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : value.toString());
|
|
11248
|
+
});
|
|
11249
|
+
const stringifiedParams = normalizedParams.toString();
|
|
11250
|
+
return stringifiedParams.length > 0 ? `${getProxyPath()}/variables?${stringifiedParams}` : `${getProxyPath()}/variables`;
|
|
11251
|
+
};
|
|
11252
|
+
/**
|
|
11253
|
+
* Enters, replaces and removes variables at the owner this request
|
|
11254
|
+
addresses.
|
|
11255
|
+
|
|
11256
|
+
Every name in the body is applied at exactly that owner — the project, or
|
|
11257
|
+
the environment named by `environment_name` — and reaches no other. Names
|
|
11258
|
+
not in the body are untouched.
|
|
11259
|
+
|
|
11260
|
+
A bare scalar enters a non-secret value. `{"value": …, "secret": true}`
|
|
11261
|
+
stores the value encrypted under the project's active `secret` key, after
|
|
11262
|
+
which it can be referenced but not read back. `null` removes the name from
|
|
11263
|
+
this owner (RFC 7386), which is how several variables are removed in one
|
|
11264
|
+
request; removing a name this owner does not hold is a no-op rather than an
|
|
11265
|
+
error.
|
|
11266
|
+
|
|
11267
|
+
The body is applied whole or not at all, so a rejected request leaves the
|
|
11268
|
+
owner exactly as it was. Writing the same name and owner twice replaces the
|
|
11269
|
+
value rather than duplicating it, which makes a retry safe.
|
|
11270
|
+
|
|
11271
|
+
* @summary Update variables
|
|
11272
|
+
*/
|
|
11273
|
+
const updateVariables = async (updateVariablesBody, params, options) => {
|
|
11274
|
+
return customFetch(getUpdateVariablesUrl(params), {
|
|
11275
|
+
...options,
|
|
11276
|
+
method: "PATCH",
|
|
11277
|
+
headers: {
|
|
11278
|
+
"Content-Type": "application/json",
|
|
11279
|
+
...options?.headers
|
|
11280
|
+
},
|
|
11281
|
+
body: JSON.stringify(updateVariablesBody)
|
|
11282
|
+
});
|
|
11283
|
+
};
|
|
11284
|
+
const getGetVariableUrl = (variableName, params) => {
|
|
11285
|
+
const normalizedParams = new URLSearchParams();
|
|
11286
|
+
Object.entries(params || {}).forEach(([key, value]) => {
|
|
11287
|
+
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : value.toString());
|
|
11288
|
+
});
|
|
11289
|
+
const stringifiedParams = normalizedParams.toString();
|
|
11290
|
+
return stringifiedParams.length > 0 ? `${getProxyPath()}/variables/${variableName}?${stringifiedParams}` : `${getProxyPath()}/variables/${variableName}`;
|
|
11291
|
+
};
|
|
11292
|
+
/**
|
|
11293
|
+
* Reads one variable by name from the owner this request addresses — one
|
|
11294
|
+
environment of the project with `environment_name`, the project level
|
|
11295
|
+
itself without it.
|
|
11296
|
+
|
|
11297
|
+
A name that owner has not entered answers `var.not_found`, even when
|
|
11298
|
+
another owner of the same project holds it: nothing is inherited. A secret
|
|
11299
|
+
is found but not disclosed: the response is `{"secret": true}`.
|
|
11300
|
+
|
|
11301
|
+
* @summary Get a variable
|
|
11302
|
+
*/
|
|
11303
|
+
const getVariable = async (variableName, params, options) => {
|
|
11304
|
+
return customFetch(getGetVariableUrl(variableName, params), {
|
|
11305
|
+
...options,
|
|
11306
|
+
method: "GET"
|
|
11307
|
+
});
|
|
11308
|
+
};
|
|
11309
|
+
const getDeleteVariableUrl = (variableName, params) => {
|
|
11310
|
+
const normalizedParams = new URLSearchParams();
|
|
11311
|
+
Object.entries(params || {}).forEach(([key, value]) => {
|
|
11312
|
+
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : value.toString());
|
|
11313
|
+
});
|
|
11314
|
+
const stringifiedParams = normalizedParams.toString();
|
|
11315
|
+
return stringifiedParams.length > 0 ? `${getProxyPath()}/variables/${variableName}?${stringifiedParams}` : `${getProxyPath()}/variables/${variableName}`;
|
|
11316
|
+
};
|
|
11317
|
+
/**
|
|
11318
|
+
* Removes the variable this owner entered under this name.
|
|
11319
|
+
|
|
11320
|
+
A variable is deletable only by the owner that entered it. Deleting a name
|
|
11321
|
+
another owner of the same project holds answers `var.not_found` and leaves
|
|
11322
|
+
that owner's value standing.
|
|
11323
|
+
|
|
11324
|
+
* @summary Delete a variable
|
|
11325
|
+
*/
|
|
11326
|
+
const deleteVariable = async (variableName, params, options) => {
|
|
11327
|
+
return customFetch(getDeleteVariableUrl(variableName, params), {
|
|
11328
|
+
...options,
|
|
11329
|
+
method: "DELETE"
|
|
11330
|
+
});
|
|
11331
|
+
};
|
|
10878
11332
|
//#endregion
|
|
10879
11333
|
//#region ../api/dist/runtime/api-factory.mjs
|
|
10880
11334
|
/**
|
|
@@ -13418,9 +13872,10 @@ function createSanitiser() {
|
|
|
13418
13872
|
* the `Branding` JSON into a CSSStyleSheet of `:host { --zl-* }` declarations
|
|
13419
13873
|
* and applies it via `shadowRoot.adoptedStyleSheets`.
|
|
13420
13874
|
*
|
|
13421
|
-
*
|
|
13422
|
-
*
|
|
13423
|
-
*
|
|
13875
|
+
* Light and dark are independent surfaces: each side's palette is emitted under
|
|
13876
|
+
* its own `data-theme` selector only, so a key the revision left unset on one
|
|
13877
|
+
* side takes the maintained default for that side rather than the other side's
|
|
13878
|
+
* colour. Resolution between `light | dark | auto` happens in `<zitadel-login>`.
|
|
13424
13879
|
*
|
|
13425
13880
|
* Base layer: the design-tokens package ships the full `--zl-*` set as both a
|
|
13426
13881
|
* `.css` file (for host pages) and a `tokensCss` string (for shadow roots and
|
|
@@ -13428,13 +13883,32 @@ function createSanitiser() {
|
|
|
13428
13883
|
* paint correctly even when the host page didn't `@import` tokens.css — the
|
|
13429
13884
|
* orchestrator is meant to drop into any page.
|
|
13430
13885
|
*/
|
|
13431
|
-
const
|
|
13432
|
-
|
|
13433
|
-
sm
|
|
13434
|
-
md
|
|
13435
|
-
lg
|
|
13436
|
-
|
|
13437
|
-
|
|
13886
|
+
const RADIUS_STEPS = [
|
|
13887
|
+
"xs",
|
|
13888
|
+
"sm",
|
|
13889
|
+
"md",
|
|
13890
|
+
"lg",
|
|
13891
|
+
"xl"
|
|
13892
|
+
];
|
|
13893
|
+
const RADIUS_RATIOS = (() => {
|
|
13894
|
+
const base = remToNumber(tokens.radius.md);
|
|
13895
|
+
const ratios = {};
|
|
13896
|
+
for (const step of RADIUS_STEPS) ratios[step] = remToNumber(tokens.radius[step]) / base;
|
|
13897
|
+
return ratios;
|
|
13898
|
+
})();
|
|
13899
|
+
const RADIUS_PRESETS = {
|
|
13900
|
+
none: 0,
|
|
13901
|
+
sm: .25,
|
|
13902
|
+
md: .5,
|
|
13903
|
+
lg: .75
|
|
13904
|
+
};
|
|
13905
|
+
const TEXT_STEPS = [
|
|
13906
|
+
"xs",
|
|
13907
|
+
"sm",
|
|
13908
|
+
"base",
|
|
13909
|
+
"lg",
|
|
13910
|
+
"xl"
|
|
13911
|
+
];
|
|
13438
13912
|
const DENSITY_MAP = {
|
|
13439
13913
|
compact: {
|
|
13440
13914
|
"--zl-spacing-4": "0.75rem",
|
|
@@ -13486,34 +13960,35 @@ const PALETTE_MAP = {
|
|
|
13486
13960
|
* the moment before a theme resolves.
|
|
13487
13961
|
*/
|
|
13488
13962
|
const BRANDING_SELECTOR = ":host, :host([data-theme=\"light\"]), :host([data-theme=\"dark\"])";
|
|
13489
|
-
/**
|
|
13963
|
+
/** Per-side palettes. Emitted after {@link BRANDING_SELECTOR}, so they win on order. */
|
|
13964
|
+
const LIGHT_SELECTOR = ":host([data-theme=\"light\"])";
|
|
13490
13965
|
const DARK_SELECTOR = ":host([data-theme=\"dark\"])";
|
|
13491
13966
|
/**
|
|
13492
13967
|
* Build a CSS string of `:host { --zl-* }` declarations from a Branding
|
|
13493
|
-
* payload.
|
|
13494
|
-
*
|
|
13495
|
-
|
|
13496
|
-
|
|
13497
|
-
|
|
13498
|
-
|
|
13499
|
-
|
|
13968
|
+
* payload. Shape and typography are shared across the sides and land on the
|
|
13969
|
+
* shared selector; each side's palette lands only under its own `data-theme`
|
|
13970
|
+
* selector, and nowhere else.
|
|
13971
|
+
*
|
|
13972
|
+
* No copy of the resolved side goes on the shared selector. That copy would
|
|
13973
|
+
* reach `[data-theme="light"]` as well, so a key set on the dark side and not
|
|
13974
|
+
* the light one would paint on both, with nothing in the light block to
|
|
13975
|
+
* override it. Callers stamp `data-theme` on the host — `applySurfaceTheme`
|
|
13976
|
+
* does it in the same update that adopts this sheet — so the per-side block is
|
|
13977
|
+
* already matching by the time anything paints.
|
|
13978
|
+
*/
|
|
13979
|
+
function buildBrandingStylesheet(branding) {
|
|
13980
|
+
const shared = collectDeclarations(branding);
|
|
13981
|
+
const light = mapPalette(branding?.theme?.light?.palette);
|
|
13982
|
+
const dark = mapPalette(branding?.theme?.dark?.palette);
|
|
13500
13983
|
const blocks = [];
|
|
13501
|
-
if (Object.keys(
|
|
13502
|
-
if (Object.keys(
|
|
13503
|
-
if (
|
|
13504
|
-
const merged = {
|
|
13505
|
-
...lightDecls,
|
|
13506
|
-
...darkDecls
|
|
13507
|
-
};
|
|
13508
|
-
blocks.length = 0;
|
|
13509
|
-
blocks.push(formatBlock(BRANDING_SELECTOR, merged));
|
|
13510
|
-
}
|
|
13984
|
+
if (Object.keys(shared).length > 0) blocks.push(formatBlock(BRANDING_SELECTOR, shared));
|
|
13985
|
+
if (Object.keys(light).length > 0) blocks.push(formatBlock(LIGHT_SELECTOR, light));
|
|
13986
|
+
if (Object.keys(dark).length > 0) blocks.push(formatBlock(DARK_SELECTOR, dark));
|
|
13511
13987
|
return blocks.join("\n");
|
|
13512
13988
|
}
|
|
13513
13989
|
function collectDeclarations(branding) {
|
|
13514
13990
|
if (!branding) return {};
|
|
13515
13991
|
const decls = {};
|
|
13516
|
-
Object.assign(decls, mapPalette(branding.palette));
|
|
13517
13992
|
Object.assign(decls, mapTypography(branding.typography));
|
|
13518
13993
|
Object.assign(decls, mapShape(branding.shape));
|
|
13519
13994
|
return decls;
|
|
@@ -13534,24 +14009,52 @@ function mapTypography(typography) {
|
|
|
13534
14009
|
out["--zl-font-family-sans"] = typography.font_family;
|
|
13535
14010
|
out["--zl-font-family-heading"] = typography.font_family;
|
|
13536
14011
|
}
|
|
13537
|
-
if (typography.font_family_heading) out["--zl-font-family-heading"] = typography.font_family_heading;
|
|
13538
|
-
if (typography.font_family_mono) out["--zl-font-family-mono"] = typography.font_family_mono;
|
|
13539
14012
|
const scale = clamp(typography.scale ?? 1, .75, 1.25);
|
|
13540
|
-
if (scale !== 1)
|
|
14013
|
+
if (scale !== 1) for (const step of TEXT_STEPS) {
|
|
14014
|
+
out[`--zl-text-${step}-size`] = scaleRem(tokens.text[step].size, scale);
|
|
14015
|
+
out[`--zl-text-${step}-leading`] = scaleRem(tokens.text[step].leading, scale);
|
|
14016
|
+
}
|
|
13541
14017
|
return out;
|
|
13542
14018
|
}
|
|
13543
14019
|
function mapShape(shape) {
|
|
13544
14020
|
if (!shape) return {};
|
|
13545
14021
|
const out = {};
|
|
13546
|
-
|
|
13547
|
-
const radius = RADIUS_MAP[shape.radius];
|
|
13548
|
-
out["--zl-radius-md"] = radius;
|
|
13549
|
-
out["--zl-radius-lg"] = radius === "0" ? "0" : `calc(${radius} * 1.25)`;
|
|
13550
|
-
out["--zl-radius-xl"] = radius === "0" ? "0" : `calc(${radius} * 1.75)`;
|
|
13551
|
-
}
|
|
14022
|
+
Object.assign(out, mapRadius(shape.radius));
|
|
13552
14023
|
if (shape.density) Object.assign(out, DENSITY_MAP[shape.density]);
|
|
14024
|
+
const logoScale = shape.logo_scale;
|
|
14025
|
+
if (typeof logoScale === "number" && Number.isFinite(logoScale)) out["--zl-logo-scale"] = `${clamp(logoScale, .5, 2)}`;
|
|
14026
|
+
return out;
|
|
14027
|
+
}
|
|
14028
|
+
/**
|
|
14029
|
+
* A brand picks one corner value and the whole ramp follows it in proportion,
|
|
14030
|
+
* which is what keeps the card rounder than the controls inside it. Both forms
|
|
14031
|
+
* the revision accepts land here: a preset name, or an integer number of pixels
|
|
14032
|
+
* for the brand that has a specific value.
|
|
14033
|
+
*/
|
|
14034
|
+
function mapRadius(radius) {
|
|
14035
|
+
if (radius == null) return {};
|
|
14036
|
+
const out = {};
|
|
14037
|
+
if (radius === "full") {
|
|
14038
|
+
for (const step of RADIUS_STEPS) out[`--zl-radius-${step}`] = tokens.radius.full;
|
|
14039
|
+
return out;
|
|
14040
|
+
}
|
|
14041
|
+
const [base, unit] = typeof radius === "number" ? [radius, "px"] : radius in RADIUS_PRESETS ? [RADIUS_PRESETS[radius], "rem"] : [NaN, ""];
|
|
14042
|
+
if (Number.isNaN(base)) return {};
|
|
14043
|
+
for (const step of RADIUS_STEPS) {
|
|
14044
|
+
const value = base * RADIUS_RATIOS[step];
|
|
14045
|
+
out[`--zl-radius-${step}`] = value === 0 ? "0" : `${round(value)}${unit}`;
|
|
14046
|
+
}
|
|
13553
14047
|
return out;
|
|
13554
14048
|
}
|
|
14049
|
+
function scaleRem(value, scale) {
|
|
14050
|
+
return `${round(remToNumber(value) * scale)}rem`;
|
|
14051
|
+
}
|
|
14052
|
+
function remToNumber(value) {
|
|
14053
|
+
return Number.parseFloat(value);
|
|
14054
|
+
}
|
|
14055
|
+
function round(value) {
|
|
14056
|
+
return Math.round(value * 1e4) / 1e4;
|
|
14057
|
+
}
|
|
13555
14058
|
function formatBlock(selector, decls) {
|
|
13556
14059
|
return `${selector} {\n${Object.entries(decls).map(([prop, value]) => ` ${prop}: ${value};`).join("\n")}\n}`;
|
|
13557
14060
|
}
|
|
@@ -13591,8 +14094,8 @@ function applyBaseTokens(shadowRoot) {
|
|
|
13591
14094
|
* Callers should run `applyBaseTokens(shadowRoot)` first (once per shadow
|
|
13592
14095
|
* root) so the base values exist before branding patches them.
|
|
13593
14096
|
*/
|
|
13594
|
-
function applyBrandingTokens(shadowRoot, branding
|
|
13595
|
-
const css = buildBrandingStylesheet(branding
|
|
14097
|
+
function applyBrandingTokens(shadowRoot, branding) {
|
|
14098
|
+
const css = buildBrandingStylesheet(branding);
|
|
13596
14099
|
if (typeof CSSStyleSheet === "undefined") return;
|
|
13597
14100
|
const sheet = new CSSStyleSheet();
|
|
13598
14101
|
sheet.replaceSync(css);
|
|
@@ -13607,9 +14110,11 @@ function applyBrandingTokens(shadowRoot, branding, resolvedTheme) {
|
|
|
13607
14110
|
* and a variant-derived fallback on top of the same branding input.
|
|
13608
14111
|
*
|
|
13609
14112
|
* Defaults to dark: the design system's primary surface, and the mode a
|
|
13610
|
-
* hosted login page renders when a
|
|
14113
|
+
* hosted login page renders when a revision states no preference.
|
|
13611
14114
|
*/
|
|
13612
14115
|
function resolveTheme(branding) {
|
|
14116
|
+
const [only, second] = publishedSides(branding);
|
|
14117
|
+
if (only && !second) return only;
|
|
13613
14118
|
const mode = branding?.theme?.mode ?? "dark";
|
|
13614
14119
|
if (mode === "light") return "light";
|
|
13615
14120
|
if (mode === "dark") return "dark";
|
|
@@ -13627,7 +14132,7 @@ function resolveTheme(branding) {
|
|
|
13627
14132
|
* (Arimo, named first in `--zl-font-family-sans`). The component ships this
|
|
13628
14133
|
* so the auth screens render in the brand font out of the box, even when the
|
|
13629
14134
|
* server returns no branding. This is the "default users can override" layer.
|
|
13630
|
-
* - The **tenant override** (`applyFontUrl`) — `branding.font_url`, resolved
|
|
14135
|
+
* - The **tenant override** (`applyFontUrl`) — `branding.typography.font_url`, resolved
|
|
13631
14136
|
* server-side from the app → team → project branding hierarchy.
|
|
13632
14137
|
*
|
|
13633
14138
|
* Both must live at document level, not inside the shadow root: browsers ignore
|
|
@@ -13656,7 +14161,7 @@ const DEFAULT_LINK_ID = "zl-default-font-link";
|
|
|
13656
14161
|
* Design-system default brand font. Arimo is the Figma body face and leads the
|
|
13657
14162
|
* `--zl-font-family-sans` stack; loading it here makes the unbranded auth UI
|
|
13658
14163
|
* paint in the brand font instead of the system fallback. Tenants override it
|
|
13659
|
-
* with `branding.font_url`. Exported so a privacy- or offline-sensitive
|
|
14164
|
+
* with `branding.typography.font_url`. Exported so a privacy- or offline-sensitive
|
|
13660
14165
|
* deployment can self-host the same face and swap this single URL.
|
|
13661
14166
|
*/
|
|
13662
14167
|
const DEFAULT_BRAND_FONT_HREF = "https://fonts.googleapis.com/css2?family=Arimo:ital,wght@0,400;0,500;0,600;0,700;1,400&display=swap";
|
|
@@ -13676,7 +14181,7 @@ const DEFAULT_BRAND_FONT_HREF = "https://fonts.googleapis.com/css2?family=Arimo:
|
|
|
13676
14181
|
/** Per-document, per-link-id map of each owner's desired href. */
|
|
13677
14182
|
const registries = /* @__PURE__ */ new WeakMap();
|
|
13678
14183
|
/**
|
|
13679
|
-
* Inject the tenant's `branding.font_url` stylesheet. Pass `null`/`undefined`
|
|
14184
|
+
* Inject the tenant's `branding.typography.font_url` stylesheet. Pass `null`/`undefined`
|
|
13680
14185
|
* to withdraw this surface's registration (e.g. when a flow resolves with no
|
|
13681
14186
|
* tenant font); the link disappears once no surface registers a URL.
|
|
13682
14187
|
*/
|
|
@@ -13686,7 +14191,7 @@ function applyFontUrl(shadowRoot, fontUrl) {
|
|
|
13686
14191
|
/**
|
|
13687
14192
|
* Inject the design-system default font stylesheet. Defaults to
|
|
13688
14193
|
* {@link DEFAULT_BRAND_FONT_HREF}; pass `null` to withdraw this surface's
|
|
13689
|
-
* registration (the orchestrator does this when a tenant
|
|
14194
|
+
* registration (the orchestrator does this when a tenant font stylesheet takes
|
|
13690
14195
|
* over, to avoid a redundant request).
|
|
13691
14196
|
*/
|
|
13692
14197
|
function applyDefaultFont(shadowRoot, href = DEFAULT_BRAND_FONT_HREF) {
|
|
@@ -13753,7 +14258,10 @@ var ThemeController = class {
|
|
|
13753
14258
|
* element nor the branding payload names a mode. Precedence, strongest
|
|
13754
14259
|
* first: element `theme` property → `branding.theme.mode` → fallback. The
|
|
13755
14260
|
* element wins because the page embedding the widget knows its own surface
|
|
13756
|
-
* better than the tenant's stored branding does
|
|
14261
|
+
* better than the tenant's stored branding does — but it selects among the
|
|
14262
|
+
* sides the revision published, and cannot reach one it did not. A revision
|
|
14263
|
+
* with a single published side therefore ignores this property: an embedder
|
|
14264
|
+
* pinning `theme="light"` against a dark-only revision gets dark.
|
|
13757
14265
|
*/
|
|
13758
14266
|
setModePreference(explicit, fallback) {
|
|
13759
14267
|
if (this.explicitMode === explicit && this.fallbackMode === fallback) return;
|
|
@@ -13768,6 +14276,12 @@ var ThemeController = class {
|
|
|
13768
14276
|
this.detach();
|
|
13769
14277
|
}
|
|
13770
14278
|
refresh() {
|
|
14279
|
+
const [only, second] = publishedSides(this.branding);
|
|
14280
|
+
if (only && !second) {
|
|
14281
|
+
this.detach();
|
|
14282
|
+
this.update(only);
|
|
14283
|
+
return;
|
|
14284
|
+
}
|
|
13771
14285
|
const mode = this.explicitMode ?? this.branding?.theme?.mode ?? this.fallbackMode;
|
|
13772
14286
|
if (mode === "auto") {
|
|
13773
14287
|
this.attach();
|
|
@@ -13846,9 +14360,10 @@ var ZitadelSurface = class extends i$2 {
|
|
|
13846
14360
|
const root = this.shadowRoot;
|
|
13847
14361
|
if (root) {
|
|
13848
14362
|
applyBaseTokens(root);
|
|
13849
|
-
applyBrandingTokens(root, branding
|
|
13850
|
-
const
|
|
13851
|
-
|
|
14363
|
+
applyBrandingTokens(root, branding);
|
|
14364
|
+
const page = this.variant === "page";
|
|
14365
|
+
const tenantFontUrl = page ? branding?.typography?.font_url ?? null : null;
|
|
14366
|
+
applyDefaultFont(root, page && !tenantFontUrl ? void 0 : null);
|
|
13852
14367
|
applyFontUrl(root, tenantFontUrl);
|
|
13853
14368
|
}
|
|
13854
14369
|
this.dataset.theme = this.themeController.theme;
|
|
@@ -13884,7 +14399,7 @@ const TEMPLATE_NAMES = {
|
|
|
13884
14399
|
};
|
|
13885
14400
|
//#endregion
|
|
13886
14401
|
//#region src/orchestrator/templates/layout-chrome.css?inline
|
|
13887
|
-
var layout_chrome_default = ":host {\n color: var(--zl-foreground);\n font-family: var(--zl-font-family-sans);\n background: none;\n display: block;\n}\n\n:host([variant=\"page\"]) {\n background: var(--zl-background);\n min-height: 100%;\n}\n\nimg[data-zl-asset-broken] {\n display: none;\n}\n\n.zl-mount {\n min-height: var(--zl-page-min-height, auto);\n background: inherit;\n color: inherit;\n flex-direction: column;\n display: flex;\n container-type: inline-size;\n}\n\n:host([variant=\"page\"]) .zl-mount {\n min-height: var(--zl-page-min-height, 100vh);\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-trustmark {\n gap: var(--zl-spacing-2-5);\n flex-wrap: wrap;\n}\n\n.zl-trustmark__mark {\n align-items: center;\n gap: var(--zl-spacing-2);\n font-family: var(--zl-font-family-sans);\n font-size: var(--zl-text-sm-size);\n line-height: var(--zl-text-sm-leading);\n color: var(--zl-foreground);\n text-decoration: none;\n display: inline-flex;\n}\n\n.zl-trustmark__mark:hover {\n text-underline-offset: 4px;\n text-decoration: underline;\n}\n\n.zl-trustmark__mark:focus-visible {\n outline: var(--zl-focus-width) solid var(--zl-ring);\n outline-offset: var(--zl-focus-offset);\n border-radius: var(--zl-radius-sm);\n}\n\n.zl-trustmark__logotype {\n flex-shrink: 0;\n width: 65px;\n height: 16px;\n line-height: 0;\n display: block;\n}\n\n.zl-trustmark__logotype-svg {\n width: 100%;\n height: 100%;\n display: block;\n}\n\n.zl-card-logo {\n width: auto;\n max-width: min(12rem, 60%);\n max-height: var(--zl-card-logo-max-height, 2.5rem);\n object-fit: contain;\n}\n\n.zl-card-title {\n font-family: var(--zl-font-family-heading);\n font-size: var(--zl-text-xl-size);\n font-weight: var(--zl-font-weight-medium);\n color: var(--zl-card-foreground);\n text-align: left;\n margin: 0;\n line-height: 1;\n}\n\n.zl-card-subtitle {\n font-family: var(--zl-font-family-sans);\n font-size: var(--zl-text-sm-size);\n line-height: var(--zl-text-sm-leading);\n font-weight: var(--zl-font-weight-normal);\n color: var(--zl-muted-foreground);\n margin: 0;\n}\n\n.zl-field-group {\n gap: var(--zl-spacing-7);\n flex-direction: column;\n display: flex;\n}\n\n.zl-field-group:not(:has(*)) {\n display: none;\n}\n\n.zl-card-actions {\n gap: var(--zl-spacing-3);\n flex-direction: column;\n display: flex;\n}\n\n[data-suppress-header] .zl-card-title, [data-suppress-header] .zl-card-subtitle {\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n position: absolute;\n overflow: hidden;\n}\n\n.zl-card-nav {\n font-family: var(--zl-font-family-sans);\n font-size: var(--zl-text-sm-size);\n line-height: var(--zl-text-sm-leading);\n font-weight: var(--zl-font-weight-normal);\n color: var(--zl-muted-foreground);\n text-align: center;\n margin: 0;\n}\n\n.zl-card-nav__link {\n font: inherit;\n line-height: inherit;\n color: var(--zl-link);\n text-underline-offset: 4px;\n cursor: pointer;\n background: none;\n border: none;\n margin: 0;\n padding: 0;\n text-decoration: underline;\n display: inline;\n}\n\n.zl-card-nav__link:hover {\n color: var(--zl-foreground);\n}\n\n.zl-card-nav__link:focus-visible {\n outline: var(--zl-focus-width) solid var(--zl-ring);\n outline-offset: var(--zl-focus-offset);\n}\n\n.zl-card-forgot {\n text-align: right;\n margin: 0;\n}\n\n.zl-card-forgot__link {\n font-family: var(--zl-font-family-sans);\n font-size: var(--zl-text-sm-size);\n line-height: var(--zl-text-sm-leading);\n font-weight: var(--zl-font-weight-normal);\n color: var(--zl-link);\n text-underline-offset: 4px;\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-forgot__link:hover {\n text-decoration: underline;\n}\n\n.zl-card-forgot__link:focus-visible {\n outline: var(--zl-focus-width) solid var(--zl-ring);\n outline-offset: var(--zl-focus-offset);\n}\n\n.zl-split {\n grid-template-columns: var(--zl-split-columns, minmax(0, 1fr) minmax(0, 1fr));\n align-items: var(--zl-split-align, center);\n gap: var(--zl-spacing-8);\n width: 100%;\n min-height: 100%;\n display: grid;\n}\n\n.zl-split__brand {\n justify-content: center;\n align-items: center;\n gap: var(--zl-spacing-6);\n padding: var(--zl-spacing-8) var(--zl-spacing-4);\n flex-direction: column;\n display: flex;\n}\n\n.zl-split__logo {\n max-width: min(16rem, 60%);\n max-height: var(--zl-split-logo-max-height, 16rem);\n}\n\n.zl-split__logo:has( + .zl-split__hero) {\n max-height: var(--zl-split-logo-max-height, 8rem);\n}\n\n.zl-split__logo:has( + .zl-split__hero) + .zl-split__hero {\n max-height: min(var(--zl-split-hero-max-height, 22.5rem),\n max(6rem,\n calc(100vh - 104px - var(--zl-spacing-8) - var(--zl-spacing-8) -\n 2.5rem - var(--zl-spacing-6) - var(--zl-spacing-6) -\n var(--zl-split-logo-max-height, 8rem))));\n}\n\n.zl-split__hero {\n width: 100%;\n max-height: var(--zl-split-hero-max-height, min(22.5rem, 60vh));\n border-radius: var(--zl-radius-lg);\n object-fit: cover;\n}\n\n.zl-split__placeholder {\n aspect-ratio: 4 / 5;\n border-radius: var(--zl-radius-lg);\n background: radial-gradient(120% 120% at 18% 12%,\n var(--zl-gradient-lavender-start) 0%,\n transparent 60%),\n radial-gradient(130% 130% at 85% 92%,\n var(--zl-gradient-rose-start) 0%,\n transparent 60%),\n var(--zl-card);\n width: min(18rem, 85%);\n}\n\n.zl-split__form {\n justify-content: center;\n align-items: center;\n gap: var(--zl-spacing-6);\n flex-direction: column;\n padding: 16px;\n display: flex;\n}\n\n.zl-split__compact {\n max-width: min(12rem, 60%);\n display: none;\n}\n\nimg.zl-split__compact {\n max-height: 2.5rem;\n}\n\nimg.zl-split__compact--hero {\n border-radius: var(--zl-radius-lg);\n object-fit: cover;\n width: 100%;\n max-width: 100%;\n max-height: 6rem;\n}\n\n.zl-split--right .zl-split__brand {\n order: 2;\n}\n\n.zl-split--right .zl-split__form {\n order: 1;\n}\n\nzl-page-shell:has(.zl-split) [slot=\"footer\"].zl-attribution {\n grid-template-columns: var(--zl-split-columns, minmax(0, 1fr) minmax(0, 1fr));\n gap: var(--zl-spacing-8);\n width: 100%;\n display: grid;\n}\n\nzl-page-shell:has(.zl-split) [slot=\"footer\"].zl-attribution > * {\n grid-column: 2;\n justify-self: center;\n}\n\nzl-page-shell:has(.zl-split--right) [slot=\"footer\"].zl-attribution > * {\n grid-column: 1;\n}\n\n@container (width <= 48rem) {\n .zl-split {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .zl-split__brand {\n display: var(--zl-split-brand-mobile, none);\n }\n\n .zl-split__compact {\n display: block;\n }\n\n zl-page-shell:has(.zl-split) [slot=\"footer\"].zl-attribution {\n grid-template-columns: minmax(0, 1fr);\n }\n\n zl-page-shell:has(.zl-split) .zl-attribution > *, zl-page-shell:has(.zl-split--right) [slot=\"footer\"].zl-attribution > * {\n grid-column: 1;\n }\n}\n\n.zl-hero {\n text-align: left;\n width: 100%;\n max-width: 34rem;\n color: var(--zl-foreground);\n font-family: var(--zl-font-family-sans);\n flex-direction: column;\n display: flex;\n}\n\n.zl-hero__nav {\n margin-bottom: var(--zl-spacing-8);\n justify-content: space-between;\n align-items: center;\n display: flex;\n}\n\n.zl-hero__brand {\n align-items: center;\n gap: var(--zl-spacing-2);\n letter-spacing: -.01em;\n font-size: 1.125rem;\n font-weight: 700;\n display: inline-flex;\n}\n\n.zl-hero__brand-logo {\n max-height: 1.75rem;\n}\n\n.zl-hero__brand-mark {\n border-radius: var(--zl-radius-md);\n background: linear-gradient(135deg,\n var(--zl-gradient-lavender-start),\n var(--zl-gradient-rose-start));\n width: 1.75rem;\n height: 1.75rem;\n display: inline-flex;\n}\n\n.zl-hero__compact-brand {\n overflow-wrap: anywhere;\n letter-spacing: -.01em;\n max-width: 100%;\n color: var(--zl-foreground);\n margin: 0;\n font-size: 1.125rem;\n font-weight: 700;\n}\n\n.zl-hero__nav-links {\n gap: var(--zl-spacing-6);\n color: var(--zl-muted-foreground);\n font-size: .9375rem;\n display: flex;\n}\n\n.zl-hero__nav-links a {\n color: inherit;\n text-decoration: none;\n}\n\n.zl-hero__nav-links a:hover {\n text-decoration: underline;\n}\n\n.zl-hero__eyebrow {\n margin: 0 0 var(--zl-spacing-4);\n letter-spacing: .08em;\n text-transform: uppercase;\n color: var(--zl-muted-foreground);\n font-size: .8125rem;\n font-weight: 600;\n}\n\n.zl-hero__headline {\n margin: 0 0 var(--zl-spacing-4);\n font-family: var(--zl-font-family-heading);\n letter-spacing: -.02em;\n font-size: 2.75rem;\n font-weight: 700;\n line-height: 1.1;\n}\n\n.zl-hero__sub {\n margin: 0 0 var(--zl-spacing-8);\n max-width: 30rem;\n color: var(--zl-muted-foreground);\n font-size: 1.0625rem;\n line-height: 1.6;\n}\n\n.zl-hero__bullets {\n gap: var(--zl-spacing-2);\n margin: 0 0 var(--zl-spacing-8);\n flex-direction: column;\n padding: 0;\n list-style: none;\n display: flex;\n}\n\n.zl-hero__bullets li {\n align-items: center;\n gap: var(--zl-spacing-2);\n font-size: 1rem;\n display: flex;\n}\n\n.zl-hero__bullets li:before {\n content: \"✓\";\n color: var(--zl-success);\n font-weight: 700;\n}\n\n.zl-hero__footnote {\n padding-top: var(--zl-spacing-6);\n border-top: 1px solid var(--zl-border);\n color: var(--zl-muted-foreground);\n margin: 0;\n font-size: .8125rem;\n}\n\n.zl-hero__footnote strong {\n color: var(--zl-muted-foreground);\n font-weight: 600;\n}\n\n.zl-minimal {\n gap: var(--zl-spacing-6);\n flex-direction: column;\n width: min(24rem, 100%);\n margin-inline: auto;\n display: flex;\n}\n\n:host([variant=\"page\"]) .zl-minimal {\n padding: 52px 16px;\n}\n";
|
|
14402
|
+
var layout_chrome_default = ":host {\n color: var(--zl-foreground);\n font-family: var(--zl-font-family-sans);\n background: none;\n display: block;\n}\n\n:host([variant=\"page\"]) {\n background: var(--zl-background);\n min-height: 100%;\n}\n\nimg[data-zl-asset-broken] {\n display: none;\n}\n\n.zl-mount {\n min-height: var(--zl-page-min-height, auto);\n background: inherit;\n color: inherit;\n flex-direction: column;\n display: flex;\n container-type: inline-size;\n}\n\n:host([variant=\"page\"]) .zl-mount {\n min-height: var(--zl-page-min-height, 100vh);\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-trustmark {\n gap: var(--zl-spacing-2-5);\n flex-wrap: wrap;\n}\n\n.zl-trustmark__mark {\n align-items: center;\n gap: var(--zl-spacing-2);\n font-family: var(--zl-font-family-sans);\n font-size: var(--zl-text-sm-size);\n line-height: var(--zl-text-sm-leading);\n color: var(--zl-foreground);\n text-decoration: none;\n display: inline-flex;\n}\n\n.zl-trustmark__mark:hover {\n text-underline-offset: 4px;\n text-decoration: underline;\n}\n\n.zl-trustmark__mark:focus-visible {\n outline: var(--zl-focus-width) solid var(--zl-ring);\n outline-offset: var(--zl-focus-offset);\n border-radius: var(--zl-radius-sm);\n}\n\n.zl-trustmark__logotype {\n flex-shrink: 0;\n width: 65px;\n height: 16px;\n line-height: 0;\n display: block;\n}\n\n.zl-trustmark__logotype-svg {\n width: 100%;\n height: 100%;\n display: block;\n}\n\n.zl-card-logo {\n width: auto;\n max-width: min(12rem, 60%);\n max-height: calc(var(--zl-card-logo-max-height, 2.5rem) * var(--zl-logo-scale, 1));\n object-fit: contain;\n}\n\n.zl-card-title {\n font-family: var(--zl-font-family-heading);\n font-size: var(--zl-text-xl-size);\n font-weight: var(--zl-font-weight-medium);\n color: var(--zl-card-foreground);\n text-align: left;\n margin: 0;\n line-height: 1;\n}\n\n.zl-card-subtitle {\n font-family: var(--zl-font-family-sans);\n font-size: var(--zl-text-sm-size);\n line-height: var(--zl-text-sm-leading);\n font-weight: var(--zl-font-weight-normal);\n color: var(--zl-muted-foreground);\n margin: 0;\n}\n\n.zl-field-group {\n gap: var(--zl-spacing-7);\n flex-direction: column;\n display: flex;\n}\n\n.zl-field-group:not(:has(*)) {\n display: none;\n}\n\n.zl-card-actions {\n gap: var(--zl-spacing-3);\n flex-direction: column;\n display: flex;\n}\n\n[data-suppress-header] .zl-card-title, [data-suppress-header] .zl-card-subtitle {\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n position: absolute;\n overflow: hidden;\n}\n\n.zl-card-nav {\n font-family: var(--zl-font-family-sans);\n font-size: var(--zl-text-sm-size);\n line-height: var(--zl-text-sm-leading);\n font-weight: var(--zl-font-weight-normal);\n color: var(--zl-muted-foreground);\n text-align: center;\n margin: 0;\n}\n\n.zl-card-nav__link {\n font: inherit;\n line-height: inherit;\n color: var(--zl-link);\n text-underline-offset: 4px;\n cursor: pointer;\n background: none;\n border: none;\n margin: 0;\n padding: 0;\n text-decoration: underline;\n display: inline;\n}\n\n.zl-card-nav__link:hover {\n color: var(--zl-foreground);\n}\n\n.zl-card-nav__link:focus-visible {\n outline: var(--zl-focus-width) solid var(--zl-ring);\n outline-offset: var(--zl-focus-offset);\n}\n\n.zl-card-forgot {\n text-align: right;\n margin: 0;\n}\n\n.zl-card-forgot__link {\n font-family: var(--zl-font-family-sans);\n font-size: var(--zl-text-sm-size);\n line-height: var(--zl-text-sm-leading);\n font-weight: var(--zl-font-weight-normal);\n color: var(--zl-link);\n text-underline-offset: 4px;\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-forgot__link:hover {\n text-decoration: underline;\n}\n\n.zl-card-forgot__link:focus-visible {\n outline: var(--zl-focus-width) solid var(--zl-ring);\n outline-offset: var(--zl-focus-offset);\n}\n\n.zl-split {\n grid-template-columns: var(--zl-split-columns, minmax(0, 1fr) minmax(0, 1fr));\n align-items: var(--zl-split-align, center);\n gap: var(--zl-spacing-8);\n width: 100%;\n min-height: 100%;\n display: grid;\n}\n\n.zl-split__brand {\n justify-content: center;\n align-items: center;\n gap: var(--zl-spacing-6);\n padding: var(--zl-spacing-8) var(--zl-spacing-4);\n flex-direction: column;\n display: flex;\n}\n\n.zl-split__logo {\n max-width: min(16rem, 60%);\n max-height: calc(var(--zl-split-logo-max-height, 16rem) * var(--zl-logo-scale, 1));\n}\n\n.zl-split__logo:has( + .zl-split__hero) {\n max-height: calc(var(--zl-split-logo-max-height, 8rem) * var(--zl-logo-scale, 1));\n}\n\n.zl-split__logo:has( + .zl-split__hero) + .zl-split__hero {\n max-height: min(var(--zl-split-hero-max-height, 22.5rem),\n max(6rem,\n calc(100vh - 104px - var(--zl-spacing-8) - var(--zl-spacing-8) -\n 2.5rem - var(--zl-spacing-6) - var(--zl-spacing-6) -\n calc(var(--zl-split-logo-max-height, 8rem) * var(--zl-logo-scale, 1)))));\n}\n\n.zl-split__hero {\n width: 100%;\n max-height: var(--zl-split-hero-max-height, min(22.5rem, 60vh));\n border-radius: var(--zl-radius-lg);\n object-fit: cover;\n}\n\n.zl-split__placeholder {\n aspect-ratio: 4 / 5;\n border-radius: var(--zl-radius-lg);\n background: radial-gradient(120% 120% at 18% 12%,\n var(--zl-gradient-lavender-start) 0%,\n transparent 60%),\n radial-gradient(130% 130% at 85% 92%,\n var(--zl-gradient-rose-start) 0%,\n transparent 60%),\n var(--zl-card);\n width: min(18rem, 85%);\n}\n\n.zl-split__form {\n justify-content: center;\n align-items: center;\n gap: var(--zl-spacing-6);\n flex-direction: column;\n padding: 16px;\n display: flex;\n}\n\n.zl-split__compact {\n max-width: min(12rem, 60%);\n display: none;\n}\n\nimg.zl-split__compact {\n max-height: calc(2.5rem * var(--zl-logo-scale, 1));\n}\n\nimg.zl-split__compact--hero {\n border-radius: var(--zl-radius-lg);\n object-fit: cover;\n width: 100%;\n max-width: 100%;\n max-height: 6rem;\n}\n\n.zl-split--right .zl-split__brand {\n order: 2;\n}\n\n.zl-split--right .zl-split__form {\n order: 1;\n}\n\nzl-page-shell:has(.zl-split) [slot=\"footer\"].zl-attribution {\n grid-template-columns: var(--zl-split-columns, minmax(0, 1fr) minmax(0, 1fr));\n gap: var(--zl-spacing-8);\n width: 100%;\n display: grid;\n}\n\nzl-page-shell:has(.zl-split) [slot=\"footer\"].zl-attribution > * {\n grid-column: 2;\n justify-self: center;\n}\n\nzl-page-shell:has(.zl-split--right) [slot=\"footer\"].zl-attribution > * {\n grid-column: 1;\n}\n\nzl-page-shell:has(.zl-split) [slot=\"footer\"].zl-attribution ::slotted(*) {\n grid-column: 2;\n justify-self: center;\n}\n\nzl-page-shell:has(.zl-split--right) [slot=\"footer\"].zl-attribution ::slotted(*) {\n grid-column: 1;\n}\n\n@container (width <= 48rem) {\n .zl-split {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .zl-split__brand {\n display: var(--zl-split-brand-mobile, none);\n }\n\n .zl-split__compact {\n display: block;\n }\n\n zl-page-shell:has(.zl-split) [slot=\"footer\"].zl-attribution {\n grid-template-columns: minmax(0, 1fr);\n }\n\n zl-page-shell:has(.zl-split) .zl-attribution > *, zl-page-shell:has(.zl-split--right) [slot=\"footer\"].zl-attribution > * {\n grid-column: 1;\n }\n}\n\n.zl-hero {\n text-align: left;\n width: 100%;\n max-width: 34rem;\n color: var(--zl-foreground);\n font-family: var(--zl-font-family-sans);\n flex-direction: column;\n display: flex;\n}\n\n.zl-hero__nav {\n margin-bottom: var(--zl-spacing-8);\n justify-content: space-between;\n align-items: center;\n display: flex;\n}\n\n.zl-hero__brand {\n align-items: center;\n gap: var(--zl-spacing-2);\n letter-spacing: -.01em;\n font-size: 1.125rem;\n font-weight: 700;\n display: inline-flex;\n}\n\n.zl-hero__brand-logo {\n max-height: calc(1.75rem * var(--zl-logo-scale, 1));\n}\n\n.zl-hero__brand-mark {\n border-radius: var(--zl-radius-md);\n background: linear-gradient(135deg,\n var(--zl-gradient-lavender-start),\n var(--zl-gradient-rose-start));\n width: 1.75rem;\n height: 1.75rem;\n display: inline-flex;\n}\n\n.zl-hero__compact-brand {\n overflow-wrap: anywhere;\n letter-spacing: -.01em;\n max-width: 100%;\n color: var(--zl-foreground);\n margin: 0;\n font-size: 1.125rem;\n font-weight: 700;\n}\n\n.zl-hero__nav-links {\n gap: var(--zl-spacing-6);\n color: var(--zl-muted-foreground);\n font-size: .9375rem;\n display: flex;\n}\n\n.zl-hero__nav-links a {\n color: inherit;\n text-decoration: none;\n}\n\n.zl-hero__nav-links a:hover {\n text-decoration: underline;\n}\n\n.zl-hero__eyebrow {\n margin: 0 0 var(--zl-spacing-4);\n letter-spacing: .08em;\n text-transform: uppercase;\n color: var(--zl-muted-foreground);\n font-size: .8125rem;\n font-weight: 600;\n}\n\n.zl-hero__headline {\n margin: 0 0 var(--zl-spacing-4);\n font-family: var(--zl-font-family-heading);\n letter-spacing: -.02em;\n font-size: 2.75rem;\n font-weight: 700;\n line-height: 1.1;\n}\n\n.zl-hero__sub {\n margin: 0 0 var(--zl-spacing-8);\n max-width: 30rem;\n color: var(--zl-muted-foreground);\n font-size: 1.0625rem;\n line-height: 1.6;\n}\n\n.zl-hero__bullets {\n gap: var(--zl-spacing-2);\n margin: 0 0 var(--zl-spacing-8);\n flex-direction: column;\n padding: 0;\n list-style: none;\n display: flex;\n}\n\n.zl-hero__bullets li {\n align-items: center;\n gap: var(--zl-spacing-2);\n font-size: 1rem;\n display: flex;\n}\n\n.zl-hero__bullets li:before {\n content: \"✓\";\n color: var(--zl-success);\n font-weight: 700;\n}\n\n.zl-hero__footnote {\n padding-top: var(--zl-spacing-6);\n border-top: 1px solid var(--zl-border);\n color: var(--zl-muted-foreground);\n margin: 0;\n font-size: .8125rem;\n}\n\n.zl-hero__footnote strong {\n color: var(--zl-muted-foreground);\n font-weight: 600;\n}\n\n.zl-minimal {\n gap: var(--zl-spacing-6);\n flex-direction: column;\n width: min(24rem, 100%);\n margin-inline: auto;\n display: flex;\n}\n\n:host([variant=\"page\"]) .zl-minimal {\n padding: 52px 16px;\n}\n";
|
|
13888
14403
|
//#endregion
|
|
13889
14404
|
//#region src/orchestrator/zitadel-login.ts
|
|
13890
14405
|
/** Narrow a rendered named element to the `formValue` field-atom contract. */
|
|
@@ -13993,6 +14508,13 @@ let ZitadelLogin = class ZitadelLogin extends ZitadelSurface {
|
|
|
13993
14508
|
set loading(value) {
|
|
13994
14509
|
this.#_loading_accessor_storage = value;
|
|
13995
14510
|
}
|
|
14511
|
+
#_completing_accessor_storage = false;
|
|
14512
|
+
get completing() {
|
|
14513
|
+
return this.#_completing_accessor_storage;
|
|
14514
|
+
}
|
|
14515
|
+
set completing(value) {
|
|
14516
|
+
this.#_completing_accessor_storage = value;
|
|
14517
|
+
}
|
|
13996
14518
|
#_startupError_accessor_storage = null;
|
|
13997
14519
|
get startupError() {
|
|
13998
14520
|
return this.#_startupError_accessor_storage;
|
|
@@ -14008,6 +14530,13 @@ let ZitadelLogin = class ZitadelLogin extends ZitadelSurface {
|
|
|
14008
14530
|
this.#_formValues_accessor_storage = value;
|
|
14009
14531
|
}
|
|
14010
14532
|
engine = null;
|
|
14533
|
+
/**
|
|
14534
|
+
* The theme the last commit rendered with. The template output carries the
|
|
14535
|
+
* resolved side's mark, so a theme change rewrites the string and
|
|
14536
|
+
* `unsafeHTML` rebuilds the form — which drops what the visitor had typed
|
|
14537
|
+
* unless it is put back.
|
|
14538
|
+
*/
|
|
14539
|
+
lastRenderedTheme = null;
|
|
14011
14540
|
sanitise = createSanitiser();
|
|
14012
14541
|
/**
|
|
14013
14542
|
* Cached compiled tenant template, keyed by source string. Re-rendering on
|
|
@@ -14106,9 +14635,14 @@ let ZitadelLogin = class ZitadelLogin extends ZitadelSurface {
|
|
|
14106
14635
|
}
|
|
14107
14636
|
for (const card of this.shadowRoot.querySelectorAll("zl-card")) card.toggleAttribute("data-suppress-header", this.suppressHeader);
|
|
14108
14637
|
}
|
|
14638
|
+
const previousTheme = this.lastRenderedTheme;
|
|
14639
|
+
this.lastRenderedTheme = this.themeController.theme;
|
|
14109
14640
|
const props = changed;
|
|
14110
|
-
if (
|
|
14111
|
-
|
|
14641
|
+
if (props.has("response")) {
|
|
14642
|
+
this.hydrateStepAfterRender(props.get("response") == null);
|
|
14643
|
+
return;
|
|
14644
|
+
}
|
|
14645
|
+
if (previousTheme !== null && previousTheme !== this.lastRenderedTheme) this.restoreValuesAfterRender();
|
|
14112
14646
|
}
|
|
14113
14647
|
/**
|
|
14114
14648
|
* Apply captured values and move focus once the new step has fully
|
|
@@ -14123,11 +14657,19 @@ let ZitadelLogin = class ZitadelLogin extends ZitadelSurface {
|
|
|
14123
14657
|
* swaps are user-initiated, so focus moves in both modes.
|
|
14124
14658
|
*/
|
|
14125
14659
|
async hydrateStepAfterRender(initial = false) {
|
|
14660
|
+
await this.restoreValuesAfterRender();
|
|
14661
|
+
if (!initial || this.variant === "page") this.moveFocusToFirstField(initial && this.variant === "page");
|
|
14662
|
+
}
|
|
14663
|
+
/**
|
|
14664
|
+
* Put captured values back once the rebuilt subtree has rendered. Awaits the
|
|
14665
|
+
* child atoms' own first render before touching them, rather than guessing a
|
|
14666
|
+
* frame with `requestAnimationFrame`.
|
|
14667
|
+
*/
|
|
14668
|
+
async restoreValuesAfterRender() {
|
|
14126
14669
|
await this.updateComplete;
|
|
14127
14670
|
const atoms = this.shadowRoot?.querySelectorAll("zl-field, zl-select, zl-checkbox, zl-button");
|
|
14128
14671
|
if (atoms) await Promise.all(Array.from(atoms).map((atom) => atom.updateComplete));
|
|
14129
14672
|
this.applyValuesToFields();
|
|
14130
|
-
if (!initial || this.variant === "page") this.moveFocusToFirstField(initial && this.variant === "page");
|
|
14131
14673
|
}
|
|
14132
14674
|
render() {
|
|
14133
14675
|
if (this.startupError) return b`<form class="zl-mount" novalidate>
|
|
@@ -14137,7 +14679,7 @@ let ZitadelLogin = class ZitadelLogin extends ZitadelSurface {
|
|
|
14137
14679
|
</zl-card>
|
|
14138
14680
|
</zl-page-shell>
|
|
14139
14681
|
</form>`;
|
|
14140
|
-
if (!this.response || !this.engine) return b`<slot name="loader"></slot>`;
|
|
14682
|
+
if (!this.response || !this.engine || this.completing) return b`<slot name="loader"></slot>`;
|
|
14141
14683
|
const rendered = this.injectAttribution(this.renderStep(this.response.step, this.engine));
|
|
14142
14684
|
return b`<form
|
|
14143
14685
|
class="zl-mount"
|
|
@@ -14169,6 +14711,20 @@ let ZitadelLogin = class ZitadelLogin extends ZitadelSurface {
|
|
|
14169
14711
|
return rendered + html;
|
|
14170
14712
|
}
|
|
14171
14713
|
/**
|
|
14714
|
+
* The branding a template renders against, with `logo_url` already resolved
|
|
14715
|
+
* to the mark for the active side. Templates read one logo field and get the
|
|
14716
|
+
* right file per surface; the per-side URLs stay on `theme` for a template
|
|
14717
|
+
* that wants to reach them itself.
|
|
14718
|
+
*/
|
|
14719
|
+
brandingForTemplate() {
|
|
14720
|
+
if (!this.branding) return {};
|
|
14721
|
+
const logoUrl = resolveLogoUrl(this.branding, this.themeController.theme);
|
|
14722
|
+
return {
|
|
14723
|
+
...this.branding,
|
|
14724
|
+
logo_url: logoUrl
|
|
14725
|
+
};
|
|
14726
|
+
}
|
|
14727
|
+
/**
|
|
14172
14728
|
* "Secured with Zitadel" attribution chrome injected into every
|
|
14173
14729
|
* template's page-shell footer slot. Controlled by
|
|
14174
14730
|
* `branding.attribution.show_zitadel` — defaults to `true` for
|
|
@@ -14181,7 +14737,7 @@ let ZitadelLogin = class ZitadelLogin extends ZitadelSurface {
|
|
|
14181
14737
|
const custom = attribution?.custom_link;
|
|
14182
14738
|
if (!show && !custom) return "";
|
|
14183
14739
|
const mark = custom ? `<a class="zl-trustmark__mark" part="attribution-mark" href="${escapeHtml(String(custom.href))}">${escapeHtml(String(custom.label))}</a>` : `<a class="zl-trustmark__mark" part="attribution-mark" href="https://zitadel.com" aria-label="Secured with Zitadel">${zitadelTrustmarkInnerHtml()}</a>`;
|
|
14184
|
-
return `<div${placement === "footer" ? ` slot="footer"` : ""} part="attribution" class="zl-attribution zl-trustmark">${mark}
|
|
14740
|
+
return `<div${placement === "footer" ? ` slot="footer"` : ""} part="attribution" class="zl-attribution zl-trustmark">${mark}<slot name="attribution-trailing"></slot></div>`;
|
|
14185
14741
|
}
|
|
14186
14742
|
/** Declarative config read from this element's attributes. */
|
|
14187
14743
|
get projectAttrs() {
|
|
@@ -14229,6 +14785,7 @@ let ZitadelLogin = class ZitadelLogin extends ZitadelSurface {
|
|
|
14229
14785
|
}
|
|
14230
14786
|
applyResponse(wire) {
|
|
14231
14787
|
this.stepErrorDismissed = false;
|
|
14788
|
+
this.completing = navigatesOnComplete(wire, this.postSignInUrl);
|
|
14232
14789
|
this.response = wire;
|
|
14233
14790
|
const { branding, issues } = validateBranding(wire.branding, { renderingOrigin: this.ownerDocument.location.origin });
|
|
14234
14791
|
this.branding = branding;
|
|
@@ -14248,7 +14805,11 @@ let ZitadelLogin = class ZitadelLogin extends ZitadelSurface {
|
|
|
14248
14805
|
this.armed = true;
|
|
14249
14806
|
} else if (!hasBack && this.armed) {
|
|
14250
14807
|
this.armed = false;
|
|
14251
|
-
if (history.state?.zl === true) {
|
|
14808
|
+
if (history.state?.zl === true) if (this.completing) history.replaceState({
|
|
14809
|
+
...history.state,
|
|
14810
|
+
zl: false
|
|
14811
|
+
}, "");
|
|
14812
|
+
else {
|
|
14252
14813
|
this.ignoreNextPop = true;
|
|
14253
14814
|
history.back();
|
|
14254
14815
|
}
|
|
@@ -14320,7 +14881,7 @@ let ZitadelLogin = class ZitadelLogin extends ZitadelSurface {
|
|
|
14320
14881
|
messages: [],
|
|
14321
14882
|
identity: this.deriveIdentity(),
|
|
14322
14883
|
errors,
|
|
14323
|
-
branding: this.
|
|
14884
|
+
branding: this.brandingForTemplate(),
|
|
14324
14885
|
loading: this.loading
|
|
14325
14886
|
};
|
|
14326
14887
|
let raw;
|
|
@@ -14700,6 +15261,7 @@ __decorate([n$1({ attribute: false })], ZitadelLogin.prototype, "locales", null)
|
|
|
14700
15261
|
__decorate([r$1()], ZitadelLogin.prototype, "response", null);
|
|
14701
15262
|
__decorate([r$1()], ZitadelLogin.prototype, "branding", null);
|
|
14702
15263
|
__decorate([r$1()], ZitadelLogin.prototype, "loading", null);
|
|
15264
|
+
__decorate([r$1()], ZitadelLogin.prototype, "completing", null);
|
|
14703
15265
|
__decorate([r$1()], ZitadelLogin.prototype, "startupError", null);
|
|
14704
15266
|
__decorate([r$1()], ZitadelLogin.prototype, "formValues", null);
|
|
14705
15267
|
ZitadelLogin = __decorate([t$4("zitadel-login")], ZitadelLogin);
|
|
@@ -14713,6 +15275,19 @@ ZitadelLogin = __decorate([t$4("zitadel-login")], ZitadelLogin);
|
|
|
14713
15275
|
function isAllowedSelectValue(field, value) {
|
|
14714
15276
|
return field.validation?.enum?.includes(value) ?? false;
|
|
14715
15277
|
}
|
|
15278
|
+
/**
|
|
15279
|
+
* Whether a terminal step ends in a navigation rather than a screen: a
|
|
15280
|
+
* `redirect` with a URI, or a `show` whose handoff the widget exchanges before
|
|
15281
|
+
* sending the browser to `post-sign-in-url`. A `show` without a
|
|
15282
|
+
* `post-sign-in-url` is the host handling the handoff itself, and that screen
|
|
15283
|
+
* is the flow's own last word — it still renders.
|
|
15284
|
+
*/
|
|
15285
|
+
function navigatesOnComplete(wire, postSignInUrl) {
|
|
15286
|
+
const behavior = wire.step.complete;
|
|
15287
|
+
if (behavior === "redirect") return Boolean(wire.redirect_uri);
|
|
15288
|
+
if (behavior === "show") return Boolean(wire.handoff_token && postSignInUrl);
|
|
15289
|
+
return false;
|
|
15290
|
+
}
|
|
14716
15291
|
function collectInitialValues(step) {
|
|
14717
15292
|
const values = {};
|
|
14718
15293
|
if (!step.fields) return values;
|
|
@@ -14970,7 +15545,7 @@ let ZitadelLogout = class ZitadelLogout extends i$2 {
|
|
|
14970
15545
|
const root = this.shadowRoot;
|
|
14971
15546
|
if (root && !this.templateMode) {
|
|
14972
15547
|
applyBaseTokens(root);
|
|
14973
|
-
applyBrandingTokens(root, void 0
|
|
15548
|
+
applyBrandingTokens(root, void 0);
|
|
14974
15549
|
}
|
|
14975
15550
|
this.dataset.theme = this.themeController.theme;
|
|
14976
15551
|
this.toggleAttribute("data-theme-dark", this.themeController.theme === "dark");
|
|
@@ -15454,4 +16029,4 @@ __decorate([r$1()], ZitadelSession.prototype, "loading", null);
|
|
|
15454
16029
|
__decorate([r$1()], ZitadelSession.prototype, "errorMessage", null);
|
|
15455
16030
|
ZitadelSession = __decorate([t$4("zitadel-session")], ZitadelSession);
|
|
15456
16031
|
//#endregion
|
|
15457
|
-
export { TEMPLATE_NAMES, ThemeController, ZITADEL_ATTRIBUTION_LOGOTYPE_SVG, ZitadelLogin, ZitadelLogout, ZitadelSession, ZlAlert, ZlButton, ZlCard, ZlCheckbox, ZlField, ZlIcon, ZlPageShell, ZlPill, ZlSelect, applyBrandingTokens, applyFontUrl, baseHostStyles, buildBrandingStylesheet, builtinLocales, businessLocales, createSanitiser, cssVars, de, default_default as defaultTemplate, en, findManifest, focusVisibleStyles, getCurrentStep, it, layout_chrome_default as layoutChromeCss, listKnownTags, manifestRegistry, patchMandatoryGates, resolveTheme, startFlow, submitStep, t, tokens, validateBranding, zitadelTrustmarkInnerHtml, zlAlertManifest, zlButtonManifest, zlCardManifest, zlCheckboxManifest, zlFieldManifest, zlIconManifest, zlPageShellManifest, zlPillManifest, zlSelectManifest };
|
|
16032
|
+
export { TEMPLATE_NAMES, ThemeController, ZITADEL_ATTRIBUTION_LOGOTYPE_SVG, ZitadelLogin, ZitadelLogout, ZitadelSession, ZlAlert, ZlButton, ZlCard, ZlCheckbox, ZlField, ZlIcon, ZlPageShell, ZlPill, ZlSelect, applyBrandingTokens, applyFontUrl, baseHostStyles, buildBrandingStylesheet, builtinLocales, businessLocales, createSanitiser, cssVars, de, default_default as defaultTemplate, en, findManifest, focusVisibleStyles, getCurrentStep, it, layout_chrome_default as layoutChromeCss, listKnownTags, manifestRegistry, patchMandatoryGates, publishedSides, resolveLogoUrl, resolveTheme, startFlow, submitStep, t, tokens, validateBranding, zitadelTrustmarkInnerHtml, zlAlertManifest, zlButtonManifest, zlCardManifest, zlCheckboxManifest, zlFieldManifest, zlIconManifest, zlPageShellManifest, zlPillManifest, zlSelectManifest };
|