@thecb/components 4.1.15 → 4.1.17

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 (22) hide show
  1. package/dist/index.cjs.js +206 -390
  2. package/package.json +1 -1
  3. package/src/components/atoms/checkbox/Checkbox.js +63 -49
  4. package/src/components/atoms/dropdown/Dropdown.js +2 -2
  5. package/src/components/atoms/icons/GenericCardLarge.js +39 -0
  6. package/src/components/atoms/icons/index.js +3 -1
  7. package/src/components/atoms/text/Text.js +2 -0
  8. package/src/components/molecules/account-and-routing-modal/AccountAndRoutingModal.js +14 -16
  9. package/src/components/molecules/account-and-routing-modal/AccountAndRoutingModal.theme.js +6 -11
  10. package/src/components/molecules/address-form/AddressForm.js +7 -27
  11. package/src/components/molecules/email-form/EmailForm.js +7 -27
  12. package/src/components/molecules/email-form/EmailForm.stories.js +4 -1
  13. package/src/components/molecules/modal/Modal.js +3 -3
  14. package/src/components/molecules/obligation/modules/AmountModule.stories.js +27 -0
  15. package/src/components/molecules/obligation/modules/AutopayModalModule.js +47 -38
  16. package/src/components/molecules/obligation/modules/AutopayModalModule.theme.js +12 -1
  17. package/src/components/molecules/payment-form-ach/PaymentFormACH.js +22 -57
  18. package/src/components/molecules/payment-form-card/PaymentFormCard.js +7 -26
  19. package/src/components/molecules/phone-form/PhoneForm.js +7 -27
  20. package/src/components/molecules/terms-and-conditions/TermsAndConditions.js +12 -40
  21. package/src/components/molecules/terms-and-conditions-modal/TermsAndConditionsModal.js +14 -15
  22. package/src/components/molecules/terms-and-conditions-modal/TermsAndConditionsModal.theme.js +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thecb/components",
3
- "version": "4.1.15",
3
+ "version": "4.1.17",
4
4
  "description": "Common lib for CityBase react components",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.esm.js",
@@ -1,4 +1,4 @@
1
- import React from "react";
1
+ import React, { useState } from "react";
2
2
  import styled, { css } from "styled-components";
3
3
  import { fallbackValues } from "./Checkbox.theme";
4
4
  import { noop } from "../../../util/general";
@@ -87,58 +87,72 @@ const Checkbox = ({
87
87
  checked,
88
88
  onChange = noop,
89
89
  disabled = false,
90
- focused = false,
91
90
  themeValues,
92
91
  hidden = false,
93
92
  error = false
94
- }) => (
95
- <Box
96
- padding="0"
97
- hiddenStyles={hidden}
98
- background={themeValues.backgroundColor}
99
- >
100
- <CheckboxLabelContainer>
101
- <CheckboxContainer data-qa="Checkbox">
102
- <HiddenCheckbox
103
- id={`checkbox-${name}`}
104
- disabled={disabled}
105
- name={name}
106
- aria-label={name}
107
- checked={checked}
108
- onChange={onChange}
109
- tabIndex="-1"
110
- />
111
- <StyledCheckbox
112
- error={error}
113
- disabled={disabled}
114
- checked={checked}
115
- focused={focused}
116
- defaultStyles={themeValues.defaultStyles}
117
- checkedStyles={themeValues.checkedStyles}
118
- errorStyles={themeValues.errorStyles}
119
- disabledStyles={themeValues.disabledStyles}
120
- focusedStyles={themeValues.focusedStyles}
121
- >
122
- <CheckboxIcon
123
- viewBox="0 0 24 24"
93
+ }) => {
94
+ const [focused, setFocused] = useState(false);
95
+
96
+ const handleClick = (e, func) => {
97
+ if (e?.keyCode === 13) {
98
+ func();
99
+ }
100
+ };
101
+
102
+ return (
103
+ <Box
104
+ padding="0"
105
+ tabIndex="0"
106
+ onFocus={() => setFocused(true)}
107
+ onBlur={() => setFocused(false)}
108
+ onKeyDown={e => handleClick(e, onChange)}
109
+ hiddenStyles={hidden}
110
+ background={themeValues.backgroundColor}
111
+ extraStyles="outline: none;"
112
+ >
113
+ <CheckboxLabelContainer>
114
+ <CheckboxContainer data-qa="Checkbox">
115
+ <HiddenCheckbox
116
+ id={`checkbox-${name}`}
124
117
  disabled={disabled}
125
- disabledCheckColor={themeValues.disabledCheckColor}
126
- checkColor={themeValues.checkColor}
118
+ name={name}
119
+ aria-label={name}
120
+ checked={checked}
121
+ onChange={onChange}
122
+ tabIndex="-1"
123
+ />
124
+ <StyledCheckbox
125
+ error={error}
126
+ disabled={disabled}
127
+ checked={checked}
128
+ focused={focused}
129
+ defaultStyles={themeValues.defaultStyles}
130
+ checkedStyles={themeValues.checkedStyles}
131
+ errorStyles={themeValues.errorStyles}
132
+ disabledStyles={themeValues.disabledStyles}
133
+ focusedStyles={themeValues.focusedStyles}
127
134
  >
128
- <polyline points="20 6 9 17 4 12" />
129
- </CheckboxIcon>
130
- </StyledCheckbox>
131
- </CheckboxContainer>
132
- <Text
133
- variant="p"
134
- weight={themeValues.textFontWeight}
135
- color={themeValues.textColor}
136
- extraStyles={`margin-left: 1rem`}
137
- >
138
- {title}
139
- </Text>
140
- </CheckboxLabelContainer>
141
- </Box>
142
- );
135
+ <CheckboxIcon
136
+ viewBox="0 0 24 24"
137
+ disabled={disabled}
138
+ disabledCheckColor={themeValues.disabledCheckColor}
139
+ checkColor={themeValues.checkColor}
140
+ >
141
+ <polyline points="20 6 9 17 4 12" />
142
+ </CheckboxIcon>
143
+ </StyledCheckbox>
144
+ </CheckboxContainer>
145
+ <Text
146
+ variant="p"
147
+ weight={themeValues.textFontWeight}
148
+ color={themeValues.textColor}
149
+ extraStyles={`margin-left: 1rem`}
150
+ >
151
+ {title}
152
+ </Text>
153
+ </CheckboxLabelContainer>
154
+ </Box>
155
+ );
156
+ };
143
157
 
144
158
  export default themeComponent(Checkbox, "Checkbox", fallbackValues, "default");
@@ -201,7 +201,6 @@ const Dropdown = ({
201
201
  <Box
202
202
  onKeyDown={onKeyDown}
203
203
  onClick={onClick}
204
- tabIndex={0}
205
204
  padding="0"
206
205
  width="100%"
207
206
  hoverStyles={`background-color: ${themeValues.hoverColor};`}
@@ -222,7 +221,8 @@ const Dropdown = ({
222
221
  : GREY_CHATEAU
223
222
  }
224
223
  borderRadius="2px"
225
- extraStyles={`tabindex: 0; height: 48px;`}
224
+ tabIndex={0}
225
+ extraStyles={`height: 48px;`}
226
226
  dataQa={placeholder}
227
227
  >
228
228
  <Stack direction="row" bottomItem={2}>
@@ -0,0 +1,39 @@
1
+ import React from "react";
2
+
3
+ const GenericCardLarge = () => {
4
+ return (
5
+ <svg
6
+ xmlns="http://www.w3.org/2000/svg"
7
+ width="34"
8
+ height="28"
9
+ viewBox="0 0 34 28"
10
+ >
11
+ <g fill="none" fillRule="evenodd" stroke="none" strokeWidth="1">
12
+ <g fillRule="nonzero" transform="translate(-142 -927)">
13
+ <g transform="translate(94 518)">
14
+ <g transform="translate(24 350)">
15
+ <g transform="translate(0 35)">
16
+ <g transform="translate(24 24)">
17
+ <path
18
+ fill="#CACED8"
19
+ d="M29.259.699H3.282C1.497.699.035 2.217.035 4.074v20.25c0 1.856 1.462 3.375 3.247 3.375H29.26c1.786 0 3.247-1.52 3.247-3.375V4.074c0-1.857-1.461-3.375-3.247-3.375z"
20
+ ></path>
21
+ <path
22
+ fill="#000"
23
+ d="M0.035 6.699H32.50599999999999V13.699H0.035z"
24
+ ></path>
25
+ <path
26
+ fill="#000"
27
+ d="M27.51 22.699h-6.244c-.468 0-.937-.47-.937-.938v-3.125c0-.469.469-.937.937-.937h6.244c.469 0 .937.468.937.937v3.125c0 .625-.312.938-.937.938z"
28
+ ></path>
29
+ </g>
30
+ </g>
31
+ </g>
32
+ </g>
33
+ </g>
34
+ </g>
35
+ </svg>
36
+ );
37
+ };
38
+
39
+ export default GenericCardLarge;
@@ -41,6 +41,7 @@ import VoidedIcon from "./VoidedIcon";
41
41
  import StatusUnknownIcon from "./StatusUnknownIcon";
42
42
  import CarrotIcon from "./CarrotIcon";
43
43
  import ProfileIcon from "./ProfileIcon";
44
+ import GenericCardLarge from "./GenericCardLarge";
44
45
 
45
46
  export {
46
47
  AccountsIcon,
@@ -85,5 +86,6 @@ export {
85
86
  VoidedIcon,
86
87
  StatusUnknownIcon,
87
88
  CarrotIcon,
88
- ProfileIcon
89
+ ProfileIcon,
90
+ GenericCardLarge
89
91
  };
@@ -13,6 +13,7 @@ const Text = ({
13
13
  extraStyles = ``,
14
14
  hoverStyles,
15
15
  onClick,
16
+ onKeyPress,
16
17
  as,
17
18
  dataQa,
18
19
  children,
@@ -27,6 +28,7 @@ const Text = ({
27
28
  extraStyles={extraStyles}
28
29
  hoverStyles={hoverStyles}
29
30
  onClick={onClick}
31
+ onKeyPress={onKeyPress}
30
32
  data-qa={dataQa}
31
33
  {...rest}
32
34
  >
@@ -16,24 +16,9 @@ const AccountAndRoutingModal = ({
16
16
  acceptText,
17
17
  content,
18
18
  imageType,
19
- variant,
20
19
  themeValues
21
20
  }) => (
22
21
  <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
- extraStyles={`cursor: pointer;`}
31
- tabIndex="0"
32
- onKeyPress={e => e.key === "Enter" && toggleOpen(true)}
33
- >
34
- {link}
35
- </Text>
36
- )}
37
22
  modalOpen={isOpen}
38
23
  hideModal={() => toggleOpen(false)}
39
24
  showModal={() => toggleOpen(true)}
@@ -63,7 +48,20 @@ const AccountAndRoutingModal = ({
63
48
  toggleAccepted(true);
64
49
  toggleOpen(false);
65
50
  }}
66
- />
51
+ >
52
+ <Text
53
+ variant="pS"
54
+ onClick={() => toggleOpen(true)}
55
+ onKeyPress={e => e.key === "Enter" && toggleOpen(true)}
56
+ tabIndex="0"
57
+ color={themeValues.linkColor}
58
+ weight={themeValues.fontWeight}
59
+ hoverStyles={themeValues.modalLinkHoverFocus}
60
+ extraStyles={`cursor: pointer;`}
61
+ >
62
+ {link}
63
+ </Text>
64
+ </Modal>
67
65
  );
68
66
 
69
67
  export default themeComponent(
@@ -1,18 +1,13 @@
1
- import {
2
- FONT_WEIGHT_REGULAR,
3
- FONT_WEIGHT_SEMIBOLD
4
- } from "../../../constants/style_constants";
1
+ import { FONT_WEIGHT_REGULAR } from "../../../constants/style_constants";
5
2
 
6
- const linkColor = { default: "#357fb8", footer: "#ffffff" };
7
- const fontSize = { default: "1rem", footer: "0.875rem" };
8
- const lineHeight = { default: "1.5rem", footer: "1.25rem" };
3
+ const linkColor = { default: "#357fb8" };
4
+ const fontSize = { default: "1rem" };
5
+ const lineHeight = { default: "1.5rem" };
9
6
  const fontWeight = {
10
- default: FONT_WEIGHT_REGULAR,
11
- footer: FONT_WEIGHT_SEMIBOLD
7
+ default: FONT_WEIGHT_REGULAR
12
8
  };
13
9
  const modalLinkHoverFocus = {
14
- default: ``,
15
- footer: `outline: none; text-decoration: underline;`
10
+ default: `outline: none; text-decoration: underline;`
16
11
  };
17
12
 
18
13
  export const fallbackValues = {
@@ -1,6 +1,5 @@
1
- import React, { useEffect, useState } from "react";
1
+ import React, { useEffect } from "react";
2
2
  import { required, hasLength } from "redux-freeform";
3
- import styled from "styled-components";
4
3
  import StateProvinceDropdown from "../../atoms/state-province-dropdown";
5
4
  import Checkbox from "../../atoms/checkbox";
6
5
  import CountryDropdown from "../../atoms/country-dropdown";
@@ -12,10 +11,6 @@ import {
12
11
  FormInputColumn
13
12
  } from "../../atoms/form-layouts";
14
13
 
15
- const CheckboxWrapper = styled.div`
16
- outline: none;
17
- `;
18
-
19
14
  const AddressForm = ({
20
15
  variant = "default",
21
16
  fields,
@@ -27,13 +22,6 @@ const AddressForm = ({
27
22
  saveToWallet,
28
23
  walletCheckboxMarked
29
24
  }) => {
30
- const [checkboxFocused, focusCheckbox] = useState(false);
31
-
32
- const handleClick = (e, func) => {
33
- if (e?.keyCode === 13) {
34
- func();
35
- }
36
- };
37
25
  if (clearOnDismount) {
38
26
  useEffect(() => () => actions.form.clear(), []);
39
27
  }
@@ -120,20 +108,12 @@ const AddressForm = ({
120
108
  onKeyDown={e => e.key === "Enter" && handleSubmit(e)}
121
109
  />
122
110
  {showWalletCheckbox && (
123
- <CheckboxWrapper
124
- tabIndex="0"
125
- onFocus={() => focusCheckbox(true)}
126
- onBlur={() => focusCheckbox(false)}
127
- onKeyDown={e => handleClick(e, saveToWallet)}
128
- >
129
- <Checkbox
130
- name="address checkbox"
131
- title="Save address to wallet"
132
- checked={walletCheckboxMarked}
133
- onChange={saveToWallet}
134
- focused={checkboxFocused}
135
- />
136
- </CheckboxWrapper>
111
+ <Checkbox
112
+ name="address checkbox"
113
+ title="Save address to wallet"
114
+ checked={walletCheckboxMarked}
115
+ onChange={saveToWallet}
116
+ />
137
117
  )}
138
118
  </FormInputColumn>
139
119
  </FormContainer>
@@ -1,5 +1,4 @@
1
- import React, { useEffect, useState } from "react";
2
- import styled from "styled-components";
1
+ import React, { useEffect } from "react";
3
2
  import { required, isProbablyEmail } from "redux-freeform";
4
3
  import {
5
4
  FormInput,
@@ -10,10 +9,6 @@ import Checkbox from "../../atoms/checkbox";
10
9
  import Paragraph from "../../atoms/paragraph";
11
10
  import { noop } from "../../../util/general";
12
11
 
13
- const CheckboxWrapper = styled.div`
14
- outline: none;
15
- `;
16
-
17
12
  const EmailForm = ({
18
13
  variant = "default",
19
14
  clearOnDismount,
@@ -26,13 +21,6 @@ const EmailForm = ({
26
21
  saveToWallet,
27
22
  walletCheckboxMarked
28
23
  }) => {
29
- const [checkboxFocused, focusCheckbox] = useState(false);
30
- const handleClick = (e, func) => {
31
- if (e?.keyCode === 13) {
32
- func();
33
- }
34
- };
35
-
36
24
  if (clearOnDismount) {
37
25
  useEffect(() => () => actions.form.clear(), []);
38
26
  }
@@ -59,20 +47,12 @@ const EmailForm = ({
59
47
  onKeyDown={e => e.key === "Enter" && handleSubmit(e)}
60
48
  />
61
49
  {showWalletCheckbox && (
62
- <CheckboxWrapper
63
- tabIndex="0"
64
- onFocus={() => focusCheckbox(true)}
65
- onBlur={() => focusCheckbox(false)}
66
- onKeyDown={e => handleClick(e, saveToWallet)}
67
- >
68
- <Checkbox
69
- name="email checkbox"
70
- title="Save email address to wallet"
71
- checked={walletCheckboxMarked}
72
- onChange={saveToWallet}
73
- focused={checkboxFocused}
74
- />
75
- </CheckboxWrapper>
50
+ <Checkbox
51
+ name="email checkbox"
52
+ title="Save email address to wallet"
53
+ checked={walletCheckboxMarked}
54
+ onChange={saveToWallet}
55
+ />
76
56
  )}
77
57
  </FormInputColumn>
78
58
  </FormContainer>
@@ -20,5 +20,8 @@ const ConnectedForm = connect(
20
20
  EmailFormState.mapDispatchToProps
21
21
  )(EmailForm);
22
22
  export const emailForm = () => (
23
- <ConnectedForm showErrors={boolean("showErrors", false, "props")} />
23
+ <ConnectedForm
24
+ showErrors={boolean("showErrors", false, "props")}
25
+ showWalletCheckbox={boolean("showWalletCheckbox", false, "props")}
26
+ />
24
27
  );
@@ -21,7 +21,6 @@ a different route (as with a link) connect() and use "push" from connected-react
21
21
  const getApplicationNode = () => document.getElementById("root");
22
22
 
23
23
  const Modal = ({
24
- ModalLink,
25
24
  hideModal,
26
25
  continueAction,
27
26
  cancelAction,
@@ -36,12 +35,12 @@ const Modal = ({
36
35
  defaultWrapper = true,
37
36
  onlyCloseButton = false,
38
37
  maxHeight,
39
- underlayClickExits = true
38
+ underlayClickExits = true,
39
+ children
40
40
  }) => {
41
41
  const { isMobile } = useContext(ThemeContext);
42
42
  return (
43
43
  <Fragment>
44
- <ModalLink />
45
44
  {modalOpen && (
46
45
  <AriaModal
47
46
  onExit={hideModal}
@@ -134,6 +133,7 @@ const Modal = ({
134
133
  </Box>
135
134
  </AriaModal>
136
135
  )}
136
+ {children}
137
137
  </Fragment>
138
138
  );
139
139
  };
@@ -0,0 +1,27 @@
1
+ import React from "react";
2
+ import { text, boolean } from "@storybook/addon-knobs";
3
+
4
+ import AmountModule from "./AmountModule";
5
+ import page from "../../../../../.storybook/page";
6
+ import { noop } from "../../../../util/general";
7
+
8
+ const groupId = "props";
9
+
10
+ export const amountModule = () => (
11
+ <AmountModule
12
+ totalAmountDue={text("totalAmountDue", "123", groupId)}
13
+ autoPayEnabled={boolean("autopayEnabled", true, groupId)}
14
+ isMobile={boolean("isMobile", false, groupId)}
15
+ deactivatePaymentSchedule={noop}
16
+ navigateToSettings={noop}
17
+ autoPaySchedule={{}}
18
+ paymentPlanSchedule={{}}
19
+ isPaymentPlan={boolean("isPaymentPlan", false, groupId)}
20
+ />
21
+ );
22
+
23
+ const story = page({
24
+ title: "Components|Molecules/AmountModule",
25
+ Component: AmountModule
26
+ });
27
+ export default story;
@@ -1,6 +1,7 @@
1
1
  import React from "react";
2
2
  import Modal from "../../modal";
3
3
  import ButtonWithAction from "../../../atoms/button-with-action";
4
+ import Text from "../../../atoms/text";
4
5
  import { AutopayOnIcon } from "../../../atoms/icons";
5
6
  import { Box, Cluster } from "../../../atoms/layouts";
6
7
  import { fallbackValues } from "./AutopayModalModule.theme";
@@ -61,48 +62,56 @@ const AutopayModal = ({
61
62
  `;
62
63
  return (
63
64
  <Modal
64
- ModalLink={() =>
65
- buttonLinkType ? (
66
- <ButtonWithAction
67
- text={autoPayActive ? `Manage ${planType}` : `Set Up ${planType}`}
68
- variant="tertiary"
69
- action={() => {
70
- toggleModal(true);
71
- }}
72
- dataQa="Manage Autopay"
73
- extraStyles={isMobile && `flex-grow: 1; width: 100%;`}
74
- />
75
- ) : (
76
- <Box
77
- padding="0"
78
- onClick={() => {
79
- toggleModal(true);
80
- }}
81
- hoverStyles={hoverStyles}
82
- activeStyles={activeStyles}
83
- extraStyles={defaultStyles}
84
- >
85
- <Cluster
86
- justify={isMobile ? "flex-start" : "flex-end"}
87
- align="center"
88
- >
89
- <AutopayOnIcon />
90
- <ButtonWithAction
91
- text={`${planType} On`}
92
- variant="smallGhost"
93
- dataQa="Autopay On"
94
- textExtraStyles={`font-size: 0.875rem; `}
95
- extraStyles={`min-width: auto; padding: 0 0 0 6px;`}
96
- />
97
- </Cluster>
98
- </Box>
99
- )
100
- }
101
65
  showModal={() => toggleModal(true)}
102
66
  hideModal={() => toggleModal(false)}
103
67
  modalOpen={modalOpen}
104
68
  {...modalExtraProps}
105
- />
69
+ >
70
+ {buttonLinkType ? (
71
+ <ButtonWithAction
72
+ text={autoPayActive ? `Manage ${planType}` : `Set Up ${planType}`}
73
+ variant="tertiary"
74
+ action={() => {
75
+ toggleModal(true);
76
+ }}
77
+ dataQa="Manage Autopay"
78
+ extraStyles={isMobile && `flex-grow: 1; width: 100%;`}
79
+ />
80
+ ) : (
81
+ <Box
82
+ padding="0"
83
+ onClick={() => {
84
+ toggleModal(true);
85
+ }}
86
+ hoverStyles={hoverStyles}
87
+ activeStyles={activeStyles}
88
+ extraStyles={defaultStyles}
89
+ >
90
+ <Cluster
91
+ justify={isMobile ? "flex-start" : "flex-end"}
92
+ align="center"
93
+ >
94
+ <AutopayOnIcon />
95
+ <Text
96
+ variant="pS"
97
+ onClick={() => toggleModal(true)}
98
+ onKeyPress={e => {
99
+ console.log({ e });
100
+ e.key === "Enter" && toggleModal(true);
101
+ }}
102
+ tabIndex="0"
103
+ dataQa={`${planType} On`}
104
+ color={themeValues.linkColor}
105
+ weight={themeValues.fontWeight}
106
+ hoverStyles={themeValues.modalLinkHoverFocus}
107
+ extraStyles={`padding: 0 0 0 6px;`}
108
+ >
109
+ {`${planType} On`}
110
+ </Text>
111
+ </Cluster>
112
+ </Box>
113
+ )}
114
+ </Modal>
106
115
  );
107
116
  };
108
117
 
@@ -1,9 +1,20 @@
1
+ import { FONT_WEIGHT_REGULAR } from "../../../../constants/style_constants";
2
+
1
3
  const color = "#15749D";
2
4
  const hoverColor = "#116285";
3
5
  const activeColor = "#0E506D";
6
+ const linkColor = "#357fb8";
7
+ const fontWeight = FONT_WEIGHT_REGULAR;
8
+ const modalLinkHoverFocus = `outline: none;
9
+ cursor: pointer;
10
+ text-decoration: underline;
11
+ text-decoration-color: #357fb8;`;
4
12
 
5
13
  export const fallbackValues = {
6
14
  color,
7
15
  hoverColor,
8
- activeColor
16
+ activeColor,
17
+ linkColor,
18
+ fontWeight,
19
+ modalLinkHoverFocus
9
20
  };