@oatfi/ui 0.4.0 → 0.6.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,785 @@ 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
+ /**
2107
+ * The unsaved-edit bar. It thickens the left border rather than adding one, so
2108
+ * the padding gives back the 2px it takes and the card's contents do not shift
2109
+ * when it appears mid-keystroke. Declared last so it wins over the shorthand
2110
+ * above, including on a $default card that already has an accent border.
2111
+ */
2112
+ ${({ theme, $edited }) => $edited && styled.css`
2113
+ border-left: 3px solid ${theme.colors.accent};
2114
+ padding-left: 14px;
2115
+ `}
2116
+ `;
2117
+ const MethodBody = styled.div`
2118
+ flex: 1;
2119
+ min-width: 0;
2120
+ `;
2121
+ const MethodHeader = styled.div`
2122
+ display: flex;
2123
+ align-items: center;
2124
+ justify-content: space-between;
2125
+ gap: 8px;
2126
+ margin-bottom: ${({ $tight }) => $tight ? "6px" : "12px"};
2127
+ `;
2128
+ const MethodTitle = styled.span`
2129
+ display: flex;
2130
+ align-items: center;
2131
+ gap: 8px;
2132
+ flex-wrap: wrap;
2133
+ font-size: 14px;
2134
+ font-weight: 600;
2135
+ color: ${({ theme }) => theme.colors.primary};
2136
+ `;
2137
+ const FieldsGrid = styled.div`
2138
+ display: grid;
2139
+ grid-template-columns: 1fr 1fr;
2140
+ gap: 10px;
2141
+
2142
+ @media (max-width: 540px) {
2143
+ grid-template-columns: 1fr;
2144
+ }
2145
+ `;
2146
+ const Banner = styled.div`
2147
+ display: flex;
2148
+ gap: 10px;
2149
+ align-items: flex-start;
2150
+ padding: 10px 14px;
2151
+ background: ${({ theme }) => `${theme.colors.accent}14`};
2152
+ border-left: 3px solid ${({ theme }) => theme.colors.accent};
2153
+ border-radius: ${({ theme }) => theme.border.radius};
2154
+ margin-bottom: 1.25rem;
2155
+
2156
+ svg {
2157
+ color: ${({ theme }) => theme.colors.accent};
2158
+ flex-shrink: 0;
2159
+ margin-top: 1px;
2160
+ }
2161
+
2162
+ p {
2163
+ font-size: 13px;
2164
+ color: ${({ theme }) => theme.colors.accent};
2165
+ margin: 0;
2166
+ line-height: 1.5;
2167
+ }
2168
+ `;
2169
+ const FooterActions = styled.div`
2170
+ display: flex;
2171
+ justify-content: space-between;
2172
+ align-items: center;
2173
+ gap: 12px;
2174
+ margin-top: 1.25rem;
2175
+ flex-wrap: wrap;
2176
+
2177
+ button {
2178
+ margin-top: 0;
2179
+ }
2180
+
2181
+ > :only-child {
2182
+ margin-left: auto;
2183
+ }
2184
+ `;
2185
+ const FooterRight = styled.div`
2186
+ display: flex;
2187
+ align-items: center;
2188
+ gap: 14px;
2189
+ `;
2190
+
2191
+ const maskOf = (plaidData) => {
2192
+ const account = plaidData?.accounts?.[0];
2193
+ return account?.mask || account?.accountMask || null;
2194
+ };
2195
+ function PlaidMethodCard({
2196
+ plaidData,
2197
+ isDefault = false,
2198
+ onSelectDefault,
2199
+ name = "default-method",
2200
+ testId
2201
+ }) {
2202
+ const institutionName = plaidData?.institution?.name || "Your bank";
2203
+ const mask = maskOf(plaidData);
2204
+ return /* @__PURE__ */ jsxRuntime.jsxs(MethodCard, { as: "label", htmlFor: "default-plaid", $default: isDefault, $readonly: true, children: [
2205
+ /* @__PURE__ */ jsxRuntime.jsx(
2206
+ RadioInput,
2207
+ {
2208
+ type: "radio",
2209
+ id: "default-plaid",
2210
+ name,
2211
+ checked: isDefault,
2212
+ onChange: onSelectDefault,
2213
+ "data-testid": testId
2214
+ }
2215
+ ),
2216
+ /* @__PURE__ */ jsxRuntime.jsxs(MethodBody, { children: [
2217
+ /* @__PURE__ */ jsxRuntime.jsxs(MethodHeader, { $tight: true, children: [
2218
+ /* @__PURE__ */ jsxRuntime.jsxs(MethodTitle, { children: [
2219
+ institutionName,
2220
+ /* @__PURE__ */ jsxRuntime.jsx(Badge, { $variant: "neutral", children: "Via Plaid" }),
2221
+ isDefault && /* @__PURE__ */ jsxRuntime.jsx(Badge, { $variant: "filled", children: "Default" })
2222
+ ] }),
2223
+ /* @__PURE__ */ jsxRuntime.jsx(LockIcon, { fontSize: "small", titleAccess: "Managed via Plaid" })
2224
+ ] }),
2225
+ /* @__PURE__ */ jsxRuntime.jsx(Body200, { color: "secondary", style: { margin: 0 }, children: mask ? `Account \xB7\xB7\xB7\xB7${mask}` : "Connected account" })
2226
+ ] })
2227
+ ] });
2228
+ }
2229
+
2230
+ function ManualMethodCard({
2231
+ index,
2232
+ value,
2233
+ isDefault = false,
2234
+ status,
2235
+ trashDisabled = false,
2236
+ disabled = false,
2237
+ accountError,
2238
+ routingError,
2239
+ onSelectDefault,
2240
+ onChangeField,
2241
+ onBlurField,
2242
+ onRemove,
2243
+ name = "default-method"
2244
+ }) {
2245
+ const radioId = `default-${value.id}`;
2246
+ return /* @__PURE__ */ jsxRuntime.jsxs(MethodCard, { $default: isDefault, $edited: status === "edited", children: [
2247
+ /* @__PURE__ */ jsxRuntime.jsx(
2248
+ RadioInput,
2249
+ {
2250
+ type: "radio",
2251
+ id: radioId,
2252
+ name,
2253
+ checked: isDefault,
2254
+ onChange: onSelectDefault,
2255
+ disabled
2256
+ }
2257
+ ),
2258
+ /* @__PURE__ */ jsxRuntime.jsxs(MethodBody, { children: [
2259
+ /* @__PURE__ */ jsxRuntime.jsxs(MethodHeader, { children: [
2260
+ /* @__PURE__ */ jsxRuntime.jsxs(MethodTitle, { children: [
2261
+ /* @__PURE__ */ jsxRuntime.jsxs(Body200, { as: "label", htmlFor: radioId, style: { margin: 0, cursor: "pointer" }, children: [
2262
+ "Account ",
2263
+ index + 1
2264
+ ] }),
2265
+ isDefault && /* @__PURE__ */ jsxRuntime.jsx(Badge, { $variant: "filled", children: "Default" }),
2266
+ status === "edited" && /* @__PURE__ */ jsxRuntime.jsx(Badge, { $variant: "info", children: "Unsaved" })
2267
+ ] }),
2268
+ /* @__PURE__ */ jsxRuntime.jsx(
2269
+ IconButton,
2270
+ {
2271
+ size: "small",
2272
+ type: "button",
2273
+ onClick: onRemove,
2274
+ disabled: disabled || trashDisabled,
2275
+ "aria-label": "Remove this account",
2276
+ title: trashDisabled ? "At least one account is required" : "Remove this account",
2277
+ children: /* @__PURE__ */ jsxRuntime.jsx(DeleteOutlineIcon, { fontSize: "small" })
2278
+ }
2279
+ )
2280
+ ] }),
2281
+ /* @__PURE__ */ jsxRuntime.jsxs(FieldsGrid, { children: [
2282
+ /* @__PURE__ */ jsxRuntime.jsx("div", { onBlur: () => onBlurField("account"), children: /* @__PURE__ */ jsxRuntime.jsx(
2283
+ TextInput,
2284
+ {
2285
+ label: "Account number",
2286
+ placeholder: "Account number",
2287
+ value: value.account,
2288
+ onChange: (next) => onChangeField("account", next),
2289
+ error: accountError,
2290
+ disabled,
2291
+ onlyNumbers: true
2292
+ }
2293
+ ) }),
2294
+ /* @__PURE__ */ jsxRuntime.jsx("div", { onBlur: () => onBlurField("routing"), children: /* @__PURE__ */ jsxRuntime.jsx(
2295
+ TextInput,
2296
+ {
2297
+ label: "Routing number",
2298
+ placeholder: "Routing number",
2299
+ value: value.routing,
2300
+ onChange: (next) => onChangeField("routing", next),
2301
+ error: routingError,
2302
+ disabled,
2303
+ onlyNumbers: true
2304
+ }
2305
+ ) })
2306
+ ] })
2307
+ ] })
2308
+ ] });
2309
+ }
2310
+
2311
+ const ConsentRow = styled.label`
2312
+ display: flex;
2313
+ align-items: center;
2314
+ padding: 12px 14px;
2315
+ background: ${({ theme }) => theme.colors.surface};
2316
+ border-radius: ${({ theme }) => theme.border.radius};
2317
+ margin: 1.25rem 0;
2318
+ cursor: pointer;
2319
+ gap: 10px;
2320
+ `;
2321
+ function AchVerificationConsent({
2322
+ consentGiven = false,
2323
+ onChange,
2324
+ disabled = false,
2325
+ actionLabel = "Continue",
2326
+ testId
2327
+ }) {
2328
+ return /* @__PURE__ */ jsxRuntime.jsxs(ConsentRow, { children: [
2329
+ /* @__PURE__ */ jsxRuntime.jsx(
2330
+ CheckboxInput,
2331
+ {
2332
+ type: "checkbox",
2333
+ checked: consentGiven,
2334
+ onChange: (event) => onChange(event.target.checked),
2335
+ disabled,
2336
+ "data-testid": testId
2337
+ }
2338
+ ),
2339
+ /* @__PURE__ */ jsxRuntime.jsxs(Body100, { style: { margin: 0 }, children: [
2340
+ "By clicking ",
2341
+ actionLabel,
2342
+ ", I agree to the",
2343
+ " ",
2344
+ /* @__PURE__ */ jsxRuntime.jsx(
2345
+ "a",
2346
+ {
2347
+ href: "https://oatfi.com/payment-method-verification-consent",
2348
+ target: "_blank",
2349
+ rel: "noopener noreferrer",
2350
+ children: "payment method verification"
2351
+ }
2352
+ ),
2353
+ " ",
2354
+ "and acknowledge the",
2355
+ " ",
2356
+ /* @__PURE__ */ jsxRuntime.jsx(
2357
+ "a",
2358
+ {
2359
+ href: "https://oatfi.com/usa-patriot-act-disclosure-page",
2360
+ target: "_blank",
2361
+ rel: "noopener noreferrer",
2362
+ children: "USA PATRIOT Act disclosure"
2363
+ }
2364
+ ),
2365
+ "."
2366
+ ] })
2367
+ ] });
2368
+ }
2369
+
1579
2370
  const PreviewCard = styled.div`
1580
2371
  display: flex;
1581
2372
  gap: 2rem;
@@ -1647,7 +2438,12 @@ function Preview({ branding, className }) {
1647
2438
  return /* @__PURE__ */ jsxRuntime.jsx(ThemeProvider, { branding, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className, children: /* @__PURE__ */ jsxRuntime.jsx(PreviewContent, {}) }) });
1648
2439
  }
1649
2440
 
2441
+ exports.AchVerificationConsent = AchVerificationConsent;
2442
+ exports.AsteriskMark = AsteriskMark;
2443
+ exports.AsteriskNote = AsteriskNote;
1650
2444
  exports.AutocompleteInput = AutocompleteInput;
2445
+ exports.Badge = Badge;
2446
+ exports.Banner = Banner;
1651
2447
  exports.BaseInput = BaseInput;
1652
2448
  exports.Body100 = Body100;
1653
2449
  exports.Body200 = Body200;
@@ -1655,8 +2451,9 @@ exports.Body400 = Body400;
1655
2451
  exports.Button = Button;
1656
2452
  exports.ButtonContainer = ButtonContainer;
1657
2453
  exports.CheckboxInput = CheckboxInput;
2454
+ exports.CollapsibleSource = CollapsibleSource;
1658
2455
  exports.Container = Container;
1659
- exports.Content = Content;
2456
+ exports.Content = Content$1;
1660
2457
  exports.CurrencyInput = CurrencyInput;
1661
2458
  exports.DateInput = DateInput;
1662
2459
  exports.DetailElement = DetailElement;
@@ -1668,9 +2465,12 @@ exports.DropdownContainer = DropdownContainer;
1668
2465
  exports.DropdownItem = DropdownItem;
1669
2466
  exports.DropdownList = DropdownList;
1670
2467
  exports.EmailInput = EmailInput;
2468
+ exports.FieldsGrid = FieldsGrid;
1671
2469
  exports.FileInput = FileInput;
1672
2470
  exports.FlexColumnWrapper = FlexColumnWrapper;
1673
2471
  exports.FlexRowWrapper = FlexRowWrapper;
2472
+ exports.FooterActions = FooterActions;
2473
+ exports.FooterRight = FooterRight;
1674
2474
  exports.Footnote = Footnote;
1675
2475
  exports.Form = Form;
1676
2476
  exports.FormActions = FormActions;
@@ -1682,12 +2482,20 @@ exports.FormTitle = FormTitle;
1682
2482
  exports.H1 = H1;
1683
2483
  exports.H2 = H2;
1684
2484
  exports.H3 = H3;
2485
+ exports.HelperText = HelperText;
1685
2486
  exports.InputError = InputError;
1686
2487
  exports.InputLabel = InputLabel;
1687
2488
  exports.InputWrapper = InputWrapper;
1688
2489
  exports.Loader = Loader;
2490
+ exports.ManualMethodCard = ManualMethodCard;
2491
+ exports.MethodBody = MethodBody;
2492
+ exports.MethodCard = MethodCard;
2493
+ exports.MethodHeader = MethodHeader;
2494
+ exports.MethodTitle = MethodTitle;
1689
2495
  exports.NoResults = NoResults;
1690
2496
  exports.PhoneInput = PhoneInput;
2497
+ exports.PlaidMethodCard = PlaidMethodCard;
2498
+ exports.PlaidTile = PlaidTile;
1691
2499
  exports.Preview = Preview;
1692
2500
  exports.RadioInput = RadioInput;
1693
2501
  exports.SSNInput = SSNInput;
@@ -1697,9 +2505,12 @@ exports.StatusTag = StatusTag;
1697
2505
  exports.Stepper = Stepper;
1698
2506
  exports.Tabs = Tabs;
1699
2507
  exports.TaxIdInput = TaxIdInput;
2508
+ exports.TermsDocument = TermsDocument;
1700
2509
  exports.TermsList = TermsList;
1701
2510
  exports.TextInput = TextInput;
1702
2511
  exports.ThemeProvider = ThemeProvider;
2512
+ exports.UnderwritingStatus = UnderwritingStatus;
2513
+ exports.UploadZone = UploadZone;
1703
2514
  exports.buildMuiTheme = buildMuiTheme;
1704
2515
  exports.defaultTheme = defaultTheme;
1705
2516
  exports.mergeBranding = mergeBranding;