@fairmint/ui 0.2.1 → 0.2.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.
- package/dist/components/form/ZipField/ZipField.d.ts +25 -0
- package/dist/components/form/ZipField/ZipField.d.ts.map +1 -0
- package/dist/components/specific/WalletList/WalletList.d.ts +45 -0
- package/dist/components/specific/WalletList/WalletList.d.ts.map +1 -0
- package/dist/fairmint-ui.cjs +236 -4
- package/dist/fairmint-ui.cjs.map +1 -1
- package/dist/fairmint-ui.js +237 -5
- package/dist/fairmint-ui.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/utils/address.d.ts +13 -0
- package/dist/utils/address.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/fairmint-ui.js
CHANGED
|
@@ -24822,6 +24822,29 @@ function PhoneField({ error: error2, ...rest }) {
|
|
|
24822
24822
|
}
|
|
24823
24823
|
);
|
|
24824
24824
|
}
|
|
24825
|
+
const US_ZIP_REGEX = /^\d{5}(-\d{4})?$/;
|
|
24826
|
+
const INTL_POSTAL_REGEX = /^[A-Z0-9]+(?:[ -][A-Z0-9]+)*$/i;
|
|
24827
|
+
function createZipSchema(options) {
|
|
24828
|
+
if (options?.international) {
|
|
24829
|
+
return stringType().trim().min(3, "Please enter a valid postal code").max(10, "Please enter a valid postal code").regex(INTL_POSTAL_REGEX, "Please enter a valid postal code");
|
|
24830
|
+
}
|
|
24831
|
+
return stringType().trim().regex(US_ZIP_REGEX, "Please enter a valid ZIP code (e.g. 94105 or 94105-1234)");
|
|
24832
|
+
}
|
|
24833
|
+
const zipSchema = createZipSchema();
|
|
24834
|
+
function ZipField({ error: error2, international = false, ...rest }) {
|
|
24835
|
+
return /* @__PURE__ */ jsx(
|
|
24836
|
+
TextInput,
|
|
24837
|
+
{
|
|
24838
|
+
type: "text",
|
|
24839
|
+
label: rest.label ?? "ZIP / Postal Code",
|
|
24840
|
+
placeholder: rest.placeholder ?? (international ? "SW1A 2AA" : "94105"),
|
|
24841
|
+
autoComplete: "postal-code",
|
|
24842
|
+
inputMode: "text",
|
|
24843
|
+
error: error2,
|
|
24844
|
+
...rest
|
|
24845
|
+
}
|
|
24846
|
+
);
|
|
24847
|
+
}
|
|
24825
24848
|
const ANIMATION_MAP = {
|
|
24826
24849
|
up: "fadeUp",
|
|
24827
24850
|
down: "fadeDown",
|
|
@@ -25515,6 +25538,211 @@ function InvestorProfileCard({
|
|
|
25515
25538
|
children
|
|
25516
25539
|
] });
|
|
25517
25540
|
}
|
|
25541
|
+
function truncateAddress(address, chars = 4) {
|
|
25542
|
+
if (address.length <= chars * 2 + 2) return address;
|
|
25543
|
+
return `${address.slice(0, chars + 2)}...${address.slice(-chars)}`;
|
|
25544
|
+
}
|
|
25545
|
+
const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
25546
|
+
const ETH_ADDRESS_RE = /^0x[a-fA-F0-9]{40}$/;
|
|
25547
|
+
function isEthereumAddress(value) {
|
|
25548
|
+
return ETH_ADDRESS_RE.test(value) && value.toLowerCase() !== ZERO_ADDRESS;
|
|
25549
|
+
}
|
|
25550
|
+
function validateEthereumAddress(value) {
|
|
25551
|
+
if (!ETH_ADDRESS_RE.test(value))
|
|
25552
|
+
return "Must be a valid Ethereum address (0x + 40 hex characters)";
|
|
25553
|
+
if (value.toLowerCase() === ZERO_ADDRESS) return "Cannot use the zero address";
|
|
25554
|
+
return null;
|
|
25555
|
+
}
|
|
25556
|
+
const ETHEREUM_ADDRESS_REGEX = ETH_ADDRESS_RE;
|
|
25557
|
+
const ZERO_ETHEREUM_ADDRESS = ZERO_ADDRESS;
|
|
25558
|
+
const DEFAULT_TYPE_LABELS = {
|
|
25559
|
+
fairmint: "Fairmint Wallet",
|
|
25560
|
+
privy: "Fairmint Wallet",
|
|
25561
|
+
manual: "Manual"
|
|
25562
|
+
};
|
|
25563
|
+
function getTypeLabel(type, custom2) {
|
|
25564
|
+
if (custom2?.[type]) return custom2[type];
|
|
25565
|
+
return DEFAULT_TYPE_LABELS[type] ?? type;
|
|
25566
|
+
}
|
|
25567
|
+
function WalletList({
|
|
25568
|
+
wallets,
|
|
25569
|
+
onAdd,
|
|
25570
|
+
onRemove,
|
|
25571
|
+
readOnly = false,
|
|
25572
|
+
addLoading = false,
|
|
25573
|
+
removeLoading = false,
|
|
25574
|
+
emptyIcon,
|
|
25575
|
+
copyIcon,
|
|
25576
|
+
copiedIcon,
|
|
25577
|
+
removeIcon,
|
|
25578
|
+
addIcon,
|
|
25579
|
+
typeLabels,
|
|
25580
|
+
removableTypes = ["manual"]
|
|
25581
|
+
}) {
|
|
25582
|
+
const [newAddress, setNewAddress] = useState("");
|
|
25583
|
+
const [addressError, setAddressError] = useState(null);
|
|
25584
|
+
const [showAddForm, setShowAddForm] = useState(false);
|
|
25585
|
+
const [walletToRemove, setWalletToRemove] = useState(null);
|
|
25586
|
+
const [copiedAddress, setCopiedAddress] = useState(null);
|
|
25587
|
+
const copyTimeoutRef = useRef(void 0);
|
|
25588
|
+
useEffect(() => () => clearTimeout(copyTimeoutRef.current), []);
|
|
25589
|
+
const copyAddress = async (address) => {
|
|
25590
|
+
try {
|
|
25591
|
+
await navigator.clipboard.writeText(address);
|
|
25592
|
+
clearTimeout(copyTimeoutRef.current);
|
|
25593
|
+
setCopiedAddress(address);
|
|
25594
|
+
copyTimeoutRef.current = setTimeout(() => setCopiedAddress(null), 2e3);
|
|
25595
|
+
} catch {
|
|
25596
|
+
}
|
|
25597
|
+
};
|
|
25598
|
+
const canAdd = !readOnly && !!onAdd;
|
|
25599
|
+
const canRemove = !readOnly && !!onRemove;
|
|
25600
|
+
const handleAdd = async () => {
|
|
25601
|
+
const trimmed = newAddress.trim();
|
|
25602
|
+
const error2 = validateEthereumAddress(trimmed);
|
|
25603
|
+
if (error2) {
|
|
25604
|
+
setAddressError(error2);
|
|
25605
|
+
return;
|
|
25606
|
+
}
|
|
25607
|
+
setAddressError(null);
|
|
25608
|
+
try {
|
|
25609
|
+
await onAdd?.(trimmed);
|
|
25610
|
+
setNewAddress("");
|
|
25611
|
+
setShowAddForm(false);
|
|
25612
|
+
} catch {
|
|
25613
|
+
setAddressError("Failed to add wallet");
|
|
25614
|
+
}
|
|
25615
|
+
};
|
|
25616
|
+
const [removeError, setRemoveError] = useState(null);
|
|
25617
|
+
const handleRemove = async () => {
|
|
25618
|
+
if (!walletToRemove) return;
|
|
25619
|
+
setRemoveError(null);
|
|
25620
|
+
try {
|
|
25621
|
+
await onRemove?.(walletToRemove);
|
|
25622
|
+
setWalletToRemove(null);
|
|
25623
|
+
} catch {
|
|
25624
|
+
setRemoveError("Failed to remove wallet. Please try again.");
|
|
25625
|
+
}
|
|
25626
|
+
};
|
|
25627
|
+
if (wallets.length === 0 && !showAddForm) {
|
|
25628
|
+
return /* @__PURE__ */ jsx(
|
|
25629
|
+
EmptyState,
|
|
25630
|
+
{
|
|
25631
|
+
icon: emptyIcon,
|
|
25632
|
+
title: "No wallets connected",
|
|
25633
|
+
description: "Add a wallet address to receive equity on-chain.",
|
|
25634
|
+
actionLabel: canAdd ? "Add Wallet" : void 0,
|
|
25635
|
+
onAction: canAdd ? () => setShowAddForm(true) : void 0
|
|
25636
|
+
}
|
|
25637
|
+
);
|
|
25638
|
+
}
|
|
25639
|
+
return /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
25640
|
+
wallets.map((w) => /* @__PURE__ */ jsxs(
|
|
25641
|
+
Group,
|
|
25642
|
+
{
|
|
25643
|
+
justify: "space-between",
|
|
25644
|
+
p: "xs",
|
|
25645
|
+
style: {
|
|
25646
|
+
borderRadius: "var(--mantine-radius-sm)",
|
|
25647
|
+
border: "1px solid var(--mantine-color-default-border)"
|
|
25648
|
+
},
|
|
25649
|
+
children: [
|
|
25650
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
25651
|
+
/* @__PURE__ */ jsx(Badge, { size: "xs", variant: "light", children: getTypeLabel(w.type, typeLabels) }),
|
|
25652
|
+
w.label && /* @__PURE__ */ jsx(Text, { size: "xs", c: `${colors.neutral}.5`, children: w.label }),
|
|
25653
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", ff: "monospace", children: truncateAddress(w.address) })
|
|
25654
|
+
] }),
|
|
25655
|
+
/* @__PURE__ */ jsxs(Group, { gap: 4, children: [
|
|
25656
|
+
copyIcon && /* @__PURE__ */ jsx(Tooltip, { label: copiedAddress === w.address ? "Copied!" : "Copy address", children: /* @__PURE__ */ jsx(
|
|
25657
|
+
ActionIcon,
|
|
25658
|
+
{
|
|
25659
|
+
variant: "subtle",
|
|
25660
|
+
size: "sm",
|
|
25661
|
+
onClick: () => copyAddress(w.address),
|
|
25662
|
+
"aria-label": "Copy wallet address",
|
|
25663
|
+
children: copiedAddress === w.address ? copiedIcon ?? copyIcon : copyIcon
|
|
25664
|
+
}
|
|
25665
|
+
) }),
|
|
25666
|
+
canRemove && removeIcon && removableTypes.includes(w.type) && /* @__PURE__ */ jsx(Tooltip, { label: "Remove wallet", children: /* @__PURE__ */ jsx(
|
|
25667
|
+
ActionIcon,
|
|
25668
|
+
{
|
|
25669
|
+
variant: "subtle",
|
|
25670
|
+
size: "sm",
|
|
25671
|
+
color: colors.error,
|
|
25672
|
+
onClick: () => setWalletToRemove(w.address),
|
|
25673
|
+
disabled: removeLoading,
|
|
25674
|
+
"aria-label": "Remove wallet",
|
|
25675
|
+
children: removeIcon
|
|
25676
|
+
}
|
|
25677
|
+
) })
|
|
25678
|
+
] })
|
|
25679
|
+
]
|
|
25680
|
+
},
|
|
25681
|
+
w.address
|
|
25682
|
+
)),
|
|
25683
|
+
canAdd && (showAddForm ? /* @__PURE__ */ jsxs(Group, { gap: "xs", mt: "xs", children: [
|
|
25684
|
+
/* @__PURE__ */ jsx(
|
|
25685
|
+
TextInput,
|
|
25686
|
+
{
|
|
25687
|
+
placeholder: "0x...",
|
|
25688
|
+
"aria-label": "Wallet address",
|
|
25689
|
+
value: newAddress,
|
|
25690
|
+
onChange: (e) => {
|
|
25691
|
+
setNewAddress(e.currentTarget.value);
|
|
25692
|
+
setAddressError(null);
|
|
25693
|
+
},
|
|
25694
|
+
error: addressError,
|
|
25695
|
+
style: { flex: 1 }
|
|
25696
|
+
}
|
|
25697
|
+
),
|
|
25698
|
+
/* @__PURE__ */ jsx(Button, { size: "sm", onClick: handleAdd, loading: addLoading, children: "Add" }),
|
|
25699
|
+
/* @__PURE__ */ jsx(
|
|
25700
|
+
Button,
|
|
25701
|
+
{
|
|
25702
|
+
size: "sm",
|
|
25703
|
+
variant: "subtle",
|
|
25704
|
+
color: colors.neutral,
|
|
25705
|
+
onClick: () => {
|
|
25706
|
+
setShowAddForm(false);
|
|
25707
|
+
setNewAddress("");
|
|
25708
|
+
setAddressError(null);
|
|
25709
|
+
},
|
|
25710
|
+
children: "Cancel"
|
|
25711
|
+
}
|
|
25712
|
+
)
|
|
25713
|
+
] }) : /* @__PURE__ */ jsx(
|
|
25714
|
+
Button,
|
|
25715
|
+
{
|
|
25716
|
+
variant: "light",
|
|
25717
|
+
size: "xs",
|
|
25718
|
+
leftSection: addIcon,
|
|
25719
|
+
onClick: () => setShowAddForm(true),
|
|
25720
|
+
mt: "xs",
|
|
25721
|
+
children: "Add Wallet"
|
|
25722
|
+
}
|
|
25723
|
+
)),
|
|
25724
|
+
/* @__PURE__ */ jsx(
|
|
25725
|
+
ConfirmDialog,
|
|
25726
|
+
{
|
|
25727
|
+
title: "Remove Wallet",
|
|
25728
|
+
message: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
25729
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", children: "Are you sure you want to remove this wallet address? This action cannot be undone." }),
|
|
25730
|
+
walletToRemove && /* @__PURE__ */ jsx(Text, { size: "sm", ff: "monospace", c: `${colors.neutral}.5`, children: walletToRemove }),
|
|
25731
|
+
removeError && /* @__PURE__ */ jsx(Text, { size: "sm", c: colors.error, children: removeError })
|
|
25732
|
+
] }),
|
|
25733
|
+
opened: walletToRemove !== null,
|
|
25734
|
+
confirmLabel: "Remove",
|
|
25735
|
+
confirmColor: colors.error,
|
|
25736
|
+
onConfirm: handleRemove,
|
|
25737
|
+
onCancel: () => {
|
|
25738
|
+
setWalletToRemove(null);
|
|
25739
|
+
setRemoveError(null);
|
|
25740
|
+
},
|
|
25741
|
+
loading: removeLoading
|
|
25742
|
+
}
|
|
25743
|
+
)
|
|
25744
|
+
] });
|
|
25745
|
+
}
|
|
25518
25746
|
function useDebouncedCallback(fn, delay) {
|
|
25519
25747
|
const timer = useRef(null);
|
|
25520
25748
|
const fnRef = useRef(fn);
|
|
@@ -25546,10 +25774,6 @@ const notify = {
|
|
|
25546
25774
|
warning: ({ title, message, autoClose = 5e3 }) => notifications.show({ title, message, color: colors.warning, autoClose }),
|
|
25547
25775
|
info: ({ title, message, autoClose = 4e3 }) => notifications.show({ title, message, color: colors.info, autoClose })
|
|
25548
25776
|
};
|
|
25549
|
-
function truncateAddress(address, chars = 4) {
|
|
25550
|
-
if (address.length <= chars * 2 + 2) return address;
|
|
25551
|
-
return `${address.slice(0, chars + 2)}...${address.slice(-chars)}`;
|
|
25552
|
-
}
|
|
25553
25777
|
export {
|
|
25554
25778
|
AVATAR_PALETTE,
|
|
25555
25779
|
ActionIcon,
|
|
@@ -25574,6 +25798,7 @@ export {
|
|
|
25574
25798
|
Divider,
|
|
25575
25799
|
DocumentRow,
|
|
25576
25800
|
Drawer,
|
|
25801
|
+
ETHEREUM_ADDRESS_REGEX,
|
|
25577
25802
|
EmailField,
|
|
25578
25803
|
EmptyState,
|
|
25579
25804
|
EquityGrantCard,
|
|
@@ -25617,8 +25842,12 @@ export {
|
|
|
25617
25842
|
Title,
|
|
25618
25843
|
Tooltip,
|
|
25619
25844
|
UserMenu,
|
|
25845
|
+
WalletList,
|
|
25846
|
+
ZERO_ETHEREUM_ADDRESS,
|
|
25847
|
+
ZipField,
|
|
25620
25848
|
brandColors,
|
|
25621
25849
|
colors,
|
|
25850
|
+
createZipSchema,
|
|
25622
25851
|
emailSchema,
|
|
25623
25852
|
formatCurrency,
|
|
25624
25853
|
formatCurrencyPrecise,
|
|
@@ -25627,6 +25856,7 @@ export {
|
|
|
25627
25856
|
formatPercent,
|
|
25628
25857
|
formatPreciseWithCurrency,
|
|
25629
25858
|
getAvatarColor,
|
|
25859
|
+
isEthereumAddress,
|
|
25630
25860
|
neutralColors,
|
|
25631
25861
|
notify,
|
|
25632
25862
|
passwordSchema,
|
|
@@ -25647,6 +25877,8 @@ export {
|
|
|
25647
25877
|
useMediaQuery,
|
|
25648
25878
|
useScrollIntoView,
|
|
25649
25879
|
useViewportSize,
|
|
25650
|
-
|
|
25880
|
+
validateEthereumAddress,
|
|
25881
|
+
z,
|
|
25882
|
+
zipSchema
|
|
25651
25883
|
};
|
|
25652
25884
|
//# sourceMappingURL=fairmint-ui.js.map
|