@1001-digital/components 0.0.2 → 0.0.4

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1001-digital/components",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "type": "module",
5
5
  "sideEffects": [
6
6
  "*.css"
@@ -13,16 +13,12 @@
13
13
  "src"
14
14
  ],
15
15
  "peerDependencies": {
16
- "@wagmi/core": ">=3.0.0",
17
- "@wagmi/vue": ">=0.4.0",
16
+ "@wagmi/vue": ">=0.5.0",
18
17
  "viem": ">=2.0.0",
19
18
  "vue": "^3.5.0",
20
- "@1001-digital/styles": "^0.0.1"
19
+ "@1001-digital/styles": "^0.0.2"
21
20
  },
22
21
  "peerDependenciesMeta": {
23
- "@wagmi/core": {
24
- "optional": true
25
- },
26
22
  "@wagmi/vue": {
27
23
  "optional": true
28
24
  },
@@ -250,9 +250,10 @@ const onClickOutside = () => {
250
250
  > footer {
251
251
  display: flex;
252
252
  gap: var(--spacer);
253
- justify-content: flex-end;
253
+ justify-content: safe flex-end;
254
254
  padding: var(--spacer);
255
255
  border-block-start: var(--border);
256
+ overflow-x: auto;
256
257
 
257
258
  &:empty {
258
259
  display: none;
@@ -13,6 +13,11 @@
13
13
  @update:open="(open) => !open && onClose(toast.id)"
14
14
  >
15
15
  <ToastTitle class="toast-title">
16
+ <span
17
+ v-if="toast.loading"
18
+ class="toast-spinner"
19
+ aria-hidden="true"
20
+ />
16
21
  {{ toast.title }}
17
22
  </ToastTitle>
18
23
  <ToastClose
@@ -37,7 +42,7 @@
37
42
  class="left"
38
43
  >
39
44
  <Button
40
- class="small"
45
+ class="small tertiary"
41
46
  @click="toast.action!.onClick()"
42
47
  >
43
48
  {{ toast.action.label }}
@@ -211,6 +216,7 @@ const onClose = (id: string) => {
211
216
  .toast-title {
212
217
  display: flex;
213
218
  align-items: center;
219
+ gap: var(--spacer-sm);
214
220
  block-size: calc(var(--spacer) * 2);
215
221
  box-shadow: var(--border-shadow);
216
222
  padding-inline-start: var(--ui-padding-inline);
@@ -222,6 +228,16 @@ const onClose = (id: string) => {
222
228
  margin: 0;
223
229
  }
224
230
 
231
+ .toast-spinner {
232
+ width: var(--ui-font-size);
233
+ height: var(--ui-font-size);
234
+ border: 2px solid currentColor;
235
+ border-top-color: transparent;
236
+ border-radius: 50%;
237
+ animation: spin var(--speed-slow, 1s) linear infinite;
238
+ flex-shrink: 0;
239
+ }
240
+
225
241
  > section {
226
242
  padding: var(--ui-padding-inline);
227
243
  display: grid;
@@ -250,5 +266,11 @@ const onClose = (id: string) => {
250
266
  }
251
267
  }
252
268
  }
269
+
270
+ @keyframes spin {
271
+ to {
272
+ transform: rotate(360deg);
273
+ }
274
+ }
253
275
  }
254
276
  </style>
@@ -14,6 +14,7 @@ export interface Toast {
14
14
  variant?: ToastVariant
15
15
  action?: ToastAction
16
16
  duration?: number
17
+ loading?: boolean
17
18
  }
18
19
 
19
20
  const toasts = ref<Toast[]>([])
@@ -22,13 +22,7 @@
22
22
  :txt="text.lead[step] || ''"
23
23
  />
24
24
 
25
- <p
26
- v-if="
27
- step !== 'requesting' &&
28
- step !== 'error' &&
29
- text.lead[step]
30
- "
31
- >
25
+ <p v-if="step !== 'requesting' && step !== 'error' && text.lead[step]">
32
26
  {{ text.lead[step] }}
33
27
  </p>
34
28
 
@@ -203,9 +197,7 @@ onBeforeUnmount(() => {
203
197
  })
204
198
 
205
199
  const canDismiss = computed(
206
- () =>
207
- props.dismissable &&
208
- step.value !== 'requesting',
200
+ () => props.dismissable && step.value !== 'requesting',
209
201
  )
210
202
 
211
203
  const initializeRequest = async (request = cachedRequest.value) => {
@@ -245,6 +237,7 @@ const initializeRequest = async (request = cachedRequest.value) => {
245
237
  title: text.value.title.waiting,
246
238
  description: text.value.lead.waiting,
247
239
  duration: Infinity,
240
+ loading: true,
248
241
  action: {
249
242
  label: 'View on Block Explorer',
250
243
  onClick: () => window.open(link, '_blank'),
@@ -264,6 +257,7 @@ const initializeRequest = async (request = cachedRequest.value) => {
264
257
  variant: 'success',
265
258
  title: text.value.title.complete,
266
259
  description: text.value.lead.complete,
260
+ loading: false,
267
261
  ...(props.autoCloseSuccess && { duration: props.delayAutoclose }),
268
262
  })
269
263
  } catch (e: unknown) {
@@ -277,6 +271,7 @@ const initializeRequest = async (request = cachedRequest.value) => {
277
271
  variant: 'error',
278
272
  title: text.value.title.error,
279
273
  description: err.shortMessage || 'Transaction failed.',
274
+ loading: false,
280
275
  })
281
276
  }
282
277
  console.log(e)
@@ -24,18 +24,19 @@ export const useBlockExplorer = (key?: string) =>
24
24
 
25
25
  export const useEnsureChainIdCheck = () => {
26
26
  const chainId = useMainChainId()
27
- const { mutate: switchChain } = useSwitchChain()
27
+ const { mutateAsync: switchChain } = useSwitchChain()
28
28
  const { chainId: currentChainId } = useConnection()
29
29
 
30
30
  return async () => {
31
- if (chainId !== currentChainId.value) {
32
- switchChain({ chainId })
33
- }
34
-
35
31
  if (chainId === currentChainId.value) {
36
32
  return true
37
33
  }
38
34
 
39
- return false
35
+ try {
36
+ await switchChain({ chainId })
37
+ return true
38
+ } catch {
39
+ return false
40
+ }
40
41
  }
41
42
  }
@@ -1,6 +1,12 @@
1
1
  import { getPublicClient } from '@wagmi/core'
2
2
  import type { Config } from '@wagmi/vue'
3
- import { ensCache, fetchEnsFromIndexer, fetchEnsFromChain, ENS_KEYS_AVATAR, ENS_KEYS_PROFILE } from '../utils/ens'
3
+ import {
4
+ ensCache,
5
+ fetchEnsFromIndexer,
6
+ fetchEnsFromChain,
7
+ ENS_KEYS_AVATAR,
8
+ ENS_KEYS_PROFILE,
9
+ } from '../utils/ens'
4
10
  import type { EnsProfile } from '../utils/ens'
5
11
 
6
12
  type EnsMode = 'indexer' | 'chain'
@@ -10,12 +16,14 @@ interface UseEnsOptions {
10
16
  }
11
17
 
12
18
  interface EnsRuntimeConfig {
13
- ens?: { indexer1?: string, indexer2?: string, indexer3?: string }
19
+ ens?: { indexer1?: string; indexer2?: string; indexer3?: string }
14
20
  }
15
21
 
16
22
  function getIndexerUrls(config: EnsRuntimeConfig): string[] {
17
23
  if (!config.ens) return []
18
- return [config.ens.indexer1, config.ens.indexer2, config.ens.indexer3].filter(Boolean) as string[]
24
+ return [config.ens.indexer1, config.ens.indexer2, config.ens.indexer3].filter(
25
+ Boolean,
26
+ ) as string[]
19
27
  }
20
28
 
21
29
  async function resolve(
@@ -55,8 +63,12 @@ function useEnsBase(
55
63
  const appConfig = useAppConfig()
56
64
  const runtimeConfig = useRuntimeConfig()
57
65
 
58
- const mode = computed<EnsMode>(() => toValue(options.mode) || appConfig.evm?.ens?.mode || 'indexer')
59
- const indexerUrls = computed(() => getIndexerUrls(runtimeConfig.public.evm as EnsRuntimeConfig))
66
+ const mode = computed<EnsMode>(
67
+ () => toValue(options.mode) || appConfig.evm?.ens?.mode || 'indexer',
68
+ )
69
+ const indexerUrls = computed(() =>
70
+ getIndexerUrls(runtimeConfig.public.evm as EnsRuntimeConfig),
71
+ )
60
72
  const cacheKey = computed(() => `ens-${tier}-${toValue(identifier)}`)
61
73
 
62
74
  return useAsyncData(
@@ -65,9 +77,8 @@ function useEnsBase(
65
77
  const id = toValue(identifier)
66
78
  if (!id) return null
67
79
 
68
- const strategies: EnsMode[] = mode.value === 'indexer'
69
- ? ['indexer', 'chain']
70
- : ['chain', 'indexer']
80
+ const strategies: EnsMode[] =
81
+ mode.value === 'indexer' ? ['indexer', 'chain'] : ['chain', 'indexer']
71
82
 
72
83
  return ensCache.fetch(cacheKey.value, () =>
73
84
  resolve(id, strategies, indexerUrls.value, $wagmi as Config, chainKeys),
@@ -80,11 +91,17 @@ function useEnsBase(
80
91
  )
81
92
  }
82
93
 
83
- export const useEns = (identifier: MaybeRefOrGetter<string | undefined>, options?: UseEnsOptions) =>
84
- useEnsBase('resolve', identifier, [], options)
94
+ export const useEns = (
95
+ identifier: MaybeRefOrGetter<string | undefined>,
96
+ options?: UseEnsOptions,
97
+ ) => useEnsBase('resolve', identifier, [], options)
85
98
 
86
- export const useEnsWithAvatar = (identifier: MaybeRefOrGetter<string | undefined>, options?: UseEnsOptions) =>
87
- useEnsBase('avatar', identifier, [...ENS_KEYS_AVATAR], options)
99
+ export const useEnsWithAvatar = (
100
+ identifier: MaybeRefOrGetter<string | undefined>,
101
+ options?: UseEnsOptions,
102
+ ) => useEnsBase('avatar', identifier, [...ENS_KEYS_AVATAR], options)
88
103
 
89
- export const useEnsProfile = (identifier: MaybeRefOrGetter<string | undefined>, options?: UseEnsOptions) =>
90
- useEnsBase('profile', identifier, [...ENS_KEYS_PROFILE], options)
104
+ export const useEnsProfile = (
105
+ identifier: MaybeRefOrGetter<string | undefined>,
106
+ options?: UseEnsOptions,
107
+ ) => useEnsBase('profile', identifier, [...ENS_KEYS_PROFILE], options)
@@ -25,9 +25,10 @@ export const useGasPrice = () => {
25
25
  eth: formatEther(price.value),
26
26
 
27
27
  formatted: {
28
- gwei: price.value > 2_000_000_000_000n
29
- ? Math.round(parseFloat(formatGwei(price.value)))
30
- : parseFloat(formatGwei(price.value)).toFixed(1),
28
+ gwei:
29
+ price.value > 2_000_000_000_000n
30
+ ? Math.round(parseFloat(formatGwei(price.value)))
31
+ : parseFloat(formatGwei(price.value)).toFixed(1),
31
32
  eth: formatEther(price.value),
32
33
  },
33
34
  }))
@@ -53,10 +53,13 @@ function saveToStorage() {
53
53
  if (typeof window === 'undefined') return
54
54
 
55
55
  try {
56
- localStorage.setItem(STORAGE_KEY, stringifyJSON({
57
- ethUSDRaw: state.ethUSDRaw,
58
- lastUpdated: state.lastUpdated,
59
- }))
56
+ localStorage.setItem(
57
+ STORAGE_KEY,
58
+ stringifyJSON({
59
+ ethUSDRaw: state.ethUSDRaw,
60
+ lastUpdated: state.lastUpdated,
61
+ }),
62
+ )
60
63
  } catch {
61
64
  // Ignore storage errors
62
65
  }
@@ -68,12 +71,18 @@ export const usePriceFeed = () => {
68
71
  // Load cached data on first use
69
72
  if (!state.lastUpdated) loadFromStorage()
70
73
 
71
- const ethUSD = computed(() => state.ethUSDRaw ? state.ethUSDRaw / BigInt(1e8) : 0n)
72
- const ethUSC = computed(() => state.ethUSDRaw ? state.ethUSDRaw / BigInt(1e6) : 0n)
73
- const ethUSDFormatted = computed(() => formatPrice(Number(ethUSC.value) / 100, 2))
74
+ const ethUSD = computed(() =>
75
+ state.ethUSDRaw ? state.ethUSDRaw / BigInt(1e8) : 0n,
76
+ )
77
+ const ethUSC = computed(() =>
78
+ state.ethUSDRaw ? state.ethUSDRaw / BigInt(1e6) : 0n,
79
+ )
80
+ const ethUSDFormatted = computed(() =>
81
+ formatPrice(Number(ethUSC.value) / 100, 2),
82
+ )
74
83
 
75
84
  const weiToUSD = (wei: bigint) => {
76
- const cents = (wei * (state.ethUSDRaw || 0n)) / (10n ** 18n) / (10n ** 6n)
85
+ const cents = (wei * (state.ethUSDRaw || 0n)) / 10n ** 18n / 10n ** 6n
77
86
  return formatPrice(Number(cents) / 100, 2)
78
87
  }
79
88
 
@@ -22,7 +22,15 @@ export interface EnsProfile {
22
22
 
23
23
  // --- Text record keys ---
24
24
 
25
- const ALL_KEYS = ['avatar', 'header', 'description', 'url', 'email', 'com.twitter', 'com.github'] as const
25
+ const ALL_KEYS = [
26
+ 'avatar',
27
+ 'header',
28
+ 'description',
29
+ 'url',
30
+ 'email',
31
+ 'com.twitter',
32
+ 'com.github',
33
+ ] as const
26
34
 
27
35
  export const ENS_KEYS_AVATAR = ['avatar'] as const
28
36
  export const ENS_KEYS_PROFILE = [...ALL_KEYS]
@@ -62,7 +70,7 @@ export async function fetchEnsFromChain(
62
70
 
63
71
  if (isAddr) {
64
72
  address = identifier
65
- ens = await client.getEnsName({ address: identifier as Address }) ?? null
73
+ ens = (await client.getEnsName({ address: identifier as Address })) ?? null
66
74
  } else {
67
75
  ens = identifier
68
76
  const resolved = await client.getEnsAddress({ name: normalize(identifier) })
@@ -74,10 +82,17 @@ export async function fetchEnsFromChain(
74
82
 
75
83
  const name = normalize(ens)
76
84
  const results = await Promise.all(
77
- keys.map(key => client.getEnsText({ name, key }).catch(() => null)),
85
+ keys.map((key) => client.getEnsText({ name, key }).catch(() => null)),
78
86
  )
79
87
 
80
- return { address, ens, data: toProfileData(keys, results.map(r => r || '')) }
88
+ return {
89
+ address,
90
+ ens,
91
+ data: toProfileData(
92
+ keys,
93
+ results.map((r) => r || ''),
94
+ ),
95
+ }
81
96
  }
82
97
 
83
98
  // --- Helpers ---
@@ -4,11 +4,13 @@ const replacer = (_: string, value: unknown) => {
4
4
  }
5
5
 
6
6
  const reviver = (_: string, value: unknown) => {
7
- if (typeof value === 'string' && /^\d+n$/.test(value)) return BigInt(value.slice(0, -1))
7
+ if (typeof value === 'string' && /^\d+n$/.test(value))
8
+ return BigInt(value.slice(0, -1))
8
9
  return value
9
10
  }
10
11
 
11
- export const stringifyJSON = (obj: unknown): string => JSON.stringify(obj, replacer)
12
+ export const stringifyJSON = (obj: unknown): string =>
13
+ JSON.stringify(obj, replacer)
12
14
  export const parseJSON = (json: string): unknown => JSON.parse(json, reviver)
13
15
 
14
16
  export const formatPrice = (num: number, digits: number = 2) =>