@lukso/transaction-view-core 0.5.0 → 0.6.0-dev.3b54e9f

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 (45) hide show
  1. package/.turbo/turbo-build.log +20 -20
  2. package/.turbo/turbo-typecheck.log +4 -0
  3. package/CHANGELOG.md +21 -0
  4. package/dist/index.cjs +131 -220
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.d.cts +1 -10
  7. package/dist/index.d.ts +1 -10
  8. package/dist/index.js +158 -252
  9. package/dist/index.js.map +1 -1
  10. package/dist/shared/index.cjs +31 -64
  11. package/dist/shared/index.cjs.map +1 -1
  12. package/dist/shared/index.d.cts +8 -20
  13. package/dist/shared/index.d.ts +8 -20
  14. package/dist/shared/index.js +43 -76
  15. package/dist/shared/index.js.map +1 -1
  16. package/dist/styles/index.cjs +1 -1
  17. package/dist/styles/index.cjs.map +1 -1
  18. package/dist/styles/index.js +1 -1
  19. package/dist/styles/index.js.map +1 -1
  20. package/package.json +5 -4
  21. package/src/components/asset-card.ts +63 -80
  22. package/src/components/contract-card.ts +2 -67
  23. package/src/components/info-panel.ts +1 -21
  24. package/src/components/permissions-block.ts +7 -5
  25. package/src/components/transaction-playback.ts +4 -4
  26. package/src/shared/address-display.ts +3 -6
  27. package/src/shared/address-view.ts +2 -18
  28. package/src/shared/custom-select.ts +1 -1
  29. package/src/shared/function-name-view.ts +1 -1
  30. package/src/shared/gas-provider-view.ts +4 -7
  31. package/src/shared/icon-view.ts +7 -9
  32. package/src/shared/image-list.ts +3 -4
  33. package/src/shared/load-web-components.ts +3 -2
  34. package/src/shared/notification-view.ts +3 -3
  35. package/src/shared/progress-view.ts +1 -10
  36. package/src/shared/scroll-to-bottom-button.ts +1 -1
  37. package/src/shared/signal-controller.ts +3 -1
  38. package/src/shared/transaction-view-controller.ts +1 -1
  39. package/src/shared/url-view.ts +3 -3
  40. package/src/shared/value-view.ts +10 -30
  41. package/src/styles/styles.css +1 -1
  42. package/src/utils.test.ts +47 -0
  43. package/src/utils.ts +82 -0
  44. package/src/vue-entry.ts +0 -1
  45. package/tsup.config.ts +3 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lukso/transaction-view-core",
3
- "version": "0.5.0",
3
+ "version": "0.6.0-dev.3b54e9f",
4
4
  "description": "Core components and hooks for LUKSO transaction display",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -35,8 +35,8 @@
35
35
  "@preact/signals-core": "^1.12.1",
36
36
  "ethereum-blockies-base64": "^1.0.2",
37
37
  "lit": "^3.3.1",
38
- "@lukso/transaction-decoder": "1.3.0",
39
- "@lukso/transaction-view-headless": "0.4.0"
38
+ "@lukso/transaction-decoder": "1.3.1-dev.3b54e9f",
39
+ "@lukso/transaction-view-headless": "0.4.1-dev.3b54e9f"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@tailwindcss/typography": "^0.5.19",
@@ -52,6 +52,7 @@
52
52
  "build": "tsup",
53
53
  "dev": "tsup --watch",
54
54
  "dev-alt": "tsup --watch",
55
- "clean": "rm -rf dist"
55
+ "clean": "rm -rf dist",
56
+ "typecheck": "tsc --noEmit"
56
57
  }
57
58
  }
@@ -11,26 +11,12 @@ import '../shared/image-list.js'
11
11
  import '@lukso/web-components'
12
12
  import { Task } from '@lit/task'
13
13
  import {
14
- ResolvedAddress,
14
+ type ResolvedAddress,
15
15
  useAddressResolver,
16
16
  } from '@lukso/transaction-view-headless'
17
17
  import { safeCustomElement } from '../shared/safe-custom-element.js'
18
18
  import { CoreLitElement } from '../styles'
19
-
20
- // Value formatting utilities
21
- function formatUnits(value: bigint, decimals = 18): string {
22
- const divisor = 10n ** BigInt(decimals)
23
- const quotient = value / divisor
24
- const remainder = value % divisor
25
-
26
- if (remainder === 0n) {
27
- return quotient.toString()
28
- }
29
-
30
- const remainderStr = remainder.toString().padStart(decimals, '0')
31
- const trimmed = remainderStr.replace(/0+$/, '')
32
- return `${quotient}.${trimmed}`
33
- }
19
+ import { formatUnits, parseBigInt } from '../utils.js'
34
20
 
35
21
  /**
36
22
  * Asset card component for displaying token/NFT information
@@ -58,9 +44,6 @@ export class AssetCard extends CoreLitElement {
58
44
  @property({ type: String, attribute: 'function-icon' })
59
45
  functionIcon: string = 'code-outline'
60
46
 
61
- @property({ type: String })
62
- size: 'small' | 'medium' | 'large' = 'medium'
63
-
64
47
  @property({ type: Boolean, attribute: 'show-info-button' })
65
48
  showInfoButton = true
66
49
 
@@ -73,13 +56,6 @@ export class AssetCard extends CoreLitElement {
73
56
  @state()
74
57
  private _resolvedData?: ResolvedAddress
75
58
 
76
- @state()
77
- private _imageError = false
78
-
79
- private _handleImageError() {
80
- this._imageError = true
81
- }
82
-
83
59
  private _handleInfoClick() {
84
60
  this.displayDetails = !this.displayDetails
85
61
  }
@@ -103,19 +79,6 @@ export class AssetCard extends CoreLitElement {
103
79
  return addressOrComposite.split('-')[0]
104
80
  }
105
81
 
106
- private _extractTokenId(addressOrComposite: string): string | undefined {
107
- const parts = addressOrComposite.split('-')
108
- return parts.length > 1 ? parts[1] : undefined
109
- }
110
-
111
- private _copyToClipboard(text: string) {
112
- if (navigator.clipboard) {
113
- navigator.clipboard.writeText(text)
114
- // Could dispatch a 'copied' event here for toast notifications
115
- this.dispatchEvent(new CustomEvent('copied', { detail: { text } }))
116
- }
117
- }
118
-
119
82
  private _renderAddressSection() {
120
83
  const data = this._resolutionTask.value
121
84
  if (!data) return ''
@@ -231,9 +194,7 @@ export class AssetCard extends CoreLitElement {
231
194
  const displayTokenId = formattedTokenId ? `${formattedTokenId}` : ''
232
195
  if (displayTokenId) return displayTokenId
233
196
  // If its a collection, do not show tokenId
234
- return this.tokenId && !this._resolvedData?.isCollection
235
- ? `${parseInt(this.tokenId, 16)}`
236
- : undefined
197
+ return this.tokenId ? `${parseInt(this.tokenId, 16)}` : undefined
237
198
  }
238
199
 
239
200
  private _renderTokenId() {
@@ -298,6 +259,7 @@ export class AssetCard extends CoreLitElement {
298
259
  private _renderImages() {
299
260
  const images = (this._resolvedData as any)?.images || []
300
261
  if (images.length === 0) return ''
262
+ if (!this.address) return ''
301
263
 
302
264
  return html`
303
265
  <image-list
@@ -312,6 +274,7 @@ export class AssetCard extends CoreLitElement {
312
274
  private _renderAssets() {
313
275
  const assets = (this._resolvedData as any)?.assets || []
314
276
  if (assets.length === 0) return ''
277
+ if (!this.address) return ''
315
278
 
316
279
  return html`
317
280
  <div class="section">
@@ -329,11 +292,11 @@ export class AssetCard extends CoreLitElement {
329
292
  return html`
330
293
  <div class="flex justify-between items-center my-4">
331
294
  <function-name-view
332
- label=${this.functionName}
333
- size="small"
334
- icon=${this.functionIcon ? this.functionIcon : 'code-outline'}
295
+ label=${this.functionName || 'Execute'}
296
+ size="small"
297
+ icon=${this.functionIcon ? this.functionIcon : 'code-outline'}
335
298
  ></function-name-view>
336
- <function-name-view label=${this._resolvedData?.standard} size="small"></function-name-view>
299
+ <function-name-view label=${this._resolvedData?.standard ?? 'Unknown'} size="small"></function-name-view>
337
300
  </div>
338
301
  `
339
302
  }
@@ -354,6 +317,15 @@ export class AssetCard extends CoreLitElement {
354
317
  `
355
318
  }
356
319
 
320
+ private _formattedAmount() {
321
+ const data = this._resolutionTask.value
322
+ const amt = this.amount
323
+ if (amt === undefined || amt === null || amt === '') return undefined
324
+ const bigintAmount = parseBigInt(amt as any)
325
+ if (bigintAmount === undefined) return undefined
326
+ return formatUnits(bigintAmount, data?.decimals)
327
+ }
328
+
357
329
  private renderFormattedTokenIdBadge() {
358
330
  if (!this.displayedTokenId) return ''
359
331
  return html`
@@ -365,54 +337,65 @@ export class AssetCard extends CoreLitElement {
365
337
  return html`
366
338
  <div >
367
339
  ${this._renderStandards()}
368
- <div class="mt-6 flex-col">
369
- <div class="flex items-center justify-center gap-4">
370
- <div class="flex justify-end w-[48%]">
371
- <div class="border relative border-neutral-90 rounded-xl">
372
- ${this.renderFormattedTokenIdBadge()}
373
- <div class="p-2 relative">
374
- <icon-view
375
- address="${this.address}"
376
- size="2x-large"
377
- .showName=${false}
378
- ></icon-view>
379
- </div>
380
- <div style="height: 1px;" class="bg-neutral-90 w-full"></div>
381
- <div class="px-2">
382
- ${this._renderAddressSection()}
340
+ <div class="mt-6 flex-col">
341
+ <div class="flex items-center justify-center gap-4">
342
+ <div class="flex justify-end w-[48%]">
343
+ <div class="border relative border-neutral-90 rounded-xl">
344
+ ${this.renderFormattedTokenIdBadge()}
345
+ <div class="p-2 relative">
346
+ ${when(
347
+ this.address,
348
+ () => html`
349
+ <icon-view
350
+ address=${this.address ?? ''}
351
+ size="2x-large"
352
+ .showName=${false}
353
+ ></icon-view>
354
+ `
355
+ )}
356
+ </div>
357
+ <div style="height: 1px;" class="bg-neutral-90 w-full"></div>
358
+ <div class="px-2">
359
+ ${this._renderAddressSection()}
360
+ </div>
383
361
  </div>
384
362
  </div>
385
- </div>
386
363
 
387
- <div class="flex flex-col gap-1 w-[51%]">
388
- <div class="text-[14px] font-bold text-neutral-20">
389
- ${this._resolvedData?.lsp4TokenName || 'UNKNOWN'}
390
- </div>
391
- <div class="text-[17px] font-semibold text-neutral-20">
364
+ <div class="flex flex-col gap-1 w-[51%]">
365
+ <div class="text-[14px] font-bold text-neutral-20">
366
+ ${this._resolvedData?.lsp4TokenName || 'UNKNOWN'}
367
+ </div>
368
+ <div class="text-[17px] font-semibold text-neutral-20">
369
+ ${when(
370
+ this.amount,
371
+ () => html`
372
+ <span class="">${this._formattedAmount() ?? ''}</span>
373
+ <span class="ml-1 text-neutral-60 max-w-[60px] whitespace-nowrap overflow-hidden text-ellipsis text-[14px] font-semibold">${
374
+ this._resolvedData?.lsp4TokenSymbol || ''
375
+ }</span>
376
+ `,
377
+ () => html`${this._resolvedData?.lsp4TokenSymbol || ''}`
378
+ )}
379
+ </div>
380
+
392
381
  ${when(
393
382
  this.amount,
394
383
  () => html`
395
- <span class="">${formatUnits(BigInt(this.amount!), this._resolvedData?.decimals)}</span>
384
+ <span class="">${formatUnits(BigInt(this.amount || 0), this._resolvedData?.decimals)}</span>
396
385
  <span class="ml-1 text-neutral-60 max-w-[60px] whitespace-nowrap overflow-hidden text-ellipsis text-[14px] font-semibold">${
397
386
  this._resolvedData?.lsp4TokenSymbol || ''
398
387
  }</span>
399
388
  `,
400
389
  () => html`${this._resolvedData?.lsp4TokenSymbol || ''}`
401
390
  )}
402
- </div>
403
-
404
- ${when(
405
- this.displayedTokenId,
406
- () =>
407
- html`<div class="text-[14px] font-medium text-neutral-60"><span class="font-bold">#${this.displayedTokenId}</span></div>`
408
- )}
409
- <div class="mt-4">
410
- ${when(this.showCreator, () => this._renderCreatorSection())}
391
+ <div class="mt-4">
392
+ ${when(this.showCreator, () => this._renderCreatorSection())}
393
+ </div>
411
394
  </div>
412
395
  </div>
413
- </div>
414
- <div class="border-neutral-90 pt-2">
415
- ${this._renderTokenDetails()}
396
+ <div class="border-neutral-90 pt-2">
397
+ ${this._renderTokenDetails()}
398
+ </div>
416
399
  </div>
417
400
  </div>
418
401
  `
@@ -1,10 +1,5 @@
1
- import { Task } from '@lit/task'
2
- import {
3
- type ResolvedAddress,
4
- useAddressResolver,
5
- useImageLoader,
6
- } from '@lukso/transaction-view-headless'
7
- import { css, html, LitElement, nothing } from 'lit'
1
+ import type { ResolvedAddress } from '@lukso/transaction-view-headless'
2
+ import { css, html, LitElement } from 'lit'
8
3
  import { property, state } from 'lit/decorators.js'
9
4
  import { safeCustomElement } from '../shared/safe-custom-element'
10
5
  import '../shared/load-web-components'
@@ -115,66 +110,6 @@ export class ContractCard extends LitElement {
115
110
  @state() private _profileImageUrl?: string
116
111
  @state() private _backgroundImageUrl?: string
117
112
 
118
- private _resolutionTask = new Task(this, {
119
- task: async ([address, resolved]) => {
120
- if (resolved) {
121
- this._resolvedData = resolved
122
- return resolved
123
- }
124
-
125
- const { resolveAddress } = useAddressResolver()
126
- const baseAddress = this._extractBaseAddress(address as string)
127
- const data = await resolveAddress(baseAddress)
128
- this._resolvedData = data
129
- return data
130
- },
131
- args: () => [this.address, this.resolved] as const,
132
- })
133
-
134
- private _profileImageTask = new Task(this, {
135
- task: async ([resolved]) => {
136
- const { loadProfileImage } = useImageLoader()
137
- const data = resolved || this._resolvedData
138
-
139
- if (!data) return null
140
-
141
- const image = await loadProfileImage(data, {
142
- width: 256,
143
- height: 256,
144
- dpr: window.devicePixelRatio || 1,
145
- })
146
-
147
- if (image?.src) {
148
- this._profileImageUrl = image.src
149
- }
150
-
151
- return image
152
- },
153
- args: () => [this._resolvedData] as const,
154
- })
155
-
156
- private _backgroundImageTask = new Task(this, {
157
- task: async ([resolved]) => {
158
- const { loadBackgroundImage } = useImageLoader()
159
- const data = resolved || this._resolvedData
160
-
161
- if (!data) return null
162
-
163
- const image = await loadBackgroundImage(data, {
164
- width: 800,
165
- height: 200,
166
- dpr: window.devicePixelRatio || 1,
167
- })
168
-
169
- if (image?.src) {
170
- this._backgroundImageUrl = image.src
171
- }
172
-
173
- return image
174
- },
175
- args: () => [this._resolvedData] as const,
176
- })
177
-
178
113
  private _extractBaseAddress(addressOrComposite: string): string {
179
114
  return addressOrComposite.split('-')[0]
180
115
  }
@@ -1,8 +1,4 @@
1
- import { Task } from '@lit/task'
2
- import {
3
- type ResolvedAddress,
4
- useAddressResolver,
5
- } from '@lukso/transaction-view-headless'
1
+ import type { ResolvedAddress } from '@lukso/transaction-view-headless'
6
2
  import { css, html, LitElement } from 'lit'
7
3
  import { property, state } from 'lit/decorators.js'
8
4
  import { classMap } from 'lit/directives/class-map.js'
@@ -34,25 +30,9 @@ export class InfoPanel extends LitElement {
34
30
  @property({ type: String })
35
31
  type: 'transfer' | 'mint' | 'burn' | 'approve' = 'transfer'
36
32
 
37
- @state()
38
- private _isAnimating = false
39
-
40
33
  @state()
41
34
  private _resolvedData?: ResolvedAddress
42
35
 
43
- private _resolutionTask = new Task(this, {
44
- task: async ([address]) => {
45
- if (!address) return null
46
-
47
- const { resolveAddress } = useAddressResolver()
48
- // Resolve the full address (including tokenId if present) to get token-specific data
49
- const data = await resolveAddress(address as string)
50
- this._resolvedData = data
51
- return data
52
- },
53
- args: () => [this.address] as const,
54
- })
55
-
56
36
  private _extractBaseAddress(addressOrComposite: string): string {
57
37
  return addressOrComposite.split('-')[0]
58
38
  }
@@ -79,13 +79,15 @@ export class PermissionsBlock extends CoreLitElement {
79
79
  }
80
80
 
81
81
  private renderPermission(p: PermissionLevels) {
82
- const nameBase = (p.icon || p.permissionName || '').toLowerCase()
82
+ const nameBase = (p.icon || p.permissionName || '')
83
+ .toLowerCase()
84
+ .replace(/_/g, '-')
83
85
  const activeIcon = `${nameBase}-activated`
84
86
  const inactiveIcon = `${nameBase}-inactive`
85
87
  return html`
86
88
  <div class="mt-4 grid grid-cols-[40px,1fr,20px] gap-x-2 items-start">
87
89
  <div class="relative w-10 h-10">
88
- <svg-icon
90
+ <lukso-icon
89
91
  class="active absolute bottom-0 opacity-0 z-[99] transition-opacity duration-200 ${
90
92
  p.isActive ? 'opacity-100' : ''
91
93
  }"
@@ -93,14 +95,14 @@ export class PermissionsBlock extends CoreLitElement {
93
95
  width="40"
94
96
  height="40"
95
97
  color=${this.color}
96
- ></svg-icon>
97
- <svg-icon
98
+ ></lukso-icon>
99
+ <lukso-icon
98
100
  class="inactive absolute bottom-0 ${p.isActive ? 'opacity-0' : 'opacity-100'}"
99
101
  name=${inactiveIcon}
100
102
  width="40"
101
103
  height="40"
102
104
  color=${this.color}
103
- ></svg-icon>
105
+ ></lukso-icon>
104
106
  </div>
105
107
 
106
108
  <div>
@@ -231,7 +231,7 @@ export class TransactionPlayback extends LitElement {
231
231
  }
232
232
  }
233
233
 
234
- protected updated(changedProperties: PropertyValues): void {
234
+ protected updated(_changedProperties: PropertyValues): void {
235
235
  // Mount component after render
236
236
  if (this.loadedComponent && this.componentContainerRef.value) {
237
237
  // Clear existing content
@@ -364,14 +364,14 @@ export class TransactionPlayback extends LitElement {
364
364
  () => html`
365
365
  <div class="debug-item">
366
366
  <span class="debug-label">Child Index:</span>
367
- <span class="debug-value">${this.currentResult!.indexInfo.childIndex}</span>
367
+ <span class="debug-value">${this.currentResult?.indexInfo.childIndex}</span>
368
368
  </div>
369
369
  `
370
370
  )}
371
371
  <div class="debug-item">
372
372
  <span class="debug-label">Available Indices:</span>
373
373
  <span class="debug-value">
374
- [${this.playbackState!.batchInfo.availableIndices.join(', ')}]
374
+ [${this.playbackState?.batchInfo.availableIndices.join(', ')}]
375
375
  </span>
376
376
  </div>
377
377
  ${when(
@@ -379,7 +379,7 @@ export class TransactionPlayback extends LitElement {
379
379
  () => html`
380
380
  <div class="debug-item">
381
381
  <span class="debug-label">Matched View:</span>
382
- <span class="debug-value">${this.currentResult!.match!.view.id}</span>
382
+ <span class="debug-value">${this.currentResult?.match?.view.id}</span>
383
383
  </div>
384
384
  `
385
385
  )}
@@ -4,7 +4,7 @@ import {
4
4
  useImageLoader,
5
5
  } from '@lukso/transaction-view-headless'
6
6
  import { css, html, LitElement } from 'lit'
7
- import { customElement, property, state } from 'lit/decorators.js'
7
+ import { property } from 'lit/decorators.js'
8
8
  import { safeCustomElement } from './safe-custom-element'
9
9
 
10
10
  // LUKSO web components are loaded dynamically via plugin
@@ -96,17 +96,14 @@ export class AddressDisplay extends LitElement {
96
96
  return this.value || this.address || ''
97
97
  }
98
98
 
99
- // Internal state
100
- @state() private imageData?: { src: string }
101
- @state() private isLoadingImage = false
102
-
103
99
  // Composables
104
100
  private imageLoader = useImageLoader()
105
101
  private addressResolver = useAddressResolver()
102
+ isLoadingImage = false
106
103
 
107
104
  // Task for loading profile image
108
105
  private imageTask = new Task(this, {
109
- task: async ([resolved], { signal }) => {
106
+ task: async ([resolved]) => {
110
107
  if (!resolved) return null
111
108
 
112
109
  this.isLoadingImage = true
@@ -90,7 +90,7 @@ export class AddressView extends CoreLitElement {
90
90
 
91
91
  // Task for resolving address data
92
92
  private addressTask = new Task(this, {
93
- task: async ([address], { signal }) => {
93
+ task: async ([address]) => {
94
94
  if (!address) return null
95
95
 
96
96
  this.isLoadingAddress = true
@@ -99,7 +99,7 @@ export class AddressView extends CoreLitElement {
99
99
  const resolved = await this.addressResolver.resolveAddress(address)
100
100
  this.requestUpdate() // Force re-render after resolution
101
101
  return resolved
102
- } catch (error) {
102
+ } catch (_error) {
103
103
  return null
104
104
  } finally {
105
105
  this.isLoadingAddress = false
@@ -129,22 +129,6 @@ export class AddressView extends CoreLitElement {
129
129
  return this.label || computedName || 'Anonymous'
130
130
  }
131
131
 
132
- /**
133
- * Check if this is a contract address (non-profile)
134
- */
135
- private get isContract(): boolean {
136
- const resolved = this.addressTask.value
137
- return resolved ? resolved.__gqltype !== 'Profile' : false
138
- }
139
-
140
- /**
141
- * Check if this should show the address hash (profiles show hash, contracts don't)
142
- */
143
- private get shouldShowAddressHash(): boolean {
144
- const resolved = this.addressTask.value
145
- return resolved ? resolved.__gqltype === 'Profile' : true // Default to true for fallback
146
- }
147
-
148
132
  /**
149
133
  * Get prefix for the address display
150
134
  */
@@ -1,5 +1,5 @@
1
1
  import { html } from 'lit'
2
- import { customElement, property, query, state } from 'lit/decorators.js'
2
+ import { property } from 'lit/decorators.js'
3
3
  import { safeCustomElement } from './safe-custom-element'
4
4
  import './load-web-components'
5
5
  import makeBlockie from 'ethereum-blockies-base64'
@@ -1,5 +1,5 @@
1
1
  import { html } from 'lit'
2
- import { customElement, property } from 'lit/decorators.js'
2
+ import { property } from 'lit/decorators.js'
3
3
  import { safeCustomElement } from './safe-custom-element'
4
4
  import './load-web-components'
5
5
  import { CoreLitElement } from '../styles'
@@ -1,8 +1,5 @@
1
- import { Task } from '@lit/task'
2
- import { useAddressResolver } from '@lukso/transaction-view-headless'
3
- import makeBlockie from 'ethereum-blockies-base64'
4
1
  import { html } from 'lit'
5
- import { customElement, property, state } from 'lit/decorators.js'
2
+ import { property } from 'lit/decorators.js'
6
3
  import { safeCustomElement } from './safe-custom-element'
7
4
  import './load-web-components'
8
5
  import { CoreLitElement } from '../styles'
@@ -148,7 +145,7 @@ export class GasProviderView extends CoreLitElement {
148
145
 
149
146
  private displayRelayerResetDate() {
150
147
  const date = new Date(this.relayerResetDate)
151
- return isNaN(date.getTime()) ? 'N/A' : date.toLocaleDateString()
148
+ return Number.isNaN(date.getTime()) ? 'N/A' : date.toLocaleDateString()
152
149
  }
153
150
 
154
151
  override render() {
@@ -178,12 +175,12 @@ export class GasProviderView extends CoreLitElement {
178
175
  ? this.controllerAddress
179
176
  : (() => {
180
177
  const r = this.allRelayers.find(
181
- (x) => x.id === this.selectedGasProvider!.id
178
+ (x) => x.id === this.selectedGasProvider?.id
182
179
  )
183
180
  return (
184
181
  r?.website ||
185
182
  r?.apiUrl ||
186
- `relayer:${this.selectedGasProvider!.id}`
183
+ `relayer:${this.selectedGasProvider?.id}`
187
184
  )
188
185
  })()
189
186
  : undefined
@@ -1,10 +1,11 @@
1
1
  import { Task } from '@lit/task'
2
2
  import {
3
+ type ImageResult,
3
4
  useAddressResolver,
4
5
  useImageLoader,
5
6
  } from '@lukso/transaction-view-headless'
6
7
  import { html } from 'lit'
7
- import { customElement, property, state } from 'lit/decorators.js'
8
+ import { property } from 'lit/decorators.js'
8
9
  import { CoreLitElement } from '../styles'
9
10
  import { safeCustomElement } from './safe-custom-element'
10
11
 
@@ -115,18 +116,15 @@ export class IconView extends CoreLitElement {
115
116
  */
116
117
  @property({ type: Number, attribute: 'image-index' }) imageIndex?: number
117
118
 
118
- // Internal state
119
- @state() private imageData?: { src: string }
120
- @state() private isLoadingImage = false
121
- @state() private isLoadingAddress = false
122
-
123
119
  // Composables
124
120
  private imageLoader = useImageLoader()
125
121
  private addressResolver = useAddressResolver()
122
+ isLoadingAddress = false
123
+ isLoadingImage = false
126
124
 
127
125
  // Task for resolving address data
128
126
  private addressTask = new Task(this, {
129
- task: async ([address], { signal }) => {
127
+ task: async ([address]) => {
130
128
  if (!address) return null
131
129
 
132
130
  this.isLoadingAddress = true
@@ -147,12 +145,12 @@ export class IconView extends CoreLitElement {
147
145
 
148
146
  // Task for loading profile image
149
147
  private imageTask = new Task(this, {
150
- task: async ([resolved], { signal }) => {
148
+ task: async ([resolved]) => {
151
149
  if (!resolved) return null
152
150
 
153
151
  this.isLoadingImage = true
154
152
  try {
155
- let image
153
+ let image: ImageResult | null = null
156
154
 
157
155
  // If imageHint is specified, load directly from that property
158
156
  if (this.imageHint && (resolved as any)[this.imageHint]) {
@@ -1,7 +1,7 @@
1
1
  import { Task } from '@lit/task'
2
2
  import { useAddressResolver } from '@lukso/transaction-view-headless'
3
3
  import { html } from 'lit'
4
- import { customElement, property, state } from 'lit/decorators.js'
4
+ import { property, state } from 'lit/decorators.js'
5
5
  import { repeat } from 'lit/directives/repeat.js'
6
6
  import { safeCustomElement } from './safe-custom-element'
7
7
  import './icon-view.js'
@@ -72,7 +72,7 @@ export class ImageList extends CoreLitElement {
72
72
 
73
73
  // Task for resolving address data
74
74
  private addressTask = new Task(this, {
75
- task: async ([address], { signal }) => {
75
+ task: async ([address]) => {
76
76
  if (!address) return null
77
77
 
78
78
  this.isLoading = true
@@ -140,7 +140,7 @@ export class ImageList extends CoreLitElement {
140
140
  * Render a single image item
141
141
  */
142
142
  private renderImageItem(item: any, index: number) {
143
- const itemIndex = item.index !== undefined ? item.index : index
143
+ const _itemIndex = item.index !== undefined ? item.index : index
144
144
  const isImage = this.isImageFile(item)
145
145
 
146
146
  if (isImage) {
@@ -237,7 +237,6 @@ export class ImageList extends CoreLitElement {
237
237
  </div>
238
238
  `
239
239
  }
240
-
241
240
  const grid = html`
242
241
  <div class="grid grid-cols-[repeat(auto-fill,minmax(${this.getImageMinSizePx()}px,300px))] gap-3 p-2">
243
242
  ${repeat(
@@ -34,11 +34,12 @@ const originalDefine =
34
34
 
35
35
  // Wrap customElements.define to catch duplicate registration errors
36
36
  if (typeof customElements !== 'undefined' && originalDefine) {
37
- customElements.define = function (
37
+ customElements.define = (
38
38
  name: string,
39
+ // biome-ignore lint/suspicious/noShadowRestrictedNames: This is the web-components api.
39
40
  constructor: CustomElementConstructor,
40
41
  options?: ElementDefinitionOptions
41
- ) {
42
+ ) => {
42
43
  // Check if already defined
43
44
  if (!customElements.get(name)) {
44
45
  originalDefine(name, constructor, options)