@lukso/up-connector 0.4.0-dev.a8c9315

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 (109) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +280 -0
  3. package/dist/account-modal.cjs +9 -0
  4. package/dist/account-modal.cjs.map +1 -0
  5. package/dist/account-modal.d.cts +16 -0
  6. package/dist/account-modal.d.ts +16 -0
  7. package/dist/account-modal.js +9 -0
  8. package/dist/account-modal.js.map +1 -0
  9. package/dist/auto-setup.cjs +17 -0
  10. package/dist/auto-setup.cjs.map +1 -0
  11. package/dist/auto-setup.d.cts +123 -0
  12. package/dist/auto-setup.d.ts +123 -0
  13. package/dist/auto-setup.js +17 -0
  14. package/dist/auto-setup.js.map +1 -0
  15. package/dist/avatar-CmUCtW_w.d.cts +205 -0
  16. package/dist/avatar-CmUCtW_w.d.ts +205 -0
  17. package/dist/avatar.cjs +12 -0
  18. package/dist/avatar.cjs.map +1 -0
  19. package/dist/avatar.d.cts +1 -0
  20. package/dist/avatar.d.ts +1 -0
  21. package/dist/avatar.js +12 -0
  22. package/dist/avatar.js.map +1 -0
  23. package/dist/backup-modal.cjs +9 -0
  24. package/dist/backup-modal.cjs.map +1 -0
  25. package/dist/backup-modal.d.cts +41 -0
  26. package/dist/backup-modal.d.ts +41 -0
  27. package/dist/backup-modal.js +9 -0
  28. package/dist/backup-modal.js.map +1 -0
  29. package/dist/chunk-3SGSPHOZ.js +595 -0
  30. package/dist/chunk-3SGSPHOZ.js.map +1 -0
  31. package/dist/chunk-6AYZOIFY.js +181 -0
  32. package/dist/chunk-6AYZOIFY.js.map +1 -0
  33. package/dist/chunk-6N35TCFT.js +852 -0
  34. package/dist/chunk-6N35TCFT.js.map +1 -0
  35. package/dist/chunk-7ETKG6KR.cjs +387 -0
  36. package/dist/chunk-7ETKG6KR.cjs.map +1 -0
  37. package/dist/chunk-EUXUH3YW.js +15 -0
  38. package/dist/chunk-EUXUH3YW.js.map +1 -0
  39. package/dist/chunk-GFVUWAG4.cjs +158 -0
  40. package/dist/chunk-GFVUWAG4.cjs.map +1 -0
  41. package/dist/chunk-IAKQFHFD.cjs +595 -0
  42. package/dist/chunk-IAKQFHFD.cjs.map +1 -0
  43. package/dist/chunk-MH7MP7XK.cjs +181 -0
  44. package/dist/chunk-MH7MP7XK.cjs.map +1 -0
  45. package/dist/chunk-NWCNJSG3.js +387 -0
  46. package/dist/chunk-NWCNJSG3.js.map +1 -0
  47. package/dist/chunk-NXU2DQAV.js +1128 -0
  48. package/dist/chunk-NXU2DQAV.js.map +1 -0
  49. package/dist/chunk-ORJK2YGG.cjs +852 -0
  50. package/dist/chunk-ORJK2YGG.cjs.map +1 -0
  51. package/dist/chunk-RFA6SEIS.cjs +1128 -0
  52. package/dist/chunk-RFA6SEIS.cjs.map +1 -0
  53. package/dist/chunk-XGIT7YUY.js +31 -0
  54. package/dist/chunk-XGIT7YUY.js.map +1 -0
  55. package/dist/chunk-XOKG3KIL.cjs +31 -0
  56. package/dist/chunk-XOKG3KIL.cjs.map +1 -0
  57. package/dist/chunk-YIWSPI4I.js +158 -0
  58. package/dist/chunk-YIWSPI4I.js.map +1 -0
  59. package/dist/chunk-ZBDE64SD.cjs +15 -0
  60. package/dist/chunk-ZBDE64SD.cjs.map +1 -0
  61. package/dist/connect-modal/index.cjs +20 -0
  62. package/dist/connect-modal/index.cjs.map +1 -0
  63. package/dist/connect-modal/index.d.cts +9 -0
  64. package/dist/connect-modal/index.d.ts +9 -0
  65. package/dist/connect-modal/index.js +20 -0
  66. package/dist/connect-modal/index.js.map +1 -0
  67. package/dist/index-D2orHGFi.d.cts +8 -0
  68. package/dist/index-D2orHGFi.d.ts +8 -0
  69. package/dist/index.cjs +793 -0
  70. package/dist/index.cjs.map +1 -0
  71. package/dist/index.d.cts +189 -0
  72. package/dist/index.d.ts +189 -0
  73. package/dist/index.js +793 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/restore-modal.cjs +9 -0
  76. package/dist/restore-modal.cjs.map +1 -0
  77. package/dist/restore-modal.d.cts +68 -0
  78. package/dist/restore-modal.d.ts +68 -0
  79. package/dist/restore-modal.js +9 -0
  80. package/dist/restore-modal.js.map +1 -0
  81. package/dist/wagmi-CVuDs_0h.d.cts +386 -0
  82. package/dist/wagmi-CVuDs_0h.d.ts +386 -0
  83. package/package.json +158 -0
  84. package/src/account-modal.ts +142 -0
  85. package/src/auto-setup.ts +362 -0
  86. package/src/avatar.ts +1135 -0
  87. package/src/backup-modal.ts +439 -0
  88. package/src/connect-modal/components/connection-view.ts +398 -0
  89. package/src/connect-modal/components/eoa-connection-view.ts +408 -0
  90. package/src/connect-modal/components/qr-code-view.ts +71 -0
  91. package/src/connect-modal/connect-modal.base.ts +18 -0
  92. package/src/connect-modal/connect-modal.config.ts +27 -0
  93. package/src/connect-modal/connect-modal.templates.ts +21 -0
  94. package/src/connect-modal/connect-modal.ts +270 -0
  95. package/src/connect-modal/connect-modal.types.ts +104 -0
  96. package/src/connect-modal/images/up-cube-glass.png +0 -0
  97. package/src/connect-modal/index.ts +23 -0
  98. package/src/connect-modal/services/wagmi.ts +266 -0
  99. package/src/connect-modal/styles/styles.css +1 -0
  100. package/src/connect-modal/utils/walletConnectDeepLinkUrl.ts +43 -0
  101. package/src/connector.ts +544 -0
  102. package/src/index.ts +62 -0
  103. package/src/popup-instance.ts +537 -0
  104. package/src/restore-modal.ts +702 -0
  105. package/src/styles/index.ts +28 -0
  106. package/src/styles/styles.css +1 -0
  107. package/src/types/css-raw.d.ts +4 -0
  108. package/src/types/images.d.ts +4 -0
  109. package/src/types.ts +168 -0
@@ -0,0 +1,537 @@
1
+ /**
2
+ * Enhanced Popup System for UP Connector
3
+ * Provides unified interface for both popup windows and modal dialogs
4
+ */
5
+
6
+ export interface PopupRequest {
7
+ mode: 'popup' | 'modal' // popup = window.open, modal = iframe in modal
8
+ url?: string // If present = external, if not = local content
9
+ size?: { width: number; height: number }
10
+ position?: 'center' | 'top-right'
11
+ allowedOrigins?: string[] // Security for message passing
12
+ reuseExisting?: boolean // Whether to reuse existing popups (default: true)
13
+ }
14
+
15
+ export interface PopupInstance {
16
+ // Lifecycle Management
17
+ show(): Promise<void> // Show the popup/modal - async for consistency
18
+ hide(): void // Hide but preserve state
19
+ close(): void // Actually destroy
20
+
21
+ // Message Passing
22
+ postMessage(data: any): void // Send to popup/iframe
23
+ onMessage(handler: (data: any) => void): void // Receive from popup/iframe
24
+ removeMessageHandler(handler: (data: any) => void): void // Remove handler
25
+
26
+ // State Queries
27
+ isVisible: boolean // Whether currently visible
28
+ isClosed: boolean // Whether destroyed
29
+ contentWindow?: Window // For advanced use
30
+
31
+ // Events
32
+ on(
33
+ event: 'show' | 'hide' | 'close' | 'message',
34
+ handler: (...args: any[]) => void
35
+ ): void
36
+ off(
37
+ event: 'show' | 'hide' | 'close' | 'message',
38
+ handler: (...args: any[]) => void
39
+ ): void
40
+ }
41
+
42
+ export interface UIDelegate {
43
+ createPopup(request: PopupRequest): PopupInstance
44
+ showPopup(request: PopupRequest): Promise<PopupInstance>
45
+ closeAll(): void
46
+ }
47
+
48
+ // Internal event emitter for popup instances
49
+ class PopupEventEmitter {
50
+ private handlers = new Map<string, Set<(...args: any[]) => void>>()
51
+
52
+ on(event: string, handler: (...args: any[]) => void): void {
53
+ if (!this.handlers.has(event)) {
54
+ this.handlers.set(event, new Set())
55
+ }
56
+ this.handlers.get(event)!.add(handler)
57
+ }
58
+
59
+ off(event: string, handler: (...args: any[]) => void): void {
60
+ this.handlers.get(event)?.delete(handler)
61
+ }
62
+
63
+ emit(event: string, ...args: any[]): void {
64
+ this.handlers.get(event)?.forEach((handler) => {
65
+ try {
66
+ handler(...args)
67
+ } catch (error) {
68
+ console.error('Error in popup event handler:', error)
69
+ }
70
+ })
71
+ }
72
+
73
+ clear(): void {
74
+ this.handlers.clear()
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Base class for popup instances
80
+ */
81
+ abstract class BasePopupInstance implements PopupInstance {
82
+ protected events = new PopupEventEmitter()
83
+ protected messageHandlers = new Set<(data: any) => void>()
84
+ protected _isClosed = false
85
+ protected _isVisible = false
86
+
87
+ constructor(protected request: PopupRequest) {}
88
+
89
+ abstract show(): Promise<void>
90
+ abstract hide(): void
91
+ abstract close(): void
92
+ abstract get contentWindow(): Window | undefined
93
+
94
+ get isVisible(): boolean {
95
+ return this._isVisible && !this._isClosed
96
+ }
97
+ get isClosed(): boolean {
98
+ return this._isClosed
99
+ }
100
+
101
+ postMessage(data: any): void {
102
+ if (!this._isClosed && this.contentWindow) {
103
+ try {
104
+ this.contentWindow.postMessage(data, '*')
105
+ } catch (error) {
106
+ console.error('Failed to post message to popup:', error)
107
+ }
108
+ }
109
+ }
110
+
111
+ onMessage(handler: (data: any) => void): void {
112
+ this.messageHandlers.add(handler)
113
+ }
114
+
115
+ removeMessageHandler(handler: (data: any) => void): void {
116
+ this.messageHandlers.delete(handler)
117
+ }
118
+
119
+ protected handleMessage(data: any): void {
120
+ this.messageHandlers.forEach((handler) => {
121
+ try {
122
+ handler(data)
123
+ } catch (error) {
124
+ console.error('Error in popup message handler:', error)
125
+ }
126
+ })
127
+ this.events.emit('message', data)
128
+ }
129
+
130
+ on(
131
+ event: 'show' | 'hide' | 'close' | 'message',
132
+ handler: (...args: any[]) => void
133
+ ): void {
134
+ this.events.on(event, handler)
135
+ }
136
+
137
+ off(
138
+ event: 'show' | 'hide' | 'close' | 'message',
139
+ handler: (...args: any[]) => void
140
+ ): void {
141
+ this.events.off(event, handler)
142
+ }
143
+
144
+ protected cleanup(): void {
145
+ this.messageHandlers.clear()
146
+ this.events.clear()
147
+ }
148
+ }
149
+
150
+ /**
151
+ * Modal popup implementation (iframe in modal dialog)
152
+ */
153
+ export class ModalPopupInstance extends BasePopupInstance {
154
+ private modalElement?: HTMLDivElement
155
+ private iframeElement?: HTMLIFrameElement
156
+ private messageListener?: (event: MessageEvent) => void
157
+
158
+ async show(): Promise<void> {
159
+ if (this._isClosed) {
160
+ throw new Error('Popup is closed')
161
+ }
162
+
163
+ if (!this.modalElement) {
164
+ await this.createElement()
165
+ }
166
+
167
+ return new Promise((resolve) => {
168
+ if (!this.modalElement) {
169
+ resolve()
170
+ return
171
+ }
172
+
173
+ // Add to DOM if not already present
174
+ if (!this.modalElement.parentNode) {
175
+ document.body.appendChild(this.modalElement)
176
+ }
177
+
178
+ this._isVisible = true
179
+
180
+ // Force reflow before adding visible class
181
+ this.modalElement.offsetHeight
182
+ this.modalElement.classList.add('visible')
183
+
184
+ this.events.emit('show')
185
+
186
+ // Wait for animation
187
+ setTimeout(() => resolve(), 50)
188
+ })
189
+ }
190
+
191
+ hide(): void {
192
+ if (!this._isVisible || this._isClosed || !this.modalElement) return
193
+
194
+ this._isVisible = false
195
+ this.modalElement.classList.remove('visible')
196
+ this.events.emit('hide')
197
+
198
+ // Remove from DOM after animation
199
+ setTimeout(() => {
200
+ if (this.modalElement && this.modalElement.parentNode) {
201
+ this.modalElement.parentNode.removeChild(this.modalElement)
202
+ }
203
+ }, 300)
204
+ }
205
+
206
+ close(): void {
207
+ if (this._isClosed) return
208
+
209
+ this._isClosed = true
210
+ this._isVisible = false
211
+
212
+ if (this.modalElement) {
213
+ this.modalElement.classList.remove('visible')
214
+ setTimeout(() => {
215
+ if (this.modalElement && this.modalElement.parentNode) {
216
+ this.modalElement.parentNode.removeChild(this.modalElement)
217
+ }
218
+ }, 300)
219
+ }
220
+
221
+ if (this.messageListener) {
222
+ window.removeEventListener('message', this.messageListener)
223
+ }
224
+
225
+ this.events.emit('close')
226
+ this.cleanup()
227
+ }
228
+
229
+ get contentWindow(): Window | undefined {
230
+ return this.iframeElement?.contentWindow || undefined
231
+ }
232
+
233
+ private async createElement(): Promise<void> {
234
+ if (typeof document === 'undefined') return
235
+
236
+ await this.createStyles()
237
+
238
+ // Create modal structure
239
+ this.modalElement = document.createElement('div')
240
+ this.modalElement.className = 'up-popup-modal'
241
+
242
+ const { width = 480, height = 640 } = this.request.size || {}
243
+
244
+ this.modalElement.innerHTML = `
245
+ <div class="up-popup-modal-content" style="width: ${width}px; height: ${height}px;">
246
+ <button class="up-popup-close" type="button">
247
+ <svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor">
248
+ <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />
249
+ </svg>
250
+ </button>
251
+ <iframe src="${this.request.url || 'about:blank'}" allow="publickey-credentials-get; publickey-credentials-create"></iframe>
252
+ </div>
253
+ `
254
+
255
+ // Get references
256
+ const closeButton = this.modalElement.querySelector(
257
+ '.up-popup-close'
258
+ ) as HTMLButtonElement
259
+ this.iframeElement = this.modalElement.querySelector(
260
+ 'iframe'
261
+ ) as HTMLIFrameElement
262
+
263
+ // Event listeners
264
+ closeButton.addEventListener('click', () => this.hide())
265
+
266
+ this.modalElement.addEventListener('click', (e) => {
267
+ if (e.target === this.modalElement) {
268
+ this.hide()
269
+ }
270
+ })
271
+
272
+ // Message handling
273
+ this.messageListener = (event: MessageEvent) => {
274
+ // Only handle messages from our iframe
275
+ if (event.source === this.iframeElement?.contentWindow) {
276
+ this.handleMessage(event.data)
277
+ }
278
+ }
279
+ window.addEventListener('message', this.messageListener)
280
+ }
281
+
282
+ private async createStyles(): Promise<void> {
283
+ if (typeof document === 'undefined') return
284
+
285
+ if (document.querySelector('#up-popup-modal-styles')) return
286
+
287
+ const style = document.createElement('style')
288
+ style.id = 'up-popup-modal-styles'
289
+ style.textContent = `
290
+ .up-popup-modal {
291
+ position: fixed;
292
+ top: 0;
293
+ left: 0;
294
+ width: 100vw;
295
+ height: 100vh;
296
+ background: rgba(0, 0, 0, 0.5);
297
+ backdrop-filter: blur(8px);
298
+ z-index: 10000;
299
+ display: flex;
300
+ align-items: center;
301
+ justify-content: center;
302
+ opacity: 0;
303
+ visibility: hidden;
304
+ transition: all 300ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
305
+ padding: 16px;
306
+ }
307
+
308
+ .up-popup-modal.visible {
309
+ opacity: 1;
310
+ visibility: visible;
311
+ }
312
+
313
+ .up-popup-modal-content {
314
+ background: white;
315
+ border-radius: 12px;
316
+ overflow: hidden;
317
+ position: relative;
318
+ box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
319
+ transform: scale(0.95) translateY(20px);
320
+ transition: all 300ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
321
+ }
322
+
323
+ .up-popup-modal.visible .up-popup-modal-content {
324
+ transform: scale(1) translateY(0);
325
+ }
326
+
327
+ .up-popup-close {
328
+ position: absolute;
329
+ top: 12px;
330
+ right: 12px;
331
+ z-index: 10;
332
+ background: rgba(255, 255, 255, 0.9);
333
+ border: none;
334
+ border-radius: 50%;
335
+ width: 32px;
336
+ height: 32px;
337
+ cursor: pointer;
338
+ display: flex;
339
+ align-items: center;
340
+ justify-content: center;
341
+ color: #6b7280;
342
+ transition: all 0.2s ease;
343
+ }
344
+
345
+ .up-popup-close:hover {
346
+ background: rgba(255, 255, 255, 1);
347
+ color: #374151;
348
+ }
349
+
350
+ .up-popup-modal iframe {
351
+ width: 100%;
352
+ height: 100%;
353
+ border: none;
354
+ border-radius: 12px;
355
+ }
356
+
357
+ @media (max-width: 640px) {
358
+ .up-popup-modal {
359
+ padding: 0;
360
+ align-items: flex-end;
361
+ }
362
+
363
+ .up-popup-modal-content {
364
+ width: 100% !important;
365
+ height: 85vh !important;
366
+ border-radius: 12px 12px 0 0;
367
+ transform: translateY(100%);
368
+ }
369
+
370
+ .up-popup-modal.visible .up-popup-modal-content {
371
+ transform: translateY(0);
372
+ }
373
+
374
+ .up-popup-modal iframe {
375
+ border-radius: 12px 12px 0 0;
376
+ }
377
+ }
378
+
379
+ @media (max-width: 480px) {
380
+ .up-popup-modal {
381
+ align-items: stretch;
382
+ }
383
+
384
+ .up-popup-modal-content {
385
+ height: 100vh !important;
386
+ border-radius: 0;
387
+ }
388
+
389
+ .up-popup-modal iframe {
390
+ border-radius: 0;
391
+ }
392
+ }
393
+ `
394
+ document.head.appendChild(style)
395
+ }
396
+ }
397
+
398
+ /**
399
+ * Window popup implementation (actual popup window)
400
+ */
401
+ export class WindowPopupInstance extends BasePopupInstance {
402
+ private popupWindow: Window | null = null
403
+ private messageListener?: (event: MessageEvent) => void
404
+
405
+ async show(): Promise<void> {
406
+ if (this._isClosed) {
407
+ throw new Error('Popup is closed')
408
+ }
409
+
410
+ if (!this.popupWindow || this.popupWindow.closed) {
411
+ await this.createPopupWindow()
412
+ }
413
+
414
+ if (this.popupWindow && !this.popupWindow.closed) {
415
+ this.popupWindow.focus()
416
+ this._isVisible = true
417
+ this.events.emit('show')
418
+ }
419
+ }
420
+
421
+ hide(): void {
422
+ // For popup windows, hide typically means minimize or move to background
423
+ // Since we can't directly minimize, we just blur it
424
+ if (this.popupWindow && !this.popupWindow.closed) {
425
+ this.popupWindow.blur()
426
+ }
427
+ this._isVisible = false
428
+ this.events.emit('hide')
429
+ }
430
+
431
+ close(): void {
432
+ if (this._isClosed) return
433
+
434
+ this._isClosed = true
435
+ this._isVisible = false
436
+
437
+ if (this.popupWindow && !this.popupWindow.closed) {
438
+ this.popupWindow.close()
439
+ }
440
+ this.popupWindow = null
441
+
442
+ if (this.messageListener) {
443
+ window.removeEventListener('message', this.messageListener)
444
+ }
445
+
446
+ this.events.emit('close')
447
+ this.cleanup()
448
+ }
449
+
450
+ get contentWindow(): Window | undefined {
451
+ return this.popupWindow && !this.popupWindow.closed
452
+ ? this.popupWindow
453
+ : undefined
454
+ }
455
+
456
+ get isVisible(): boolean {
457
+ return !this._isClosed && !!(this.popupWindow && !this.popupWindow.closed)
458
+ }
459
+
460
+ private async createPopupWindow(): Promise<void> {
461
+ if (!this.request.url) {
462
+ throw new Error('URL required for popup windows')
463
+ }
464
+
465
+ const { width = 400, height = 600 } = this.request.size || {}
466
+ const position = this.request.position || 'center'
467
+ const features = [
468
+ `width=${width}`,
469
+ `height=${height}`,
470
+ ...this.getPositionFeatures(position, width, height),
471
+ 'scrollbars=yes',
472
+ 'resizable=yes',
473
+ 'status=no',
474
+ 'location=no',
475
+ 'toolbar=no',
476
+ 'menubar=no',
477
+ ].join(',')
478
+
479
+ this.popupWindow = window.open(this.request.url, '_blank', features)
480
+
481
+ if (!this.popupWindow) {
482
+ throw new Error('Popup blocked or failed to open')
483
+ }
484
+
485
+ // Setup message listener
486
+ this.messageListener = (event: MessageEvent) => {
487
+ if (event.source === this.popupWindow) {
488
+ this.handleMessage(event.data)
489
+ }
490
+ }
491
+ window.addEventListener('message', this.messageListener)
492
+
493
+ // Monitor popup close
494
+ const checkClosed = () => {
495
+ if (this.popupWindow?.closed && !this._isClosed) {
496
+ this.close()
497
+ } else if (!this._isClosed) {
498
+ setTimeout(checkClosed, 1000)
499
+ }
500
+ }
501
+ setTimeout(checkClosed, 1000)
502
+ }
503
+
504
+ private getPositionFeatures(
505
+ position: string,
506
+ width: number,
507
+ height: number
508
+ ): string[] {
509
+ const screenLeft =
510
+ window.screenLeft !== undefined ? window.screenLeft : window.screenX
511
+ const screenTop =
512
+ window.screenTop !== undefined ? window.screenTop : window.screenY
513
+ const windowWidth =
514
+ window.innerWidth || document.documentElement.clientWidth || screen.width
515
+ const windowHeight =
516
+ window.innerHeight ||
517
+ document.documentElement.clientHeight ||
518
+ screen.height
519
+
520
+ let left: number
521
+ let top: number
522
+
523
+ switch (position) {
524
+ case 'top-right':
525
+ left = screenLeft + windowWidth - width - 20
526
+ top = screenTop + 20
527
+ break
528
+ case 'center':
529
+ default:
530
+ left = screenLeft + (windowWidth - width) / 2
531
+ top = screenTop + (windowHeight - height) / 2
532
+ break
533
+ }
534
+
535
+ return [`left=${Math.max(0, left)}`, `top=${Math.max(0, top)}`]
536
+ }
537
+ }