@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
@@ -1,5 +1,5 @@
1
1
  import { html } from 'lit'
2
- import { customElement, property, state } from 'lit/decorators.js'
2
+ import { property, state } from 'lit/decorators.js'
3
3
  import { safeCustomElement } from './safe-custom-element'
4
4
  import './load-web-components'
5
5
  import { CoreLitElement } from '../styles'
@@ -58,7 +58,7 @@ export class NotificationView extends CoreLitElement {
58
58
  return html`
59
59
  <div class="grid grid-cols-[24px_1fr] items-start gap-3 p-3 rounded-xl text-neutral-10 leading-snug ${this.getVariantBackgroundClass()}">
60
60
  <div class="flex items-center justify-center text-[16px] text-neutral-20 self-center" aria-hidden="true">
61
- <lukso-icon name="${this.renderIcon()}" size="large" color="${this.getVariantColor()}"></lukso-icon>
61
+ <lukso-icon name="${this.renderIcon()}" size="small" color="${this.getVariantColor()}"></lukso-icon>
62
62
  </div>
63
63
  <div class="text-[14px] flex flex-col gap-1.5">
64
64
  ${
@@ -66,7 +66,7 @@ export class NotificationView extends CoreLitElement {
66
66
  ? html`<div class="font-semibold text-neutral-20 paragraph-inter-14-semi-bold">${this.title}</div>`
67
67
  : ''
68
68
  }
69
- <div class="text-neutral-30"><slot>${this.message}</slot></div>
69
+ <div class="text-neutral-20"><slot>${this.message}</slot></div>
70
70
  ${
71
71
  this.acknowledgeable
72
72
  ? html`
@@ -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 { CoreLitElement } from '../styles'
4
4
  import { safeCustomElement } from './safe-custom-element'
5
5
 
@@ -42,15 +42,6 @@ export class ProgressView extends CoreLitElement {
42
42
  `
43
43
  }
44
44
 
45
- private renderAddressLabel() {
46
- return html`
47
- <value-view
48
- .value=${this.address}
49
- .unit=${this.unit}
50
- ></value-view>
51
- `
52
- }
53
-
54
45
  override render() {
55
46
  const isError = (this.className || '').split(/\s+/).includes('error')
56
47
  return html`
@@ -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 { CoreLitElement } from '../styles'
4
4
  import { safeCustomElement } from './safe-custom-element'
5
5
 
@@ -90,7 +90,9 @@ export class MultiSignalController implements ReactiveController {
90
90
  }
91
91
 
92
92
  hostDisconnected() {
93
- this.unsubscribes.forEach((unsubscribe) => unsubscribe())
93
+ this.unsubscribes.forEach((unsubscribe) => {
94
+ unsubscribe()
95
+ })
94
96
  this.unsubscribes = []
95
97
  }
96
98
 
@@ -255,7 +255,7 @@ export function useTransactionView(
255
255
  /**
256
256
  * Controller for working with transaction signals from the decoder
257
257
  */
258
- export class TransactionSignalController<T = any>
258
+ export class TransactionSignalController<_T = any>
259
259
  implements ReactiveController
260
260
  {
261
261
  private host: ReactiveControllerHost
@@ -1,5 +1,5 @@
1
1
  import { html } from 'lit'
2
- import { customElement, property, state } from 'lit/decorators.js'
2
+ import { property, state } from 'lit/decorators.js'
3
3
  import { safeCustomElement } from './safe-custom-element'
4
4
  import './load-web-components'
5
5
  import { CoreLitElement } from '../styles'
@@ -56,7 +56,7 @@ export class UrlView extends CoreLitElement {
56
56
  .replace(/-/g, ' ')
57
57
  .replace(/\b\w/g, (c) => c.toUpperCase())
58
58
 
59
- if (this.label && this.label.trim()) {
59
+ if (this.label?.trim()) {
60
60
  this.displayName = this.label.trim()
61
61
  } else {
62
62
  this.displayName = hostnamePretty || this.url
@@ -64,7 +64,7 @@ export class UrlView extends CoreLitElement {
64
64
  } catch {
65
65
  this.favicon = undefined
66
66
  // Fallback to raw string if URL parse fails
67
- this.displayName = this.label && this.label.trim() ? this.label : this.url
67
+ this.displayName = this.label?.trim() ? this.label : this.url
68
68
  }
69
69
  }
70
70
 
@@ -1,6 +1,6 @@
1
1
  import { Task } from '@lit/task'
2
2
  import { useAddressResolver } from '@lukso/transaction-view-headless'
3
- import { css, html } from 'lit'
3
+ import { html, type TemplateResult } from 'lit'
4
4
  import { property, state } from 'lit/decorators.js'
5
5
  import { when } from 'lit/directives/when.js'
6
6
  import { safeCustomElement } from './safe-custom-element'
@@ -8,21 +8,7 @@ import { safeCustomElement } from './safe-custom-element'
8
8
  // Import LUKSO web components
9
9
  import './load-web-components'
10
10
  import { CoreLitElement } from '../styles'
11
-
12
- // Value formatting utilities
13
- function formatUnits(value: bigint, decimals = 18): string {
14
- const divisor = 10n ** BigInt(decimals)
15
- const quotient = value / divisor
16
- const remainder = value % divisor
17
-
18
- if (remainder === 0n) {
19
- return quotient.toString()
20
- }
21
-
22
- const remainderStr = remainder.toString().padStart(decimals, '0')
23
- const trimmed = remainderStr.replace(/0+$/, '')
24
- return `${quotient}.${trimmed}`
25
- }
11
+ import { formatUnits } from '../utils'
26
12
 
27
13
  /**
28
14
  * Value display component
@@ -47,7 +33,7 @@ export class ValueView extends CoreLitElement {
47
33
  * The value to display (required)
48
34
  * Can be string, number, boolean, or bigint
49
35
  */
50
- @property() value?: string | number | boolean | bigint | null
36
+ @property() value?: TemplateResult | string | number | boolean | bigint | null
51
37
 
52
38
  /**
53
39
  * The key name (used for special formatting logic)
@@ -98,7 +84,7 @@ export class ValueView extends CoreLitElement {
98
84
  /**
99
85
  * Optional label to show in card header
100
86
  */
101
- @property() label?: string
87
+ @property() label?: string | TemplateResult
102
88
 
103
89
  /**
104
90
  * Maximum width for truncation
@@ -111,13 +97,6 @@ export class ValueView extends CoreLitElement {
111
97
  */
112
98
  @property() address?: string
113
99
 
114
- // Internal state for resolved metadata
115
- @state() private resolvedMetadata?: {
116
- symbol?: string
117
- decimals?: number
118
- name?: string
119
- }
120
-
121
100
  // Tracks whether the component has any slotted content
122
101
  @state() private _hasSlotContent = false
123
102
 
@@ -219,15 +198,16 @@ export class ValueView extends CoreLitElement {
219
198
  if (value === undefined) return 'undefined'
220
199
 
221
200
  switch (effectiveType) {
222
- case 'currency':
201
+ case 'currency': {
223
202
  const { numeric, symbol } = this.getCurrencyParts()
224
203
  return `${numeric} ${symbol}`
204
+ }
225
205
 
226
206
  case 'bigint':
227
207
  if (typeof value === 'bigint') {
228
- return value.toString() + 'n'
208
+ return `${value.toString()}n`
229
209
  }
230
- return String(value) + 'n'
210
+ return `${String(value)}n`
231
211
 
232
212
  case 'boolean':
233
213
  return value ? 'true' : 'false'
@@ -270,7 +250,7 @@ export class ValueView extends CoreLitElement {
270
250
  try {
271
251
  if (typeof value === 'bigint') {
272
252
  numeric = formatUnits(value, effectiveDecimals)
273
- } else if (typeof value === 'string' && !isNaN(Number(value))) {
253
+ } else if (typeof value === 'string' && !Number.isNaN(Number(value))) {
274
254
  const bigintValue = BigInt(value)
275
255
  numeric = formatUnits(bigintValue, effectiveDecimals)
276
256
  }
@@ -386,7 +366,7 @@ export class ValueView extends CoreLitElement {
386
366
 
387
367
  if (effectiveType === 'currency') {
388
368
  const { numeric, symbol } = this.getCurrencyParts()
389
- if (this.label && this.label.trim() !== '') {
369
+ if (this.label) {
390
370
  headerText = this.label
391
371
  contentTemplate = html`
392
372
  <span class="inline-block overflow-hidden text-ellipsis whitespace-nowrap min-w-0 ${this.getNumericClass()}">${numeric}</span>
@@ -1 +1 @@
1
- @import "@lukso/web-components/dist/styles/main.css";
1
+ @import "@lukso/web-components/tools/styles/main.css";
@@ -0,0 +1,47 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { formatUnits, parseBigInt } from './utils.js'
3
+
4
+ describe('formatUnits', () => {
5
+ it('returns integer string when remainder is zero', () => {
6
+ expect(formatUnits(1000000000000000000n)).toBe('1')
7
+ expect(formatUnits(5000n, 3)).toBe('5')
8
+ })
9
+
10
+ it('formats values with fractional part respecting decimals', () => {
11
+ expect(formatUnits(123000000000000000n)).toBe('0.123')
12
+ expect(formatUnits(987654321n, 6)).toBe('987.654321')
13
+ })
14
+
15
+ it('trims trailing zeros in fractional part', () => {
16
+ expect(formatUnits(120n, 2)).toBe('1.2')
17
+ expect(formatUnits(1001000n, 6)).toBe('1.001')
18
+ })
19
+
20
+ it('handles zero value', () => {
21
+ expect(formatUnits(0n)).toBe('0')
22
+ })
23
+ })
24
+
25
+ describe('parseBigInt', () => {
26
+ it('parses decimal and hex strings with optional suffix', () => {
27
+ expect(parseBigInt('42')).toBe(42n)
28
+ expect(parseBigInt('0x10')).toBe(16n)
29
+ expect(parseBigInt('21n')).toBe(21n)
30
+ expect(parseBigInt(' 0xFFn ')).toBe(255n)
31
+ })
32
+
33
+ it('returns bigint directly or from integer numbers', () => {
34
+ const value = 123n
35
+ expect(parseBigInt(value)).toBe(value)
36
+ expect(parseBigInt(9007199254740991)).toBe(9007199254740991n)
37
+ })
38
+
39
+ it('returns undefined for invalid inputs', () => {
40
+ expect(parseBigInt('')).toBeUndefined()
41
+ expect(parseBigInt('1.5')).toBeUndefined()
42
+ expect(parseBigInt('0xG')).toBeUndefined()
43
+ expect(parseBigInt(1.1)).toBeUndefined()
44
+ expect(parseBigInt(null)).toBeUndefined()
45
+ expect(parseBigInt(undefined)).toBeUndefined()
46
+ })
47
+ })
package/src/utils.ts ADDED
@@ -0,0 +1,82 @@
1
+ // Value formatting utilities
2
+ /**
3
+ * Convert a token amount from base units (bigint) to a decimal string.
4
+ *
5
+ * - Handles arbitrary `decimals` without floating point precision loss.
6
+ * - Trims trailing zeros in the fractional part.
7
+ * - Returns only the integer part when remainder is zero.
8
+ *
9
+ * @param value - The amount in base units as a bigint (e.g., wei for ETH).
10
+ * @param decimals - Number of decimal places the token uses (default 18).
11
+ * @returns A human-readable decimal string.
12
+ *
13
+ * @example
14
+ * // 1 ether in wei
15
+ * formatUnits(1000000000000000000n) // '1'
16
+ *
17
+ * @example
18
+ * // 1.23 tokens with 2 decimals
19
+ * formatUnits(123n, 2) // '1.23'
20
+ *
21
+ * @example
22
+ * // No remainder: return integer part only
23
+ * formatUnits(2000000000000000000n) // '2'
24
+ */
25
+ export function formatUnits(value: bigint, decimals = 18): string {
26
+ const divisor = 10n ** BigInt(decimals)
27
+ const quotient = value / divisor
28
+ const remainder = value % divisor
29
+
30
+ if (remainder === 0n) {
31
+ return quotient.toString()
32
+ }
33
+
34
+ const remainderStr = remainder.toString().padStart(decimals, '0')
35
+ const trimmed = remainderStr.replace(/0+$/, '')
36
+ return `${quotient}.${trimmed}`
37
+ }
38
+
39
+ function isBigIntString(str: string): boolean {
40
+ const trimmed = str.trim()
41
+ if (trimmed.endsWith('n'))
42
+ return /^[0-9]+n$/.test(trimmed) || /^0x[0-9a-fA-F]+n$/.test(trimmed)
43
+ return /^[0-9]+$/.test(trimmed) || /^0x[0-9a-fA-F]+$/.test(trimmed)
44
+ }
45
+
46
+ /**
47
+ * Parse loose bigint inputs coming from attributes, JSON, or user input.
48
+ *
49
+ * - Accepts bigint literals (`123n`), decimal/hex strings, and integers.
50
+ * - Trims whitespace and optional trailing `n` suffix.
51
+ * - Returns `undefined` for invalid formats (floats, empty strings, non-numeric text).
52
+ *
53
+ * @param value - Source value to parse (string | number | bigint | null | undefined).
54
+ * @returns BigInt when parsing succeeds, otherwise `undefined`.
55
+ *
56
+ * @example
57
+ * parseBigInt('42') // 42n
58
+ * @example
59
+ * parseBigInt('0x10n') // 16n
60
+ * @example
61
+ * parseBigInt(1000n) // 1000n (passthrough)
62
+ * @example
63
+ * parseBigInt('1.5') // undefined (decimals not allowed)
64
+ */
65
+ export function parseBigInt(
66
+ value: string | number | bigint | null | undefined
67
+ ): bigint | undefined {
68
+ if (!value) return undefined
69
+ if (typeof value === 'bigint') return value
70
+ if (typeof value === 'number') {
71
+ if (!Number.isInteger(value)) return undefined
72
+ return BigInt(value)
73
+ }
74
+ const trimmed = value.trim()
75
+ const cleaned = trimmed.endsWith('n') ? trimmed.slice(0, -1) : trimmed
76
+ if (!isBigIntString(cleaned)) return undefined
77
+ try {
78
+ return BigInt(cleaned)
79
+ } catch {
80
+ return undefined
81
+ }
82
+ }
package/src/vue-entry.ts CHANGED
@@ -12,4 +12,3 @@ export type {
12
12
  // Also re-export the core functionality
13
13
  export * from './registry/index.js'
14
14
  export * from './shared/index.js'
15
- export * from './vue/index.js'
package/tsup.config.ts CHANGED
@@ -1,6 +1,6 @@
1
+ import { readFileSync } from 'node:fs'
2
+ import { dirname, resolve } from 'node:path'
1
3
  import autoprefixer from 'autoprefixer'
2
- import { readFileSync } from 'fs'
3
- import { dirname, resolve } from 'path'
4
4
  import postcss from 'postcss'
5
5
  import postcssImport from 'postcss-import'
6
6
  import tailwindcss from 'tailwindcss'
@@ -37,7 +37,7 @@ export default defineConfig({
37
37
  // Return with a special virtual path marker that the onLoad hook can recognize
38
38
  // Use 'file' namespace to ensure esbuild calls our onLoad handler
39
39
  return {
40
- path: resolvedPath + '?__raw__',
40
+ path: `${resolvedPath}?__raw__`,
41
41
  namespace: 'file',
42
42
  }
43
43
  })