@fairmint/ui 0.3.10 → 0.3.11

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.
Files changed (129) hide show
  1. package/dist/_virtual/index3.cjs +3 -5
  2. package/dist/_virtual/index3.cjs.map +1 -1
  3. package/dist/_virtual/index3.js +2 -5
  4. package/dist/_virtual/index3.js.map +1 -1
  5. package/dist/_virtual/index4.cjs +5 -3
  6. package/dist/_virtual/index4.cjs.map +1 -1
  7. package/dist/_virtual/index4.js +5 -2
  8. package/dist/_virtual/index4.js.map +1 -1
  9. package/dist/components/FairmintProvider/FairmintProvider.cjs +1 -1
  10. package/dist/components/FairmintProvider/FairmintProvider.cjs.map +1 -1
  11. package/dist/components/FairmintProvider/FairmintProvider.d.ts.map +1 -1
  12. package/dist/components/FairmintProvider/FairmintProvider.js +1 -1
  13. package/dist/components/FairmintProvider/FairmintProvider.js.map +1 -1
  14. package/dist/components/LoadingOverlay/LoadingOverlay.cjs +1 -1
  15. package/dist/components/LoadingOverlay/LoadingOverlay.cjs.map +1 -1
  16. package/dist/components/LoadingOverlay/LoadingOverlay.d.ts.map +1 -1
  17. package/dist/components/LoadingOverlay/LoadingOverlay.js +2 -2
  18. package/dist/components/LoadingOverlay/LoadingOverlay.js.map +1 -1
  19. package/dist/components/LoadingSpinner/LoadingSpinner.cjs +2 -2
  20. package/dist/components/LoadingSpinner/LoadingSpinner.cjs.map +1 -1
  21. package/dist/components/LoadingSpinner/LoadingSpinner.js +3 -3
  22. package/dist/components/LoadingSpinner/LoadingSpinner.js.map +1 -1
  23. package/dist/components/generic/Banner/Banner.cjs +46 -11
  24. package/dist/components/generic/Banner/Banner.cjs.map +1 -1
  25. package/dist/components/generic/Banner/Banner.d.ts.map +1 -1
  26. package/dist/components/generic/Banner/Banner.js +47 -12
  27. package/dist/components/generic/Banner/Banner.js.map +1 -1
  28. package/dist/components/generic/CompanyBanner/CompanyBanner.cjs +1 -1
  29. package/dist/components/generic/CompanyBanner/CompanyBanner.cjs.map +1 -1
  30. package/dist/components/generic/CompanyBanner/CompanyBanner.js +2 -2
  31. package/dist/components/generic/CompanyBanner/CompanyBanner.js.map +1 -1
  32. package/dist/components/generic/ConfidentialityBanner/ConfidentialityBanner.cjs +3 -3
  33. package/dist/components/generic/ConfidentialityBanner/ConfidentialityBanner.cjs.map +1 -1
  34. package/dist/components/generic/ConfidentialityBanner/ConfidentialityBanner.js +4 -4
  35. package/dist/components/generic/ConfidentialityBanner/ConfidentialityBanner.js.map +1 -1
  36. package/dist/components/generic/DataRow/DataRow.cjs +4 -5
  37. package/dist/components/generic/DataRow/DataRow.cjs.map +1 -1
  38. package/dist/components/generic/DataRow/DataRow.d.ts.map +1 -1
  39. package/dist/components/generic/DataRow/DataRow.js +5 -6
  40. package/dist/components/generic/DataRow/DataRow.js.map +1 -1
  41. package/dist/components/generic/DocumentRow/DocumentRow.cjs +97 -28
  42. package/dist/components/generic/DocumentRow/DocumentRow.cjs.map +1 -1
  43. package/dist/components/generic/DocumentRow/DocumentRow.d.ts.map +1 -1
  44. package/dist/components/generic/DocumentRow/DocumentRow.js +98 -29
  45. package/dist/components/generic/DocumentRow/DocumentRow.js.map +1 -1
  46. package/dist/components/generic/Eyebrow/Eyebrow.cjs +6 -1
  47. package/dist/components/generic/Eyebrow/Eyebrow.cjs.map +1 -1
  48. package/dist/components/generic/Eyebrow/Eyebrow.d.ts +2 -2
  49. package/dist/components/generic/Eyebrow/Eyebrow.d.ts.map +1 -1
  50. package/dist/components/generic/Eyebrow/Eyebrow.js +7 -2
  51. package/dist/components/generic/Eyebrow/Eyebrow.js.map +1 -1
  52. package/dist/components/generic/FileDropzone/FileDropzone.cjs +38 -20
  53. package/dist/components/generic/FileDropzone/FileDropzone.cjs.map +1 -1
  54. package/dist/components/generic/FileDropzone/FileDropzone.d.ts.map +1 -1
  55. package/dist/components/generic/FileDropzone/FileDropzone.js +39 -21
  56. package/dist/components/generic/FileDropzone/FileDropzone.js.map +1 -1
  57. package/dist/components/generic/PhotoCropModal/PhotoCropModal.cjs +1 -1
  58. package/dist/components/generic/PhotoCropModal/PhotoCropModal.cjs.map +1 -1
  59. package/dist/components/generic/PhotoCropModal/PhotoCropModal.js +2 -2
  60. package/dist/components/generic/PhotoCropModal/PhotoCropModal.js.map +1 -1
  61. package/dist/components/generic/ProcessingState/ProcessingState.cjs +11 -2
  62. package/dist/components/generic/ProcessingState/ProcessingState.cjs.map +1 -1
  63. package/dist/components/generic/ProcessingState/ProcessingState.d.ts.map +1 -1
  64. package/dist/components/generic/ProcessingState/ProcessingState.js +12 -3
  65. package/dist/components/generic/ProcessingState/ProcessingState.js.map +1 -1
  66. package/dist/components/generic/RadioCard/RadioCard.cjs +7 -7
  67. package/dist/components/generic/RadioCard/RadioCard.cjs.map +1 -1
  68. package/dist/components/generic/RadioCard/RadioCard.js +8 -8
  69. package/dist/components/generic/RadioCard/RadioCard.js.map +1 -1
  70. package/dist/components/generic/StatCard/StatCard.cjs +27 -18
  71. package/dist/components/generic/StatCard/StatCard.cjs.map +1 -1
  72. package/dist/components/generic/StatCard/StatCard.d.ts.map +1 -1
  73. package/dist/components/generic/StatCard/StatCard.js +27 -18
  74. package/dist/components/generic/StatCard/StatCard.js.map +1 -1
  75. package/dist/components/generic/StepCard/StepCard.cjs +2 -2
  76. package/dist/components/generic/StepCard/StepCard.cjs.map +1 -1
  77. package/dist/components/generic/StepCard/StepCard.d.ts.map +1 -1
  78. package/dist/components/generic/StepCard/StepCard.js +3 -3
  79. package/dist/components/generic/StepCard/StepCard.js.map +1 -1
  80. package/dist/components/layout/SideNav/SideNav.cjs +2 -2
  81. package/dist/components/layout/SideNav/SideNav.cjs.map +1 -1
  82. package/dist/components/layout/SideNav/SideNav.js +3 -3
  83. package/dist/components/layout/SideNav/SideNav.js.map +1 -1
  84. package/dist/components/primitives/Badge/Badge.cjs +11 -3
  85. package/dist/components/primitives/Badge/Badge.cjs.map +1 -1
  86. package/dist/components/primitives/Badge/Badge.d.ts.map +1 -1
  87. package/dist/components/primitives/Badge/Badge.js +12 -4
  88. package/dist/components/primitives/Badge/Badge.js.map +1 -1
  89. package/dist/components/primitives/muiCompat.cjs +41 -44
  90. package/dist/components/primitives/muiCompat.cjs.map +1 -1
  91. package/dist/components/primitives/muiCompat.d.ts +21 -21
  92. package/dist/components/primitives/muiCompat.d.ts.map +1 -1
  93. package/dist/components/primitives/muiCompat.js +42 -45
  94. package/dist/components/primitives/muiCompat.js.map +1 -1
  95. package/dist/components/primitives/sx.cjs +21 -25
  96. package/dist/components/primitives/sx.cjs.map +1 -1
  97. package/dist/components/primitives/sx.d.ts.map +1 -1
  98. package/dist/components/primitives/sx.js +22 -26
  99. package/dist/components/primitives/sx.js.map +1 -1
  100. package/dist/components/specific/DocumentRow/DocumentRow.cjs +14 -1
  101. package/dist/components/specific/DocumentRow/DocumentRow.cjs.map +1 -1
  102. package/dist/components/specific/DocumentRow/DocumentRow.d.ts.map +1 -1
  103. package/dist/components/specific/DocumentRow/DocumentRow.js +14 -1
  104. package/dist/components/specific/DocumentRow/DocumentRow.js.map +1 -1
  105. package/dist/components/specific/InvestorProfileCard/InvestorProfileCard.cjs +2 -2
  106. package/dist/components/specific/InvestorProfileCard/InvestorProfileCard.cjs.map +1 -1
  107. package/dist/components/specific/InvestorProfileCard/InvestorProfileCard.js +3 -3
  108. package/dist/components/specific/InvestorProfileCard/InvestorProfileCard.js.map +1 -1
  109. package/dist/fairmint-ui.cjs +1 -0
  110. package/dist/fairmint-ui.cjs.map +1 -1
  111. package/dist/fairmint-ui.js +2 -1
  112. package/dist/index.d.ts +1 -1
  113. package/dist/index.d.ts.map +1 -1
  114. package/dist/mui-icons.cjs +7 -7
  115. package/dist/mui-icons.cjs.map +1 -1
  116. package/dist/mui-icons.js +8 -8
  117. package/dist/mui-icons.js.map +1 -1
  118. package/dist/node_modules/@mantine/form/esm/hooks/use-form-status/use-form-status.cjs +1 -1
  119. package/dist/node_modules/@mantine/form/esm/hooks/use-form-status/use-form-status.js +1 -1
  120. package/dist/node_modules/prop-types/index.cjs +1 -1
  121. package/dist/node_modules/prop-types/index.js +1 -1
  122. package/dist/styles.css +35 -0
  123. package/dist/theme/index.cjs +329 -28
  124. package/dist/theme/index.cjs.map +1 -1
  125. package/dist/theme/index.d.ts +85 -17
  126. package/dist/theme/index.d.ts.map +1 -1
  127. package/dist/theme/index.js +329 -28
  128. package/dist/theme/index.js.map +1 -1
  129. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"FileDropzone.js","sources":["../../../../src/components/generic/FileDropzone/FileDropzone.tsx"],"sourcesContent":["import { type DragEvent, type KeyboardEvent, type ReactNode, useRef, useState } from \"react\";\nimport { brandColors, neutralColors } from \"../../../theme\";\nimport { colors } from \"../../../theme/colors\";\nimport { Button } from \"../../primitives/Button/Button\";\nimport { Loader } from \"../../primitives/Loader/Loader\";\nimport { Box, Group, Stack, Text, ThemeIcon } from \"../../primitives/layout\";\nimport { Banner } from \"../Banner/Banner\";\n\nconst errorTextProps = {\n size: \"xs\" as const,\n c: colors.error,\n style: { lineHeight: 1.4 },\n};\n\nconst rejectionTextProps = {\n size: \"sm\" as const,\n c: neutralColors[500],\n style: { lineHeight: 1.4 },\n};\n\n/** Default supported document-type chips shown beneath the dropzone title. */\nexport const FILE_DROPZONE_DEFAULT_SUPPORTED_TYPES = [\n \"SAFE\",\n \"Convertible note\",\n \"Purchase agreement\",\n \"Token warrant\",\n \"Other agreement\",\n] as const;\n\n/** Default batch cap surfaced in the dropzone helper copy. */\nexport const FILE_DROPZONE_DEFAULT_MAX_FILES = 50;\n\nexport interface FileDropzoneRejection {\n name: string;\n error: string;\n}\n\nexport interface FileDropzoneProps {\n /**\n * Called with the files the user selected or dropped. Per-file validation,\n * dedup, and batch caps are the caller's responsibility.\n */\n onFilesSelected: (files: File[]) => void;\n /** Full dropzone (Stage A) or collapsed header (Stages B/C). @default \"default\" */\n variant?: \"default\" | \"compact\";\n /** External error (e.g. upload failure) shown beneath the dropzone. */\n errorMessage?: string | null;\n /** Per-file validation rejections (wrong type, oversize, batch cap, etc.). */\n fileRejections?: FileDropzoneRejection[];\n /**\n * Default variant only: shows the live upload animation (loader + gradient\n * status). The dropzone stays interactive so callers can queue more files\n * while an upload batch is in flight (ENG-854).\n *\n * Ignored by `variant=\"compact\"` — keep the add-more bar calm and put\n * processing copy on parent-owned file rows instead (Slack design review).\n */\n uploading?: boolean;\n /**\n * Default variant only: gradient status copy while `uploading` is true.\n * @default \"Uploading…\"\n */\n uploadingLabel?: string;\n /** Disables all interaction (e.g. final import). Does not apply to `uploading`. */\n disabled?: boolean;\n /**\n * Visual override for drag-active styling (Storybook / visual tests). Omit for\n * normal drag-and-drop behavior.\n */\n dragging?: boolean;\n /** Primary heading in the default variant. */\n title?: string;\n /** Override the helper line beneath the title/chips. */\n helperCopy?: string;\n /** Supported document-type chips. Pass `[]` to hide chips (e.g. cap table uses prose above). */\n supportedTypes?: readonly string[];\n /** Label on the Browse / Choose files button. @default \"Browse\" */\n browseLabel?: string;\n /** Maximum files copy-deck number. @default 50 */\n maxFiles?: number;\n /** Size constraint copy shown in the helper line. @default \"50MB each\" */\n maxFileSizeLabel?: string;\n /** `input[type=file]` accept attribute. @default \"application/pdf,.pdf\" */\n accept?: string;\n /** Compact variant: staged file count (investor: total staged files). */\n fileCount?: number;\n /** Compact variant: completed count (investor: analyzed files). */\n analyzedCount?: number;\n /**\n * Compact variant: custom progress copy. When set, replaces the default\n * investor string (`9 files · 3 of 9 analyzed (33%)`). Use for cap table\n * (`6 files · 4 classified`) or pipeline states (`Processing 2 documents`).\n */\n compactProgressText?: string;\n /** Compact variant: leading action label. @default \"Add more PDFs\" */\n compactAddLabel?: string;\n /** Icon in the default variant upload circle. */\n uploadIcon?: ReactNode;\n /** Icon beside the Browse button. */\n browseIcon?: ReactNode;\n /** Icon beside the compact add label. */\n compactAddIcon?: ReactNode;\n}\n\nconst DRAG_GRADIENT_BORDER = `linear-gradient(${neutralColors[50]}, ${neutralColors[50]}) padding-box, linear-gradient(135deg, ${brandColors.indigo}, ${brandColors.purple}) border-box`;\n\nfunction DefaultUploadIcon() {\n return (\n <svg\n aria-hidden=\"true\"\n width=\"28\"\n height=\"28\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M12 13v8\" />\n <path d=\"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242\" />\n <path d=\"m8 17 4-4 4 4\" />\n </svg>\n );\n}\n\nfunction DefaultBrowseIcon() {\n return (\n <svg\n aria-hidden=\"true\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z\" />\n <path d=\"M14 2v6h6\" />\n <path d=\"M10 13H8\" />\n <path d=\"M16 13h-2\" />\n <path d=\"M10 17H8\" />\n <path d=\"M13 17h2\" />\n </svg>\n );\n}\n\nfunction DefaultCompactAddIcon() {\n return (\n <svg\n aria-hidden=\"true\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M12 19V5\" />\n <path d=\"m5 12 7-7 7 7\" />\n </svg>\n );\n}\n\nfunction pluralizeFiles(count: number): string {\n return count === 1 ? \"file\" : \"files\";\n}\n\nfunction DropzoneUploadingLabel({ label }: { label: string }) {\n return (\n <>\n <Text component=\"span\" size=\"sm\" className=\"file-dropzone-status--active\" role=\"status\">\n {label}\n </Text>\n <DropzoneStatusStyles />\n </>\n );\n}\n\nfunction DropzoneStatusStyles() {\n return (\n <style>{`\n .file-dropzone-status--active {\n display: inline-block;\n background-image: linear-gradient(90deg, ${brandColors.indigo}, ${brandColors.purple}, ${brandColors.indigo});\n background-size: 200% auto;\n -webkit-background-clip: text;\n background-clip: text;\n color: transparent;\n font-weight: 500;\n animation: gradientFlow 2.2s linear infinite;\n }\n @media (prefers-reduced-motion: reduce) {\n .file-dropzone-status--active {\n animation: none;\n background-image: none;\n color: ${neutralColors[600]};\n }\n }\n `}</style>\n );\n}\n\n/**\n * Multi-file document dropzone for investor import and similar flows.\n *\n * Keyboard-operable: the visible Browse button is the sole focusable control;\n * clicking the drop surface also opens the file picker. Drag state adds a\n * `breathe` glow. Set `uploading` on the **default** variant for the ENG-854\n * gradient status + loader while keeping the dropzone open for more files;\n * reserve `disabled` for hard blocks. Compact stays a calm add-more control —\n * put flashy processing copy on parent-owned file rows, not the header.\n *\n * Responsive: uses CSS container queries on `.file-dropzone-root` so the layout\n * adapts inside narrow right panels (cap table drawer ~360px, investor aside\n * ~420px) without callers passing breakpoint props.\n */\nexport function FileDropzone({\n onFilesSelected,\n variant = \"default\",\n errorMessage,\n fileRejections = [],\n uploading = false,\n uploadingLabel = \"Uploading…\",\n disabled = false,\n dragging,\n title = \"Drop your PDFs here, or browse\",\n helperCopy,\n supportedTypes = FILE_DROPZONE_DEFAULT_SUPPORTED_TYPES,\n browseLabel = \"Browse\",\n maxFiles = FILE_DROPZONE_DEFAULT_MAX_FILES,\n maxFileSizeLabel = \"50MB each\",\n accept = \"application/pdf,.pdf\",\n fileCount = 0,\n analyzedCount = 0,\n compactProgressText,\n compactAddLabel = \"Add more PDFs\",\n uploadIcon,\n browseIcon,\n compactAddIcon,\n}: FileDropzoneProps) {\n const inputRef = useRef<HTMLInputElement>(null);\n const dragCounterRef = useRef(0);\n const [internalDragging, setInternalDragging] = useState(false);\n const isDragging = dragging ?? internalDragging;\n const isCompact = variant === \"compact\";\n /** Compact never shows upload chrome — processing belongs on file rows. */\n const showUploadingChrome = uploading && !isCompact;\n const resolvedUploadIcon = uploadIcon ?? <DefaultUploadIcon />;\n const resolvedBrowseIcon = browseIcon ?? <DefaultBrowseIcon />;\n const resolvedCompactAddIcon = compactAddIcon ?? <DefaultCompactAddIcon />;\n const resolvedHelperCopy =\n helperCopy ??\n (showUploadingChrome\n ? \"You can add more PDFs while we upload\"\n : `PDF · up to ${maxFiles} files · ${maxFileSizeLabel}`);\n const safeFileCount = Math.max(0, fileCount);\n const clampedAnalyzed = Math.min(Math.max(0, analyzedCount), safeFileCount);\n const pct = safeFileCount > 0 ? Math.round((clampedAnalyzed / safeFileCount) * 100) : 0;\n const defaultCompactProgress =\n safeFileCount > 0\n ? `${safeFileCount} ${pluralizeFiles(safeFileCount)} · ${clampedAnalyzed} of ${safeFileCount} analyzed (${pct}%)`\n : null;\n const resolvedCompactProgress = compactProgressText ?? defaultCompactProgress;\n const compactAriaLabel = `${compactAddLabel}. Drop files here or activate to browse.`;\n\n const handleFiles = (fileList: FileList | null | undefined) => {\n if (disabled) return;\n if (!fileList || fileList.length === 0) return;\n onFilesSelected([...fileList]);\n };\n\n const openPicker = () => {\n if (disabled) return;\n inputRef.current?.click();\n };\n\n const setDragging = (next: boolean) => {\n if (dragging === undefined) {\n setInternalDragging(next);\n }\n };\n\n const handleDragEnter = (event: DragEvent<HTMLDivElement>) => {\n event.preventDefault();\n if (disabled) return;\n dragCounterRef.current += 1;\n setDragging(true);\n };\n\n const handleDragLeave = () => {\n // Counter-only: each enter/leave (including child targets) must balance.\n // Do not also filter with relatedTarget containment — that skips decrements\n // while enters still increment, leaving drag state stuck above zero.\n dragCounterRef.current = Math.max(0, dragCounterRef.current - 1);\n if (dragCounterRef.current === 0) {\n setDragging(false);\n }\n };\n\n const handleDragOver = (event: DragEvent<HTMLDivElement>) => {\n // Always cancel default so the browser does not navigate/open the file on\n // drop — including when the dropzone is disabled.\n event.preventDefault();\n if (disabled) return;\n setDragging(true);\n };\n\n const handleDrop = (event: DragEvent<HTMLDivElement>) => {\n event.preventDefault();\n dragCounterRef.current = 0;\n setDragging(false);\n if (disabled) return;\n handleFiles(event.dataTransfer.files);\n };\n\n const fileInput = (\n <input\n ref={inputRef}\n type=\"file\"\n accept={accept}\n multiple\n hidden\n disabled={disabled}\n aria-hidden=\"true\"\n tabIndex={-1}\n onClick={(event) => event.stopPropagation()}\n onChange={(event) => {\n handleFiles(event.target.files);\n event.target.value = \"\";\n }}\n />\n );\n\n return (\n <Stack gap=\"xs\" data-testid=\"file-dropzone\" className=\"file-dropzone-root\" w=\"100%\" miw={0}>\n {isCompact ? (\n <Box\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n aria-label={compactAriaLabel}\n aria-disabled={disabled}\n data-testid=\"file-dropzone-surface\"\n data-dragging={isDragging || undefined}\n className=\"file-dropzone-surface file-dropzone-surface--compact\"\n onClick={openPicker}\n onKeyDown={(event: KeyboardEvent<HTMLDivElement>) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n openPicker();\n }\n }}\n onDragEnter={handleDragEnter}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n style={{\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n borderRadius: 12,\n padding: \"10px 16px\",\n border: `1px dashed ${isDragging ? neutralColors[500] : neutralColors[300]}`,\n background: isDragging ? neutralColors[100] : neutralColors[50],\n transition: \"background 0.15s ease, border-color 0.15s ease\",\n opacity: disabled ? 0.6 : 1,\n }}\n >\n <Group\n justify=\"space-between\"\n wrap=\"nowrap\"\n gap=\"sm\"\n className=\"file-dropzone-compact-row\"\n align=\"flex-start\"\n >\n <Group gap={6} wrap=\"nowrap\" className=\"file-dropzone-compact-leading\" miw={0}>\n <Box c={neutralColors[600]} style={{ display: \"flex\" }} aria-hidden>\n {resolvedCompactAddIcon}\n </Box>\n <Text size=\"sm\" fw={500} c={neutralColors[800]}>\n {compactAddLabel}\n </Text>\n </Group>\n <Text\n size=\"sm\"\n c={neutralColors[600]}\n className=\"file-dropzone-compact-progress\"\n style={{ fontVariantNumeric: \"tabular-nums\" }}\n >\n {resolvedCompactProgress}\n </Text>\n </Group>\n {fileInput}\n </Box>\n ) : (\n <Box\n aria-disabled={disabled || undefined}\n aria-busy={showUploadingChrome || undefined}\n data-testid=\"file-dropzone-surface\"\n data-uploading={showUploadingChrome || undefined}\n data-dragging={isDragging || undefined}\n className=\"file-dropzone-surface file-dropzone-surface--default\"\n onClick={openPicker}\n onDragEnter={handleDragEnter}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n style={{\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n opacity: disabled ? 0.6 : 1,\n borderRadius: 16,\n padding: \"40px 24px\",\n textAlign: \"center\",\n border: \"2px solid transparent\",\n background: isDragging ? DRAG_GRADIENT_BORDER : neutralColors[50],\n borderStyle: isDragging ? \"solid\" : \"dashed\",\n borderColor: isDragging ? \"transparent\" : neutralColors[300],\n boxShadow: isDragging ? `0 0 0 4px ${brandColors.indigo}1f` : \"none\",\n transition: \"box-shadow 0.2s ease, border-color 0.2s ease\",\n }}\n >\n <Stack gap=\"sm\" align=\"center\">\n <ThemeIcon\n size={56}\n radius=\"xl\"\n variant=\"light\"\n color={colors.primary}\n className={`file-dropzone-icon-wrap${\n isDragging\n ? \" file-dropzone-icon--dragging\"\n : showUploadingChrome\n ? \" file-dropzone-icon--uploading\"\n : \"\"\n }`}\n data-dragging={isDragging || undefined}\n data-uploading={showUploadingChrome || undefined}\n >\n {showUploadingChrome ? (\n <Loader size=\"sm\" color={colors.primary} aria-hidden />\n ) : (\n resolvedUploadIcon\n )}\n </ThemeIcon>\n <Stack gap=\"xs\" align=\"center\" className=\"file-dropzone-copy\" w=\"100%\">\n <Text fw={600} c={neutralColors[900]} className=\"file-dropzone-title\" ta=\"center\">\n {title}\n </Text>\n {showUploadingChrome && <DropzoneUploadingLabel label={uploadingLabel} />}\n {supportedTypes.length > 0 && (\n <Group\n gap={6}\n justify=\"center\"\n wrap=\"wrap\"\n w=\"100%\"\n className=\"file-dropzone-chips\"\n >\n {supportedTypes.map((type) => (\n <Text\n key={type}\n component=\"span\"\n size=\"xs\"\n fw={500}\n c={neutralColors[600]}\n px={8}\n py={2}\n style={{\n background: neutralColors[100],\n borderRadius: 999,\n whiteSpace: \"nowrap\",\n }}\n >\n {type}\n </Text>\n ))}\n </Group>\n )}\n <Text size=\"xs\" c={neutralColors[500]} ta=\"center\" className=\"file-dropzone-helper\">\n {resolvedHelperCopy}\n </Text>\n </Stack>\n <Button\n variant=\"light\"\n radius=\"md\"\n disabled={disabled}\n className=\"file-dropzone-browse\"\n mih={44}\n leftSection={resolvedBrowseIcon}\n onClick={(event) => {\n event.stopPropagation();\n openPicker();\n }}\n >\n {browseLabel}\n </Button>\n </Stack>\n {fileInput}\n </Box>\n )}\n\n {fileRejections.length > 0 && (\n <Banner\n tone=\"error\"\n icon={null}\n title=\"Some files weren't added\"\n description={\n <Stack gap={2}>\n {fileRejections.map((rejection) => (\n <Text key={`${rejection.name}:${rejection.error}`} {...rejectionTextProps}>\n {rejection.error}\n </Text>\n ))}\n </Stack>\n }\n />\n )}\n\n {errorMessage && (\n <Text {...errorTextProps} role=\"alert\">\n {errorMessage}\n </Text>\n )}\n </Stack>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FileDropzone.js","sources":["../../../../src/components/generic/FileDropzone/FileDropzone.tsx"],"sourcesContent":["import { type DragEvent, type KeyboardEvent, type ReactNode, useRef, useState } from \"react\";\nimport { fairmintVars } from \"../../../theme\";\nimport { colors } from \"../../../theme/colors\";\nimport { Button } from \"../../primitives/Button/Button\";\nimport { Loader } from \"../../primitives/Loader/Loader\";\nimport { Box, Group, Stack, Text, ThemeIcon } from \"../../primitives/layout\";\nimport { Banner } from \"../Banner/Banner\";\n\nconst errorTextProps = {\n size: \"xs\" as const,\n c: fairmintVars.colorErrorText,\n style: { lineHeight: 1.4 },\n};\n\nconst rejectionTextProps = {\n size: \"sm\" as const,\n c: fairmintVars.colorTextSecondary,\n style: { lineHeight: 1.4 },\n};\n\n/** Default supported document-type chips shown beneath the dropzone title. */\nexport const FILE_DROPZONE_DEFAULT_SUPPORTED_TYPES = [\n \"SAFE\",\n \"Convertible note\",\n \"Purchase agreement\",\n \"Token warrant\",\n \"Other agreement\",\n] as const;\n\n/** Default batch cap surfaced in the dropzone helper copy. */\nexport const FILE_DROPZONE_DEFAULT_MAX_FILES = 50;\n\nexport interface FileDropzoneRejection {\n name: string;\n error: string;\n}\n\nexport interface FileDropzoneProps {\n /**\n * Called with the files the user selected or dropped. Per-file validation,\n * dedup, and batch caps are the caller's responsibility.\n */\n onFilesSelected: (files: File[]) => void;\n /** Full dropzone (Stage A) or collapsed header (Stages B/C). @default \"default\" */\n variant?: \"default\" | \"compact\";\n /** External error (e.g. upload failure) shown beneath the dropzone. */\n errorMessage?: string | null;\n /** Per-file validation rejections (wrong type, oversize, batch cap, etc.). */\n fileRejections?: FileDropzoneRejection[];\n /**\n * Default variant only: shows the live upload animation (loader + gradient\n * status). The dropzone stays interactive so callers can queue more files\n * while an upload batch is in flight (ENG-854).\n *\n * Ignored by `variant=\"compact\"` — keep the add-more bar calm and put\n * processing copy on parent-owned file rows instead (Slack design review).\n */\n uploading?: boolean;\n /**\n * Default variant only: gradient status copy while `uploading` is true.\n * @default \"Uploading…\"\n */\n uploadingLabel?: string;\n /** Disables all interaction (e.g. final import). Does not apply to `uploading`. */\n disabled?: boolean;\n /**\n * Visual override for drag-active styling (Storybook / visual tests). Omit for\n * normal drag-and-drop behavior.\n */\n dragging?: boolean;\n /** Primary heading in the default variant. */\n title?: string;\n /** Override the helper line beneath the title/chips. */\n helperCopy?: string;\n /** Supported document-type chips. Pass `[]` to hide chips (e.g. cap table uses prose above). */\n supportedTypes?: readonly string[];\n /** Label on the Browse / Choose files button. @default \"Browse\" */\n browseLabel?: string;\n /** Maximum files copy-deck number. @default 50 */\n maxFiles?: number;\n /** Size constraint copy shown in the helper line. @default \"50MB each\" */\n maxFileSizeLabel?: string;\n /** `input[type=file]` accept attribute. @default \"application/pdf,.pdf\" */\n accept?: string;\n /** Compact variant: staged file count (investor: total staged files). */\n fileCount?: number;\n /** Compact variant: completed count (investor: analyzed files). */\n analyzedCount?: number;\n /**\n * Compact variant: custom progress copy. When set, replaces the default\n * investor string (`9 files · 3 of 9 analyzed (33%)`). Use for cap table\n * (`6 files · 4 classified`) or pipeline states (`Processing 2 documents`).\n */\n compactProgressText?: string;\n /** Compact variant: leading action label. @default \"Add more PDFs\" */\n compactAddLabel?: string;\n /** Icon in the default variant upload circle. */\n uploadIcon?: ReactNode;\n /** Icon beside the Browse button. */\n browseIcon?: ReactNode;\n /** Icon beside the compact add label. */\n compactAddIcon?: ReactNode;\n}\n\nconst DRAG_GRADIENT_BORDER = `linear-gradient(${fairmintVars.colorBgSurfaceSecondary}, ${fairmintVars.colorBgSurfaceSecondary}) padding-box, linear-gradient(135deg, ${fairmintVars.colorBrandPrimary}, ${fairmintVars.colorBrandPurple}) border-box`;\n\nfunction DefaultUploadIcon() {\n return (\n <svg\n aria-hidden=\"true\"\n width=\"28\"\n height=\"28\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M12 13v8\" />\n <path d=\"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242\" />\n <path d=\"m8 17 4-4 4 4\" />\n </svg>\n );\n}\n\nfunction DefaultBrowseIcon() {\n return (\n <svg\n aria-hidden=\"true\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z\" />\n <path d=\"M14 2v6h6\" />\n <path d=\"M10 13H8\" />\n <path d=\"M16 13h-2\" />\n <path d=\"M10 17H8\" />\n <path d=\"M13 17h2\" />\n </svg>\n );\n}\n\nfunction DefaultCompactAddIcon() {\n return (\n <svg\n aria-hidden=\"true\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M12 19V5\" />\n <path d=\"m5 12 7-7 7 7\" />\n </svg>\n );\n}\n\nfunction pluralizeFiles(count: number): string {\n return count === 1 ? \"file\" : \"files\";\n}\n\nfunction DropzoneUploadingLabel({ label }: { label: string }) {\n return (\n <>\n <Text component=\"span\" size=\"sm\" className=\"file-dropzone-status--active\" role=\"status\">\n {label}\n </Text>\n <DropzoneStatusStyles />\n </>\n );\n}\n\nfunction DropzoneStatusStyles() {\n return (\n <style>{`\n .file-dropzone-status--active {\n display: inline-block;\n background-image: linear-gradient(90deg, ${fairmintVars.colorBrandPrimary}, ${fairmintVars.colorBrandPurple}, ${fairmintVars.colorBrandPrimary});\n background-size: 200% auto;\n -webkit-background-clip: text;\n background-clip: text;\n color: transparent;\n font-weight: 500;\n animation: gradientFlow 2.2s linear infinite;\n }\n @media (prefers-reduced-motion: reduce) {\n .file-dropzone-status--active {\n animation: none;\n background-image: none;\n color: ${fairmintVars.colorTextSecondary};\n }\n }\n `}</style>\n );\n}\n\n/**\n * Multi-file document dropzone for investor import and similar flows.\n *\n * Keyboard-operable: the visible Browse button is the sole focusable control;\n * clicking the drop surface also opens the file picker. Drag state adds a\n * `breathe` glow. Set `uploading` on the **default** variant for the ENG-854\n * gradient status + loader while keeping the dropzone open for more files;\n * reserve `disabled` for hard blocks. Compact stays a calm add-more control —\n * put flashy processing copy on parent-owned file rows, not the header.\n *\n * Responsive: uses CSS container queries on `.file-dropzone-root` so the layout\n * adapts inside narrow right panels (cap table drawer ~360px, investor aside\n * ~420px) without callers passing breakpoint props.\n */\nexport function FileDropzone({\n onFilesSelected,\n variant = \"default\",\n errorMessage,\n fileRejections = [],\n uploading = false,\n uploadingLabel = \"Uploading…\",\n disabled = false,\n dragging,\n title = \"Drop your PDFs here, or browse\",\n helperCopy,\n supportedTypes = FILE_DROPZONE_DEFAULT_SUPPORTED_TYPES,\n browseLabel = \"Browse\",\n maxFiles = FILE_DROPZONE_DEFAULT_MAX_FILES,\n maxFileSizeLabel = \"50MB each\",\n accept = \"application/pdf,.pdf\",\n fileCount = 0,\n analyzedCount = 0,\n compactProgressText,\n compactAddLabel = \"Add more PDFs\",\n uploadIcon,\n browseIcon,\n compactAddIcon,\n}: FileDropzoneProps) {\n const inputRef = useRef<HTMLInputElement>(null);\n const dragCounterRef = useRef(0);\n const [internalDragging, setInternalDragging] = useState(false);\n const isDragging = dragging ?? internalDragging;\n const isCompact = variant === \"compact\";\n /** Compact never shows upload chrome — processing belongs on file rows. */\n const showUploadingChrome = uploading && !isCompact;\n const resolvedUploadIcon = uploadIcon ?? <DefaultUploadIcon />;\n const resolvedBrowseIcon = browseIcon ?? <DefaultBrowseIcon />;\n const resolvedCompactAddIcon = compactAddIcon ?? <DefaultCompactAddIcon />;\n const resolvedHelperCopy =\n helperCopy ??\n (showUploadingChrome\n ? \"You can add more PDFs while we upload\"\n : `PDF · up to ${maxFiles} files · ${maxFileSizeLabel}`);\n const safeFileCount = Math.max(0, fileCount);\n const clampedAnalyzed = Math.min(Math.max(0, analyzedCount), safeFileCount);\n const pct = safeFileCount > 0 ? Math.round((clampedAnalyzed / safeFileCount) * 100) : 0;\n const defaultCompactProgress =\n safeFileCount > 0\n ? `${safeFileCount} ${pluralizeFiles(safeFileCount)} · ${clampedAnalyzed} of ${safeFileCount} analyzed (${pct}%)`\n : null;\n const resolvedCompactProgress = compactProgressText ?? defaultCompactProgress;\n const compactAriaLabel = `${compactAddLabel}. Drop files here or activate to browse.`;\n\n const handleFiles = (fileList: FileList | null | undefined) => {\n if (disabled) return;\n if (!fileList || fileList.length === 0) return;\n onFilesSelected([...fileList]);\n };\n\n const openPicker = () => {\n if (disabled) return;\n inputRef.current?.click();\n };\n\n const setDragging = (next: boolean) => {\n if (dragging === undefined) {\n setInternalDragging(next);\n }\n };\n\n const handleDragEnter = (event: DragEvent<HTMLDivElement>) => {\n event.preventDefault();\n if (disabled) return;\n dragCounterRef.current += 1;\n setDragging(true);\n };\n\n const handleDragLeave = () => {\n // Counter-only: each enter/leave (including child targets) must balance.\n // Do not also filter with relatedTarget containment — that skips decrements\n // while enters still increment, leaving drag state stuck above zero.\n dragCounterRef.current = Math.max(0, dragCounterRef.current - 1);\n if (dragCounterRef.current === 0) {\n setDragging(false);\n }\n };\n\n const handleDragOver = (event: DragEvent<HTMLDivElement>) => {\n // Always cancel default so the browser does not navigate/open the file on\n // drop — including when the dropzone is disabled.\n event.preventDefault();\n if (disabled) return;\n setDragging(true);\n };\n\n const handleDrop = (event: DragEvent<HTMLDivElement>) => {\n event.preventDefault();\n dragCounterRef.current = 0;\n setDragging(false);\n if (disabled) return;\n handleFiles(event.dataTransfer.files);\n };\n\n const fileInput = (\n <input\n ref={inputRef}\n type=\"file\"\n accept={accept}\n multiple\n hidden\n disabled={disabled}\n aria-hidden=\"true\"\n tabIndex={-1}\n onClick={(event) => event.stopPropagation()}\n onChange={(event) => {\n handleFiles(event.target.files);\n event.target.value = \"\";\n }}\n />\n );\n\n return (\n <Stack gap=\"xs\" data-testid=\"file-dropzone\" className=\"file-dropzone-root\" w=\"100%\" miw={0}>\n {isCompact ? (\n <Box\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n aria-label={compactAriaLabel}\n aria-disabled={disabled}\n data-testid=\"file-dropzone-surface\"\n data-dragging={isDragging || undefined}\n className=\"file-dropzone-surface file-dropzone-surface--compact\"\n onClick={openPicker}\n onKeyDown={(event: KeyboardEvent<HTMLDivElement>) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n openPicker();\n }\n }}\n onDragEnter={handleDragEnter}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n style={{\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n borderRadius: 12,\n padding: \"10px 16px\",\n border: `1px dashed ${isDragging ? fairmintVars.colorBorderFocus : fairmintVars.colorBorderDefault}`,\n background: isDragging\n ? fairmintVars.colorBgHover\n : fairmintVars.colorBgSurfaceSecondary,\n transition: \"background 0.15s ease, border-color 0.15s ease\",\n opacity: disabled ? 0.6 : 1,\n }}\n >\n <Group\n justify=\"space-between\"\n wrap=\"nowrap\"\n gap=\"sm\"\n className=\"file-dropzone-compact-row\"\n align=\"flex-start\"\n >\n <Group gap={6} wrap=\"nowrap\" className=\"file-dropzone-compact-leading\" miw={0}>\n <Box c={fairmintVars.colorIconSecondary} style={{ display: \"flex\" }} aria-hidden>\n {resolvedCompactAddIcon}\n </Box>\n <Text size=\"sm\" fw={500} c={fairmintVars.colorTextPrimary}>\n {compactAddLabel}\n </Text>\n </Group>\n <Text\n size=\"sm\"\n c={fairmintVars.colorTextSecondary}\n className=\"file-dropzone-compact-progress\"\n style={{ fontVariantNumeric: \"tabular-nums\" }}\n >\n {resolvedCompactProgress}\n </Text>\n </Group>\n {fileInput}\n </Box>\n ) : (\n <Box\n aria-disabled={disabled || undefined}\n aria-busy={showUploadingChrome || undefined}\n data-testid=\"file-dropzone-surface\"\n data-uploading={showUploadingChrome || undefined}\n data-dragging={isDragging || undefined}\n className=\"file-dropzone-surface file-dropzone-surface--default\"\n onClick={openPicker}\n onDragEnter={handleDragEnter}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n style={{\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n opacity: disabled ? 0.6 : 1,\n borderRadius: 16,\n padding: \"40px 24px\",\n textAlign: \"center\",\n border: \"2px solid transparent\",\n background: isDragging ? DRAG_GRADIENT_BORDER : fairmintVars.colorBgSurfaceSecondary,\n borderStyle: isDragging ? \"solid\" : \"dashed\",\n borderColor: isDragging ? \"transparent\" : fairmintVars.colorBorderDefault,\n boxShadow: isDragging\n ? `0 0 0 4px color-mix(in srgb, ${fairmintVars.colorBrandPrimary} 12%, transparent)`\n : \"none\",\n transition: \"box-shadow 0.2s ease, border-color 0.2s ease\",\n }}\n >\n <Stack gap=\"sm\" align=\"center\">\n <ThemeIcon\n size={56}\n radius=\"xl\"\n variant=\"light\"\n color={colors.primary}\n className={`file-dropzone-icon-wrap${\n isDragging\n ? \" file-dropzone-icon--dragging\"\n : showUploadingChrome\n ? \" file-dropzone-icon--uploading\"\n : \"\"\n }`}\n data-dragging={isDragging || undefined}\n data-uploading={showUploadingChrome || undefined}\n >\n {showUploadingChrome ? (\n <Loader size=\"sm\" color={colors.primary} aria-hidden />\n ) : (\n resolvedUploadIcon\n )}\n </ThemeIcon>\n <Stack gap=\"xs\" align=\"center\" className=\"file-dropzone-copy\" w=\"100%\">\n <Text\n fw={600}\n c={fairmintVars.colorTextPrimary}\n className=\"file-dropzone-title\"\n ta=\"center\"\n >\n {title}\n </Text>\n {showUploadingChrome && <DropzoneUploadingLabel label={uploadingLabel} />}\n {supportedTypes.length > 0 && (\n <Group\n gap={6}\n justify=\"center\"\n wrap=\"wrap\"\n w=\"100%\"\n className=\"file-dropzone-chips\"\n >\n {supportedTypes.map((type) => (\n <Text\n key={type}\n component=\"span\"\n size=\"xs\"\n fw={500}\n c={fairmintVars.colorTextSecondary}\n px={8}\n py={2}\n style={{\n background: fairmintVars.colorBgSurface,\n borderRadius: 999,\n whiteSpace: \"nowrap\",\n }}\n >\n {type}\n </Text>\n ))}\n </Group>\n )}\n <Text\n size=\"xs\"\n c={fairmintVars.colorTextSecondary}\n ta=\"center\"\n className=\"file-dropzone-helper\"\n >\n {resolvedHelperCopy}\n </Text>\n </Stack>\n <Button\n variant=\"light\"\n radius=\"md\"\n disabled={disabled}\n className=\"file-dropzone-browse\"\n mih={44}\n leftSection={resolvedBrowseIcon}\n onClick={(event) => {\n event.stopPropagation();\n openPicker();\n }}\n >\n {browseLabel}\n </Button>\n </Stack>\n {fileInput}\n </Box>\n )}\n\n {fileRejections.length > 0 && (\n <Banner\n tone=\"error\"\n icon={null}\n title=\"Some files weren't added\"\n description={\n <Stack gap={2}>\n {fileRejections.map((rejection) => (\n <Text key={`${rejection.name}:${rejection.error}`} {...rejectionTextProps}>\n {rejection.error}\n </Text>\n ))}\n </Stack>\n }\n />\n )}\n\n {errorMessage && (\n <Text {...errorTextProps} role=\"alert\">\n {errorMessage}\n </Text>\n )}\n </Stack>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -107,7 +107,7 @@ function PhotoCropModal({
107
107
  height: 320,
108
108
  borderRadius: index.radii.md,
109
109
  overflow: "hidden",
110
- background: index.neutralColors[900]
110
+ background: index.fairmintVars.colorBgCanvas
111
111
  },
112
112
  children: imageUrl && /* @__PURE__ */ jsxRuntime.jsx(
113
113
  index_module.default,
@@ -1 +1 @@
1
- {"version":3,"file":"PhotoCropModal.cjs","sources":["../../../../src/components/generic/PhotoCropModal/PhotoCropModal.tsx"],"sourcesContent":["import { useCallback, useEffect, useState } from \"react\";\nimport type { Area } from \"react-easy-crop\";\nimport Cropper from \"react-easy-crop\";\nimport { colors, fairmintVars, neutralColors, radii } from \"../../../theme\";\nimport { Button } from \"../../primitives/Button/Button\";\nimport { Box, Group, Stack, Text } from \"../../primitives/layout\";\nimport { Modal } from \"../../primitives/Modal/Modal\";\n\nexport async function getCroppedBlob(imageSrc: string, croppedAreaPixels: Area): Promise<Blob> {\n return new Promise((resolve, reject) => {\n const image = new Image();\n image.addEventListener(\"load\", () => {\n const canvas = document.createElement(\"canvas\");\n canvas.width = croppedAreaPixels.width;\n canvas.height = croppedAreaPixels.height;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n reject(new Error(\"Canvas 2D context unavailable\"));\n return;\n }\n ctx.drawImage(\n image,\n croppedAreaPixels.x,\n croppedAreaPixels.y,\n croppedAreaPixels.width,\n croppedAreaPixels.height,\n 0,\n 0,\n croppedAreaPixels.width,\n croppedAreaPixels.height,\n );\n canvas.toBlob(\n (blob) => {\n if (blob) resolve(blob);\n else reject(new Error(\"canvas.toBlob returned null\"));\n },\n \"image/jpeg\",\n 0.92,\n );\n });\n image.addEventListener(\"error\", () => reject(new Error(\"Failed to load image for crop\")));\n image.src = imageSrc;\n });\n}\n\nexport interface PhotoCropModalProps {\n opened: boolean;\n file: File | null;\n onConfirm: (blob: Blob) => void | Promise<void>;\n onClose: () => void;\n onError?: (error: Error) => void;\n aspect?: number;\n cropShape?: \"round\" | \"rect\";\n}\n\nexport function PhotoCropModal({\n opened,\n file,\n onConfirm,\n onClose,\n onError,\n aspect = 1,\n cropShape = \"round\",\n}: PhotoCropModalProps) {\n const [imageUrl, setImageUrl] = useState<string | null>(null);\n const [crop, setCrop] = useState({ x: 0, y: 0 });\n const [zoom, setZoom] = useState(1);\n const [croppedAreaPixels, setCroppedAreaPixels] = useState<Area | null>(null);\n const [isConfirming, setIsConfirming] = useState(false);\n\n useEffect(() => {\n if (!file) {\n setImageUrl(null);\n setCrop({ x: 0, y: 0 });\n setZoom(1);\n setCroppedAreaPixels(null);\n return;\n }\n const url = URL.createObjectURL(file);\n setImageUrl(url);\n setCrop({ x: 0, y: 0 });\n setZoom(1);\n setCroppedAreaPixels(null);\n return () => URL.revokeObjectURL(url);\n }, [file]);\n\n const onCropComplete = useCallback((_croppedArea: Area, pixels: Area) => {\n setCroppedAreaPixels(pixels);\n }, []);\n\n const handleConfirm = async () => {\n if (!imageUrl || !croppedAreaPixels || isConfirming) return;\n setIsConfirming(true);\n try {\n let blob: Blob;\n try {\n blob = await getCroppedBlob(imageUrl, croppedAreaPixels);\n } catch (err) {\n onError?.(err instanceof Error ? err : new Error(\"Crop failed\"));\n return;\n }\n try {\n await onConfirm(blob);\n } catch (err) {\n onError?.(err instanceof Error ? err : new Error(\"Upload failed\"));\n }\n } finally {\n setIsConfirming(false);\n }\n };\n\n return (\n <Modal opened={opened} onClose={onClose} title=\"Adjust photo\" size=\"md\">\n <Stack gap=\"md\">\n <Box\n style={{\n position: \"relative\",\n height: 320,\n borderRadius: radii.md,\n overflow: \"hidden\",\n background: neutralColors[900],\n }}\n >\n {imageUrl && (\n <Cropper\n image={imageUrl}\n crop={crop}\n zoom={zoom}\n aspect={aspect}\n cropShape={cropShape}\n showGrid={false}\n onCropChange={setCrop}\n onCropComplete={onCropComplete}\n onZoomChange={setZoom}\n mediaProps={{\n onError: () => {\n onError?.(new Error(\"Failed to load image preview\"));\n setImageUrl(null);\n setCrop({ x: 0, y: 0 });\n setZoom(1);\n setCroppedAreaPixels(null);\n },\n }}\n />\n )}\n </Box>\n\n <Text size=\"xs\" c={fairmintVars.colorTextSecondary} ta=\"center\">\n Drag to reposition · Scroll or pinch to zoom\n </Text>\n\n <Group justify=\"flex-end\" gap=\"xs\">\n <Button variant=\"subtle\" color={colors.neutral} onClick={onClose} disabled={isConfirming}>\n Cancel\n </Button>\n <Button onClick={handleConfirm} loading={isConfirming} disabled={!croppedAreaPixels}>\n Apply\n </Button>\n </Group>\n </Stack>\n </Modal>\n );\n}\n"],"names":["useState","useEffect","useCallback","jsx","Modal","jsxs","Stack","Box","radii","neutralColors","Cropper","Text","fairmintVars","Group","Button","colors"],"mappings":"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"}
1
+ {"version":3,"file":"PhotoCropModal.cjs","sources":["../../../../src/components/generic/PhotoCropModal/PhotoCropModal.tsx"],"sourcesContent":["import { useCallback, useEffect, useState } from \"react\";\nimport type { Area } from \"react-easy-crop\";\nimport Cropper from \"react-easy-crop\";\nimport { colors, fairmintVars, radii } from \"../../../theme\";\nimport { Button } from \"../../primitives/Button/Button\";\nimport { Box, Group, Stack, Text } from \"../../primitives/layout\";\nimport { Modal } from \"../../primitives/Modal/Modal\";\n\nexport async function getCroppedBlob(imageSrc: string, croppedAreaPixels: Area): Promise<Blob> {\n return new Promise((resolve, reject) => {\n const image = new Image();\n image.addEventListener(\"load\", () => {\n const canvas = document.createElement(\"canvas\");\n canvas.width = croppedAreaPixels.width;\n canvas.height = croppedAreaPixels.height;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n reject(new Error(\"Canvas 2D context unavailable\"));\n return;\n }\n ctx.drawImage(\n image,\n croppedAreaPixels.x,\n croppedAreaPixels.y,\n croppedAreaPixels.width,\n croppedAreaPixels.height,\n 0,\n 0,\n croppedAreaPixels.width,\n croppedAreaPixels.height,\n );\n canvas.toBlob(\n (blob) => {\n if (blob) resolve(blob);\n else reject(new Error(\"canvas.toBlob returned null\"));\n },\n \"image/jpeg\",\n 0.92,\n );\n });\n image.addEventListener(\"error\", () => reject(new Error(\"Failed to load image for crop\")));\n image.src = imageSrc;\n });\n}\n\nexport interface PhotoCropModalProps {\n opened: boolean;\n file: File | null;\n onConfirm: (blob: Blob) => void | Promise<void>;\n onClose: () => void;\n onError?: (error: Error) => void;\n aspect?: number;\n cropShape?: \"round\" | \"rect\";\n}\n\nexport function PhotoCropModal({\n opened,\n file,\n onConfirm,\n onClose,\n onError,\n aspect = 1,\n cropShape = \"round\",\n}: PhotoCropModalProps) {\n const [imageUrl, setImageUrl] = useState<string | null>(null);\n const [crop, setCrop] = useState({ x: 0, y: 0 });\n const [zoom, setZoom] = useState(1);\n const [croppedAreaPixels, setCroppedAreaPixels] = useState<Area | null>(null);\n const [isConfirming, setIsConfirming] = useState(false);\n\n useEffect(() => {\n if (!file) {\n setImageUrl(null);\n setCrop({ x: 0, y: 0 });\n setZoom(1);\n setCroppedAreaPixels(null);\n return;\n }\n const url = URL.createObjectURL(file);\n setImageUrl(url);\n setCrop({ x: 0, y: 0 });\n setZoom(1);\n setCroppedAreaPixels(null);\n return () => URL.revokeObjectURL(url);\n }, [file]);\n\n const onCropComplete = useCallback((_croppedArea: Area, pixels: Area) => {\n setCroppedAreaPixels(pixels);\n }, []);\n\n const handleConfirm = async () => {\n if (!imageUrl || !croppedAreaPixels || isConfirming) return;\n setIsConfirming(true);\n try {\n let blob: Blob;\n try {\n blob = await getCroppedBlob(imageUrl, croppedAreaPixels);\n } catch (err) {\n onError?.(err instanceof Error ? err : new Error(\"Crop failed\"));\n return;\n }\n try {\n await onConfirm(blob);\n } catch (err) {\n onError?.(err instanceof Error ? err : new Error(\"Upload failed\"));\n }\n } finally {\n setIsConfirming(false);\n }\n };\n\n return (\n <Modal opened={opened} onClose={onClose} title=\"Adjust photo\" size=\"md\">\n <Stack gap=\"md\">\n <Box\n style={{\n position: \"relative\",\n height: 320,\n borderRadius: radii.md,\n overflow: \"hidden\",\n background: fairmintVars.colorBgCanvas,\n }}\n >\n {imageUrl && (\n <Cropper\n image={imageUrl}\n crop={crop}\n zoom={zoom}\n aspect={aspect}\n cropShape={cropShape}\n showGrid={false}\n onCropChange={setCrop}\n onCropComplete={onCropComplete}\n onZoomChange={setZoom}\n mediaProps={{\n onError: () => {\n onError?.(new Error(\"Failed to load image preview\"));\n setImageUrl(null);\n setCrop({ x: 0, y: 0 });\n setZoom(1);\n setCroppedAreaPixels(null);\n },\n }}\n />\n )}\n </Box>\n\n <Text size=\"xs\" c={fairmintVars.colorTextSecondary} ta=\"center\">\n Drag to reposition · Scroll or pinch to zoom\n </Text>\n\n <Group justify=\"flex-end\" gap=\"xs\">\n <Button variant=\"subtle\" color={colors.neutral} onClick={onClose} disabled={isConfirming}>\n Cancel\n </Button>\n <Button onClick={handleConfirm} loading={isConfirming} disabled={!croppedAreaPixels}>\n Apply\n </Button>\n </Group>\n </Stack>\n </Modal>\n );\n}\n"],"names":["useState","useEffect","useCallback","jsx","Modal","jsxs","Stack","Box","radii","fairmintVars","Cropper","Text","Group","Button","colors"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useState, useEffect, useCallback } from "react";
3
3
  import Cropper from "../../../node_modules/react-easy-crop/index.module.js";
4
- import { neutralColors, radii, fairmintVars } from "../../../theme/index.js";
4
+ import { fairmintVars, radii } from "../../../theme/index.js";
5
5
  import { Button } from "../../primitives/Button/Button.js";
6
6
  import { Stack, Box } from "../../primitives/layout.js";
7
7
  import { Modal } from "../../primitives/Modal/Modal.js";
@@ -105,7 +105,7 @@ function PhotoCropModal({
105
105
  height: 320,
106
106
  borderRadius: radii.md,
107
107
  overflow: "hidden",
108
- background: neutralColors[900]
108
+ background: fairmintVars.colorBgCanvas
109
109
  },
110
110
  children: imageUrl && /* @__PURE__ */ jsx(
111
111
  Cropper,
@@ -1 +1 @@
1
- {"version":3,"file":"PhotoCropModal.js","sources":["../../../../src/components/generic/PhotoCropModal/PhotoCropModal.tsx"],"sourcesContent":["import { useCallback, useEffect, useState } from \"react\";\nimport type { Area } from \"react-easy-crop\";\nimport Cropper from \"react-easy-crop\";\nimport { colors, fairmintVars, neutralColors, radii } from \"../../../theme\";\nimport { Button } from \"../../primitives/Button/Button\";\nimport { Box, Group, Stack, Text } from \"../../primitives/layout\";\nimport { Modal } from \"../../primitives/Modal/Modal\";\n\nexport async function getCroppedBlob(imageSrc: string, croppedAreaPixels: Area): Promise<Blob> {\n return new Promise((resolve, reject) => {\n const image = new Image();\n image.addEventListener(\"load\", () => {\n const canvas = document.createElement(\"canvas\");\n canvas.width = croppedAreaPixels.width;\n canvas.height = croppedAreaPixels.height;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n reject(new Error(\"Canvas 2D context unavailable\"));\n return;\n }\n ctx.drawImage(\n image,\n croppedAreaPixels.x,\n croppedAreaPixels.y,\n croppedAreaPixels.width,\n croppedAreaPixels.height,\n 0,\n 0,\n croppedAreaPixels.width,\n croppedAreaPixels.height,\n );\n canvas.toBlob(\n (blob) => {\n if (blob) resolve(blob);\n else reject(new Error(\"canvas.toBlob returned null\"));\n },\n \"image/jpeg\",\n 0.92,\n );\n });\n image.addEventListener(\"error\", () => reject(new Error(\"Failed to load image for crop\")));\n image.src = imageSrc;\n });\n}\n\nexport interface PhotoCropModalProps {\n opened: boolean;\n file: File | null;\n onConfirm: (blob: Blob) => void | Promise<void>;\n onClose: () => void;\n onError?: (error: Error) => void;\n aspect?: number;\n cropShape?: \"round\" | \"rect\";\n}\n\nexport function PhotoCropModal({\n opened,\n file,\n onConfirm,\n onClose,\n onError,\n aspect = 1,\n cropShape = \"round\",\n}: PhotoCropModalProps) {\n const [imageUrl, setImageUrl] = useState<string | null>(null);\n const [crop, setCrop] = useState({ x: 0, y: 0 });\n const [zoom, setZoom] = useState(1);\n const [croppedAreaPixels, setCroppedAreaPixels] = useState<Area | null>(null);\n const [isConfirming, setIsConfirming] = useState(false);\n\n useEffect(() => {\n if (!file) {\n setImageUrl(null);\n setCrop({ x: 0, y: 0 });\n setZoom(1);\n setCroppedAreaPixels(null);\n return;\n }\n const url = URL.createObjectURL(file);\n setImageUrl(url);\n setCrop({ x: 0, y: 0 });\n setZoom(1);\n setCroppedAreaPixels(null);\n return () => URL.revokeObjectURL(url);\n }, [file]);\n\n const onCropComplete = useCallback((_croppedArea: Area, pixels: Area) => {\n setCroppedAreaPixels(pixels);\n }, []);\n\n const handleConfirm = async () => {\n if (!imageUrl || !croppedAreaPixels || isConfirming) return;\n setIsConfirming(true);\n try {\n let blob: Blob;\n try {\n blob = await getCroppedBlob(imageUrl, croppedAreaPixels);\n } catch (err) {\n onError?.(err instanceof Error ? err : new Error(\"Crop failed\"));\n return;\n }\n try {\n await onConfirm(blob);\n } catch (err) {\n onError?.(err instanceof Error ? err : new Error(\"Upload failed\"));\n }\n } finally {\n setIsConfirming(false);\n }\n };\n\n return (\n <Modal opened={opened} onClose={onClose} title=\"Adjust photo\" size=\"md\">\n <Stack gap=\"md\">\n <Box\n style={{\n position: \"relative\",\n height: 320,\n borderRadius: radii.md,\n overflow: \"hidden\",\n background: neutralColors[900],\n }}\n >\n {imageUrl && (\n <Cropper\n image={imageUrl}\n crop={crop}\n zoom={zoom}\n aspect={aspect}\n cropShape={cropShape}\n showGrid={false}\n onCropChange={setCrop}\n onCropComplete={onCropComplete}\n onZoomChange={setZoom}\n mediaProps={{\n onError: () => {\n onError?.(new Error(\"Failed to load image preview\"));\n setImageUrl(null);\n setCrop({ x: 0, y: 0 });\n setZoom(1);\n setCroppedAreaPixels(null);\n },\n }}\n />\n )}\n </Box>\n\n <Text size=\"xs\" c={fairmintVars.colorTextSecondary} ta=\"center\">\n Drag to reposition · Scroll or pinch to zoom\n </Text>\n\n <Group justify=\"flex-end\" gap=\"xs\">\n <Button variant=\"subtle\" color={colors.neutral} onClick={onClose} disabled={isConfirming}>\n Cancel\n </Button>\n <Button onClick={handleConfirm} loading={isConfirming} disabled={!croppedAreaPixels}>\n Apply\n </Button>\n </Group>\n </Stack>\n </Modal>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PhotoCropModal.js","sources":["../../../../src/components/generic/PhotoCropModal/PhotoCropModal.tsx"],"sourcesContent":["import { useCallback, useEffect, useState } from \"react\";\nimport type { Area } from \"react-easy-crop\";\nimport Cropper from \"react-easy-crop\";\nimport { colors, fairmintVars, radii } from \"../../../theme\";\nimport { Button } from \"../../primitives/Button/Button\";\nimport { Box, Group, Stack, Text } from \"../../primitives/layout\";\nimport { Modal } from \"../../primitives/Modal/Modal\";\n\nexport async function getCroppedBlob(imageSrc: string, croppedAreaPixels: Area): Promise<Blob> {\n return new Promise((resolve, reject) => {\n const image = new Image();\n image.addEventListener(\"load\", () => {\n const canvas = document.createElement(\"canvas\");\n canvas.width = croppedAreaPixels.width;\n canvas.height = croppedAreaPixels.height;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n reject(new Error(\"Canvas 2D context unavailable\"));\n return;\n }\n ctx.drawImage(\n image,\n croppedAreaPixels.x,\n croppedAreaPixels.y,\n croppedAreaPixels.width,\n croppedAreaPixels.height,\n 0,\n 0,\n croppedAreaPixels.width,\n croppedAreaPixels.height,\n );\n canvas.toBlob(\n (blob) => {\n if (blob) resolve(blob);\n else reject(new Error(\"canvas.toBlob returned null\"));\n },\n \"image/jpeg\",\n 0.92,\n );\n });\n image.addEventListener(\"error\", () => reject(new Error(\"Failed to load image for crop\")));\n image.src = imageSrc;\n });\n}\n\nexport interface PhotoCropModalProps {\n opened: boolean;\n file: File | null;\n onConfirm: (blob: Blob) => void | Promise<void>;\n onClose: () => void;\n onError?: (error: Error) => void;\n aspect?: number;\n cropShape?: \"round\" | \"rect\";\n}\n\nexport function PhotoCropModal({\n opened,\n file,\n onConfirm,\n onClose,\n onError,\n aspect = 1,\n cropShape = \"round\",\n}: PhotoCropModalProps) {\n const [imageUrl, setImageUrl] = useState<string | null>(null);\n const [crop, setCrop] = useState({ x: 0, y: 0 });\n const [zoom, setZoom] = useState(1);\n const [croppedAreaPixels, setCroppedAreaPixels] = useState<Area | null>(null);\n const [isConfirming, setIsConfirming] = useState(false);\n\n useEffect(() => {\n if (!file) {\n setImageUrl(null);\n setCrop({ x: 0, y: 0 });\n setZoom(1);\n setCroppedAreaPixels(null);\n return;\n }\n const url = URL.createObjectURL(file);\n setImageUrl(url);\n setCrop({ x: 0, y: 0 });\n setZoom(1);\n setCroppedAreaPixels(null);\n return () => URL.revokeObjectURL(url);\n }, [file]);\n\n const onCropComplete = useCallback((_croppedArea: Area, pixels: Area) => {\n setCroppedAreaPixels(pixels);\n }, []);\n\n const handleConfirm = async () => {\n if (!imageUrl || !croppedAreaPixels || isConfirming) return;\n setIsConfirming(true);\n try {\n let blob: Blob;\n try {\n blob = await getCroppedBlob(imageUrl, croppedAreaPixels);\n } catch (err) {\n onError?.(err instanceof Error ? err : new Error(\"Crop failed\"));\n return;\n }\n try {\n await onConfirm(blob);\n } catch (err) {\n onError?.(err instanceof Error ? err : new Error(\"Upload failed\"));\n }\n } finally {\n setIsConfirming(false);\n }\n };\n\n return (\n <Modal opened={opened} onClose={onClose} title=\"Adjust photo\" size=\"md\">\n <Stack gap=\"md\">\n <Box\n style={{\n position: \"relative\",\n height: 320,\n borderRadius: radii.md,\n overflow: \"hidden\",\n background: fairmintVars.colorBgCanvas,\n }}\n >\n {imageUrl && (\n <Cropper\n image={imageUrl}\n crop={crop}\n zoom={zoom}\n aspect={aspect}\n cropShape={cropShape}\n showGrid={false}\n onCropChange={setCrop}\n onCropComplete={onCropComplete}\n onZoomChange={setZoom}\n mediaProps={{\n onError: () => {\n onError?.(new Error(\"Failed to load image preview\"));\n setImageUrl(null);\n setCrop({ x: 0, y: 0 });\n setZoom(1);\n setCroppedAreaPixels(null);\n },\n }}\n />\n )}\n </Box>\n\n <Text size=\"xs\" c={fairmintVars.colorTextSecondary} ta=\"center\">\n Drag to reposition · Scroll or pinch to zoom\n </Text>\n\n <Group justify=\"flex-end\" gap=\"xs\">\n <Button variant=\"subtle\" color={colors.neutral} onClick={onClose} disabled={isConfirming}>\n Cancel\n </Button>\n <Button onClick={handleConfirm} loading={isConfirming} disabled={!croppedAreaPixels}>\n Apply\n </Button>\n </Group>\n </Stack>\n </Modal>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -26,7 +26,7 @@ function ProcessingState({
26
26
  justifyContent: "center",
27
27
  minHeight: centerScreen ? "100vh" : minHeight,
28
28
  ...centerScreen ? {
29
- backgroundColor: index.commonColors.white,
29
+ backgroundColor: index.fairmintVars.colorBgCanvas,
30
30
  height: "100vh",
31
31
  inset: 0,
32
32
  pointerEvents: "auto",
@@ -36,7 +36,16 @@ function ProcessingState({
36
36
  } : {}
37
37
  },
38
38
  children: /* @__PURE__ */ jsxRuntime.jsxs(layout.Stack, { align: "center", gap: "md", children: [
39
- /* @__PURE__ */ jsxRuntime.jsx(AnimateIn.AnimateIn, { duration: 1e3, direction: "none", children: /* @__PURE__ */ jsxRuntime.jsx(Title.Title, { order: 3, ta: "center", fw: 600, style: { fontSize: 28 }, children: title }) }),
39
+ /* @__PURE__ */ jsxRuntime.jsx(AnimateIn.AnimateIn, { duration: 1e3, direction: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
40
+ Title.Title,
41
+ {
42
+ order: 3,
43
+ ta: "center",
44
+ fw: 600,
45
+ style: { color: index.fairmintVars.colorTextPrimary, fontSize: 28 },
46
+ children: title
47
+ }
48
+ ) }),
40
49
  /* @__PURE__ */ jsxRuntime.jsx(AnimateIn.AnimateIn, { duration: 1e3, delay: 250, direction: "none", children: /* @__PURE__ */ jsxRuntime.jsx(Text.Text, { ta: "center", c: index.fairmintVars.colorTextSecondary, children: message }) }),
41
50
  showSupport && /* @__PURE__ */ jsxRuntime.jsx(AnimateIn.AnimateIn, { duration: 1e3, delay: 500, direction: "none", children: /* @__PURE__ */ jsxRuntime.jsxs(Text.Text, { ta: "center", c: index.fairmintVars.colorTextSecondary, children: [
42
51
  "Need help? Contact",
@@ -1 +1 @@
1
- {"version":3,"file":"ProcessingState.cjs","sources":["../../../../src/components/generic/ProcessingState/ProcessingState.tsx"],"sourcesContent":["import type { CSSProperties, MouseEvent, ReactNode } from \"react\";\nimport { commonColors, fairmintVars, overlayZIndexAboveLegacyShell } from \"../../../theme\";\nimport { Anchor, Box, Stack, Text, Title } from \"../../primitives/layout\";\nimport { AnimateIn } from \"../AnimateIn/AnimateIn\";\n\nexport interface ProcessingStateProps {\n minHeight?: CSSProperties[\"minHeight\"];\n showSupport?: boolean;\n title?: ReactNode;\n message?: ReactNode;\n centerScreen?: boolean;\n onSupportClick?: (event: MouseEvent<HTMLButtonElement>) => void;\n}\n\nexport function ProcessingState({\n minHeight = \"60vh\",\n showSupport = true,\n title = \"Your cap table is being processed\",\n message = \"Sit tight we're crunching the numbers. This will be back up shortly.\",\n centerScreen = true,\n onSupportClick,\n}: ProcessingStateProps) {\n return (\n <Box\n role=\"status\"\n style={{\n alignItems: \"center\",\n display: \"flex\",\n justifyContent: \"center\",\n minHeight: centerScreen ? \"100vh\" : minHeight,\n ...(centerScreen\n ? {\n backgroundColor: commonColors.white,\n height: \"100vh\",\n inset: 0,\n pointerEvents: \"auto\",\n position: \"fixed\",\n width: \"100vw\",\n zIndex: overlayZIndexAboveLegacyShell + 1,\n }\n : {}),\n }}\n >\n <Stack align=\"center\" gap=\"md\">\n <AnimateIn duration={1000} direction=\"none\">\n <Title order={3} ta=\"center\" fw={600} style={{ fontSize: 28 }}>\n {title}\n </Title>\n </AnimateIn>\n <AnimateIn duration={1000} delay={250} direction=\"none\">\n <Text ta=\"center\" c={fairmintVars.colorTextSecondary}>\n {message}\n </Text>\n </AnimateIn>\n {showSupport && (\n <AnimateIn duration={1000} delay={500} direction=\"none\">\n <Text ta=\"center\" c={fairmintVars.colorTextSecondary}>\n Need help? Contact{\" \"}\n <Anchor component=\"button\" type=\"button\" onClick={onSupportClick} fw={500}>\n support\n </Anchor>\n </Text>\n </AnimateIn>\n )}\n </Stack>\n </Box>\n );\n}\n"],"names":["jsx","Box","commonColors","overlayZIndexAboveLegacyShell","jsxs","Stack","AnimateIn","Title","Text","fairmintVars","Anchor"],"mappings":";;;;;;;;;;AAcO,SAAS,gBAAgB;AAAA,EAC9B,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,eAAe;AAAA,EACf;AACF,GAAyB;AACvB,SACEA,2BAAAA;AAAAA,IAACC,OAAAA;AAAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,OAAO;AAAA,QACL,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,gBAAgB;AAAA,QAChB,WAAW,eAAe,UAAU;AAAA,QACpC,GAAI,eACA;AAAA,UACE,iBAAiBC,MAAAA,aAAa;AAAA,UAC9B,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,eAAe;AAAA,UACf,UAAU;AAAA,UACV,OAAO;AAAA,UACP,QAAQC,OAAAA,gCAAgC;AAAA,QAAA,IAE1C,CAAA;AAAA,MAAC;AAAA,MAGP,UAAAC,2BAAAA,KAACC,OAAAA,OAAA,EAAM,OAAM,UAAS,KAAI,MACxB,UAAA;AAAA,QAAAL,2BAAAA,IAACM,UAAAA,aAAU,UAAU,KAAM,WAAU,QACnC,UAAAN,2BAAAA,IAACO,MAAAA,SAAM,OAAO,GAAG,IAAG,UAAS,IAAI,KAAK,OAAO,EAAE,UAAU,MACtD,iBACH,EAAA,CACF;AAAA,uCACCD,UAAAA,WAAA,EAAU,UAAU,KAAM,OAAO,KAAK,WAAU,QAC/C,UAAAN,2BAAAA,IAACQ,KAAAA,MAAA,EAAK,IAAG,UAAS,GAAGC,MAAAA,aAAa,oBAC/B,mBACH,GACF;AAAA,QACC,eACCT,2BAAAA,IAACM,UAAAA,WAAA,EAAU,UAAU,KAAM,OAAO,KAAK,WAAU,QAC/C,0CAACE,KAAAA,MAAA,EAAK,IAAG,UAAS,GAAGC,MAAAA,aAAa,oBAAoB,UAAA;AAAA,UAAA;AAAA,UACjC;AAAA,UACnBT,2BAAAA,IAACU,OAAAA,QAAA,EAAO,WAAU,UAAS,MAAK,UAAS,SAAS,gBAAgB,IAAI,KAAK,UAAA,UAAA,CAE3E;AAAA,QAAA,EAAA,CACF,EAAA,CACF;AAAA,MAAA,EAAA,CAEJ;AAAA,IAAA;AAAA,EAAA;AAGN;;"}
1
+ {"version":3,"file":"ProcessingState.cjs","sources":["../../../../src/components/generic/ProcessingState/ProcessingState.tsx"],"sourcesContent":["import type { CSSProperties, MouseEvent, ReactNode } from \"react\";\nimport { fairmintVars, overlayZIndexAboveLegacyShell } from \"../../../theme\";\nimport { Anchor, Box, Stack, Text, Title } from \"../../primitives/layout\";\nimport { AnimateIn } from \"../AnimateIn/AnimateIn\";\n\nexport interface ProcessingStateProps {\n minHeight?: CSSProperties[\"minHeight\"];\n showSupport?: boolean;\n title?: ReactNode;\n message?: ReactNode;\n centerScreen?: boolean;\n onSupportClick?: (event: MouseEvent<HTMLButtonElement>) => void;\n}\n\nexport function ProcessingState({\n minHeight = \"60vh\",\n showSupport = true,\n title = \"Your cap table is being processed\",\n message = \"Sit tight we're crunching the numbers. This will be back up shortly.\",\n centerScreen = true,\n onSupportClick,\n}: ProcessingStateProps) {\n return (\n <Box\n role=\"status\"\n style={{\n alignItems: \"center\",\n display: \"flex\",\n justifyContent: \"center\",\n minHeight: centerScreen ? \"100vh\" : minHeight,\n ...(centerScreen\n ? {\n backgroundColor: fairmintVars.colorBgCanvas,\n height: \"100vh\",\n inset: 0,\n pointerEvents: \"auto\",\n position: \"fixed\",\n width: \"100vw\",\n zIndex: overlayZIndexAboveLegacyShell + 1,\n }\n : {}),\n }}\n >\n <Stack align=\"center\" gap=\"md\">\n <AnimateIn duration={1000} direction=\"none\">\n <Title\n order={3}\n ta=\"center\"\n fw={600}\n style={{ color: fairmintVars.colorTextPrimary, fontSize: 28 }}\n >\n {title}\n </Title>\n </AnimateIn>\n <AnimateIn duration={1000} delay={250} direction=\"none\">\n <Text ta=\"center\" c={fairmintVars.colorTextSecondary}>\n {message}\n </Text>\n </AnimateIn>\n {showSupport && (\n <AnimateIn duration={1000} delay={500} direction=\"none\">\n <Text ta=\"center\" c={fairmintVars.colorTextSecondary}>\n Need help? Contact{\" \"}\n <Anchor component=\"button\" type=\"button\" onClick={onSupportClick} fw={500}>\n support\n </Anchor>\n </Text>\n </AnimateIn>\n )}\n </Stack>\n </Box>\n );\n}\n"],"names":["jsx","Box","fairmintVars","overlayZIndexAboveLegacyShell","jsxs","Stack","AnimateIn","Title","Text","Anchor"],"mappings":";;;;;;;;;;AAcO,SAAS,gBAAgB;AAAA,EAC9B,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,eAAe;AAAA,EACf;AACF,GAAyB;AACvB,SACEA,2BAAAA;AAAAA,IAACC,OAAAA;AAAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,OAAO;AAAA,QACL,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,gBAAgB;AAAA,QAChB,WAAW,eAAe,UAAU;AAAA,QACpC,GAAI,eACA;AAAA,UACE,iBAAiBC,MAAAA,aAAa;AAAA,UAC9B,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,eAAe;AAAA,UACf,UAAU;AAAA,UACV,OAAO;AAAA,UACP,QAAQC,OAAAA,gCAAgC;AAAA,QAAA,IAE1C,CAAA;AAAA,MAAC;AAAA,MAGP,UAAAC,2BAAAA,KAACC,OAAAA,OAAA,EAAM,OAAM,UAAS,KAAI,MACxB,UAAA;AAAA,QAAAL,2BAAAA,IAACM,UAAAA,WAAA,EAAU,UAAU,KAAM,WAAU,QACnC,UAAAN,2BAAAA;AAAAA,UAACO,MAAAA;AAAAA,UAAA;AAAA,YACC,OAAO;AAAA,YACP,IAAG;AAAA,YACH,IAAI;AAAA,YACJ,OAAO,EAAE,OAAOL,MAAAA,aAAa,kBAAkB,UAAU,GAAA;AAAA,YAExD,UAAA;AAAA,UAAA;AAAA,QAAA,GAEL;AAAA,uCACCI,UAAAA,WAAA,EAAU,UAAU,KAAM,OAAO,KAAK,WAAU,QAC/C,UAAAN,2BAAAA,IAACQ,KAAAA,MAAA,EAAK,IAAG,UAAS,GAAGN,MAAAA,aAAa,oBAC/B,mBACH,GACF;AAAA,QACC,eACCF,2BAAAA,IAACM,UAAAA,WAAA,EAAU,UAAU,KAAM,OAAO,KAAK,WAAU,QAC/C,0CAACE,KAAAA,MAAA,EAAK,IAAG,UAAS,GAAGN,MAAAA,aAAa,oBAAoB,UAAA;AAAA,UAAA;AAAA,UACjC;AAAA,UACnBF,2BAAAA,IAACS,OAAAA,QAAA,EAAO,WAAU,UAAS,MAAK,UAAS,SAAS,gBAAgB,IAAI,KAAK,UAAA,UAAA,CAE3E;AAAA,QAAA,EAAA,CACF,EAAA,CACF;AAAA,MAAA,EAAA,CAEJ;AAAA,IAAA;AAAA,EAAA;AAGN;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProcessingState.d.ts","sourceRoot":"","sources":["../../../../src/components/generic/ProcessingState/ProcessingState.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKlE,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IACvC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;CACjE;AAED,wBAAgB,eAAe,CAAC,EAC9B,SAAkB,EAClB,WAAkB,EAClB,KAA2C,EAC3C,OAAgF,EAChF,YAAmB,EACnB,cAAc,GACf,EAAE,oBAAoB,2CA8CtB"}
1
+ {"version":3,"file":"ProcessingState.d.ts","sourceRoot":"","sources":["../../../../src/components/generic/ProcessingState/ProcessingState.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKlE,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IACvC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;CACjE;AAED,wBAAgB,eAAe,CAAC,EAC9B,SAAkB,EAClB,WAAkB,EAClB,KAA2C,EAC3C,OAAgF,EAChF,YAAmB,EACnB,cAAc,GACf,EAAE,oBAAoB,2CAmDtB"}
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { commonColors, fairmintVars } from "../../../theme/index.js";
2
+ import { fairmintVars } from "../../../theme/index.js";
3
3
  import { Box, Stack } from "../../primitives/layout.js";
4
4
  import { AnimateIn } from "../AnimateIn/AnimateIn.js";
5
5
  import { Title } from "../../../node_modules/@mantine/core/esm/components/Title/Title.js";
@@ -24,7 +24,7 @@ function ProcessingState({
24
24
  justifyContent: "center",
25
25
  minHeight: centerScreen ? "100vh" : minHeight,
26
26
  ...centerScreen ? {
27
- backgroundColor: commonColors.white,
27
+ backgroundColor: fairmintVars.colorBgCanvas,
28
28
  height: "100vh",
29
29
  inset: 0,
30
30
  pointerEvents: "auto",
@@ -34,7 +34,16 @@ function ProcessingState({
34
34
  } : {}
35
35
  },
36
36
  children: /* @__PURE__ */ jsxs(Stack, { align: "center", gap: "md", children: [
37
- /* @__PURE__ */ jsx(AnimateIn, { duration: 1e3, direction: "none", children: /* @__PURE__ */ jsx(Title, { order: 3, ta: "center", fw: 600, style: { fontSize: 28 }, children: title }) }),
37
+ /* @__PURE__ */ jsx(AnimateIn, { duration: 1e3, direction: "none", children: /* @__PURE__ */ jsx(
38
+ Title,
39
+ {
40
+ order: 3,
41
+ ta: "center",
42
+ fw: 600,
43
+ style: { color: fairmintVars.colorTextPrimary, fontSize: 28 },
44
+ children: title
45
+ }
46
+ ) }),
38
47
  /* @__PURE__ */ jsx(AnimateIn, { duration: 1e3, delay: 250, direction: "none", children: /* @__PURE__ */ jsx(Text, { ta: "center", c: fairmintVars.colorTextSecondary, children: message }) }),
39
48
  showSupport && /* @__PURE__ */ jsx(AnimateIn, { duration: 1e3, delay: 500, direction: "none", children: /* @__PURE__ */ jsxs(Text, { ta: "center", c: fairmintVars.colorTextSecondary, children: [
40
49
  "Need help? Contact",
@@ -1 +1 @@
1
- {"version":3,"file":"ProcessingState.js","sources":["../../../../src/components/generic/ProcessingState/ProcessingState.tsx"],"sourcesContent":["import type { CSSProperties, MouseEvent, ReactNode } from \"react\";\nimport { commonColors, fairmintVars, overlayZIndexAboveLegacyShell } from \"../../../theme\";\nimport { Anchor, Box, Stack, Text, Title } from \"../../primitives/layout\";\nimport { AnimateIn } from \"../AnimateIn/AnimateIn\";\n\nexport interface ProcessingStateProps {\n minHeight?: CSSProperties[\"minHeight\"];\n showSupport?: boolean;\n title?: ReactNode;\n message?: ReactNode;\n centerScreen?: boolean;\n onSupportClick?: (event: MouseEvent<HTMLButtonElement>) => void;\n}\n\nexport function ProcessingState({\n minHeight = \"60vh\",\n showSupport = true,\n title = \"Your cap table is being processed\",\n message = \"Sit tight we're crunching the numbers. This will be back up shortly.\",\n centerScreen = true,\n onSupportClick,\n}: ProcessingStateProps) {\n return (\n <Box\n role=\"status\"\n style={{\n alignItems: \"center\",\n display: \"flex\",\n justifyContent: \"center\",\n minHeight: centerScreen ? \"100vh\" : minHeight,\n ...(centerScreen\n ? {\n backgroundColor: commonColors.white,\n height: \"100vh\",\n inset: 0,\n pointerEvents: \"auto\",\n position: \"fixed\",\n width: \"100vw\",\n zIndex: overlayZIndexAboveLegacyShell + 1,\n }\n : {}),\n }}\n >\n <Stack align=\"center\" gap=\"md\">\n <AnimateIn duration={1000} direction=\"none\">\n <Title order={3} ta=\"center\" fw={600} style={{ fontSize: 28 }}>\n {title}\n </Title>\n </AnimateIn>\n <AnimateIn duration={1000} delay={250} direction=\"none\">\n <Text ta=\"center\" c={fairmintVars.colorTextSecondary}>\n {message}\n </Text>\n </AnimateIn>\n {showSupport && (\n <AnimateIn duration={1000} delay={500} direction=\"none\">\n <Text ta=\"center\" c={fairmintVars.colorTextSecondary}>\n Need help? Contact{\" \"}\n <Anchor component=\"button\" type=\"button\" onClick={onSupportClick} fw={500}>\n support\n </Anchor>\n </Text>\n </AnimateIn>\n )}\n </Stack>\n </Box>\n );\n}\n"],"names":[],"mappings":";;;;;;;;AAcO,SAAS,gBAAgB;AAAA,EAC9B,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,eAAe;AAAA,EACf;AACF,GAAyB;AACvB,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,OAAO;AAAA,QACL,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,gBAAgB;AAAA,QAChB,WAAW,eAAe,UAAU;AAAA,QACpC,GAAI,eACA;AAAA,UACE,iBAAiB,aAAa;AAAA,UAC9B,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,eAAe;AAAA,UACf,UAAU;AAAA,UACV,OAAO;AAAA,UACP,QAAQ,gCAAgC;AAAA,QAAA,IAE1C,CAAA;AAAA,MAAC;AAAA,MAGP,UAAA,qBAAC,OAAA,EAAM,OAAM,UAAS,KAAI,MACxB,UAAA;AAAA,QAAA,oBAAC,aAAU,UAAU,KAAM,WAAU,QACnC,UAAA,oBAAC,SAAM,OAAO,GAAG,IAAG,UAAS,IAAI,KAAK,OAAO,EAAE,UAAU,MACtD,iBACH,EAAA,CACF;AAAA,4BACC,WAAA,EAAU,UAAU,KAAM,OAAO,KAAK,WAAU,QAC/C,UAAA,oBAAC,MAAA,EAAK,IAAG,UAAS,GAAG,aAAa,oBAC/B,mBACH,GACF;AAAA,QACC,eACC,oBAAC,WAAA,EAAU,UAAU,KAAM,OAAO,KAAK,WAAU,QAC/C,+BAAC,MAAA,EAAK,IAAG,UAAS,GAAG,aAAa,oBAAoB,UAAA;AAAA,UAAA;AAAA,UACjC;AAAA,UACnB,oBAAC,QAAA,EAAO,WAAU,UAAS,MAAK,UAAS,SAAS,gBAAgB,IAAI,KAAK,UAAA,UAAA,CAE3E;AAAA,QAAA,EAAA,CACF,EAAA,CACF;AAAA,MAAA,EAAA,CAEJ;AAAA,IAAA;AAAA,EAAA;AAGN;"}
1
+ {"version":3,"file":"ProcessingState.js","sources":["../../../../src/components/generic/ProcessingState/ProcessingState.tsx"],"sourcesContent":["import type { CSSProperties, MouseEvent, ReactNode } from \"react\";\nimport { fairmintVars, overlayZIndexAboveLegacyShell } from \"../../../theme\";\nimport { Anchor, Box, Stack, Text, Title } from \"../../primitives/layout\";\nimport { AnimateIn } from \"../AnimateIn/AnimateIn\";\n\nexport interface ProcessingStateProps {\n minHeight?: CSSProperties[\"minHeight\"];\n showSupport?: boolean;\n title?: ReactNode;\n message?: ReactNode;\n centerScreen?: boolean;\n onSupportClick?: (event: MouseEvent<HTMLButtonElement>) => void;\n}\n\nexport function ProcessingState({\n minHeight = \"60vh\",\n showSupport = true,\n title = \"Your cap table is being processed\",\n message = \"Sit tight we're crunching the numbers. This will be back up shortly.\",\n centerScreen = true,\n onSupportClick,\n}: ProcessingStateProps) {\n return (\n <Box\n role=\"status\"\n style={{\n alignItems: \"center\",\n display: \"flex\",\n justifyContent: \"center\",\n minHeight: centerScreen ? \"100vh\" : minHeight,\n ...(centerScreen\n ? {\n backgroundColor: fairmintVars.colorBgCanvas,\n height: \"100vh\",\n inset: 0,\n pointerEvents: \"auto\",\n position: \"fixed\",\n width: \"100vw\",\n zIndex: overlayZIndexAboveLegacyShell + 1,\n }\n : {}),\n }}\n >\n <Stack align=\"center\" gap=\"md\">\n <AnimateIn duration={1000} direction=\"none\">\n <Title\n order={3}\n ta=\"center\"\n fw={600}\n style={{ color: fairmintVars.colorTextPrimary, fontSize: 28 }}\n >\n {title}\n </Title>\n </AnimateIn>\n <AnimateIn duration={1000} delay={250} direction=\"none\">\n <Text ta=\"center\" c={fairmintVars.colorTextSecondary}>\n {message}\n </Text>\n </AnimateIn>\n {showSupport && (\n <AnimateIn duration={1000} delay={500} direction=\"none\">\n <Text ta=\"center\" c={fairmintVars.colorTextSecondary}>\n Need help? Contact{\" \"}\n <Anchor component=\"button\" type=\"button\" onClick={onSupportClick} fw={500}>\n support\n </Anchor>\n </Text>\n </AnimateIn>\n )}\n </Stack>\n </Box>\n );\n}\n"],"names":[],"mappings":";;;;;;;;AAcO,SAAS,gBAAgB;AAAA,EAC9B,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,eAAe;AAAA,EACf;AACF,GAAyB;AACvB,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,OAAO;AAAA,QACL,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,gBAAgB;AAAA,QAChB,WAAW,eAAe,UAAU;AAAA,QACpC,GAAI,eACA;AAAA,UACE,iBAAiB,aAAa;AAAA,UAC9B,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,eAAe;AAAA,UACf,UAAU;AAAA,UACV,OAAO;AAAA,UACP,QAAQ,gCAAgC;AAAA,QAAA,IAE1C,CAAA;AAAA,MAAC;AAAA,MAGP,UAAA,qBAAC,OAAA,EAAM,OAAM,UAAS,KAAI,MACxB,UAAA;AAAA,QAAA,oBAAC,WAAA,EAAU,UAAU,KAAM,WAAU,QACnC,UAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,OAAO;AAAA,YACP,IAAG;AAAA,YACH,IAAI;AAAA,YACJ,OAAO,EAAE,OAAO,aAAa,kBAAkB,UAAU,GAAA;AAAA,YAExD,UAAA;AAAA,UAAA;AAAA,QAAA,GAEL;AAAA,4BACC,WAAA,EAAU,UAAU,KAAM,OAAO,KAAK,WAAU,QAC/C,UAAA,oBAAC,MAAA,EAAK,IAAG,UAAS,GAAG,aAAa,oBAC/B,mBACH,GACF;AAAA,QACC,eACC,oBAAC,WAAA,EAAU,UAAU,KAAM,OAAO,KAAK,WAAU,QAC/C,+BAAC,MAAA,EAAK,IAAG,UAAS,GAAG,aAAa,oBAAoB,UAAA;AAAA,UAAA;AAAA,UACjC;AAAA,UACnB,oBAAC,QAAA,EAAO,WAAU,UAAS,MAAK,UAAS,SAAS,gBAAgB,IAAI,KAAK,UAAA,UAAA,CAE3E;AAAA,QAAA,EAAA,CACF,EAAA,CACF;AAAA,MAAA,EAAA,CAEJ;AAAA,IAAA;AAAA,EAAA;AAGN;"}
@@ -24,8 +24,8 @@ function RadioCard({
24
24
  width: "100%",
25
25
  padding: 16,
26
26
  borderRadius: 12,
27
- border: `1.5px solid ${selected ? index.brandColors.indigo : index.neutralColors[200]}`,
28
- background: selected ? `${index.brandColors.indigo}08` : "white",
27
+ border: `1px solid ${selected ? index.fairmintVars.colorBrandPrimary : index.fairmintVars.colorBorderDefault}`,
28
+ background: selected ? index.fairmintVars.colorBgBrandSubtle : index.fairmintVars.colorBgSurface,
29
29
  transition: "all 120ms ease",
30
30
  textAlign: "left"
31
31
  },
@@ -42,12 +42,12 @@ function RadioCard({
42
42
  gap: 8
43
43
  },
44
44
  children: [
45
- /* @__PURE__ */ jsxRuntime.jsx(Text.Text, { fw: 600, size: "sm", c: index.neutralColors[900], children: title }),
45
+ /* @__PURE__ */ jsxRuntime.jsx(Text.Text, { fw: 600, size: "sm", c: index.fairmintVars.colorTextPrimary, children: title }),
46
46
  badge
47
47
  ]
48
48
  }
49
49
  ),
50
- description && /* @__PURE__ */ jsxRuntime.jsx(Text.Text, { size: "xs", c: index.neutralColors[600], lh: 1.5, children: description })
50
+ description && /* @__PURE__ */ jsxRuntime.jsx(Text.Text, { size: "xs", c: index.fairmintVars.colorTextSecondary, lh: 1.5, children: description })
51
51
  ] }),
52
52
  /* @__PURE__ */ jsxRuntime.jsx(
53
53
  layout.Box,
@@ -56,8 +56,8 @@ function RadioCard({
56
56
  width: 18,
57
57
  height: 18,
58
58
  borderRadius: "50%",
59
- border: `2px solid ${selected ? index.brandColors.indigo : index.neutralColors[300]}`,
60
- background: selected ? index.brandColors.indigo : "transparent",
59
+ border: `2px solid ${selected ? index.fairmintVars.colorBrandPrimary : index.fairmintVars.colorBorderDefault}`,
60
+ background: selected ? index.fairmintVars.colorBrandPrimary : "transparent",
61
61
  position: "relative",
62
62
  flexShrink: 0,
63
63
  marginTop: 2
@@ -69,7 +69,7 @@ function RadioCard({
69
69
  position: "absolute",
70
70
  inset: 4,
71
71
  borderRadius: "50%",
72
- background: "white"
72
+ background: index.fairmintVars.colorTextInverse
73
73
  }
74
74
  }
75
75
  )
@@ -1 +1 @@
1
- {"version":3,"file":"RadioCard.cjs","sources":["../../../../src/components/generic/RadioCard/RadioCard.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { brandColors, neutralColors } from \"../../../theme\";\nimport { Box, Stack, Text, UnstyledButton } from \"../../primitives/layout\";\n\nexport interface RadioCardProps {\n /** Whether this card is currently selected. */\n selected: boolean;\n /** Primary label (top-left). */\n title: ReactNode;\n /** Supporting description below the title. */\n description?: ReactNode;\n /** Optional pill / chip rendered next to the title (top-right). */\n badge?: ReactNode;\n /** Optional leading slot (icon / small avatar / number badge). */\n leading?: ReactNode;\n /** Triggered when the card is clicked. */\n onSelect: () => void;\n}\n\n/**\n * Selectable card with a title + description and a radio dot affordance.\n *\n * Used for any \"pick one from a few\" UX: funding methods, accreditation\n * categories, tax classifications, plan tiers, etc. The visual treatment\n * (indigo border + tinted background when active, radio dot on the\n * right) is the standard Fairmint pattern so users learn it once and\n * apply it everywhere.\n */\nexport function RadioCard({\n selected,\n title,\n description,\n badge,\n leading,\n onSelect,\n}: RadioCardProps) {\n return (\n <UnstyledButton\n onClick={onSelect}\n role=\"radio\"\n aria-checked={selected}\n style={{\n display: \"block\",\n width: \"100%\",\n padding: 16,\n borderRadius: 12,\n border: `1.5px solid ${selected ? brandColors.indigo : neutralColors[200]}`,\n background: selected ? `${brandColors.indigo}08` : \"white\",\n transition: \"all 120ms ease\",\n textAlign: \"left\",\n }}\n >\n <Box style={{ display: \"flex\", gap: 12, alignItems: \"flex-start\" }}>\n {leading && <Box style={{ flexShrink: 0 }}>{leading}</Box>}\n <Stack gap={2} style={{ minWidth: 0, flex: 1 }}>\n <Box\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"baseline\",\n gap: 8,\n }}\n >\n <Text fw={600} size=\"sm\" c={neutralColors[900]}>\n {title}\n </Text>\n {badge}\n </Box>\n {description && (\n <Text size=\"xs\" c={neutralColors[600]} lh={1.5}>\n {description}\n </Text>\n )}\n </Stack>\n <Box\n style={{\n width: 18,\n height: 18,\n borderRadius: \"50%\",\n border: `2px solid ${selected ? brandColors.indigo : neutralColors[300]}`,\n background: selected ? brandColors.indigo : \"transparent\",\n position: \"relative\",\n flexShrink: 0,\n marginTop: 2,\n }}\n >\n {selected && (\n <Box\n style={{\n position: \"absolute\",\n inset: 4,\n borderRadius: \"50%\",\n background: \"white\",\n }}\n />\n )}\n </Box>\n </Box>\n </UnstyledButton>\n );\n}\n"],"names":["jsx","UnstyledButton","brandColors","neutralColors","jsxs","Box","Stack","Text"],"mappings":";;;;;;;AA4BO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAmB;AACjB,SACEA,2BAAAA;AAAAA,IAACC,eAAAA;AAAAA,IAAA;AAAA,MACC,SAAS;AAAA,MACT,MAAK;AAAA,MACL,gBAAc;AAAA,MACd,OAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO;AAAA,QACP,SAAS;AAAA,QACT,cAAc;AAAA,QACd,QAAQ,eAAe,WAAWC,MAAAA,YAAY,SAASC,MAAAA,cAAc,GAAG,CAAC;AAAA,QACzE,YAAY,WAAW,GAAGD,MAAAA,YAAY,MAAM,OAAO;AAAA,QACnD,YAAY;AAAA,QACZ,WAAW;AAAA,MAAA;AAAA,MAGb,UAAAE,2BAAAA,KAACC,OAAAA,KAAA,EAAI,OAAO,EAAE,SAAS,QAAQ,KAAK,IAAI,YAAY,aAAA,GACjD,UAAA;AAAA,QAAA,0CAAYA,OAAAA,KAAA,EAAI,OAAO,EAAE,YAAY,EAAA,GAAM,UAAA,SAAQ;AAAA,QACpDD,2BAAAA,KAACE,OAAAA,OAAA,EAAM,KAAK,GAAG,OAAO,EAAE,UAAU,GAAG,MAAM,EAAA,GACzC,UAAA;AAAA,UAAAF,2BAAAA;AAAAA,YAACC,OAAAA;AAAAA,YAAA;AAAA,cACC,OAAO;AAAA,gBACL,SAAS;AAAA,gBACT,gBAAgB;AAAA,gBAChB,YAAY;AAAA,gBACZ,KAAK;AAAA,cAAA;AAAA,cAGP,UAAA;AAAA,gBAAAL,2BAAAA,IAACO,KAAAA,MAAA,EAAK,IAAI,KAAK,MAAK,MAAK,GAAGJ,MAAAA,cAAc,GAAG,GAC1C,UAAA,MAAA,CACH;AAAA,gBACC;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAEF,eACCH,2BAAAA,IAACO,KAAAA,MAAA,EAAK,MAAK,MAAK,GAAGJ,MAAAA,cAAc,GAAG,GAAG,IAAI,KACxC,UAAA,YAAA,CACH;AAAA,QAAA,GAEJ;AAAA,QACAH,2BAAAA;AAAAA,UAACK,OAAAA;AAAAA,UAAA;AAAA,YACC,OAAO;AAAA,cACL,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,cAAc;AAAA,cACd,QAAQ,aAAa,WAAWH,MAAAA,YAAY,SAASC,MAAAA,cAAc,GAAG,CAAC;AAAA,cACvE,YAAY,WAAWD,kBAAY,SAAS;AAAA,cAC5C,UAAU;AAAA,cACV,YAAY;AAAA,cACZ,WAAW;AAAA,YAAA;AAAA,YAGZ,UAAA,YACCF,2BAAAA;AAAAA,cAACK,OAAAA;AAAAA,cAAA;AAAA,gBACC,OAAO;AAAA,kBACL,UAAU;AAAA,kBACV,OAAO;AAAA,kBACP,cAAc;AAAA,kBACd,YAAY;AAAA,gBAAA;AAAA,cACd;AAAA,YAAA;AAAA,UACF;AAAA,QAAA;AAAA,MAEJ,EAAA,CACF;AAAA,IAAA;AAAA,EAAA;AAGN;;"}
1
+ {"version":3,"file":"RadioCard.cjs","sources":["../../../../src/components/generic/RadioCard/RadioCard.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { fairmintVars } from \"../../../theme\";\nimport { Box, Stack, Text, UnstyledButton } from \"../../primitives/layout\";\n\nexport interface RadioCardProps {\n /** Whether this card is currently selected. */\n selected: boolean;\n /** Primary label (top-left). */\n title: ReactNode;\n /** Supporting description below the title. */\n description?: ReactNode;\n /** Optional pill / chip rendered next to the title (top-right). */\n badge?: ReactNode;\n /** Optional leading slot (icon / small avatar / number badge). */\n leading?: ReactNode;\n /** Triggered when the card is clicked. */\n onSelect: () => void;\n}\n\n/**\n * Selectable card with a title + description and a radio dot affordance.\n *\n * Used for any \"pick one from a few\" UX: funding methods, accreditation\n * categories, tax classifications, plan tiers, etc. The visual treatment\n * (indigo border + tinted background when active, radio dot on the\n * right) is the standard Fairmint pattern so users learn it once and\n * apply it everywhere.\n */\nexport function RadioCard({\n selected,\n title,\n description,\n badge,\n leading,\n onSelect,\n}: RadioCardProps) {\n return (\n <UnstyledButton\n onClick={onSelect}\n role=\"radio\"\n aria-checked={selected}\n style={{\n display: \"block\",\n width: \"100%\",\n padding: 16,\n borderRadius: 12,\n border: `1px solid ${selected ? fairmintVars.colorBrandPrimary : fairmintVars.colorBorderDefault}`,\n background: selected ? fairmintVars.colorBgBrandSubtle : fairmintVars.colorBgSurface,\n transition: \"all 120ms ease\",\n textAlign: \"left\",\n }}\n >\n <Box style={{ display: \"flex\", gap: 12, alignItems: \"flex-start\" }}>\n {leading && <Box style={{ flexShrink: 0 }}>{leading}</Box>}\n <Stack gap={2} style={{ minWidth: 0, flex: 1 }}>\n <Box\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"baseline\",\n gap: 8,\n }}\n >\n <Text fw={600} size=\"sm\" c={fairmintVars.colorTextPrimary}>\n {title}\n </Text>\n {badge}\n </Box>\n {description && (\n <Text size=\"xs\" c={fairmintVars.colorTextSecondary} lh={1.5}>\n {description}\n </Text>\n )}\n </Stack>\n <Box\n style={{\n width: 18,\n height: 18,\n borderRadius: \"50%\",\n border: `2px solid ${selected ? fairmintVars.colorBrandPrimary : fairmintVars.colorBorderDefault}`,\n background: selected ? fairmintVars.colorBrandPrimary : \"transparent\",\n position: \"relative\",\n flexShrink: 0,\n marginTop: 2,\n }}\n >\n {selected && (\n <Box\n style={{\n position: \"absolute\",\n inset: 4,\n borderRadius: \"50%\",\n background: fairmintVars.colorTextInverse,\n }}\n />\n )}\n </Box>\n </Box>\n </UnstyledButton>\n );\n}\n"],"names":["jsx","UnstyledButton","fairmintVars","jsxs","Box","Stack","Text"],"mappings":";;;;;;;AA4BO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAmB;AACjB,SACEA,2BAAAA;AAAAA,IAACC,eAAAA;AAAAA,IAAA;AAAA,MACC,SAAS;AAAA,MACT,MAAK;AAAA,MACL,gBAAc;AAAA,MACd,OAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO;AAAA,QACP,SAAS;AAAA,QACT,cAAc;AAAA,QACd,QAAQ,aAAa,WAAWC,MAAAA,aAAa,oBAAoBA,MAAAA,aAAa,kBAAkB;AAAA,QAChG,YAAY,WAAWA,MAAAA,aAAa,qBAAqBA,MAAAA,aAAa;AAAA,QACtE,YAAY;AAAA,QACZ,WAAW;AAAA,MAAA;AAAA,MAGb,UAAAC,2BAAAA,KAACC,OAAAA,KAAA,EAAI,OAAO,EAAE,SAAS,QAAQ,KAAK,IAAI,YAAY,aAAA,GACjD,UAAA;AAAA,QAAA,0CAAYA,OAAAA,KAAA,EAAI,OAAO,EAAE,YAAY,EAAA,GAAM,UAAA,SAAQ;AAAA,QACpDD,2BAAAA,KAACE,OAAAA,OAAA,EAAM,KAAK,GAAG,OAAO,EAAE,UAAU,GAAG,MAAM,EAAA,GACzC,UAAA;AAAA,UAAAF,2BAAAA;AAAAA,YAACC,OAAAA;AAAAA,YAAA;AAAA,cACC,OAAO;AAAA,gBACL,SAAS;AAAA,gBACT,gBAAgB;AAAA,gBAChB,YAAY;AAAA,gBACZ,KAAK;AAAA,cAAA;AAAA,cAGP,UAAA;AAAA,gBAAAJ,2BAAAA,IAACM,KAAAA,MAAA,EAAK,IAAI,KAAK,MAAK,MAAK,GAAGJ,MAAAA,aAAa,kBACtC,UAAA,MAAA,CACH;AAAA,gBACC;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAEF,eACCF,2BAAAA,IAACM,KAAAA,MAAA,EAAK,MAAK,MAAK,GAAGJ,MAAAA,aAAa,oBAAoB,IAAI,KACrD,UAAA,YAAA,CACH;AAAA,QAAA,GAEJ;AAAA,QACAF,2BAAAA;AAAAA,UAACI,OAAAA;AAAAA,UAAA;AAAA,YACC,OAAO;AAAA,cACL,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,cAAc;AAAA,cACd,QAAQ,aAAa,WAAWF,MAAAA,aAAa,oBAAoBA,MAAAA,aAAa,kBAAkB;AAAA,cAChG,YAAY,WAAWA,mBAAa,oBAAoB;AAAA,cACxD,UAAU;AAAA,cACV,YAAY;AAAA,cACZ,WAAW;AAAA,YAAA;AAAA,YAGZ,UAAA,YACCF,2BAAAA;AAAAA,cAACI,OAAAA;AAAAA,cAAA;AAAA,gBACC,OAAO;AAAA,kBACL,UAAU;AAAA,kBACV,OAAO;AAAA,kBACP,cAAc;AAAA,kBACd,YAAYF,MAAAA,aAAa;AAAA,gBAAA;AAAA,cAC3B;AAAA,YAAA;AAAA,UACF;AAAA,QAAA;AAAA,MAEJ,EAAA,CACF;AAAA,IAAA;AAAA,EAAA;AAGN;;"}
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { brandColors, neutralColors } from "../../../theme/index.js";
2
+ import { fairmintVars } from "../../../theme/index.js";
3
3
  import { Box, Stack } from "../../primitives/layout.js";
4
4
  import { UnstyledButton } from "../../../node_modules/@mantine/core/esm/components/UnstyledButton/UnstyledButton.js";
5
5
  import { Text } from "../../../node_modules/@mantine/core/esm/components/Text/Text.js";
@@ -22,8 +22,8 @@ function RadioCard({
22
22
  width: "100%",
23
23
  padding: 16,
24
24
  borderRadius: 12,
25
- border: `1.5px solid ${selected ? brandColors.indigo : neutralColors[200]}`,
26
- background: selected ? `${brandColors.indigo}08` : "white",
25
+ border: `1px solid ${selected ? fairmintVars.colorBrandPrimary : fairmintVars.colorBorderDefault}`,
26
+ background: selected ? fairmintVars.colorBgBrandSubtle : fairmintVars.colorBgSurface,
27
27
  transition: "all 120ms ease",
28
28
  textAlign: "left"
29
29
  },
@@ -40,12 +40,12 @@ function RadioCard({
40
40
  gap: 8
41
41
  },
42
42
  children: [
43
- /* @__PURE__ */ jsx(Text, { fw: 600, size: "sm", c: neutralColors[900], children: title }),
43
+ /* @__PURE__ */ jsx(Text, { fw: 600, size: "sm", c: fairmintVars.colorTextPrimary, children: title }),
44
44
  badge
45
45
  ]
46
46
  }
47
47
  ),
48
- description && /* @__PURE__ */ jsx(Text, { size: "xs", c: neutralColors[600], lh: 1.5, children: description })
48
+ description && /* @__PURE__ */ jsx(Text, { size: "xs", c: fairmintVars.colorTextSecondary, lh: 1.5, children: description })
49
49
  ] }),
50
50
  /* @__PURE__ */ jsx(
51
51
  Box,
@@ -54,8 +54,8 @@ function RadioCard({
54
54
  width: 18,
55
55
  height: 18,
56
56
  borderRadius: "50%",
57
- border: `2px solid ${selected ? brandColors.indigo : neutralColors[300]}`,
58
- background: selected ? brandColors.indigo : "transparent",
57
+ border: `2px solid ${selected ? fairmintVars.colorBrandPrimary : fairmintVars.colorBorderDefault}`,
58
+ background: selected ? fairmintVars.colorBrandPrimary : "transparent",
59
59
  position: "relative",
60
60
  flexShrink: 0,
61
61
  marginTop: 2
@@ -67,7 +67,7 @@ function RadioCard({
67
67
  position: "absolute",
68
68
  inset: 4,
69
69
  borderRadius: "50%",
70
- background: "white"
70
+ background: fairmintVars.colorTextInverse
71
71
  }
72
72
  }
73
73
  )
@@ -1 +1 @@
1
- {"version":3,"file":"RadioCard.js","sources":["../../../../src/components/generic/RadioCard/RadioCard.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { brandColors, neutralColors } from \"../../../theme\";\nimport { Box, Stack, Text, UnstyledButton } from \"../../primitives/layout\";\n\nexport interface RadioCardProps {\n /** Whether this card is currently selected. */\n selected: boolean;\n /** Primary label (top-left). */\n title: ReactNode;\n /** Supporting description below the title. */\n description?: ReactNode;\n /** Optional pill / chip rendered next to the title (top-right). */\n badge?: ReactNode;\n /** Optional leading slot (icon / small avatar / number badge). */\n leading?: ReactNode;\n /** Triggered when the card is clicked. */\n onSelect: () => void;\n}\n\n/**\n * Selectable card with a title + description and a radio dot affordance.\n *\n * Used for any \"pick one from a few\" UX: funding methods, accreditation\n * categories, tax classifications, plan tiers, etc. The visual treatment\n * (indigo border + tinted background when active, radio dot on the\n * right) is the standard Fairmint pattern so users learn it once and\n * apply it everywhere.\n */\nexport function RadioCard({\n selected,\n title,\n description,\n badge,\n leading,\n onSelect,\n}: RadioCardProps) {\n return (\n <UnstyledButton\n onClick={onSelect}\n role=\"radio\"\n aria-checked={selected}\n style={{\n display: \"block\",\n width: \"100%\",\n padding: 16,\n borderRadius: 12,\n border: `1.5px solid ${selected ? brandColors.indigo : neutralColors[200]}`,\n background: selected ? `${brandColors.indigo}08` : \"white\",\n transition: \"all 120ms ease\",\n textAlign: \"left\",\n }}\n >\n <Box style={{ display: \"flex\", gap: 12, alignItems: \"flex-start\" }}>\n {leading && <Box style={{ flexShrink: 0 }}>{leading}</Box>}\n <Stack gap={2} style={{ minWidth: 0, flex: 1 }}>\n <Box\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"baseline\",\n gap: 8,\n }}\n >\n <Text fw={600} size=\"sm\" c={neutralColors[900]}>\n {title}\n </Text>\n {badge}\n </Box>\n {description && (\n <Text size=\"xs\" c={neutralColors[600]} lh={1.5}>\n {description}\n </Text>\n )}\n </Stack>\n <Box\n style={{\n width: 18,\n height: 18,\n borderRadius: \"50%\",\n border: `2px solid ${selected ? brandColors.indigo : neutralColors[300]}`,\n background: selected ? brandColors.indigo : \"transparent\",\n position: \"relative\",\n flexShrink: 0,\n marginTop: 2,\n }}\n >\n {selected && (\n <Box\n style={{\n position: \"absolute\",\n inset: 4,\n borderRadius: \"50%\",\n background: \"white\",\n }}\n />\n )}\n </Box>\n </Box>\n </UnstyledButton>\n );\n}\n"],"names":[],"mappings":";;;;;AA4BO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAmB;AACjB,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,SAAS;AAAA,MACT,MAAK;AAAA,MACL,gBAAc;AAAA,MACd,OAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO;AAAA,QACP,SAAS;AAAA,QACT,cAAc;AAAA,QACd,QAAQ,eAAe,WAAW,YAAY,SAAS,cAAc,GAAG,CAAC;AAAA,QACzE,YAAY,WAAW,GAAG,YAAY,MAAM,OAAO;AAAA,QACnD,YAAY;AAAA,QACZ,WAAW;AAAA,MAAA;AAAA,MAGb,UAAA,qBAAC,KAAA,EAAI,OAAO,EAAE,SAAS,QAAQ,KAAK,IAAI,YAAY,aAAA,GACjD,UAAA;AAAA,QAAA,+BAAY,KAAA,EAAI,OAAO,EAAE,YAAY,EAAA,GAAM,UAAA,SAAQ;AAAA,QACpD,qBAAC,OAAA,EAAM,KAAK,GAAG,OAAO,EAAE,UAAU,GAAG,MAAM,EAAA,GACzC,UAAA;AAAA,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO;AAAA,gBACL,SAAS;AAAA,gBACT,gBAAgB;AAAA,gBAChB,YAAY;AAAA,gBACZ,KAAK;AAAA,cAAA;AAAA,cAGP,UAAA;AAAA,gBAAA,oBAAC,MAAA,EAAK,IAAI,KAAK,MAAK,MAAK,GAAG,cAAc,GAAG,GAC1C,UAAA,MAAA,CACH;AAAA,gBACC;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAEF,eACC,oBAAC,MAAA,EAAK,MAAK,MAAK,GAAG,cAAc,GAAG,GAAG,IAAI,KACxC,UAAA,YAAA,CACH;AAAA,QAAA,GAEJ;AAAA,QACA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,OAAO;AAAA,cACL,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,cAAc;AAAA,cACd,QAAQ,aAAa,WAAW,YAAY,SAAS,cAAc,GAAG,CAAC;AAAA,cACvE,YAAY,WAAW,YAAY,SAAS;AAAA,cAC5C,UAAU;AAAA,cACV,YAAY;AAAA,cACZ,WAAW;AAAA,YAAA;AAAA,YAGZ,UAAA,YACC;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,OAAO;AAAA,kBACL,UAAU;AAAA,kBACV,OAAO;AAAA,kBACP,cAAc;AAAA,kBACd,YAAY;AAAA,gBAAA;AAAA,cACd;AAAA,YAAA;AAAA,UACF;AAAA,QAAA;AAAA,MAEJ,EAAA,CACF;AAAA,IAAA;AAAA,EAAA;AAGN;"}
1
+ {"version":3,"file":"RadioCard.js","sources":["../../../../src/components/generic/RadioCard/RadioCard.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { fairmintVars } from \"../../../theme\";\nimport { Box, Stack, Text, UnstyledButton } from \"../../primitives/layout\";\n\nexport interface RadioCardProps {\n /** Whether this card is currently selected. */\n selected: boolean;\n /** Primary label (top-left). */\n title: ReactNode;\n /** Supporting description below the title. */\n description?: ReactNode;\n /** Optional pill / chip rendered next to the title (top-right). */\n badge?: ReactNode;\n /** Optional leading slot (icon / small avatar / number badge). */\n leading?: ReactNode;\n /** Triggered when the card is clicked. */\n onSelect: () => void;\n}\n\n/**\n * Selectable card with a title + description and a radio dot affordance.\n *\n * Used for any \"pick one from a few\" UX: funding methods, accreditation\n * categories, tax classifications, plan tiers, etc. The visual treatment\n * (indigo border + tinted background when active, radio dot on the\n * right) is the standard Fairmint pattern so users learn it once and\n * apply it everywhere.\n */\nexport function RadioCard({\n selected,\n title,\n description,\n badge,\n leading,\n onSelect,\n}: RadioCardProps) {\n return (\n <UnstyledButton\n onClick={onSelect}\n role=\"radio\"\n aria-checked={selected}\n style={{\n display: \"block\",\n width: \"100%\",\n padding: 16,\n borderRadius: 12,\n border: `1px solid ${selected ? fairmintVars.colorBrandPrimary : fairmintVars.colorBorderDefault}`,\n background: selected ? fairmintVars.colorBgBrandSubtle : fairmintVars.colorBgSurface,\n transition: \"all 120ms ease\",\n textAlign: \"left\",\n }}\n >\n <Box style={{ display: \"flex\", gap: 12, alignItems: \"flex-start\" }}>\n {leading && <Box style={{ flexShrink: 0 }}>{leading}</Box>}\n <Stack gap={2} style={{ minWidth: 0, flex: 1 }}>\n <Box\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"baseline\",\n gap: 8,\n }}\n >\n <Text fw={600} size=\"sm\" c={fairmintVars.colorTextPrimary}>\n {title}\n </Text>\n {badge}\n </Box>\n {description && (\n <Text size=\"xs\" c={fairmintVars.colorTextSecondary} lh={1.5}>\n {description}\n </Text>\n )}\n </Stack>\n <Box\n style={{\n width: 18,\n height: 18,\n borderRadius: \"50%\",\n border: `2px solid ${selected ? fairmintVars.colorBrandPrimary : fairmintVars.colorBorderDefault}`,\n background: selected ? fairmintVars.colorBrandPrimary : \"transparent\",\n position: \"relative\",\n flexShrink: 0,\n marginTop: 2,\n }}\n >\n {selected && (\n <Box\n style={{\n position: \"absolute\",\n inset: 4,\n borderRadius: \"50%\",\n background: fairmintVars.colorTextInverse,\n }}\n />\n )}\n </Box>\n </Box>\n </UnstyledButton>\n );\n}\n"],"names":[],"mappings":";;;;;AA4BO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAmB;AACjB,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,SAAS;AAAA,MACT,MAAK;AAAA,MACL,gBAAc;AAAA,MACd,OAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO;AAAA,QACP,SAAS;AAAA,QACT,cAAc;AAAA,QACd,QAAQ,aAAa,WAAW,aAAa,oBAAoB,aAAa,kBAAkB;AAAA,QAChG,YAAY,WAAW,aAAa,qBAAqB,aAAa;AAAA,QACtE,YAAY;AAAA,QACZ,WAAW;AAAA,MAAA;AAAA,MAGb,UAAA,qBAAC,KAAA,EAAI,OAAO,EAAE,SAAS,QAAQ,KAAK,IAAI,YAAY,aAAA,GACjD,UAAA;AAAA,QAAA,+BAAY,KAAA,EAAI,OAAO,EAAE,YAAY,EAAA,GAAM,UAAA,SAAQ;AAAA,QACpD,qBAAC,OAAA,EAAM,KAAK,GAAG,OAAO,EAAE,UAAU,GAAG,MAAM,EAAA,GACzC,UAAA;AAAA,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO;AAAA,gBACL,SAAS;AAAA,gBACT,gBAAgB;AAAA,gBAChB,YAAY;AAAA,gBACZ,KAAK;AAAA,cAAA;AAAA,cAGP,UAAA;AAAA,gBAAA,oBAAC,MAAA,EAAK,IAAI,KAAK,MAAK,MAAK,GAAG,aAAa,kBACtC,UAAA,MAAA,CACH;AAAA,gBACC;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAEF,eACC,oBAAC,MAAA,EAAK,MAAK,MAAK,GAAG,aAAa,oBAAoB,IAAI,KACrD,UAAA,YAAA,CACH;AAAA,QAAA,GAEJ;AAAA,QACA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,OAAO;AAAA,cACL,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,cAAc;AAAA,cACd,QAAQ,aAAa,WAAW,aAAa,oBAAoB,aAAa,kBAAkB;AAAA,cAChG,YAAY,WAAW,aAAa,oBAAoB;AAAA,cACxD,UAAU;AAAA,cACV,YAAY;AAAA,cACZ,WAAW;AAAA,YAAA;AAAA,YAGZ,UAAA,YACC;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,OAAO;AAAA,kBACL,UAAU;AAAA,kBACV,OAAO;AAAA,kBACP,cAAc;AAAA,kBACd,YAAY,aAAa;AAAA,gBAAA;AAAA,cAC3B;AAAA,YAAA;AAAA,UACF;AAAA,QAAA;AAAA,MAEJ,EAAA,CACF;AAAA,IAAA;AAAA,EAAA;AAGN;"}
@@ -15,24 +15,33 @@ function StatCard({
15
15
  trend,
16
16
  ...rest
17
17
  }) {
18
- return /* @__PURE__ */ jsxRuntime.jsx(Card.Card, { bg: `${color}.0`, bd: `1px solid ${color}.2`, ...rest, children: /* @__PURE__ */ jsxRuntime.jsxs(Group.Group, { justify: "space-between", align: "flex-start", children: [
19
- /* @__PURE__ */ jsxRuntime.jsxs(layout.Stack, { gap: 4, children: [
20
- /* @__PURE__ */ jsxRuntime.jsx(
21
- Text.Text,
22
- {
23
- size: "xs",
24
- fw: 600,
25
- tt: "uppercase",
26
- c: `${color}.6`,
27
- style: { letterSpacing: "0.05em" },
28
- children: label
29
- }
30
- ),
31
- /* @__PURE__ */ jsxRuntime.jsx(Text.Text, { fw: 700, size: "xl", lh: 1, children: value }),
32
- trend && /* @__PURE__ */ jsxRuntime.jsx(Text.Text, { size: "xs", c: index.fairmintVars.colorTextSecondary, children: trend })
33
- ] }),
34
- icon && /* @__PURE__ */ jsxRuntime.jsx(layout.Box, { c: `${color}.5`, fz: "1.5rem", children: icon })
35
- ] }) });
18
+ const isNeutral = color === "neutral";
19
+ return /* @__PURE__ */ jsxRuntime.jsx(
20
+ Card.Card,
21
+ {
22
+ bg: isNeutral ? index.fairmintVars.colorBgSurface : `${color}.0`,
23
+ bd: isNeutral ? `1px solid ${index.fairmintVars.colorBorderDefault}` : `1px solid ${color}.2`,
24
+ ...rest,
25
+ children: /* @__PURE__ */ jsxRuntime.jsxs(Group.Group, { justify: "space-between", align: "flex-start", children: [
26
+ /* @__PURE__ */ jsxRuntime.jsxs(layout.Stack, { gap: 4, children: [
27
+ /* @__PURE__ */ jsxRuntime.jsx(
28
+ Text.Text,
29
+ {
30
+ size: "xs",
31
+ fw: 600,
32
+ tt: "uppercase",
33
+ c: isNeutral ? index.fairmintVars.colorTextTertiary : `${color}.6`,
34
+ style: { letterSpacing: "0.05em" },
35
+ children: label
36
+ }
37
+ ),
38
+ /* @__PURE__ */ jsxRuntime.jsx(Text.Text, { fw: 700, size: "xl", lh: 1, children: value }),
39
+ trend && /* @__PURE__ */ jsxRuntime.jsx(Text.Text, { size: "xs", c: index.fairmintVars.colorTextSecondary, children: trend })
40
+ ] }),
41
+ icon && /* @__PURE__ */ jsxRuntime.jsx(layout.Box, { c: `${color}.5`, fz: "1.5rem", children: icon })
42
+ ] })
43
+ }
44
+ );
36
45
  }
37
46
  exports.StatCard = StatCard;
38
47
  //# sourceMappingURL=StatCard.cjs.map