@thecb/components 4.1.10 → 4.1.12-beta.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thecb/components",
3
- "version": "4.1.10",
3
+ "version": "4.1.12-beta.0",
4
4
  "description": "Common lib for CityBase react components",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.esm.js",
@@ -48,7 +48,7 @@
48
48
  "prettier": "^1.19.1",
49
49
  "pretty-quick": "^2.0.1",
50
50
  "react-redux": "^7.2.0",
51
- "react-router-dom": "6.0.0-alpha.3",
51
+ "react-router-dom": "^5.2.0",
52
52
  "redux": "^4.0.5",
53
53
  "rollup": "^1.21.4",
54
54
  "rollup-plugin-babel": "^4.3.3",
@@ -1,5 +1,5 @@
1
1
  import {
2
- FIREFLY_GREY,
2
+ CHARADE_GREY,
3
3
  MATISSE_BLUE,
4
4
  WHITE,
5
5
  SEASHELL_WHITE,
@@ -23,7 +23,7 @@ const inputBackgroundColor = {
23
23
  disabled: `${SEASHELL_WHITE}`
24
24
  };
25
25
  const color = { default: `${MINESHAFT_GREY}`, disabled: `${DUSTY_GREY}` };
26
- const labelColor = { default: `${FIREFLY_GREY}`, disabled: `${FIREFLY_GREY}` };
26
+ const labelColor = { default: `${CHARADE_GREY}`, disabled: `${CHARADE_GREY}` };
27
27
  const borderColor = { default: `${GREY_CHATEAU}`, disabled: `${GREY_CHATEAU}` };
28
28
  const lineHeight = { default: "1rem", disabled: "1rem" };
29
29
  const fontSize = { default: "0.875rem", disabled: "0.875rem" };
@@ -1,8 +1,11 @@
1
1
  import React, { useState, useRef, useEffect } from "react";
2
2
  import Dropdown from "../dropdown";
3
3
  import Text from "../text";
4
- import { STORM_GREY } from "../../../constants/colors";
4
+ import { ERROR_COLOR } from "../../../constants/colors";
5
5
  import { SelectContainer, SelectLabel } from "./FormSelect.styled";
6
+ import { fallbackValues } from "./FormSelect.theme";
7
+ import { themeComponent } from "../../../util/themeUtils";
8
+ import { Box, Cluster } from "../layouts";
6
9
 
7
10
  const FormSelect = ({
8
11
  fieldActions,
@@ -12,7 +15,9 @@ const FormSelect = ({
12
15
  field,
13
16
  showErrors,
14
17
  onChange,
15
- dropdownMaxHeight
18
+ dropdownMaxHeight,
19
+ disabledValues,
20
+ themeValues
16
21
  }) => {
17
22
  const [open, setOpen] = useState(false);
18
23
  const dropdownRef = useRef(null);
@@ -32,33 +37,63 @@ const FormSelect = ({
32
37
 
33
38
  return (
34
39
  <SelectContainer ref={dropdownRef}>
35
- <Text
36
- variant="pS"
37
- color={STORM_GREY}
38
- weight="400"
39
- extraStyles={`margin-bottom: 4px;`}
40
- >
41
- {labelTextWhenNoError}
42
- </Text>
40
+ <Box padding="0" minWidth="100%">
41
+ <Cluster justify="space-between" align="center">
42
+ <Text
43
+ as="label"
44
+ variant="pS"
45
+ color={themeValues.labelColor}
46
+ weight={themeValues.fontWeight}
47
+ extraStyles={`word-break: break-word;
48
+ font-family: Public Sans;
49
+ &::first-letter {
50
+ text-transform: uppercase;
51
+ }`}
52
+ >
53
+ {labelTextWhenNoError}
54
+ </Text>
55
+ </Cluster>
56
+ </Box>
43
57
  <Dropdown
44
58
  maxHeight={dropdownMaxHeight}
45
59
  placeholder={options[0] ? options[0].text : ""}
46
60
  options={options}
47
61
  value={field.rawValue}
62
+ disabledValues={disabledValues}
48
63
  isOpen={open}
49
- isError={false}
64
+ isError={
65
+ (field.hasErrors && field.dirty) || (field.hasErrors && showErrors)
66
+ }
50
67
  onSelect={
51
68
  onChange ? value => onChange(value) : value => fieldActions.set(value)
52
69
  }
53
70
  onClick={() => setOpen(!open)}
54
71
  />
55
72
  <SelectLabel field={field} showErrors={showErrors}>
56
- {(field.hasErrors && field.dirty) || (field.hasErrors && showErrors)
57
- ? errorMessages[field.errors[0]]
58
- : null}
73
+ {(field.hasErrors && field.dirty) || (field.hasErrors && showErrors) ? (
74
+ <Text
75
+ color={ERROR_COLOR}
76
+ variant="pXS"
77
+ weight={themeValues.fontWeight}
78
+ extraStyles={`word-break: break-word;
79
+ font-family: Public Sans;
80
+ &::first-letter {
81
+ text-transform: uppercase;
82
+ }`}
83
+ >
84
+ {errorMessages[field.errors[0]]}
85
+ </Text>
86
+ ) : (
87
+ <Text extraStyles={`height: ${themeValues.lineHeight};`} />
88
+ )}
59
89
  </SelectLabel>
60
90
  </SelectContainer>
61
91
  );
62
92
  };
63
93
 
64
- export default FormSelect;
94
+ export default themeComponent(
95
+ FormSelect,
96
+ "FormSelect",
97
+ fallbackValues,
98
+ "default"
99
+ );
@@ -1,6 +1,5 @@
1
1
  import React from "react";
2
2
  import { connect } from "react-redux";
3
- import { boolean } from "@storybook/addon-knobs";
4
3
  import { createFormState, required } from "redux-freeform";
5
4
 
6
5
  import FormSelect from "./FormSelect";
@@ -18,7 +17,8 @@ const options = [
18
17
  { value: "", text: "choose name" },
19
18
  { value: "foo", text: "foo" },
20
19
  { value: "bar", text: "bar" },
21
- { value: "baz", text: "baz" }
20
+ { value: "baz", text: "baz" },
21
+ { value: "disabled", text: "disabled" }
22
22
  ];
23
23
 
24
24
  const story = page({
@@ -32,10 +32,12 @@ const story = page({
32
32
 
33
33
  const FormWrapper = ({ fields, actions }) => (
34
34
  <FormSelect
35
+ labelTextWhenNoError="Form Select"
35
36
  errorMessages={errorMessages}
36
37
  options={options}
37
38
  field={fields.thing}
38
39
  fieldActions={actions.fields.thing}
40
+ disabledValues={["disabled"]}
39
41
  />
40
42
  );
41
43
 
@@ -1,10 +1,6 @@
1
1
  import styled from "styled-components";
2
2
  import {
3
- MINESHAFT_GREY,
4
3
  STORM_GREY,
5
- WHITE,
6
- SEASHELL_WHITE,
7
- DUSTY_GREY,
8
4
  GHOST_GREY,
9
5
  ERROR_COLOR,
10
6
  MATISSE_BLUE
@@ -17,6 +13,9 @@ export const SelectContainer = styled.div`
17
13
  flex-direction: column;
18
14
  justify-content: space-between;
19
15
  align-items: flex-start;
16
+ > * + * {
17
+ margin-top: 0.25rem;
18
+ }
20
19
  `;
21
20
 
22
21
  export const SelectLabel = styled.label`
@@ -53,8 +52,9 @@ export const SelectField = styled.select`
53
52
  font-family: Public Sans;
54
53
  line-height: 2rem;
55
54
  font-weight: ${FONT_WEIGHT_REGULAR};
56
- background-color: ${({ disabled }) => (disabled ? SEASHELL_WHITE : WHITE)};
57
- color: ${({ disabled }) => (disabled ? DUSTY_GREY : MINESHAFT_GREY)};
55
+ background-color: ${({ themeValues }) =>
56
+ themeValues.inputBackgroundColor && themeValues.inputBackgroundColor};
57
+ color: ${({ themeValues }) => themeValues.color && themeValues.color};
58
58
  box-shadow: none;
59
59
 
60
60
  &:focus {
@@ -0,0 +1,52 @@
1
+ import {
2
+ CHARADE_GREY,
3
+ MATISSE_BLUE,
4
+ WHITE,
5
+ SEASHELL_WHITE,
6
+ MINESHAFT_GREY,
7
+ DUSTY_GREY,
8
+ GREY_CHATEAU,
9
+ ATHENS_GREY
10
+ } from "../../../constants/colors";
11
+ import { FONT_WEIGHT_REGULAR } from "../../../constants/style_constants";
12
+
13
+ const linkColor = { default: `${MATISSE_BLUE}`, disabled: `${MATISSE_BLUE}` };
14
+ const formBackgroundColor = {
15
+ default: `${WHITE}`,
16
+ disabled: `${WHITE}`,
17
+ checkout: `${ATHENS_GREY}`,
18
+ collapsible: `${ATHENS_GREY}`
19
+ };
20
+
21
+ const inputBackgroundColor = {
22
+ default: `${WHITE}`,
23
+ disabled: `${SEASHELL_WHITE}`
24
+ };
25
+ const color = { default: `${MINESHAFT_GREY}`, disabled: `${DUSTY_GREY}` };
26
+ const labelColor = { default: `${CHARADE_GREY}`, disabled: `${CHARADE_GREY}` };
27
+ const borderColor = { default: `${GREY_CHATEAU}`, disabled: `${GREY_CHATEAU}` };
28
+ const lineHeight = { default: "1rem", disabled: "1rem" };
29
+ const fontSize = { default: "0.875rem", disabled: "0.875rem" };
30
+ const errorFontSize = { default: "0.75rem", disabled: "0.75rem" };
31
+ const fontWeight = {
32
+ default: `${FONT_WEIGHT_REGULAR}`,
33
+ disabled: `${FONT_WEIGHT_REGULAR}`
34
+ };
35
+ const hoverFocusStyles = {
36
+ default: `color: #0E506D; outline: none; text-decoration: underline; `,
37
+ disabled: `color: #6E727E;`
38
+ };
39
+
40
+ export const fallbackValues = {
41
+ linkColor,
42
+ formBackgroundColor,
43
+ inputBackgroundColor,
44
+ color,
45
+ labelColor,
46
+ borderColor,
47
+ lineHeight,
48
+ fontSize,
49
+ errorFontSize,
50
+ fontWeight,
51
+ hoverFocusStyles
52
+ };
@@ -3,7 +3,7 @@ import { required, hasLength } from "redux-freeform";
3
3
  import styled from "styled-components";
4
4
  import StateProvinceDropdown from "../../atoms/state-province-dropdown";
5
5
  import Checkbox from "../../atoms/checkbox";
6
- // import CountryDropdown from "../../atoms/country-dropdown";
6
+ import CountryDropdown from "../../atoms/country-dropdown";
7
7
  import { zipFormat } from "../../../util/formats";
8
8
  import { noop } from "../../../util/general";
9
9
  import {
@@ -51,16 +51,16 @@ const AddressForm = ({
51
51
  const stateProvinceErrorMessages = {
52
52
  [required.error]: "State or Province is required"
53
53
  };
54
- // const countryErrorMessages = {
55
- // [required.error]: "Country is required"
56
- // };
54
+ const countryErrorMessages = {
55
+ [required.error]: "Country is required"
56
+ };
57
57
 
58
58
  const isUS = fields.country.rawValue === "US";
59
59
 
60
60
  return (
61
61
  <FormContainer variant={variant} role="form" aria-label="Address">
62
62
  <FormInputColumn>
63
- {/* <CountryDropdown
63
+ <CountryDropdown
64
64
  labelTextWhenNoError="Country"
65
65
  errorMessages={countryErrorMessages}
66
66
  field={fields.country}
@@ -76,7 +76,7 @@ const AddressForm = ({
76
76
  }
77
77
  }}
78
78
  showErrors={showErrors}
79
- /> */}
79
+ />
80
80
  <FormInput
81
81
  labelTextWhenNoError="Address"
82
82
  errorMessages={street1ErrorMessages}
@@ -16,7 +16,8 @@ const PaymentButtonBar = ({
16
16
  cancelURL,
17
17
  cancelText = "Cancel",
18
18
  redirectURL,
19
- redirectText = "Return"
19
+ redirectText = "Return",
20
+ buttonFlexOverride
20
21
  }) => {
21
22
  const { isMobile } = useContext(ThemeContext);
22
23
 
@@ -68,7 +69,13 @@ const PaymentButtonBar = ({
68
69
  <SolidDivider />
69
70
  <Box padding="2.5rem 0 3.125rem 0">
70
71
  <Cluster
71
- justify={!!backButton ? "space-between" : "flex-end"}
72
+ justify={
73
+ buttonFlexOverride
74
+ ? buttonFlexOverride
75
+ : !!backButton
76
+ ? "space-between"
77
+ : "flex-end"
78
+ }
72
79
  align="center"
73
80
  childGap="0.75rem"
74
81
  >
@@ -2,8 +2,13 @@ import React, { useEffect, useState } from "react";
2
2
  import styled from "styled-components";
3
3
  import { required, hasLength, matchesRegex } from "redux-freeform";
4
4
  import Checkbox from "../../atoms/checkbox";
5
+ import CountryDropdown from "../../atoms/country-dropdown";
5
6
  import { checkCardBrand, noop } from "../../../util/general";
6
- import { expirationDateFormat, creditCardFormat } from "../../../util/formats";
7
+ import {
8
+ expirationDateFormat,
9
+ creditCardFormat,
10
+ zipFormat
11
+ } from "../../../util/formats";
7
12
  import {
8
13
  FormInput,
9
14
  FormInputColumn,
@@ -36,6 +41,9 @@ const zipCodeErrors = {
36
41
  [required.error]: "Zip code is required",
37
42
  [hasLength.error]: "Zip code is invalid"
38
43
  };
44
+ const countryErrorMessages = {
45
+ [required.error]: "Country is required"
46
+ };
39
47
 
40
48
  const PaymentFormCard = ({
41
49
  variant = "default",
@@ -61,9 +69,26 @@ const PaymentFormCard = ({
61
69
  return () => actions.form.clear();
62
70
  }
63
71
  }, []);
72
+ const isUS = fields.country.rawValue === "US";
64
73
  return (
65
74
  <FormContainer variant={variant} role="form" aria-label="Card payment">
66
75
  <FormInputColumn>
76
+ {!hideZipCode && (
77
+ <CountryDropdown
78
+ labelTextWhenNoError="Country"
79
+ errorMessages={countryErrorMessages}
80
+ field={fields.country}
81
+ onChange={value => {
82
+ actions.fields.country.set(value);
83
+ // temporary measure to not dirty fields until
84
+ // we can write a reset function for fields
85
+ if (fields.zipCode.rawValue) {
86
+ actions.fields.zipCode.set("");
87
+ }
88
+ }}
89
+ showErrors={showErrors}
90
+ />
91
+ )}
67
92
  <FormInput
68
93
  labelTextWhenNoError="Name on card"
69
94
  errorMessages={nameOnCardErrors}
@@ -111,6 +136,8 @@ const PaymentFormCard = ({
111
136
  width={isMobile ? "100%" : "50%"}
112
137
  >
113
138
  <FormInput
139
+ isNum={isUS}
140
+ formatter={isUS ? zipFormat : null}
114
141
  labelTextWhenNoError="Zip code"
115
142
  errorMessages={zipCodeErrors}
116
143
  field={fields.zipCode}
@@ -3,12 +3,17 @@ import {
3
3
  required,
4
4
  onlyIntegers,
5
5
  hasLength,
6
- matchesRegex
6
+ matchesRegex,
7
+ validateWhen
7
8
  } from "redux-freeform";
8
9
 
9
10
  //TODO: Will make zip code able to have more than 5 digits once we add in the FormattedInput because it will have issues with format of 60606-1111.
10
11
 
11
12
  const formConfig = {
13
+ country: {
14
+ defaultValue: "US",
15
+ validators: [required()]
16
+ },
12
17
  nameOnCard: {
13
18
  validators: [required()]
14
19
  },
@@ -29,8 +34,23 @@ const formConfig = {
29
34
  constraints: [onlyIntegers(), hasLength(0, 4)]
30
35
  },
31
36
  zipCode: {
32
- validators: [required(), hasLength(5, 5)],
33
- constraints: [onlyIntegers(), hasLength(0, 5)]
37
+ validators: [
38
+ required(),
39
+ validateWhen(
40
+ validateWhen(hasLength(5, 5), hasLength(0, 5)),
41
+ matchesRegex("US"),
42
+ "country"
43
+ ),
44
+ validateWhen(
45
+ validateWhen(hasLength(9, 9), hasLength(6, 9)),
46
+ matchesRegex("US"),
47
+ "country"
48
+ )
49
+ ],
50
+ constraints: [
51
+ validateWhen(onlyIntegers(), matchesRegex("US"), "country"),
52
+ validateWhen(hasLength(0, 9), matchesRegex("US"), "country")
53
+ ]
34
54
  }
35
55
  };
36
56