@thecb/components 11.1.11-beta.1 → 11.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/dist/index.cjs.js +133 -53
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +133 -53
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/atoms/form-layouts/FormInput.js +29 -20
- package/src/components/molecules/multiple-select-filter/MultipleSelectFilter.js +49 -10
- package/src/components/molecules/multiple-select-filter/__private__/FilterButton.js +3 -1
- package/src/components/molecules/multiple-select-filter/__private__/util.js +13 -0
- package/src/components/molecules/obligation/Obligation.js +3 -1
- package/src/components/molecules/obligation/modules/AutopayModalModule.js +2 -2
- package/src/components/molecules/partial-amount-form/PartialAmountField.js +29 -5
- package/src/components/molecules/partial-amount-form/PartialAmountField.theme.js +7 -0
package/package.json
CHANGED
|
@@ -99,6 +99,7 @@ const FormattedInputField = styled(({ showErrors, themeValues, ...props }) => (
|
|
|
99
99
|
|
|
100
100
|
const FormInput = ({
|
|
101
101
|
type = "text",
|
|
102
|
+
labelDisplayOverride = null,
|
|
102
103
|
labelTextWhenNoError = "",
|
|
103
104
|
errorMessages,
|
|
104
105
|
isNum = false,
|
|
@@ -147,39 +148,47 @@ const FormInput = ({
|
|
|
147
148
|
<Box padding="0">
|
|
148
149
|
{helperModal ? (
|
|
149
150
|
<Cluster justify="space-between" align="center">
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
151
|
+
{labelDisplayOverride ? (
|
|
152
|
+
labelDisplayOverride
|
|
153
|
+
) : (
|
|
154
|
+
<Text
|
|
155
|
+
as="label"
|
|
156
|
+
color={themeValues.labelColor}
|
|
157
|
+
variant={labelTextVariant}
|
|
158
|
+
weight={themeValues.fontWeight}
|
|
159
|
+
extraStyles={`word-break: break-word;
|
|
156
160
|
font-family: Public Sans;
|
|
157
161
|
&::first-letter {
|
|
158
162
|
text-transform: uppercase;
|
|
159
163
|
}`}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
+
id={createIdFromString(labelTextWhenNoError)}
|
|
165
|
+
>
|
|
166
|
+
{labelTextWhenNoError}
|
|
167
|
+
</Text>
|
|
168
|
+
)}
|
|
164
169
|
{helperModal()}
|
|
165
170
|
</Cluster>
|
|
166
171
|
) : (
|
|
167
172
|
<Box padding="0" minWidth="100%">
|
|
168
173
|
<Cluster justify="space-between" align="center">
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
174
|
+
{labelDisplayOverride ? (
|
|
175
|
+
labelDisplayOverride
|
|
176
|
+
) : (
|
|
177
|
+
<Text
|
|
178
|
+
as="label"
|
|
179
|
+
color={themeValues.labelColor}
|
|
180
|
+
variant={labelTextVariant}
|
|
181
|
+
fontWeight={themeValues.fontWeight}
|
|
182
|
+
extraStyles={`word-break: break-word;
|
|
175
183
|
font-family: Public Sans;
|
|
176
184
|
&::first-letter {
|
|
177
185
|
text-transform: uppercase;
|
|
178
186
|
}`}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
187
|
+
id={createIdFromString(labelTextWhenNoError)}
|
|
188
|
+
>
|
|
189
|
+
{labelTextWhenNoError}
|
|
190
|
+
</Text>
|
|
191
|
+
)}
|
|
183
192
|
{type === "password" && (
|
|
184
193
|
<Text
|
|
185
194
|
variant={labelTextVariant}
|
|
@@ -11,6 +11,7 @@ import FilterDropdown from "./__private__/FilterDropdown";
|
|
|
11
11
|
import SearchBox from "./__private__/SearchBox";
|
|
12
12
|
import FilterableList from "./__private__/FilterableList";
|
|
13
13
|
import useOutsideClickHook from "../../../hooks/use-outside-click";
|
|
14
|
+
import { mergeOptions } from "./__private__/util";
|
|
14
15
|
|
|
15
16
|
const MultipleSelectFilter = ({
|
|
16
17
|
actions,
|
|
@@ -32,34 +33,71 @@ const MultipleSelectFilter = ({
|
|
|
32
33
|
placeholder = "Search",
|
|
33
34
|
searchable = true,
|
|
34
35
|
themeValues,
|
|
35
|
-
truncateBtnTextWidth = "15rem"
|
|
36
|
+
truncateBtnTextWidth = "15rem",
|
|
37
|
+
activeAppliedOptions
|
|
36
38
|
}) => {
|
|
39
|
+
// State to manage whether the dropdown is open or closed
|
|
37
40
|
const [opened, setOpened] = useState(false);
|
|
41
|
+
|
|
42
|
+
// State to manage the currently selected options
|
|
38
43
|
const [selectedOptions, setSelectedOptions] = useState([]);
|
|
39
|
-
|
|
44
|
+
|
|
45
|
+
// State to manage the applied options, initialized with activeAppliedOptions or an empty array
|
|
46
|
+
const [appliedOptions, setAppliedOptions] = useState(
|
|
47
|
+
activeAppliedOptions || []
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
// State to track whether the user has interacted with the component
|
|
51
|
+
const [hasInteracted, setHasInteracted] = useState(false);
|
|
52
|
+
|
|
53
|
+
// Reference to keep track of the opened state across renders without causing re-renders
|
|
40
54
|
const openedRef = useRef(opened);
|
|
41
55
|
|
|
42
|
-
|
|
43
|
-
if (openedRef.current) {
|
|
44
|
-
setOpened(false);
|
|
45
|
-
actions.fields.searchTerm.set("");
|
|
46
|
-
}
|
|
47
|
-
};
|
|
56
|
+
// Hook to detect clicks outside the component and close the dropdown
|
|
48
57
|
const containerRef = useOutsideClickHook(() => handleOnClose());
|
|
58
|
+
|
|
59
|
+
// References to various elements within the component
|
|
49
60
|
const dropdownRef = useRef(null);
|
|
50
61
|
const filterButtonRef = useRef(null);
|
|
51
62
|
const applyFilterButtonRef = useRef(null);
|
|
63
|
+
|
|
64
|
+
// IDs for accessibility and identification purposes
|
|
52
65
|
const filterDropdownID = `${name}-filter-dropdown`;
|
|
53
66
|
const listGroupID = `${name}-list-group`;
|
|
54
67
|
|
|
68
|
+
const handleOnClose = () => {
|
|
69
|
+
if (openedRef.current) {
|
|
70
|
+
setOpened(false);
|
|
71
|
+
actions.fields.searchTerm.set("");
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
55
75
|
useEffect(() => {
|
|
56
76
|
openedRef.current = opened;
|
|
57
77
|
if (!opened) {
|
|
58
|
-
|
|
59
|
-
|
|
78
|
+
if (hasInteracted) {
|
|
79
|
+
onApply(selectedOptions);
|
|
80
|
+
setAppliedOptions(selectedOptions);
|
|
81
|
+
}
|
|
82
|
+
} else {
|
|
83
|
+
setHasInteracted(true);
|
|
60
84
|
}
|
|
61
85
|
}, [opened]);
|
|
62
86
|
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
// Update the applied options state with the current active applied options,
|
|
89
|
+
// or an empty array if activeAppliedOptions is undefined or null.
|
|
90
|
+
// This ensures that the current applied options are in sync with the parent component.
|
|
91
|
+
setAppliedOptions(activeAppliedOptions || []);
|
|
92
|
+
|
|
93
|
+
// Merge the selected options with the active applied options.
|
|
94
|
+
const mergedSelections = mergeOptions(
|
|
95
|
+
selectedOptions,
|
|
96
|
+
activeAppliedOptions
|
|
97
|
+
);
|
|
98
|
+
setSelectedOptions(mergedSelections);
|
|
99
|
+
}, [activeAppliedOptions]);
|
|
100
|
+
|
|
63
101
|
useEffect(() => {
|
|
64
102
|
const handleKeyDown = event => {
|
|
65
103
|
if (event.key === "Escape") {
|
|
@@ -122,6 +160,7 @@ const MultipleSelectFilter = ({
|
|
|
122
160
|
filterLabel={filterLabel}
|
|
123
161
|
selectedOptions={selectedOptions}
|
|
124
162
|
extraStyles={btnExtraStyles}
|
|
163
|
+
dataAppliedOptions={appliedOptions?.length}
|
|
125
164
|
></FilterButton>
|
|
126
165
|
<FilterDropdown
|
|
127
166
|
id={filterDropdownID}
|
|
@@ -21,7 +21,8 @@ const FilterButton = forwardRef(
|
|
|
21
21
|
truncateBtnTextWidth,
|
|
22
22
|
filterLabel,
|
|
23
23
|
selectedOptions,
|
|
24
|
-
extraStyles
|
|
24
|
+
extraStyles,
|
|
25
|
+
dataAppliedOptions
|
|
25
26
|
},
|
|
26
27
|
ref
|
|
27
28
|
) => {
|
|
@@ -48,6 +49,7 @@ const FilterButton = forwardRef(
|
|
|
48
49
|
dataQa={`${name}-filter-button`}
|
|
49
50
|
extraStyles={extraStyles}
|
|
50
51
|
aria-label={`${filterLabel} Filter: ${btnTextFilterDescription} ${btnTextItemsDescription}`}
|
|
52
|
+
data-applied-options={dataAppliedOptions}
|
|
51
53
|
contentOverride
|
|
52
54
|
>
|
|
53
55
|
{btnContentOverride ? (
|
|
@@ -29,3 +29,16 @@ export const selectOption = (option, selectedOptions, setSelectedOptions) => {
|
|
|
29
29
|
setSelectedOptions(moreOptions);
|
|
30
30
|
}
|
|
31
31
|
};
|
|
32
|
+
|
|
33
|
+
export const mergeOptions = (selectedOptions, activeOptions) => {
|
|
34
|
+
if (!activeOptions.length) return selectedOptions;
|
|
35
|
+
if (!selectedOptions.length) return activeOptions;
|
|
36
|
+
|
|
37
|
+
const mergedOptions = [...selectedOptions];
|
|
38
|
+
activeOptions.forEach(activeOption => {
|
|
39
|
+
if (!mergedOptions.some(option => option.name === activeOption.name)) {
|
|
40
|
+
mergedOptions.push(activeOption);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
return mergedOptions;
|
|
44
|
+
};
|
|
@@ -20,7 +20,7 @@ import { fallbackValues } from "./Obligation.theme";
|
|
|
20
20
|
|
|
21
21
|
const Obligation = ({
|
|
22
22
|
config,
|
|
23
|
-
obligations,
|
|
23
|
+
obligations = [],
|
|
24
24
|
actions,
|
|
25
25
|
autoPayEnabled,
|
|
26
26
|
autoPayAvailable,
|
|
@@ -121,6 +121,7 @@ const Obligation = ({
|
|
|
121
121
|
{!isMobile && (
|
|
122
122
|
<PaymentDetailsActions
|
|
123
123
|
obligations={obligations}
|
|
124
|
+
obligationAssocID={obligationAssocID}
|
|
124
125
|
autoPayEnabled={autoPayEnabled}
|
|
125
126
|
autoPayAvailable={autoPayAvailable}
|
|
126
127
|
handleAutopayAction={handleAutopayAction}
|
|
@@ -146,6 +147,7 @@ const Obligation = ({
|
|
|
146
147
|
{isMobile && (
|
|
147
148
|
<PaymentDetailsActions
|
|
148
149
|
obligations={obligations}
|
|
150
|
+
obligationAssocID={obligationAssocID}
|
|
149
151
|
autoPayEnabled={autoPayEnabled}
|
|
150
152
|
autoPayAvailable={autoPayAvailable}
|
|
151
153
|
handleAutopayAction={handleAutopayAction}
|
|
@@ -33,8 +33,8 @@ const AutopayModalModule = ({
|
|
|
33
33
|
onKeyPress
|
|
34
34
|
}) => {
|
|
35
35
|
const generateMethodNeededText = (planText, allowedPaymentInstruments) => {
|
|
36
|
-
const allowsCard = allowedPaymentInstruments
|
|
37
|
-
const allowsACH = allowedPaymentInstruments
|
|
36
|
+
const allowsCard = allowedPaymentInstruments?.includes(CC_METHOD);
|
|
37
|
+
const allowsACH = allowedPaymentInstruments?.includes(ACH_METHOD);
|
|
38
38
|
const methodRequired =
|
|
39
39
|
allowsCard && !allowsACH
|
|
40
40
|
? "debit or credit card payment method"
|
|
@@ -2,18 +2,34 @@ import React from "react";
|
|
|
2
2
|
import { equals } from "ramda";
|
|
3
3
|
import { FormInput } from "../../atoms/form-layouts";
|
|
4
4
|
import { displayCurrency } from "../../../util/general";
|
|
5
|
-
import Text from "../../atoms
|
|
6
|
-
|
|
5
|
+
import { Stack, Detail, Text } from "../../atoms";
|
|
6
|
+
import { themeComponent } from "../../../util/themeUtils";
|
|
7
|
+
import { fallbackValues } from "./PartialAmountField.theme";
|
|
7
8
|
const PartialAmountField = ({
|
|
8
9
|
lineItem,
|
|
9
10
|
field,
|
|
10
11
|
showErrors,
|
|
11
12
|
errorMessages,
|
|
12
13
|
moneyFormat,
|
|
13
|
-
fieldActions
|
|
14
|
+
fieldActions,
|
|
15
|
+
themeValues
|
|
14
16
|
}) => (
|
|
15
17
|
<FormInput
|
|
16
|
-
|
|
18
|
+
labelDisplayOverride={
|
|
19
|
+
<Stack childGap="0px">
|
|
20
|
+
<Detail
|
|
21
|
+
as="h3"
|
|
22
|
+
variant={themeValues.detailVariant}
|
|
23
|
+
weight={themeValues.weightTitle}
|
|
24
|
+
>
|
|
25
|
+
<span>{lineItem.description}</span>
|
|
26
|
+
</Detail>
|
|
27
|
+
<Detail as="p" variant={themeValues.detailVariant} weight="400">
|
|
28
|
+
{lineItem.subDescription}
|
|
29
|
+
</Detail>
|
|
30
|
+
</Stack>
|
|
31
|
+
}
|
|
32
|
+
labelTextWhenNoError={`${lineItem.description} | ${lineItem.subDescription}`}
|
|
17
33
|
key={lineItem.id}
|
|
18
34
|
field={field}
|
|
19
35
|
fieldActions={fieldActions}
|
|
@@ -46,4 +62,12 @@ function arePropsEqual(prevProps, nextProps) {
|
|
|
46
62
|
);
|
|
47
63
|
}
|
|
48
64
|
|
|
49
|
-
export default React.memo(
|
|
65
|
+
export default React.memo(
|
|
66
|
+
themeComponent(
|
|
67
|
+
PartialAmountField,
|
|
68
|
+
"PartialAmountField",
|
|
69
|
+
fallbackValues,
|
|
70
|
+
"default"
|
|
71
|
+
),
|
|
72
|
+
arePropsEqual
|
|
73
|
+
);
|