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