@oatfi/ui 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -12,6 +12,17 @@ var IconButton = require('@mui/material/IconButton');
12
12
  var Menu = require('@mui/material/Menu');
13
13
  var MenuItem = require('@mui/material/MenuItem');
14
14
  var MoreVertIcon = require('@mui/icons-material/MoreVert');
15
+ var DescriptionIcon = require('@mui/icons-material/Description');
16
+ var CircularProgress = require('@mui/material/CircularProgress');
17
+ var ExpandMoreIcon = require('@mui/icons-material/ExpandMore');
18
+ var LinkIcon = require('@mui/icons-material/Link');
19
+ var RefreshIcon = require('@mui/icons-material/Refresh');
20
+ var Box = require('@mui/material/Box');
21
+ var Button$1 = require('@mui/material/Button');
22
+ var CheckRoundedIcon = require('@mui/icons-material/CheckRounded');
23
+ var Stack = require('@mui/material/Stack');
24
+ var LockIcon = require('@mui/icons-material/Lock');
25
+ var DeleteOutlineIcon = require('@mui/icons-material/DeleteOutline');
15
26
 
16
27
  const defaultTheme = {
17
28
  colors: {
@@ -431,7 +442,7 @@ const Container = styled.div`
431
442
  max-width: 1000px;
432
443
  margin: 0 auto;
433
444
  `;
434
- const Content = styled.div`
445
+ const Content$1 = styled.div`
435
446
  margin-top: 1.5rem;
436
447
  margin-bottom: 1.5rem;
437
448
  `;
@@ -1025,6 +1036,14 @@ function SearchDropdown({
1025
1036
  );
1026
1037
  }
1027
1038
 
1039
+ function formatFileSize(bytes) {
1040
+ if (bytes === 0) return "0 Bytes";
1041
+ const k = 1024;
1042
+ const sizes = ["Bytes", "KB", "MB", "GB"];
1043
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
1044
+ return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
1045
+ }
1046
+
1028
1047
  const FileInputContainer = styled.div`
1029
1048
  display: flex;
1030
1049
  flex-direction: column;
@@ -1109,13 +1128,6 @@ const FileRequirements = styled.div`
1109
1128
  border: 1px solid ${({ theme }) => theme.border.color};
1110
1129
  border-radius: ${({ theme }) => theme.border.radius};
1111
1130
  `;
1112
- const formatFileSize = (bytes) => {
1113
- if (bytes === 0) return "0 Bytes";
1114
- const k = 1024;
1115
- const sizes = ["Bytes", "KB", "MB", "GB"];
1116
- const i = Math.floor(Math.log(bytes) / Math.log(k));
1117
- return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
1118
- };
1119
1131
  function FileInput({
1120
1132
  label,
1121
1133
  error,
@@ -1483,7 +1495,7 @@ function Loader({ className, size, label = "Loading", testId }) {
1483
1495
  );
1484
1496
  }
1485
1497
 
1486
- const Root = styled.footer`
1498
+ const Root$1 = styled.footer`
1487
1499
  margin-top: 2rem;
1488
1500
  padding-top: 0.75rem;
1489
1501
  border-top: ${({ theme }) => `${theme.border.width} solid ${theme.colors.border}`};
@@ -1508,7 +1520,7 @@ const Anchor = styled.a`
1508
1520
  }
1509
1521
  `;
1510
1522
  function Footnote({ title, text, links = [], className, testId }) {
1511
- return /* @__PURE__ */ jsxRuntime.jsxs(Root, { className, "data-testid": testId, children: [
1523
+ return /* @__PURE__ */ jsxRuntime.jsxs(Root$1, { className, "data-testid": testId, children: [
1512
1524
  title && /* @__PURE__ */ jsxRuntime.jsx(Title, { children: title }),
1513
1525
  /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { margin: 0 }, children: [
1514
1526
  text && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -1576,6 +1588,768 @@ function DotsMenu({
1576
1588
  ] });
1577
1589
  }
1578
1590
 
1591
+ const AsteriskMark = styled.sup`
1592
+ color: ${({ theme }) => theme.colors.accent};
1593
+ font-weight: 600;
1594
+ margin-left: 1px;
1595
+ font-size: 0.95em;
1596
+ `;
1597
+ const AsteriskNote = styled.p`
1598
+ font-size: 12px;
1599
+ color: ${({ theme }) => theme.colors.secondary};
1600
+ margin: 14px 4px 0;
1601
+ line-height: 1.5;
1602
+ font-style: italic;
1603
+
1604
+ .asterisk {
1605
+ font-style: normal;
1606
+ color: ${({ theme }) => theme.colors.accent};
1607
+ font-weight: 600;
1608
+ margin-right: 2px;
1609
+ }
1610
+ `;
1611
+
1612
+ const background = (theme, variant) => {
1613
+ if (variant === "filled") return theme.colors.accent;
1614
+ if (variant === "success" || variant === "neutral") return theme.colors.background;
1615
+ return `${theme.colors.accent}14`;
1616
+ };
1617
+ const foreground = (theme, variant) => {
1618
+ if (variant === "filled") return theme.colors.background;
1619
+ if (variant === "success") return theme.colors.success;
1620
+ if (variant === "neutral") return theme.colors.secondary;
1621
+ return theme.colors.accent;
1622
+ };
1623
+ const outline = (theme, variant) => {
1624
+ if (variant === "success") return `1px solid ${theme.colors.success}`;
1625
+ if (variant === "neutral") return `1px solid ${theme.colors.border}`;
1626
+ if (variant === "filled") return `1px solid ${theme.colors.accent}`;
1627
+ return "none";
1628
+ };
1629
+ const Badge = styled.span`
1630
+ font-size: 10px;
1631
+ padding: 2px 8px;
1632
+ border-radius: 4px;
1633
+ font-weight: 600;
1634
+ letter-spacing: 0.04em;
1635
+ text-transform: uppercase;
1636
+ white-space: nowrap;
1637
+ background: ${({ theme, $variant }) => background(theme, $variant)};
1638
+ color: ${({ theme, $variant }) => foreground(theme, $variant)};
1639
+ border: ${({ theme, $variant }) => outline(theme, $variant)};
1640
+ `;
1641
+
1642
+ const Zone = styled.div`
1643
+ display: flex;
1644
+ flex-direction: column;
1645
+ align-items: center;
1646
+ justify-content: center;
1647
+ gap: 4px;
1648
+ width: 100%;
1649
+ min-height: 100px;
1650
+ border: 1px dashed ${({ theme }) => theme.colors.border};
1651
+ border-radius: ${({ theme }) => theme.border.radius};
1652
+ padding: 16px;
1653
+ text-align: center;
1654
+ background: ${({ theme }) => theme.colors.surface};
1655
+ cursor: pointer;
1656
+ transition:
1657
+ border-color 0.15s ease,
1658
+ background 0.15s ease;
1659
+
1660
+ ${({ $dragging, theme }) => $dragging && `
1661
+ border-color: ${theme.colors.accent};
1662
+ background: ${theme.colors.accent}14;
1663
+ `}
1664
+
1665
+ &:hover {
1666
+ border-color: ${({ theme }) => theme.colors.accent};
1667
+ background: ${({ theme }) => `${theme.colors.accent}14`};
1668
+ }
1669
+
1670
+ &:focus-visible {
1671
+ outline: none;
1672
+ border-color: ${({ theme }) => theme.colors.accent};
1673
+ box-shadow: 0 0 0 3px ${({ theme }) => `${theme.colors.accent}26`};
1674
+ }
1675
+ `;
1676
+ const ZoneIcon = styled(CloudUploadIcon)`
1677
+ color: ${({ theme }) => theme.colors.secondary};
1678
+ `;
1679
+ const ZoneText = styled.p`
1680
+ font-size: 13px;
1681
+ margin: 0;
1682
+ color: ${({ theme }) => theme.colors.primary};
1683
+
1684
+ span {
1685
+ color: ${({ theme }) => theme.colors.accent};
1686
+ }
1687
+ `;
1688
+ const ZoneHint = styled.p`
1689
+ font-size: 11px;
1690
+ color: ${({ theme }) => theme.colors.secondary};
1691
+ margin: 0;
1692
+ `;
1693
+ const HiddenInput = styled.input`
1694
+ display: none;
1695
+ `;
1696
+ const FileList = styled.div`
1697
+ margin-top: 10px;
1698
+ display: flex;
1699
+ flex-direction: column;
1700
+ gap: 6px;
1701
+ `;
1702
+ const FileItem = styled.div`
1703
+ display: flex;
1704
+ align-items: center;
1705
+ gap: 10px;
1706
+ padding: 8px 12px;
1707
+ background: ${({ theme }) => theme.colors.background};
1708
+ border: 1px solid ${({ theme }) => theme.colors.border};
1709
+ border-radius: 4px;
1710
+ font-size: 13px;
1711
+
1712
+ .file-icon {
1713
+ color: ${({ theme }) => theme.colors.secondary};
1714
+ font-size: 18px;
1715
+ flex-shrink: 0;
1716
+ }
1717
+
1718
+ .file-name {
1719
+ flex: 1;
1720
+ min-width: 0;
1721
+ overflow: hidden;
1722
+ text-overflow: ellipsis;
1723
+ white-space: nowrap;
1724
+ color: ${({ theme }) => theme.colors.primary};
1725
+ }
1726
+
1727
+ .file-size {
1728
+ color: ${({ theme }) => theme.colors.secondary};
1729
+ font-size: 12px;
1730
+ flex-shrink: 0;
1731
+ }
1732
+ `;
1733
+ const RemoveButton = styled.button`
1734
+ display: inline-flex;
1735
+ align-items: center;
1736
+ justify-content: center;
1737
+ width: 24px;
1738
+ height: 24px;
1739
+ padding: 0;
1740
+ border: none;
1741
+ background: transparent;
1742
+ color: ${({ theme }) => theme.colors.secondary};
1743
+ border-radius: 4px;
1744
+ cursor: pointer;
1745
+ flex-shrink: 0;
1746
+ transition:
1747
+ background 0.15s ease,
1748
+ color 0.15s ease;
1749
+
1750
+ &:hover {
1751
+ background: ${({ theme }) => theme.colors.surface};
1752
+ color: ${({ theme }) => theme.colors.error};
1753
+ }
1754
+
1755
+ &:disabled {
1756
+ cursor: not-allowed;
1757
+ opacity: 0.6;
1758
+ }
1759
+
1760
+ svg {
1761
+ font-size: 16px;
1762
+ }
1763
+ `;
1764
+ function UploadZone({
1765
+ accept,
1766
+ hint,
1767
+ files = [],
1768
+ onAdd,
1769
+ onRemove,
1770
+ removingIds,
1771
+ disabled = false,
1772
+ inputId,
1773
+ testId
1774
+ }) {
1775
+ const inputRef = React.useRef(null);
1776
+ const [dragging, setDragging] = React.useState(false);
1777
+ const openPicker = () => {
1778
+ if (!disabled) inputRef.current?.click();
1779
+ };
1780
+ const handleKeyDown = (event) => {
1781
+ if (event.key === "Enter" || event.key === " ") {
1782
+ event.preventDefault();
1783
+ openPicker();
1784
+ }
1785
+ };
1786
+ const handleChange = (event) => {
1787
+ if (event.target.files?.length) onAdd(event.target.files);
1788
+ event.target.value = "";
1789
+ };
1790
+ const handleDrop = (event) => {
1791
+ event.preventDefault();
1792
+ setDragging(false);
1793
+ if (disabled) return;
1794
+ if (event.dataTransfer.files?.length) onAdd(event.dataTransfer.files);
1795
+ };
1796
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1797
+ /* @__PURE__ */ jsxRuntime.jsxs(
1798
+ Zone,
1799
+ {
1800
+ role: "button",
1801
+ tabIndex: disabled ? -1 : 0,
1802
+ "aria-disabled": disabled,
1803
+ $dragging: dragging,
1804
+ onClick: openPicker,
1805
+ onKeyDown: handleKeyDown,
1806
+ onDragOver: (event) => {
1807
+ event.preventDefault();
1808
+ if (!disabled) setDragging(true);
1809
+ },
1810
+ onDragLeave: () => setDragging(false),
1811
+ onDrop: handleDrop,
1812
+ children: [
1813
+ /* @__PURE__ */ jsxRuntime.jsx(
1814
+ HiddenInput,
1815
+ {
1816
+ id: inputId,
1817
+ ref: inputRef,
1818
+ type: "file",
1819
+ multiple: true,
1820
+ accept,
1821
+ disabled,
1822
+ onChange: handleChange,
1823
+ "data-testid": testId
1824
+ }
1825
+ ),
1826
+ /* @__PURE__ */ jsxRuntime.jsx(ZoneIcon, { fontSize: "medium", "aria-hidden": "true" }),
1827
+ /* @__PURE__ */ jsxRuntime.jsxs(ZoneText, { children: [
1828
+ "Drop files or ",
1829
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "browse" })
1830
+ ] }),
1831
+ /* @__PURE__ */ jsxRuntime.jsx(ZoneHint, { children: hint })
1832
+ ]
1833
+ }
1834
+ ),
1835
+ files.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(FileList, { children: files.map((file) => {
1836
+ const isRemoving = removingIds?.has(file.id);
1837
+ return /* @__PURE__ */ jsxRuntime.jsxs(FileItem, { children: [
1838
+ /* @__PURE__ */ jsxRuntime.jsx(DescriptionIcon, { className: "file-icon", "aria-hidden": "true" }),
1839
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "file-name", children: file.fileName }),
1840
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "file-size", children: formatFileSize(file.fileSize) }),
1841
+ isRemoving ? /* @__PURE__ */ jsxRuntime.jsx(CircularProgress, { size: 16, color: "secondary" }) : /* @__PURE__ */ jsxRuntime.jsx(
1842
+ RemoveButton,
1843
+ {
1844
+ type: "button",
1845
+ "aria-label": `Remove ${file.fileName}`,
1846
+ disabled,
1847
+ onClick: () => onRemove(file.id),
1848
+ children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, { "aria-hidden": "true" })
1849
+ }
1850
+ )
1851
+ ] }, file.id);
1852
+ }) })
1853
+ ] });
1854
+ }
1855
+
1856
+ const Wrapper = styled.div`
1857
+ background: ${({ theme }) => theme.colors.background};
1858
+ border: 1px solid ${({ theme, $open }) => $open ? theme.colors.secondary : theme.colors.border};
1859
+ border-radius: ${({ theme }) => theme.border.radius};
1860
+ overflow: hidden;
1861
+ transition: border-color 0.15s ease;
1862
+
1863
+ ${({ $open }) => $open && "grid-column: 1 / -1;"}
1864
+ `;
1865
+ const Summary = styled.button`
1866
+ width: 100%;
1867
+ text-align: left;
1868
+ cursor: pointer;
1869
+ padding: 12px 16px;
1870
+ display: flex;
1871
+ align-items: center;
1872
+ gap: 12px;
1873
+ background: transparent;
1874
+ border: none;
1875
+ transition: background 0.15s ease;
1876
+
1877
+ &:hover {
1878
+ background: ${({ theme }) => theme.colors.surface};
1879
+ }
1880
+
1881
+ &:focus-visible {
1882
+ outline: none;
1883
+ box-shadow: inset 0 0 0 2px ${({ theme }) => `${theme.colors.accent}40`};
1884
+ }
1885
+ `;
1886
+ const SummaryText = styled.div`
1887
+ flex: 1;
1888
+ min-width: 0;
1889
+ `;
1890
+ const Chevron = styled(ExpandMoreIcon)`
1891
+ color: ${({ theme }) => theme.colors.secondary};
1892
+ transition: transform 0.2s ease;
1893
+ transform: rotate(${({ $open }) => $open ? "180deg" : "0deg"});
1894
+ flex-shrink: 0;
1895
+ `;
1896
+ const Content = styled.div`
1897
+ padding: 12px 16px 14px;
1898
+ `;
1899
+ const Note = styled(AsteriskNote)`
1900
+ margin: 4px 0 0;
1901
+ `;
1902
+ function CollapsibleSource({
1903
+ title,
1904
+ desc,
1905
+ note,
1906
+ open = false,
1907
+ onToggle,
1908
+ children,
1909
+ testId
1910
+ }) {
1911
+ const contentId = React.useId();
1912
+ return /* @__PURE__ */ jsxRuntime.jsxs(Wrapper, { $open: open, children: [
1913
+ /* @__PURE__ */ jsxRuntime.jsxs(
1914
+ Summary,
1915
+ {
1916
+ type: "button",
1917
+ "aria-expanded": open,
1918
+ "aria-controls": contentId,
1919
+ onClick: onToggle,
1920
+ "data-testid": testId,
1921
+ children: [
1922
+ /* @__PURE__ */ jsxRuntime.jsxs(SummaryText, { children: [
1923
+ /* @__PURE__ */ jsxRuntime.jsxs(FormSubtitle, { style: { margin: 0 }, children: [
1924
+ title,
1925
+ note ? /* @__PURE__ */ jsxRuntime.jsx(AsteriskMark, { "aria-hidden": "true", children: "*" }) : null
1926
+ ] }),
1927
+ desc ? /* @__PURE__ */ jsxRuntime.jsx(Body100, { color: "secondary", style: { margin: "2px 0 0" }, children: desc }) : null,
1928
+ note ? /* @__PURE__ */ jsxRuntime.jsxs(Note, { children: [
1929
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "asterisk", "aria-hidden": "true", children: "*" }),
1930
+ note
1931
+ ] }) : null
1932
+ ] }),
1933
+ /* @__PURE__ */ jsxRuntime.jsx(Chevron, { $open: open, "aria-hidden": "true" })
1934
+ ]
1935
+ }
1936
+ ),
1937
+ open && /* @__PURE__ */ jsxRuntime.jsx(Content, { id: contentId, children })
1938
+ ] });
1939
+ }
1940
+
1941
+ const maskOf$1 = (plaidData) => {
1942
+ const account = plaidData?.accounts?.[0];
1943
+ return account?.mask || account?.accountMask || null;
1944
+ };
1945
+ function PlaidTile({ plaidData, onConnect, isConnecting = false, testId }) {
1946
+ const { palette, shape } = styles.useTheme();
1947
+ const connected = Boolean(plaidData);
1948
+ const institutionName = plaidData?.institution?.name || "Your bank";
1949
+ const mask = maskOf$1(plaidData);
1950
+ const accentColor = connected ? palette.success.dark : palette.primary.main;
1951
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1952
+ Box,
1953
+ {
1954
+ component: "section",
1955
+ "aria-labelledby": "plaid-tile-title",
1956
+ sx: {
1957
+ display: "flex",
1958
+ alignItems: "center",
1959
+ justifyContent: "space-between",
1960
+ gap: "14px",
1961
+ flexWrap: "wrap",
1962
+ padding: "16px 18px",
1963
+ marginBottom: "14px",
1964
+ borderRadius: `${shape.borderRadius}px`,
1965
+ border: `1px solid ${accentColor}`,
1966
+ backgroundColor: connected ? styles.alpha(palette.success.main, 0.08) : palette.background.default,
1967
+ transition: "border-color 0.15s ease, background 0.15s ease"
1968
+ },
1969
+ children: [
1970
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { sx: { flex: 1, minWidth: 220 }, children: [
1971
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: "10px", marginBottom: "2px" }, children: [
1972
+ /* @__PURE__ */ jsxRuntime.jsx(FormSubtitle, { id: "plaid-tile-title", style: { margin: 0, fontWeight: 600 }, children: connected ? "Connected via Plaid" : "Connect via Plaid" }),
1973
+ /* @__PURE__ */ jsxRuntime.jsx(Badge, { $variant: connected ? "success" : "info", children: connected ? "Verified" : "Recommended" })
1974
+ ] }),
1975
+ connected ? /* @__PURE__ */ jsxRuntime.jsxs(Body100, { style: { margin: 0, color: palette.success.dark, fontWeight: 500 }, children: [
1976
+ institutionName,
1977
+ mask ? ` \xB7\xB7\xB7\xB7${mask}` : ""
1978
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(Body100, { color: "secondary", style: { margin: 0 }, children: "Securely link your bank in seconds. Best signal for fastest decisions." })
1979
+ ] }),
1980
+ connected ? /* @__PURE__ */ jsxRuntime.jsx(
1981
+ Button$1,
1982
+ {
1983
+ size: "small",
1984
+ variant: "outlined",
1985
+ color: "inherit",
1986
+ type: "button",
1987
+ onClick: onConnect,
1988
+ disabled: isConnecting,
1989
+ "data-testid": testId,
1990
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(RefreshIcon, { fontSize: "small" }),
1991
+ sx: { flexShrink: 0, textTransform: "none" },
1992
+ children: isConnecting ? "Connecting\u2026" : "Reconnect"
1993
+ }
1994
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1995
+ Button$1,
1996
+ {
1997
+ size: "small",
1998
+ variant: "contained",
1999
+ color: "primary",
2000
+ type: "button",
2001
+ onClick: onConnect,
2002
+ disabled: isConnecting,
2003
+ "data-testid": testId,
2004
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(LinkIcon, { fontSize: "small" }),
2005
+ sx: { flexShrink: 0, textTransform: "none" },
2006
+ children: isConnecting ? "Connecting\u2026" : "Connect bank account"
2007
+ }
2008
+ )
2009
+ ]
2010
+ }
2011
+ );
2012
+ }
2013
+
2014
+ const Root = styled.div`
2015
+ background-color: ${({ theme }) => theme.colors.surface};
2016
+ border: 1px solid ${({ theme }) => theme.colors.border};
2017
+ border-radius: ${({ theme }) => theme.border.radius};
2018
+ padding: 1.5rem;
2019
+ overflow-y: auto;
2020
+ max-height: 400px;
2021
+ margin-bottom: 1rem;
2022
+ font-size: 14px;
2023
+ line-height: 1.6;
2024
+ `;
2025
+ function TermsDocument({ html, className, testId }) {
2026
+ return /* @__PURE__ */ jsxRuntime.jsx(
2027
+ Root,
2028
+ {
2029
+ className,
2030
+ "data-testid": testId,
2031
+ dangerouslySetInnerHTML: { __html: html }
2032
+ }
2033
+ );
2034
+ }
2035
+ const HelperText = styled.span`
2036
+ display: block;
2037
+ font-size: 12.5px;
2038
+ color: ${({ theme }) => theme.colors.secondary};
2039
+ text-align: right;
2040
+ margin-top: 0.5rem;
2041
+ `;
2042
+
2043
+ const DECLINED = /* @__PURE__ */ new Set([
2044
+ "CLOSED_NO_DECISION",
2045
+ "DECLINED",
2046
+ "DENIED",
2047
+ "ERROR",
2048
+ "N/A",
2049
+ "REJECTED"
2050
+ ]);
2051
+ function UnderwritingStatus({
2052
+ status,
2053
+ creditLimit,
2054
+ children,
2055
+ testId
2056
+ }) {
2057
+ if (status === "PROCESSING") {
2058
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-testid": testId, children: [
2059
+ /* @__PURE__ */ jsxRuntime.jsx(H3, { children: "Your application is being reviewed" }),
2060
+ /* @__PURE__ */ jsxRuntime.jsxs(Stack, { width: "100%", alignItems: "center", gap: "16px", children: [
2061
+ /* @__PURE__ */ jsxRuntime.jsx(Loader, {}),
2062
+ /* @__PURE__ */ jsxRuntime.jsx(Body200, { children: "We are underwriting your business. This process can take a minute or two." })
2063
+ ] })
2064
+ ] });
2065
+ }
2066
+ if (status === "APPROVED") {
2067
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-testid": testId, children: [
2068
+ /* @__PURE__ */ jsxRuntime.jsx(H3, { children: "Congrats!" }),
2069
+ /* @__PURE__ */ jsxRuntime.jsxs(Body200, { children: [
2070
+ "You have been approved.",
2071
+ creditLimit ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2072
+ " Your credit limit is: ",
2073
+ creditLimit
2074
+ ] }) : null
2075
+ ] }),
2076
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { sx: { display: "flex", justifyContent: "center", alignItems: "center" }, children: /* @__PURE__ */ jsxRuntime.jsx(CheckRoundedIcon, { color: "success", sx: { fontSize: "5rem" } }) }),
2077
+ children
2078
+ ] });
2079
+ }
2080
+ if (status && DECLINED.has(status)) {
2081
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-testid": testId, children: [
2082
+ /* @__PURE__ */ jsxRuntime.jsx(H3, { children: "Sorry, we cannot approve your application" }),
2083
+ /* @__PURE__ */ jsxRuntime.jsx(Body200, { children: "We are sorry to inform you that we cannot approve your application. Please try again later." })
2084
+ ] });
2085
+ }
2086
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-testid": testId, children: [
2087
+ /* @__PURE__ */ jsxRuntime.jsx(H3, { children: "Your application is being reviewed" }),
2088
+ /* @__PURE__ */ jsxRuntime.jsx(Body200, { children: "We are reviewing your application and will reach out within 2 business days." })
2089
+ ] });
2090
+ }
2091
+
2092
+ const MethodCard = styled.div`
2093
+ display: flex;
2094
+ gap: 12px;
2095
+ align-items: flex-start;
2096
+ padding: 14px 16px;
2097
+ margin-bottom: 10px;
2098
+ border-radius: ${({ theme }) => theme.border.radius};
2099
+ border: 1px solid
2100
+ ${({ theme, $default }) => $default ? theme.colors.accent : theme.colors.border};
2101
+ background: ${({ theme, $default, $readonly }) => $default ? `${theme.colors.accent}14` : $readonly ? theme.colors.surface : theme.colors.background};
2102
+ transition:
2103
+ border-color 0.15s ease,
2104
+ background 0.15s ease;
2105
+ `;
2106
+ const MethodBody = styled.div`
2107
+ flex: 1;
2108
+ min-width: 0;
2109
+ `;
2110
+ const MethodHeader = styled.div`
2111
+ display: flex;
2112
+ align-items: center;
2113
+ justify-content: space-between;
2114
+ gap: 8px;
2115
+ margin-bottom: ${({ $tight }) => $tight ? "6px" : "12px"};
2116
+ `;
2117
+ const MethodTitle = styled.span`
2118
+ display: flex;
2119
+ align-items: center;
2120
+ gap: 8px;
2121
+ flex-wrap: wrap;
2122
+ font-size: 14px;
2123
+ font-weight: 600;
2124
+ color: ${({ theme }) => theme.colors.primary};
2125
+ `;
2126
+ const FieldsGrid = styled.div`
2127
+ display: grid;
2128
+ grid-template-columns: 1fr 1fr;
2129
+ gap: 10px;
2130
+
2131
+ @media (max-width: 540px) {
2132
+ grid-template-columns: 1fr;
2133
+ }
2134
+ `;
2135
+ const Banner = styled.div`
2136
+ display: flex;
2137
+ gap: 10px;
2138
+ align-items: flex-start;
2139
+ padding: 10px 14px;
2140
+ background: ${({ theme }) => `${theme.colors.accent}14`};
2141
+ border-left: 3px solid ${({ theme }) => theme.colors.accent};
2142
+ border-radius: ${({ theme }) => theme.border.radius};
2143
+ margin-bottom: 1.25rem;
2144
+
2145
+ svg {
2146
+ color: ${({ theme }) => theme.colors.accent};
2147
+ flex-shrink: 0;
2148
+ margin-top: 1px;
2149
+ }
2150
+
2151
+ p {
2152
+ font-size: 13px;
2153
+ color: ${({ theme }) => theme.colors.accent};
2154
+ margin: 0;
2155
+ line-height: 1.5;
2156
+ }
2157
+ `;
2158
+ const FooterActions = styled.div`
2159
+ display: flex;
2160
+ justify-content: space-between;
2161
+ align-items: center;
2162
+ gap: 12px;
2163
+ margin-top: 1.25rem;
2164
+ flex-wrap: wrap;
2165
+
2166
+ button {
2167
+ margin-top: 0;
2168
+ }
2169
+ `;
2170
+ const FooterRight = styled.div`
2171
+ display: flex;
2172
+ align-items: center;
2173
+ gap: 14px;
2174
+ `;
2175
+
2176
+ const maskOf = (plaidData) => {
2177
+ const account = plaidData?.accounts?.[0];
2178
+ return account?.mask || account?.accountMask || null;
2179
+ };
2180
+ function PlaidMethodCard({
2181
+ plaidData,
2182
+ isDefault = false,
2183
+ onSelectDefault,
2184
+ name = "default-method",
2185
+ testId
2186
+ }) {
2187
+ const institutionName = plaidData?.institution?.name || "Your bank";
2188
+ const mask = maskOf(plaidData);
2189
+ return /* @__PURE__ */ jsxRuntime.jsxs(MethodCard, { as: "label", htmlFor: "default-plaid", $default: isDefault, $readonly: true, children: [
2190
+ /* @__PURE__ */ jsxRuntime.jsx(
2191
+ RadioInput,
2192
+ {
2193
+ type: "radio",
2194
+ id: "default-plaid",
2195
+ name,
2196
+ checked: isDefault,
2197
+ onChange: onSelectDefault,
2198
+ "data-testid": testId
2199
+ }
2200
+ ),
2201
+ /* @__PURE__ */ jsxRuntime.jsxs(MethodBody, { children: [
2202
+ /* @__PURE__ */ jsxRuntime.jsxs(MethodHeader, { $tight: true, children: [
2203
+ /* @__PURE__ */ jsxRuntime.jsxs(MethodTitle, { children: [
2204
+ institutionName,
2205
+ /* @__PURE__ */ jsxRuntime.jsx(Badge, { $variant: "neutral", children: "Via Plaid" }),
2206
+ isDefault && /* @__PURE__ */ jsxRuntime.jsx(Badge, { $variant: "filled", children: "Default" })
2207
+ ] }),
2208
+ /* @__PURE__ */ jsxRuntime.jsx(LockIcon, { fontSize: "small", titleAccess: "Managed via Plaid" })
2209
+ ] }),
2210
+ /* @__PURE__ */ jsxRuntime.jsx(Body200, { color: "secondary", style: { margin: 0 }, children: mask ? `Account \xB7\xB7\xB7\xB7${mask}` : "Connected account" })
2211
+ ] })
2212
+ ] });
2213
+ }
2214
+
2215
+ function ManualMethodCard({
2216
+ index,
2217
+ value,
2218
+ isDefault = false,
2219
+ trashDisabled = false,
2220
+ disabled = false,
2221
+ accountError,
2222
+ routingError,
2223
+ onSelectDefault,
2224
+ onChangeField,
2225
+ onBlurField,
2226
+ onRemove,
2227
+ name = "default-method"
2228
+ }) {
2229
+ const radioId = `default-${value.id}`;
2230
+ return /* @__PURE__ */ jsxRuntime.jsxs(MethodCard, { $default: isDefault, children: [
2231
+ /* @__PURE__ */ jsxRuntime.jsx(
2232
+ RadioInput,
2233
+ {
2234
+ type: "radio",
2235
+ id: radioId,
2236
+ name,
2237
+ checked: isDefault,
2238
+ onChange: onSelectDefault,
2239
+ disabled
2240
+ }
2241
+ ),
2242
+ /* @__PURE__ */ jsxRuntime.jsxs(MethodBody, { children: [
2243
+ /* @__PURE__ */ jsxRuntime.jsxs(MethodHeader, { children: [
2244
+ /* @__PURE__ */ jsxRuntime.jsxs(MethodTitle, { children: [
2245
+ /* @__PURE__ */ jsxRuntime.jsxs(Body200, { as: "label", htmlFor: radioId, style: { margin: 0, cursor: "pointer" }, children: [
2246
+ "Account ",
2247
+ index + 1
2248
+ ] }),
2249
+ isDefault && /* @__PURE__ */ jsxRuntime.jsx(Badge, { $variant: "filled", children: "Default" })
2250
+ ] }),
2251
+ /* @__PURE__ */ jsxRuntime.jsx(
2252
+ IconButton,
2253
+ {
2254
+ size: "small",
2255
+ type: "button",
2256
+ onClick: onRemove,
2257
+ disabled: disabled || trashDisabled,
2258
+ "aria-label": "Remove this account",
2259
+ title: trashDisabled ? "At least one account is required" : "Remove this account",
2260
+ children: /* @__PURE__ */ jsxRuntime.jsx(DeleteOutlineIcon, { fontSize: "small" })
2261
+ }
2262
+ )
2263
+ ] }),
2264
+ /* @__PURE__ */ jsxRuntime.jsxs(FieldsGrid, { children: [
2265
+ /* @__PURE__ */ jsxRuntime.jsx("div", { onBlur: () => onBlurField("account"), children: /* @__PURE__ */ jsxRuntime.jsx(
2266
+ TextInput,
2267
+ {
2268
+ label: "Account number",
2269
+ placeholder: "Account number",
2270
+ value: value.account,
2271
+ onChange: (next) => onChangeField("account", next),
2272
+ error: accountError,
2273
+ disabled,
2274
+ onlyNumbers: true
2275
+ }
2276
+ ) }),
2277
+ /* @__PURE__ */ jsxRuntime.jsx("div", { onBlur: () => onBlurField("routing"), children: /* @__PURE__ */ jsxRuntime.jsx(
2278
+ TextInput,
2279
+ {
2280
+ label: "Routing number",
2281
+ placeholder: "Routing number",
2282
+ value: value.routing,
2283
+ onChange: (next) => onChangeField("routing", next),
2284
+ error: routingError,
2285
+ disabled,
2286
+ onlyNumbers: true
2287
+ }
2288
+ ) })
2289
+ ] })
2290
+ ] })
2291
+ ] });
2292
+ }
2293
+
2294
+ const ConsentRow = styled.label`
2295
+ display: flex;
2296
+ align-items: center;
2297
+ padding: 12px 14px;
2298
+ background: ${({ theme }) => theme.colors.surface};
2299
+ border-radius: ${({ theme }) => theme.border.radius};
2300
+ margin: 1.25rem 0;
2301
+ cursor: pointer;
2302
+ gap: 10px;
2303
+ `;
2304
+ function AchVerificationConsent({
2305
+ consentGiven = false,
2306
+ onChange,
2307
+ disabled = false,
2308
+ actionLabel = "Continue",
2309
+ testId
2310
+ }) {
2311
+ return /* @__PURE__ */ jsxRuntime.jsxs(ConsentRow, { children: [
2312
+ /* @__PURE__ */ jsxRuntime.jsx(
2313
+ CheckboxInput,
2314
+ {
2315
+ type: "checkbox",
2316
+ checked: consentGiven,
2317
+ onChange: (event) => onChange(event.target.checked),
2318
+ disabled,
2319
+ "data-testid": testId
2320
+ }
2321
+ ),
2322
+ /* @__PURE__ */ jsxRuntime.jsxs(Body100, { style: { margin: 0 }, children: [
2323
+ "By clicking ",
2324
+ actionLabel,
2325
+ ", I agree to the",
2326
+ " ",
2327
+ /* @__PURE__ */ jsxRuntime.jsx(
2328
+ "a",
2329
+ {
2330
+ href: "https://oatfi.com/payment-method-verification-consent",
2331
+ target: "_blank",
2332
+ rel: "noopener noreferrer",
2333
+ children: "payment method verification"
2334
+ }
2335
+ ),
2336
+ " ",
2337
+ "and acknowledge the",
2338
+ " ",
2339
+ /* @__PURE__ */ jsxRuntime.jsx(
2340
+ "a",
2341
+ {
2342
+ href: "https://oatfi.com/usa-patriot-act-disclosure-page",
2343
+ target: "_blank",
2344
+ rel: "noopener noreferrer",
2345
+ children: "USA PATRIOT Act disclosure"
2346
+ }
2347
+ ),
2348
+ "."
2349
+ ] })
2350
+ ] });
2351
+ }
2352
+
1579
2353
  const PreviewCard = styled.div`
1580
2354
  display: flex;
1581
2355
  gap: 2rem;
@@ -1647,7 +2421,12 @@ function Preview({ branding, className }) {
1647
2421
  return /* @__PURE__ */ jsxRuntime.jsx(ThemeProvider, { branding, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className, children: /* @__PURE__ */ jsxRuntime.jsx(PreviewContent, {}) }) });
1648
2422
  }
1649
2423
 
2424
+ exports.AchVerificationConsent = AchVerificationConsent;
2425
+ exports.AsteriskMark = AsteriskMark;
2426
+ exports.AsteriskNote = AsteriskNote;
1650
2427
  exports.AutocompleteInput = AutocompleteInput;
2428
+ exports.Badge = Badge;
2429
+ exports.Banner = Banner;
1651
2430
  exports.BaseInput = BaseInput;
1652
2431
  exports.Body100 = Body100;
1653
2432
  exports.Body200 = Body200;
@@ -1655,8 +2434,9 @@ exports.Body400 = Body400;
1655
2434
  exports.Button = Button;
1656
2435
  exports.ButtonContainer = ButtonContainer;
1657
2436
  exports.CheckboxInput = CheckboxInput;
2437
+ exports.CollapsibleSource = CollapsibleSource;
1658
2438
  exports.Container = Container;
1659
- exports.Content = Content;
2439
+ exports.Content = Content$1;
1660
2440
  exports.CurrencyInput = CurrencyInput;
1661
2441
  exports.DateInput = DateInput;
1662
2442
  exports.DetailElement = DetailElement;
@@ -1668,9 +2448,12 @@ exports.DropdownContainer = DropdownContainer;
1668
2448
  exports.DropdownItem = DropdownItem;
1669
2449
  exports.DropdownList = DropdownList;
1670
2450
  exports.EmailInput = EmailInput;
2451
+ exports.FieldsGrid = FieldsGrid;
1671
2452
  exports.FileInput = FileInput;
1672
2453
  exports.FlexColumnWrapper = FlexColumnWrapper;
1673
2454
  exports.FlexRowWrapper = FlexRowWrapper;
2455
+ exports.FooterActions = FooterActions;
2456
+ exports.FooterRight = FooterRight;
1674
2457
  exports.Footnote = Footnote;
1675
2458
  exports.Form = Form;
1676
2459
  exports.FormActions = FormActions;
@@ -1682,12 +2465,20 @@ exports.FormTitle = FormTitle;
1682
2465
  exports.H1 = H1;
1683
2466
  exports.H2 = H2;
1684
2467
  exports.H3 = H3;
2468
+ exports.HelperText = HelperText;
1685
2469
  exports.InputError = InputError;
1686
2470
  exports.InputLabel = InputLabel;
1687
2471
  exports.InputWrapper = InputWrapper;
1688
2472
  exports.Loader = Loader;
2473
+ exports.ManualMethodCard = ManualMethodCard;
2474
+ exports.MethodBody = MethodBody;
2475
+ exports.MethodCard = MethodCard;
2476
+ exports.MethodHeader = MethodHeader;
2477
+ exports.MethodTitle = MethodTitle;
1689
2478
  exports.NoResults = NoResults;
1690
2479
  exports.PhoneInput = PhoneInput;
2480
+ exports.PlaidMethodCard = PlaidMethodCard;
2481
+ exports.PlaidTile = PlaidTile;
1691
2482
  exports.Preview = Preview;
1692
2483
  exports.RadioInput = RadioInput;
1693
2484
  exports.SSNInput = SSNInput;
@@ -1697,9 +2488,12 @@ exports.StatusTag = StatusTag;
1697
2488
  exports.Stepper = Stepper;
1698
2489
  exports.Tabs = Tabs;
1699
2490
  exports.TaxIdInput = TaxIdInput;
2491
+ exports.TermsDocument = TermsDocument;
1700
2492
  exports.TermsList = TermsList;
1701
2493
  exports.TextInput = TextInput;
1702
2494
  exports.ThemeProvider = ThemeProvider;
2495
+ exports.UnderwritingStatus = UnderwritingStatus;
2496
+ exports.UploadZone = UploadZone;
1703
2497
  exports.buildMuiTheme = buildMuiTheme;
1704
2498
  exports.defaultTheme = defaultTheme;
1705
2499
  exports.mergeBranding = mergeBranding;