@lukso/up-connector 0.6.0 → 0.7.0-dev.360c7b1

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 (79) hide show
  1. package/dist/account-modal.cjs +3 -3
  2. package/dist/account-modal.js +2 -2
  3. package/dist/auto-setup.cjs +3 -3
  4. package/dist/auto-setup.js +2 -2
  5. package/dist/{avatar-CmUCtW_w.d.cts → avatar-CQkubMTK.d.cts} +0 -1
  6. package/dist/{avatar-CmUCtW_w.d.ts → avatar-CQkubMTK.d.ts} +0 -1
  7. package/dist/avatar.cjs +2 -2
  8. package/dist/avatar.d.cts +1 -1
  9. package/dist/avatar.d.ts +1 -1
  10. package/dist/avatar.js +1 -1
  11. package/dist/backup-modal.cjs +3 -3
  12. package/dist/backup-modal.js +2 -2
  13. package/dist/{chunk-W7QI6BTA.cjs → chunk-4YK3Q32C.cjs} +3 -3
  14. package/dist/chunk-4YK3Q32C.cjs.map +1 -0
  15. package/dist/{chunk-ORJK2YGG.cjs → chunk-7LQ5EB2X.cjs} +22 -24
  16. package/dist/chunk-7LQ5EB2X.cjs.map +1 -0
  17. package/dist/{chunk-KMCCANMJ.js → chunk-DI4MT7EC.js} +2 -2
  18. package/dist/chunk-DI4MT7EC.js.map +1 -0
  19. package/dist/{chunk-IAKQFHFD.cjs → chunk-E34NRQRA.cjs} +8 -12
  20. package/dist/chunk-E34NRQRA.cjs.map +1 -0
  21. package/dist/{chunk-6N35TCFT.js → chunk-GKAVIDXP.js} +21 -23
  22. package/dist/chunk-GKAVIDXP.js.map +1 -0
  23. package/dist/{chunk-NWCNJSG3.js → chunk-I5I6SZZ5.js} +8 -4
  24. package/dist/chunk-I5I6SZZ5.js.map +1 -0
  25. package/dist/{chunk-YIWSPI4I.js → chunk-LIHQISFN.js} +2 -2
  26. package/dist/{chunk-GFVUWAG4.cjs → chunk-MEEN5QJZ.cjs} +3 -3
  27. package/dist/{chunk-GFVUWAG4.cjs.map → chunk-MEEN5QJZ.cjs.map} +1 -1
  28. package/dist/{chunk-SAQWNAQ6.js → chunk-NIMT2B6H.js} +51 -80
  29. package/dist/{chunk-SAQWNAQ6.js.map → chunk-NIMT2B6H.js.map} +1 -1
  30. package/dist/{chunk-GCYDV7FB.cjs → chunk-QIKRPHWT.cjs} +47 -76
  31. package/dist/chunk-QIKRPHWT.cjs.map +1 -0
  32. package/dist/{chunk-3SGSPHOZ.js → chunk-RCCGJ3DC.js} +7 -11
  33. package/dist/chunk-RCCGJ3DC.js.map +1 -0
  34. package/dist/{chunk-XGIT7YUY.js → chunk-UPWE4L5Z.js} +2 -2
  35. package/dist/{chunk-XGIT7YUY.js.map → chunk-UPWE4L5Z.js.map} +1 -1
  36. package/dist/{chunk-7ETKG6KR.cjs → chunk-UQZN2AKN.cjs} +9 -5
  37. package/dist/chunk-UQZN2AKN.cjs.map +1 -0
  38. package/dist/{chunk-XOKG3KIL.cjs → chunk-ZWXGWUXQ.cjs} +2 -2
  39. package/dist/{chunk-XOKG3KIL.cjs.map → chunk-ZWXGWUXQ.cjs.map} +1 -1
  40. package/dist/connect-modal/index.cjs +2 -2
  41. package/dist/connect-modal/index.d.cts +1 -1
  42. package/dist/connect-modal/index.d.ts +1 -1
  43. package/dist/connect-modal/index.js +1 -1
  44. package/dist/index.cjs +23 -24
  45. package/dist/index.cjs.map +1 -1
  46. package/dist/index.d.cts +5 -5
  47. package/dist/index.d.ts +5 -5
  48. package/dist/index.js +13 -14
  49. package/dist/index.js.map +1 -1
  50. package/dist/restore-modal.cjs +3 -3
  51. package/dist/restore-modal.d.cts +2 -2
  52. package/dist/restore-modal.d.ts +2 -2
  53. package/dist/restore-modal.js +2 -2
  54. package/dist/{wagmi-DgjkdmGk.d.cts → wagmi-84MPgN9w.d.cts} +0 -15
  55. package/dist/{wagmi-DgjkdmGk.d.ts → wagmi-84MPgN9w.d.ts} +0 -15
  56. package/package.json +7 -7
  57. package/src/auto-setup.ts +0 -1
  58. package/src/avatar.ts +20 -23
  59. package/src/backup-modal.ts +6 -2
  60. package/src/connect-modal/components/connection-view.ts +16 -9
  61. package/src/connect-modal/components/eoa-connection-view.ts +9 -5
  62. package/src/connect-modal/components/qr-code-view.ts +4 -4
  63. package/src/connect-modal/connect-modal.templates.ts +7 -6
  64. package/src/connect-modal/connect-modal.ts +17 -60
  65. package/src/connect-modal/styles/styles.css +1 -1
  66. package/src/connector.ts +4 -8
  67. package/src/popup-instance.ts +3 -4
  68. package/src/restore-modal.ts +5 -3
  69. package/src/styles/styles.css +1 -1
  70. package/dist/chunk-3SGSPHOZ.js.map +0 -1
  71. package/dist/chunk-6N35TCFT.js.map +0 -1
  72. package/dist/chunk-7ETKG6KR.cjs.map +0 -1
  73. package/dist/chunk-GCYDV7FB.cjs.map +0 -1
  74. package/dist/chunk-IAKQFHFD.cjs.map +0 -1
  75. package/dist/chunk-KMCCANMJ.js.map +0 -1
  76. package/dist/chunk-NWCNJSG3.js.map +0 -1
  77. package/dist/chunk-ORJK2YGG.cjs.map +0 -1
  78. package/dist/chunk-W7QI6BTA.cjs.map +0 -1
  79. /package/dist/{chunk-YIWSPI4I.js.map → chunk-LIHQISFN.js.map} +0 -0
@@ -4,7 +4,11 @@
4
4
  * Main connection view displaying primary Lukso connectors and option to show EOA connectors.
5
5
  */
6
6
 
7
- import { withDeviceService, withIntlService } from '@lukso/core/mixins'
7
+ import {
8
+ withDeviceService,
9
+ withIntlService,
10
+ withTheme,
11
+ } from '@lukso/core/mixins'
8
12
  import { html, type TemplateResult } from 'lit'
9
13
  import { property } from 'lit/decorators.js'
10
14
 
@@ -25,8 +29,8 @@ import { walletConnectDeepLinkUrl } from '../utils/walletConnectDeepLinkUrl'
25
29
 
26
30
  const logInfo = debug('connect-modal:info')
27
31
 
28
- export class ConnectionView extends withIntlService(
29
- withDeviceService(ConnectModalBase)
32
+ export class ConnectionView extends withTheme(
33
+ withIntlService(withDeviceService(ConnectModalBase))
30
34
  ) {
31
35
  @property({ type: Boolean }) isConnecting = false
32
36
  @property({ type: String }) connectingRdns: string | undefined = undefined
@@ -272,6 +276,7 @@ export class ConnectionView extends withIntlService(
272
276
  return html`
273
277
  <lukso-button
274
278
  variant="secondary"
279
+ .theme=${this.theme}
275
280
  size=${this.device?.isMobile ? 'medium' : 'large'}
276
281
  is-full-width
277
282
  ?disabled=${isDisabled}
@@ -283,7 +288,7 @@ export class ConnectionView extends withIntlService(
283
288
  name=${iconName}
284
289
  size=${this.device?.isMobile ? 'small' : 'medium'}
285
290
  class="mr-2"
286
- secondary-color="neutral-100"
291
+ secondary-color="${this.theme === 'dark' ? 'neutral-20' : 'neutral-100'}"
287
292
  ></lukso-icon>
288
293
  ${label}
289
294
  </lukso-button>
@@ -344,12 +349,12 @@ export class ConnectionView extends withIntlService(
344
349
  private renderDivider(): TemplateResult<1> {
345
350
  return html`
346
351
  <div class="relative w-full my-2">
347
- <div class="paragraph-inter-12-regular relative z-[1] bg-neutral-98 dark:bg-neutral-15 px-4 text-neutral-40 inline-block">
352
+ <div class="paragraph-inter-12-regular relative z-[1] bg-neutral-98 dark:bg-neutral-10 px-4 text-neutral-40 dark:text-neutral-95 inline-block">
348
353
  ${this.formatMessage('connect_modal_or')}
349
354
  </div>
350
- <div class="absolute top-[13px] left-0 right-0 h-px bg-neutral-80 dark:bg-neutral-70" />
355
+ <div class="absolute top-[13px] left-0 right-0 h-px bg-neutral-80 dark:bg-neutral-80" />
351
356
  </div>
352
- <div class="paragraph-inter-16-regular py-4">
357
+ <div class="paragraph-inter-16-regular py-4 text-neutral-20 dark:text-neutral-100">
353
358
  ${this.formatMessage('connect_modal_or_info')}
354
359
  </div>
355
360
  `
@@ -361,13 +366,13 @@ export class ConnectionView extends withIntlService(
361
366
  <button
362
367
  @click=${this.handleClose}
363
368
  >
364
- ${renderCloseButton()}
369
+ ${renderCloseButton(this.theme)}
365
370
  </button>
366
371
  </div>
367
372
  <div class="flex flex-col items-center text-center">
368
373
  ${renderLogo()}
369
374
  ${renderTitle(this.formatMessage('connect_modal_title'))}
370
- <p class="mb-6 paragraph-inter-16-regular">
375
+ <p class="mb-6 paragraph-inter-16-regular text-neutral-20 dark:text-neutral-100">
371
376
  ${this.formatMessage('connect_modal_description')}
372
377
  </p>
373
378
  <div class="${cn('flex w-full gap-2 mb-4', this.device?.isMobile ? 'flex-col-reverse' : 'flex-col')}">
@@ -378,6 +383,7 @@ export class ConnectionView extends withIntlService(
378
383
  variant="secondary"
379
384
  size=${this.device?.isMobile ? 'medium' : 'large'}
380
385
  is-full-width
386
+ .theme=${this.theme}
381
387
  ?disabled=${this.isConnecting}
382
388
  @click=${this.handleShowEoaConnections}
383
389
  >
@@ -385,6 +391,7 @@ export class ConnectionView extends withIntlService(
385
391
  name="wallet-outline"
386
392
  size=${this.device?.isMobile ? 'small' : 'medium'}
387
393
  class="mr-2"
394
+ color="${this.theme === 'dark' ? 'neutral-100' : 'neutral-20'}"
388
395
  ></lukso-icon>
389
396
  ${this.formatMessage('connect_modal_other_connectors')}
390
397
  </lukso-button>
@@ -5,7 +5,11 @@
5
5
  */
6
6
 
7
7
  import { Task } from '@lit/task'
8
- import { withDeviceService, withIntlService } from '@lukso/core/mixins'
8
+ import {
9
+ withDeviceService,
10
+ withIntlService,
11
+ withTheme,
12
+ } from '@lukso/core/mixins'
9
13
  import debug from 'debug'
10
14
  import { html, nothing, type TemplateResult } from 'lit'
11
15
  import { property, state } from 'lit/decorators.js'
@@ -40,8 +44,8 @@ import { getWagmiSetup } from '../services/wagmi'
40
44
 
41
45
  const logInfo = debug('connect-modal:info')
42
46
 
43
- export class EoaConnectionView extends withIntlService(
44
- withDeviceService(ConnectModalBase)
47
+ export class EoaConnectionView extends withTheme(
48
+ withIntlService(withDeviceService(ConnectModalBase))
45
49
  ) {
46
50
  @property({ type: Array }) connectors: WalletConnector[] = []
47
51
 
@@ -382,13 +386,13 @@ export class EoaConnectionView extends withIntlService(
382
386
  <button
383
387
  @click=${this.handleBack}
384
388
  >
385
- ${renderBackButton()}
389
+ ${renderBackButton(this.theme)}
386
390
  </button>
387
391
 
388
392
  <button
389
393
  @click=${this.handleClose}
390
394
  >
391
- ${renderCloseButton()}
395
+ ${renderCloseButton(this.theme)}
392
396
  </button>
393
397
  </div>
394
398
  <div class="flex flex-col items-center text-center">
@@ -10,12 +10,12 @@ import { ConnectModalBase } from '../connect-modal.base'
10
10
 
11
11
  // Import lukso web components
12
12
  import '@lukso/web-components/dist/components/lukso-qr-code'
13
- import { withIntlService } from '@lukso/core/mixins'
13
+ import { withIntlService, withTheme } from '@lukso/core/mixins'
14
14
  import { property } from 'lit/decorators.js'
15
15
  import { renderBackButton, renderCloseButton } from '../connect-modal.templates'
16
16
  import cubeGlassImage from '../images/up-cube-glass.png'
17
17
 
18
- export class QrCodeView extends withIntlService(ConnectModalBase) {
18
+ export class QrCodeView extends withTheme(withIntlService(ConnectModalBase)) {
19
19
  @property({ type: String }) data: string | undefined = undefined
20
20
 
21
21
  /**
@@ -41,13 +41,13 @@ export class QrCodeView extends withIntlService(ConnectModalBase) {
41
41
  <button
42
42
  @click=${this.handleBack}
43
43
  >
44
- ${renderBackButton()}
44
+ ${renderBackButton(this.theme)}
45
45
  </button>
46
46
 
47
47
  <button
48
48
  @click=${this.handleClose}
49
49
  >
50
- ${renderCloseButton()}
50
+ ${renderCloseButton(this.theme)}
51
51
  </button>
52
52
  </div>
53
53
  <div class="flex flex-col items-center text-center">
@@ -1,21 +1,22 @@
1
+ import type { Theme } from '@lukso/core'
1
2
  import { cn } from '@lukso/web-components/tools'
2
3
  import { html } from 'lit'
3
4
  import cubeGlassImage from './images/up-cube-glass.png'
4
5
 
5
- export const renderCloseButton = () =>
6
+ export const renderCloseButton = (theme: Theme) =>
6
7
  html`<lukso-icon name="close-lg"
7
- class="cursor-pointer transition-opacity hover:opacity-60"></lukso-icon>`
8
+ class="cursor-pointer transition-opacity hover:opacity-60" color="${theme === 'dark' ? 'neutral-100' : 'neutral-20'}"></lukso-icon>`
8
9
 
9
- export const renderBackButton = () =>
10
- html`<lukso-icon name="arrow-left-lg" class="cursor-pointer transition-opacity hover:opacity-60"></lukso-icon>`
10
+ export const renderBackButton = (theme: Theme) =>
11
+ html`<lukso-icon name="arrow-left-lg" class="cursor-pointer transition-opacity hover:opacity-60" color="${theme === 'dark' ? 'neutral-100' : 'neutral-20'}"></lukso-icon>`
11
12
 
12
13
  export const renderLogo = () =>
13
14
  html`<img src="${cubeGlassImage}" alt="" class="mb-5 w-14 animate-bounce2" />`
14
15
 
15
16
  export const renderTitle = (title: string) =>
16
- html`<h2 class="m-0 mb-4 text-neutral-20 dark:text-white heading-inter-21-semi-bold">
17
+ html`<h2 class="m-0 mb-4 text-neutral-20 dark:text-neutral-100 heading-inter-21-semi-bold">
17
18
  ${title}
18
19
  </h2>`
19
20
 
20
21
  export const renderPlaceholder = (style: string) =>
21
- html`<div class="${cn('bg-neutral-90 dark:bg-neutral-80 rounded-4 animate-pulse', style)}"></div>`
22
+ html`<div class="${cn('bg-neutral-90 dark:bg-neutral-20 rounded-4 animate-pulse', style)}"></div>`
@@ -4,7 +4,7 @@
4
4
  * Framework-agnostic connection modal for wallet/profile connections.
5
5
  */
6
6
 
7
- import { withDeviceService } from '@lukso/core/mixins'
7
+ import { withDeviceService, withTheme } from '@lukso/core/mixins'
8
8
  import debug from 'debug'
9
9
  import { html, type TemplateResult } from 'lit'
10
10
  import { property, state } from 'lit/decorators.js'
@@ -12,7 +12,6 @@ import { property, state } from 'lit/decorators.js'
12
12
  import { ConnectModalBase } from './connect-modal.base.js'
13
13
  import type {
14
14
  ConnectionModalView,
15
- ConnectModalTheme,
16
15
  WalletConnector,
17
16
  } from './connect-modal.types'
18
17
  import { fromWagmiConnectors, getWagmiSetup } from './services/wagmi'
@@ -24,64 +23,26 @@ import './components/qr-code-view'
24
23
 
25
24
  const logInfo = debug('connect-modal:info')
26
25
 
27
- export class ConnectModal extends withDeviceService(ConnectModalBase) {
26
+ export class ConnectModal extends withTheme(
27
+ withDeviceService(ConnectModalBase)
28
+ ) {
28
29
  // Public properties
29
30
  @property({ type: Boolean, reflect: true }) open = false
30
- @property({ type: String, reflect: true }) theme: ConnectModalTheme = 'light'
31
31
 
32
32
  // Private state
33
33
  @state() private connectors: WalletConnector[] = []
34
- @state() private isDark = false
34
+ // isDark state is provided by withTheme mixin
35
35
  @state() private modalView: ConnectionModalView = 'up_connection'
36
36
  @state() private qrCodeData: string | undefined = undefined
37
37
 
38
- private mediaQueryList: MediaQueryList | null = null
39
-
40
38
  updated(changedProperties: Map<string, any>): void {
39
+ super.updated(changedProperties)
40
+
41
41
  // Reset view and load connectors when modal opens
42
42
  if (changedProperties.has('open') && this.open) {
43
43
  this.modalView = 'up_connection' // Reset to main view when modal opens
44
44
  this.loadConnectors()
45
45
  }
46
-
47
- // Handle theme changes
48
- if (changedProperties.has('theme')) {
49
- this.updateTheme()
50
- }
51
- }
52
-
53
- connectedCallback(): void {
54
- super.connectedCallback()
55
- this.updateTheme()
56
-
57
- // Listen for system theme changes when in 'auto' mode
58
- if (this.theme === 'auto') {
59
- this.mediaQueryList = window.matchMedia('(prefers-color-scheme: dark)')
60
- this.mediaQueryList.addEventListener(
61
- 'change',
62
- this.handleMediaQueryChange
63
- )
64
- }
65
- }
66
-
67
- disconnectedCallback(): void {
68
- super.disconnectedCallback()
69
-
70
- if (this.mediaQueryList) {
71
- this.mediaQueryList.removeEventListener(
72
- 'change',
73
- this.handleMediaQueryChange
74
- )
75
- }
76
- }
77
-
78
- /**
79
- * Handle system theme changes
80
- *
81
- * @param event
82
- */
83
- private handleMediaQueryChange = (event: MediaQueryListEvent): void => {
84
- this.isDark = event.matches
85
46
  }
86
47
 
87
48
  /**
@@ -95,17 +56,6 @@ export class ConnectModal extends withDeviceService(ConnectModalBase) {
95
56
  )
96
57
  }
97
58
 
98
- /**
99
- * Update isDark state based on theme property
100
- */
101
- private updateTheme(): void {
102
- if (this.theme === 'auto') {
103
- this.isDark = window.matchMedia('(prefers-color-scheme: dark)').matches
104
- } else {
105
- this.isDark = this.theme === 'dark'
106
- }
107
- }
108
-
109
59
  private async loadConnectors(): Promise<void> {
110
60
  const globalWagmiSetup = getWagmiSetup()
111
61
  logInfo('Global wagmi setup:', globalWagmiSetup)
@@ -217,12 +167,17 @@ export class ConnectModal extends withDeviceService(ConnectModalBase) {
217
167
  private renderModalContent(): TemplateResult<1> {
218
168
  switch (this.modalView) {
219
169
  case 'qr_code':
220
- return html`<qr-code-view .data=${this.qrCodeData} @on-back=${this.handleBackToConnectionView}
221
- @on-close=${this.handleClose}></qr-code-view>`
170
+ return html`<qr-code-view
171
+ .data=${this.qrCodeData}
172
+ .theme=${this.theme}
173
+ @on-back=${this.handleBackToConnectionView}
174
+ @on-close=${this.handleClose}
175
+ ></qr-code-view>`
222
176
  case 'eoa_connection':
223
177
  return html`
224
178
  <eoa-connection-view
225
179
  .connectors=${this.connectors}
180
+ .theme=${this.theme}
226
181
  @on-back=${this.handleBackToConnectionView}
227
182
  @on-close=${this.handleClose}
228
183
  @on-connect=${this.handleOnConnectSuccess}
@@ -233,6 +188,7 @@ export class ConnectModal extends withDeviceService(ConnectModalBase) {
233
188
  return html`
234
189
  <connection-view
235
190
  .connectors=${this.connectors}
191
+ .theme=${this.theme}
236
192
  @on-back=${this.handleBackToConnectionView}
237
193
  @on-close=${this.handleClose}
238
194
  @on-connect=${this.handleOnConnectSuccess}
@@ -250,9 +206,10 @@ export class ConnectModal extends withDeviceService(ConnectModalBase) {
250
206
  ?is-open=${this.open}
251
207
  ?has-bottom-padding=${!!(this.device?.isIOS && this.device?.isSafari)}
252
208
  size="auto"
209
+ .theme=${this.theme}
253
210
  @on-backdrop-click=${this.handleClose}
254
211
  >
255
- <div class="p-6 ${this.isDark ? 'dark' : ''} w-full sm:w-[372px] text-neutral-20">
212
+ <div class="p-6 w-full sm:w-[372px]">
256
213
  ${this.renderModalContent()}
257
214
  </div>
258
215
  </lukso-modal>
@@ -1 +1 @@
1
- @import "@lukso/web-components/dist/styles/main.css";
1
+ @import "@lukso/web-components/tools/styles/main.css";
package/src/connector.ts CHANGED
@@ -31,11 +31,7 @@ import {
31
31
  getConnection,
32
32
  watchConnection,
33
33
  } from './connect-modal/index.js'
34
- import type {
35
- ConnectionState,
36
- ConnectorConfig,
37
- WalletProvider,
38
- } from './types.js'
34
+ import type { ConnectionState, ConnectorConfig } from './types.js'
39
35
 
40
36
  const DEFAULT_CONFIG: Required<
41
37
  Omit<ConnectorConfig, 'avatar' | 'modal' | 'onConnectionChange'>
@@ -52,12 +48,12 @@ export class UPConnector {
52
48
  private avatar?: DraggableAvatar
53
49
  private connectModal?: ConnectModal
54
50
  private accountModal?: AccountModal
55
- private connectors: WalletConnector[] = []
56
51
  private connectionState: ConnectionState = 'disconnected'
57
52
  private connectedAddress?: string
58
53
  private connectedProvider?: any
59
54
  private connectedChainId?: number
60
55
  private wagmiUnsubscribe?: (() => void) | null
56
+ connectors: WalletConnector[] = []
61
57
 
62
58
  constructor(config: ConnectorConfig = {}) {
63
59
  this.config = { ...DEFAULT_CONFIG, ...config }
@@ -194,7 +190,7 @@ export class UPConnector {
194
190
  // TODO: Replace with Lit-based account management modal
195
191
  // Legacy createModal() method removed - was using deprecated ConnectorModal
196
192
 
197
- private handleAvatarClick(event: MouseEvent): void {
193
+ private handleAvatarClick(_event: MouseEvent): void {
198
194
  if (this.connectionState === 'connected') {
199
195
  // Show account management modal
200
196
  this.showAccountModal()
@@ -221,7 +217,7 @@ export class UPConnector {
221
217
 
222
218
  // Handle connect event
223
219
  this.connectModal.addEventListener('connect', ((e: CustomEvent) => {
224
- const connector = e.detail.connector as WalletConnector
220
+ const _connector = e.detail.connector as WalletConnector
225
221
  // TODO: Handle actual connection logic
226
222
  // For now, this will be extended when wagmi/viem integration is added
227
223
  }) as EventListener)
@@ -53,7 +53,7 @@ class PopupEventEmitter {
53
53
  if (!this.handlers.has(event)) {
54
54
  this.handlers.set(event, new Set())
55
55
  }
56
- this.handlers.get(event)!.add(handler)
56
+ this.handlers.get(event)?.add(handler)
57
57
  }
58
58
 
59
59
  off(event: string, handler: (...args: any[]) => void): void {
@@ -197,7 +197,7 @@ export class ModalPopupInstance extends BasePopupInstance {
197
197
 
198
198
  // Remove from DOM after animation
199
199
  setTimeout(() => {
200
- if (this.modalElement && this.modalElement.parentNode) {
200
+ if (this.modalElement?.parentNode) {
201
201
  this.modalElement.parentNode.removeChild(this.modalElement)
202
202
  }
203
203
  }, 300)
@@ -212,7 +212,7 @@ export class ModalPopupInstance extends BasePopupInstance {
212
212
  if (this.modalElement) {
213
213
  this.modalElement.classList.remove('visible')
214
214
  setTimeout(() => {
215
- if (this.modalElement && this.modalElement.parentNode) {
215
+ if (this.modalElement?.parentNode) {
216
216
  this.modalElement.parentNode.removeChild(this.modalElement)
217
217
  }
218
218
  }, 300)
@@ -525,7 +525,6 @@ export class WindowPopupInstance extends BasePopupInstance {
525
525
  left = screenLeft + windowWidth - width - 20
526
526
  top = screenTop + 20
527
527
  break
528
- case 'center':
529
528
  default:
530
529
  left = screenLeft + (windowWidth - width) / 2
531
530
  top = screenTop + (windowHeight - height) / 2
@@ -43,14 +43,14 @@ export class RestoreModal extends CoreLitElement {
43
43
  @state() private password = ''
44
44
  @state() private passwordErrors: string[] = []
45
45
  @state() private isRestoring = false
46
- @state() private walletData: WalletData | null = null
47
46
  @state() private validationWarnings: string[] = []
48
- @state() private validationInfo: string[] = []
49
47
  @state() private controllers: Array<{
50
48
  address: string
51
49
  status: 'new' | 'existing'
52
50
  }> = []
53
51
  @state() private restoredAddresses: string[] = []
52
+ validationInfo: string[] = []
53
+ walletData: WalletData | null = null
54
54
 
55
55
  /**
56
56
  * Public method for parent to set preview result
@@ -208,7 +208,9 @@ export class RestoreModal extends CoreLitElement {
208
208
  label="Password"
209
209
  placeholder="Enter decryption password"
210
210
  .value=${this.password}
211
- @on-input=${(e: CustomEvent) => (this.password = e.detail.value)}
211
+ @on-input=${(e: CustomEvent) => {
212
+ this.password = e.detail.value
213
+ }}
212
214
  @keyup=${(e: KeyboardEvent) => e.key === 'Enter' && canProceed && this.previewRestore()}
213
215
  is-full-width
214
216
  autofocus
@@ -1 +1 @@
1
- @import "@lukso/web-components/dist/styles/main.css";
1
+ @import "@lukso/web-components/tools/styles/main.css";
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/restore-modal.ts"],"sourcesContent":["/**\n * Restore Modal - Lit Component\n *\n * Framework-agnostic restore modal for wallet data import.\n * Uses lukso-modal from @lukso/web-components for consistent UI.\n */\n\nimport type {\n BackupFile,\n PasskeyAuthProvider,\n WalletData,\n} from '@lukso/passkey-auth'\nimport { readBackupFile } from '@lukso/passkey-auth'\nimport { html, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { CoreLitElement } from './styles'\n\n// Import lukso web components\nimport '@lukso/web-components/dist/components/lukso-modal'\nimport '@lukso/web-components/dist/components/lukso-button'\nimport '@lukso/web-components/dist/components/lukso-input'\n\nenum Step {\n UPLOAD = 1,\n PASSWORD = 2,\n PREVIEW = 3,\n SUCCESS = 4,\n}\n\n@customElement('restore-modal')\nexport class RestoreModal extends CoreLitElement {\n // Public properties\n @property({ type: Boolean, reflect: true }) isOpen = false\n @property({ type: String }) theme: 'light' | 'dark' | 'auto' = 'auto'\n @property({ type: Object }) keyGenerator: PasskeyAuthProvider | null = null\n\n // Private state\n @state() private currentStep: Step = Step.UPLOAD\n @state() private selectedFile: File | null = null\n @state() private backupData: BackupFile | null = null\n @state() private fileError: string | null = null\n @state() private isDragging = false\n @state() private password = ''\n @state() private passwordErrors: string[] = []\n @state() private isRestoring = false\n @state() private walletData: WalletData | null = null\n @state() private validationWarnings: string[] = []\n @state() private validationInfo: string[] = []\n @state() private controllers: Array<{\n address: string\n status: 'new' | 'existing'\n }> = []\n @state() private restoredAddresses: string[] = []\n\n /**\n * Public method for parent to set preview result\n * Called after parent handles the 'preview' event\n */\n public setPreviewResult(options: {\n controllers: Array<{ address: string; status: 'new' | 'existing' }>\n warnings?: string[]\n }) {\n this.controllers = options.controllers\n this.validationWarnings = options.warnings || []\n }\n\n /**\n * Public method for parent to set validation result\n * Called after parent handles the 'validate' event\n */\n public setValidationResult(\n walletData: WalletData | null,\n options?: {\n error?: string\n warnings?: string[]\n info?: string[]\n }\n ) {\n this.isRestoring = false\n\n if (options?.error) {\n this.passwordErrors = [options.error]\n this.validationWarnings = []\n this.validationInfo = []\n } else if (walletData) {\n this.walletData = walletData\n this.validationWarnings = options?.warnings || []\n this.validationInfo = options?.info || []\n this.currentStep = Step.SUCCESS\n }\n }\n\n render() {\n return html`\n <lukso-modal\n ?is-open=${this.isOpen}\n size=\"medium\"\n @on-backdrop-click=${this.close}\n >\n <div class=\"p-6\">\n <!-- Header -->\n <h2 class=\"m-0 mb-6 text-neutral-20 dark:text-white heading-inter-21-semi-bold\">\n ${this.getStepTitle()}\n </h2>\n\n <!-- Step content -->\n ${this.renderStep()}\n </div>\n </lukso-modal>\n `\n }\n\n private renderStep() {\n switch (this.currentStep) {\n case Step.UPLOAD:\n return this.renderUploadStep()\n case Step.PASSWORD:\n return this.renderPasswordStep()\n case Step.PREVIEW:\n return this.renderPreviewStep()\n case Step.SUCCESS:\n return this.renderSuccessStep()\n default:\n return nothing\n }\n }\n\n private renderUploadStep() {\n return html`\n <p class=\"mb-6 text-neutral-40 dark:text-neutral-50 paragraph-inter-16-regular\">\n Select your backup file to restore your wallet data. Your backup file stays on your device and is never uploaded.\n </p>\n\n <div\n class=\"border-2 border-dashed rounded-xl p-10 text-center bg-neutral-95 dark:bg-neutral-80 transition-all cursor-pointer my-6 ${\n this.isDragging\n ? 'border-blue-60 bg-blue-95 dark:bg-blue-95/10'\n : this.fileError\n ? 'border-red-55 bg-red-95'\n : 'border-neutral-90 dark:border-neutral-70'\n }\"\n @drop=${this.handleDrop}\n @dragover=${this.handleDragOver}\n @dragleave=${this.handleDragLeave}\n @click=${this.triggerFileInput}\n >\n <div class=\"flex flex-col items-center gap-3\">\n <p class=\"m-0 text-neutral-10 dark:text-white heading-inter-16-semi-bold\">\n Drag and drop your backup file here\n </p>\n <p class=\"m-0 text-neutral-40 paragraph-inter-14-regular\">or</p>\n <lukso-button\n variant=\"primary\"\n @click=${(e: Event) => {\n e.stopPropagation()\n this.triggerFileInput()\n }}\n >\n Choose File\n </lukso-button>\n ${\n this.selectedFile\n ? html`\n <p class=\"mt-2 mb-0 text-green-54 paragraph-inter-14-semi-bold\">\n ${this.selectedFile.name}\n </p>\n `\n : nothing\n }\n ${\n this.fileError\n ? html`\n <p class=\"mt-2 mb-0 text-red-55 paragraph-inter-14-semi-bold\">\n ${this.fileError}\n </p>\n `\n : nothing\n }\n </div>\n </div>\n\n <input\n type=\"file\"\n class=\"hidden\"\n accept=\".json\"\n @change=${this.handleFileSelect}\n />\n\n <div class=\"flex justify-end mt-6\">\n <lukso-button variant=\"text\" @click=${this.close}>\n Cancel\n </lukso-button>\n </div>\n `\n }\n\n private renderPasswordStep() {\n const canProceed = this.password && this.password.length > 0\n\n return html`\n <p class=\"mb-5 text-neutral-40 dark:text-neutral-50 paragraph-inter-14-regular\">\n This backup is encrypted. Enter the password to decrypt it.\n </p>\n\n <div>\n <lukso-input\n type=\"password\"\n label=\"Password\"\n placeholder=\"Enter decryption password\"\n .value=${this.password}\n @on-input=${(e: CustomEvent) => (this.password = e.detail.value)}\n @keyup=${(e: KeyboardEvent) => e.key === 'Enter' && canProceed && this.previewRestore()}\n is-full-width\n autofocus\n ></lukso-input>\n ${this.passwordErrors.map(\n (error) => html`\n <div class=\"mt-1 text-red-55 paragraph-inter-13-regular\">${error}</div>\n `\n )}\n </div>\n\n <div class=\"flex justify-between gap-3 mt-6\">\n <div class=\"flex gap-3\">\n <lukso-button variant=\"text\" @click=${this.close}>\n Cancel\n </lukso-button>\n <lukso-button variant=\"secondary\" @click=${this.goBack}>\n Back\n </lukso-button>\n </div>\n <lukso-button\n variant=\"primary\"\n ?disabled=${!canProceed || this.isRestoring}\n ?is-loading=${this.isRestoring}\n @click=${this.previewRestore}\n >\n Continue\n </lukso-button>\n </div>\n `\n }\n\n private renderPreviewStep() {\n return html`\n <p class=\"mb-6 text-neutral-40 dark:text-neutral-50 paragraph-inter-16-regular\">\n ${\n this.controllers.length > 0\n ? `Found ${this.controllers.length} controller${this.controllers.length === 1 ? '' : 's'} in backup.`\n : 'No controllers found in backup.'\n }\n </p>\n\n ${\n this.controllers.length > 0\n ? html`\n <div class=\"mb-6\">\n <div class=\"mb-3 text-neutral-20 dark:text-neutral-90 paragraph-inter-14-semi-bold\">\n Controllers:\n </div>\n ${this.controllers.map(\n (controller) => html`\n <div class=\"bg-neutral-95 dark:bg-neutral-80 border border-neutral-90 dark:border-neutral-70 rounded-lg px-3 py-2.5 mb-2\">\n <div class=\"flex items-center justify-between\">\n <div class=\"text-neutral-40 paragraph-inter-13-regular font-mono\">\n ${this.truncateAddress(controller.address)}\n </div>\n <div\n class=\"px-2 py-0.5 rounded text-xs font-semibold ${\n controller.status === 'new'\n ? 'bg-green-95 dark:bg-green-95/10 text-green-55 border border-green-55/30'\n : 'bg-neutral-90 dark:bg-neutral-70 text-neutral-50 border border-neutral-80 dark:border-neutral-60'\n }\"\n >\n ${controller.status === 'new' ? 'NEW' : 'EXISTS'}\n </div>\n </div>\n <div class=\"text-neutral-60 paragraph-inter-12-regular mt-1\">\n ${controller.address}\n </div>\n </div>\n `\n )}\n </div>\n `\n : nothing\n }\n\n ${\n this.validationWarnings.length > 0\n ? html`\n <div class=\"mb-4\">\n ${this.validationWarnings.map(\n (warning) => html`\n <div class=\"bg-yellow-95 dark:bg-yellow-95/10 border border-yellow-55 dark:border-yellow-55/50 rounded-lg px-3 py-2.5 mb-2 flex items-start gap-2\">\n <span class=\"text-yellow-55 dark:text-yellow-55 text-lg leading-none\">⚠️</span>\n <span class=\"text-yellow-55 dark:text-yellow-55 paragraph-inter-13-regular flex-1\">${warning}</span>\n </div>\n `\n )}\n </div>\n `\n : nothing\n }\n\n <div class=\"flex justify-between gap-3 mt-6\">\n <div class=\"flex gap-3\">\n <lukso-button variant=\"text\" @click=${this.close}>\n Cancel\n </lukso-button>\n <lukso-button variant=\"secondary\" @click=${this.goBackFromPreview}>\n Back\n </lukso-button>\n </div>\n <lukso-button\n variant=\"primary\"\n @click=${this.confirmRestore}\n >\n Confirm Restore\n </lukso-button>\n </div>\n `\n }\n\n private renderSuccessStep() {\n return html`\n <!-- Success header with icon -->\n <div class=\"text-center mb-6\">\n <div class=\"w-16 h-16 mx-auto mb-4 bg-green-95 dark:bg-green-95/20 rounded-full flex items-center justify-center\">\n <span class=\"text-2xl text-green-55\">✅</span>\n </div>\n <h3 class=\"text-neutral-20 dark:text-white heading-inter-18-semi-bold mb-2\">\n Wallet Restored Successfully!\n </h3>\n <p class=\"text-neutral-40 dark:text-neutral-50 paragraph-inter-14-regular\">\n ${\n this.restoredAddresses.length > 0\n ? `Imported ${this.restoredAddresses.length} address${this.restoredAddresses.length > 1 ? 'es' : ''} to your wallet.`\n : 'Your wallet has been restored successfully.'\n }\n </p>\n </div>\n \n <!-- Restored addresses -->\n ${\n this.restoredAddresses.length > 0\n ? html`\n <div class=\"mb-6\">\n <div class=\"mb-3 text-neutral-20 dark:text-neutral-90 paragraph-inter-14-semi-bold\">\n Restored Addresses:\n </div>\n ${this.restoredAddresses.map(\n (address: string) => html`\n <div class=\"bg-green-95 dark:bg-green-95/10 border border-green-60 dark:border-green-60/50 rounded-lg px-3 py-2.5 mb-2 flex items-center gap-2\">\n <span class=\"text-green-60 dark:text-green-45 text-sm\">✓</span>\n <span class=\"text-neutral-20 dark:text-white paragraph-inter-13-regular font-mono flex-1\">${this.truncateAddress(address)}</span>\n </div>\n `\n )}\n </div>\n `\n : ''\n }\n\n <!-- Action buttons for success -->\n <div class=\"flex justify-center mt-6\">\n <lukso-button variant=\"primary\" @click=${this.close}>\n OK\n </lukso-button>\n </div>\n `\n }\n\n private getStepTitle(): string {\n switch (this.currentStep) {\n case Step.UPLOAD:\n return 'Restore Wallet'\n case Step.PASSWORD:\n return 'Enter Password'\n case Step.PREVIEW:\n return 'Review Changes'\n case Step.SUCCESS:\n return 'Restore Complete'\n default:\n return 'Restore Wallet'\n }\n }\n\n private triggerFileInput() {\n const input = this.shadowRoot?.querySelector(\n 'input[type=\"file\"]'\n ) as HTMLInputElement\n if (input) {\n input.click()\n }\n }\n\n private async handleFileSelect(e: Event) {\n const input = e.target as HTMLInputElement\n const file = input.files?.[0]\n if (file) {\n await this.handleFile(file)\n }\n }\n\n private handleDragOver(e: DragEvent) {\n e.preventDefault()\n this.isDragging = true\n }\n\n private handleDragLeave() {\n this.isDragging = false\n }\n\n private async handleDrop(e: DragEvent) {\n e.preventDefault()\n this.isDragging = false\n\n const file = e.dataTransfer?.files?.[0]\n if (file) {\n await this.handleFile(file)\n }\n }\n\n private async handleFile(file: File) {\n this.fileError = null\n\n if (!file.name.endsWith('.json')) {\n this.fileError = 'Please select a valid JSON backup file'\n return\n }\n\n try {\n // Use passkey-auth readBackupFile function\n const backup = await readBackupFile(file)\n\n this.selectedFile = file\n this.backupData = backup\n\n // Check if encrypted (handle both current and legacy formats)\n const isEncrypted = backup.encryptedSecrets // Legacy: always encrypted if encryptedSecrets exists\n ? true\n : backup.secrets?.encrypted // Current: check encrypted flag\n\n if (isEncrypted) {\n this.currentStep = Step.PASSWORD\n } else {\n // Unencrypted backup - preview directly\n await this.previewRestore()\n }\n } catch (error) {\n this.fileError =\n error instanceof Error ? error.message : 'Failed to read backup file'\n console.error('Failed to read backup file:', error)\n }\n }\n\n private async previewRestore() {\n if (!this.backupData) return\n\n this.isRestoring = true\n this.passwordErrors = []\n\n try {\n // First, we need to decrypt the backup if it's encrypted\n let decryptedBackup = this.backupData\n\n if (\n this.backupData.encryptedSecrets ||\n this.backupData.secrets?.encrypted\n ) {\n // PREVIEW ONLY: Use verify to check password and get preview data (don't actually import yet)\n if (!this.keyGenerator) {\n throw new Error('KeyGenerator not available')\n }\n\n // Use verifyBackup for preview - this validates password and returns public data only\n const verifiedBackup = await this.keyGenerator.verifyBackup(\n this.backupData,\n this.password\n )\n\n // Use the verified backup data (which has filtered public data)\n decryptedBackup = verifiedBackup\n } else {\n // Unencrypted - use data directly for preview (no import needed)\n decryptedBackup = this.backupData\n }\n\n // Extract all controller addresses from the backup\n const backupControllers = new Set<string>()\n\n // Get addresses from the secrets (the actual private keys we're restoring)\n const secretsData = (decryptedBackup.secrets?.data as any[]) || []\n for (const secret of secretsData) {\n if (secret.address) {\n backupControllers.add(secret.address.toLowerCase())\n }\n }\n\n // Also get controllers from account metadata (V2 format with networks)\n for (const account of decryptedBackup.accounts || []) {\n // V2 format: accounts have networks array with controllers\n if (account.networks) {\n for (const network of account.networks) {\n for (const controller of network.controllers || []) {\n if (controller.address) {\n backupControllers.add(controller.address.toLowerCase())\n }\n }\n }\n }\n }\n\n // Also get controllers from LSP23CrossChainDeployment if present\n const lsp23Deployments =\n (decryptedBackup as any).LSP23CrossChainDeployment || []\n for (const deployment of lsp23Deployments) {\n for (const controller of deployment.initialControllers || []) {\n if (controller.address) {\n backupControllers.add(controller.address.toLowerCase())\n }\n }\n }\n\n console.log(\n '🔍 [RestoreModal] Found controller addresses:',\n Array.from(backupControllers)\n )\n\n // Extract addresses from the decrypted backup for preview\n for (const secret of secretsData) {\n if (secret.address) {\n backupControllers.add(secret.address.toLowerCase())\n }\n }\n\n // For now, mark all addresses as 'new' - could enhance this later\n this.controllers = Array.from(backupControllers).map((address) => ({\n address,\n status: 'new' as const,\n }))\n\n this.currentStep = Step.PREVIEW\n } catch (error) {\n console.error('Failed to preview restore:', error)\n const errorMessage =\n error instanceof Error ? error.message : 'Failed to preview restore'\n\n // Check for password-specific errors\n if (errorMessage.toLowerCase().includes('password')) {\n this.passwordErrors = ['Incorrect password. Please try again.']\n } else {\n // For non-password errors, set as file error to show in upload step\n this.fileError = errorMessage\n this.currentStep = Step.UPLOAD\n // Clear the file selection so user can try again\n this.selectedFile = null\n this.backupData = null\n // Clear the file input\n const input = this.shadowRoot?.querySelector(\n 'input[type=\"file\"]'\n ) as HTMLInputElement\n if (input) {\n input.value = ''\n }\n }\n } finally {\n this.isRestoring = false\n }\n }\n\n private async confirmRestore() {\n if (!this.backupData || !this.keyGenerator) {\n console.error(\n '❌ [RestoreModal] Missing backup data or keyGenerator for restore'\n )\n this.dispatchEvent(\n new CustomEvent('error', {\n detail: { error: 'Missing backup data or keyGenerator' },\n bubbles: true,\n composed: true,\n })\n )\n return\n }\n\n try {\n this.isRestoring = true\n console.log('🔄 [RestoreModal] Starting secure restoration process...')\n\n // ✅ SECURE: Use keyGenerator.restoreFromBackup internally\n const result = await this.keyGenerator.restoreFromBackup(\n this.backupData,\n this.password\n )\n\n if (result.success) {\n console.log('✅ [RestoreModal] Restore successful:', result.addresses)\n\n // Store restored addresses for display on success screen\n this.restoredAddresses = result.addresses\n\n // Emit success event (only public addresses, no sensitive data)\n this.dispatchEvent(\n new CustomEvent('success', {\n detail: { addresses: result.addresses },\n bubbles: true,\n composed: true,\n })\n )\n\n // Move to success step\n this.currentStep = Step.SUCCESS\n } else {\n console.error('❌ [RestoreModal] Restore failed')\n this.dispatchEvent(\n new CustomEvent('error', {\n detail: {\n error:\n 'Restore failed. Please check the backup file and password.',\n },\n bubbles: true,\n composed: true,\n })\n )\n }\n } catch (error) {\n console.error('❌ [RestoreModal] Restore error:', error)\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error'\n\n this.dispatchEvent(\n new CustomEvent('error', {\n detail: { error: errorMessage },\n bubbles: true,\n composed: true,\n })\n )\n } finally {\n this.isRestoring = false\n }\n }\n\n private goBack() {\n if (this.currentStep === Step.PASSWORD) {\n this.currentStep = Step.UPLOAD\n this.password = ''\n this.passwordErrors = []\n }\n }\n\n private goBackFromPreview() {\n // Go back to password step (or upload if unencrypted)\n const isEncrypted = this.backupData?.encryptedSecrets\n ? true\n : this.backupData?.secrets?.encrypted\n\n if (isEncrypted) {\n this.currentStep = Step.PASSWORD\n } else {\n this.currentStep = Step.UPLOAD\n }\n // Clear preview data\n this.controllers = []\n this.validationWarnings = []\n }\n\n private close() {\n this.isOpen = false\n this.dispatchEvent(\n new CustomEvent('close', { bubbles: true, composed: true })\n )\n\n // Reset state after animation\n setTimeout(() => {\n this.currentStep = Step.UPLOAD\n this.selectedFile = null\n this.backupData = null\n this.fileError = null\n this.isDragging = false\n this.password = ''\n this.passwordErrors = []\n this.isRestoring = false\n this.walletData = null\n this.restoredAddresses = []\n this.controllers = []\n this.validationWarnings = []\n }, 300)\n }\n\n private truncateAddress(address: string): string {\n if (!address || address.length < 10) return address\n return `${address.slice(0, 6)}...${address.slice(-4)}`\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'restore-modal': RestoreModal\n }\n}\n"],"mappings":"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","names":[]}