@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,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Stylesheet Generation
|
|
4
|
+
*
|
|
5
|
+
* Generates complete CSS stylesheets for consent pages.
|
|
6
|
+
*
|
|
7
|
+
* @module @kya-os/consent/styles/stylesheet
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.TRANSITION_STYLES = exports.SPINNER_STYLES = exports.INPUT_STYLES = exports.CHECKBOX_STYLES = void 0;
|
|
11
|
+
exports.generateStylesheet = generateStylesheet;
|
|
12
|
+
exports.generateInlineStyles = generateInlineStyles;
|
|
13
|
+
exports.generateComponentStyles = generateComponentStyles;
|
|
14
|
+
exports.generateHeadStyles = generateHeadStyles;
|
|
15
|
+
const css_variables_js_1 = require("./css-variables.js");
|
|
16
|
+
/**
|
|
17
|
+
* Custom checkbox styles that work with Tailwind's appearance-none
|
|
18
|
+
*
|
|
19
|
+
* Creates a checkmark using CSS that appears when checked.
|
|
20
|
+
*/
|
|
21
|
+
exports.CHECKBOX_STYLES = `
|
|
22
|
+
/* Custom checkbox checkmark */
|
|
23
|
+
input[type="checkbox"]:checked::before {
|
|
24
|
+
content: '';
|
|
25
|
+
position: absolute;
|
|
26
|
+
left: 50%;
|
|
27
|
+
top: 50%;
|
|
28
|
+
width: 5px;
|
|
29
|
+
height: 9px;
|
|
30
|
+
border: solid white;
|
|
31
|
+
border-width: 0 2px 2px 0;
|
|
32
|
+
transform: translate(-50%, -60%) rotate(45deg);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* Focus ring for accessibility */
|
|
36
|
+
input[type="checkbox"]:focus-visible {
|
|
37
|
+
outline: 2px solid var(--consent-primary);
|
|
38
|
+
outline-offset: 2px;
|
|
39
|
+
}
|
|
40
|
+
`;
|
|
41
|
+
/**
|
|
42
|
+
* Form input focus styles
|
|
43
|
+
*/
|
|
44
|
+
exports.INPUT_STYLES = `
|
|
45
|
+
/* Input focus states */
|
|
46
|
+
input:focus,
|
|
47
|
+
select:focus,
|
|
48
|
+
textarea:focus {
|
|
49
|
+
outline: none;
|
|
50
|
+
ring: 2px;
|
|
51
|
+
ring-color: var(--consent-primary);
|
|
52
|
+
border-color: transparent;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* Password visibility toggle button */
|
|
56
|
+
.password-toggle {
|
|
57
|
+
position: absolute;
|
|
58
|
+
right: 12px;
|
|
59
|
+
top: 50%;
|
|
60
|
+
transform: translateY(-50%);
|
|
61
|
+
background: none;
|
|
62
|
+
border: none;
|
|
63
|
+
padding: 4px;
|
|
64
|
+
cursor: pointer;
|
|
65
|
+
color: #6B7280;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.password-toggle:hover {
|
|
69
|
+
color: #374151;
|
|
70
|
+
}
|
|
71
|
+
`;
|
|
72
|
+
/**
|
|
73
|
+
* Loading spinner animation
|
|
74
|
+
*/
|
|
75
|
+
exports.SPINNER_STYLES = `
|
|
76
|
+
/* Loading spinner */
|
|
77
|
+
@keyframes spin {
|
|
78
|
+
to {
|
|
79
|
+
transform: rotate(360deg);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.animate-spin {
|
|
84
|
+
animation: spin 1s linear infinite;
|
|
85
|
+
}
|
|
86
|
+
`;
|
|
87
|
+
/**
|
|
88
|
+
* Smooth transitions
|
|
89
|
+
*/
|
|
90
|
+
exports.TRANSITION_STYLES = `
|
|
91
|
+
/* Smooth transitions */
|
|
92
|
+
.transition-opacity {
|
|
93
|
+
transition-property: opacity;
|
|
94
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
95
|
+
transition-duration: 150ms;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.transition-colors {
|
|
99
|
+
transition-property: color, background-color, border-color;
|
|
100
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
101
|
+
transition-duration: 150ms;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.transition-shadow {
|
|
105
|
+
transition-property: box-shadow;
|
|
106
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
107
|
+
transition-duration: 150ms;
|
|
108
|
+
}
|
|
109
|
+
`;
|
|
110
|
+
/**
|
|
111
|
+
* Generate a complete stylesheet for consent pages
|
|
112
|
+
*
|
|
113
|
+
* @param branding - Branding configuration
|
|
114
|
+
* @returns Complete CSS stylesheet string
|
|
115
|
+
*/
|
|
116
|
+
function generateStylesheet(branding) {
|
|
117
|
+
const rootVars = (0, css_variables_js_1.generateRootCSSBlock)(branding);
|
|
118
|
+
return `
|
|
119
|
+
/* Consent Page Styles - Generated by @kya-os/consent */
|
|
120
|
+
|
|
121
|
+
${rootVars}
|
|
122
|
+
|
|
123
|
+
${exports.CHECKBOX_STYLES}
|
|
124
|
+
|
|
125
|
+
${exports.INPUT_STYLES}
|
|
126
|
+
|
|
127
|
+
${exports.SPINNER_STYLES}
|
|
128
|
+
|
|
129
|
+
${exports.TRANSITION_STYLES}
|
|
130
|
+
|
|
131
|
+
/* Button hover states with primary color */
|
|
132
|
+
button[type="submit"]:not(:disabled):hover,
|
|
133
|
+
.btn-primary:not(:disabled):hover {
|
|
134
|
+
opacity: 0.9;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* Disabled states */
|
|
138
|
+
button:disabled,
|
|
139
|
+
input:disabled {
|
|
140
|
+
opacity: 0.5;
|
|
141
|
+
cursor: not-allowed;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/* Link with primary color */
|
|
145
|
+
a.consent-link {
|
|
146
|
+
color: var(--consent-primary);
|
|
147
|
+
text-decoration: none;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
a.consent-link:hover {
|
|
151
|
+
text-decoration: underline;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* Scope badge with derived colors */
|
|
155
|
+
.scope-badge {
|
|
156
|
+
background-color: var(--consent-secondary);
|
|
157
|
+
color: var(--consent-primary);
|
|
158
|
+
}
|
|
159
|
+
`.trim();
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Generate minimal inline styles (for embedding in HTML)
|
|
163
|
+
*
|
|
164
|
+
* @param branding - Branding configuration
|
|
165
|
+
* @returns Minimal CSS for inline <style> tag
|
|
166
|
+
*/
|
|
167
|
+
function generateInlineStyles(branding) {
|
|
168
|
+
const rootVars = (0, css_variables_js_1.generateRootCSSBlock)(branding);
|
|
169
|
+
return `
|
|
170
|
+
${rootVars}
|
|
171
|
+
${exports.CHECKBOX_STYLES}
|
|
172
|
+
input:focus { outline: none; box-shadow: 0 0 0 2px var(--consent-primary); }
|
|
173
|
+
`.trim();
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Generate styles for a specific component
|
|
177
|
+
*
|
|
178
|
+
* @param component - Component name
|
|
179
|
+
* @returns Component-specific CSS
|
|
180
|
+
*/
|
|
181
|
+
function generateComponentStyles(component) {
|
|
182
|
+
switch (component) {
|
|
183
|
+
case "checkbox":
|
|
184
|
+
return exports.CHECKBOX_STYLES;
|
|
185
|
+
case "input":
|
|
186
|
+
return exports.INPUT_STYLES;
|
|
187
|
+
case "spinner":
|
|
188
|
+
return exports.SPINNER_STYLES;
|
|
189
|
+
case "all":
|
|
190
|
+
return [exports.CHECKBOX_STYLES, exports.INPUT_STYLES, exports.SPINNER_STYLES, exports.TRANSITION_STYLES].join("\n");
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Generate styles for the <head> section of consent pages
|
|
195
|
+
*
|
|
196
|
+
* This is an alias for generateStylesheet for compatibility with templates.
|
|
197
|
+
*
|
|
198
|
+
* @param branding - Branding configuration
|
|
199
|
+
* @returns CSS styles for <style> tag in <head>
|
|
200
|
+
*/
|
|
201
|
+
function generateHeadStyles(branding) {
|
|
202
|
+
return generateStylesheet(branding);
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=stylesheet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stylesheet.js","sourceRoot":"","sources":["../../../src/styles/stylesheet.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AA6GH,gDA6CC;AAQD,oDAQC;AAQD,0DAaC;AAUD,gDAEC;AAxMD,yDAA0D;AAE1D;;;;GAIG;AACU,QAAA,eAAe,GAAG;;;;;;;;;;;;;;;;;;;CAmB9B,CAAC;AAEF;;GAEG;AACU,QAAA,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2B3B,CAAC;AAEF;;GAEG;AACU,QAAA,cAAc,GAAG;;;;;;;;;;;CAW7B,CAAC;AAEF;;GAEG;AACU,QAAA,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;CAmBhC,CAAC;AAEF;;;;;GAKG;AACH,SAAgB,kBAAkB,CAAC,QAA0B;IAC3D,MAAM,QAAQ,GAAG,IAAA,uCAAoB,EAAC,QAAQ,CAAC,CAAC;IAEhD,OAAO;;;EAGP,QAAQ;;EAER,uBAAe;;EAEf,oBAAY;;EAEZ,sBAAc;;EAEd,yBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BlB,CAAC,IAAI,EAAE,CAAC;AACT,CAAC;AAED;;;;;GAKG;AACH,SAAgB,oBAAoB,CAAC,QAA0B;IAC7D,MAAM,QAAQ,GAAG,IAAA,uCAAoB,EAAC,QAAQ,CAAC,CAAC;IAEhD,OAAO;EACP,QAAQ;EACR,uBAAe;;CAEhB,CAAC,IAAI,EAAE,CAAC;AACT,CAAC;AAED;;;;;GAKG;AACH,SAAgB,uBAAuB,CACrC,SAAmD;IAEnD,QAAQ,SAAS,EAAE,CAAC;QAClB,KAAK,UAAU;YACb,OAAO,uBAAe,CAAC;QACzB,KAAK,OAAO;YACV,OAAO,oBAAY,CAAC;QACtB,KAAK,SAAS;YACZ,OAAO,sBAAc,CAAC;QACxB,KAAK,KAAK;YACR,OAAO,CAAC,uBAAe,EAAE,oBAAY,EAAE,sBAAc,EAAE,yBAAiB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzF,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,kBAAkB,CAAC,QAA0B;IAC3D,OAAO,kBAAkB,CAAC,QAAQ,CAAC,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Consent CSS Class Tokens
|
|
4
|
+
*
|
|
5
|
+
* Single source of truth for all Tailwind classes used in consent pages.
|
|
6
|
+
* CRITICAL: These MUST match AgentShield preview components exactly.
|
|
7
|
+
*
|
|
8
|
+
* Divergences identified and fixed:
|
|
9
|
+
* - Button: py-2 → py-3, rounded-md → rounded-lg (match AgentShield)
|
|
10
|
+
* - Checkbox: w-5 h-5 → w-4 h-4 (match AgentShield)
|
|
11
|
+
* - Container: max-w-md → max-w-[512px] (match AgentShield)
|
|
12
|
+
*
|
|
13
|
+
* @module @kya-os/consent/styles/tokens
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.CONSENT_CLASSES = void 0;
|
|
17
|
+
/**
|
|
18
|
+
* CONSENT_CLASSES - Canonical CSS classes for consent UI components
|
|
19
|
+
*
|
|
20
|
+
* All classes are Tailwind CSS utilities that match AgentShield exactly.
|
|
21
|
+
*/
|
|
22
|
+
exports.CONSENT_CLASSES = {
|
|
23
|
+
// =========================================================================
|
|
24
|
+
// Container / Shell - Matches AgentShield PreviewShell.tsx
|
|
25
|
+
// =========================================================================
|
|
26
|
+
/** Main container wrapper - background with centered content */
|
|
27
|
+
wrapper: "bg-gray-50 min-h-screen flex items-center justify-center p-4",
|
|
28
|
+
/** Card container - MUST be max-w-[512px] not max-w-md (448px) */
|
|
29
|
+
container: "bg-white rounded-[20px] border border-black/10 shadow-xl overflow-hidden max-w-[512px] w-full",
|
|
30
|
+
/** Header section with logo and agent info */
|
|
31
|
+
header: "p-6 pb-0",
|
|
32
|
+
/** Main content area */
|
|
33
|
+
content: "p-6 pt-4 space-y-6",
|
|
34
|
+
/** Footer with buttons */
|
|
35
|
+
footer: "p-6 pt-0 flex gap-3",
|
|
36
|
+
// =========================================================================
|
|
37
|
+
// Buttons - Matches AgentShield PreviewButton.tsx
|
|
38
|
+
// CRITICAL: h-11, py-3, rounded-lg (NOT py-2, rounded-md)
|
|
39
|
+
// =========================================================================
|
|
40
|
+
/** Primary action button (Allow access) */
|
|
41
|
+
buttonPrimary: "px-4 py-3 h-11 rounded-lg text-white font-medium transition-opacity hover:opacity-90 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
42
|
+
/** Secondary action button (Cancel) */
|
|
43
|
+
buttonSecondary: "px-4 py-3 h-11 rounded-lg border border-gray-300 text-gray-700 font-medium hover:bg-gray-50 transition-colors",
|
|
44
|
+
/** Full width button variant */
|
|
45
|
+
buttonFull: "w-full py-3 px-4 h-11 rounded-lg text-white font-medium transition-opacity hover:opacity-90 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
46
|
+
/** OAuth/Social login button */
|
|
47
|
+
buttonOAuth: "w-full py-3 px-4 h-11 rounded-lg border border-gray-300 text-gray-700 font-medium hover:bg-gray-50 transition-colors flex items-center justify-center gap-2",
|
|
48
|
+
/** Icon button (small) */
|
|
49
|
+
buttonIcon: "p-2 rounded-lg hover:bg-gray-100 transition-colors",
|
|
50
|
+
/** Button group container (for multiple buttons) */
|
|
51
|
+
buttonGroup: "flex gap-3 mt-6",
|
|
52
|
+
// =========================================================================
|
|
53
|
+
// Checkbox - Matches AgentShield PreviewCheckbox.tsx
|
|
54
|
+
// CRITICAL: w-4 h-4 (NOT w-5 h-5)
|
|
55
|
+
// =========================================================================
|
|
56
|
+
/** Checkbox input - custom styled */
|
|
57
|
+
checkbox: "w-4 h-4 rounded border border-gray-300 bg-white checked:bg-[var(--consent-primary)] checked:border-[var(--consent-primary)] appearance-none cursor-pointer relative flex-shrink-0",
|
|
58
|
+
/** Checkbox container with label */
|
|
59
|
+
checkboxContainer: "flex items-start gap-3 cursor-pointer",
|
|
60
|
+
/** Checkbox label text */
|
|
61
|
+
checkboxLabel: "text-sm text-gray-700 select-none",
|
|
62
|
+
/** Checkbox wrapper for proper alignment */
|
|
63
|
+
checkboxWrapper: "flex items-center h-5",
|
|
64
|
+
/** Checkbox text (alias for checkboxLabel) */
|
|
65
|
+
checkboxText: "text-sm text-gray-700 select-none",
|
|
66
|
+
// =========================================================================
|
|
67
|
+
// Form Elements
|
|
68
|
+
// =========================================================================
|
|
69
|
+
/** Input field (text, email, password) */
|
|
70
|
+
input: "w-full px-4 py-3 h-11 rounded-lg border border-gray-300 text-gray-900 placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-[var(--consent-primary)] focus:border-transparent transition-shadow",
|
|
71
|
+
/** Input with error state */
|
|
72
|
+
inputError: "w-full px-4 py-3 h-11 rounded-lg border border-red-500 text-gray-900 placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-red-500 focus:border-transparent",
|
|
73
|
+
/** Form label */
|
|
74
|
+
label: "block text-sm font-medium text-gray-700 mb-1.5",
|
|
75
|
+
/** Form field container */
|
|
76
|
+
fieldGroup: "space-y-1.5",
|
|
77
|
+
/** Error message text */
|
|
78
|
+
errorText: "text-sm text-red-600 mt-1",
|
|
79
|
+
/** Help text */
|
|
80
|
+
helpText: "text-sm text-gray-500 mt-1",
|
|
81
|
+
/** Input focus ring class */
|
|
82
|
+
inputFocus: "focus:outline-none focus:ring-2 focus:ring-[var(--consent-primary)] focus:border-transparent",
|
|
83
|
+
// =========================================================================
|
|
84
|
+
// Typography
|
|
85
|
+
// =========================================================================
|
|
86
|
+
/** Page title */
|
|
87
|
+
title: "text-xl font-semibold text-gray-900",
|
|
88
|
+
/** Page description / subtitle */
|
|
89
|
+
description: "text-sm text-gray-600 mt-1",
|
|
90
|
+
/** Subtitle (alternative name for description) */
|
|
91
|
+
subtitle: "text-sm text-gray-600 mt-1",
|
|
92
|
+
/** Section header */
|
|
93
|
+
sectionHeader: "text-sm font-medium text-gray-700",
|
|
94
|
+
/** Body text */
|
|
95
|
+
bodyText: "text-sm text-gray-700",
|
|
96
|
+
/** Muted / secondary text */
|
|
97
|
+
mutedText: "text-sm text-gray-500",
|
|
98
|
+
/** Link styling */
|
|
99
|
+
link: "text-[var(--consent-primary)] hover:underline cursor-pointer",
|
|
100
|
+
/** Header centered text */
|
|
101
|
+
headerCenter: "text-center",
|
|
102
|
+
// =========================================================================
|
|
103
|
+
// Permissions List
|
|
104
|
+
// =========================================================================
|
|
105
|
+
/** Permissions section container */
|
|
106
|
+
permissionsContainer: "space-y-2",
|
|
107
|
+
/** Permissions header text */
|
|
108
|
+
permissionsHeader: "text-sm font-medium text-gray-700 mb-2",
|
|
109
|
+
/** Permissions list wrapper */
|
|
110
|
+
permissionsList: "space-y-2",
|
|
111
|
+
/** Single permission item */
|
|
112
|
+
permissionItem: "flex items-center gap-2 text-sm text-gray-700 bg-gray-50 px-3 py-2 rounded-lg",
|
|
113
|
+
/** Permission icon */
|
|
114
|
+
permissionIcon: "w-4 h-4 text-[var(--consent-primary)] flex-shrink-0",
|
|
115
|
+
/** Scope badge */
|
|
116
|
+
scopeBadge: "inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800",
|
|
117
|
+
// =========================================================================
|
|
118
|
+
// Agent Info Section
|
|
119
|
+
// =========================================================================
|
|
120
|
+
/** Agent info container */
|
|
121
|
+
agentContainer: "flex items-start gap-4",
|
|
122
|
+
/** Agent info wrapper (alternative name) */
|
|
123
|
+
agentWrapper: "flex items-start gap-4",
|
|
124
|
+
/** Agent avatar/logo */
|
|
125
|
+
agentAvatar: "w-12 h-12 rounded-xl bg-gray-100 flex items-center justify-center text-gray-400 flex-shrink-0",
|
|
126
|
+
/** Agent icon container (alternative to avatar) */
|
|
127
|
+
agentIcon: "w-12 h-12 rounded-xl bg-gray-100 flex items-center justify-center text-gray-400 flex-shrink-0",
|
|
128
|
+
/** Agent details wrapper */
|
|
129
|
+
agentDetails: "flex-1 min-w-0",
|
|
130
|
+
/** Agent name */
|
|
131
|
+
agentName: "font-medium text-gray-900 truncate",
|
|
132
|
+
/** Agent description text */
|
|
133
|
+
agentDescription: "text-sm text-gray-600 mt-1",
|
|
134
|
+
/** Agent DID (truncated) */
|
|
135
|
+
agentDid: "text-xs text-gray-500 font-mono truncate",
|
|
136
|
+
// =========================================================================
|
|
137
|
+
// Success Page
|
|
138
|
+
// =========================================================================
|
|
139
|
+
/** Success icon container */
|
|
140
|
+
successIcon: "w-16 h-16 rounded-full bg-green-100 flex items-center justify-center mx-auto mb-4",
|
|
141
|
+
/** Success checkmark */
|
|
142
|
+
successCheck: "w-8 h-8 text-green-600",
|
|
143
|
+
/** Credential display box */
|
|
144
|
+
credentialBox: "bg-gray-50 rounded-lg p-4 font-mono text-sm text-gray-700 break-all",
|
|
145
|
+
// =========================================================================
|
|
146
|
+
// Loading States
|
|
147
|
+
// =========================================================================
|
|
148
|
+
/** Loading spinner */
|
|
149
|
+
spinner: "animate-spin w-5 h-5 text-white",
|
|
150
|
+
/** Loading overlay */
|
|
151
|
+
loadingOverlay: "absolute inset-0 bg-white/80 flex items-center justify-center",
|
|
152
|
+
// =========================================================================
|
|
153
|
+
// Dividers
|
|
154
|
+
// =========================================================================
|
|
155
|
+
/** Horizontal divider */
|
|
156
|
+
divider: "border-t border-gray-200",
|
|
157
|
+
/** Divider with text (OR) */
|
|
158
|
+
dividerWithText: "relative flex items-center my-4",
|
|
159
|
+
/** Divider text styling */
|
|
160
|
+
dividerText: "absolute inset-0 flex items-center justify-center text-sm text-gray-500 bg-white px-4",
|
|
161
|
+
// =========================================================================
|
|
162
|
+
// Alerts / Messages
|
|
163
|
+
// =========================================================================
|
|
164
|
+
/** Info alert */
|
|
165
|
+
alertInfo: "bg-blue-50 border border-blue-200 rounded-lg p-4 text-sm text-blue-800",
|
|
166
|
+
/** Warning alert */
|
|
167
|
+
alertWarning: "bg-amber-50 border border-amber-200 rounded-lg p-4 text-sm text-amber-800",
|
|
168
|
+
/** Error alert */
|
|
169
|
+
alertError: "bg-red-50 border border-red-200 rounded-lg p-4 text-sm text-red-800",
|
|
170
|
+
/** Success alert */
|
|
171
|
+
alertSuccess: "bg-green-50 border border-green-200 rounded-lg p-4 text-sm text-green-800",
|
|
172
|
+
// =========================================================================
|
|
173
|
+
// Expiration Notice
|
|
174
|
+
// =========================================================================
|
|
175
|
+
/** Expiration notice wrapper */
|
|
176
|
+
expirationWrapper: "flex items-center gap-2 text-sm text-gray-500 mt-4",
|
|
177
|
+
// =========================================================================
|
|
178
|
+
// Error Container
|
|
179
|
+
// =========================================================================
|
|
180
|
+
/** Error container (hidden by default) */
|
|
181
|
+
errorContainer: "hidden",
|
|
182
|
+
};
|
|
183
|
+
//# sourceMappingURL=tokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../../src/styles/tokens.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Base Consent Template
|
|
4
|
+
*
|
|
5
|
+
* Abstract class implementing the Template Method pattern.
|
|
6
|
+
* Defines the overall page structure, subclasses implement auth-specific content.
|
|
7
|
+
*
|
|
8
|
+
* @module @kya-os/consent/templates/base/base-template
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.BaseConsentTemplate = void 0;
|
|
12
|
+
const tokens_js_1 = require("../../styles/tokens.js");
|
|
13
|
+
const stylesheet_js_1 = require("../../styles/stylesheet.js");
|
|
14
|
+
const components_js_1 = require("./components.js");
|
|
15
|
+
const escape_js_1 = require("../../security/escape.js");
|
|
16
|
+
/**
|
|
17
|
+
* Abstract base class for consent page templates.
|
|
18
|
+
*
|
|
19
|
+
* Implements the Template Method pattern:
|
|
20
|
+
* - `render()` defines the overall structure
|
|
21
|
+
* - Subclasses override `renderAuthContent()` for mode-specific UI
|
|
22
|
+
* - Other methods can be overridden for customization
|
|
23
|
+
*/
|
|
24
|
+
class BaseConsentTemplate {
|
|
25
|
+
constructor(config, resolved) {
|
|
26
|
+
this.config = config;
|
|
27
|
+
this.resolved = resolved;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Optional: Render mode-specific scripts.
|
|
31
|
+
* Override in subclasses if needed.
|
|
32
|
+
*/
|
|
33
|
+
renderModeScript() {
|
|
34
|
+
return "";
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Main render method - Template Method Pattern.
|
|
38
|
+
* Defines the overall page structure.
|
|
39
|
+
*/
|
|
40
|
+
render() {
|
|
41
|
+
return `<!DOCTYPE html>
|
|
42
|
+
<html lang="en">
|
|
43
|
+
<head>
|
|
44
|
+
${this.renderHead()}
|
|
45
|
+
</head>
|
|
46
|
+
<body class="bg-gray-50 min-h-screen flex items-center justify-center p-4">
|
|
47
|
+
<div class="${tokens_js_1.CONSENT_CLASSES.container}">
|
|
48
|
+
${this.renderPageHeader()}
|
|
49
|
+
<div class="${tokens_js_1.CONSENT_CLASSES.content}">
|
|
50
|
+
${this.renderAgentSection()}
|
|
51
|
+
${this.renderAuthContent()}
|
|
52
|
+
${this.renderCustomFields()}
|
|
53
|
+
${this.renderTermsSection()}
|
|
54
|
+
${this.renderActionButtons()}
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
${this.renderForm()}
|
|
58
|
+
${this.renderBaseScript()}
|
|
59
|
+
${this.renderModeScript()}
|
|
60
|
+
</body>
|
|
61
|
+
</html>`;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Render the <head> section with meta tags, styles, and scripts.
|
|
65
|
+
*/
|
|
66
|
+
renderHead() {
|
|
67
|
+
const { branding } = this.resolved;
|
|
68
|
+
return `
|
|
69
|
+
<meta charset="UTF-8">
|
|
70
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
71
|
+
<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:;">
|
|
72
|
+
<title>${this.getPageTitle()}</title>
|
|
73
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
74
|
+
<style>
|
|
75
|
+
${(0, stylesheet_js_1.generateHeadStyles)(branding)}
|
|
76
|
+
</style>
|
|
77
|
+
`;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get the page title.
|
|
81
|
+
*/
|
|
82
|
+
getPageTitle() {
|
|
83
|
+
return `${this.resolved.copy.title} - ${(0, escape_js_1.escapeHtml)(this.config.tool)}`;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Render the page header with logo, company name, and title.
|
|
87
|
+
*/
|
|
88
|
+
renderPageHeader() {
|
|
89
|
+
const { copy, branding } = this.resolved;
|
|
90
|
+
return (0, components_js_1.renderHeader)(copy.title, undefined, branding.logoUrl, branding.companyName);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Render the agent info section with description.
|
|
94
|
+
* Uses config.toolDescription if provided, otherwise falls back to resolved copy.
|
|
95
|
+
*/
|
|
96
|
+
renderAgentSection() {
|
|
97
|
+
const { copy, branding } = this.resolved;
|
|
98
|
+
// Use toolDescription from page config if provided (backward compatibility)
|
|
99
|
+
// Otherwise use the resolved description from remote config
|
|
100
|
+
const description = this.config.toolDescription || copy.resolvedDescription;
|
|
101
|
+
return (0, components_js_1.renderAgentInfo)(description, branding.logoUrl);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Render custom fields section.
|
|
105
|
+
*/
|
|
106
|
+
renderCustomFields() {
|
|
107
|
+
// Custom fields come from resolved config (which gets them from remote config)
|
|
108
|
+
const customFields = this.resolved.customFields;
|
|
109
|
+
if (!customFields || customFields.length === 0) {
|
|
110
|
+
return "";
|
|
111
|
+
}
|
|
112
|
+
const fieldsHtml = customFields
|
|
113
|
+
.map((field) => {
|
|
114
|
+
if (field.type === "checkbox") {
|
|
115
|
+
return (0, components_js_1.renderCheckbox)((0, escape_js_1.escapeAttr)(field.name), (0, escape_js_1.escapeHtml)(field.label), field.required ?? false);
|
|
116
|
+
}
|
|
117
|
+
else if (field.type === "select" && field.options) {
|
|
118
|
+
// Render select dropdown
|
|
119
|
+
const optionsHtml = field.options
|
|
120
|
+
.map((opt) => `<option value="${(0, escape_js_1.escapeAttr)(opt.value)}">${(0, escape_js_1.escapeHtml)(opt.label)}</option>`)
|
|
121
|
+
.join("");
|
|
122
|
+
const requiredAttr = field.required ? " required" : "";
|
|
123
|
+
return `
|
|
124
|
+
<div class="space-y-2">
|
|
125
|
+
<label for="${(0, escape_js_1.escapeAttr)(field.name)}" class="block text-sm font-medium text-gray-700">${(0, escape_js_1.escapeHtml)(field.label)}</label>
|
|
126
|
+
<select
|
|
127
|
+
id="${(0, escape_js_1.escapeAttr)(field.name)}"
|
|
128
|
+
name="${(0, escape_js_1.escapeAttr)(field.name)}"
|
|
129
|
+
class="${tokens_js_1.CONSENT_CLASSES.input}"
|
|
130
|
+
${requiredAttr}
|
|
131
|
+
>
|
|
132
|
+
<option value="">Select...</option>
|
|
133
|
+
${optionsHtml}
|
|
134
|
+
</select>
|
|
135
|
+
</div>
|
|
136
|
+
`;
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
// Use text input for non-checkbox, non-select fields
|
|
140
|
+
const inputType = field.type === "email" ? "email" : "text";
|
|
141
|
+
return (0, components_js_1.renderInput)(inputType, field.name, field.label, field.placeholder, field.required ?? false);
|
|
142
|
+
}
|
|
143
|
+
})
|
|
144
|
+
.join("");
|
|
145
|
+
return `
|
|
146
|
+
<div class="space-y-4">
|
|
147
|
+
${fieldsHtml}
|
|
148
|
+
</div>
|
|
149
|
+
`;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Render the terms acceptance section.
|
|
153
|
+
*/
|
|
154
|
+
renderTermsSection() {
|
|
155
|
+
const { copy } = this.resolved;
|
|
156
|
+
if (!copy.termsRequired) {
|
|
157
|
+
return "";
|
|
158
|
+
}
|
|
159
|
+
// Build terms label with optional link
|
|
160
|
+
let termsLabel = `I agree to the ${(0, escape_js_1.escapeHtml)(copy.termsText)}`;
|
|
161
|
+
if (copy.termsUrl) {
|
|
162
|
+
termsLabel = `I agree to the <a href="${(0, escape_js_1.escapeAttr)(copy.termsUrl)}" target="_blank" rel="noopener noreferrer" class="link-primary">${(0, escape_js_1.escapeHtml)(copy.termsText)}</a>`;
|
|
163
|
+
}
|
|
164
|
+
return `
|
|
165
|
+
<div class="space-y-2">
|
|
166
|
+
${(0, components_js_1.renderCheckbox)("termsAccepted", termsLabel, true)}
|
|
167
|
+
</div>
|
|
168
|
+
`;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Render the action buttons (cancel/submit).
|
|
172
|
+
*/
|
|
173
|
+
renderActionButtons() {
|
|
174
|
+
const { copy } = this.resolved;
|
|
175
|
+
return (0, components_js_1.renderButtonGroup)(copy.cancelButtonText, copy.submitButtonText);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Render the hidden form with common fields.
|
|
179
|
+
*/
|
|
180
|
+
renderForm() {
|
|
181
|
+
const { tool, scopes, agentDid, sessionId, projectId, serverUrl, oauthIdentity } = this.config;
|
|
182
|
+
// Escape HTML entities in JSON to prevent XSS when embedded in HTML attributes
|
|
183
|
+
const scopesJson = (0, escape_js_1.escapeHtml)(JSON.stringify(scopes));
|
|
184
|
+
// Include OAuth identity as hidden field if present (for approval with identity)
|
|
185
|
+
const oauthIdentityField = oauthIdentity
|
|
186
|
+
? `<input type="hidden" name="oauth_identity_json" value="${(0, escape_js_1.escapeHtml)(JSON.stringify(oauthIdentity))}" />`
|
|
187
|
+
: "";
|
|
188
|
+
return `
|
|
189
|
+
<form id="consent-form" method="POST" action="${(0, escape_js_1.escapeAttr)(serverUrl)}/consent/approve" style="display:none;">
|
|
190
|
+
${oauthIdentityField}
|
|
191
|
+
<input type="hidden" name="tool" value="${(0, escape_js_1.escapeAttr)(tool)}" />
|
|
192
|
+
<input type="hidden" name="scopes" value="${scopesJson}" />
|
|
193
|
+
<input type="hidden" name="agent_did" value="${(0, escape_js_1.escapeAttr)(agentDid)}" />
|
|
194
|
+
<input type="hidden" name="session_id" value="${(0, escape_js_1.escapeAttr)(sessionId)}" />
|
|
195
|
+
<input type="hidden" name="project_id" value="${(0, escape_js_1.escapeAttr)(projectId)}" />
|
|
196
|
+
<input type="hidden" name="auth_mode" value="${this.authMode}" />
|
|
197
|
+
<input type="hidden" name="provider_type" value="none" />
|
|
198
|
+
</form>
|
|
199
|
+
`;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Render the base JavaScript for form handling.
|
|
203
|
+
*/
|
|
204
|
+
renderBaseScript() {
|
|
205
|
+
const serverUrl = (0, escape_js_1.escapeJs)(this.config.serverUrl);
|
|
206
|
+
return `
|
|
207
|
+
<script>
|
|
208
|
+
(function() {
|
|
209
|
+
const form = document.getElementById('consent-form');
|
|
210
|
+
if (!form) return;
|
|
211
|
+
|
|
212
|
+
const serverUrl = ${serverUrl};
|
|
213
|
+
|
|
214
|
+
// Find all checkboxes and inputs in the visible content
|
|
215
|
+
const contentDiv = document.querySelector('.${tokens_js_1.CONSENT_CLASSES.content.split(" ")[0]}');
|
|
216
|
+
|
|
217
|
+
// Handle form submission for consent-only mode
|
|
218
|
+
// NOTE: Mode-specific templates (credentials, oauth, etc.) have their own form handlers
|
|
219
|
+
// This handler only applies to buttons within the hidden consent-form
|
|
220
|
+
form.addEventListener('submit', async function(e) {
|
|
221
|
+
e.preventDefault();
|
|
222
|
+
|
|
223
|
+
// Validate required checkboxes
|
|
224
|
+
const termsCheckbox = document.querySelector('input[name="termsAccepted"]');
|
|
225
|
+
if (termsCheckbox && termsCheckbox.required && !termsCheckbox.checked) {
|
|
226
|
+
alert('Please accept the terms and conditions to continue.');
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Collect form data
|
|
231
|
+
const formData = new FormData(form);
|
|
232
|
+
const data = Object.fromEntries(formData.entries());
|
|
233
|
+
|
|
234
|
+
// Add checkbox values from visible form
|
|
235
|
+
if (termsCheckbox) {
|
|
236
|
+
data.termsAccepted = termsCheckbox.checked;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Parse scopes
|
|
240
|
+
try {
|
|
241
|
+
data.scopes = JSON.parse(data.scopes);
|
|
242
|
+
} catch (e) {
|
|
243
|
+
data.scopes = [];
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
try {
|
|
247
|
+
const response = await fetch(serverUrl + '/consent/approve', {
|
|
248
|
+
method: 'POST',
|
|
249
|
+
headers: { 'Content-Type': 'application/json' },
|
|
250
|
+
body: JSON.stringify(data)
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
const result = await response.json();
|
|
254
|
+
|
|
255
|
+
if (result.success) {
|
|
256
|
+
const successUrl = serverUrl + '/consent/success?delegation_id=' +
|
|
257
|
+
encodeURIComponent(result.delegation_id || 'unknown') +
|
|
258
|
+
'&project_id=' + encodeURIComponent(data.project_id || '');
|
|
259
|
+
window.location.href = successUrl;
|
|
260
|
+
} else {
|
|
261
|
+
alert('Authorization failed: ' + (result.error || 'Unknown error'));
|
|
262
|
+
}
|
|
263
|
+
} catch (error) {
|
|
264
|
+
console.error('Error:', error);
|
|
265
|
+
alert('Error: ' + (error instanceof Error ? error.message : String(error)));
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
// Handle cancel button
|
|
270
|
+
document.querySelectorAll('button[type="button"]').forEach(btn => {
|
|
271
|
+
if (btn.textContent && btn.textContent.toLowerCase().includes('cancel')) {
|
|
272
|
+
btn.addEventListener('click', function() {
|
|
273
|
+
window.close();
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
})();
|
|
278
|
+
</script>`;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
exports.BaseConsentTemplate = BaseConsentTemplate;
|
|
282
|
+
//# sourceMappingURL=base-template.js.map
|