@thecb/components 10.12.3-beta.0 → 10.12.3-beta.1

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 (211) hide show
  1. package/README.md +0 -4
  2. package/dist/index.cjs.js +2526 -1617
  3. package/dist/index.cjs.js.map +1 -1
  4. package/dist/index.d.ts +4 -5
  5. package/dist/index.esm.js +2527 -1617
  6. package/dist/index.esm.js.map +1 -1
  7. package/package.json +13 -25
  8. package/src/components/atoms/alert/Alert.stories.js +26 -148
  9. package/src/components/atoms/badge/Badge.js +2 -2
  10. package/src/components/atoms/badge/Badge.stories.js +29 -143
  11. package/src/components/atoms/breadcrumb/Breadcrumb.stories.js +29 -38
  12. package/src/components/atoms/button-with-action/ButtonWithAction.stories.js +55 -108
  13. package/src/components/atoms/button-with-link/ButtonWithLink.stories.js +31 -160
  14. package/src/components/atoms/checkbox/Checkbox.stories.js +29 -148
  15. package/src/components/atoms/country-dropdown/CountryDropdown.stories.js +27 -61
  16. package/src/components/atoms/detail/Detail.js +26 -0
  17. package/src/components/atoms/display-box/DisplayBox.stories.js +21 -65
  18. package/src/components/atoms/display-card/DisplayCard.stories.js +22 -163
  19. package/src/components/atoms/dropdown/Dropdown.stories.js +10 -91
  20. package/src/components/atoms/form-layouts/FormInput.stories.js +26 -212
  21. package/src/components/atoms/form-select/FormSelect.stories.js +29 -55
  22. package/src/components/atoms/formatted-address/FormattedAddress.stories.js +27 -133
  23. package/src/components/atoms/icons/icons.stories.js +116 -0
  24. package/src/components/atoms/labeled-amount/LabeledAmount.stories.js +34 -110
  25. package/src/components/atoms/line-item/LineItem.stories.js +22 -89
  26. package/src/components/atoms/link/Link.stories.js +49 -155
  27. package/src/components/atoms/loading-line/LoadingLine.js +10 -14
  28. package/src/components/atoms/loading-line/LoadingLine.stories.js +28 -132
  29. package/src/components/atoms/nav-footer/NavFooter.stories.js +22 -235
  30. package/src/components/atoms/nav-header/NavHeader.stories.js +21 -122
  31. package/src/components/atoms/password-requirements/PasswordRequirements.stories.js +44 -108
  32. package/src/components/atoms/placeholder/Placeholder.stories.js +36 -164
  33. package/src/components/atoms/searchable-select/SearchableSelect.stories.js +28 -103
  34. package/src/components/atoms/state-province-dropdown/StateProvinceDropdown.stories.js +40 -65
  35. package/src/components/atoms/table/Table.stories.js +75 -59
  36. package/src/components/atoms/table/TableRow.js +0 -1
  37. package/src/components/atoms/title/Title.js +23 -0
  38. package/src/components/atoms/toggle-switch/ToggleSwitch.stories.js +20 -103
  39. package/src/components/atoms/toggle-switch/ToggleSwitch.theme.js +5 -8
  40. package/src/components/molecules/address-form/AddressForm.stories.js +20 -223
  41. package/src/components/molecules/banner/Banner.stories.js +26 -122
  42. package/src/components/molecules/change-password-form/ChangePasswordForm.stories.js +19 -203
  43. package/src/components/molecules/collapsible-section/CollapsibleSection.stories.js +61 -210
  44. package/src/components/molecules/edit-name-form/EdidNameForm.stories.js +24 -0
  45. package/src/components/molecules/index.js +0 -1
  46. package/src/components/molecules/link-card/LinkCard.stories.js +72 -287
  47. package/src/components/molecules/login-form/LoginForm.stories.js +21 -117
  48. package/src/components/molecules/modal/Modal.stories.js +128 -342
  49. package/src/components/molecules/module/Module.stories.js +25 -267
  50. package/src/components/molecules/multiple-select-filter/MultipleSelectFilter.js +61 -295
  51. package/src/components/molecules/multiple-select-filter/{MultipleSelectFilter.oldstories.js → MultipleSelectFilter.stories.js} +1 -1
  52. package/src/components/molecules/multiple-select-filter/MultipleSelectFilter.styled.js +4 -4
  53. package/src/components/molecules/multiple-select-filter/__private__/ActionLinkButton.js +24 -0
  54. package/src/components/molecules/multiple-select-filter/__private__/FilterButton.js +85 -0
  55. package/src/components/molecules/multiple-select-filter/__private__/FilterDropdown.js +23 -0
  56. package/src/components/molecules/multiple-select-filter/__private__/FilterableList.js +144 -0
  57. package/src/components/molecules/multiple-select-filter/__private__/FilterableListItem.js +67 -0
  58. package/src/components/molecules/multiple-select-filter/__private__/SearchBox.js +38 -0
  59. package/src/components/molecules/multiple-select-filter/__private__/useKeyboardNavigation.js +84 -0
  60. package/src/components/molecules/multiple-select-filter/__private__/util.js +31 -0
  61. package/src/components/molecules/obligation/icons/PropertyPersonalIcon.js +1 -1
  62. package/src/components/molecules/pagination/Pagination.stories.js +28 -177
  63. package/src/components/molecules/tabs/Tabs.stories.js +227 -135
  64. package/src/components/molecules/toast-notification/ToastNotification.stories.js +105 -0
  65. package/src/hooks/use-outside-click/index.js +4 -5
  66. package/src/util/index.js +1 -3
  67. package/src/components/atoms/alert/Alert.mdx +0 -19
  68. package/src/components/atoms/badge/Badge.mdx +0 -27
  69. package/src/components/atoms/breadcrumb/Breadcrumb.mdx +0 -21
  70. package/src/components/atoms/button-with-link/ButtonWithLink.mdx +0 -21
  71. package/src/components/atoms/card/Card.mdx +0 -41
  72. package/src/components/atoms/card/Card.stories.js +0 -360
  73. package/src/components/atoms/checkbox/Checkbox.mdx +0 -15
  74. package/src/components/atoms/checkbox/Checkbox.oldstories.js +0 -30
  75. package/src/components/atoms/country-dropdown/CountryDropdown.mdx +0 -36
  76. package/src/components/atoms/detail/Detail.mdx +0 -32
  77. package/src/components/atoms/detail/Detail.stories.js +0 -156
  78. package/src/components/atoms/display-box/DisplayBox.mdx +0 -11
  79. package/src/components/atoms/display-card/DisplayCard.mdx +0 -13
  80. package/src/components/atoms/dropdown/Dropdown.mdx +0 -65
  81. package/src/components/atoms/form-layouts/FormInput.mdx +0 -38
  82. package/src/components/atoms/form-select/FormSelect.mdx +0 -42
  83. package/src/components/atoms/formatted-address/FormattedAddress.mdx +0 -13
  84. package/src/components/atoms/formatted-bank-account/FormattedBankAccount.mdx +0 -17
  85. package/src/components/atoms/formatted-bank-account/FormattedBankAccount.stories.js +0 -57
  86. package/src/components/atoms/formatted-credit-card/FormattedCreditCard.mdx +0 -40
  87. package/src/components/atoms/formatted-credit-card/FormattedCreditCard.stories.js +0 -74
  88. package/src/components/atoms/icons/Icons.mdx +0 -40
  89. package/src/components/atoms/icons/Icons.stories.js +0 -325
  90. package/src/components/atoms/labeled-amount/LabeledAmount.mdx +0 -23
  91. package/src/components/atoms/line-item/LineItem.mdx +0 -28
  92. package/src/components/atoms/link/Link.mdx +0 -19
  93. package/src/components/atoms/loading/Loading.mdx +0 -13
  94. package/src/components/atoms/loading/Loading.stories.js +0 -22
  95. package/src/components/atoms/loading-line/LoadingLine.mdx +0 -15
  96. package/src/components/atoms/nav-footer/NavFooter.mdx +0 -15
  97. package/src/components/atoms/nav-header/NavHeader.mdx +0 -13
  98. package/src/components/atoms/nav-tabs/NavTabs.mdx +0 -30
  99. package/src/components/atoms/nav-tabs/NavTabs.stories.js +0 -49
  100. package/src/components/atoms/password-requirements/PasswordRequirements.mdx +0 -39
  101. package/src/components/atoms/placeholder/Placeholder.mdx +0 -19
  102. package/src/components/atoms/searchable-select/SearchableSelect.mdx +0 -44
  103. package/src/components/atoms/state-province-dropdown/StateProvinceDropdown.mdx +0 -36
  104. package/src/components/atoms/table/Table.mdx +0 -71
  105. package/src/components/atoms/table/Table.oldstories.js +0 -84
  106. package/src/components/atoms/title/Title.mdx +0 -26
  107. package/src/components/atoms/title/Title.stories.js +0 -144
  108. package/src/components/atoms/toggle-switch/ToggleSwitch.mdx +0 -17
  109. package/src/components/atoms/typeahead-input/TypeaheadInput.mdx +0 -13
  110. package/src/components/atoms/typeahead-input/TypeaheadInput.stories.js +0 -63
  111. package/src/components/molecules/address-form/AddressForm.mdx +0 -18
  112. package/src/components/molecules/banner/Banner.mdx +0 -23
  113. package/src/components/molecules/change-password-form/ChangePasswordForm.mdx +0 -15
  114. package/src/components/molecules/collapsible-section/CollapsibleSection.mdx +0 -15
  115. package/src/components/molecules/edit-name-form/EditNameForm.mdx +0 -13
  116. package/src/components/molecules/edit-name-form/EditNameForm.stories.js +0 -117
  117. package/src/components/molecules/idle-modal/IdleModal.js +0 -101
  118. package/src/components/molecules/idle-modal/IdleModal.mdx +0 -17
  119. package/src/components/molecules/idle-modal/IdleModal.stories.js +0 -180
  120. package/src/components/molecules/idle-modal/index.d.ts +0 -16
  121. package/src/components/molecules/idle-modal/index.js +0 -3
  122. package/src/components/molecules/link-card/LinkCard.mdx +0 -17
  123. package/src/components/molecules/login-form/LoginForm.mdx +0 -16
  124. package/src/components/molecules/modal/Modal.mdx +0 -17
  125. package/src/components/molecules/module/Module.mdx +0 -17
  126. package/src/components/molecules/obligation/Obligation.mdx +0 -23
  127. package/src/components/molecules/obligation/Obligation.stories.js +0 -460
  128. package/src/components/molecules/pagination/Pagination.mdx +0 -15
  129. package/src/components/molecules/popover/Popover.mdx +0 -15
  130. package/src/components/molecules/popover/Popover.stories.js +0 -220
  131. package/src/components/molecules/tabs/Tabs.mdx +0 -17
  132. package/src/components/molecules/toast-notification/Toast.mdx +0 -15
  133. package/src/components/molecules/toast-notification/Toast.stories.js +0 -183
  134. package/src/stories/Button.stories.ts +0 -53
  135. package/src/stories/Button.tsx +0 -48
  136. package/src/stories/Configure.mdx +0 -364
  137. package/src/stories/Header.stories.ts +0 -33
  138. package/src/stories/Header.tsx +0 -56
  139. package/src/stories/Page.stories.ts +0 -32
  140. package/src/stories/Page.tsx +0 -73
  141. package/src/stories/assets/accessibility.png +0 -0
  142. package/src/stories/assets/accessibility.svg +0 -5
  143. package/src/stories/assets/addon-library.png +0 -0
  144. package/src/stories/assets/assets.png +0 -0
  145. package/src/stories/assets/avif-test-image.avif +0 -0
  146. package/src/stories/assets/context.png +0 -0
  147. package/src/stories/assets/discord.svg +0 -15
  148. package/src/stories/assets/docs.png +0 -0
  149. package/src/stories/assets/figma-plugin.png +0 -0
  150. package/src/stories/assets/github.svg +0 -3
  151. package/src/stories/assets/share.png +0 -0
  152. package/src/stories/assets/styling.png +0 -0
  153. package/src/stories/assets/testing.png +0 -0
  154. package/src/stories/assets/theming.png +0 -0
  155. package/src/stories/assets/tutorials.svg +0 -12
  156. package/src/stories/assets/youtube.svg +0 -4
  157. package/src/stories/button.css +0 -30
  158. package/src/stories/header.css +0 -32
  159. package/src/stories/page.css +0 -69
  160. package/src/util/idleTimerUtils.js +0 -36
  161. /package/src/components/atoms/add-obligation/{AddObligation.oldstories.js → AddObligation.stories.js} +0 -0
  162. /package/src/components/atoms/amount-callout/{AmountCallout.oldstories.js → AmountCallout.stories.js} +0 -0
  163. /package/src/components/atoms/checkbox-list/{CheckboxList.oldstories.js → CheckboxList.stories.js} +0 -0
  164. /package/src/components/atoms/form-layouts/{FormLayouts.oldstories.js → FormLayouts.stories.js} +0 -0
  165. /package/src/components/atoms/hamburger-button/{HamburgerButton.oldstories.js → HamburgerButton.stories.js} +0 -0
  166. /package/src/components/atoms/heading/{Heading.oldstories.js → Heading.stories.js} +0 -0
  167. /package/src/components/atoms/layouts/examples/box-example/{BoxExample.oldstories.js → BoxExample.stories.js} +0 -0
  168. /package/src/components/atoms/layouts/examples/center-example/{CenterExample.oldstories.js → CenterExample.stories.js} +0 -0
  169. /package/src/components/atoms/layouts/examples/cluster-example/{ClusterExample.oldstories.js → ClusterExample.stories.js} +0 -0
  170. /package/src/components/atoms/layouts/examples/cover-example/{CoverExample.oldstories.js → CoverExample.stories.js} +0 -0
  171. /package/src/components/atoms/layouts/examples/frame-example/{FrameExample.oldstories.js → FrameExample.stories.js} +0 -0
  172. /package/src/components/atoms/layouts/examples/grid-example/{GridExample.oldstories.js → GridExample.stories.js} +0 -0
  173. /package/src/components/atoms/layouts/examples/imposter-example/{ImposterExample.oldstories.js → ImposterExample.stories.js} +0 -0
  174. /package/src/components/atoms/layouts/examples/motion-example/{MotionExample.oldstories.js → MotionExample.stories.js} +0 -0
  175. /package/src/components/atoms/layouts/examples/reel-example/{ReelExample.oldstories.js → ReelExample.stories.js} +0 -0
  176. /package/src/components/atoms/layouts/examples/sidebar-example/{SidebarExample.oldstories.js → SidebarExample.stories.js} +0 -0
  177. /package/src/components/atoms/layouts/examples/stack-example/{StackExample.oldstories.js → StackExample.stories.js} +0 -0
  178. /package/src/components/atoms/layouts/examples/switcher-example/{SwitcherExample.oldstories.js → SwitcherExample.stories.js} +0 -0
  179. /package/src/components/atoms/paragraph/{Paragraph.oldstories.js → Paragraph.stories.js} +0 -0
  180. /package/src/components/atoms/processing-fee/{ProcessingFee.oldstories.js → ProcessingFee.stories.js} +0 -0
  181. /package/src/components/atoms/search/{Search.oldstories.js → Search.stories.js} +0 -0
  182. /package/src/components/atoms/solid-divider/{SolidDivider.oldstories.js → SolidDivider.stories.js} +0 -0
  183. /package/src/components/atoms/sortable-table-heading/{SortableTableHeading.oldstories.js → SortableTableHeading.stories.js} +0 -0
  184. /package/src/components/atoms/spinner/{Spinner.oldstories.js → Spinner.stories.js} +0 -0
  185. /package/src/components/atoms/tab/{Tab.oldstories.js → Tab.stories.js} +0 -0
  186. /package/src/components/atoms/text/{Text.oldstories.js → Text.stories.js} +0 -0
  187. /package/src/components/atoms/typeahead-input/{TypeaheadIinput.oldstories.js → TypeaheadIinput.stories.js} +0 -0
  188. /package/src/components/atoms/wallet-name/{WalletName.oldstories.js → WalletName.stories.js} +0 -0
  189. /package/src/components/molecules/account-and-routing-modal/{AccountAndRoutingModal.oldstories.js → AccountAndRoutingModal.stories.js} +0 -0
  190. /package/src/components/molecules/editable-list/{EditableList.oldstories.js → EditableList.stories.js} +0 -0
  191. /package/src/components/molecules/email-form/{EmailForm.oldstories.js → EmailForm.stories.js} +0 -0
  192. /package/src/components/molecules/forgot-password-form/{ForgotPasswordForm.oldstories.js → ForgotPasswordForm.stories.js} +0 -0
  193. /package/src/components/molecules/highlight-tab-row/{HighlightTabRow.oldstories.js → HighlightTabRow.stories.js} +0 -0
  194. /package/src/components/molecules/obligation/modules/{AmountModule.oldstories.js → AmountModule.stories.js} +0 -0
  195. /package/src/components/molecules/payment-button-bar/{PaymentButtonBar.oldstories.js → PaymentButtonBar.stories.js} +0 -0
  196. /package/src/components/molecules/payment-details/{PaymentDetails.oldstories.js → PaymentDetails.stories.js} +0 -0
  197. /package/src/components/molecules/payment-form-ach/{PaymentFormACH.oldstories.js → PaymentFormACH.stories.js} +0 -0
  198. /package/src/components/molecules/payment-form-card/{PaymentFormCard.oldstories.js → PaymentFormCard.stories.js} +0 -0
  199. /package/src/components/molecules/periscope-dashboard-iframe/{PeriscopeDashBoardIframe.oldstories.js → PeriscopeDashBoardIframe.stories.js} +0 -0
  200. /package/src/components/molecules/phone-form/{PhoneForm.oldstories.js → PhoneForm.stories.js} +0 -0
  201. /package/src/components/molecules/popup-menu/{PopupMenu.oldstories.js → PopupMenu.stories.js} +0 -0
  202. /package/src/components/molecules/radio-group/{RadioGroup.oldstories.js → RadioGroup.stories.js} +0 -0
  203. /package/src/components/molecules/radio-section/{RadioSection.oldstories.js → RadioSection.stories.js} +0 -0
  204. /package/src/components/molecules/registration-form/{RegistrationForm.oldstories.js → RegistrationForm.stories.js} +0 -0
  205. /package/src/components/molecules/reset-confirmation-form/{ResetConfirmationForm.oldstories.js → ResetConfirmationForm.stories.js} +0 -0
  206. /package/src/components/molecules/reset-password-form/{ResetPasswordForm.oldstories.js → ResetPasswordForm.stories.js} +0 -0
  207. /package/src/components/molecules/reset-password-success/{ResetPasswordSuccess.oldstories.js → ResetPasswordSuccess.stories.js} +0 -0
  208. /package/src/components/molecules/tab-sidebar/{TabSidebar.oldstories.js → TabSidebar.stories.js} +0 -0
  209. /package/src/components/molecules/terms-and-conditions/{TermsAndConditions.oldstories.js → TermsAndConditions.stories.js} +0 -0
  210. /package/src/components/molecules/terms-and-conditions-modal/{TermsAndConditionsModal.oldstories.js → TermsAndConditionsModal.stories.js} +0 -0
  211. /package/src/components/molecules/workflow-tile/{WorkflowTile.oldstories.js → WorkflowTile.stories.js} +0 -0
@@ -1,146 +1,16 @@
1
- import React, { useState, useEffect, useRef, forwardRef } from "react";
1
+ import React, { useState, useEffect, useRef } from "react";
2
2
  import { fallbackValues } from "./MultipleSelectFilter.theme";
3
3
  import { themeComponent } from "../../../util/themeUtils";
4
- import { Box, Center } from "../../atoms/layouts";
5
- import { FormInput } from "../../atoms/form-layouts";
6
- import ButtonWithAction from "../../atoms/button-with-action";
7
- import Checkbox from "../../atoms/checkbox";
8
- import { GHOST_GREY, WHITE } from "../../../constants/colors";
9
- import { Text } from "../../atoms";
10
- import DropdownIconV2 from "../../atoms/dropdown/DropdownIconV2";
11
- import { FONT_WEIGHT_REGULAR } from "../../../constants/style_constants";
4
+ import { Box } from "../../atoms/layouts";
5
+ import { GHOST_GREY, WHITE, CHARADE_GREY } from "../../../constants/colors";
12
6
  import { noop } from "../../../util/general";
13
- import {
14
- FilterContainer,
15
- FilterButton,
16
- FilterDropdown
17
- } from "./MultipleSelectFilter.styled";
18
-
19
- const ScrollableOptionsList = ({
20
- id,
21
- optionsList,
22
- selectedOptions,
23
- themeValues,
24
- selectOption,
25
- maxSelections,
26
- name
27
- }) => {
28
- const [focusedIndex, setFocusedIndex] = useState(-1);
29
- const checkboxRefs = useRef([]);
30
- const isMaxSelectionReached =
31
- maxSelections && maxSelections === selectedOptions?.length;
32
- const isChecked = option =>
33
- selectedOptions?.some(
34
- selectedOption => selectedOption?.name === option?.name
35
- );
36
-
37
- useEffect(() => {
38
- if (
39
- focusedIndex !== -1 &&
40
- checkboxRefs.current &&
41
- checkboxRefs.current[focusedIndex]
42
- ) {
43
- checkboxRefs.current[focusedIndex].focus(); // move focus to the active option
44
- }
45
- }, [focusedIndex]);
46
-
47
- const handleKeyDown = event => {
48
- if (event.key === "ArrowDown") {
49
- event.preventDefault();
50
- setFocusedIndex(prevIndex =>
51
- prevIndex < optionsList.length - 1 ? prevIndex + 1 : 0
52
- );
53
- } else if (event.key === "ArrowUp") {
54
- event.preventDefault();
55
- setFocusedIndex(prevIndex =>
56
- prevIndex > 0 ? prevIndex - 1 : optionsList.length - 1
57
- );
58
- } else if (event.key === " ") {
59
- event.preventDefault();
60
- // Select option on spacebar press if the maximum selection hasn't been reached.
61
- const validFocusedIndex = focusedIndex < 0 ? 0 : focusedIndex;
62
- if (
63
- !isMaxSelectionReached ||
64
- (focusedIndex !== -1 && isChecked(optionsList[validFocusedIndex]))
65
- ) {
66
- selectOption(optionsList[validFocusedIndex]);
67
- }
68
- } else if (event.key === "Tab") {
69
- // Reset focus when tabbing out of the list.
70
- setTimeout(() => {
71
- setFocusedIndex(-1);
72
- }, 500);
73
- }
74
- };
75
-
76
- return (
77
- <Box
78
- id={id}
79
- role="listbox"
80
- padding="0"
81
- extraStyles={`
82
- overflow-y: auto;
83
- max-height: 250px;
84
- display: flex;
85
- flex-flow: column;
86
- `}
87
- onKeyDown={handleKeyDown}
88
- >
89
- {optionsList.map((option, index) => {
90
- const checked = isChecked(option);
91
- const isDisabled = isMaxSelectionReached && !checked;
92
- const tabIndex =
93
- index === focusedIndex || (index === 0 && focusedIndex === -1)
94
- ? "0"
95
- : "-1";
96
- return (
97
- <Box
98
- padding="0"
99
- key={index}
100
- extraStyles={`
101
- :hover,
102
- :active,
103
- :focus {
104
- background-color: ${themeValues.primaryColor};
105
- }
106
- `}
107
- >
108
- <Checkbox
109
- ref={el => (checkboxRefs.current[index] = el)}
110
- title={option.name}
111
- name={option.name}
112
- checked={checked}
113
- onChange={() => (isDisabled ? noop : selectOption(option))}
114
- textExtraStyles={`font-size: 0.875rem; margin: 0;`}
115
- disabled={isDisabled}
116
- extraStyles={`
117
- padding: 0.075rem 0.325rem;
118
- margin: 0;
119
- :hover,
120
- :active,
121
- :focus {
122
- background-color: ${themeValues.primaryColor};
123
- }
124
- `}
125
- checkboxMargin="0.3rem"
126
- role="option"
127
- checkboxExtraStyles={`
128
- width: 1.375rem;
129
- height: 1.375rem;
130
- ${
131
- checked && !isDisabled
132
- ? `background: ` + themeValues.secondaryColor + `;`
133
- : ""
134
- }`}
135
- tabIndex={tabIndex}
136
- dataQa={`${name}-option-${index}`}
137
- />
138
- </Box>
139
- );
140
- })}
141
- </Box>
142
- );
143
- };
7
+ import { FilterContainer } from "./MultipleSelectFilter.styled";
8
+ import ActionLinkButton from "./__private__/ActionLinkButton";
9
+ import FilterButton from "./__private__/FilterButton";
10
+ import FilterDropdown from "./__private__/FilterDropdown";
11
+ import SearchBox from "./__private__/SearchBox";
12
+ import FilterableList from "./__private__/FilterableList";
13
+ import useOutsideClickHook from "../../../hooks/use-outside-click";
144
14
 
145
15
  const MultipleSelectFilter = ({
146
16
  actions,
@@ -164,53 +34,27 @@ const MultipleSelectFilter = ({
164
34
  themeValues,
165
35
  truncateBtnTextWidth = "15rem"
166
36
  }) => {
167
- const [itemList, setItemList] = useState([]);
168
37
  const [opened, setOpened] = useState(false);
169
- const containerRef = useRef(null);
38
+ const [appliedOptions, setAppliedOptions] = useState([]);
39
+
40
+ const handleClickOutsideContainer = () => {
41
+ setOpened(false);
42
+ actions.fields.searchTerm.set("");
43
+ onApply(selectedOptions);
44
+ };
45
+ const containerRef = useOutsideClickHook(() => handleClickOutsideContainer());
170
46
  const dropdownRef = useRef(null);
171
47
  const filterButtonRef = useRef(null);
172
48
  const applyFilterButtonRef = useRef(null);
173
49
  const filterDropdownID = `${name}-filter-dropdown`;
174
50
  const checkboxListID = `${name}-checkbox-list`;
175
51
 
176
- const backgroundColor = opened
177
- ? themeValues.primaryColor
178
- : selectedOptions?.length
179
- ? themeValues.secondaryColor
180
- : WHITE;
181
- const contentColor = !opened && selectedOptions?.length ? WHITE : "#292A33";
182
-
183
- const completeOptionsList = itemList
184
- .slice()
185
- .sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()));
186
- const selectValues = items => items.map(item => item.value);
187
- const selectOption = selectedOption => {
188
- if (selectValues(selectedOptions).includes(selectedOption.value)) {
189
- const fewerOptions = selectedOptions.filter(
190
- option => option.value !== selectedOption.value
191
- );
192
- setSelectedOptions(fewerOptions);
193
- } else {
194
- const moreOptions = selectedOptions.concat(selectedOption);
195
- setSelectedOptions(moreOptions);
196
- }
197
- };
198
-
199
- useEffect(() => setItemList(options), [options]);
200
-
201
52
  useEffect(() => {
202
- const filteredItems = options.filter(item =>
203
- item?.name
204
- ?.toLowerCase()
205
- .includes(fields?.searchTerm?.rawValue?.toLowerCase())
206
- );
207
- // If no items are filtered, display the entire list of options.
208
- if (filteredItems?.length) {
209
- setItemList(filteredItems);
210
- } else {
211
- setItemList(options);
53
+ if (!opened) {
54
+ onApply(selectedOptions);
55
+ setAppliedOptions(selectedOptions);
212
56
  }
213
- }, [fields.searchTerm.rawValue]);
57
+ }, [opened]);
214
58
 
215
59
  useEffect(() => {
216
60
  const handleKeyDown = event => {
@@ -238,22 +82,8 @@ const MultipleSelectFilter = ({
238
82
  onApply(selectedOptions);
239
83
  }
240
84
  };
241
- const handleClickOutside = event => {
242
- if (
243
- containerRef.current &&
244
- !containerRef.current.contains(event.target) &&
245
- dropdownRef.current &&
246
- !dropdownRef.current.contains(event.target)
247
- ) {
248
- setOpened(false);
249
- actions.fields.searchTerm.set("");
250
- onApply(selectedOptions);
251
- }
252
- };
253
- document.addEventListener("mousedown", handleClickOutside);
254
85
  document.addEventListener("keydown", handleKeyDown);
255
86
  return () => {
256
- document.addEventListener("mousedown", handleClickOutside);
257
87
  document.removeEventListener("keydown", handleKeyDown);
258
88
  };
259
89
  }, []);
@@ -262,101 +92,53 @@ const MultipleSelectFilter = ({
262
92
  <FilterContainer ref={containerRef} extraStyles={`${extraStyles}`}>
263
93
  <FilterButton
264
94
  ref={filterButtonRef}
265
- variant="tertiary"
95
+ btnContentOverride={btnContentOverride}
266
96
  action={() => {
267
97
  actions.fields.searchTerm.set("");
268
98
  setOpened(!opened);
269
99
  }}
270
- aria-haspopup="listbox"
271
- aria-expanded={opened}
272
- aria-controls={filterDropdownID}
273
- backgroundColor={backgroundColor}
274
- dataQa={`${name}-filter-button`}
275
- contentOverride
276
- >
277
- {btnContentOverride ? (
278
- btnContentOverride
279
- ) : (
280
- <Center
281
- as="span"
282
- style={{ display: "flex", flexDirection: "row" }}
283
- intrinsic
284
- >
285
- {hasIcon && <Icon color={contentColor} />}
286
- <Center
287
- as="span"
288
- style={{
289
- display: "flex",
290
- flexDirection: "row",
291
- padding: "0 0.5rem 0 0.25rem"
292
- }}
293
- intrinsic
294
- >
295
- <Text
296
- variant="pS"
297
- color={contentColor}
298
- extraStyles={`
299
- white-space: nowrap;
300
- overflow: hidden;
301
- text-overflow: ellipsis;
302
- ${truncateBtnTextWidth && `max-width:` + truncateBtnTextWidth}
303
- `}
304
- >
305
- {selectedOptions?.length
306
- ? `${filterLabel ? filterLabel + ": " : ""}${
307
- selectedOptions[0].name
308
- }`
309
- : `${filterLabel ? filterLabel : ""}`}
310
- </Text>
311
- <Text color={contentColor} variant="pS">
312
- {selectedOptions?.length && selectedOptions?.length > 1
313
- ? `, +${selectedOptions?.length - 1} More`
314
- : ""}
315
- </Text>
316
- </Center>
317
- <DropdownIconV2 color={contentColor} />
318
- </Center>
319
- )}
320
- </FilterButton>
100
+ opened={opened}
101
+ backgroundColor={
102
+ opened
103
+ ? themeValues.primaryColor
104
+ : selectedOptions?.length
105
+ ? themeValues.secondaryColor
106
+ : WHITE
107
+ }
108
+ contentColor={!opened && selectedOptions?.length ? WHITE : CHARADE_GREY}
109
+ name={name}
110
+ filterDropdownID={filterDropdownID}
111
+ hasIcon={hasIcon}
112
+ icon={Icon}
113
+ truncateBtnTextWidth={truncateBtnTextWidth}
114
+ filterLabel={filterLabel}
115
+ selectedOptions={selectedOptions}
116
+ ></FilterButton>
321
117
  <FilterDropdown
322
118
  id={filterDropdownID}
323
119
  ref={dropdownRef}
324
- hidden={!opened}
325
- role="combobox"
326
- aria-expanded={opened}
327
- aria-haspopup="listbox"
328
- aria-owns={checkboxListID}
120
+ ariaOwns={checkboxListID}
121
+ opened={opened}
329
122
  >
330
- <Box padding="0 0 0.5rem">
331
- {searchable && options?.length > 8 && (
332
- <FormInput
333
- autocompleteValue={autocompleteValue}
334
- showFieldErrorRow={false}
335
- errorMessages={{}}
336
- field={fields.searchTerm}
337
- fieldActions={actions.fields.searchTerm}
338
- placeholder={placeholder}
339
- disabled={disabled}
340
- extraStyles={`
341
- height: 2.875rem;
342
- border: 0;
343
- border-radius: 0;
344
- padding: 0.45rem;
345
- font-size: 0.875rem;
346
- border-bottom: 1px solid ${GHOST_GREY};
347
- `}
348
- />
349
- )}
350
- </Box>
351
- <ScrollableOptionsList
123
+ <SearchBox
124
+ showSearchBox={searchable && options?.length > 8}
125
+ autocompleteValue={autocompleteValue}
126
+ fields={fields}
127
+ actions={actions}
128
+ placeholder={placeholder}
129
+ disabled={disabled}
130
+ ></SearchBox>
131
+ <FilterableList
352
132
  id={checkboxListID}
353
- optionsList={completeOptionsList}
354
- selectedOptions={selectedOptions}
133
+ options={options}
134
+ appliedOptions={appliedOptions}
355
135
  themeValues={themeValues}
356
- selectOption={selectOption}
136
+ selectedOptions={selectedOptions}
357
137
  maxSelections={maxSelections}
358
138
  name={name}
359
- ></ScrollableOptionsList>
139
+ setSelectedOptions={setSelectedOptions}
140
+ searchTerm={fields?.searchTerm}
141
+ ></FilterableList>
360
142
  <Box
361
143
  padding="0 0.5rem 0.0625rem 0.5rem"
362
144
  extraStyles={`
@@ -367,42 +149,26 @@ const MultipleSelectFilter = ({
367
149
  border-top: 1px solid ${GHOST_GREY};
368
150
  `}
369
151
  >
370
- <ButtonWithAction
152
+ <ActionLinkButton
371
153
  action={() => {
372
154
  setOpened(false);
373
155
  setSelectedOptions([]);
374
156
  actions.fields.searchTerm.set("");
375
157
  onClear();
376
158
  }}
377
- variant="tertiary"
378
- extraStyles={`
379
- padding: 0.2rem;
380
- margin: 0.5rem;
381
- min-height: auto;
382
- min-width: auto;
383
- `}
384
- textExtraStyles={`font-weight: ${FONT_WEIGHT_REGULAR};`}
385
159
  text="Clear"
386
160
  dataQa={`${name}-clear-filters`}
387
- ></ButtonWithAction>
388
- <ButtonWithAction
161
+ ></ActionLinkButton>
162
+ <ActionLinkButton
389
163
  ref={applyFilterButtonRef}
390
164
  action={() => {
391
165
  setOpened(false);
392
166
  actions.fields.searchTerm.set("");
393
167
  onApply(selectedOptions);
394
168
  }}
395
- variant="tertiary"
396
- extraStyles={`
397
- padding: 0.2rem;
398
- margin: 0.5rem;
399
- min-height: auto;
400
- min-width: auto;
401
- `}
402
- textExtraStyles={`font-weight: ${FONT_WEIGHT_REGULAR};`}
403
169
  text="Apply"
404
170
  dataQa={`${name}-apply-filters`}
405
- ></ButtonWithAction>
171
+ ></ActionLinkButton>
406
172
  </Box>
407
173
  </FilterDropdown>
408
174
  </FilterContainer>
@@ -41,7 +41,7 @@ const items = [
41
41
  ];
42
42
 
43
43
  const FormWrapper = props => {
44
- const [selectedItems, setSelectedItems] = useState(props.selectedItems || []);
44
+ const [selectedItems, setSelectedItems] = useState([]);
45
45
 
46
46
  return (
47
47
  <MultipleSelectFilter
@@ -28,11 +28,11 @@ const StyledFilterDropdown = styled(Box)`
28
28
  max-width: 18.625rem;
29
29
  `;
30
30
 
31
- export const FilterDropdown = forwardRef((props, ref) => (
31
+ export const FilterDropdownContainer = forwardRef((props, ref) => (
32
32
  <StyledFilterDropdown ref={ref} {...props} />
33
33
  ));
34
34
 
35
- const StyledFilterButton = styled(ButtonWithAction)`
35
+ const FilterButton = styled(ButtonWithAction)`
36
36
  min-width: auto;
37
37
  min-height: 2.3125rem;
38
38
  margin: 0;
@@ -52,6 +52,6 @@ const StyledFilterButton = styled(ButtonWithAction)`
52
52
  `}
53
53
  `;
54
54
 
55
- export const FilterButton = forwardRef((props, ref) => (
56
- <StyledFilterButton ref={ref} {...props} />
55
+ export const StyledFilterButton = forwardRef((props, ref) => (
56
+ <FilterButton ref={ref} {...props} />
57
57
  ));
@@ -0,0 +1,24 @@
1
+ import React, { forwardRef } from "react";
2
+ import { ButtonWithAction } from "../../../atoms";
3
+ import { FONT_WEIGHT_REGULAR } from "../../../../constants/style_constants";
4
+
5
+ const ActionLinkButton = forwardRef(({ action, text, dataQa }, ref) => {
6
+ return (
7
+ <ButtonWithAction
8
+ ref={ref}
9
+ action={action}
10
+ variant="tertiary"
11
+ extraStyles={`
12
+ padding: 0.2rem;
13
+ margin: 0.5rem;
14
+ min-height: auto;
15
+ min-width: auto;
16
+ `}
17
+ textExtraStyles={`font-weight: ${FONT_WEIGHT_REGULAR};`}
18
+ text={text}
19
+ dataQa={dataQa}
20
+ ></ButtonWithAction>
21
+ );
22
+ });
23
+
24
+ export default ActionLinkButton;
@@ -0,0 +1,85 @@
1
+ import React, { forwardRef } from "react";
2
+ import { Text, Center } from "../../../atoms";
3
+ import DropdownIconV2 from "../../../atoms/dropdown/DropdownIconV2";
4
+ import { StyledFilterButton } from "../MultipleSelectFilter.styled";
5
+ import { noop } from "../../../../util/general";
6
+
7
+ const FilterButton = forwardRef(
8
+ (
9
+ {
10
+ btnContentOverride,
11
+ action = noop,
12
+ opened,
13
+ backgroundColor,
14
+ contentColor,
15
+ name,
16
+ filterDropdownID,
17
+ hasIcon = false,
18
+ icon: Icon,
19
+ truncateBtnTextWidth,
20
+ filterLabel,
21
+ selectedOptions
22
+ },
23
+ ref
24
+ ) => {
25
+ return (
26
+ <StyledFilterButton
27
+ ref={ref}
28
+ variant="tertiary"
29
+ action={action}
30
+ aria-haspopup="listbox"
31
+ aria-expanded={opened}
32
+ aria-controls={filterDropdownID}
33
+ backgroundColor={backgroundColor}
34
+ dataQa={`${name}-filter-button`}
35
+ contentOverride
36
+ >
37
+ {btnContentOverride ? (
38
+ btnContentOverride
39
+ ) : (
40
+ <Center
41
+ as="span"
42
+ style={{ display: "flex", flexDirection: "row" }}
43
+ intrinsic
44
+ >
45
+ {hasIcon && <Icon color={contentColor} />}
46
+ <Center
47
+ as="span"
48
+ style={{
49
+ display: "flex",
50
+ flexDirection: "row",
51
+ padding: "0 0.5rem 0 0.25rem"
52
+ }}
53
+ intrinsic
54
+ >
55
+ <Text
56
+ variant="pS"
57
+ color={contentColor}
58
+ extraStyles={`
59
+ white-space: nowrap;
60
+ overflow: hidden;
61
+ text-overflow: ellipsis;
62
+ ${truncateBtnTextWidth && `max-width:` + truncateBtnTextWidth}
63
+ `}
64
+ >
65
+ {selectedOptions?.length
66
+ ? `${filterLabel ? filterLabel + ": " : ""}${
67
+ selectedOptions[0].name
68
+ }`
69
+ : `${filterLabel ? filterLabel : ""}`}
70
+ </Text>
71
+ <Text color={contentColor} variant="pS">
72
+ {selectedOptions?.length && selectedOptions?.length > 1
73
+ ? `, +${selectedOptions?.length - 1} More`
74
+ : ""}
75
+ </Text>
76
+ </Center>
77
+ <DropdownIconV2 color={contentColor} />
78
+ </Center>
79
+ )}
80
+ </StyledFilterButton>
81
+ );
82
+ }
83
+ );
84
+
85
+ export default FilterButton;
@@ -0,0 +1,23 @@
1
+ import React, { forwardRef } from "react";
2
+ import { FilterDropdownContainer } from "../MultipleSelectFilter.styled";
3
+
4
+ const FilterDropdown = forwardRef(({ id, ariaOwns, opened, children }, ref) => {
5
+ return (
6
+ <>
7
+ {opened && (
8
+ <FilterDropdownContainer
9
+ ref={ref}
10
+ id={id}
11
+ role="combobox"
12
+ aria-expanded={opened}
13
+ aria-haspopup="listbox"
14
+ aria-owns={ariaOwns}
15
+ >
16
+ {children}
17
+ </FilterDropdownContainer>
18
+ )}
19
+ </>
20
+ );
21
+ });
22
+
23
+ export default FilterDropdown;