@fairmint/ui 0.3.1 → 0.3.3

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 (32) hide show
  1. package/dist/components/generic/DocumentRow/DocumentRow.cjs +297 -0
  2. package/dist/components/generic/DocumentRow/DocumentRow.cjs.map +1 -0
  3. package/dist/components/generic/DocumentRow/DocumentRow.d.ts +49 -0
  4. package/dist/components/generic/DocumentRow/DocumentRow.d.ts.map +1 -0
  5. package/dist/components/generic/DocumentRow/DocumentRow.js +297 -0
  6. package/dist/components/generic/DocumentRow/DocumentRow.js.map +1 -0
  7. package/dist/components/specific/WalletList/WalletList.cjs +129 -141
  8. package/dist/components/specific/WalletList/WalletList.cjs.map +1 -1
  9. package/dist/components/specific/WalletList/WalletList.d.ts +2 -10
  10. package/dist/components/specific/WalletList/WalletList.d.ts.map +1 -1
  11. package/dist/components/specific/WalletList/WalletList.js +131 -143
  12. package/dist/components/specific/WalletList/WalletList.js.map +1 -1
  13. package/dist/components/specific/WalletListItem/WalletListItem.cjs +161 -0
  14. package/dist/components/specific/WalletListItem/WalletListItem.cjs.map +1 -0
  15. package/dist/components/specific/WalletListItem/WalletListItem.d.ts +32 -0
  16. package/dist/components/specific/WalletListItem/WalletListItem.d.ts.map +1 -0
  17. package/dist/components/specific/WalletListItem/WalletListItem.js +161 -0
  18. package/dist/components/specific/WalletListItem/WalletListItem.js.map +1 -0
  19. package/dist/fairmint-ui.cjs +6 -0
  20. package/dist/fairmint-ui.cjs.map +1 -1
  21. package/dist/fairmint-ui.js +9 -3
  22. package/dist/fairmint-ui.js.map +1 -1
  23. package/dist/index.d.ts +9 -4
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/styles.css +2 -1
  26. package/dist/utils/wallets.cjs +18 -2
  27. package/dist/utils/wallets.cjs.map +1 -1
  28. package/dist/utils/wallets.d.ts +13 -0
  29. package/dist/utils/wallets.d.ts.map +1 -1
  30. package/dist/utils/wallets.js +18 -2
  31. package/dist/utils/wallets.js.map +1 -1
  32. package/package.json +1 -1
@@ -1,33 +1,20 @@
1
1
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
2
  import { useCallback, useState, useRef, useEffect } from "react";
3
3
  import { shadowColor, neutralColors, radii, fairmintVars } from "../../../theme/index.js";
4
- import { truncateAddress, validateEthereumAddress } from "../../../utils/address.js";
5
- import { getWalletDisplayName, getWalletKindPill, normalizeWalletType, isRemovableWalletType, walletKey } from "../../../utils/wallets.js";
4
+ import { validateEthereumAddress } from "../../../utils/address.js";
5
+ import { getWalletDisplayName, normalizeWalletType, isRemovableWalletType, getWalletIconColor, walletKey } from "../../../utils/wallets.js";
6
6
  import { ConfirmDialog } from "../../generic/ConfirmDialog/ConfirmDialog.js";
7
7
  import { EmptyState } from "../../generic/EmptyState/EmptyState.js";
8
8
  import { ActionIcon } from "../../primitives/ActionIcon/ActionIcon.js";
9
- import { Badge } from "../../primitives/Badge/Badge.js";
10
9
  import { Button } from "../../primitives/Button/Button.js";
11
10
  import { Stack } from "../../primitives/layout.js";
12
11
  import { Menu } from "../../primitives/Menu/Menu.js";
13
12
  import { TextInput } from "../../primitives/TextInput/TextInput.js";
13
+ import { WalletListItem } from "../WalletListItem/WalletListItem.js";
14
14
  import { Text } from "../../../node_modules/@mantine/core/esm/components/Text/Text.js";
15
15
  import { colors } from "../../../theme/colors.js";
16
16
  import { Group } from "../../../node_modules/@mantine/core/esm/components/Group/Group.js";
17
17
  import { ThemeIcon } from "../../../node_modules/@mantine/core/esm/components/ThemeIcon/ThemeIcon.js";
18
- function getWalletIconColor(type) {
19
- const key = normalizeWalletType(type).replace(/_/g, " ");
20
- if (key === "fairmint" || key === "privy") return colors.primary;
21
- if (key === "metamask") return colors.warning;
22
- if (key === "coinbase wallet" || key === "coinbase smart wallet" || key === "coinbase custody")
23
- return colors.info;
24
- if (key === "phantom") return colors.brandPurple;
25
- if (key === "rainbow") return colors.accent2;
26
- if (key === "manual") return colors.neutral;
27
- if (key === "anchorage" || key === "bitgo" || key === "gemini custody" || key === "ledger vault" || key === "fireblocks")
28
- return colors.success;
29
- return colors.neutral;
30
- }
31
18
  function WalletList({
32
19
  wallets,
33
20
  onAdd,
@@ -88,15 +75,18 @@ function WalletList({
88
75
  setLabelError(null);
89
76
  }
90
77
  }, [wallets, renamingAddress, normalizeWalletAddress]);
91
- const copyAddress = useCallback(async (address) => {
92
- try {
93
- await navigator.clipboard.writeText(address);
94
- clearTimeout(copyTimeoutRef.current);
95
- setCopiedAddress(address);
96
- copyTimeoutRef.current = setTimeout(() => setCopiedAddress(null), 2e3);
97
- } catch {
98
- }
99
- }, []);
78
+ const copyAddress = useCallback(
79
+ async (address) => {
80
+ try {
81
+ await navigator.clipboard.writeText(address);
82
+ clearTimeout(copyTimeoutRef.current);
83
+ setCopiedAddress(normalizeWalletAddress(address));
84
+ copyTimeoutRef.current = setTimeout(() => setCopiedAddress(null), 2e3);
85
+ } catch {
86
+ }
87
+ },
88
+ [normalizeWalletAddress]
89
+ );
100
90
  const canAdd = !readOnly && !!onAdd;
101
91
  const canRemove = !readOnly && !!onRemove;
102
92
  const canSetDefault = !readOnly && !!onSetDefault;
@@ -197,16 +187,16 @@ function WalletList({
197
187
  return /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
198
188
  wallets.map((w) => {
199
189
  const normalizedWalletAddress = normalizeWalletAddress(w.address);
190
+ const isCopied = copiedAddress === normalizedWalletAddress;
200
191
  const setDefaultActionLoading = setDefaultLoading && (!setDefaultAddress || normalizeWalletAddress(setDefaultAddress) === normalizedWalletAddress);
201
192
  const labelActionLoading = labelLoading && (!labelAddress || normalizeWalletAddress(labelAddress) === normalizedWalletAddress);
202
193
  const explorerUrl = getSafeExplorerUrl(w.address);
203
194
  const isRenaming = normalizeWalletAddress(renamingAddress ?? "") === normalizedWalletAddress;
204
195
  const displayName = getWalletDisplayName(w, typeLabels);
205
- const kindPill = getWalletKindPill(w.type, typeLabels);
206
196
  const isDefault = !!w.defaultRecipient;
207
197
  const canBeRemoved = canRemove && (removableTypes ? removableTypes.some((t) => normalizeWalletType(t) === normalizeWalletType(w.type)) : isRemovableWalletType(w.type));
208
198
  const hasMenuActions = canSetDefault && !!defaultIcon && !isDefault || canLabel && !!renameIcon || !!explorerUrl && !!explorerIcon || canBeRemoved && !!removeIcon;
209
- return /* @__PURE__ */ jsx(Stack, { gap: 0, children: /* @__PURE__ */ jsxs(
199
+ return /* @__PURE__ */ jsx(Stack, { gap: 0, children: isRenaming ? /* @__PURE__ */ jsx(
210
200
  Group,
211
201
  {
212
202
  justify: "space-between",
@@ -219,144 +209,142 @@ function WalletList({
219
209
  background: "transparent",
220
210
  boxShadow: `0 1px 3px ${shadowColor.card}`
221
211
  },
222
- children: [
223
- /* @__PURE__ */ jsxs(Group, { gap: "sm", align: "flex-start", wrap: "nowrap", style: { flex: 1, minWidth: 0 }, children: [
224
- walletIcon && /* @__PURE__ */ jsx(
225
- ThemeIcon,
212
+ children: /* @__PURE__ */ jsxs(Group, { gap: "sm", align: "flex-start", wrap: "nowrap", style: { flex: 1, minWidth: 0 }, children: [
213
+ walletIcon && /* @__PURE__ */ jsx(
214
+ ThemeIcon,
215
+ {
216
+ size: 40,
217
+ radius: "xl",
218
+ variant: "light",
219
+ color: getWalletIconColor(w.type),
220
+ style: { flexShrink: 0 },
221
+ children: walletIcon
222
+ }
223
+ ),
224
+ /* @__PURE__ */ jsxs(Stack, { gap: 6, style: { flex: 1, minWidth: 0 }, children: [
225
+ /* @__PURE__ */ jsx(
226
+ TextInput,
226
227
  {
227
- size: 40,
228
- radius: "xl",
229
- variant: "light",
230
- color: getWalletIconColor(w.type),
231
- style: { flexShrink: 0 },
232
- children: walletIcon
228
+ value: renameValue,
229
+ onChange: (e) => {
230
+ setRenameValue(e.currentTarget.value);
231
+ setLabelError(null);
232
+ },
233
+ placeholder: displayName,
234
+ size: "xs",
235
+ "aria-label": "Wallet label",
236
+ maxLength: 50,
237
+ error: labelError ?? void 0,
238
+ autoFocus: true
233
239
  }
234
240
  ),
235
- isRenaming ? /* @__PURE__ */ jsxs(Stack, { gap: 6, style: { flex: 1, minWidth: 0 }, children: [
241
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
236
242
  /* @__PURE__ */ jsx(
237
- TextInput,
243
+ Button,
238
244
  {
239
- value: renameValue,
240
- onChange: (e) => {
241
- setRenameValue(e.currentTarget.value);
242
- setLabelError(null);
243
- },
244
- placeholder: getWalletDisplayName(w, typeLabels),
245
245
  size: "xs",
246
- "aria-label": "Wallet label",
247
- maxLength: 50,
248
- error: labelError ?? void 0,
249
- autoFocus: true
246
+ loading: labelActionLoading,
247
+ disabled: labelActionLoading,
248
+ onClick: () => handleLabelSave(w.address),
249
+ children: "Save"
250
250
  }
251
251
  ),
252
- /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
253
- /* @__PURE__ */ jsx(
254
- Button,
255
- {
256
- size: "xs",
257
- loading: labelActionLoading,
258
- disabled: labelActionLoading,
259
- onClick: () => handleLabelSave(w.address),
260
- children: "Save"
261
- }
262
- ),
263
- /* @__PURE__ */ jsx(
264
- Button,
265
- {
266
- size: "xs",
267
- variant: "subtle",
268
- color: colors.neutral,
269
- onClick: () => {
270
- setRenamingAddress(null);
271
- setLabelError(null);
272
- },
273
- children: "Cancel"
274
- }
275
- )
276
- ] })
277
- ] }) : /* @__PURE__ */ jsxs(Stack, { gap: 4, style: { flex: 1, minWidth: 0 }, children: [
278
- /* @__PURE__ */ jsxs(Group, { gap: "xs", align: "center", wrap: "wrap", children: [
279
- /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, style: { wordBreak: "break-word" }, children: displayName }),
280
- isDefault && /* @__PURE__ */ jsx(Badge, { size: "xs", color: colors.warning, variant: "light", tt: "uppercase", children: "Default" }),
281
- /* @__PURE__ */ jsx(Badge, { size: "xs", variant: "light", color: colors.neutral, children: kindPill })
282
- ] }),
283
- /* @__PURE__ */ jsx(Text, { size: "xs", ff: "monospace", c: fairmintVars.colorTextSecondary, children: truncateAddress(w.address) })
252
+ /* @__PURE__ */ jsx(
253
+ Button,
254
+ {
255
+ size: "xs",
256
+ variant: "subtle",
257
+ color: colors.neutral,
258
+ onClick: () => {
259
+ setRenamingAddress(null);
260
+ setLabelError(null);
261
+ },
262
+ children: "Cancel"
263
+ }
264
+ )
284
265
  ] })
285
- ] }),
286
- !isRenaming && /* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "nowrap", style: { flexShrink: 0 }, children: [
287
- copyIcon && /* @__PURE__ */ jsx(
266
+ ] })
267
+ ] })
268
+ }
269
+ ) : /* @__PURE__ */ jsx(
270
+ WalletListItem,
271
+ {
272
+ wallet: w,
273
+ typeLabels,
274
+ walletIcon,
275
+ rightSection: /* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "nowrap", style: { flexShrink: 0 }, children: [
276
+ copyIcon && /* @__PURE__ */ jsx(
277
+ ActionIcon,
278
+ {
279
+ variant: "subtle",
280
+ size: "sm",
281
+ color: isCopied ? colors.success : colors.neutral,
282
+ onClick: () => copyAddress(w.address),
283
+ "aria-label": "Copy wallet address",
284
+ title: isCopied ? "Copied!" : "Copy address",
285
+ children: isCopied ? copiedIcon ?? copyIcon : copyIcon
286
+ }
287
+ ),
288
+ hasMenuActions && /* @__PURE__ */ jsxs(Menu, { position: "bottom-end", withinPortal: true, children: [
289
+ /* @__PURE__ */ jsx(Menu.Target, { children: /* @__PURE__ */ jsx(
288
290
  ActionIcon,
289
291
  {
290
292
  variant: "subtle",
291
293
  size: "sm",
292
- color: copiedAddress === w.address ? colors.success : colors.neutral,
293
- onClick: () => copyAddress(w.address),
294
- "aria-label": "Copy wallet address",
295
- title: copiedAddress === w.address ? "Copied!" : "Copy address",
296
- children: copiedAddress === w.address ? copiedIcon ?? copyIcon : copyIcon
294
+ color: colors.neutral,
295
+ "aria-label": "Wallet actions",
296
+ children: menuIcon ?? /* @__PURE__ */ jsx(Text, { size: "xs", fw: 700, lh: 1, c: fairmintVars.colorTextSecondary, children: "•••" })
297
297
  }
298
- ),
299
- hasMenuActions && /* @__PURE__ */ jsxs(Menu, { position: "bottom-end", withinPortal: true, children: [
300
- /* @__PURE__ */ jsx(Menu.Target, { children: /* @__PURE__ */ jsx(
301
- ActionIcon,
298
+ ) }),
299
+ /* @__PURE__ */ jsxs(Menu.Dropdown, { children: [
300
+ canSetDefault && defaultIcon && !isDefault && /* @__PURE__ */ jsx(
301
+ Menu.Item,
302
302
  {
303
- variant: "subtle",
304
- size: "sm",
305
- color: colors.neutral,
306
- "aria-label": "Wallet actions",
307
- children: menuIcon ?? /* @__PURE__ */ jsx(Text, { size: "xs", fw: 700, lh: 1, c: fairmintVars.colorTextSecondary, children: "•••" })
303
+ leftSection: defaultIcon,
304
+ onClick: () => handleSetDefault(w.address),
305
+ disabled: setDefaultActionLoading,
306
+ children: "Set as default"
308
307
  }
309
- ) }),
310
- /* @__PURE__ */ jsxs(Menu.Dropdown, { children: [
311
- canSetDefault && defaultIcon && !isDefault && /* @__PURE__ */ jsx(
312
- Menu.Item,
313
- {
314
- leftSection: defaultIcon,
315
- onClick: () => handleSetDefault(w.address),
316
- disabled: setDefaultActionLoading,
317
- children: "Set as default"
318
- }
319
- ),
320
- canLabel && renameIcon && /* @__PURE__ */ jsx(
321
- Menu.Item,
322
- {
323
- leftSection: renameIcon,
324
- onClick: () => {
325
- setLabelError(null);
326
- setRenamingAddress(w.address);
327
- setRenameValue(w.label ?? "");
328
- },
329
- children: "Rename"
330
- }
331
- ),
332
- explorerUrl && explorerIcon && /* @__PURE__ */ jsx(
308
+ ),
309
+ canLabel && renameIcon && /* @__PURE__ */ jsx(
310
+ Menu.Item,
311
+ {
312
+ leftSection: renameIcon,
313
+ onClick: () => {
314
+ setLabelError(null);
315
+ setRenamingAddress(w.address);
316
+ setRenameValue(w.label ?? "");
317
+ },
318
+ children: "Rename"
319
+ }
320
+ ),
321
+ explorerUrl && explorerIcon && /* @__PURE__ */ jsx(
322
+ Menu.Item,
323
+ {
324
+ leftSection: explorerIcon,
325
+ component: "a",
326
+ href: explorerUrl,
327
+ target: "_blank",
328
+ rel: "noopener noreferrer",
329
+ children: "View on explorer"
330
+ }
331
+ ),
332
+ canBeRemoved && removeIcon && /* @__PURE__ */ jsxs(Fragment, { children: [
333
+ /* @__PURE__ */ jsx(Menu.Divider, {}),
334
+ /* @__PURE__ */ jsx(
333
335
  Menu.Item,
334
336
  {
335
- leftSection: explorerIcon,
336
- component: "a",
337
- href: explorerUrl,
338
- target: "_blank",
339
- rel: "noopener noreferrer",
340
- children: "View on explorer"
337
+ leftSection: removeIcon,
338
+ color: colors.error,
339
+ onClick: () => setWalletToRemove(w.address),
340
+ disabled: removeLoading,
341
+ children: "Remove wallet"
341
342
  }
342
- ),
343
- canBeRemoved && removeIcon && /* @__PURE__ */ jsxs(Fragment, { children: [
344
- /* @__PURE__ */ jsx(Menu.Divider, {}),
345
- /* @__PURE__ */ jsx(
346
- Menu.Item,
347
- {
348
- leftSection: removeIcon,
349
- color: colors.error,
350
- onClick: () => setWalletToRemove(w.address),
351
- disabled: removeLoading,
352
- children: "Remove wallet"
353
- }
354
- )
355
- ] })
343
+ )
356
344
  ] })
357
345
  ] })
358
346
  ] })
359
- ]
347
+ ] })
360
348
  }
361
349
  ) }, walletKey(w));
362
350
  }),
@@ -1 +1 @@
1
- {"version":3,"file":"WalletList.js","sources":["../../../../src/components/specific/WalletList/WalletList.tsx"],"sourcesContent":["import { type ReactNode, useCallback, useEffect, useRef, useState } from \"react\";\nimport { colors, fairmintVars, neutralColors, radii, shadowColor } from \"../../../theme\";\nimport { truncateAddress, validateEthereumAddress } from \"../../../utils/address\";\nimport {\n getWalletDisplayName,\n getWalletKindPill,\n isRemovableWalletType,\n normalizeWalletType,\n walletKey,\n} from \"../../../utils/wallets\";\nimport { ConfirmDialog } from \"../../generic/ConfirmDialog/ConfirmDialog\";\nimport { EmptyState } from \"../../generic/EmptyState/EmptyState\";\nimport { ActionIcon } from \"../../primitives/ActionIcon/ActionIcon\";\nimport { Badge } from \"../../primitives/Badge/Badge\";\nimport { Button } from \"../../primitives/Button/Button\";\nimport { Group, Stack, Text, ThemeIcon } from \"../../primitives/layout\";\nimport { Menu } from \"../../primitives/Menu/Menu\";\nimport { TextInput } from \"../../primitives/TextInput/TextInput\";\n\n/**\n * Map wallet type → ThemeIcon color for instant visual differentiation.\n * Falls back to neutral for unknown types.\n */\nfunction getWalletIconColor(type: unknown): string {\n // Normalize to lowercase with spaces so both \"coinbase_custody\" and \"coinbase custody\" match.\n const key = normalizeWalletType(type).replace(/_/g, \" \");\n if (key === \"fairmint\" || key === \"privy\") return colors.primary;\n if (key === \"metamask\") return colors.warning;\n if (key === \"coinbase wallet\" || key === \"coinbase smart wallet\" || key === \"coinbase custody\")\n return colors.info;\n if (key === \"phantom\") return colors.brandPurple;\n if (key === \"rainbow\") return colors.accent2;\n if (key === \"manual\") return colors.neutral;\n if (\n key === \"anchorage\" ||\n key === \"bitgo\" ||\n key === \"gemini custody\" ||\n key === \"ledger vault\" ||\n key === \"fireblocks\"\n )\n return colors.success;\n return colors.neutral;\n}\n\nexport interface Wallet {\n /** Ethereum wallet address. */\n address: string;\n /** Wallet type identifier (e.g. \"fairmint\", \"privy\", \"manual\"). */\n type: string;\n /** Optional display label. */\n label?: string | null;\n /** Whether this is the default equity recipient wallet. */\n defaultRecipient?: boolean;\n}\n\nexport interface WalletListProps {\n /** Wallets to display. */\n wallets: Wallet[];\n /** Called when user adds a new wallet address. */\n onAdd?: (address: string) => void | Promise<void>;\n /** Called when user confirms removal of a wallet address. */\n onRemove?: (address: string) => void | Promise<void>;\n /** Called when user sets a wallet as default recipient. */\n onSetDefault?: (address: string) => void | Promise<void>;\n /** Called when user saves a label for a wallet. Null clears the label. May reject — label error is displayed inline. */\n onLabel?: (address: string, label: string | null) => void | Promise<void>;\n /** Called when user clicks the connect wallet button (Privy linking). */\n onConnect?: () => void;\n /** Returns a block explorer URL for a wallet address. If omitted, explorer link is hidden. */\n getExplorerUrl?: (address: string) => string;\n /** Whether add/remove/edit actions are disabled (e.g. admin viewing another user). */\n readOnly?: boolean;\n /** Whether an add operation is in progress. */\n addLoading?: boolean;\n /** Whether a remove operation is in progress. */\n removeLoading?: boolean;\n /** Whether a set-default operation is in progress. */\n setDefaultLoading?: boolean;\n /** Address of the wallet currently being set as default (for per-row loading). */\n setDefaultAddress?: string;\n /** Whether a label operation is in progress. */\n labelLoading?: boolean;\n /** Address of the wallet currently being labeled (for per-row loading). */\n labelAddress?: string;\n /** Whether the connect wallet operation is in progress. */\n connectLoading?: boolean;\n /** Icon for the empty state. Passed as ReactNode. */\n emptyIcon?: ReactNode;\n /** Icon for the copy button. Passed as ReactNode. */\n copyIcon?: ReactNode;\n /** Icon for the \"copied\" state. Passed as ReactNode. */\n copiedIcon?: ReactNode;\n /** Icon for the remove button. Passed as ReactNode. */\n removeIcon?: ReactNode;\n /** Icon for the add button. Passed as ReactNode. */\n addIcon?: ReactNode;\n /** Icon for the set-default button. Passed as ReactNode. */\n defaultIcon?: ReactNode;\n /** Icon for the rename button. Passed as ReactNode. */\n renameIcon?: ReactNode;\n /** Icon for the block explorer link. Passed as ReactNode. */\n explorerIcon?: ReactNode;\n /** Icon for the connect wallet button. Passed as ReactNode. */\n connectIcon?: ReactNode;\n /** Icon for the overflow (kebab) menu trigger. Passed as ReactNode. */\n menuIcon?: ReactNode;\n /**\n * Override default type → label mapping.\n * @default Built-in: \"fairmint\"|\"privy\" → \"Fairmint Wallet\", \"manual\" → \"Manual\", else as-is\n */\n typeLabels?: Record<string, string>;\n /**\n * Which wallet types can be removed. Overrides the default system-type check.\n * @default All non-system types (everything except \"fairmint\" and \"privy\")\n */\n removableTypes?: string[];\n /** Additional content rendered below the wallet list (e.g. advanced wallet forms). */\n children?: ReactNode;\n /** Optional icon shown in a circle at the start of each wallet row. */\n walletIcon?: ReactNode;\n}\n\nexport function WalletList({\n wallets,\n onAdd,\n onRemove,\n onSetDefault,\n onLabel,\n onConnect,\n getExplorerUrl,\n readOnly = false,\n addLoading = false,\n removeLoading = false,\n setDefaultLoading = false,\n setDefaultAddress,\n labelLoading = false,\n labelAddress,\n connectLoading = false,\n emptyIcon,\n copyIcon,\n copiedIcon,\n removeIcon,\n addIcon,\n defaultIcon,\n renameIcon,\n explorerIcon,\n connectIcon,\n menuIcon,\n typeLabels,\n removableTypes,\n children,\n walletIcon,\n}: WalletListProps) {\n const normalizeWalletAddress = useCallback(\n (address: string | undefined) => address?.trim().toLowerCase() ?? \"\",\n [],\n );\n const [newAddress, setNewAddress] = useState(\"\");\n const [newLabel, setNewLabel] = useState(\"\");\n const [addressError, setAddressError] = useState<string | null>(null);\n const [showAddForm, setShowAddForm] = useState(false);\n const [walletToRemove, setWalletToRemove] = useState<string | null>(null);\n const [copiedAddress, setCopiedAddress] = useState<string | null>(null);\n const [renamingAddress, setRenamingAddress] = useState<string | null>(null);\n const [renameValue, setRenameValue] = useState(\"\");\n const [labelError, setLabelError] = useState<string | null>(null);\n const [setDefaultError, setSetDefaultError] = useState<string | null>(null);\n const copyTimeoutRef = useRef<ReturnType<typeof setTimeout>>(undefined);\n\n useEffect(() => () => clearTimeout(copyTimeoutRef.current), []);\n\n useEffect(() => {\n if (readOnly) setRenamingAddress(null);\n }, [readOnly]);\n\n useEffect(() => {\n if (!renamingAddress) return;\n const normalized = normalizeWalletAddress(renamingAddress);\n const stillExists = wallets.some((w) => normalizeWalletAddress(w.address) === normalized);\n if (!stillExists) {\n setRenamingAddress(null);\n setRenameValue(\"\");\n setLabelError(null);\n }\n }, [wallets, renamingAddress, normalizeWalletAddress]);\n\n const copyAddress = useCallback(async (address: string) => {\n try {\n await navigator.clipboard.writeText(address);\n clearTimeout(copyTimeoutRef.current);\n setCopiedAddress(address);\n copyTimeoutRef.current = setTimeout(() => setCopiedAddress(null), 2000);\n } catch {\n // Clipboard API unavailable or denied\n }\n }, []);\n\n const canAdd = !readOnly && !!onAdd;\n const canRemove = !readOnly && !!onRemove;\n const canSetDefault = !readOnly && !!onSetDefault;\n const canLabel = !readOnly && !!onLabel;\n const canConnect = !readOnly && !!onConnect;\n\n const getSafeExplorerUrl = useCallback(\n (address: string) => {\n if (!getExplorerUrl) return null;\n try {\n const url = getExplorerUrl(address);\n if (!url) return null;\n const parsed = new URL(url);\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") return null;\n return parsed.toString();\n } catch {\n return null;\n }\n },\n [getExplorerUrl],\n );\n\n const handleAdd = async () => {\n const trimmed = newAddress.trim();\n const error = validateEthereumAddress(trimmed);\n if (error) {\n setAddressError(error);\n return;\n }\n setAddressError(null);\n setLabelError(null);\n try {\n await onAdd?.(trimmed);\n } catch (err) {\n setAddressError(err instanceof Error ? err.message : \"Failed to add wallet\");\n return;\n }\n // Wallet added — close the form. Attempt to save the label; on failure\n // surface an inline error so the user can rename manually.\n const label = newLabel.trim();\n setNewAddress(\"\");\n setShowAddForm(false);\n if (label && onLabel) {\n try {\n await onLabel(trimmed, label);\n setNewLabel(\"\");\n } catch {\n setNewLabel(\"\");\n setLabelError(\"Wallet added, but label could not be saved. You can rename it below.\");\n }\n } else {\n setNewLabel(\"\");\n }\n };\n\n const [removeError, setRemoveError] = useState<string | null>(null);\n\n const handleRemove = async () => {\n if (!walletToRemove) return;\n setRemoveError(null);\n try {\n await onRemove?.(walletToRemove);\n setWalletToRemove(null);\n } catch {\n setRemoveError(\"Failed to remove wallet. Please try again.\");\n }\n };\n\n const handleSetDefault = async (address: string) => {\n setSetDefaultError(null);\n try {\n await onSetDefault?.(address);\n } catch {\n setSetDefaultError(\"Failed to set default wallet. Please try again.\");\n }\n };\n\n const handleLabelSave = async (address: string) => {\n setLabelError(null);\n try {\n await onLabel?.(address, renameValue.trim() || null);\n setRenamingAddress((current) =>\n normalizeWalletAddress(current ?? \"\") === normalizeWalletAddress(address) ? null : current,\n );\n } catch {\n setLabelError(\"Failed to update label. Please try again.\");\n }\n };\n\n const hasWallets = wallets.length > 0;\n\n if (!hasWallets && !showAddForm && !canConnect) {\n return (\n <Stack gap=\"sm\">\n <EmptyState\n icon={emptyIcon}\n title=\"No wallets connected\"\n description=\"Connect a wallet to receive your equity on-chain when it vests.\"\n actionLabel={canAdd ? \"Add Wallet\" : undefined}\n onAction={canAdd ? () => setShowAddForm(true) : undefined}\n />\n {labelError && (\n <Text size=\"sm\" c={colors.error}>\n {labelError}\n </Text>\n )}\n {children}\n </Stack>\n );\n }\n\n return (\n <Stack gap=\"sm\">\n {wallets.map((w) => {\n const normalizedWalletAddress = normalizeWalletAddress(w.address);\n const setDefaultActionLoading =\n setDefaultLoading &&\n (!setDefaultAddress ||\n normalizeWalletAddress(setDefaultAddress) === normalizedWalletAddress);\n const labelActionLoading =\n labelLoading &&\n (!labelAddress || normalizeWalletAddress(labelAddress) === normalizedWalletAddress);\n const explorerUrl = getSafeExplorerUrl(w.address);\n const isRenaming =\n normalizeWalletAddress(renamingAddress ?? \"\") === normalizedWalletAddress;\n\n const displayName = getWalletDisplayName(w, typeLabels);\n const kindPill = getWalletKindPill(w.type, typeLabels);\n\n const isDefault = !!w.defaultRecipient;\n const canBeRemoved =\n canRemove &&\n (removableTypes\n ? removableTypes.some((t) => normalizeWalletType(t) === normalizeWalletType(w.type))\n : isRemovableWalletType(w.type));\n\n const hasMenuActions =\n (canSetDefault && !!defaultIcon && !isDefault) ||\n (canLabel && !!renameIcon) ||\n (!!explorerUrl && !!explorerIcon) ||\n (canBeRemoved && !!removeIcon);\n\n return (\n <Stack key={walletKey(w)} gap={0}>\n <Group\n justify=\"space-between\"\n align=\"flex-start\"\n wrap=\"nowrap\"\n p=\"md\"\n style={{\n borderRadius: radii.lg,\n border: `1px solid ${neutralColors[200]}`,\n background: \"transparent\",\n boxShadow: `0 1px 3px ${shadowColor.card}`,\n }}\n >\n {/* Left: icon + name + address */}\n <Group gap=\"sm\" align=\"flex-start\" wrap=\"nowrap\" style={{ flex: 1, minWidth: 0 }}>\n {walletIcon && (\n <ThemeIcon\n size={40}\n radius=\"xl\"\n variant=\"light\"\n color={getWalletIconColor(w.type)}\n style={{ flexShrink: 0 }}\n >\n {walletIcon}\n </ThemeIcon>\n )}\n\n {/* Inline rename mode — replaces name text in-place */}\n {isRenaming ? (\n <Stack gap={6} style={{ flex: 1, minWidth: 0 }}>\n <TextInput\n value={renameValue}\n onChange={(e) => {\n setRenameValue(e.currentTarget.value);\n setLabelError(null);\n }}\n placeholder={getWalletDisplayName(w, typeLabels)}\n size=\"xs\"\n aria-label=\"Wallet label\"\n maxLength={50}\n error={labelError ?? undefined}\n autoFocus\n />\n <Group gap=\"xs\">\n <Button\n size=\"xs\"\n loading={labelActionLoading}\n disabled={labelActionLoading}\n onClick={() => handleLabelSave(w.address)}\n >\n Save\n </Button>\n <Button\n size=\"xs\"\n variant=\"subtle\"\n color={colors.neutral}\n onClick={() => {\n setRenamingAddress(null);\n setLabelError(null);\n }}\n >\n Cancel\n </Button>\n </Group>\n </Stack>\n ) : (\n <Stack gap={4} style={{ flex: 1, minWidth: 0 }}>\n <Group gap=\"xs\" align=\"center\" wrap=\"wrap\">\n <Text size=\"sm\" fw={600} style={{ wordBreak: \"break-word\" }}>\n {displayName}\n </Text>\n {isDefault && (\n <Badge size=\"xs\" color={colors.warning} variant=\"light\" tt=\"uppercase\">\n Default\n </Badge>\n )}\n <Badge size=\"xs\" variant=\"light\" color={colors.neutral}>\n {kindPill}\n </Badge>\n </Group>\n <Text size=\"xs\" ff=\"monospace\" c={fairmintVars.colorTextSecondary}>\n {truncateAddress(w.address)}\n </Text>\n </Stack>\n )}\n </Group>\n\n {/* Right: copy shortcut + overflow menu */}\n {!isRenaming && (\n <Group gap={4} wrap=\"nowrap\" style={{ flexShrink: 0 }}>\n {/* Inline copy — most frequent action, stays visible */}\n {copyIcon && (\n <ActionIcon\n variant=\"subtle\"\n size=\"sm\"\n color={copiedAddress === w.address ? colors.success : colors.neutral}\n onClick={() => copyAddress(w.address)}\n aria-label=\"Copy wallet address\"\n title={copiedAddress === w.address ? \"Copied!\" : \"Copy address\"}\n >\n {copiedAddress === w.address ? (copiedIcon ?? copyIcon) : copyIcon}\n </ActionIcon>\n )}\n\n {/* Overflow menu — all secondary/destructive actions */}\n {hasMenuActions && (\n <Menu position=\"bottom-end\" withinPortal>\n <Menu.Target>\n <ActionIcon\n variant=\"subtle\"\n size=\"sm\"\n color={colors.neutral}\n aria-label=\"Wallet actions\"\n >\n {menuIcon ?? (\n <Text size=\"xs\" fw={700} lh={1} c={fairmintVars.colorTextSecondary}>\n •••\n </Text>\n )}\n </ActionIcon>\n </Menu.Target>\n <Menu.Dropdown>\n {canSetDefault && defaultIcon && !isDefault && (\n <Menu.Item\n leftSection={defaultIcon}\n onClick={() => handleSetDefault(w.address)}\n disabled={setDefaultActionLoading}\n >\n Set as default\n </Menu.Item>\n )}\n {canLabel && renameIcon && (\n <Menu.Item\n leftSection={renameIcon}\n onClick={() => {\n setLabelError(null);\n setRenamingAddress(w.address);\n setRenameValue(w.label ?? \"\");\n }}\n >\n Rename\n </Menu.Item>\n )}\n {explorerUrl && explorerIcon && (\n <Menu.Item\n leftSection={explorerIcon}\n component=\"a\"\n href={explorerUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n View on explorer\n </Menu.Item>\n )}\n {canBeRemoved && removeIcon && (\n <>\n <Menu.Divider />\n <Menu.Item\n leftSection={removeIcon}\n color={colors.error}\n onClick={() => setWalletToRemove(w.address)}\n disabled={removeLoading}\n >\n Remove wallet\n </Menu.Item>\n </>\n )}\n </Menu.Dropdown>\n </Menu>\n )}\n </Group>\n )}\n </Group>\n </Stack>\n );\n })}\n\n {setDefaultError && (\n <Text size=\"sm\" c={colors.error}>\n {setDefaultError}\n </Text>\n )}\n\n {/* Global label error — shown when labeling fails after add (no rename editor open) */}\n {labelError && !renamingAddress && (\n <Text size=\"sm\" c={colors.error}>\n {labelError}\n </Text>\n )}\n\n {!hasWallets && !showAddForm && (\n <EmptyState\n icon={emptyIcon}\n title=\"No wallets connected\"\n description=\"Connect a wallet to receive your equity on-chain when it vests.\"\n />\n )}\n\n {/* Add form — shown when user clicks add manually */}\n {canAdd && showAddForm && (\n <Stack gap=\"sm\" pt=\"xs\">\n <Stack gap=\"xs\">\n {canLabel && (\n <TextInput\n aria-label=\"Wallet label\"\n placeholder=\"Label (optional)\"\n size=\"sm\"\n value={newLabel}\n onChange={(e) => setNewLabel(e.currentTarget.value)}\n maxLength={50}\n autoFocus={true}\n />\n )}\n <TextInput\n placeholder=\"0x…\"\n size=\"sm\"\n autoFocus={!canLabel}\n aria-label=\"Wallet address\"\n aria-invalid={!!addressError}\n aria-describedby={addressError ? \"wallet-list-add-address-error\" : undefined}\n value={newAddress}\n onChange={(e) => {\n setNewAddress(e.currentTarget.value);\n setAddressError(null);\n }}\n error={\n addressError ? (\n <span id=\"wallet-list-add-address-error\" role=\"alert\">\n {addressError}\n </span>\n ) : undefined\n }\n />\n </Stack>\n <Group gap=\"xs\" justify=\"flex-end\">\n <Button\n size=\"sm\"\n variant=\"subtle\"\n color={colors.neutral}\n onClick={() => {\n setShowAddForm(false);\n setNewAddress(\"\");\n setNewLabel(\"\");\n setAddressError(null);\n setLabelError(null);\n }}\n >\n Cancel\n </Button>\n <Button size=\"sm\" onClick={handleAdd} loading={addLoading}>\n Add Wallet\n </Button>\n </Group>\n </Stack>\n )}\n\n {/* Action buttons — connect + manual add triggers */}\n {(canConnect || canAdd) && !showAddForm && (\n <Stack gap=\"xs\" pt=\"xs\">\n {canConnect && (\n <Button\n variant=\"subtle\"\n size=\"sm\"\n fullWidth\n leftSection={connectIcon}\n onClick={onConnect}\n loading={connectLoading}\n >\n Connect Wallet\n </Button>\n )}\n {canAdd && (\n <Button\n variant=\"subtle\"\n size=\"sm\"\n fullWidth\n leftSection={addIcon}\n color={colors.neutral}\n onClick={() => setShowAddForm(true)}\n >\n {canConnect ? \"Add manually\" : \"Add Wallet\"}\n </Button>\n )}\n </Stack>\n )}\n\n {children}\n\n <ConfirmDialog\n title=\"Remove Wallet\"\n message={\n <Stack gap=\"sm\">\n <Text size=\"sm\">\n Are you sure you want to remove this wallet address? This action cannot be undone.\n </Text>\n {walletToRemove && (\n <Text size=\"sm\" ff=\"monospace\" c={fairmintVars.colorTextSecondary}>\n {walletToRemove}\n </Text>\n )}\n {removeError && (\n <Text size=\"sm\" c={colors.error}>\n {removeError}\n </Text>\n )}\n </Stack>\n }\n opened={walletToRemove !== null}\n confirmLabel=\"Remove\"\n confirmColor={colors.error}\n onConfirm={handleRemove}\n onCancel={() => {\n setWalletToRemove(null);\n setRemoveError(null);\n }}\n loading={removeLoading}\n />\n </Stack>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"WalletList.js","sources":["../../../../src/components/specific/WalletList/WalletList.tsx"],"sourcesContent":["import { type ReactNode, useCallback, useEffect, useRef, useState } from \"react\";\nimport { colors, fairmintVars, neutralColors, radii, shadowColor } from \"../../../theme\";\nimport { validateEthereumAddress } from \"../../../utils/address\";\nimport {\n getWalletDisplayName,\n getWalletIconColor,\n isRemovableWalletType,\n normalizeWalletType,\n type Wallet,\n walletKey,\n} from \"../../../utils/wallets\";\nimport { ConfirmDialog } from \"../../generic/ConfirmDialog/ConfirmDialog\";\nimport { EmptyState } from \"../../generic/EmptyState/EmptyState\";\nimport { ActionIcon } from \"../../primitives/ActionIcon/ActionIcon\";\nimport { Button } from \"../../primitives/Button/Button\";\nimport { Group, Stack, Text, ThemeIcon } from \"../../primitives/layout\";\nimport { Menu } from \"../../primitives/Menu/Menu\";\nimport { TextInput } from \"../../primitives/TextInput/TextInput\";\nimport { WalletListItem } from \"../WalletListItem/WalletListItem\";\n\nexport type { Wallet };\n\nexport interface WalletListProps {\n /** Wallets to display. */\n wallets: Wallet[];\n /** Called when user adds a new wallet address. */\n onAdd?: (address: string) => void | Promise<void>;\n /** Called when user confirms removal of a wallet address. */\n onRemove?: (address: string) => void | Promise<void>;\n /** Called when user sets a wallet as default recipient. */\n onSetDefault?: (address: string) => void | Promise<void>;\n /** Called when user saves a label for a wallet. Null clears the label. May reject — label error is displayed inline. */\n onLabel?: (address: string, label: string | null) => void | Promise<void>;\n /** Called when user clicks the connect wallet button (Privy linking). */\n onConnect?: () => void;\n /** Returns a block explorer URL for a wallet address. If omitted, explorer link is hidden. */\n getExplorerUrl?: (address: string) => string;\n /** Whether add/remove/edit actions are disabled (e.g. admin viewing another user). */\n readOnly?: boolean;\n /** Whether an add operation is in progress. */\n addLoading?: boolean;\n /** Whether a remove operation is in progress. */\n removeLoading?: boolean;\n /** Whether a set-default operation is in progress. */\n setDefaultLoading?: boolean;\n /** Address of the wallet currently being set as default (for per-row loading). */\n setDefaultAddress?: string;\n /** Whether a label operation is in progress. */\n labelLoading?: boolean;\n /** Address of the wallet currently being labeled (for per-row loading). */\n labelAddress?: string;\n /** Whether the connect wallet operation is in progress. */\n connectLoading?: boolean;\n /** Icon for the empty state. Passed as ReactNode. */\n emptyIcon?: ReactNode;\n /** Icon for the copy button. Passed as ReactNode. */\n copyIcon?: ReactNode;\n /** Icon for the \"copied\" state. Passed as ReactNode. */\n copiedIcon?: ReactNode;\n /** Icon for the remove button. Passed as ReactNode. */\n removeIcon?: ReactNode;\n /** Icon for the add button. Passed as ReactNode. */\n addIcon?: ReactNode;\n /** Icon for the set-default button. Passed as ReactNode. */\n defaultIcon?: ReactNode;\n /** Icon for the rename button. Passed as ReactNode. */\n renameIcon?: ReactNode;\n /** Icon for the block explorer link. Passed as ReactNode. */\n explorerIcon?: ReactNode;\n /** Icon for the connect wallet button. Passed as ReactNode. */\n connectIcon?: ReactNode;\n /** Icon for the overflow (kebab) menu trigger. Passed as ReactNode. */\n menuIcon?: ReactNode;\n /**\n * Override default type → label mapping.\n * @default Built-in: \"fairmint\"|\"privy\" → \"Fairmint Wallet\", \"manual\" → \"Manual\", else as-is\n */\n typeLabels?: Record<string, string>;\n /**\n * Which wallet types can be removed. Overrides the default system-type check.\n * @default All non-system types (everything except \"fairmint\" and \"privy\")\n */\n removableTypes?: string[];\n /** Additional content rendered below the wallet list (e.g. advanced wallet forms). */\n children?: ReactNode;\n /** Optional icon shown in a circle at the start of each wallet row. */\n walletIcon?: ReactNode;\n}\n\nexport function WalletList({\n wallets,\n onAdd,\n onRemove,\n onSetDefault,\n onLabel,\n onConnect,\n getExplorerUrl,\n readOnly = false,\n addLoading = false,\n removeLoading = false,\n setDefaultLoading = false,\n setDefaultAddress,\n labelLoading = false,\n labelAddress,\n connectLoading = false,\n emptyIcon,\n copyIcon,\n copiedIcon,\n removeIcon,\n addIcon,\n defaultIcon,\n renameIcon,\n explorerIcon,\n connectIcon,\n menuIcon,\n typeLabels,\n removableTypes,\n children,\n walletIcon,\n}: WalletListProps) {\n const normalizeWalletAddress = useCallback(\n (address: string | undefined) => address?.trim().toLowerCase() ?? \"\",\n [],\n );\n const [newAddress, setNewAddress] = useState(\"\");\n const [newLabel, setNewLabel] = useState(\"\");\n const [addressError, setAddressError] = useState<string | null>(null);\n const [showAddForm, setShowAddForm] = useState(false);\n const [walletToRemove, setWalletToRemove] = useState<string | null>(null);\n const [copiedAddress, setCopiedAddress] = useState<string | null>(null);\n const [renamingAddress, setRenamingAddress] = useState<string | null>(null);\n const [renameValue, setRenameValue] = useState(\"\");\n const [labelError, setLabelError] = useState<string | null>(null);\n const [setDefaultError, setSetDefaultError] = useState<string | null>(null);\n const copyTimeoutRef = useRef<ReturnType<typeof setTimeout>>(undefined);\n\n useEffect(() => () => clearTimeout(copyTimeoutRef.current), []);\n\n useEffect(() => {\n if (readOnly) setRenamingAddress(null);\n }, [readOnly]);\n\n useEffect(() => {\n if (!renamingAddress) return;\n const normalized = normalizeWalletAddress(renamingAddress);\n const stillExists = wallets.some((w) => normalizeWalletAddress(w.address) === normalized);\n if (!stillExists) {\n setRenamingAddress(null);\n setRenameValue(\"\");\n setLabelError(null);\n }\n }, [wallets, renamingAddress, normalizeWalletAddress]);\n\n const copyAddress = useCallback(\n async (address: string) => {\n try {\n await navigator.clipboard.writeText(address);\n clearTimeout(copyTimeoutRef.current);\n // Store normalized so feedback survives parent re-renders that change EIP-55 casing.\n setCopiedAddress(normalizeWalletAddress(address));\n copyTimeoutRef.current = setTimeout(() => setCopiedAddress(null), 2000);\n } catch {\n // Clipboard API unavailable or denied\n }\n },\n [normalizeWalletAddress],\n );\n\n const canAdd = !readOnly && !!onAdd;\n const canRemove = !readOnly && !!onRemove;\n const canSetDefault = !readOnly && !!onSetDefault;\n const canLabel = !readOnly && !!onLabel;\n const canConnect = !readOnly && !!onConnect;\n\n const getSafeExplorerUrl = useCallback(\n (address: string) => {\n if (!getExplorerUrl) return null;\n try {\n const url = getExplorerUrl(address);\n if (!url) return null;\n const parsed = new URL(url);\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") return null;\n return parsed.toString();\n } catch {\n return null;\n }\n },\n [getExplorerUrl],\n );\n\n const handleAdd = async () => {\n const trimmed = newAddress.trim();\n const error = validateEthereumAddress(trimmed);\n if (error) {\n setAddressError(error);\n return;\n }\n setAddressError(null);\n setLabelError(null);\n try {\n await onAdd?.(trimmed);\n } catch (err) {\n setAddressError(err instanceof Error ? err.message : \"Failed to add wallet\");\n return;\n }\n // Wallet added — close the form. Attempt to save the label; on failure\n // surface an inline error so the user can rename manually.\n const label = newLabel.trim();\n setNewAddress(\"\");\n setShowAddForm(false);\n if (label && onLabel) {\n try {\n await onLabel(trimmed, label);\n setNewLabel(\"\");\n } catch {\n setNewLabel(\"\");\n setLabelError(\"Wallet added, but label could not be saved. You can rename it below.\");\n }\n } else {\n setNewLabel(\"\");\n }\n };\n\n const [removeError, setRemoveError] = useState<string | null>(null);\n\n const handleRemove = async () => {\n if (!walletToRemove) return;\n setRemoveError(null);\n try {\n await onRemove?.(walletToRemove);\n setWalletToRemove(null);\n } catch {\n setRemoveError(\"Failed to remove wallet. Please try again.\");\n }\n };\n\n const handleSetDefault = async (address: string) => {\n setSetDefaultError(null);\n try {\n await onSetDefault?.(address);\n } catch {\n setSetDefaultError(\"Failed to set default wallet. Please try again.\");\n }\n };\n\n const handleLabelSave = async (address: string) => {\n setLabelError(null);\n try {\n await onLabel?.(address, renameValue.trim() || null);\n setRenamingAddress((current) =>\n normalizeWalletAddress(current ?? \"\") === normalizeWalletAddress(address) ? null : current,\n );\n } catch {\n setLabelError(\"Failed to update label. Please try again.\");\n }\n };\n\n const hasWallets = wallets.length > 0;\n\n if (!hasWallets && !showAddForm && !canConnect) {\n return (\n <Stack gap=\"sm\">\n <EmptyState\n icon={emptyIcon}\n title=\"No wallets connected\"\n description=\"Connect a wallet to receive your equity on-chain when it vests.\"\n actionLabel={canAdd ? \"Add Wallet\" : undefined}\n onAction={canAdd ? () => setShowAddForm(true) : undefined}\n />\n {labelError && (\n <Text size=\"sm\" c={colors.error}>\n {labelError}\n </Text>\n )}\n {children}\n </Stack>\n );\n }\n\n return (\n <Stack gap=\"sm\">\n {wallets.map((w) => {\n const normalizedWalletAddress = normalizeWalletAddress(w.address);\n const isCopied = copiedAddress === normalizedWalletAddress;\n const setDefaultActionLoading =\n setDefaultLoading &&\n (!setDefaultAddress ||\n normalizeWalletAddress(setDefaultAddress) === normalizedWalletAddress);\n const labelActionLoading =\n labelLoading &&\n (!labelAddress || normalizeWalletAddress(labelAddress) === normalizedWalletAddress);\n const explorerUrl = getSafeExplorerUrl(w.address);\n const isRenaming =\n normalizeWalletAddress(renamingAddress ?? \"\") === normalizedWalletAddress;\n\n const displayName = getWalletDisplayName(w, typeLabels);\n const isDefault = !!w.defaultRecipient;\n const canBeRemoved =\n canRemove &&\n (removableTypes\n ? removableTypes.some((t) => normalizeWalletType(t) === normalizeWalletType(w.type))\n : isRemovableWalletType(w.type));\n\n const hasMenuActions =\n (canSetDefault && !!defaultIcon && !isDefault) ||\n (canLabel && !!renameIcon) ||\n (!!explorerUrl && !!explorerIcon) ||\n (canBeRemoved && !!removeIcon);\n\n return (\n <Stack key={walletKey(w)} gap={0}>\n {isRenaming ? (\n <Group\n justify=\"space-between\"\n align=\"flex-start\"\n wrap=\"nowrap\"\n p=\"md\"\n style={{\n borderRadius: radii.lg,\n border: `1px solid ${neutralColors[200]}`,\n background: \"transparent\",\n boxShadow: `0 1px 3px ${shadowColor.card}`,\n }}\n >\n <Group gap=\"sm\" align=\"flex-start\" wrap=\"nowrap\" style={{ flex: 1, minWidth: 0 }}>\n {walletIcon && (\n <ThemeIcon\n size={40}\n radius=\"xl\"\n variant=\"light\"\n color={getWalletIconColor(w.type)}\n style={{ flexShrink: 0 }}\n >\n {walletIcon}\n </ThemeIcon>\n )}\n <Stack gap={6} style={{ flex: 1, minWidth: 0 }}>\n <TextInput\n value={renameValue}\n onChange={(e) => {\n setRenameValue(e.currentTarget.value);\n setLabelError(null);\n }}\n placeholder={displayName}\n size=\"xs\"\n aria-label=\"Wallet label\"\n maxLength={50}\n error={labelError ?? undefined}\n autoFocus\n />\n <Group gap=\"xs\">\n <Button\n size=\"xs\"\n loading={labelActionLoading}\n disabled={labelActionLoading}\n onClick={() => handleLabelSave(w.address)}\n >\n Save\n </Button>\n <Button\n size=\"xs\"\n variant=\"subtle\"\n color={colors.neutral}\n onClick={() => {\n setRenamingAddress(null);\n setLabelError(null);\n }}\n >\n Cancel\n </Button>\n </Group>\n </Stack>\n </Group>\n </Group>\n ) : (\n <WalletListItem\n wallet={w}\n typeLabels={typeLabels}\n walletIcon={walletIcon}\n rightSection={\n <Group gap={4} wrap=\"nowrap\" style={{ flexShrink: 0 }}>\n {/* Inline copy — most frequent action, stays visible */}\n {copyIcon && (\n <ActionIcon\n variant=\"subtle\"\n size=\"sm\"\n color={isCopied ? colors.success : colors.neutral}\n onClick={() => copyAddress(w.address)}\n aria-label=\"Copy wallet address\"\n title={isCopied ? \"Copied!\" : \"Copy address\"}\n >\n {isCopied ? (copiedIcon ?? copyIcon) : copyIcon}\n </ActionIcon>\n )}\n\n {/* Overflow menu — all secondary/destructive actions */}\n {hasMenuActions && (\n <Menu position=\"bottom-end\" withinPortal>\n <Menu.Target>\n <ActionIcon\n variant=\"subtle\"\n size=\"sm\"\n color={colors.neutral}\n aria-label=\"Wallet actions\"\n >\n {menuIcon ?? (\n <Text size=\"xs\" fw={700} lh={1} c={fairmintVars.colorTextSecondary}>\n •••\n </Text>\n )}\n </ActionIcon>\n </Menu.Target>\n <Menu.Dropdown>\n {canSetDefault && defaultIcon && !isDefault && (\n <Menu.Item\n leftSection={defaultIcon}\n onClick={() => handleSetDefault(w.address)}\n disabled={setDefaultActionLoading}\n >\n Set as default\n </Menu.Item>\n )}\n {canLabel && renameIcon && (\n <Menu.Item\n leftSection={renameIcon}\n onClick={() => {\n setLabelError(null);\n setRenamingAddress(w.address);\n setRenameValue(w.label ?? \"\");\n }}\n >\n Rename\n </Menu.Item>\n )}\n {explorerUrl && explorerIcon && (\n <Menu.Item\n leftSection={explorerIcon}\n component=\"a\"\n href={explorerUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n View on explorer\n </Menu.Item>\n )}\n {canBeRemoved && removeIcon && (\n <>\n <Menu.Divider />\n <Menu.Item\n leftSection={removeIcon}\n color={colors.error}\n onClick={() => setWalletToRemove(w.address)}\n disabled={removeLoading}\n >\n Remove wallet\n </Menu.Item>\n </>\n )}\n </Menu.Dropdown>\n </Menu>\n )}\n </Group>\n }\n />\n )}\n </Stack>\n );\n })}\n\n {setDefaultError && (\n <Text size=\"sm\" c={colors.error}>\n {setDefaultError}\n </Text>\n )}\n\n {/* Global label error — shown when labeling fails after add (no rename editor open) */}\n {labelError && !renamingAddress && (\n <Text size=\"sm\" c={colors.error}>\n {labelError}\n </Text>\n )}\n\n {!hasWallets && !showAddForm && (\n <EmptyState\n icon={emptyIcon}\n title=\"No wallets connected\"\n description=\"Connect a wallet to receive your equity on-chain when it vests.\"\n />\n )}\n\n {/* Add form — shown when user clicks add manually */}\n {canAdd && showAddForm && (\n <Stack gap=\"sm\" pt=\"xs\">\n <Stack gap=\"xs\">\n {canLabel && (\n <TextInput\n aria-label=\"Wallet label\"\n placeholder=\"Label (optional)\"\n size=\"sm\"\n value={newLabel}\n onChange={(e) => setNewLabel(e.currentTarget.value)}\n maxLength={50}\n autoFocus={true}\n />\n )}\n <TextInput\n placeholder=\"0x…\"\n size=\"sm\"\n autoFocus={!canLabel}\n aria-label=\"Wallet address\"\n aria-invalid={!!addressError}\n aria-describedby={addressError ? \"wallet-list-add-address-error\" : undefined}\n value={newAddress}\n onChange={(e) => {\n setNewAddress(e.currentTarget.value);\n setAddressError(null);\n }}\n error={\n addressError ? (\n <span id=\"wallet-list-add-address-error\" role=\"alert\">\n {addressError}\n </span>\n ) : undefined\n }\n />\n </Stack>\n <Group gap=\"xs\" justify=\"flex-end\">\n <Button\n size=\"sm\"\n variant=\"subtle\"\n color={colors.neutral}\n onClick={() => {\n setShowAddForm(false);\n setNewAddress(\"\");\n setNewLabel(\"\");\n setAddressError(null);\n setLabelError(null);\n }}\n >\n Cancel\n </Button>\n <Button size=\"sm\" onClick={handleAdd} loading={addLoading}>\n Add Wallet\n </Button>\n </Group>\n </Stack>\n )}\n\n {/* Action buttons — connect + manual add triggers */}\n {(canConnect || canAdd) && !showAddForm && (\n <Stack gap=\"xs\" pt=\"xs\">\n {canConnect && (\n <Button\n variant=\"subtle\"\n size=\"sm\"\n fullWidth\n leftSection={connectIcon}\n onClick={onConnect}\n loading={connectLoading}\n >\n Connect Wallet\n </Button>\n )}\n {canAdd && (\n <Button\n variant=\"subtle\"\n size=\"sm\"\n fullWidth\n leftSection={addIcon}\n color={colors.neutral}\n onClick={() => setShowAddForm(true)}\n >\n {canConnect ? \"Add manually\" : \"Add Wallet\"}\n </Button>\n )}\n </Stack>\n )}\n\n {children}\n\n <ConfirmDialog\n title=\"Remove Wallet\"\n message={\n <Stack gap=\"sm\">\n <Text size=\"sm\">\n Are you sure you want to remove this wallet address? This action cannot be undone.\n </Text>\n {walletToRemove && (\n <Text size=\"sm\" ff=\"monospace\" c={fairmintVars.colorTextSecondary}>\n {walletToRemove}\n </Text>\n )}\n {removeError && (\n <Text size=\"sm\" c={colors.error}>\n {removeError}\n </Text>\n )}\n </Stack>\n }\n opened={walletToRemove !== null}\n confirmLabel=\"Remove\"\n confirmColor={colors.error}\n onConfirm={handleRemove}\n onCancel={() => {\n setWalletToRemove(null);\n setRemoveError(null);\n }}\n loading={removeLoading}\n />\n </Stack>\n );\n}\n"],"names":[],"mappings":"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"}