@embarkai/ui-kit 0.1.1

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.
@@ -0,0 +1,102 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Sumsub KYC - Lumia Passport</title>
7
+
8
+ <style>
9
+ * {
10
+ margin: 0;
11
+ padding: 0;
12
+ box-sizing: border-box;
13
+ }
14
+
15
+ html,
16
+ body {
17
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica', 'Arial', sans-serif;
18
+ background: #ffffff;
19
+ color: #333;
20
+ min-height: 100vh;
21
+ padding: 0;
22
+ margin: 0;
23
+ }
24
+
25
+ html::-webkit-scrollbar,
26
+ body::-webkit-scrollbar {
27
+ display: none;
28
+ }
29
+
30
+ #sumsub-websdk-container {
31
+ width: 100%;
32
+ font-size: 0;
33
+ line-height: 0;
34
+ }
35
+
36
+ #sumsub-websdk-container iframe {
37
+ display: block;
38
+ }
39
+
40
+ .loading-container {
41
+ display: flex;
42
+ flex-direction: column;
43
+ align-items: center;
44
+ justify-content: center;
45
+ min-height: 100vh;
46
+ gap: 1rem;
47
+ }
48
+
49
+ .spinner {
50
+ width: 40px;
51
+ height: 40px;
52
+ border: 4px solid rgba(102, 126, 234, 0.3);
53
+ border-top-color: #667eea;
54
+ border-radius: 50%;
55
+ animation: spin 1s linear infinite;
56
+ }
57
+
58
+ @keyframes spin {
59
+ to {
60
+ transform: rotate(360deg);
61
+ }
62
+ }
63
+
64
+ .error-container {
65
+ display: flex;
66
+ flex-direction: column;
67
+ align-items: center;
68
+ justify-content: center;
69
+ min-height: 100vh;
70
+ padding: 2rem;
71
+ text-align: center;
72
+ }
73
+
74
+ .error-message {
75
+ background: #fee;
76
+ border: 1px solid #fcc;
77
+ border-radius: 8px;
78
+ padding: 1rem;
79
+ color: #c33;
80
+ max-width: 500px;
81
+ }
82
+ </style>
83
+ </head>
84
+ <body>
85
+ <div id="loading" class="loading-container">
86
+ <div class="spinner"></div>
87
+ <p>Initializing KYC verification...</p>
88
+ </div>
89
+
90
+ <div id="error" class="error-container" style="display: none">
91
+ <div class="error-message"><strong>Error:</strong> <span id="error-text"></span></div>
92
+ </div>
93
+
94
+ <div id="sumsub-websdk-container"></div>
95
+
96
+ <!-- Sumsub WebSDK -->
97
+ <script src="https://static.sumsub.com/idensic/static/sns-websdk-builder.js"></script>
98
+
99
+ <!-- Sumsub KYC iframe integration script -->
100
+ <script src="./sumsub.js"></script>
101
+ </body>
102
+ </html>
@@ -0,0 +1,237 @@
1
+ /**
2
+ * Sumsub KYC Iframe Script
3
+ * Handles postMessage communication with parent window and Sumsub SDK integration
4
+ */
5
+
6
+ ;(function () {
7
+ 'use strict'
8
+
9
+ // ========================================
10
+ // State Management
11
+ // ========================================
12
+
13
+ let snsWebSdkInstance = null
14
+ let parentOrigin = null
15
+
16
+ // ========================================
17
+ // Logging
18
+ // ========================================
19
+
20
+ function log(message, data) {
21
+ if (data !== undefined) {
22
+ console.log('[Sumsub KYC]', message, data)
23
+ } else {
24
+ console.log('[Sumsub KYC]', message)
25
+ }
26
+ }
27
+
28
+ // ========================================
29
+ // UI Helpers
30
+ // ========================================
31
+
32
+ function hideLoading() {
33
+ const loading = document.getElementById('loading')
34
+ if (loading) loading.style.display = 'none'
35
+ }
36
+
37
+ function showError(message) {
38
+ const loading = document.getElementById('loading')
39
+ const error = document.getElementById('error')
40
+ const errorText = document.getElementById('error-text')
41
+ const container = document.getElementById('sumsub-websdk-container')
42
+
43
+ if (loading) loading.style.display = 'none'
44
+ if (error) error.style.display = 'flex'
45
+ if (errorText) errorText.textContent = message
46
+ if (container) container.style.display = 'none'
47
+
48
+ log('Error displayed:', message)
49
+ }
50
+
51
+ function showSumsubContainer() {
52
+ const loading = document.getElementById('loading')
53
+ const error = document.getElementById('error')
54
+ const container = document.getElementById('sumsub-websdk-container')
55
+
56
+ if (loading) loading.style.display = 'none'
57
+ if (error) error.style.display = 'none'
58
+ if (container) container.style.display = 'block'
59
+ }
60
+
61
+ // ========================================
62
+ // postMessage Communication
63
+ // ========================================
64
+
65
+ function sendMessageToParent(type, data = {}) {
66
+ if (!parentOrigin) {
67
+ log('Cannot send message: parent origin not set')
68
+ return
69
+ }
70
+
71
+ const message = {
72
+ type: type,
73
+ data: data
74
+ }
75
+
76
+ log('Sending message to parent:', message)
77
+ window.parent.postMessage(message, parentOrigin)
78
+ }
79
+
80
+ // ========================================
81
+ // Sumsub SDK Integration
82
+ // ========================================
83
+
84
+ function requestNewAccessToken() {
85
+ log('Requesting new access token from parent...')
86
+
87
+ return new Promise((resolve, reject) => {
88
+ const timeout = setTimeout(() => {
89
+ window.removeEventListener('message', handler)
90
+ reject(new Error('Token refresh timeout'))
91
+ }, 30000)
92
+
93
+ const handler = (event) => {
94
+ const message = event.data
95
+ if (
96
+ message.type === 'SUMSUB_TOKEN_REFRESH' &&
97
+ message.data?.requestId === requestId &&
98
+ message.data.accessToken
99
+ ) {
100
+ clearTimeout(timeout)
101
+ window.removeEventListener('message', handler)
102
+ log('Received new access token from parent')
103
+ resolve(message.data.accessToken)
104
+ }
105
+ }
106
+
107
+ window.addEventListener('message', handler)
108
+
109
+ const requestId = `token_refresh_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
110
+ sendMessageToParent('SUMSUB_TOKEN_EXPIRED', { requestId })
111
+ })
112
+ }
113
+
114
+ function launchSumsubSdk(options) {
115
+ log('Launching Sumsub SDK with access token')
116
+
117
+ try {
118
+ if (!window.snsWebSdk) {
119
+ throw new Error('Sumsub SDK not loaded')
120
+ }
121
+
122
+ // Build SDK instance
123
+ snsWebSdkInstance = window.snsWebSdk
124
+ .init(
125
+ options.accessToken,
126
+ // Expiration handler - called when token expires
127
+ () => {
128
+ log('Access token expired, requesting new one...')
129
+ return requestNewAccessToken()
130
+ }
131
+ )
132
+ .withOptions({
133
+ addViewportTag: false,
134
+ adaptIframeHeight: true,
135
+ enableScrollIntoView: true
136
+ })
137
+ .withConf({
138
+ lang: 'en',
139
+ theme: options.theme,
140
+ customizationName: options.customizationName
141
+ })
142
+ .on('idCheck.onError', (error) => {
143
+ log('onError', error)
144
+ sendMessageToParent('SUMSUB_ERROR', { error: error.message || 'Unknown error' })
145
+ })
146
+ .on('idCheck.onResize', (payload) => {
147
+ log('onResize', payload)
148
+ sendMessageToParent('SUMSUB_ON_RESIZE', { height: payload.height })
149
+ })
150
+ .on('idCheck.onInitialized', () => {
151
+ sendMessageToParent('SUMSUB_SDK_ON_INIT')
152
+ })
153
+ .build()
154
+
155
+ // Launch SDK
156
+ snsWebSdkInstance.launch('#sumsub-websdk-container')
157
+
158
+ showSumsubContainer()
159
+ sendMessageToParent('SUMSUB_SDK_ON_BUILD')
160
+ log('Sumsub SDK launched successfully')
161
+ } catch (error) {
162
+ log('Failed to launch Sumsub SDK:', error)
163
+ showError(error.message || 'Failed to initialize KYC verification')
164
+ sendMessageToParent('SUMSUB_INIT_ERROR', { error: error.message })
165
+ }
166
+ }
167
+
168
+ // ========================================
169
+ // Message Handler
170
+ // ========================================
171
+
172
+ function handleMessage(event) {
173
+ // Store parent origin on first valid message
174
+ if (!parentOrigin && event.origin && event.source === window.parent) {
175
+ parentOrigin = event.origin
176
+ log('Parent origin set to:', parentOrigin)
177
+ }
178
+
179
+ const message = event.data
180
+
181
+ // Validate message structure
182
+ if (!message || typeof message !== 'object' || !message.type) {
183
+ return
184
+ }
185
+
186
+ log('Received message:', message)
187
+
188
+ switch (message.type) {
189
+ case 'SUMSUB_INIT':
190
+ // Initialize Sumsub SDK with access token
191
+ if (!message.data?.accessToken) {
192
+ showError('No access token provided')
193
+ sendMessageToParent('SUMSUB_INIT_ERROR', { error: 'No access token provided' })
194
+ return
195
+ }
196
+
197
+ hideLoading()
198
+ launchSumsubSdk({
199
+ accessToken: message.data.accessToken,
200
+ theme: message.data.theme,
201
+ customizationName: message.data.customizationName
202
+ })
203
+ break
204
+
205
+ default:
206
+ log('Unknown message type:', message.type)
207
+ }
208
+ }
209
+
210
+ // ========================================
211
+ // Initialization
212
+ // ========================================
213
+
214
+ window.addEventListener('message', handleMessage)
215
+
216
+ // Notify parent that iframe is ready
217
+ window.addEventListener('load', () => {
218
+ log('Iframe loaded, notifying parent')
219
+
220
+ // Send ready signal to parent with wildcard (parent will send origin back)
221
+ window.parent.postMessage(
222
+ {
223
+ type: 'SUMSUB_IFRAME_LOADED'
224
+ },
225
+ '*'
226
+ )
227
+ })
228
+
229
+ // Cleanup on unload
230
+ window.addEventListener('beforeunload', () => {
231
+ if (snsWebSdkInstance && typeof snsWebSdkInstance.destroy === 'function') {
232
+ snsWebSdkInstance.destroy()
233
+ }
234
+ })
235
+
236
+ log('Sumsub KYC iframe script initialized')
237
+ })()
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg id="CIRCLE_OUTLINE_BLACK" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><circle cx="256" cy="256" r="256" fill="#060117" stroke-width="0"/><path d="M264.13948,48.01032l63.62778,132.2788,133.95322,68.65102h-147.34854s-48.55804-10.04649-50.23246-56.93012,0-143.99971,0-143.99971Z" fill="#fefdff" stroke-width="0"/><path d="M50.27932,245.59045l132.27894-63.62734L251.20943,48.01032l-.00012,147.34824s-10.04654,48.55792-56.93019,50.23222c-46.88366,1.6743-143.9998-.00033-143.9998-.00033Z" fill="#fefdff" stroke-width="0"/><path d="M247.86056,463.98968l-63.62772-132.27875-133.95315-68.65092,147.34848-.00011s48.55802,10.04646,50.23242,56.93008c1.6744,46.88362-.00004,143.9997-.00004,143.9997Z" fill="#fefdff" stroke-width="0"/><path d="M461.72068,266.40941l-132.2789,63.62744-68.65118,133.95283.00016-147.34823s10.04655-48.55792,56.93018-50.23226c46.88364-1.67434,143.99974.00023,143.99974.00023Z" fill="#fefdff" stroke-width="0"/></svg>