@fairmint/ui 0.2.12 → 0.2.13
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/PhoneField.d.ts +31 -2
- package/dist/components/form/PhoneField.d.ts.map +1 -1
- package/dist/components/specific/InvestorProfileCard/InvestorProfileCard.d.ts +5 -1
- package/dist/components/specific/InvestorProfileCard/InvestorProfileCard.d.ts.map +1 -1
- package/dist/fairmint-ui.cjs +85 -6
- package/dist/fairmint-ui.cjs.map +1 -1
- package/dist/fairmint-ui.js +85 -6
- package/dist/fairmint-ui.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,8 +1,37 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { TextInputProps } from '../primitives/TextInput/TextInput';
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Validates that a phone string contains enough digits to be a real number.
|
|
5
|
+
* - Characters allowed: digits, spaces, `(`, `)`, `.`, `-`, and optional leading `+`
|
|
6
|
+
* - Domestic (no +): exactly 10 digits, or 11 digits starting with `1`
|
|
7
|
+
* - US/CA (+1): exactly 11 digits total
|
|
8
|
+
* - Other international (+): 8–15 digits (E.164 range)
|
|
9
|
+
*/
|
|
10
|
+
export declare const phoneSchema: z.ZodEffects<z.ZodString, string, string>;
|
|
11
|
+
/**
|
|
12
|
+
* Formats a phone string for display, progressively as digits are added.
|
|
13
|
+
*
|
|
14
|
+
* - Domestic (no +): `(XXX) XXX-XXXX`
|
|
15
|
+
* - US/CA with +1: `+1 (XXX) XXX-XXXX`
|
|
16
|
+
* - Other international: `+{digits}` (no structural formatting)
|
|
17
|
+
*
|
|
18
|
+
* Idempotent: passing an already-formatted string returns the same result.
|
|
19
|
+
*/
|
|
20
|
+
export declare function formatPhone(raw: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Strips a formatted phone string to E.164-ish digits for API storage.
|
|
23
|
+
*
|
|
24
|
+
* - `(260) 255-5555` → `+12602555555`
|
|
25
|
+
* - `+1 (260) 255-5555` → `+12602555555`
|
|
26
|
+
* - `+44 20 7946 0958` → `+442079460958`
|
|
27
|
+
*
|
|
28
|
+
* Note: 10-digit numbers without `+` are assumed to be US/CA and get `+1`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function normalizePhone(formatted: string): string;
|
|
31
|
+
/** @deprecated Use `formatPhone` instead. */
|
|
32
|
+
export declare const formatPhoneDisplay: typeof formatPhone;
|
|
4
33
|
export interface PhoneFieldProps extends Omit<TextInputProps, "type"> {
|
|
5
34
|
error?: string;
|
|
6
35
|
}
|
|
7
|
-
export declare function PhoneField({ error, ...rest }: PhoneFieldProps): import("react/jsx-runtime").JSX.Element;
|
|
36
|
+
export declare function PhoneField({ error, onChange, value, ...rest }: PhoneFieldProps): import("react/jsx-runtime").JSX.Element;
|
|
8
37
|
//# sourceMappingURL=PhoneField.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PhoneField.d.ts","sourceRoot":"","sources":["../../../src/components/form/PhoneField.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PhoneField.d.ts","sourceRoot":"","sources":["../../../src/components/form/PhoneField.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAGxE;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,2CAUe,CAAC;AAExC;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAwB/C;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAOxD;AAED,6CAA6C;AAC7C,eAAO,MAAM,kBAAkB,oBAAc,CAAC;AAE9C,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,EAAE,eAAe,2CAqD9E"}
|
|
@@ -16,6 +16,10 @@ export interface InvestorProfileCardProps {
|
|
|
16
16
|
children?: ReactNode;
|
|
17
17
|
/** If undefined, no pencil icon is shown. */
|
|
18
18
|
onEditName?: () => void;
|
|
19
|
+
/** When true, the pencil icon is shown but disabled. Requires `onEditName` to be provided. */
|
|
20
|
+
editNameDisabled?: boolean;
|
|
21
|
+
/** Tooltip label shown on the disabled pencil icon. Only used when `editNameDisabled` is true. */
|
|
22
|
+
editNameTooltip?: string;
|
|
19
23
|
/** If undefined, no camera overlay is shown. */
|
|
20
24
|
onUploadPhoto?: () => void;
|
|
21
25
|
/** Shows a centered Loader over the avatar during upload. */
|
|
@@ -31,5 +35,5 @@ export interface InvestorProfileCardProps {
|
|
|
31
35
|
*/
|
|
32
36
|
uploadPhotoIcon?: ReactNode;
|
|
33
37
|
}
|
|
34
|
-
export declare function InvestorProfileCard({ name, email, avatarUrl, verificationStatus, memberSince, subtitle, children, onEditName, onUploadPhoto, photoUploading, editNameIcon, uploadPhotoIcon, }: InvestorProfileCardProps): import("react/jsx-runtime").JSX.Element;
|
|
38
|
+
export declare function InvestorProfileCard({ name, email, avatarUrl, verificationStatus, memberSince, subtitle, children, onEditName, editNameDisabled, editNameTooltip, onUploadPhoto, photoUploading, editNameIcon, uploadPhotoIcon, }: InvestorProfileCardProps): import("react/jsx-runtime").JSX.Element;
|
|
35
39
|
//# sourceMappingURL=InvestorProfileCard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InvestorProfileCard.d.ts","sourceRoot":"","sources":["../../../../src/components/specific/InvestorProfileCard/InvestorProfileCard.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAY,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"InvestorProfileCard.d.ts","sourceRoot":"","sources":["../../../../src/components/specific/InvestorProfileCard/InvestorProfileCard.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAY,MAAM,OAAO,CAAC;AAUjD,MAAM,WAAW,wBAAwB;IACvC,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,wJAAwJ;IACxJ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,8FAA8F;IAC9F,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,kGAAkG;IAClG,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gDAAgD;IAChD,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,6DAA6D;IAC7D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB;;;OAGG;IACH,eAAe,CAAC,EAAE,SAAS,CAAC;CAC7B;AA6CD,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,KAAK,EACL,SAAS,EACT,kBAAkB,EAClB,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,cAAc,EACd,YAAY,EACZ,eAAe,GAChB,EAAE,wBAAwB,2CAuI1B"}
|
package/dist/fairmint-ui.cjs
CHANGED
|
@@ -26886,7 +26886,7 @@ const Tabs = Object.assign(TabsBase, {
|
|
|
26886
26886
|
const TextInput = React.forwardRef((props, ref) => /* @__PURE__ */ jsxRuntime.jsx(TextInput$1, { size: "md", ...props, ref }));
|
|
26887
26887
|
TextInput.displayName = "TextInput";
|
|
26888
26888
|
function Tooltip(props) {
|
|
26889
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Tooltip$1, { ...props });
|
|
26889
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Tooltip$1, { fz: "xs", ...props });
|
|
26890
26890
|
}
|
|
26891
26891
|
function ErrorFallback({
|
|
26892
26892
|
title = "Something went wrong",
|
|
@@ -28245,17 +28245,77 @@ function PasswordField({ error: error2, ...rest }) {
|
|
|
28245
28245
|
}
|
|
28246
28246
|
);
|
|
28247
28247
|
}
|
|
28248
|
-
const phoneSchema = stringType().
|
|
28249
|
-
|
|
28248
|
+
const phoneSchema = stringType().refine((value) => {
|
|
28249
|
+
if (!/^\+?[\d\s\-().]*$/.test(value)) return false;
|
|
28250
|
+
const digits = value.replace(/\D/g, "");
|
|
28251
|
+
if (value.startsWith("+")) {
|
|
28252
|
+
if (digits.startsWith("1")) return digits.length === 11;
|
|
28253
|
+
return digits.length >= 8 && digits.length <= 15;
|
|
28254
|
+
}
|
|
28255
|
+
return digits.length === 10 || digits.length === 11 && digits.startsWith("1");
|
|
28256
|
+
}, "Please enter a valid phone number");
|
|
28257
|
+
function formatPhone(raw) {
|
|
28258
|
+
const hasPlus = raw.startsWith("+");
|
|
28259
|
+
const digits = raw.replace(/\D/g, "");
|
|
28260
|
+
if (!digits) return hasPlus ? "+" : "";
|
|
28261
|
+
if (!hasPlus && digits.length === 11 && digits.startsWith("1")) {
|
|
28262
|
+
return formatPhone(`+${digits}`);
|
|
28263
|
+
}
|
|
28264
|
+
if (hasPlus && digits.startsWith("1")) {
|
|
28265
|
+
const local = digits.slice(1);
|
|
28266
|
+
if (!local.length) return "+1";
|
|
28267
|
+
if (local.length <= 3) return `+1 (${local}`;
|
|
28268
|
+
if (local.length <= 6) return `+1 (${local.slice(0, 3)}) ${local.slice(3)}`;
|
|
28269
|
+
return `+1 (${local.slice(0, 3)}) ${local.slice(3, 6)}-${local.slice(6, 10)}`;
|
|
28270
|
+
}
|
|
28271
|
+
if (hasPlus) return `+${digits}`;
|
|
28272
|
+
if (digits.length <= 3) return digits;
|
|
28273
|
+
if (digits.length <= 6) return `(${digits.slice(0, 3)}) ${digits.slice(3)}`;
|
|
28274
|
+
return `(${digits.slice(0, 3)}) ${digits.slice(3, 6)}-${digits.slice(6, 10)}`;
|
|
28275
|
+
}
|
|
28276
|
+
function normalizePhone(formatted) {
|
|
28277
|
+
const hasPlus = formatted.startsWith("+");
|
|
28278
|
+
const digits = formatted.replace(/\D/g, "");
|
|
28279
|
+
if (!digits) return "";
|
|
28280
|
+
if (hasPlus) return `+${digits}`;
|
|
28281
|
+
if (digits.length === 10) return `+1${digits}`;
|
|
28282
|
+
return `+${digits}`;
|
|
28283
|
+
}
|
|
28284
|
+
const formatPhoneDisplay = formatPhone;
|
|
28285
|
+
function PhoneField({ error: error2, onChange, value, ...rest }) {
|
|
28286
|
+
const inputRef = React.useRef(null);
|
|
28287
|
+
const handleChange = (e) => {
|
|
28288
|
+
const raw = e.target.value;
|
|
28289
|
+
const hasPlus = raw.startsWith("+");
|
|
28290
|
+
let digits = raw.replace(/\D/g, "");
|
|
28291
|
+
const shouldFormatAsUsCountryCode = digits.startsWith("1") && (hasPlus || !hasPlus && digits.length > 10);
|
|
28292
|
+
if (shouldFormatAsUsCountryCode) {
|
|
28293
|
+
digits = digits.slice(0, 11);
|
|
28294
|
+
} else {
|
|
28295
|
+
digits = digits.slice(0, hasPlus ? 15 : 10);
|
|
28296
|
+
}
|
|
28297
|
+
const formatted = formatPhone(hasPlus || shouldFormatAsUsCountryCode ? `+${digits}` : digits);
|
|
28298
|
+
e.target.value = formatted;
|
|
28299
|
+
onChange?.(e);
|
|
28300
|
+
};
|
|
28301
|
+
const displayValue = typeof value === "string" ? formatPhone(value) : value;
|
|
28302
|
+
React.useEffect(() => {
|
|
28303
|
+
if (inputRef.current && displayValue != null && inputRef.current.value !== String(displayValue)) {
|
|
28304
|
+
inputRef.current.value = String(displayValue);
|
|
28305
|
+
}
|
|
28306
|
+
}, [displayValue]);
|
|
28250
28307
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
28251
28308
|
TextInput,
|
|
28252
28309
|
{
|
|
28310
|
+
ref: inputRef,
|
|
28253
28311
|
type: "tel",
|
|
28254
28312
|
label: rest.label ?? "Phone",
|
|
28255
|
-
placeholder: rest.placeholder ?? "
|
|
28313
|
+
placeholder: rest.placeholder ?? "(555) 000-0000",
|
|
28256
28314
|
autoComplete: "tel",
|
|
28315
|
+
...rest,
|
|
28257
28316
|
error: error2,
|
|
28258
|
-
|
|
28317
|
+
value: displayValue,
|
|
28318
|
+
onChange: handleChange
|
|
28259
28319
|
}
|
|
28260
28320
|
);
|
|
28261
28321
|
}
|
|
@@ -30373,6 +30433,8 @@ function InvestorProfileCard({
|
|
|
30373
30433
|
subtitle,
|
|
30374
30434
|
children,
|
|
30375
30435
|
onEditName,
|
|
30436
|
+
editNameDisabled,
|
|
30437
|
+
editNameTooltip,
|
|
30376
30438
|
onUploadPhoto,
|
|
30377
30439
|
photoUploading,
|
|
30378
30440
|
editNameIcon,
|
|
@@ -30461,7 +30523,21 @@ function InvestorProfileCard({
|
|
|
30461
30523
|
/* @__PURE__ */ jsxRuntime.jsxs(Group, { gap: "xs", wrap: "nowrap", align: "center", children: [
|
|
30462
30524
|
/* @__PURE__ */ jsxRuntime.jsx(Text, { fw: 600, size: "md", children: displayName }),
|
|
30463
30525
|
verificationStatus && /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: verificationStatus, size: "xs" }),
|
|
30464
|
-
onEditName && /* @__PURE__ */ jsxRuntime.jsx(
|
|
30526
|
+
onEditName && (editNameDisabled ? /* @__PURE__ */ jsxRuntime.jsx(Tooltip, { label: editNameTooltip ?? "Coming soon", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
30527
|
+
ActionIcon,
|
|
30528
|
+
{
|
|
30529
|
+
variant: "subtle",
|
|
30530
|
+
size: "sm",
|
|
30531
|
+
"aria-label": "Edit name",
|
|
30532
|
+
"aria-disabled": "true",
|
|
30533
|
+
onClick: (event) => {
|
|
30534
|
+
event.preventDefault();
|
|
30535
|
+
event.stopPropagation();
|
|
30536
|
+
},
|
|
30537
|
+
style: { opacity: 0.5, cursor: "not-allowed" },
|
|
30538
|
+
children: editNameIcon ?? /* @__PURE__ */ jsxRuntime.jsx(DefaultPencilIcon, {})
|
|
30539
|
+
}
|
|
30540
|
+
) }) : /* @__PURE__ */ jsxRuntime.jsx(ActionIcon, { variant: "subtle", size: "sm", onClick: onEditName, "aria-label": "Edit name", children: editNameIcon ?? /* @__PURE__ */ jsxRuntime.jsx(DefaultPencilIcon, {}) }))
|
|
30465
30541
|
] }),
|
|
30466
30542
|
email && /* @__PURE__ */ jsxRuntime.jsx(Text, { size: "sm", c: `${colors.neutral}.5`, children: email }),
|
|
30467
30543
|
memberSinceText && /* @__PURE__ */ jsxRuntime.jsx(Text, { size: "xs", c: `${colors.neutral}.4`, children: memberSinceText }),
|
|
@@ -30787,10 +30863,13 @@ exports.formatCurrencyPrecise = formatCurrencyPrecise;
|
|
|
30787
30863
|
exports.formatDate = formatDate;
|
|
30788
30864
|
exports.formatNumber = formatNumber;
|
|
30789
30865
|
exports.formatPercent = formatPercent;
|
|
30866
|
+
exports.formatPhone = formatPhone;
|
|
30867
|
+
exports.formatPhoneDisplay = formatPhoneDisplay;
|
|
30790
30868
|
exports.formatPreciseWithCurrency = formatPreciseWithCurrency;
|
|
30791
30869
|
exports.getAvatarColor = getAvatarColor;
|
|
30792
30870
|
exports.isEthereumAddress = isEthereumAddress;
|
|
30793
30871
|
exports.neutralColors = neutralColors;
|
|
30872
|
+
exports.normalizePhone = normalizePhone;
|
|
30794
30873
|
exports.notify = notify;
|
|
30795
30874
|
exports.passwordSchema = passwordSchema;
|
|
30796
30875
|
exports.phoneSchema = phoneSchema;
|