@fairmint/ui 0.2.3 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/form/EthereumAddressField/EthereumAddressField.d.ts +13 -0
- package/dist/components/form/EthereumAddressField/EthereumAddressField.d.ts.map +1 -0
- package/dist/components/generic/EditableSection/EditableSection.d.ts +43 -0
- package/dist/components/generic/EditableSection/EditableSection.d.ts.map +1 -0
- package/dist/fairmint-ui.cjs +112 -17
- package/dist/fairmint-ui.cjs.map +1 -1
- package/dist/fairmint-ui.js +112 -17
- package/dist/fairmint-ui.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { TextInputProps } from '../../primitives/TextInput/TextInput';
|
|
3
|
+
/**
|
|
4
|
+
* Zod schema for Ethereum wallet address validation.
|
|
5
|
+
* Trims whitespace, then validates `0x` + 40 hex characters, rejecting the zero address.
|
|
6
|
+
*/
|
|
7
|
+
export declare const ethereumAddressSchema: z.ZodEffects<z.ZodString, string, string>;
|
|
8
|
+
export interface EthereumAddressFieldProps extends Omit<TextInputProps, "type"> {
|
|
9
|
+
error?: string;
|
|
10
|
+
}
|
|
11
|
+
/** Ethereum wallet address input with monospace font and Zod-based validation via `ethereumAddressSchema`. */
|
|
12
|
+
export declare function EthereumAddressField({ error, ...rest }: EthereumAddressFieldProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
//# sourceMappingURL=EthereumAddressField.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EthereumAddressField.d.ts","sourceRoot":"","sources":["../../../../src/components/form/EthereumAddressField/EthereumAddressField.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAG3E;;;GAGG;AACH,eAAO,MAAM,qBAAqB,2CAU/B,CAAC;AAEJ,MAAM,WAAW,yBAA0B,SAAQ,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,8GAA8G;AAC9G,wBAAgB,oBAAoB,CAAC,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,EAAE,yBAAyB,2CAcjF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export interface EditableSectionProps {
|
|
3
|
+
/** Section heading shown in the header row. */
|
|
4
|
+
title?: ReactNode;
|
|
5
|
+
/** Content rendered in read (non-editing) mode. */
|
|
6
|
+
readView: ReactNode;
|
|
7
|
+
/**
|
|
8
|
+
* Called when Save is clicked. Resolve to close edit mode; throw to stay open
|
|
9
|
+
* (e.g. validation failure or API error — handle `notify.error` inside here).
|
|
10
|
+
*/
|
|
11
|
+
onSave: () => Promise<void>;
|
|
12
|
+
/** Called when Cancel is clicked, before the edit mode closes. Use to reset form state. */
|
|
13
|
+
onCancel?: () => void;
|
|
14
|
+
/**
|
|
15
|
+
* When true the edit button is hidden and any open edit session is closed.
|
|
16
|
+
* Pass `isViewingAs` to prevent edits during admin impersonation.
|
|
17
|
+
*/
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Called when `onSave` throws. Use for logging or error tracking. The
|
|
21
|
+
* component stays in edit mode regardless — this is purely observational.
|
|
22
|
+
*/
|
|
23
|
+
onSaveError?: (error: unknown) => void;
|
|
24
|
+
/**
|
|
25
|
+
* Icon rendered inside the edit `ActionIcon`. When omitted a plain text
|
|
26
|
+
* "Edit" button is shown instead.
|
|
27
|
+
*/
|
|
28
|
+
editIcon?: ReactNode;
|
|
29
|
+
/** Save button label. @default "Save" */
|
|
30
|
+
saveLabel?: string;
|
|
31
|
+
/** Cancel button label. @default "Cancel" */
|
|
32
|
+
cancelLabel?: string;
|
|
33
|
+
/** Children rendered in edit mode (form fields, etc.). */
|
|
34
|
+
children: ReactNode;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Wraps a section of the page with a pencil-icon toggle between a read view
|
|
38
|
+
* and an edit view. Manages `isEditing` and `isSaving` state internally so
|
|
39
|
+
* consumers only need to supply `readView`, the edit fields as `children`,
|
|
40
|
+
* and the async `onSave` callback.
|
|
41
|
+
*/
|
|
42
|
+
export declare function EditableSection({ title, readView, onSave, onCancel, disabled, onSaveError, editIcon, saveLabel, cancelLabel, children, }: EditableSectionProps): import("react/jsx-runtime").JSX.Element;
|
|
43
|
+
//# sourceMappingURL=EditableSection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EditableSection.d.ts","sourceRoot":"","sources":["../../../../src/components/generic/EditableSection/EditableSection.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAuB,MAAM,OAAO,CAAC;AAM5D,MAAM,WAAW,oBAAoB;IACnC,+CAA+C;IAC/C,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,mDAAmD;IACnD,QAAQ,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,2FAA2F;IAC3F,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,QAAgB,EAChB,WAAW,EACX,QAAQ,EACR,SAAkB,EAClB,WAAsB,EACtB,QAAQ,GACT,EAAE,oBAAoB,2CAwFtB"}
|
package/dist/fairmint-ui.cjs
CHANGED
|
@@ -23751,6 +23751,46 @@ function EmailField({ error: error2, ...rest }) {
|
|
|
23751
23751
|
}
|
|
23752
23752
|
);
|
|
23753
23753
|
}
|
|
23754
|
+
function truncateAddress(address, chars = 4) {
|
|
23755
|
+
if (address.length <= chars * 2 + 2) return address;
|
|
23756
|
+
return `${address.slice(0, chars + 2)}...${address.slice(-chars)}`;
|
|
23757
|
+
}
|
|
23758
|
+
const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
23759
|
+
const ETH_ADDRESS_RE = /^0x[a-fA-F0-9]{40}$/;
|
|
23760
|
+
function isEthereumAddress(value) {
|
|
23761
|
+
return ETH_ADDRESS_RE.test(value) && value.toLowerCase() !== ZERO_ADDRESS;
|
|
23762
|
+
}
|
|
23763
|
+
function validateEthereumAddress(value) {
|
|
23764
|
+
if (!ETH_ADDRESS_RE.test(value))
|
|
23765
|
+
return "Must be a valid Ethereum address (0x + 40 hex characters)";
|
|
23766
|
+
if (value.toLowerCase() === ZERO_ADDRESS) return "Cannot use the zero address";
|
|
23767
|
+
return null;
|
|
23768
|
+
}
|
|
23769
|
+
const ETHEREUM_ADDRESS_REGEX = ETH_ADDRESS_RE;
|
|
23770
|
+
const ZERO_ETHEREUM_ADDRESS = ZERO_ADDRESS;
|
|
23771
|
+
const ethereumAddressSchema = stringType().trim().regex(
|
|
23772
|
+
ETHEREUM_ADDRESS_REGEX,
|
|
23773
|
+
"Must be a valid Ethereum address (0x followed by 40 hex characters)"
|
|
23774
|
+
).refine(
|
|
23775
|
+
(v) => v.toLowerCase() !== ZERO_ETHEREUM_ADDRESS.toLowerCase(),
|
|
23776
|
+
"Cannot use the zero address"
|
|
23777
|
+
);
|
|
23778
|
+
function EthereumAddressField({ error: error2, ...rest }) {
|
|
23779
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
23780
|
+
TextInput,
|
|
23781
|
+
{
|
|
23782
|
+
type: "text",
|
|
23783
|
+
label: rest.label ?? "Wallet Address",
|
|
23784
|
+
placeholder: rest.placeholder ?? "0x...",
|
|
23785
|
+
autoComplete: "off",
|
|
23786
|
+
inputMode: "text",
|
|
23787
|
+
spellCheck: false,
|
|
23788
|
+
styles: { input: { fontFamily: "monospace" } },
|
|
23789
|
+
error: error2,
|
|
23790
|
+
...rest
|
|
23791
|
+
}
|
|
23792
|
+
);
|
|
23793
|
+
}
|
|
23754
23794
|
function validateFormName(name) {
|
|
23755
23795
|
if (!/^[0-9a-zA-Z-]+$/.test(name)) {
|
|
23756
23796
|
throw new Error(
|
|
@@ -25095,6 +25135,75 @@ function DetailDrawer({
|
|
|
25095
25135
|
}
|
|
25096
25136
|
);
|
|
25097
25137
|
}
|
|
25138
|
+
function EditableSection({
|
|
25139
|
+
title,
|
|
25140
|
+
readView,
|
|
25141
|
+
onSave,
|
|
25142
|
+
onCancel,
|
|
25143
|
+
disabled = false,
|
|
25144
|
+
onSaveError,
|
|
25145
|
+
editIcon,
|
|
25146
|
+
saveLabel = "Save",
|
|
25147
|
+
cancelLabel = "Cancel",
|
|
25148
|
+
children
|
|
25149
|
+
}) {
|
|
25150
|
+
const [isEditing, setIsEditing] = React.useState(false);
|
|
25151
|
+
const [isSaving, setIsSaving] = React.useState(false);
|
|
25152
|
+
React.useEffect(() => {
|
|
25153
|
+
if (disabled && isEditing) {
|
|
25154
|
+
onCancel?.();
|
|
25155
|
+
setIsEditing(false);
|
|
25156
|
+
}
|
|
25157
|
+
}, [disabled, isEditing, onCancel]);
|
|
25158
|
+
const handleEdit = () => setIsEditing(true);
|
|
25159
|
+
const handleSave = async () => {
|
|
25160
|
+
setIsSaving(true);
|
|
25161
|
+
try {
|
|
25162
|
+
await onSave();
|
|
25163
|
+
setIsEditing(false);
|
|
25164
|
+
} catch (err) {
|
|
25165
|
+
onSaveError?.(err);
|
|
25166
|
+
} finally {
|
|
25167
|
+
setIsSaving(false);
|
|
25168
|
+
}
|
|
25169
|
+
};
|
|
25170
|
+
const handleCancel = () => {
|
|
25171
|
+
onCancel?.();
|
|
25172
|
+
setIsEditing(false);
|
|
25173
|
+
};
|
|
25174
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Stack, { gap: "md", children: [
|
|
25175
|
+
(title || !disabled && !isEditing) && /* @__PURE__ */ jsxRuntime.jsxs(Group, { justify: "space-between", align: "center", children: [
|
|
25176
|
+
title && /* @__PURE__ */ jsxRuntime.jsx(Text, { fw: 500, size: "sm", children: title }),
|
|
25177
|
+
!disabled && !isEditing && (editIcon ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
25178
|
+
ActionIcon,
|
|
25179
|
+
{
|
|
25180
|
+
variant: "subtle",
|
|
25181
|
+
size: "sm",
|
|
25182
|
+
onClick: handleEdit,
|
|
25183
|
+
"aria-label": `Edit ${typeof title === "string" ? title : "section"}`,
|
|
25184
|
+
children: editIcon
|
|
25185
|
+
}
|
|
25186
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "subtle", size: "xs", onClick: handleEdit, children: "Edit" }))
|
|
25187
|
+
] }),
|
|
25188
|
+
isEditing ? /* @__PURE__ */ jsxRuntime.jsxs(Stack, { gap: "sm", children: [
|
|
25189
|
+
children,
|
|
25190
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Group, { gap: "xs", justify: "flex-end", children: [
|
|
25191
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
25192
|
+
Button,
|
|
25193
|
+
{
|
|
25194
|
+
variant: "subtle",
|
|
25195
|
+
size: "xs",
|
|
25196
|
+
color: colors.neutral,
|
|
25197
|
+
onClick: handleCancel,
|
|
25198
|
+
disabled: isSaving,
|
|
25199
|
+
children: cancelLabel
|
|
25200
|
+
}
|
|
25201
|
+
),
|
|
25202
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { size: "xs", onClick: handleSave, loading: isSaving, children: saveLabel })
|
|
25203
|
+
] })
|
|
25204
|
+
] }) : readView
|
|
25205
|
+
] });
|
|
25206
|
+
}
|
|
25098
25207
|
const DefaultChevronIcon = () => /* @__PURE__ */ jsxRuntime.jsx(
|
|
25099
25208
|
"svg",
|
|
25100
25209
|
{
|
|
@@ -25556,23 +25665,6 @@ function InvestorProfileCard({
|
|
|
25556
25665
|
children
|
|
25557
25666
|
] });
|
|
25558
25667
|
}
|
|
25559
|
-
function truncateAddress(address, chars = 4) {
|
|
25560
|
-
if (address.length <= chars * 2 + 2) return address;
|
|
25561
|
-
return `${address.slice(0, chars + 2)}...${address.slice(-chars)}`;
|
|
25562
|
-
}
|
|
25563
|
-
const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
25564
|
-
const ETH_ADDRESS_RE = /^0x[a-fA-F0-9]{40}$/;
|
|
25565
|
-
function isEthereumAddress(value) {
|
|
25566
|
-
return ETH_ADDRESS_RE.test(value) && value.toLowerCase() !== ZERO_ADDRESS;
|
|
25567
|
-
}
|
|
25568
|
-
function validateEthereumAddress(value) {
|
|
25569
|
-
if (!ETH_ADDRESS_RE.test(value))
|
|
25570
|
-
return "Must be a valid Ethereum address (0x + 40 hex characters)";
|
|
25571
|
-
if (value.toLowerCase() === ZERO_ADDRESS) return "Cannot use the zero address";
|
|
25572
|
-
return null;
|
|
25573
|
-
}
|
|
25574
|
-
const ETHEREUM_ADDRESS_REGEX = ETH_ADDRESS_RE;
|
|
25575
|
-
const ZERO_ETHEREUM_ADDRESS = ZERO_ADDRESS;
|
|
25576
25668
|
const DEFAULT_TYPE_LABELS = {
|
|
25577
25669
|
fairmint: "Fairmint Wallet",
|
|
25578
25670
|
privy: "Fairmint Wallet",
|
|
@@ -25816,10 +25908,12 @@ exports.Divider = Divider;
|
|
|
25816
25908
|
exports.DocumentRow = DocumentRow;
|
|
25817
25909
|
exports.Drawer = Drawer;
|
|
25818
25910
|
exports.ETHEREUM_ADDRESS_REGEX = ETHEREUM_ADDRESS_REGEX;
|
|
25911
|
+
exports.EditableSection = EditableSection;
|
|
25819
25912
|
exports.EmailField = EmailField;
|
|
25820
25913
|
exports.EmptyState = EmptyState;
|
|
25821
25914
|
exports.EquityGrantCard = EquityGrantCard;
|
|
25822
25915
|
exports.ErrorFallback = ErrorFallback;
|
|
25916
|
+
exports.EthereumAddressField = EthereumAddressField;
|
|
25823
25917
|
exports.FairmintLogo = FairmintLogo;
|
|
25824
25918
|
exports.FairmintProvider = FairmintProvider;
|
|
25825
25919
|
exports.Flex = Flex;
|
|
@@ -25866,6 +25960,7 @@ exports.brandColors = brandColors;
|
|
|
25866
25960
|
exports.colors = colors;
|
|
25867
25961
|
exports.createZipSchema = createZipSchema;
|
|
25868
25962
|
exports.emailSchema = emailSchema;
|
|
25963
|
+
exports.ethereumAddressSchema = ethereumAddressSchema;
|
|
25869
25964
|
exports.formatCurrency = formatCurrency;
|
|
25870
25965
|
exports.formatCurrencyPrecise = formatCurrencyPrecise;
|
|
25871
25966
|
exports.formatDate = formatDate;
|