@kya-os/consent 0.1.13 → 0.1.14
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/bundle/inline.d.ts.map +1 -1
- package/dist/bundle/inline.js +2 -2
- package/dist/bundle/inline.js.map +1 -1
- package/dist/bundle/shell.d.ts +5 -0
- package/dist/bundle/shell.d.ts.map +1 -1
- package/dist/bundle/shell.js +3 -1
- package/dist/bundle/shell.js.map +1 -1
- package/dist/cjs/bundle/index.js +57 -0
- package/dist/cjs/bundle/index.js.map +1 -0
- package/dist/cjs/bundle/inline.js +22 -0
- package/dist/cjs/bundle/inline.js.map +1 -0
- package/dist/cjs/bundle/shell.js +291 -0
- package/dist/cjs/bundle/shell.js.map +1 -0
- package/dist/cjs/components/consent-button.js +180 -0
- package/dist/cjs/components/consent-button.js.map +1 -0
- package/dist/cjs/components/consent-checkbox.js +223 -0
- package/dist/cjs/components/consent-checkbox.js.map +1 -0
- package/dist/cjs/components/consent-input.js +335 -0
- package/dist/cjs/components/consent-input.js.map +1 -0
- package/dist/cjs/components/consent-oauth-button.js +392 -0
- package/dist/cjs/components/consent-oauth-button.js.map +1 -0
- package/dist/cjs/components/consent-otp-input.js +388 -0
- package/dist/cjs/components/consent-otp-input.js.map +1 -0
- package/dist/cjs/components/consent-permissions.js +433 -0
- package/dist/cjs/components/consent-permissions.js.map +1 -0
- package/dist/cjs/components/consent-shell.js +234 -0
- package/dist/cjs/components/consent-shell.js.map +1 -0
- package/dist/cjs/components/consent-terms.js +287 -0
- package/dist/cjs/components/consent-terms.js.map +1 -0
- package/dist/cjs/components/index.js +37 -0
- package/dist/cjs/components/index.js.map +1 -0
- package/dist/cjs/components/mcp-consent.js +1034 -0
- package/dist/cjs/components/mcp-consent.js.map +1 -0
- package/dist/cjs/constants/auth-modes.js +128 -0
- package/dist/cjs/constants/auth-modes.js.map +1 -0
- package/dist/cjs/constants/colors.js +40 -0
- package/dist/cjs/constants/colors.js.map +1 -0
- package/dist/cjs/constants/defaults.js +146 -0
- package/dist/cjs/constants/defaults.js.map +1 -0
- package/dist/cjs/constants/index.js +40 -0
- package/dist/cjs/constants/index.js.map +1 -0
- package/dist/cjs/index.js +49 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/react/index.js +190 -0
- package/dist/cjs/react/index.js.map +1 -0
- package/dist/cjs/resolution/index.js +28 -0
- package/dist/cjs/resolution/index.js.map +1 -0
- package/dist/cjs/resolution/resolve-branding.js +159 -0
- package/dist/cjs/resolution/resolve-branding.js.map +1 -0
- package/dist/cjs/resolution/resolve-config.js +270 -0
- package/dist/cjs/resolution/resolve-config.js.map +1 -0
- package/dist/cjs/resolution/resolve-copy.js +136 -0
- package/dist/cjs/resolution/resolve-copy.js.map +1 -0
- package/dist/cjs/schemas/api.schemas.js +156 -0
- package/dist/cjs/schemas/api.schemas.js.map +1 -0
- package/dist/cjs/schemas/branding.schemas.js +57 -0
- package/dist/cjs/schemas/branding.schemas.js.map +1 -0
- package/dist/cjs/schemas/config.schemas.js +147 -0
- package/dist/cjs/schemas/config.schemas.js.map +1 -0
- package/dist/cjs/schemas/index.js +29 -0
- package/dist/cjs/schemas/index.js.map +1 -0
- package/dist/cjs/schemas/modes.schemas.js +107 -0
- package/dist/cjs/schemas/modes.schemas.js.map +1 -0
- package/dist/cjs/security/escape.js +206 -0
- package/dist/cjs/security/escape.js.map +1 -0
- package/dist/cjs/security/index.js +26 -0
- package/dist/cjs/security/index.js.map +1 -0
- package/dist/cjs/security/validators.js +210 -0
- package/dist/cjs/security/validators.js.map +1 -0
- package/dist/cjs/styles/css-variables.js +129 -0
- package/dist/cjs/styles/css-variables.js.map +1 -0
- package/dist/cjs/styles/index.js +28 -0
- package/dist/cjs/styles/index.js.map +1 -0
- package/dist/cjs/styles/stylesheet.js +204 -0
- package/dist/cjs/styles/stylesheet.js.map +1 -0
- package/dist/cjs/styles/tokens.js +183 -0
- package/dist/cjs/styles/tokens.js.map +1 -0
- package/dist/cjs/templates/base/base-template.js +282 -0
- package/dist/cjs/templates/base/base-template.js.map +1 -0
- package/dist/cjs/templates/base/components.js +295 -0
- package/dist/cjs/templates/base/components.js.map +1 -0
- package/dist/cjs/templates/base/index.js +26 -0
- package/dist/cjs/templates/base/index.js.map +1 -0
- package/dist/cjs/templates/index.js +34 -0
- package/dist/cjs/templates/index.js.map +1 -0
- package/dist/cjs/templates/modes/consent-only.template.js +74 -0
- package/dist/cjs/templates/modes/consent-only.template.js.map +1 -0
- package/dist/cjs/templates/modes/credentials.template.js +414 -0
- package/dist/cjs/templates/modes/credentials.template.js.map +1 -0
- package/dist/cjs/templates/modes/index.js +24 -0
- package/dist/cjs/templates/modes/index.js.map +1 -0
- package/dist/cjs/templates/modes/magic-link.template.js +196 -0
- package/dist/cjs/templates/modes/magic-link.template.js.map +1 -0
- package/dist/cjs/templates/modes/oauth.template.js +153 -0
- package/dist/cjs/templates/modes/oauth.template.js.map +1 -0
- package/dist/cjs/templates/modes/otp.template.js +316 -0
- package/dist/cjs/templates/modes/otp.template.js.map +1 -0
- package/dist/cjs/templates/modes/success.template.js +140 -0
- package/dist/cjs/templates/modes/success.template.js.map +1 -0
- package/dist/cjs/templates/registry.js +133 -0
- package/dist/cjs/templates/registry.js.map +1 -0
- package/dist/cjs/types/api.types.js +10 -0
- package/dist/cjs/types/api.types.js.map +1 -0
- package/dist/cjs/types/branding.types.js +10 -0
- package/dist/cjs/types/branding.types.js.map +1 -0
- package/dist/cjs/types/config.types.js +10 -0
- package/dist/cjs/types/config.types.js.map +1 -0
- package/dist/cjs/types/copy.types.js +10 -0
- package/dist/cjs/types/copy.types.js.map +1 -0
- package/dist/cjs/types/index.js +31 -0
- package/dist/cjs/types/index.js.map +1 -0
- package/dist/cjs/types/modes.types.js +140 -0
- package/dist/cjs/types/modes.types.js.map +1 -0
- package/dist/cjs/types/page.types.js +10 -0
- package/dist/cjs/types/page.types.js.map +1 -0
- package/dist/components/mcp-consent.d.ts +6 -0
- package/dist/components/mcp-consent.d.ts.map +1 -1
- package/dist/components/mcp-consent.js +14 -0
- package/dist/components/mcp-consent.js.map +1 -1
- package/dist/consent.js +7 -0
- package/dist/consent.min.js +2 -2
- package/dist/schemas/api.schemas.d.ts +116 -116
- package/dist/schemas/config.schemas.d.ts +116 -116
- package/dist/schemas/modes.schemas.d.ts +28 -28
- package/package.json +29 -15
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OAuth Template
|
|
4
|
+
*
|
|
5
|
+
* OAuth redirect flow with provider branding.
|
|
6
|
+
*
|
|
7
|
+
* @module @kya-os/consent/templates/modes/oauth
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.OAuthTemplate = void 0;
|
|
11
|
+
const base_template_js_1 = require("../base/base-template.js");
|
|
12
|
+
const components_js_1 = require("../base/components.js");
|
|
13
|
+
const tokens_js_1 = require("../../styles/tokens.js");
|
|
14
|
+
const escape_js_1 = require("../../security/escape.js");
|
|
15
|
+
const modes_types_js_1 = require("../../types/modes.types.js");
|
|
16
|
+
/**
|
|
17
|
+
* OAuth provider branding information.
|
|
18
|
+
*/
|
|
19
|
+
const PROVIDER_BRANDING = {
|
|
20
|
+
github: {
|
|
21
|
+
color: "#24292e",
|
|
22
|
+
name: "GitHub",
|
|
23
|
+
icon: `<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>`,
|
|
24
|
+
},
|
|
25
|
+
google: {
|
|
26
|
+
color: "#4285f4",
|
|
27
|
+
name: "Google",
|
|
28
|
+
icon: `<svg class="w-5 h-5" viewBox="0 0 24 24"><path fill="currentColor" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/><path fill="currentColor" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/><path fill="currentColor" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/><path fill="currentColor" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/></svg>`,
|
|
29
|
+
},
|
|
30
|
+
microsoft: {
|
|
31
|
+
color: "#0078d4",
|
|
32
|
+
name: "Microsoft",
|
|
33
|
+
icon: `<svg class="w-5 h-5" viewBox="0 0 24 24"><path fill="#f35325" d="M1 1h10v10H1z"/><path fill="#81bc06" d="M13 1h10v10H13z"/><path fill="#05a6f0" d="M1 13h10v10H1z"/><path fill="#ffba08" d="M13 13h10v10H13z"/></svg>`,
|
|
34
|
+
},
|
|
35
|
+
slack: {
|
|
36
|
+
color: "#4a154b",
|
|
37
|
+
name: "Slack",
|
|
38
|
+
icon: `<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"><path d="M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52zM6.313 15.165a2.527 2.527 0 0 1 2.521-2.52 2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522v-6.313zM8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52H8.834zM8.834 6.313a2.528 2.528 0 0 1 2.521 2.521 2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521h6.312zM18.956 8.834a2.528 2.528 0 0 1 2.522-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.522 2.521h-2.522V8.834zM17.688 8.834a2.528 2.528 0 0 1-2.523 2.521 2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.165 0a2.528 2.528 0 0 1 2.523 2.522v6.312zM15.165 18.956a2.528 2.528 0 0 1 2.523 2.522A2.528 2.528 0 0 1 15.165 24a2.527 2.527 0 0 1-2.52-2.522v-2.522h2.52zM15.165 17.688a2.527 2.527 0 0 1-2.52-2.523 2.526 2.526 0 0 1 2.52-2.52h6.313A2.527 2.527 0 0 1 24 15.165a2.528 2.528 0 0 1-2.522 2.523h-6.313z"/></svg>`,
|
|
39
|
+
},
|
|
40
|
+
auth0: {
|
|
41
|
+
color: "#eb5424",
|
|
42
|
+
name: "Auth0",
|
|
43
|
+
icon: `<svg class="w-5 h-5" viewBox="0 0 24 24" fill="currentColor"><path d="M21.98 7.448L19.62 0H4.347L2.02 7.448c-1.352 4.312.03 9.206 3.815 12.015L12.007 24l6.157-4.552c3.755-2.81 5.182-7.688 3.815-12.015l-6.16 4.58 2.343 7.45-6.157-4.597-6.158 4.58 2.358-7.433-6.188-4.55 7.63-.045L12.008 0l2.356 7.404 7.615.044z"/></svg>`,
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* OAuth Template
|
|
48
|
+
*
|
|
49
|
+
* Renders an OAuth consent page with:
|
|
50
|
+
* - Permission list
|
|
51
|
+
* - Expiration notice
|
|
52
|
+
* - Provider-branded continue button
|
|
53
|
+
*/
|
|
54
|
+
class OAuthTemplate extends base_template_js_1.BaseConsentTemplate {
|
|
55
|
+
get authMode() {
|
|
56
|
+
return modes_types_js_1.AUTH_MODES.OAUTH;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Set the OAuth authorization URL.
|
|
60
|
+
*/
|
|
61
|
+
setOAuthUrl(url) {
|
|
62
|
+
this.oauthUrl = url;
|
|
63
|
+
}
|
|
64
|
+
get oauthConfig() {
|
|
65
|
+
return this.config.modeConfig?.oauth;
|
|
66
|
+
}
|
|
67
|
+
renderAuthContent() {
|
|
68
|
+
const config = this.oauthConfig;
|
|
69
|
+
const providerId = config?.providerId || this.config.provider || "oauth";
|
|
70
|
+
const branding = PROVIDER_BRANDING[providerId.toLowerCase()];
|
|
71
|
+
return `
|
|
72
|
+
<div class="space-y-4">
|
|
73
|
+
${this.renderPermissionsList()}
|
|
74
|
+
<div class="pt-2">
|
|
75
|
+
<p class="text-sm text-gray-600">
|
|
76
|
+
You will be redirected to ${(0, escape_js_1.escapeHtml)(branding?.name || config?.providerName || "the identity provider")} to authenticate.
|
|
77
|
+
</p>
|
|
78
|
+
</div>
|
|
79
|
+
${this.renderExpirationNotice()}
|
|
80
|
+
</div>
|
|
81
|
+
`;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Render permissions as a simple list.
|
|
85
|
+
*/
|
|
86
|
+
renderPermissionsList() {
|
|
87
|
+
const { scopes } = this.config;
|
|
88
|
+
if (scopes.length === 0)
|
|
89
|
+
return "";
|
|
90
|
+
const items = scopes.map((s) => `<li>${(0, escape_js_1.escapeHtml)(s)}</li>`).join("");
|
|
91
|
+
return `
|
|
92
|
+
<div class="space-y-2">
|
|
93
|
+
<p class="text-sm font-medium text-gray-700">Requested permissions:</p>
|
|
94
|
+
<ul class="list-disc list-inside text-sm text-gray-600 space-y-1">
|
|
95
|
+
${items}
|
|
96
|
+
</ul>
|
|
97
|
+
</div>
|
|
98
|
+
`;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Render expiration notice.
|
|
102
|
+
*/
|
|
103
|
+
renderExpirationNotice() {
|
|
104
|
+
const { copy } = this.resolved;
|
|
105
|
+
const expirationDays = this.resolved.expirationDays || 30;
|
|
106
|
+
return (0, components_js_1.renderExpirationNotice)(copy.expirationText, expirationDays);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Override action buttons to show OAuth provider button.
|
|
110
|
+
*/
|
|
111
|
+
renderActionButtons() {
|
|
112
|
+
const config = this.oauthConfig;
|
|
113
|
+
const providerId = config?.providerId || this.config.provider || "oauth";
|
|
114
|
+
const branding = PROVIDER_BRANDING[providerId.toLowerCase()];
|
|
115
|
+
const buttonText = config?.buttonText ||
|
|
116
|
+
`Continue with ${branding?.name || config?.providerName || "Provider"}`;
|
|
117
|
+
const { copy } = this.resolved;
|
|
118
|
+
// If OAuth URL is set, use a direct link
|
|
119
|
+
const oauthUrl = this.oauthUrl || this.config.oauthUrl;
|
|
120
|
+
if (oauthUrl) {
|
|
121
|
+
const buttonStyle = branding
|
|
122
|
+
? `style="background-color: ${branding.color}"`
|
|
123
|
+
: "";
|
|
124
|
+
return `
|
|
125
|
+
<div class="${tokens_js_1.CONSENT_CLASSES.buttonGroup}">
|
|
126
|
+
<button type="button" onclick="window.close()" class="${tokens_js_1.CONSENT_CLASSES.buttonSecondary}">
|
|
127
|
+
${(0, escape_js_1.escapeHtml)(copy.cancelButtonText)}
|
|
128
|
+
</button>
|
|
129
|
+
<a href="${(0, escape_js_1.escapeAttr)(oauthUrl)}"
|
|
130
|
+
class="${tokens_js_1.CONSENT_CLASSES.buttonPrimary} flex items-center justify-center gap-2"
|
|
131
|
+
${buttonStyle}>
|
|
132
|
+
${branding?.icon || ""}
|
|
133
|
+
${(0, escape_js_1.escapeHtml)(buttonText)}
|
|
134
|
+
</a>
|
|
135
|
+
</div>
|
|
136
|
+
`;
|
|
137
|
+
}
|
|
138
|
+
// Fallback to standard buttons
|
|
139
|
+
return `
|
|
140
|
+
<div class="${tokens_js_1.CONSENT_CLASSES.buttonGroup}">
|
|
141
|
+
<button type="button" onclick="window.close()" class="${tokens_js_1.CONSENT_CLASSES.buttonSecondary}">
|
|
142
|
+
${(0, escape_js_1.escapeHtml)(copy.cancelButtonText)}
|
|
143
|
+
</button>
|
|
144
|
+
<button type="submit" class="${tokens_js_1.CONSENT_CLASSES.buttonPrimary} btn-primary flex items-center justify-center gap-2">
|
|
145
|
+
${branding?.icon || ""}
|
|
146
|
+
${(0, escape_js_1.escapeHtml)(buttonText)}
|
|
147
|
+
</button>
|
|
148
|
+
</div>
|
|
149
|
+
`;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
exports.OAuthTemplate = OAuthTemplate;
|
|
153
|
+
//# sourceMappingURL=oauth.template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.template.js","sourceRoot":"","sources":["../../../../src/templates/modes/oauth.template.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OTP Template
|
|
4
|
+
*
|
|
5
|
+
* One-Time Password authentication via SMS/email.
|
|
6
|
+
*
|
|
7
|
+
* @module @kya-os/consent/templates/modes/otp
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.OTPTemplate = void 0;
|
|
11
|
+
const base_template_js_1 = require("../base/base-template.js");
|
|
12
|
+
const components_js_1 = require("../base/components.js");
|
|
13
|
+
const escape_js_1 = require("../../security/escape.js");
|
|
14
|
+
const modes_types_js_1 = require("../../types/modes.types.js");
|
|
15
|
+
/**
|
|
16
|
+
* OTP Template
|
|
17
|
+
*
|
|
18
|
+
* Renders a two-step OTP flow:
|
|
19
|
+
* 1. Phone/email input to request code
|
|
20
|
+
* 2. Code input to verify
|
|
21
|
+
*/
|
|
22
|
+
class OTPTemplate extends base_template_js_1.BaseConsentTemplate {
|
|
23
|
+
get authMode() {
|
|
24
|
+
return modes_types_js_1.AUTH_MODES.OTP;
|
|
25
|
+
}
|
|
26
|
+
get otpConfig() {
|
|
27
|
+
return this.config.modeConfig?.otp;
|
|
28
|
+
}
|
|
29
|
+
renderAuthContent() {
|
|
30
|
+
const config = this.otpConfig;
|
|
31
|
+
const digits = config?.digits || 6;
|
|
32
|
+
return `
|
|
33
|
+
<div id="otp-request-container">
|
|
34
|
+
<form id="otp-request-form" class="space-y-4">
|
|
35
|
+
${this.renderPhoneField(config)}
|
|
36
|
+
${(0, components_js_1.renderErrorContainer)("otp-request-error")}
|
|
37
|
+
${(0, components_js_1.renderFullWidthButton)("Send verification code", "submit")}
|
|
38
|
+
</form>
|
|
39
|
+
</div>
|
|
40
|
+
<div id="otp-verify-container" class="hidden">
|
|
41
|
+
<form id="otp-verify-form" class="space-y-4">
|
|
42
|
+
<div class="text-center mb-4">
|
|
43
|
+
<p class="text-sm text-gray-600">
|
|
44
|
+
${(0, escape_js_1.escapeHtml)(config?.instructions || `Enter the ${digits}-digit code sent to your phone`)}
|
|
45
|
+
</p>
|
|
46
|
+
</div>
|
|
47
|
+
<div class="flex justify-center gap-2" id="otp-inputs">
|
|
48
|
+
${this.renderOTPInputs(digits)}
|
|
49
|
+
</div>
|
|
50
|
+
${(0, components_js_1.renderErrorContainer)("otp-verify-error")}
|
|
51
|
+
${(0, components_js_1.renderFullWidthButton)("Verify", "submit")}
|
|
52
|
+
<div class="text-center">
|
|
53
|
+
<button type="button" id="resend-otp" class="text-sm link-primary disabled:opacity-50">
|
|
54
|
+
Resend code
|
|
55
|
+
</button>
|
|
56
|
+
</div>
|
|
57
|
+
</form>
|
|
58
|
+
</div>
|
|
59
|
+
`;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Render phone/email input field.
|
|
63
|
+
*/
|
|
64
|
+
renderPhoneField(config) {
|
|
65
|
+
return (0, components_js_1.renderInput)("tel", "phone", config?.phoneLabel || "Phone number", config?.phonePlaceholder || "+1 (555) 123-4567", true, "tel");
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Render OTP digit input boxes.
|
|
69
|
+
*/
|
|
70
|
+
renderOTPInputs(digits) {
|
|
71
|
+
const inputs = [];
|
|
72
|
+
for (let i = 0; i < digits; i++) {
|
|
73
|
+
inputs.push(`
|
|
74
|
+
<input type="text" inputmode="numeric" pattern="[0-9]" maxlength="1"
|
|
75
|
+
class="w-12 h-14 text-center text-2xl font-bold border border-gray-300 rounded-lg shadow-sm focus-primary"
|
|
76
|
+
data-otp-index="${i}"
|
|
77
|
+
autocomplete="one-time-code" />
|
|
78
|
+
`);
|
|
79
|
+
}
|
|
80
|
+
return inputs.join("");
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Override action buttons - form has its own submit.
|
|
84
|
+
*/
|
|
85
|
+
renderActionButtons() {
|
|
86
|
+
return "";
|
|
87
|
+
}
|
|
88
|
+
renderModeScript() {
|
|
89
|
+
const serverUrl = (0, escape_js_1.escapeJs)(this.config.serverUrl);
|
|
90
|
+
const projectId = (0, escape_js_1.escapeJs)(this.config.projectId);
|
|
91
|
+
const sessionId = (0, escape_js_1.escapeJs)(this.config.sessionId);
|
|
92
|
+
const agentDid = (0, escape_js_1.escapeJs)(this.config.agentDid);
|
|
93
|
+
const tool = (0, escape_js_1.escapeJs)(this.config.tool);
|
|
94
|
+
const scopes = JSON.stringify(this.config.scopes);
|
|
95
|
+
const digits = this.otpConfig?.digits || 6;
|
|
96
|
+
const resendCooldown = this.otpConfig?.resendCooldown || 60;
|
|
97
|
+
return `
|
|
98
|
+
<script>
|
|
99
|
+
(function() {
|
|
100
|
+
const requestContainer = document.getElementById('otp-request-container');
|
|
101
|
+
const verifyContainer = document.getElementById('otp-verify-container');
|
|
102
|
+
const requestForm = document.getElementById('otp-request-form');
|
|
103
|
+
const verifyForm = document.getElementById('otp-verify-form');
|
|
104
|
+
const resendBtn = document.getElementById('resend-otp');
|
|
105
|
+
const otpInputs = document.querySelectorAll('[data-otp-index]');
|
|
106
|
+
|
|
107
|
+
const serverUrl = ${serverUrl};
|
|
108
|
+
const digits = ${digits};
|
|
109
|
+
const cooldown = ${resendCooldown};
|
|
110
|
+
let lastPhone = '';
|
|
111
|
+
let verificationId = '';
|
|
112
|
+
|
|
113
|
+
function getError(id) {
|
|
114
|
+
const container = document.getElementById(id);
|
|
115
|
+
return { container, div: container?.querySelector('div') };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function showError(id, message) {
|
|
119
|
+
const { container, div } = getError(id);
|
|
120
|
+
if (div) {
|
|
121
|
+
div.textContent = message;
|
|
122
|
+
container.classList.remove('hidden');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function hideError(id) {
|
|
127
|
+
const { container } = getError(id);
|
|
128
|
+
if (container) container.classList.add('hidden');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// OTP input auto-focus behavior
|
|
132
|
+
otpInputs.forEach((input, idx) => {
|
|
133
|
+
input.addEventListener('input', (e) => {
|
|
134
|
+
const value = e.target.value;
|
|
135
|
+
if (value && idx < otpInputs.length - 1) {
|
|
136
|
+
otpInputs[idx + 1].focus();
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
input.addEventListener('keydown', (e) => {
|
|
141
|
+
if (e.key === 'Backspace' && !e.target.value && idx > 0) {
|
|
142
|
+
otpInputs[idx - 1].focus();
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
input.addEventListener('paste', (e) => {
|
|
147
|
+
e.preventDefault();
|
|
148
|
+
const paste = (e.clipboardData || window.clipboardData).getData('text');
|
|
149
|
+
const chars = paste.replace(/\\D/g, '').slice(0, digits).split('');
|
|
150
|
+
chars.forEach((char, i) => {
|
|
151
|
+
if (otpInputs[i]) otpInputs[i].value = char;
|
|
152
|
+
});
|
|
153
|
+
if (chars.length > 0 && otpInputs[chars.length - 1]) {
|
|
154
|
+
otpInputs[chars.length - 1].focus();
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Request OTP
|
|
160
|
+
requestForm?.addEventListener('submit', async (e) => {
|
|
161
|
+
e.preventDefault();
|
|
162
|
+
hideError('otp-request-error');
|
|
163
|
+
|
|
164
|
+
const button = requestForm.querySelector('button[type="submit"]');
|
|
165
|
+
const phoneInput = requestForm.querySelector('input[name="phone"]');
|
|
166
|
+
lastPhone = phoneInput.value;
|
|
167
|
+
|
|
168
|
+
button.disabled = true;
|
|
169
|
+
button.textContent = 'Sending...';
|
|
170
|
+
|
|
171
|
+
try {
|
|
172
|
+
const response = await fetch(serverUrl + '/consent/otp/request', {
|
|
173
|
+
method: 'POST',
|
|
174
|
+
headers: { 'Content-Type': 'application/json' },
|
|
175
|
+
body: JSON.stringify({
|
|
176
|
+
phone: lastPhone,
|
|
177
|
+
tool: ${tool},
|
|
178
|
+
scopes: ${scopes},
|
|
179
|
+
agent_did: ${agentDid},
|
|
180
|
+
session_id: ${sessionId},
|
|
181
|
+
project_id: ${projectId},
|
|
182
|
+
})
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
const result = await response.json();
|
|
186
|
+
|
|
187
|
+
if (result.success) {
|
|
188
|
+
verificationId = result.verificationId || '';
|
|
189
|
+
requestContainer.classList.add('hidden');
|
|
190
|
+
verifyContainer.classList.remove('hidden');
|
|
191
|
+
otpInputs[0]?.focus();
|
|
192
|
+
startResendCooldown();
|
|
193
|
+
} else {
|
|
194
|
+
showError('otp-request-error', result.error || 'Failed to send code');
|
|
195
|
+
button.disabled = false;
|
|
196
|
+
button.textContent = 'Send verification code';
|
|
197
|
+
}
|
|
198
|
+
} catch (err) {
|
|
199
|
+
showError('otp-request-error', 'Network error. Please try again.');
|
|
200
|
+
button.disabled = false;
|
|
201
|
+
button.textContent = 'Send verification code';
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
// Verify OTP
|
|
206
|
+
verifyForm?.addEventListener('submit', async (e) => {
|
|
207
|
+
e.preventDefault();
|
|
208
|
+
hideError('otp-verify-error');
|
|
209
|
+
|
|
210
|
+
const button = verifyForm.querySelector('button[type="submit"]');
|
|
211
|
+
const code = Array.from(otpInputs).map(i => i.value).join('');
|
|
212
|
+
|
|
213
|
+
if (code.length !== digits) {
|
|
214
|
+
showError('otp-verify-error', 'Please enter the full code');
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
button.disabled = true;
|
|
219
|
+
button.textContent = 'Verifying...';
|
|
220
|
+
|
|
221
|
+
try {
|
|
222
|
+
const response = await fetch(serverUrl + '/consent/otp/verify', {
|
|
223
|
+
method: 'POST',
|
|
224
|
+
headers: { 'Content-Type': 'application/json' },
|
|
225
|
+
body: JSON.stringify({
|
|
226
|
+
phone: lastPhone,
|
|
227
|
+
code: code,
|
|
228
|
+
verification_id: verificationId,
|
|
229
|
+
tool: ${tool},
|
|
230
|
+
scopes: ${scopes},
|
|
231
|
+
agent_did: ${agentDid},
|
|
232
|
+
session_id: ${sessionId},
|
|
233
|
+
project_id: ${projectId},
|
|
234
|
+
})
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
const result = await response.json();
|
|
238
|
+
|
|
239
|
+
if (result.success) {
|
|
240
|
+
button.textContent = 'Success!';
|
|
241
|
+
button.style.backgroundColor = '#10B981';
|
|
242
|
+
|
|
243
|
+
if (result.redirectUrl) {
|
|
244
|
+
window.location.href = result.redirectUrl;
|
|
245
|
+
} else if (result.delegation_id) {
|
|
246
|
+
window.location.href = serverUrl + '/consent/success?delegation_id=' +
|
|
247
|
+
encodeURIComponent(result.delegation_id) +
|
|
248
|
+
'&project_id=' + encodeURIComponent(${projectId});
|
|
249
|
+
}
|
|
250
|
+
} else {
|
|
251
|
+
showError('otp-verify-error', result.error || 'Invalid code');
|
|
252
|
+
button.disabled = false;
|
|
253
|
+
button.textContent = 'Verify';
|
|
254
|
+
}
|
|
255
|
+
} catch (err) {
|
|
256
|
+
showError('otp-verify-error', 'Network error. Please try again.');
|
|
257
|
+
button.disabled = false;
|
|
258
|
+
button.textContent = 'Verify';
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
// Resend cooldown
|
|
263
|
+
function startResendCooldown() {
|
|
264
|
+
resendBtn.disabled = true;
|
|
265
|
+
let remaining = cooldown;
|
|
266
|
+
resendBtn.textContent = 'Resend code (' + remaining + 's)';
|
|
267
|
+
|
|
268
|
+
const timer = setInterval(() => {
|
|
269
|
+
remaining--;
|
|
270
|
+
if (remaining <= 0) {
|
|
271
|
+
clearInterval(timer);
|
|
272
|
+
resendBtn.disabled = false;
|
|
273
|
+
resendBtn.textContent = 'Resend code';
|
|
274
|
+
} else {
|
|
275
|
+
resendBtn.textContent = 'Resend code (' + remaining + 's)';
|
|
276
|
+
}
|
|
277
|
+
}, 1000);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
resendBtn?.addEventListener('click', async () => {
|
|
281
|
+
if (resendBtn.disabled) return;
|
|
282
|
+
|
|
283
|
+
resendBtn.disabled = true;
|
|
284
|
+
try {
|
|
285
|
+
const response = await fetch(serverUrl + '/consent/otp/request', {
|
|
286
|
+
method: 'POST',
|
|
287
|
+
headers: { 'Content-Type': 'application/json' },
|
|
288
|
+
body: JSON.stringify({
|
|
289
|
+
phone: lastPhone,
|
|
290
|
+
tool: ${tool},
|
|
291
|
+
scopes: ${scopes},
|
|
292
|
+
agent_did: ${agentDid},
|
|
293
|
+
session_id: ${sessionId},
|
|
294
|
+
project_id: ${projectId},
|
|
295
|
+
})
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
const result = await response.json();
|
|
299
|
+
if (result.success) {
|
|
300
|
+
verificationId = result.verificationId || verificationId;
|
|
301
|
+
startResendCooldown();
|
|
302
|
+
} else {
|
|
303
|
+
resendBtn.disabled = false;
|
|
304
|
+
alert(result.error || 'Failed to resend');
|
|
305
|
+
}
|
|
306
|
+
} catch (err) {
|
|
307
|
+
resendBtn.disabled = false;
|
|
308
|
+
alert('Network error');
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
})();
|
|
312
|
+
</script>`;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
exports.OTPTemplate = OTPTemplate;
|
|
316
|
+
//# sourceMappingURL=otp.template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otp.template.js","sourceRoot":"","sources":["../../../../src/templates/modes/otp.template.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Success Page Template
|
|
4
|
+
*
|
|
5
|
+
* Rendered after successful consent approval.
|
|
6
|
+
*
|
|
7
|
+
* @module @kya-os/consent/templates/modes/success
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.SuccessTemplate = void 0;
|
|
11
|
+
exports.renderSuccessPage = renderSuccessPage;
|
|
12
|
+
const tokens_js_1 = require("../../styles/tokens.js");
|
|
13
|
+
const stylesheet_js_1 = require("../../styles/stylesheet.js");
|
|
14
|
+
const components_js_1 = require("../base/components.js");
|
|
15
|
+
const escape_js_1 = require("../../security/escape.js");
|
|
16
|
+
const colors_js_1 = require("../../constants/colors.js");
|
|
17
|
+
const defaults_js_1 = require("../../constants/defaults.js");
|
|
18
|
+
const css_variables_js_1 = require("../../styles/css-variables.js");
|
|
19
|
+
/**
|
|
20
|
+
* Success Page Template
|
|
21
|
+
*
|
|
22
|
+
* Standalone template for the success page (not extending BaseConsentTemplate).
|
|
23
|
+
* Renders a simple confirmation after consent is granted.
|
|
24
|
+
*/
|
|
25
|
+
class SuccessTemplate {
|
|
26
|
+
constructor(config, branding) {
|
|
27
|
+
this.config = config;
|
|
28
|
+
const primaryColor = branding?.primaryColor || colors_js_1.DEFAULT_COLORS.PRIMARY;
|
|
29
|
+
const secondaryColor = branding?.secondaryColor || colors_js_1.DEFAULT_COLORS.SECONDARY;
|
|
30
|
+
this.branding = {
|
|
31
|
+
primaryColor,
|
|
32
|
+
secondaryColor,
|
|
33
|
+
logoUrl: branding?.logoUrl,
|
|
34
|
+
companyName: branding?.companyName,
|
|
35
|
+
cssVars: {
|
|
36
|
+
"--consent-primary": primaryColor,
|
|
37
|
+
"--consent-secondary": secondaryColor,
|
|
38
|
+
"--consent-primary-rgb": (0, css_variables_js_1.hexToRgb)(primaryColor),
|
|
39
|
+
"--consent-secondary-rgb": (0, css_variables_js_1.hexToRgb)(secondaryColor),
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Render the success page.
|
|
45
|
+
*/
|
|
46
|
+
render() {
|
|
47
|
+
const title = this.config.title || defaults_js_1.DEFAULT_SUCCESS.title;
|
|
48
|
+
const description = this.config.description || defaults_js_1.DEFAULT_SUCCESS.description;
|
|
49
|
+
const buttonText = this.config.continueButtonText || defaults_js_1.DEFAULT_SUCCESS.continueButtonText;
|
|
50
|
+
return `<!DOCTYPE html>
|
|
51
|
+
<html lang="en">
|
|
52
|
+
<head>
|
|
53
|
+
${this.renderHead()}
|
|
54
|
+
</head>
|
|
55
|
+
<body class="bg-gray-50 min-h-screen flex items-center justify-center p-4">
|
|
56
|
+
<div class="${tokens_js_1.CONSENT_CLASSES.container}">
|
|
57
|
+
<div class="${tokens_js_1.CONSENT_CLASSES.content}">
|
|
58
|
+
<div class="text-center py-8">
|
|
59
|
+
${(0, components_js_1.renderSuccessIcon)()}
|
|
60
|
+
<h1 class="${tokens_js_1.CONSENT_CLASSES.title} mb-4">${(0, escape_js_1.escapeHtml)(title)}</h1>
|
|
61
|
+
<p class="text-gray-600 mb-8">${(0, escape_js_1.escapeHtml)(description)}</p>
|
|
62
|
+
${this.renderCredentialInfo()}
|
|
63
|
+
<div class="mt-6">
|
|
64
|
+
${(0, components_js_1.renderFullWidthButton)(buttonText, "button")}
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
${this.renderScript()}
|
|
70
|
+
</body>
|
|
71
|
+
</html>`;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Render the <head> section.
|
|
75
|
+
*/
|
|
76
|
+
renderHead() {
|
|
77
|
+
return `
|
|
78
|
+
<meta charset="UTF-8">
|
|
79
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
80
|
+
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.tailwindcss.com; style-src 'self' 'unsafe-inline' https://cdn.tailwindcss.com; img-src 'self' data: https:; font-src 'self' data:;">
|
|
81
|
+
<title>Access Granted</title>
|
|
82
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
83
|
+
<style>
|
|
84
|
+
${(0, stylesheet_js_1.generateHeadStyles)(this.branding)}
|
|
85
|
+
</style>
|
|
86
|
+
`;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Render credential/delegation info.
|
|
90
|
+
*/
|
|
91
|
+
renderCredentialInfo() {
|
|
92
|
+
if (!this.config.delegationId) {
|
|
93
|
+
return "";
|
|
94
|
+
}
|
|
95
|
+
return `
|
|
96
|
+
<div class="bg-gray-50 rounded-lg p-4 mb-4">
|
|
97
|
+
<p class="text-xs text-gray-500 uppercase tracking-wide mb-1">Delegation ID</p>
|
|
98
|
+
<p class="text-sm font-mono text-gray-700 break-all">${(0, escape_js_1.escapeHtml)(this.config.delegationId)}</p>
|
|
99
|
+
</div>
|
|
100
|
+
`;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Render client-side script.
|
|
104
|
+
*/
|
|
105
|
+
renderScript() {
|
|
106
|
+
const autoClose = this.config.autoClose ?? false;
|
|
107
|
+
return `
|
|
108
|
+
<script>
|
|
109
|
+
(function() {
|
|
110
|
+
const closeBtn = document.querySelector('button');
|
|
111
|
+
const autoClose = ${autoClose};
|
|
112
|
+
|
|
113
|
+
if (closeBtn) {
|
|
114
|
+
closeBtn.addEventListener('click', function() {
|
|
115
|
+
window.close();
|
|
116
|
+
// If window.close() doesn't work (not opened by script), redirect home
|
|
117
|
+
setTimeout(function() {
|
|
118
|
+
window.location.href = '/';
|
|
119
|
+
}, 100);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (autoClose) {
|
|
124
|
+
setTimeout(function() {
|
|
125
|
+
window.close();
|
|
126
|
+
}, 3000);
|
|
127
|
+
}
|
|
128
|
+
})();
|
|
129
|
+
</script>`;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
exports.SuccessTemplate = SuccessTemplate;
|
|
133
|
+
/**
|
|
134
|
+
* Render a success page with the given configuration.
|
|
135
|
+
*/
|
|
136
|
+
function renderSuccessPage(config, branding) {
|
|
137
|
+
const template = new SuccessTemplate(config, branding);
|
|
138
|
+
return template.render();
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=success.template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"success.template.js","sourceRoot":"","sources":["../../../../src/templates/modes/success.template.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AA2IH,8CAMC;AA/ID,sDAAyD;AACzD,8DAAgE;AAChE,yDAAiF;AACjF,wDAAsD;AAGtD,yDAA2D;AAC3D,6DAA8D;AAC9D,oEAAyD;AAEzD;;;;;GAKG;AACH,MAAa,eAAe;IAI1B,YAAY,MAAyB,EAAE,QAA2C;QAChF,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,MAAM,YAAY,GAAG,QAAQ,EAAE,YAAY,IAAI,0BAAc,CAAC,OAAO,CAAC;QACtE,MAAM,cAAc,GAAG,QAAQ,EAAE,cAAc,IAAI,0BAAc,CAAC,SAAS,CAAC;QAC5E,IAAI,CAAC,QAAQ,GAAG;YACd,YAAY;YACZ,cAAc;YACd,OAAO,EAAE,QAAQ,EAAE,OAAO;YAC1B,WAAW,EAAE,QAAQ,EAAE,WAAW;YAClC,OAAO,EAAE;gBACP,mBAAmB,EAAE,YAAY;gBACjC,qBAAqB,EAAE,cAAc;gBACrC,uBAAuB,EAAE,IAAA,2BAAQ,EAAC,YAAY,CAAC;gBAC/C,yBAAyB,EAAE,IAAA,2BAAQ,EAAC,cAAc,CAAC;aACpD;SACF,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,MAAM;QACJ,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,6BAAe,CAAC,KAAK,CAAC;QACzD,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,6BAAe,CAAC,WAAW,CAAC;QAC3E,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,kBAAkB,IAAI,6BAAe,CAAC,kBAAkB,CAAC;QAExF,OAAO;;;IAGP,IAAI,CAAC,UAAU,EAAE;;;gBAGL,2BAAe,CAAC,SAAS;kBACvB,2BAAe,CAAC,OAAO;;UAE/B,IAAA,iCAAiB,GAAE;qBACR,2BAAe,CAAC,KAAK,UAAU,IAAA,sBAAU,EAAC,KAAK,CAAC;wCAC7B,IAAA,sBAAU,EAAC,WAAW,CAAC;UACrD,IAAI,CAAC,oBAAoB,EAAE;;YAEzB,IAAA,qCAAqB,EAAC,UAAU,EAAE,QAAQ,CAAC;;;;;IAKnD,IAAI,CAAC,YAAY,EAAE;;QAEf,CAAC;IACP,CAAC;IAED;;OAEG;IACK,UAAU;QAChB,OAAO;;;;;;;UAOD,IAAA,kCAAkB,EAAC,IAAI,CAAC,QAAQ,CAAC;;KAEtC,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,oBAAoB;QAC1B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;YAC9B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,OAAO;;;+DAGoD,IAAA,sBAAU,EAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC;;KAE9F,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,YAAY;QAClB,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,KAAK,CAAC;QAEjD,OAAO;;;;sBAIW,SAAS;;;;;;;;;;;;;;;;;;UAkBrB,CAAC;IACT,CAAC;CACF;AApHD,0CAoHC;AAED;;GAEG;AACH,SAAgB,iBAAiB,CAC/B,MAAyB,EACzB,QAA2C;IAE3C,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvD,OAAO,QAAQ,CAAC,MAAM,EAAE,CAAC;AAC3B,CAAC"}
|