@fairmint/ui 0.2.22 → 0.2.24

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.
@@ -36334,6 +36334,28 @@ const z = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
36334
36334
  xid,
36335
36335
  xor
36336
36336
  }, Symbol.toStringTag, { value: "Module" }));
36337
+ const fontSizes = {
36338
+ /** 12px — labels, captions, table headers */
36339
+ xs: "0.75rem",
36340
+ /** 14px — secondary body text, meta */
36341
+ sm: "0.875rem",
36342
+ /** 16px — default body text */
36343
+ md: "1rem",
36344
+ /** 18px — large body, lead text */
36345
+ lg: "1.125rem",
36346
+ /** 20px — small headings, emphasized values */
36347
+ xl: "1.25rem",
36348
+ /** 24px — section values, stat subtitles */
36349
+ "2xl": "1.5rem",
36350
+ /** 28px — card hero values */
36351
+ "3xl": "1.75rem",
36352
+ /** 32px — page hero values */
36353
+ "4xl": "2rem",
36354
+ /** 36px — large display values */
36355
+ "5xl": "2.25rem",
36356
+ /** 40px — extra-large display values */
36357
+ "6xl": "2.5rem"
36358
+ };
36337
36359
  const spacing = {
36338
36360
  xs: "0.625rem",
36339
36361
  sm: "0.75rem",
@@ -36493,6 +36515,13 @@ const theme = createTheme({
36493
36515
  radius: radii,
36494
36516
  defaultRadius: "md",
36495
36517
  spacing,
36518
+ fontSizes: {
36519
+ xs: fontSizes.xs,
36520
+ sm: fontSizes.sm,
36521
+ md: fontSizes.md,
36522
+ lg: fontSizes.lg,
36523
+ xl: fontSizes.xl
36524
+ },
36496
36525
  breakpoints: {
36497
36526
  xs: "30em",
36498
36527
  sm: "48em",
@@ -36618,7 +36647,40 @@ ActionIcon.displayName = "ActionIcon";
36618
36647
  function Alert(props) {
36619
36648
  return /* @__PURE__ */ jsx(Alert$1, { ...props });
36620
36649
  }
36621
- const Avatar = forwardRef((props, ref) => /* @__PURE__ */ jsx(Avatar$1, { radius: "md", color: colors.primary, ...props, ref }));
36650
+ function getAvatarColor(name) {
36651
+ if (!name) return AVATAR_PALETTE[0];
36652
+ let hash2 = 0;
36653
+ for (let i = 0; i < name.length; i++) {
36654
+ hash2 = hash2 * 31 + name.charCodeAt(i) >>> 0;
36655
+ }
36656
+ return AVATAR_PALETTE[hash2 % AVATAR_PALETTE.length];
36657
+ }
36658
+ function getInitials(name) {
36659
+ const words = name.trim().split(/\s+/).filter(Boolean);
36660
+ if (words.length >= 2) {
36661
+ return (words[0][0] + words[1][0]).toUpperCase();
36662
+ }
36663
+ if (words.length === 1) {
36664
+ return words[0][0].toUpperCase();
36665
+ }
36666
+ return "";
36667
+ }
36668
+ const Avatar = forwardRef(
36669
+ ({ children, color, name, ...props }, ref) => {
36670
+ const normalizedName = name?.trim() ?? "";
36671
+ const fallbackInitial = normalizedName ? Array.from(normalizedName)[0]?.toUpperCase() : void 0;
36672
+ return /* @__PURE__ */ jsx(
36673
+ Avatar$1,
36674
+ {
36675
+ radius: "md",
36676
+ color: color ?? (normalizedName ? getAvatarColor(normalizedName) : colors.primary),
36677
+ ...props,
36678
+ ref,
36679
+ children: children ?? fallbackInitial
36680
+ }
36681
+ );
36682
+ }
36683
+ );
36622
36684
  Avatar.displayName = "Avatar";
36623
36685
  const Badge = forwardRef((props, ref) => /* @__PURE__ */ jsx(Badge$1, { variant: "light", ...props, ref }));
36624
36686
  Badge.displayName = "Badge";
@@ -38114,24 +38176,6 @@ function ColorDot({ color, size: size2 = 8, style, ...rest }) {
38114
38176
  };
38115
38177
  return /* @__PURE__ */ jsx(Box, { "data-testid": "color-dot", style: [baseStyle, style], ...rest });
38116
38178
  }
38117
- function getAvatarColor(name) {
38118
- if (!name) return AVATAR_PALETTE[0];
38119
- let hash2 = 0;
38120
- for (let i = 0; i < name.length; i++) {
38121
- hash2 = hash2 * 31 + name.charCodeAt(i) >>> 0;
38122
- }
38123
- return AVATAR_PALETTE[hash2 % AVATAR_PALETTE.length];
38124
- }
38125
- function getInitials(name) {
38126
- const words = name.trim().split(/\s+/).filter(Boolean);
38127
- if (words.length >= 2) {
38128
- return (words[0][0] + words[1][0]).toUpperCase();
38129
- }
38130
- if (words.length === 1) {
38131
- return words[0][0].toUpperCase();
38132
- }
38133
- return "";
38134
- }
38135
38179
  const BRAND_GRADIENT = `linear-gradient(90deg, ${brandColors.blue} 0%, ${brandColors.indigo} 50%, ${brandColors.purple} 100%)`;
38136
38180
  function CompanyBanner({
38137
38181
  companyName,
@@ -38289,6 +38333,90 @@ function formatDate(dateString) {
38289
38333
  function formatPercent(n, decimals = 2) {
38290
38334
  return `${n.toFixed(decimals)}%`;
38291
38335
  }
38336
+ const COUNTRY_LOCALES = {
38337
+ US: "en-US",
38338
+ CA: "en-CA",
38339
+ GB: "en-GB",
38340
+ IE: "en-IE",
38341
+ AU: "en-AU",
38342
+ NZ: "en-NZ",
38343
+ FR: "fr-FR",
38344
+ BE: "fr-BE",
38345
+ LU: "fr-LU",
38346
+ DE: "de-DE",
38347
+ AT: "de-AT",
38348
+ CH: "de-CH",
38349
+ NL: "nl-NL",
38350
+ ES: "es-ES",
38351
+ IT: "it-IT",
38352
+ PT: "pt-PT",
38353
+ BR: "pt-BR",
38354
+ SE: "sv-SE",
38355
+ NO: "nb-NO",
38356
+ DK: "da-DK",
38357
+ FI: "fi-FI",
38358
+ PL: "pl-PL",
38359
+ JP: "ja-JP",
38360
+ CN: "zh-CN",
38361
+ IN: "en-IN",
38362
+ SG: "en-SG"
38363
+ };
38364
+ function localeForCountry(country) {
38365
+ if (!country) return "en-US";
38366
+ const key = country.toUpperCase();
38367
+ return COUNTRY_LOCALES[key] ?? "en-US";
38368
+ }
38369
+ const toNumber = (value) => {
38370
+ if (typeof value === "number") return value;
38371
+ if (value.trim() === "") return Number.NaN;
38372
+ const parsed = Number(value);
38373
+ return Number.isFinite(parsed) ? parsed : Number.NaN;
38374
+ };
38375
+ function formatMonetary(monetary, options = {}) {
38376
+ const {
38377
+ locale: explicitLocale,
38378
+ country,
38379
+ fallbackCurrency = "USD",
38380
+ compactWholeNumbers = true
38381
+ } = options;
38382
+ if (monetary === null || monetary === void 0) return "";
38383
+ let amount;
38384
+ let currency;
38385
+ if (typeof monetary === "number" || typeof monetary === "string") {
38386
+ amount = toNumber(monetary);
38387
+ currency = fallbackCurrency.toUpperCase();
38388
+ } else {
38389
+ amount = toNumber(monetary.amount);
38390
+ currency = (monetary.currency || fallbackCurrency).toUpperCase();
38391
+ }
38392
+ if (!Number.isFinite(amount)) return "";
38393
+ const locale = explicitLocale ?? localeForCountry(country);
38394
+ let nativeFractionDigits = 2;
38395
+ try {
38396
+ const resolved = new Intl.NumberFormat(locale, {
38397
+ style: "currency",
38398
+ currency
38399
+ }).resolvedOptions().maximumFractionDigits;
38400
+ if (typeof resolved === "number") nativeFractionDigits = resolved;
38401
+ } catch {
38402
+ }
38403
+ const isWhole = Number.isInteger(amount);
38404
+ const minimumFractionDigits = compactWholeNumbers && isWhole ? 0 : nativeFractionDigits;
38405
+ const subUnitThreshold = 10 ** -nativeFractionDigits;
38406
+ const subUnit = Math.abs(amount) > 0 && Math.abs(amount) < subUnitThreshold;
38407
+ const maximumFractionDigits = subUnit ? Math.max(6, nativeFractionDigits) : nativeFractionDigits;
38408
+ try {
38409
+ return new Intl.NumberFormat(locale, {
38410
+ style: "currency",
38411
+ currency,
38412
+ minimumFractionDigits,
38413
+ maximumFractionDigits
38414
+ }).format(amount);
38415
+ } catch {
38416
+ const fallbackDigits = subUnit ? maximumFractionDigits : minimumFractionDigits;
38417
+ return `${amount.toFixed(fallbackDigits)} ${currency}`;
38418
+ }
38419
+ }
38292
38420
  const TABULAR_NUMS = { fontVariantNumeric: "tabular-nums" };
38293
38421
  function Currency({ value, precise = false, currency, style, ...rest }) {
38294
38422
  let formatted;
@@ -38604,8 +38732,10 @@ const DefaultChevronIcon = () => /* @__PURE__ */ jsx(
38604
38732
  function ListRow({
38605
38733
  avatarSrc,
38606
38734
  avatarFallback,
38607
- avatarColor = colors.primary,
38735
+ avatarColor,
38736
+ avatarColorFromName = false,
38608
38737
  title,
38738
+ avatarName = title,
38609
38739
  subtitle,
38610
38740
  value,
38611
38741
  valueSubtitle,
@@ -38621,7 +38751,17 @@ function ListRow({
38621
38751
  const isClickable = Boolean(onClick);
38622
38752
  const displayChevron = showChevron ?? isClickable;
38623
38753
  const content = /* @__PURE__ */ jsxs(Group, { gap: "sm", wrap: "nowrap", children: [
38624
- /* @__PURE__ */ jsx(Avatar, { src: avatarSrc, alt: title, radius: "md", size: 40, color: avatarColor, children: avatarFallback ?? title.charAt(0).toUpperCase() }),
38754
+ /* @__PURE__ */ jsx(
38755
+ Avatar,
38756
+ {
38757
+ src: avatarSrc,
38758
+ alt: title,
38759
+ name: avatarName,
38760
+ size: 40,
38761
+ color: avatarColor ?? (avatarColorFromName ? void 0 : colors.primary),
38762
+ children: avatarFallback
38763
+ }
38764
+ ),
38625
38765
  /* @__PURE__ */ jsxs(Box, { flex: 1, miw: 0, children: [
38626
38766
  /* @__PURE__ */ jsx(Text, { fw: 500, size: "sm", truncate: true, children: title }),
38627
38767
  subtitle && /* @__PURE__ */ jsx(Text, { size: "xs", c: fairmintVars.colorTextSecondary, lh: 1.3, children: subtitle })
@@ -40190,7 +40330,7 @@ function DocumentRow({
40190
40330
  {
40191
40331
  title: name,
40192
40332
  subtitle: subtitle || void 0,
40193
- avatarFallback: name.charAt(0).toUpperCase(),
40333
+ avatarName: name,
40194
40334
  avatarColor: colors.neutral,
40195
40335
  rightSection,
40196
40336
  onClick,
@@ -40216,7 +40356,8 @@ function EquityGrantCard({
40216
40356
  ListRow,
40217
40357
  {
40218
40358
  avatarSrc: logoUrl,
40219
- avatarColor: getAvatarColor(companyName),
40359
+ avatarName: companyName,
40360
+ avatarColorFromName: true,
40220
40361
  title: companyName,
40221
40362
  subtitle,
40222
40363
  value: estimatedValue !== void 0 ? formatCurrency(estimatedValue) : void 0,
@@ -40239,7 +40380,8 @@ function InvestmentCard({
40239
40380
  ListRow,
40240
40381
  {
40241
40382
  avatarSrc: logoUrl,
40242
- avatarColor: getAvatarColor(companyName),
40383
+ avatarName: companyName,
40384
+ avatarColorFromName: true,
40243
40385
  title: companyName,
40244
40386
  subtitle: status,
40245
40387
  rightSection: rightSection ?? /* @__PURE__ */ jsx(Currency, { value, fw: 500, size: "sm" }),
@@ -40311,17 +40453,7 @@ function InvestorProfileCard({
40311
40453
  const [isAvatarHovered, setIsAvatarHovered] = useState(false);
40312
40454
  const [isAvatarFocused, setIsAvatarFocused] = useState(false);
40313
40455
  const displayName = name?.trim() || "Add your name";
40314
- const avatarEl = /* @__PURE__ */ jsx(
40315
- Avatar,
40316
- {
40317
- src: avatarUrl,
40318
- alt: displayName,
40319
- radius: "md",
40320
- size: 56,
40321
- color: getAvatarColor(displayName),
40322
- children: displayName.charAt(0).toUpperCase()
40323
- }
40324
- );
40456
+ const avatarEl = /* @__PURE__ */ jsx(Avatar, { name: displayName, src: avatarUrl, alt: displayName, radius: "md", size: 56 });
40325
40457
  return /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
40326
40458
  /* @__PURE__ */ jsxs(Group, { gap: "md", wrap: "nowrap", children: [
40327
40459
  onUploadPhoto ? /* @__PURE__ */ jsxs(
@@ -41081,9 +41213,11 @@ export {
41081
41213
  ethereumAddressSchema,
41082
41214
  fairmintCssVariables,
41083
41215
  fairmintVars,
41216
+ fontSizes,
41084
41217
  formatCurrency,
41085
41218
  formatCurrencyPrecise,
41086
41219
  formatDate,
41220
+ formatMonetary,
41087
41221
  formatNumber,
41088
41222
  formatPercent,
41089
41223
  formatPhone,
@@ -41097,6 +41231,7 @@ export {
41097
41231
  isEthereumAddress,
41098
41232
  isRemovableWalletType,
41099
41233
  isSystemWalletType,
41234
+ localeForCountry,
41100
41235
  neutralColors,
41101
41236
  normalizePhone,
41102
41237
  normalizeWalletType,