@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.
Files changed (126) hide show
  1. package/dist/bundle/inline.d.ts.map +1 -1
  2. package/dist/bundle/inline.js +2 -2
  3. package/dist/bundle/inline.js.map +1 -1
  4. package/dist/bundle/shell.d.ts +5 -0
  5. package/dist/bundle/shell.d.ts.map +1 -1
  6. package/dist/bundle/shell.js +3 -1
  7. package/dist/bundle/shell.js.map +1 -1
  8. package/dist/cjs/bundle/index.js +57 -0
  9. package/dist/cjs/bundle/index.js.map +1 -0
  10. package/dist/cjs/bundle/inline.js +22 -0
  11. package/dist/cjs/bundle/inline.js.map +1 -0
  12. package/dist/cjs/bundle/shell.js +291 -0
  13. package/dist/cjs/bundle/shell.js.map +1 -0
  14. package/dist/cjs/components/consent-button.js +180 -0
  15. package/dist/cjs/components/consent-button.js.map +1 -0
  16. package/dist/cjs/components/consent-checkbox.js +223 -0
  17. package/dist/cjs/components/consent-checkbox.js.map +1 -0
  18. package/dist/cjs/components/consent-input.js +335 -0
  19. package/dist/cjs/components/consent-input.js.map +1 -0
  20. package/dist/cjs/components/consent-oauth-button.js +392 -0
  21. package/dist/cjs/components/consent-oauth-button.js.map +1 -0
  22. package/dist/cjs/components/consent-otp-input.js +388 -0
  23. package/dist/cjs/components/consent-otp-input.js.map +1 -0
  24. package/dist/cjs/components/consent-permissions.js +433 -0
  25. package/dist/cjs/components/consent-permissions.js.map +1 -0
  26. package/dist/cjs/components/consent-shell.js +234 -0
  27. package/dist/cjs/components/consent-shell.js.map +1 -0
  28. package/dist/cjs/components/consent-terms.js +287 -0
  29. package/dist/cjs/components/consent-terms.js.map +1 -0
  30. package/dist/cjs/components/index.js +37 -0
  31. package/dist/cjs/components/index.js.map +1 -0
  32. package/dist/cjs/components/mcp-consent.js +1034 -0
  33. package/dist/cjs/components/mcp-consent.js.map +1 -0
  34. package/dist/cjs/constants/auth-modes.js +128 -0
  35. package/dist/cjs/constants/auth-modes.js.map +1 -0
  36. package/dist/cjs/constants/colors.js +40 -0
  37. package/dist/cjs/constants/colors.js.map +1 -0
  38. package/dist/cjs/constants/defaults.js +146 -0
  39. package/dist/cjs/constants/defaults.js.map +1 -0
  40. package/dist/cjs/constants/index.js +40 -0
  41. package/dist/cjs/constants/index.js.map +1 -0
  42. package/dist/cjs/index.js +49 -0
  43. package/dist/cjs/index.js.map +1 -0
  44. package/dist/cjs/package.json +1 -0
  45. package/dist/cjs/react/index.js +190 -0
  46. package/dist/cjs/react/index.js.map +1 -0
  47. package/dist/cjs/resolution/index.js +28 -0
  48. package/dist/cjs/resolution/index.js.map +1 -0
  49. package/dist/cjs/resolution/resolve-branding.js +159 -0
  50. package/dist/cjs/resolution/resolve-branding.js.map +1 -0
  51. package/dist/cjs/resolution/resolve-config.js +270 -0
  52. package/dist/cjs/resolution/resolve-config.js.map +1 -0
  53. package/dist/cjs/resolution/resolve-copy.js +136 -0
  54. package/dist/cjs/resolution/resolve-copy.js.map +1 -0
  55. package/dist/cjs/schemas/api.schemas.js +156 -0
  56. package/dist/cjs/schemas/api.schemas.js.map +1 -0
  57. package/dist/cjs/schemas/branding.schemas.js +57 -0
  58. package/dist/cjs/schemas/branding.schemas.js.map +1 -0
  59. package/dist/cjs/schemas/config.schemas.js +147 -0
  60. package/dist/cjs/schemas/config.schemas.js.map +1 -0
  61. package/dist/cjs/schemas/index.js +29 -0
  62. package/dist/cjs/schemas/index.js.map +1 -0
  63. package/dist/cjs/schemas/modes.schemas.js +107 -0
  64. package/dist/cjs/schemas/modes.schemas.js.map +1 -0
  65. package/dist/cjs/security/escape.js +206 -0
  66. package/dist/cjs/security/escape.js.map +1 -0
  67. package/dist/cjs/security/index.js +26 -0
  68. package/dist/cjs/security/index.js.map +1 -0
  69. package/dist/cjs/security/validators.js +210 -0
  70. package/dist/cjs/security/validators.js.map +1 -0
  71. package/dist/cjs/styles/css-variables.js +129 -0
  72. package/dist/cjs/styles/css-variables.js.map +1 -0
  73. package/dist/cjs/styles/index.js +28 -0
  74. package/dist/cjs/styles/index.js.map +1 -0
  75. package/dist/cjs/styles/stylesheet.js +204 -0
  76. package/dist/cjs/styles/stylesheet.js.map +1 -0
  77. package/dist/cjs/styles/tokens.js +183 -0
  78. package/dist/cjs/styles/tokens.js.map +1 -0
  79. package/dist/cjs/templates/base/base-template.js +282 -0
  80. package/dist/cjs/templates/base/base-template.js.map +1 -0
  81. package/dist/cjs/templates/base/components.js +295 -0
  82. package/dist/cjs/templates/base/components.js.map +1 -0
  83. package/dist/cjs/templates/base/index.js +26 -0
  84. package/dist/cjs/templates/base/index.js.map +1 -0
  85. package/dist/cjs/templates/index.js +34 -0
  86. package/dist/cjs/templates/index.js.map +1 -0
  87. package/dist/cjs/templates/modes/consent-only.template.js +74 -0
  88. package/dist/cjs/templates/modes/consent-only.template.js.map +1 -0
  89. package/dist/cjs/templates/modes/credentials.template.js +414 -0
  90. package/dist/cjs/templates/modes/credentials.template.js.map +1 -0
  91. package/dist/cjs/templates/modes/index.js +24 -0
  92. package/dist/cjs/templates/modes/index.js.map +1 -0
  93. package/dist/cjs/templates/modes/magic-link.template.js +196 -0
  94. package/dist/cjs/templates/modes/magic-link.template.js.map +1 -0
  95. package/dist/cjs/templates/modes/oauth.template.js +153 -0
  96. package/dist/cjs/templates/modes/oauth.template.js.map +1 -0
  97. package/dist/cjs/templates/modes/otp.template.js +316 -0
  98. package/dist/cjs/templates/modes/otp.template.js.map +1 -0
  99. package/dist/cjs/templates/modes/success.template.js +140 -0
  100. package/dist/cjs/templates/modes/success.template.js.map +1 -0
  101. package/dist/cjs/templates/registry.js +133 -0
  102. package/dist/cjs/templates/registry.js.map +1 -0
  103. package/dist/cjs/types/api.types.js +10 -0
  104. package/dist/cjs/types/api.types.js.map +1 -0
  105. package/dist/cjs/types/branding.types.js +10 -0
  106. package/dist/cjs/types/branding.types.js.map +1 -0
  107. package/dist/cjs/types/config.types.js +10 -0
  108. package/dist/cjs/types/config.types.js.map +1 -0
  109. package/dist/cjs/types/copy.types.js +10 -0
  110. package/dist/cjs/types/copy.types.js.map +1 -0
  111. package/dist/cjs/types/index.js +31 -0
  112. package/dist/cjs/types/index.js.map +1 -0
  113. package/dist/cjs/types/modes.types.js +140 -0
  114. package/dist/cjs/types/modes.types.js.map +1 -0
  115. package/dist/cjs/types/page.types.js +10 -0
  116. package/dist/cjs/types/page.types.js.map +1 -0
  117. package/dist/components/mcp-consent.d.ts +6 -0
  118. package/dist/components/mcp-consent.d.ts.map +1 -1
  119. package/dist/components/mcp-consent.js +14 -0
  120. package/dist/components/mcp-consent.js.map +1 -1
  121. package/dist/consent.js +7 -0
  122. package/dist/consent.min.js +2 -2
  123. package/dist/schemas/api.schemas.d.ts +116 -116
  124. package/dist/schemas/config.schemas.d.ts +116 -116
  125. package/dist/schemas/modes.schemas.d.ts +28 -28
  126. 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