@fairmint/ui 0.2.14 → 0.2.16

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.
@@ -6,6 +6,8 @@ export interface Wallet {
6
6
  type: string;
7
7
  /** Optional display label. */
8
8
  label?: string | null;
9
+ /** Whether this is the default equity recipient wallet. */
10
+ defaultRecipient?: boolean;
9
11
  }
10
12
  export interface WalletListProps {
11
13
  /** Wallets to display. */
@@ -14,12 +16,30 @@ export interface WalletListProps {
14
16
  onAdd?: (address: string) => void | Promise<void>;
15
17
  /** Called when user confirms removal of a wallet address. */
16
18
  onRemove?: (address: string) => void | Promise<void>;
17
- /** Whether add/remove actions are disabled (e.g. admin viewing another user). */
19
+ /** Called when user sets a wallet as default recipient. */
20
+ onSetDefault?: (address: string) => void | Promise<void>;
21
+ /** Called when user saves a label for a wallet. Null clears the label. May reject — label error is displayed inline. */
22
+ onLabel?: (address: string, label: string | null) => void | Promise<void>;
23
+ /** Called when user clicks the connect wallet button (Privy linking). */
24
+ onConnect?: () => void;
25
+ /** Returns a block explorer URL for a wallet address. If omitted, explorer link is hidden. */
26
+ getExplorerUrl?: (address: string) => string;
27
+ /** Whether add/remove/edit actions are disabled (e.g. admin viewing another user). */
18
28
  readOnly?: boolean;
19
29
  /** Whether an add operation is in progress. */
20
30
  addLoading?: boolean;
21
31
  /** Whether a remove operation is in progress. */
22
32
  removeLoading?: boolean;
33
+ /** Whether a set-default operation is in progress. */
34
+ setDefaultLoading?: boolean;
35
+ /** Address of the wallet currently being set as default (for per-row loading). */
36
+ setDefaultAddress?: string;
37
+ /** Whether a label operation is in progress. */
38
+ labelLoading?: boolean;
39
+ /** Address of the wallet currently being labeled (for per-row loading). */
40
+ labelAddress?: string;
41
+ /** Whether the connect wallet operation is in progress. */
42
+ connectLoading?: boolean;
23
43
  /** Icon for the empty state. Passed as ReactNode. */
24
44
  emptyIcon?: ReactNode;
25
45
  /** Icon for the copy button. Passed as ReactNode. */
@@ -30,16 +50,26 @@ export interface WalletListProps {
30
50
  removeIcon?: ReactNode;
31
51
  /** Icon for the add button. Passed as ReactNode. */
32
52
  addIcon?: ReactNode;
53
+ /** Icon for the set-default button. Passed as ReactNode. */
54
+ defaultIcon?: ReactNode;
55
+ /** Icon for the rename button. Passed as ReactNode. */
56
+ renameIcon?: ReactNode;
57
+ /** Icon for the block explorer link. Passed as ReactNode. */
58
+ explorerIcon?: ReactNode;
59
+ /** Icon for the connect wallet button. Passed as ReactNode. */
60
+ connectIcon?: ReactNode;
33
61
  /**
34
- * Map a wallet type string to a display label.
62
+ * Override default type → label mapping.
35
63
  * @default Built-in: "fairmint"|"privy" → "Fairmint Wallet", "manual" → "Manual", else as-is
36
64
  */
37
65
  typeLabels?: Record<string, string>;
38
66
  /**
39
- * Which wallet types can be removed.
40
- * @default ["manual"]
67
+ * Which wallet types can be removed. Overrides the default system-type check.
68
+ * @default All non-system types (everything except "fairmint" and "privy")
41
69
  */
42
70
  removableTypes?: string[];
71
+ /** Additional content rendered below the wallet list (e.g. advanced wallet forms). */
72
+ children?: ReactNode;
43
73
  }
44
- export declare function WalletList({ wallets, onAdd, onRemove, readOnly, addLoading, removeLoading, emptyIcon, copyIcon, copiedIcon, removeIcon, addIcon, typeLabels, removableTypes, }: WalletListProps): import("react/jsx-runtime").JSX.Element;
74
+ export declare function WalletList({ wallets, onAdd, onRemove, onSetDefault, onLabel, onConnect, getExplorerUrl, readOnly, addLoading, removeLoading, setDefaultLoading, setDefaultAddress, labelLoading, labelAddress, connectLoading, emptyIcon, copyIcon, copiedIcon, removeIcon, addIcon, defaultIcon, renameIcon, explorerIcon, connectIcon, typeLabels, removableTypes, children, }: WalletListProps): import("react/jsx-runtime").JSX.Element;
45
75
  //# sourceMappingURL=WalletList.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"WalletList.d.ts","sourceRoot":"","sources":["../../../../src/components/specific/WalletList/WalletList.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAA+B,MAAM,OAAO,CAAC;AAYpE,MAAM,WAAW,MAAM;IACrB,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,0BAA0B;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,kDAAkD;IAClD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,iDAAiD;IACjD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qDAAqD;IACrD,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,wDAAwD;IACxD,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,uDAAuD;IACvD,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,oDAAoD;IACpD,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAaD,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,KAAK,EACL,QAAQ,EACR,QAAgB,EAChB,UAAkB,EAClB,aAAqB,EACrB,SAAS,EACT,QAAQ,EACR,UAAU,EACV,UAAU,EACV,OAAO,EACP,UAAU,EACV,cAA2B,GAC5B,EAAE,eAAe,2CAmMjB"}
1
+ {"version":3,"file":"WalletList.d.ts","sourceRoot":"","sources":["../../../../src/components/specific/WalletList/WalletList.tsx"],"names":[],"mappings":"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"}
@@ -15857,14 +15857,14 @@ function useAvatarGroupContext() {
15857
15857
  const ctx = React.useContext(AvatarGroupContext);
15858
15858
  return { withinGroup: !!ctx };
15859
15859
  }
15860
- const varsResolver$v = createVarsResolver((_, { spacing }) => ({
15860
+ const varsResolver$v = createVarsResolver((_, { spacing: spacing2 }) => ({
15861
15861
  group: {
15862
- "--ag-spacing": getSpacing(spacing)
15862
+ "--ag-spacing": getSpacing(spacing2)
15863
15863
  }
15864
15864
  }));
15865
15865
  const AvatarGroup = factory((_props, ref) => {
15866
15866
  const props = useProps("AvatarGroup", null, _props);
15867
- const { classNames: classNames2, className, style, styles, unstyled, vars, spacing, attributes, ...others } = props;
15867
+ const { classNames: classNames2, className, style, styles, unstyled, vars, spacing: spacing2, attributes, ...others } = props;
15868
15868
  const getStyles2 = useStyles({
15869
15869
  name: "AvatarGroup",
15870
15870
  classes: classes$t,
@@ -21401,15 +21401,15 @@ Select$1.classes = { ...InputBase.classes, ...Combobox.classes };
21401
21401
  Select$1.displayName = "@mantine/core/Select";
21402
21402
  var classes$8 = { "container": "m_925c2d2c", "root": "m_2415a157" };
21403
21403
  function SimpleGridMediaVariables({
21404
- spacing,
21404
+ spacing: spacing2,
21405
21405
  verticalSpacing,
21406
21406
  cols,
21407
21407
  selector
21408
21408
  }) {
21409
21409
  const theme2 = useMantineTheme();
21410
- const _verticalSpacing = verticalSpacing === void 0 ? spacing : verticalSpacing;
21410
+ const _verticalSpacing = verticalSpacing === void 0 ? spacing2 : verticalSpacing;
21411
21411
  const baseStyles = filterProps({
21412
- "--sg-spacing-x": getSpacing(getBaseValue$1(spacing)),
21412
+ "--sg-spacing-x": getSpacing(getBaseValue$1(spacing2)),
21413
21413
  "--sg-spacing-y": getSpacing(getBaseValue$1(_verticalSpacing)),
21414
21414
  "--sg-cols": getBaseValue$1(cols)?.toString()
21415
21415
  });
@@ -21418,8 +21418,8 @@ function SimpleGridMediaVariables({
21418
21418
  if (!acc[breakpoint]) {
21419
21419
  acc[breakpoint] = {};
21420
21420
  }
21421
- if (typeof spacing === "object" && spacing[breakpoint] !== void 0) {
21422
- acc[breakpoint]["--sg-spacing-x"] = getSpacing(spacing[breakpoint]);
21421
+ if (typeof spacing2 === "object" && spacing2[breakpoint] !== void 0) {
21422
+ acc[breakpoint]["--sg-spacing-x"] = getSpacing(spacing2[breakpoint]);
21423
21423
  }
21424
21424
  if (typeof _verticalSpacing === "object" && _verticalSpacing[breakpoint] !== void 0) {
21425
21425
  acc[breakpoint]["--sg-spacing-y"] = getSpacing(_verticalSpacing[breakpoint]);
@@ -21450,13 +21450,13 @@ function sortBreakpoints(breakpoints) {
21450
21450
  return breakpoints.sort((a, b) => px(a) - px(b));
21451
21451
  }
21452
21452
  function getUniqueBreakpoints({
21453
- spacing,
21453
+ spacing: spacing2,
21454
21454
  verticalSpacing,
21455
21455
  cols
21456
21456
  }) {
21457
21457
  const breakpoints = Array.from(
21458
21458
  /* @__PURE__ */ new Set([
21459
- ...getBreakpoints(spacing),
21459
+ ...getBreakpoints(spacing2),
21460
21460
  ...getBreakpoints(verticalSpacing),
21461
21461
  ...getBreakpoints(cols)
21462
21462
  ])
@@ -21464,25 +21464,25 @@ function getUniqueBreakpoints({
21464
21464
  return sortBreakpoints(breakpoints);
21465
21465
  }
21466
21466
  function SimpleGridContainerVariables({
21467
- spacing,
21467
+ spacing: spacing2,
21468
21468
  verticalSpacing,
21469
21469
  cols,
21470
21470
  selector
21471
21471
  }) {
21472
- const _verticalSpacing = verticalSpacing === void 0 ? spacing : verticalSpacing;
21472
+ const _verticalSpacing = verticalSpacing === void 0 ? spacing2 : verticalSpacing;
21473
21473
  const baseStyles = filterProps({
21474
- "--sg-spacing-x": getSpacing(getBaseValue$1(spacing)),
21474
+ "--sg-spacing-x": getSpacing(getBaseValue$1(spacing2)),
21475
21475
  "--sg-spacing-y": getSpacing(getBaseValue$1(_verticalSpacing)),
21476
21476
  "--sg-cols": getBaseValue$1(cols)?.toString()
21477
21477
  });
21478
- const uniqueBreakpoints = getUniqueBreakpoints({ spacing, verticalSpacing, cols });
21478
+ const uniqueBreakpoints = getUniqueBreakpoints({ spacing: spacing2, verticalSpacing, cols });
21479
21479
  const queries = uniqueBreakpoints.reduce(
21480
21480
  (acc, breakpoint) => {
21481
21481
  if (!acc[breakpoint]) {
21482
21482
  acc[breakpoint] = {};
21483
21483
  }
21484
- if (typeof spacing === "object" && spacing[breakpoint] !== void 0) {
21485
- acc[breakpoint]["--sg-spacing-x"] = getSpacing(spacing[breakpoint]);
21484
+ if (typeof spacing2 === "object" && spacing2[breakpoint] !== void 0) {
21485
+ acc[breakpoint]["--sg-spacing-x"] = getSpacing(spacing2[breakpoint]);
21486
21486
  }
21487
21487
  if (typeof _verticalSpacing === "object" && _verticalSpacing[breakpoint] !== void 0) {
21488
21488
  acc[breakpoint]["--sg-spacing-y"] = getSpacing(_verticalSpacing[breakpoint]);
@@ -21516,7 +21516,7 @@ const SimpleGrid = factory((_props, ref) => {
21516
21516
  vars,
21517
21517
  cols,
21518
21518
  verticalSpacing,
21519
- spacing,
21519
+ spacing: spacing2,
21520
21520
  type,
21521
21521
  attributes,
21522
21522
  ...others
@@ -26786,6 +26786,13 @@ const z = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
26786
26786
  },
26787
26787
  void: voidType
26788
26788
  }, Symbol.toStringTag, { value: "Module" }));
26789
+ const spacing = {
26790
+ xs: "0.625rem",
26791
+ sm: "0.75rem",
26792
+ md: "1rem",
26793
+ lg: "1.25rem",
26794
+ xl: "2rem"
26795
+ };
26789
26796
  const colors = {
26790
26797
  /** Primary UI color — buttons, links, active states. */
26791
26798
  primary: "indigo",
@@ -26937,6 +26944,7 @@ const theme = createTheme({
26937
26944
  },
26938
26945
  radius: radii,
26939
26946
  defaultRadius: "md",
26947
+ spacing,
26940
26948
  breakpoints: {
26941
26949
  xs: "30em",
26942
26950
  sm: "48em",
@@ -30706,38 +30714,84 @@ function InvestorProfileCard({
30706
30714
  children
30707
30715
  ] });
30708
30716
  }
30709
- const DEFAULT_TYPE_LABELS = {
30717
+ const SYSTEM_TYPES = /* @__PURE__ */ new Set(["fairmint", "privy"]);
30718
+ const TYPE_LABELS = {
30710
30719
  fairmint: "Fairmint Wallet",
30711
30720
  privy: "Fairmint Wallet",
30712
30721
  manual: "Manual"
30713
30722
  };
30714
- function getTypeLabel(type, custom2) {
30715
- if (custom2?.[type]) return custom2[type];
30716
- return DEFAULT_TYPE_LABELS[type] ?? type;
30723
+ function normalizeWalletType(type) {
30724
+ return String(type ?? "").trim().toLowerCase();
30725
+ }
30726
+ function getWalletLabel(type, custom2) {
30727
+ const key = normalizeWalletType(type);
30728
+ const rawType = typeof type === "string" ? type : String(type ?? "");
30729
+ if (custom2?.[key]) return custom2[key];
30730
+ if (custom2?.[rawType]) return custom2[rawType];
30731
+ return TYPE_LABELS[key] ?? rawType;
30732
+ }
30733
+ function getWalletDisplayName(wallet, customLabels) {
30734
+ const label = wallet.label?.trim();
30735
+ if (label) return label;
30736
+ return getWalletLabel(wallet.type, customLabels);
30737
+ }
30738
+ function isSystemWalletType(type) {
30739
+ return SYSTEM_TYPES.has(normalizeWalletType(type));
30740
+ }
30741
+ function isRemovableWalletType(type) {
30742
+ return !isSystemWalletType(type);
30743
+ }
30744
+ function walletKey(w) {
30745
+ return `${normalizeWalletType(w.type)}:${w.address.toLowerCase()}`;
30717
30746
  }
30718
30747
  function WalletList({
30719
30748
  wallets,
30720
30749
  onAdd,
30721
30750
  onRemove,
30751
+ onSetDefault,
30752
+ onLabel,
30753
+ onConnect,
30754
+ getExplorerUrl,
30722
30755
  readOnly = false,
30723
30756
  addLoading = false,
30724
30757
  removeLoading = false,
30758
+ setDefaultLoading = false,
30759
+ setDefaultAddress,
30760
+ labelLoading = false,
30761
+ labelAddress,
30762
+ connectLoading = false,
30725
30763
  emptyIcon,
30726
30764
  copyIcon,
30727
30765
  copiedIcon,
30728
30766
  removeIcon,
30729
30767
  addIcon,
30768
+ defaultIcon,
30769
+ renameIcon,
30770
+ explorerIcon,
30771
+ connectIcon,
30730
30772
  typeLabels,
30731
- removableTypes = ["manual"]
30773
+ removableTypes,
30774
+ children
30732
30775
  }) {
30776
+ const normalizeWalletAddress = React.useCallback(
30777
+ (address) => address?.trim().toLowerCase() ?? "",
30778
+ []
30779
+ );
30733
30780
  const [newAddress, setNewAddress] = React.useState("");
30734
30781
  const [addressError, setAddressError] = React.useState(null);
30735
30782
  const [showAddForm, setShowAddForm] = React.useState(false);
30736
30783
  const [walletToRemove, setWalletToRemove] = React.useState(null);
30737
30784
  const [copiedAddress, setCopiedAddress] = React.useState(null);
30785
+ const [renamingAddress, setRenamingAddress] = React.useState(null);
30786
+ const [renameValue, setRenameValue] = React.useState("");
30787
+ const [labelError, setLabelError] = React.useState(null);
30788
+ const [setDefaultError, setSetDefaultError] = React.useState(null);
30738
30789
  const copyTimeoutRef = React.useRef(void 0);
30739
30790
  React.useEffect(() => () => clearTimeout(copyTimeoutRef.current), []);
30740
- const copyAddress = async (address) => {
30791
+ React.useEffect(() => {
30792
+ if (readOnly) setRenamingAddress(null);
30793
+ }, [readOnly]);
30794
+ const copyAddress = React.useCallback(async (address) => {
30741
30795
  try {
30742
30796
  await navigator.clipboard.writeText(address);
30743
30797
  clearTimeout(copyTimeoutRef.current);
@@ -30745,9 +30799,27 @@ function WalletList({
30745
30799
  copyTimeoutRef.current = setTimeout(() => setCopiedAddress(null), 2e3);
30746
30800
  } catch {
30747
30801
  }
30748
- };
30802
+ }, []);
30749
30803
  const canAdd = !readOnly && !!onAdd;
30750
30804
  const canRemove = !readOnly && !!onRemove;
30805
+ const canSetDefault = !readOnly && !!onSetDefault;
30806
+ const canLabel = !readOnly && !!onLabel;
30807
+ const canConnect = !readOnly && !!onConnect;
30808
+ const getSafeExplorerUrl = React.useCallback(
30809
+ (address) => {
30810
+ if (!getExplorerUrl) return null;
30811
+ try {
30812
+ const url = getExplorerUrl(address);
30813
+ if (!url) return null;
30814
+ const parsed = new URL(url);
30815
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return null;
30816
+ return parsed.toString();
30817
+ } catch {
30818
+ return null;
30819
+ }
30820
+ },
30821
+ [getExplorerUrl]
30822
+ );
30751
30823
  const handleAdd = async () => {
30752
30824
  const trimmed = newAddress.trim();
30753
30825
  const error2 = validateEthereumAddress(trimmed);
@@ -30775,8 +30847,191 @@ function WalletList({
30775
30847
  setRemoveError("Failed to remove wallet. Please try again.");
30776
30848
  }
30777
30849
  };
30778
- if (wallets.length === 0 && !showAddForm) {
30779
- return /* @__PURE__ */ jsxRuntime.jsx(
30850
+ const handleSetDefault = async (address) => {
30851
+ setSetDefaultError(null);
30852
+ try {
30853
+ await onSetDefault?.(address);
30854
+ } catch {
30855
+ setSetDefaultError("Failed to set default wallet. Please try again.");
30856
+ }
30857
+ };
30858
+ const handleLabelSave = async (address) => {
30859
+ setLabelError(null);
30860
+ try {
30861
+ await onLabel?.(address, renameValue.trim() || null);
30862
+ setRenamingAddress((current) => current === address ? null : current);
30863
+ } catch {
30864
+ setLabelError("Failed to update label. Please try again.");
30865
+ }
30866
+ };
30867
+ const hasWallets = wallets.length > 0;
30868
+ if (!hasWallets && !showAddForm && !canConnect) {
30869
+ return /* @__PURE__ */ jsxRuntime.jsxs(Stack, { gap: "sm", children: [
30870
+ /* @__PURE__ */ jsxRuntime.jsx(
30871
+ EmptyState,
30872
+ {
30873
+ icon: emptyIcon,
30874
+ title: "No wallets connected",
30875
+ description: "Add a wallet address to receive equity on-chain.",
30876
+ actionLabel: canAdd ? "Add Wallet" : void 0,
30877
+ onAction: canAdd ? () => setShowAddForm(true) : void 0
30878
+ }
30879
+ ),
30880
+ children
30881
+ ] });
30882
+ }
30883
+ return /* @__PURE__ */ jsxRuntime.jsxs(Stack, { gap: "sm", children: [
30884
+ wallets.map((w) => {
30885
+ const normalizedWalletAddress = normalizeWalletAddress(w.address);
30886
+ const setDefaultActionLoading = setDefaultLoading && (!setDefaultAddress || normalizeWalletAddress(setDefaultAddress) === normalizedWalletAddress);
30887
+ const labelActionLoading = labelLoading && (!labelAddress || normalizeWalletAddress(labelAddress) === normalizedWalletAddress);
30888
+ const explorerUrl = getSafeExplorerUrl(w.address);
30889
+ return /* @__PURE__ */ jsxRuntime.jsxs(Stack, { gap: 0, children: [
30890
+ /* @__PURE__ */ jsxRuntime.jsxs(
30891
+ Group,
30892
+ {
30893
+ justify: "space-between",
30894
+ p: "xs",
30895
+ style: {
30896
+ borderRadius: radii.sm,
30897
+ border: `1px solid ${neutralColors[200]}`
30898
+ },
30899
+ children: [
30900
+ /* @__PURE__ */ jsxRuntime.jsxs(Group, { gap: "xs", children: [
30901
+ /* @__PURE__ */ jsxRuntime.jsx(Badge, { size: "xs", variant: "light", children: getWalletLabel(w.type, typeLabels) }),
30902
+ w.label && /* @__PURE__ */ jsxRuntime.jsx(Text, { size: "xs", c: fairmintVars.colorTextSecondary, children: w.label }),
30903
+ w.defaultRecipient && /* @__PURE__ */ jsxRuntime.jsx(Badge, { size: "xs", color: colors.success, variant: "light", children: "Default" }),
30904
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: "sm", ff: "monospace", children: truncateAddress(w.address) })
30905
+ ] }),
30906
+ /* @__PURE__ */ jsxRuntime.jsxs(Group, { gap: 4, children: [
30907
+ copyIcon && /* @__PURE__ */ jsxRuntime.jsx(Tooltip, { label: copiedAddress === w.address ? "Copied!" : "Copy address", children: /* @__PURE__ */ jsxRuntime.jsx(
30908
+ ActionIcon,
30909
+ {
30910
+ variant: "subtle",
30911
+ size: "sm",
30912
+ onClick: () => copyAddress(w.address),
30913
+ "aria-label": "Copy wallet address",
30914
+ children: copiedAddress === w.address ? copiedIcon ?? copyIcon : copyIcon
30915
+ }
30916
+ ) }),
30917
+ canSetDefault && defaultIcon && !w.defaultRecipient && /* @__PURE__ */ jsxRuntime.jsx(Tooltip, { label: "Set as default recipient", children: /* @__PURE__ */ jsxRuntime.jsx(
30918
+ ActionIcon,
30919
+ {
30920
+ variant: "subtle",
30921
+ size: "sm",
30922
+ onClick: () => handleSetDefault(w.address),
30923
+ loading: setDefaultActionLoading,
30924
+ disabled: setDefaultActionLoading,
30925
+ "aria-label": "Set as default wallet",
30926
+ children: defaultIcon
30927
+ }
30928
+ ) }),
30929
+ canLabel && renameIcon && /* @__PURE__ */ jsxRuntime.jsx(
30930
+ Tooltip,
30931
+ {
30932
+ label: renamingAddress === w.address ? "Cancel rename" : "Rename wallet",
30933
+ children: /* @__PURE__ */ jsxRuntime.jsx(
30934
+ ActionIcon,
30935
+ {
30936
+ variant: "subtle",
30937
+ size: "sm",
30938
+ onClick: () => {
30939
+ setLabelError(null);
30940
+ if (renamingAddress === w.address) {
30941
+ setRenamingAddress(null);
30942
+ } else {
30943
+ setRenamingAddress(w.address);
30944
+ setRenameValue(w.label ?? "");
30945
+ }
30946
+ },
30947
+ "aria-label": "Rename wallet",
30948
+ children: renameIcon
30949
+ }
30950
+ )
30951
+ }
30952
+ ),
30953
+ explorerUrl && explorerIcon && /* @__PURE__ */ jsxRuntime.jsx(Tooltip, { label: "View on block explorer", children: /* @__PURE__ */ jsxRuntime.jsx(
30954
+ Anchor,
30955
+ {
30956
+ href: explorerUrl,
30957
+ target: "_blank",
30958
+ rel: "noopener noreferrer",
30959
+ "aria-label": "View on block explorer",
30960
+ c: colors.primary,
30961
+ style: {
30962
+ display: "inline-flex",
30963
+ alignItems: "center",
30964
+ justifyContent: "center",
30965
+ width: "1.625rem",
30966
+ height: "1.625rem",
30967
+ borderRadius: radii.sm
30968
+ },
30969
+ children: explorerIcon
30970
+ }
30971
+ ) }),
30972
+ canRemove && removeIcon && (removableTypes ? removableTypes.some(
30973
+ (t) => normalizeWalletType(t) === normalizeWalletType(w.type)
30974
+ ) : isRemovableWalletType(w.type)) && /* @__PURE__ */ jsxRuntime.jsx(Tooltip, { label: "Remove wallet", children: /* @__PURE__ */ jsxRuntime.jsx(
30975
+ ActionIcon,
30976
+ {
30977
+ variant: "subtle",
30978
+ size: "sm",
30979
+ color: colors.error,
30980
+ onClick: () => setWalletToRemove(w.address),
30981
+ disabled: removeLoading,
30982
+ "aria-label": "Remove wallet",
30983
+ children: removeIcon
30984
+ }
30985
+ ) })
30986
+ ] })
30987
+ ]
30988
+ }
30989
+ ),
30990
+ renamingAddress === w.address && /* @__PURE__ */ jsxRuntime.jsxs(Group, { gap: "xs", mt: "xs", align: "flex-start", children: [
30991
+ /* @__PURE__ */ jsxRuntime.jsx(
30992
+ TextInput,
30993
+ {
30994
+ value: renameValue,
30995
+ onChange: (e) => {
30996
+ setRenameValue(e.currentTarget.value);
30997
+ setLabelError(null);
30998
+ },
30999
+ placeholder: getWalletLabel(w.type, typeLabels),
31000
+ size: "xs",
31001
+ style: { flex: 1 },
31002
+ "aria-label": "Wallet label",
31003
+ maxLength: 50,
31004
+ error: labelError
31005
+ }
31006
+ ),
31007
+ /* @__PURE__ */ jsxRuntime.jsx(
31008
+ Button,
31009
+ {
31010
+ size: "xs",
31011
+ loading: labelActionLoading,
31012
+ disabled: labelActionLoading,
31013
+ onClick: () => handleLabelSave(w.address),
31014
+ children: "Save"
31015
+ }
31016
+ ),
31017
+ /* @__PURE__ */ jsxRuntime.jsx(
31018
+ Button,
31019
+ {
31020
+ size: "xs",
31021
+ variant: "subtle",
31022
+ color: colors.neutral,
31023
+ onClick: () => {
31024
+ setRenamingAddress(null);
31025
+ setLabelError(null);
31026
+ },
31027
+ children: "Cancel"
31028
+ }
31029
+ )
31030
+ ] })
31031
+ ] }, walletKey(w));
31032
+ }),
31033
+ setDefaultError && /* @__PURE__ */ jsxRuntime.jsx(Text, { size: "sm", c: colors.error, children: setDefaultError }),
31034
+ !hasWallets && !showAddForm && /* @__PURE__ */ jsxRuntime.jsx(
30780
31035
  EmptyState,
30781
31036
  {
30782
31037
  icon: emptyIcon,
@@ -30785,52 +31040,19 @@ function WalletList({
30785
31040
  actionLabel: canAdd ? "Add Wallet" : void 0,
30786
31041
  onAction: canAdd ? () => setShowAddForm(true) : void 0
30787
31042
  }
30788
- );
30789
- }
30790
- return /* @__PURE__ */ jsxRuntime.jsxs(Stack, { gap: "sm", children: [
30791
- wallets.map((w) => /* @__PURE__ */ jsxRuntime.jsxs(
30792
- Group,
31043
+ ),
31044
+ canConnect && /* @__PURE__ */ jsxRuntime.jsx(
31045
+ Button,
30793
31046
  {
30794
- justify: "space-between",
30795
- p: "xs",
30796
- style: {
30797
- borderRadius: radii.sm,
30798
- border: `1px solid ${neutralColors[200]}`
30799
- },
30800
- children: [
30801
- /* @__PURE__ */ jsxRuntime.jsxs(Group, { gap: "xs", children: [
30802
- /* @__PURE__ */ jsxRuntime.jsx(Badge, { size: "xs", variant: "light", children: getTypeLabel(w.type, typeLabels) }),
30803
- w.label && /* @__PURE__ */ jsxRuntime.jsx(Text, { size: "xs", c: fairmintVars.colorTextSecondary, children: w.label }),
30804
- /* @__PURE__ */ jsxRuntime.jsx(Text, { size: "sm", ff: "monospace", children: truncateAddress(w.address) })
30805
- ] }),
30806
- /* @__PURE__ */ jsxRuntime.jsxs(Group, { gap: 4, children: [
30807
- copyIcon && /* @__PURE__ */ jsxRuntime.jsx(Tooltip, { label: copiedAddress === w.address ? "Copied!" : "Copy address", children: /* @__PURE__ */ jsxRuntime.jsx(
30808
- ActionIcon,
30809
- {
30810
- variant: "subtle",
30811
- size: "sm",
30812
- onClick: () => copyAddress(w.address),
30813
- "aria-label": "Copy wallet address",
30814
- children: copiedAddress === w.address ? copiedIcon ?? copyIcon : copyIcon
30815
- }
30816
- ) }),
30817
- canRemove && removeIcon && removableTypes.includes(w.type) && /* @__PURE__ */ jsxRuntime.jsx(Tooltip, { label: "Remove wallet", children: /* @__PURE__ */ jsxRuntime.jsx(
30818
- ActionIcon,
30819
- {
30820
- variant: "subtle",
30821
- size: "sm",
30822
- color: colors.error,
30823
- onClick: () => setWalletToRemove(w.address),
30824
- disabled: removeLoading,
30825
- "aria-label": "Remove wallet",
30826
- children: removeIcon
30827
- }
30828
- ) })
30829
- ] })
30830
- ]
30831
- },
30832
- w.address
30833
- )),
31047
+ variant: "light",
31048
+ size: "xs",
31049
+ leftSection: connectIcon,
31050
+ onClick: onConnect,
31051
+ loading: connectLoading,
31052
+ mt: "xs",
31053
+ children: "Connect Wallet"
31054
+ }
31055
+ ),
30834
31056
  canAdd && (showAddForm ? /* @__PURE__ */ jsxRuntime.jsxs(Group, { gap: "xs", mt: "xs", children: [
30835
31057
  /* @__PURE__ */ jsxRuntime.jsx(
30836
31058
  TextInput,
@@ -30861,7 +31083,7 @@ function WalletList({
30861
31083
  children: "Cancel"
30862
31084
  }
30863
31085
  )
30864
- ] }) : /* @__PURE__ */ jsxRuntime.jsx(
31086
+ ] }) : hasWallets ? /* @__PURE__ */ jsxRuntime.jsx(
30865
31087
  Button,
30866
31088
  {
30867
31089
  variant: "light",
@@ -30871,7 +31093,8 @@ function WalletList({
30871
31093
  mt: "xs",
30872
31094
  children: "Add Wallet"
30873
31095
  }
30874
- )),
31096
+ ) : null),
31097
+ children,
30875
31098
  /* @__PURE__ */ jsxRuntime.jsx(
30876
31099
  ConfirmDialog,
30877
31100
  {
@@ -31030,14 +31253,20 @@ exports.formatPhone = formatPhone;
31030
31253
  exports.formatPhoneDisplay = formatPhoneDisplay;
31031
31254
  exports.formatPreciseWithCurrency = formatPreciseWithCurrency;
31032
31255
  exports.getAvatarColor = getAvatarColor;
31256
+ exports.getWalletDisplayName = getWalletDisplayName;
31257
+ exports.getWalletLabel = getWalletLabel;
31033
31258
  exports.isEthereumAddress = isEthereumAddress;
31259
+ exports.isRemovableWalletType = isRemovableWalletType;
31260
+ exports.isSystemWalletType = isSystemWalletType;
31034
31261
  exports.neutralColors = neutralColors;
31035
31262
  exports.normalizePhone = normalizePhone;
31263
+ exports.normalizeWalletType = normalizeWalletType;
31036
31264
  exports.notify = notify;
31037
31265
  exports.passwordSchema = passwordSchema;
31038
31266
  exports.phoneSchema = phoneSchema;
31039
31267
  exports.radii = radii;
31040
31268
  exports.semanticColors = semanticColors;
31269
+ exports.spacing = spacing;
31041
31270
  exports.theme = theme;
31042
31271
  exports.truncateAddress = truncateAddress;
31043
31272
  exports.typography = typography;
@@ -31055,6 +31284,7 @@ exports.useMediaQuery = useMediaQuery;
31055
31284
  exports.useScrollIntoView = useScrollIntoView;
31056
31285
  exports.useViewportSize = useViewportSize;
31057
31286
  exports.validateEthereumAddress = validateEthereumAddress;
31287
+ exports.walletKey = walletKey;
31058
31288
  exports.z = z;
31059
31289
  exports.zipSchema = zipSchema;
31060
31290
  //# sourceMappingURL=fairmint-ui.cjs.map