@thecb/components 2.2.0 → 3.0.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.
Files changed (75) hide show
  1. package/.github/workflows/bump-version.yml +30 -0
  2. package/.github/workflows/create-release/build-body.sh +35 -0
  3. package/.github/workflows/create-release.yml +52 -0
  4. package/.github/workflows/publish-update.yml +73 -0
  5. package/README.md +68 -90
  6. package/dist/index.cjs.js +49122 -0
  7. package/package.json +17 -37
  8. package/rollup.config.js +43 -23
  9. package/src/components/atoms/button-with-action/ButtonWithAction.js +25 -4
  10. package/src/components/atoms/button-with-action/ButtonWithAction.theme.js +64 -234
  11. package/src/components/atoms/formatted-credit-card/FormattedCreditCard.js +53 -0
  12. package/src/components/atoms/formatted-credit-card/FormattedCreditCard.theme.js +9 -0
  13. package/src/components/atoms/formatted-credit-card/index.js +3 -0
  14. package/src/components/atoms/icons/AccountNumberImage.js +95 -0
  15. package/src/components/atoms/icons/BankIcon.js +82 -0
  16. package/src/components/atoms/icons/CheckmarkIcon.js +55 -0
  17. package/src/components/atoms/icons/GenericCard.js +39 -0
  18. package/src/components/atoms/icons/PaymentIcon.js +50 -0
  19. package/src/components/atoms/icons/RoutingNumberImage.js +95 -0
  20. package/src/components/atoms/icons/index.js +14 -1
  21. package/src/components/atoms/index.js +3 -0
  22. package/src/components/atoms/jumbo/Jumbo.js +76 -0
  23. package/src/components/atoms/jumbo/index.js +3 -0
  24. package/src/components/atoms/loading/Loading.js +17 -0
  25. package/src/components/atoms/loading/index.js +3 -0
  26. package/src/components/atoms/nav-header/NavHeader.js +1 -1
  27. package/src/components/index.js +1 -0
  28. package/src/components/molecules/account-and-routing-modal/AccountAndRoutingModal.js +75 -0
  29. package/src/components/molecules/account-and-routing-modal/AccountAndRoutingModal.theme.js +24 -0
  30. package/src/components/molecules/account-and-routing-modal/index.js +3 -0
  31. package/src/components/molecules/address-form/AddressForm.js +2 -1
  32. package/src/components/molecules/address-form/index.js +6 -6
  33. package/src/components/molecules/change-password-form/ChangePasswordForm.js +2 -1
  34. package/src/components/molecules/change-password-form/index.js +1 -1
  35. package/src/components/molecules/edit-name-form/EditNameForm.js +2 -1
  36. package/src/components/molecules/edit-name-form/index.js +1 -1
  37. package/src/components/molecules/editable-list/EditableList.js +139 -0
  38. package/src/components/molecules/editable-list/EditableList.styled.js +31 -0
  39. package/src/components/molecules/editable-list/index.js +3 -0
  40. package/src/components/molecules/editable-table/EditableTable.js +30 -0
  41. package/src/components/molecules/editable-table/EditableTable.styled.js +80 -0
  42. package/src/components/molecules/editable-table/TableListItem.js +64 -0
  43. package/src/components/molecules/editable-table/index.js +4 -0
  44. package/src/components/molecules/email-form/EmailForm.js +2 -1
  45. package/src/components/molecules/email-form/index.js +1 -1
  46. package/src/components/molecules/forgot-password-form/ForgotPasswordForm.js +2 -1
  47. package/src/components/molecules/forgot-password-form/index.js +1 -1
  48. package/src/components/molecules/index.js +5 -0
  49. package/src/components/molecules/login-form/LoginForm.js +2 -1
  50. package/src/components/molecules/login-form/index.js +1 -1
  51. package/src/components/molecules/module/Module.js +1 -3
  52. package/src/components/molecules/partial-amount-form/PartialAmountForm.js +73 -0
  53. package/src/components/molecules/partial-amount-form/PartialAmountForm.state.js +51 -0
  54. package/src/components/molecules/partial-amount-form/index.js +4 -0
  55. package/src/components/molecules/payment-form-ach/PaymentFormACH.js +189 -0
  56. package/src/components/molecules/payment-form-ach/PaymentFormACH.state.js +38 -0
  57. package/src/components/molecules/payment-form-ach/index.js +11 -0
  58. package/src/components/molecules/payment-form-card/PaymentFormCard.js +132 -0
  59. package/src/components/molecules/payment-form-card/PaymentFormCard.state.js +39 -0
  60. package/src/components/molecules/payment-form-card/index.js +11 -0
  61. package/src/components/molecules/phone-form/PhoneForm.js +2 -1
  62. package/src/components/molecules/phone-form/index.js +1 -1
  63. package/src/components/molecules/registration-form/RegistrationForm.js +2 -1
  64. package/src/components/molecules/registration-form/index.js +1 -1
  65. package/src/components/molecules/reset-password-form/ResetPasswordForm.js +3 -1
  66. package/src/components/molecules/reset-password-form/index.js +1 -1
  67. package/src/constants/index.js +4 -0
  68. package/src/index.js +3 -1
  69. package/src/util/formats.js +54 -2
  70. package/src/util/general.js +27 -4
  71. package/src/util/index.js +4 -0
  72. package/src/util/inputValidationUtils.js +0 -167
  73. package/.tool-versions +0 -1
  74. package/dist/cb-components.cjs.js +0 -77
  75. package/src/util/router-utils.js +0 -23
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+ import Spinner from "../spinner";
3
+ import { Box, Cover, Center } from "../layouts";
4
+
5
+ const Loading = () => (
6
+ <Box key="spinner-container">
7
+ <Cover minHeight="100%" singleChild>
8
+ <Center intrinsic>
9
+ <Box>
10
+ <Spinner size="100" />
11
+ </Box>
12
+ </Center>
13
+ </Cover>
14
+ </Box>
15
+ );
16
+
17
+ export default Loading;
@@ -0,0 +1,3 @@
1
+ import Loading from "./Loading";
2
+
3
+ export default Loading;
@@ -10,7 +10,7 @@ const NavHeader = ({
10
10
  ...rest
11
11
  }) => (
12
12
  <Box
13
- padding="0 1rem 0.25rem 1rem"
13
+ padding="0 16px 4px"
14
14
  background={backgroundColor}
15
15
  extraStyles={
16
16
  isMobile
@@ -1,3 +1,4 @@
1
1
  export * from "./atoms";
2
2
  export * from "./molecules";
3
3
  export * from "./templates";
4
+ export { default as withWindowSize } from "./withWindowSize";
@@ -0,0 +1,75 @@
1
+ import React, { Fragment } from "react";
2
+ import Modal from "../modal";
3
+ import Text from "../../atoms/text";
4
+ import Paragraph from "../../atoms/paragraph";
5
+ import { Box, Stack, Center } from "../../atoms/layouts";
6
+ import { fallbackValues } from "./AccountAndRoutingModal.theme";
7
+ import { themeComponent } from "../../../util/themeUtils";
8
+ import { AccountNumberImage, RoutingNumberImage } from "../../atoms/icons";
9
+
10
+ const AccountAndRoutingModal = ({
11
+ link,
12
+ title,
13
+ isOpen,
14
+ toggleOpen,
15
+ toggleAccepted,
16
+ acceptText,
17
+ content,
18
+ imageType,
19
+ variant,
20
+ themeValues
21
+ }) => (
22
+ <Modal
23
+ ModalLink={() => (
24
+ <Text
25
+ variant={variant === "default" ? "pS" : "pXS"}
26
+ onClick={() => toggleOpen(true)}
27
+ color={themeValues.linkColor}
28
+ weight={themeValues.fontWeight}
29
+ hoverStyles={themeValues.modalLinkHoverFocus}
30
+ focusStyles={themeValues.modalLinkHoverFocus}
31
+ extraStyles={`cursor: pointer;`}
32
+ tabIndex="0"
33
+ onKeyPress={e => e.key === "Enter" && toggleOpen(true)}
34
+ >
35
+ {link}
36
+ </Text>
37
+ )}
38
+ modalOpen={isOpen}
39
+ hideModal={() => toggleOpen(false)}
40
+ showModal={() => toggleOpen(true)}
41
+ modalHeaderText={title}
42
+ modalBodyText={
43
+ <Box extraStyles="overflow: scroll; max-height: 20rem;">
44
+ <Stack>
45
+ <Paragraph variant="p">{content}</Paragraph>
46
+ {imageType === "Account" ? (
47
+ <Center intrinsic>
48
+ <AccountNumberImage />
49
+ </Center>
50
+ ) : imageType === "Routing" ? (
51
+ <Center intrinsic>
52
+ <RoutingNumberImage />
53
+ </Center>
54
+ ) : (
55
+ <Fragment />
56
+ )}
57
+ </Stack>
58
+ </Box>
59
+ }
60
+ defaultWrapper={false}
61
+ onlyCloseButton={!acceptText}
62
+ continueButtonText={acceptText}
63
+ continueAction={() => {
64
+ toggleAccepted(true);
65
+ toggleOpen(false);
66
+ }}
67
+ />
68
+ );
69
+
70
+ export default themeComponent(
71
+ AccountAndRoutingModal,
72
+ "AccountAndRoutingModal",
73
+ fallbackValues,
74
+ "default"
75
+ );
@@ -0,0 +1,24 @@
1
+ import {
2
+ FONT_WEIGHT_REGULAR,
3
+ FONT_WEIGHT_SEMIBOLD
4
+ } from "../../../constants/style_constants";
5
+
6
+ const linkColor = { default: "#357fb8", footer: "#ffffff" };
7
+ const fontSize = { default: "1rem", footer: "0.875rem" };
8
+ const lineHeight = { default: "1.5rem", footer: "1.25rem" };
9
+ const fontWeight = {
10
+ default: FONT_WEIGHT_REGULAR,
11
+ footer: FONT_WEIGHT_SEMIBOLD
12
+ };
13
+ const modalLinkHoverFocus = {
14
+ default: ``,
15
+ footer: `outline: none; text-decoration: underline;`
16
+ };
17
+
18
+ export const fallbackValues = {
19
+ linkColor,
20
+ fontSize,
21
+ lineHeight,
22
+ fontWeight,
23
+ modalLinkHoverFocus
24
+ };
@@ -0,0 +1,3 @@
1
+ import AccountAndRoutingModal from "./AccountAndRoutingModal";
2
+
3
+ export default AccountAndRoutingModal;
@@ -3,6 +3,7 @@ import { required, hasLength } from "redux-freeform";
3
3
  import StateProvinceDropdown from "../../atoms/state-province-dropdown";
4
4
  // import CountryDropdown from "../../atoms/country-dropdown";
5
5
  import { zipFormat } from "../../../util/formats";
6
+ import { noop } from "../../../util/general";
6
7
  import {
7
8
  FormInput,
8
9
  FormContainer,
@@ -15,7 +16,7 @@ const AddressForm = ({
15
16
  actions,
16
17
  clearOnDismount,
17
18
  showErrors,
18
- handleSubmit
19
+ handleSubmit = noop
19
20
  }) => {
20
21
  if (clearOnDismount) {
21
22
  useEffect(() => () => actions.form.clear(), []);
@@ -1,11 +1,11 @@
1
- import AddressFrom from "./AddressForm";
1
+ import AddressForm from "./AddressForm";
2
2
  import {
3
3
  reducer,
4
4
  mapStateToProps,
5
- mapDispatchToProps,
5
+ mapDispatchToProps
6
6
  } from "./AddressForm.state";
7
7
 
8
- AddressFrom.reducer = reducer;
9
- AddressFrom.mapStateToProps = mapStateToProps;
10
- AddressFrom.mapDispatchToProps = mapDispatchToProps;
11
- export default AddressFrom;
8
+ AddressForm.reducer = reducer;
9
+ AddressForm.mapStateToProps = mapStateToProps;
10
+ AddressForm.mapDispatchToProps = mapDispatchToProps;
11
+ export default AddressForm;
@@ -15,12 +15,13 @@ import {
15
15
  } from "../../atoms/form-layouts";
16
16
  import { Box, Cluster } from "../../atoms/layouts";
17
17
  import PasswordRequirements from "../../atoms/password-requirements";
18
+ import { noop } from "../../../util/general";
18
19
 
19
20
  const ChangePasswordForm = ({
20
21
  clearOnDismount,
21
22
  fields,
22
23
  actions,
23
- handleSubmit,
24
+ handleSubmit = noop,
24
25
  showErrors,
25
26
  isMobile
26
27
  }) => {
@@ -2,7 +2,7 @@ import ChangePasswordForm from "./ChangePasswordForm";
2
2
  import {
3
3
  reducer,
4
4
  mapStateToProps,
5
- mapDispatchToProps,
5
+ mapDispatchToProps
6
6
  } from "./ChangePasswordForm.state";
7
7
 
8
8
  ChangePasswordForm.reducer = reducer;
@@ -5,13 +5,14 @@ import {
5
5
  FormContainer,
6
6
  FormInputColumn
7
7
  } from "../../atoms/form-layouts";
8
+ import { noop } from "../../../util/general";
8
9
 
9
10
  const EditNameForm = ({
10
11
  fields,
11
12
  actions,
12
13
  clearOnDismount,
13
14
  showErrors,
14
- handleSubmit
15
+ handleSubmit = noop
15
16
  }) => {
16
17
  if (clearOnDismount) {
17
18
  useEffect(() => () => actions.form.clear(), []);
@@ -2,7 +2,7 @@ import EditNameForm from "./EditNameForm";
2
2
  import {
3
3
  reducer,
4
4
  mapStateToProps,
5
- mapDispatchToProps,
5
+ mapDispatchToProps
6
6
  } from "./EditNameForm.state";
7
7
 
8
8
  EditNameForm.reducer = reducer;
@@ -0,0 +1,139 @@
1
+ import React, { useState } from "react";
2
+
3
+ import {
4
+ EditableListItem,
5
+ EditableListItemControls
6
+ } from "./EditableList.styled";
7
+ import { Box, Stack } from "../../atoms/layouts";
8
+ import Placeholder from "../../atoms/placeholder";
9
+ import ButtonWithAction from "../../atoms/button-with-action";
10
+ import Text from "../../atoms/text";
11
+ import Paragraph from "../../atoms/paragraph";
12
+ import {
13
+ STORM_GREY,
14
+ BOSTON_BLUE,
15
+ CHARADE_GREY
16
+ } from "../../../constants/colors";
17
+
18
+ const EditableList = ({
19
+ title = "",
20
+ titleWeight = "400",
21
+ addItem,
22
+ removeItem,
23
+ editItem,
24
+ itemName,
25
+ renderItem,
26
+ items,
27
+ canEdit = true,
28
+ canRemove = true,
29
+ listItemSize = "small",
30
+ maxItems,
31
+ useModal = false,
32
+ modal: Modal,
33
+ modalProps,
34
+ autoPayMethod,
35
+ qaPrefix
36
+ }) => (
37
+ <Box padding="0rem 0rem 1.5rem 0rem">
38
+ <Stack childGap="0rem">
39
+ {title !== "" && (
40
+ <Box padding="0rem 0rem 0.5rem 0rem">
41
+ <Paragraph
42
+ variant="pL"
43
+ weight={titleWeight}
44
+ color={CHARADE_GREY}
45
+ extraStyles="letter-spacing: 0.29px;"
46
+ aria-level="3"
47
+ >
48
+ {title}
49
+ </Paragraph>
50
+ </Box>
51
+ )}
52
+ <Box
53
+ padding="0"
54
+ borderRadius="4px"
55
+ extraStyles={`box-shadow: 0px 2px 14px 0px rgb(246, 246, 249),
56
+ 0px 3px 8px 0px rgb(202, 206, 216);`}
57
+ >
58
+ {items.map(props => {
59
+ const [modalOpen, toggleModal] = useState(false);
60
+ return (
61
+ <EditableListItem
62
+ listItemSize={
63
+ !!props.id && props.id === autoPayMethod ? "big" : listItemSize
64
+ }
65
+ key={props.id}
66
+ >
67
+ <Text variant="p" color={CHARADE_GREY}>
68
+ {renderItem(props)}
69
+ </Text>
70
+ <EditableListItemControls>
71
+ {props.isPrimary && (
72
+ <Text
73
+ variant="p"
74
+ color={STORM_GREY}
75
+ extraStyles={`font-style: italic;`}
76
+ >
77
+ Default {itemName}
78
+ </Text>
79
+ )}
80
+ {canRemove && (
81
+ <Box
82
+ padding="0 0.5rem"
83
+ border="2px solid transparent"
84
+ extraStyles={`:not(:first-child) { border-left: 2px solid ${BOSTON_BLUE};}`}
85
+ dataQa={qaPrefix + " Remove"}
86
+ >
87
+ {useModal ? (
88
+ <Modal
89
+ item={{ ...props }}
90
+ {...modalProps}
91
+ modalOpen={modalOpen}
92
+ toggleModal={toggleModal}
93
+ />
94
+ ) : (
95
+ <ButtonWithAction
96
+ variant="smallGhost"
97
+ text="Remove"
98
+ action={() => removeItem(props.id)}
99
+ extraStyles={`min-width: 0;`}
100
+ />
101
+ )}
102
+ </Box>
103
+ )}
104
+ {canEdit && (
105
+ <Box
106
+ padding="0 0.5rem"
107
+ border="2px solid transparent"
108
+ extraStyles={`:not(:first-child) { border-left: 2px solid ${BOSTON_BLUE};}`}
109
+ dataQa={qaPrefix + " Edit"}
110
+ >
111
+ <ButtonWithAction
112
+ variant="smallGhost"
113
+ text="Edit"
114
+ action={() => editItem(props.id)}
115
+ extraStyles={`min-width: 0;`}
116
+ />
117
+ </Box>
118
+ )}
119
+ </EditableListItemControls>
120
+ </EditableListItem>
121
+ );
122
+ })}
123
+ </Box>
124
+ {(!maxItems || items.length < maxItems) && (
125
+ <Box padding={items.length === 0 ? "0" : "1rem 0 0"}>
126
+ <Placeholder
127
+ text={`Add a${
128
+ itemName[0].match(/[aieouAIEOU]/) ? "n" : ""
129
+ } ${itemName}`}
130
+ action={addItem}
131
+ dataQa={"Add " + qaPrefix}
132
+ />
133
+ </Box>
134
+ )}
135
+ </Stack>
136
+ </Box>
137
+ );
138
+
139
+ export default EditableList;
@@ -0,0 +1,31 @@
1
+ import styled from "styled-components";
2
+ import { WHITE } from "../../../constants/colors";
3
+
4
+ export const EditableListItem = styled.div`
5
+ box-sizing: border-box;
6
+ background: ${WHITE};
7
+ height: ${({ listItemSize }) => (listItemSize === "big" ? "120px" : "72px")};
8
+ display: flex;
9
+ justify-content: space-between;
10
+ align-items: center;
11
+ padding: 1.5rem;
12
+ :not(:last-child),
13
+ :not(:first-child) {
14
+ box-shadow: inset 0px -1px 0px 0px rgb(202, 206, 216);
15
+ }
16
+ :first-child {
17
+ border-top-left-radius: 3px;
18
+ border-top-right-radius: 3px;
19
+ }
20
+ :last-child {
21
+ border-bottom-left-radius: 3px;
22
+ border-bottom-right-radius: 3px;
23
+ box-shadow: none;
24
+ }
25
+ `;
26
+
27
+ export const EditableListItemControls = styled.div`
28
+ display: flex;
29
+ justify-content: space-evenly;
30
+ align-items: center;
31
+ `;
@@ -0,0 +1,3 @@
1
+ import EditableList from "./EditableList";
2
+
3
+ export default EditableList;
@@ -0,0 +1,30 @@
1
+ import React, { Fragment } from "react";
2
+ import { EditableTableContainer, TableWrapper } from "./EditableTable.styled";
3
+ import { Box } from "../../atoms/layouts";
4
+ import Paragraph from "../../atoms/paragraph";
5
+ import { GHOST_GREY } from "../../../constants/colors";
6
+ import { FONT_WEIGHT_SEMIBOLD } from "../../../constants/style_constants";
7
+ import { safeChildren } from "../../../util/general";
8
+
9
+ const EditableTable = ({ title, renderItem, items, isMobile }) => {
10
+ const titleChild = title && (
11
+ <Box
12
+ padding={"0 0 0.5rem 0.5rem"}
13
+ borderSize="1px"
14
+ borderColor={GHOST_GREY}
15
+ borderWidthOverride="0 0 1px 0"
16
+ >
17
+ <Paragraph variant="pL" weight={FONT_WEIGHT_SEMIBOLD}>
18
+ {title}
19
+ </Paragraph>
20
+ </Box>
21
+ );
22
+ return (
23
+ <EditableTableContainer isMobile={isMobile}>
24
+ {safeChildren(titleChild, <Fragment />)}
25
+ <TableWrapper>{renderItem(items)}</TableWrapper>
26
+ </EditableTableContainer>
27
+ );
28
+ };
29
+
30
+ export default EditableTable;
@@ -0,0 +1,80 @@
1
+ import styled from "styled-components";
2
+ import {
3
+ BRIGHT_GREY,
4
+ STORM_GREY,
5
+ GHOST_GREY,
6
+ MATISSE_BLUE
7
+ } from "../../../constants/colors";
8
+
9
+ export const EditableTableContainer = styled.div`
10
+ display: ${({ hide }) => (hide ? "none" : "flex")};
11
+ flex-direction: column;
12
+ flex: 1;
13
+ `;
14
+
15
+ export const EditableTableListItem = styled.div`
16
+ width: 100%;
17
+ display: flex;
18
+ ${({ isMobile }) => isMobile && "justify-content: center"};
19
+ align-items: ${({ isMobile }) => (isMobile ? "flex-start" : "center")};
20
+ flex-direction: ${({ isMobile }) => (isMobile ? "column" : "row")};
21
+ flex: 1;
22
+ ${({ isMobile }) =>
23
+ isMobile ? "padding: 1rem 0.5rem" : "padding: 0 0.5rem"};
24
+ `;
25
+
26
+ export const EditableListItemControls = styled.div`
27
+ display: flex;
28
+ justify-content: space-evenly;
29
+ align-items: center;
30
+ `;
31
+
32
+ export const EditableListAction = styled.div`
33
+ color: ${MATISSE_BLUE};
34
+ align-items: center;
35
+ font-size: 1rem;
36
+ padding-right: 1rem;
37
+ cursor: pointer;
38
+ display: ${({ hide }) => (hide ? "none" : "flex")};
39
+ `;
40
+
41
+ export const ItemWrapper = styled.div`
42
+ display: flex;
43
+ flex-direction: row;
44
+ flex: 1;
45
+ width: 100%;
46
+ border-bottom: 1px solid ${GHOST_GREY};
47
+ `;
48
+
49
+ export const ActionWrapper = styled.div`
50
+ display: flex;
51
+ align-self: center;
52
+ justify-content: flex-end;
53
+ ${({ isMobile }) => isMobile && `display: none`};
54
+ flex: 1;
55
+ `;
56
+
57
+ export const TableItemKey = styled.div`
58
+ display: flex;
59
+ ${({ isMobile }) => !isMobile && "flex: 1"};
60
+ ${({ isMobile }) => isMobile && "align-items: center"};
61
+ ${({ isMobile }) => !isMobile && "padding: 1.25rem 0"};
62
+ font-size: ${({ isMobile }) => (isMobile ? "1rem" : "1.125rem")};
63
+ color: ${STORM_GREY};
64
+ `;
65
+
66
+ export const TableItemValue = styled.div`
67
+ display: flex;
68
+ ${({ isMobile }) => !isMobile && "flex: 1"};
69
+ ${({ isMobile }) => !isMobile && "padding: 1.25rem 0"};
70
+ ${({ isMobile }) => isMobile && "align-items: center"};
71
+ font-size: ${({ isMobile }) => (isMobile ? "1.125rem" : "1.0625rem")};
72
+ color: ${BRIGHT_GREY};
73
+ `;
74
+
75
+ export const TableWrapper = styled.div`
76
+ display: flex;
77
+ flex-direction: row;
78
+ flex: 1;
79
+ width: 100%;
80
+ `;
@@ -0,0 +1,64 @@
1
+ import React, { Fragment } from "react";
2
+ import {
3
+ EditableTableListItem,
4
+ EditableListAction,
5
+ ItemWrapper,
6
+ ActionWrapper,
7
+ TableItemKey,
8
+ TableItemValue
9
+ } from "./EditableTable.styled";
10
+ import { Box } from "../../atoms/layouts";
11
+ import Text from "../../atoms/text";
12
+ import { CHARADE_GREY } from "../../../constants/colors";
13
+
14
+ const TableListItem = ({
15
+ title,
16
+ value,
17
+ canEdit = false,
18
+ canRemove = false,
19
+ isMobile
20
+ }) => (
21
+ <Box
22
+ padding="0px"
23
+ extraStyles={`&:last-child {
24
+ > * {
25
+ border-bottom: none;
26
+ }
27
+ }`}
28
+ >
29
+ <ItemWrapper>
30
+ <EditableTableListItem isMobile={isMobile}>
31
+ <TableItemKey isMobile={isMobile}>
32
+ <Text variant="pS" color={CHARADE_GREY} aria-level="3">
33
+ {title}
34
+ </Text>
35
+ </TableItemKey>
36
+ <TableItemValue isMobile={isMobile}>
37
+ <Text variant="p" color={CHARADE_GREY}>
38
+ {value}
39
+ </Text>
40
+ </TableItemValue>
41
+ {canRemove || canEdit ? (
42
+ <ActionWrapper isMobile={isMobile}>
43
+ <EditableListAction
44
+ hide={!canRemove}
45
+ onClick={() => console.log("Remove Item Coming Soon...")}
46
+ >
47
+ Remove
48
+ </EditableListAction>
49
+ <EditableListAction
50
+ hide={!canEdit}
51
+ onClick={() => console.log("Edit Item Coming Soon...")}
52
+ >
53
+ Edit
54
+ </EditableListAction>
55
+ </ActionWrapper>
56
+ ) : (
57
+ <Fragment />
58
+ )}
59
+ </EditableTableListItem>
60
+ </ItemWrapper>
61
+ </Box>
62
+ );
63
+
64
+ export default TableListItem;
@@ -0,0 +1,4 @@
1
+ import EditableTable from "./EditableTable";
2
+ import TableListItem from "./TableListItem";
3
+
4
+ export { EditableTable, TableListItem };
@@ -5,6 +5,7 @@ import {
5
5
  FormContainer,
6
6
  FormInputColumn
7
7
  } from "../../atoms/form-layouts";
8
+ import { noop } from "../../../util/general";
8
9
 
9
10
  const EmailForm = ({
10
11
  variant = "default",
@@ -12,7 +13,7 @@ const EmailForm = ({
12
13
  fields,
13
14
  actions,
14
15
  showErrors,
15
- handleSubmit
16
+ handleSubmit = noop
16
17
  }) => {
17
18
  if (clearOnDismount) {
18
19
  useEffect(() => () => actions.form.clear(), []);
@@ -2,7 +2,7 @@ import EmailForm from "./EmailForm";
2
2
  import {
3
3
  reducer,
4
4
  mapStateToProps,
5
- mapDispatchToProps,
5
+ mapDispatchToProps
6
6
  } from "./EmailForm.state";
7
7
 
8
8
  EmailForm.reducer = reducer;
@@ -1,13 +1,14 @@
1
1
  import React, { useEffect } from "react";
2
2
  import { required, isProbablyEmail } from "redux-freeform";
3
3
  import { FormInput } from "../../atoms/form-layouts";
4
+ import { noop } from "../../../util/general";
4
5
 
5
6
  const ForgotPasswordForm = ({
6
7
  fields,
7
8
  actions,
8
9
  clearOnDismount,
9
10
  showErrors,
10
- handleSubmit
11
+ handleSubmit = noop
11
12
  }) => {
12
13
  if (clearOnDismount) {
13
14
  useEffect(() => () => actions.form.clear(), []);
@@ -2,7 +2,7 @@ import ForgotPasswordForm from "./ForgotPasswordForm";
2
2
  import {
3
3
  reducer,
4
4
  mapStateToProps,
5
- mapDispatchToProps,
5
+ mapDispatchToProps
6
6
  } from "./ForgotPasswordForm.state";
7
7
 
8
8
  ForgotPasswordForm.reducer = reducer;
@@ -2,6 +2,8 @@ export { default as AddressForm } from "./address-form";
2
2
  export { default as ChangePasswordForm } from "./change-password-form";
3
3
  export { default as CollapsibleSection } from "./collapsible-section";
4
4
  export { default as EditNameForm } from "./edit-name-form";
5
+ export { default as EditableList } from "./editable-list";
6
+ export * from "./editable-table";
5
7
  export { default as EmailForm } from "./email-form";
6
8
  export { default as ForgotPasswordForm } from "./forgot-password-form";
7
9
  export { default as HighlightTabRow } from "./highlight-tab-row";
@@ -10,8 +12,11 @@ export { default as Modal } from "./modal";
10
12
  export { default as Module } from "./module";
11
13
  export * from "./nav-menu";
12
14
  export { default as Obligation } from "./obligation";
15
+ export * from "./partial-amount-form";
13
16
  export { default as PaymentButtonBar } from "./payment-button-bar";
14
17
  export { default as PaymentDetails } from "./payment-details";
18
+ export { default as PaymentFormACH } from "./payment-form-ach";
19
+ export { default as PaymentFormCard } from "./payment-form-card";
15
20
  export { default as PhoneForm } from "./phone-form";
16
21
  export { default as RadioSection } from "./radio-section";
17
22
  export { default as RegistrationForm } from "./registration-form";