@saleor/macaw-ui 0.4.0 → 0.5.2

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 (264) hide show
  1. package/dist/ActionBar/ActionBar.d.ts +8 -0
  2. package/dist/ActionBar/ActionBar.stories.d.ts +4 -0
  3. package/dist/ActionBar/context.d.ts +9 -0
  4. package/dist/ActionBar/index.d.ts +2 -0
  5. package/dist/ActionBar/styles.d.ts +2 -0
  6. package/dist/Alert/Alert.d.ts +8 -0
  7. package/dist/Alert/Alert.stories.d.ts +12 -0
  8. package/dist/Alert/AlertBase.d.ts +8 -0
  9. package/dist/Alert/index.d.ts +2 -0
  10. package/dist/Alert/styles.d.ts +2 -0
  11. package/dist/Backlink/Backlink.d.ts +8 -0
  12. package/dist/Backlink/Backlink.stories.d.ts +5 -0
  13. package/dist/Backlink/context.d.ts +5 -0
  14. package/dist/Backlink/index.d.ts +2 -0
  15. package/dist/Backlink/styles.d.ts +2 -0
  16. package/dist/BaseList/BaseList.d.ts +26 -0
  17. package/dist/BaseList/context.d.ts +7 -0
  18. package/dist/BaseList/index.d.ts +1 -0
  19. package/dist/BaseList/styles.d.ts +5 -0
  20. package/dist/Button/Button.d.ts +16 -0
  21. package/dist/Button/index.d.ts +1 -0
  22. package/dist/Button/styles.d.ts +2 -0
  23. package/dist/ConfirmButton/ConfirmButton.d.ts +11 -0
  24. package/dist/ConfirmButton/ConfirmButton.stories.d.ts +8 -0
  25. package/dist/ConfirmButton/index.d.ts +1 -0
  26. package/dist/ConfirmButton/styles.d.ts +2 -0
  27. package/dist/DialogHeader/DialogHeader.d.ts +6 -0
  28. package/dist/DialogHeader/index.d.ts +1 -0
  29. package/dist/DialogHeader/styles.d.ts +1 -0
  30. package/dist/DialogTable/DialogTable.d.ts +6 -0
  31. package/dist/DialogTable/index.d.ts +1 -0
  32. package/dist/DialogTable/styles.d.ts +1 -0
  33. package/dist/Filter/Filter.d.ts +10 -0
  34. package/dist/Filter/Filter.stories.d.ts +5 -0
  35. package/dist/Filter/FilterBar.d.ts +11 -0
  36. package/dist/Filter/FilterContent.d.ts +7 -0
  37. package/dist/Filter/FilterField/MultipleSelectFilterField.d.ts +6 -0
  38. package/dist/Filter/FilterField/RangeFilterField.d.ts +7 -0
  39. package/dist/Filter/FilterField/SelectFilterField.d.ts +6 -0
  40. package/dist/Filter/FilterField/TextFilterField.d.ts +6 -0
  41. package/dist/Filter/FilterMenu.d.ts +9 -0
  42. package/dist/Filter/context.d.ts +4 -0
  43. package/dist/Filter/index.d.ts +4 -0
  44. package/dist/Filter/styles.d.ts +2 -0
  45. package/dist/Filter/types.d.ts +49 -0
  46. package/dist/Filter/utils.d.ts +8 -0
  47. package/dist/IconButton/IconButton.d.ts +8 -0
  48. package/dist/IconButton/index.d.ts +1 -0
  49. package/dist/IconButton/partials.d.ts +14 -0
  50. package/dist/IconButton/styles.d.ts +2 -0
  51. package/dist/LayoutButton/LayoutButton.d.ts +7 -0
  52. package/dist/LayoutButton/index.d.ts +1 -0
  53. package/dist/LayoutButton/styles.d.ts +2 -0
  54. package/dist/List/List.d.ts +13 -0
  55. package/dist/List/List.stories.d.ts +5 -0
  56. package/dist/List/context.d.ts +8 -0
  57. package/dist/List/index.d.ts +1 -0
  58. package/dist/List/styles.d.ts +1 -0
  59. package/dist/Notification/Notification.d.ts +3 -0
  60. package/dist/Notification/Notification.stories.d.ts +10 -0
  61. package/dist/Notification/index.d.ts +2 -0
  62. package/dist/Notification/styles.d.ts +2 -0
  63. package/dist/Notification/types.d.ts +16 -0
  64. package/dist/OffsettedList/OffsettedList.d.ts +12 -0
  65. package/dist/OffsettedList/OffsettedList.stories.d.ts +5 -0
  66. package/dist/OffsettedList/index.d.ts +1 -0
  67. package/dist/OffsettedList/styles.d.ts +2 -0
  68. package/dist/PageTabs/PageTab.d.ts +3 -0
  69. package/dist/PageTabs/PageTab.stories.d.ts +4 -0
  70. package/dist/PageTabs/PageTabPanel.d.ts +4 -0
  71. package/dist/PageTabs/PageTabs.d.ts +5 -0
  72. package/dist/PageTabs/index.d.ts +3 -0
  73. package/dist/PageTabs/styles.d.ts +2 -0
  74. package/dist/Pagination/Pagination.d.ts +10 -0
  75. package/dist/Pagination/PaginationActions.d.ts +11 -0
  76. package/dist/Pagination/PaginationRowNumberSelect.d.ts +11 -0
  77. package/dist/Pagination/TablePagination.d.ts +6 -0
  78. package/dist/Pagination/index.d.ts +4 -0
  79. package/dist/Pagination/styles.d.ts +2 -0
  80. package/dist/PillLink/PillLink.d.ts +15 -0
  81. package/dist/PillLink/index.d.ts +1 -0
  82. package/dist/PillLink/styles.d.ts +2 -0
  83. package/dist/ResponsiveTable/ResponsiveTable.d.ts +8 -0
  84. package/dist/ResponsiveTable/index.d.ts +1 -0
  85. package/dist/ResponsiveTable/styles.d.ts +2 -0
  86. package/dist/Savebar/ButtonTooltipDecorator.d.ts +6 -0
  87. package/dist/Savebar/Savebar.d.ts +14 -0
  88. package/dist/Savebar/Savebar.stories.d.ts +6 -0
  89. package/dist/Savebar/index.d.ts +1 -0
  90. package/dist/Savebar/styles.d.ts +2 -0
  91. package/dist/ScrollShadow/ScrollShadow.d.ts +6 -0
  92. package/dist/ScrollShadow/index.d.ts +1 -0
  93. package/dist/ScrollShadow/styles.d.ts +1 -0
  94. package/dist/Sidebar/ExpandButton.d.ts +6 -0
  95. package/dist/Sidebar/MenuItem.d.ts +11 -0
  96. package/dist/Sidebar/Sidebar.d.ts +6 -0
  97. package/dist/Sidebar/Sidebar.stories.d.ts +6 -0
  98. package/dist/Sidebar/fixtures.d.ts +2 -0
  99. package/dist/Sidebar/index.d.ts +4 -0
  100. package/dist/Sidebar/types.d.ts +16 -0
  101. package/dist/SidebarDrawer/MenuItemBtn.d.ts +7 -0
  102. package/dist/SidebarDrawer/SidebarDrawer.d.ts +4 -0
  103. package/dist/SidebarDrawer/SidebarDrawer.stories.d.ts +4 -0
  104. package/dist/SidebarDrawer/index.d.ts +2 -0
  105. package/dist/SidebarDrawer/styles.d.ts +2 -0
  106. package/dist/SquareButton/SquareButton.d.ts +3 -0
  107. package/dist/SquareButton/SquareButton.stories.d.ts +5 -0
  108. package/dist/SquareButton/index.d.ts +1 -0
  109. package/dist/StatusChip/StatusChip.d.ts +3 -0
  110. package/dist/StatusChip/StatusChip.stories.d.ts +8 -0
  111. package/dist/StatusChip/index.d.ts +2 -0
  112. package/dist/StatusChip/styles.d.ts +3 -0
  113. package/dist/StatusChip/types.d.ts +8 -0
  114. package/dist/Tooltip/Tooltip.d.ts +6 -0
  115. package/dist/Tooltip/Tooltip.stories.d.ts +7 -0
  116. package/dist/Tooltip/index.d.ts +1 -0
  117. package/dist/Tooltip/styles.d.ts +3 -0
  118. package/dist/UserChipMenu/UserChipMenu.d.ts +9 -0
  119. package/dist/UserChipMenu/UserChipMenu.stories.d.ts +6 -0
  120. package/dist/UserChipMenu/UserChipMenuItem.d.ts +6 -0
  121. package/dist/UserChipMenu/context.d.ts +4 -0
  122. package/dist/UserChipMenu/index.d.ts +2 -0
  123. package/dist/UserChipMenu/styles.d.ts +2 -0
  124. package/dist/cjs/index.js +2 -2
  125. package/dist/cjs/index.js.map +3 -3
  126. package/dist/esm/index.js +2 -2
  127. package/dist/esm/index.js.map +3 -3
  128. package/dist/extensions/index.d.ts +3 -0
  129. package/dist/extensions/sendMessage.d.ts +3 -0
  130. package/dist/extensions/types.d.ts +22 -0
  131. package/dist/extensions/useExtensionMessage.d.ts +2 -0
  132. package/dist/icons/ArrowDropdownIcon.d.ts +2 -0
  133. package/dist/icons/ArrowRightIcon.d.ts +1 -0
  134. package/dist/icons/CheckboxCheckedIcon.d.ts +1 -0
  135. package/dist/icons/CheckboxIcon.d.ts +1 -0
  136. package/dist/icons/CheckboxIndeterminateIcon.d.ts +1 -0
  137. package/dist/icons/CloseIcon.d.ts +1 -0
  138. package/dist/icons/CompleteIcon.d.ts +2 -0
  139. package/dist/icons/DeleteIcon.d.ts +1 -0
  140. package/dist/icons/EditIcon.d.ts +1 -0
  141. package/dist/icons/FilteringIcon.d.ts +1 -0
  142. package/dist/icons/ImageIcon.d.ts +1 -0
  143. package/dist/icons/InfoIcon.d.ts +2 -0
  144. package/dist/icons/Logo.d.ts +2 -0
  145. package/dist/icons/LogoLight.d.ts +2 -0
  146. package/dist/icons/MoreIcon.d.ts +1 -0
  147. package/dist/icons/NavigatorIcon.d.ts +1 -0
  148. package/dist/icons/NotAllowedIcon.d.ts +2 -0
  149. package/dist/icons/NotAllowedInvertedIcon.d.ts +2 -0
  150. package/dist/icons/PlusIcon.d.ts +1 -0
  151. package/dist/icons/RadioCheckedIcon.d.ts +1 -0
  152. package/dist/icons/RadioIcon.d.ts +1 -0
  153. package/dist/icons/SearchIcon.d.ts +1 -0
  154. package/dist/icons/WarningIcon.d.ts +2 -0
  155. package/dist/icons/index.d.ts +18 -0
  156. package/dist/index.d.ts +29 -0
  157. package/dist/index.js +2 -0
  158. package/dist/index.js.map +7 -0
  159. package/dist/localStorageKeys.d.ts +4 -0
  160. package/dist/mjs/index.js +5 -0
  161. package/dist/mjs/index.js.map +7 -0
  162. package/dist/theme/Baseline.d.ts +2 -0
  163. package/dist/theme/ThemeProvider.d.ts +17 -0
  164. package/dist/theme/context.d.ts +3 -0
  165. package/dist/theme/createSaleorTheme/createSaleorTheme.d.ts +3 -0
  166. package/dist/theme/createSaleorTheme/index.d.ts +2 -0
  167. package/dist/theme/createSaleorTheme/overrides/buttons.d.ts +3 -0
  168. package/dist/theme/createSaleorTheme/overrides/controls.d.ts +3 -0
  169. package/dist/theme/createSaleorTheme/overrides/index.d.ts +3 -0
  170. package/dist/theme/createSaleorTheme/overrides/inputs.d.ts +3 -0
  171. package/dist/theme/createSaleorTheme/overrides/tables.d.ts +3 -0
  172. package/dist/theme/createSaleorTheme/palette.d.ts +2 -0
  173. package/dist/theme/createSaleorTheme/shadows.d.ts +2 -0
  174. package/dist/theme/createSaleorTheme/types.d.ts +51 -0
  175. package/dist/theme/index.d.ts +4 -0
  176. package/dist/theme/styles.d.ts +5 -0
  177. package/dist/theme/themes.d.ts +3 -0
  178. package/dist/theme/types.d.ts +6 -0
  179. package/dist/theme/utils.d.ts +1 -0
  180. package/dist/theme/utils.test.d.ts +1 -0
  181. package/dist/tools/index.d.ts +2 -0
  182. package/dist/tools/useElementScroll.d.ts +12 -0
  183. package/dist/tools/useLocalStorage.d.ts +5 -0
  184. package/dist/tools/useWindowScroll.d.ts +4 -0
  185. package/dist/types/Autocomplete/Autocomplete.d.ts +23 -0
  186. package/dist/types/Autocomplete/Autocomplete.stories.d.ts +5 -0
  187. package/dist/types/Autocomplete/fixtures.d.ts +4 -0
  188. package/dist/types/Autocomplete/index.d.ts +1 -0
  189. package/dist/types/Autocomplete/styles.d.ts +2 -0
  190. package/dist/types/Backlink/Backlink.d.ts +6 -4
  191. package/dist/types/Filter/FilterField/AutocompleteFilterField.d.ts +6 -0
  192. package/dist/types/Filter/FilterField/MultipleValueAutocompleteFilterField.d.ts +6 -0
  193. package/dist/types/Filter/stories/Filter.stories.d.ts +5 -0
  194. package/dist/types/Filter/stories/FilterInteractive.stories.d.ts +4 -0
  195. package/dist/types/Filter/stories/labels.d.ts +8 -0
  196. package/dist/types/Filter/styles.d.ts +1 -1
  197. package/dist/types/Filter/types.d.ts +8 -2
  198. package/dist/types/Filter/utils.d.ts +4 -1
  199. package/dist/types/IconButton/IconButton.d.ts +44 -2
  200. package/dist/types/LayoutButton/LayoutButton.d.ts +29 -2
  201. package/dist/types/MultipleValueAutocomplete/MultipleValueAutocomplete.d.ts +26 -0
  202. package/dist/types/MultipleValueAutocomplete/MultipleValueAutocomplete.stories.d.ts +6 -0
  203. package/dist/types/MultipleValueAutocomplete/fixtures.d.ts +4 -0
  204. package/dist/types/MultipleValueAutocomplete/index.d.ts +1 -0
  205. package/dist/types/MultipleValueAutocomplete/styles.d.ts +2 -0
  206. package/dist/types/MultipleValueAutocomplete/useMultipleValueAutocomplete.d.ts +32 -0
  207. package/dist/types/StatusChip/styles.d.ts +3 -0
  208. package/dist/types/SwitchSelector/SwitchSelector.d.ts +2 -0
  209. package/dist/types/SwitchSelector/SwitchSelector.stories.d.ts +4 -0
  210. package/dist/types/SwitchSelector/SwitchSelectorButton.d.ts +8 -0
  211. package/dist/types/SwitchSelector/index.d.ts +2 -0
  212. package/dist/types/consts.d.ts +4 -0
  213. package/dist/types/index.d.ts +3 -0
  214. package/dist/types/tools/useTextWidth.d.ts +2 -0
  215. package/dist/types/utils/mergeRefs.d.ts +2 -0
  216. package/dist/types/utils/useMockAutocomplete.d.ts +10 -0
  217. package/dist/utils/Decorator.d.ts +4 -0
  218. package/dist/utils/useListStory.d.ts +21 -0
  219. package/package.json +10 -6
  220. package/src/Autocomplete/Autocomplete.stories.tsx +43 -0
  221. package/src/Autocomplete/Autocomplete.tsx +188 -0
  222. package/src/Autocomplete/fixtures.ts +122 -0
  223. package/src/Autocomplete/index.ts +1 -0
  224. package/src/Autocomplete/styles.ts +22 -0
  225. package/src/Backlink/Backlink.tsx +7 -7
  226. package/src/Backlink/styles.ts +1 -1
  227. package/src/Chip/styles.ts +2 -1
  228. package/src/Filter/Filter.tsx +88 -44
  229. package/src/Filter/FilterBar.tsx +15 -9
  230. package/src/Filter/FilterContent.tsx +8 -1
  231. package/src/Filter/FilterField/AutocompleteFilterField.tsx +61 -0
  232. package/src/Filter/FilterField/MultipleSelectFilterField.tsx +6 -2
  233. package/src/Filter/FilterField/MultipleValueAutocompleteFilterField.tsx +60 -0
  234. package/src/Filter/context.tsx +1 -1
  235. package/src/Filter/{Filter.stories.tsx → stories/Filter.stories.tsx} +47 -13
  236. package/src/Filter/stories/FilterInteractive.stories.tsx +97 -0
  237. package/src/Filter/stories/labels.ts +8 -0
  238. package/src/Filter/styles.ts +37 -6
  239. package/src/Filter/types.ts +8 -1
  240. package/src/Filter/utils.ts +71 -5
  241. package/src/IconButton/IconButton.tsx +29 -7
  242. package/src/LayoutButton/LayoutButton.tsx +39 -23
  243. package/src/MultipleValueAutocomplete/MultipleValueAutocomplete.stories.tsx +76 -0
  244. package/src/MultipleValueAutocomplete/MultipleValueAutocomplete.tsx +185 -0
  245. package/src/MultipleValueAutocomplete/fixtures.ts +122 -0
  246. package/src/MultipleValueAutocomplete/index.ts +1 -0
  247. package/src/MultipleValueAutocomplete/styles.ts +41 -0
  248. package/src/MultipleValueAutocomplete/useMultipleValueAutocomplete.ts +172 -0
  249. package/src/SwitchSelector/SwitchSelector.stories.tsx +63 -0
  250. package/src/SwitchSelector/SwitchSelector.tsx +20 -0
  251. package/src/SwitchSelector/SwitchSelectorButton.tsx +60 -0
  252. package/src/SwitchSelector/index.ts +2 -0
  253. package/src/consts.ts +4 -0
  254. package/src/index.tsx +3 -0
  255. package/src/theme/createSaleorTheme/createSaleorTheme.tsx +1 -1
  256. package/src/tools/useTextWidth.ts +20 -0
  257. package/src/utils/mergeRefs.ts +14 -0
  258. package/src/utils/useMockAutocomplete.ts +37 -0
  259. package/dist/types/Chip/ColorSwatch.d.ts +0 -6
  260. package/dist/types/Chip/common/ChipMovable.d.ts +0 -5
  261. package/dist/types/Chip/common/ChipRemovable.d.ts +0 -6
  262. package/dist/types/Chip/common/ChipSwatch.d.ts +0 -7
  263. package/dist/types/Chip/common/index.d.ts +0 -3
  264. package/src/Chip/.DS_Store +0 -0
@@ -1,11 +1,11 @@
1
- import Button from "@material-ui/core/Button";
2
1
  import Card from "@material-ui/core/Card";
3
2
  import CardContent from "@material-ui/core/CardContent";
4
3
  import CardHeader from "@material-ui/core/CardHeader";
5
- import IconButton from "@material-ui/core/IconButton";
6
- import Close from "@material-ui/icons/Close";
7
4
  import React from "react";
8
5
 
6
+ import { Button } from "../Button";
7
+ import { IconButton } from "../IconButton";
8
+ import { CloseIcon, PlusIcon } from "../icons";
9
9
  import { FilterContext } from "./context";
10
10
  import { FilterRow } from "./Filter";
11
11
  import { FilterMenu, FilterMenuLabels } from "./FilterMenu";
@@ -56,8 +56,10 @@ export const FilterBar: React.FC<FilterBarProps> = React.forwardRef(
56
56
  setFilterData((fd) => fd.filter((filter) => filter.name !== name));
57
57
  const set = (name: string, filter: Partial<FilterData>) =>
58
58
  setFilterData((fd) =>
59
- fd.map((f) => (f.name === name ? { ...f, filter } : f))
59
+ fd.map((f) => (f.name === name ? { ...f, ...filter } : f))
60
60
  );
61
+ const swap = (previousFilterName: string, nextFilterName: string) =>
62
+ setFilterData((fd) => utils.swap(fd, previousFilterName, nextFilterName));
61
63
 
62
64
  const availableFilters = utils.getAvailableFilters(filterData);
63
65
 
@@ -75,16 +77,17 @@ export const FilterBar: React.FC<FilterBarProps> = React.forwardRef(
75
77
  toggle,
76
78
  toggleRange,
77
79
  unregister,
80
+ swap,
78
81
  onChange,
79
82
  }}
80
83
  >
81
84
  {children}
82
- <Card className={classes.bar} ref={ref} elevation={20}>
85
+ <Card className={classes.bar} ref={ref} elevation={8}>
83
86
  <CardHeader
84
87
  title={labels.header}
85
88
  action={
86
- <IconButton onClick={onClose}>
87
- <Close />
89
+ <IconButton variant="secondary" onClick={onClose}>
90
+ <CloseIcon />
88
91
  </IconButton>
89
92
  }
90
93
  />
@@ -105,11 +108,14 @@ export const FilterBar: React.FC<FilterBarProps> = React.forwardRef(
105
108
  {!!availableFilters.length && (
106
109
  <>
107
110
  <Button
108
- color="primary"
111
+ className={classes.barAddBtn}
112
+ color="text"
113
+ variant="secondary"
109
114
  ref={button}
110
115
  onClick={() => setMenuOpen(true)}
111
116
  >
112
- + {labels.addButton}
117
+ {labels.addButton}
118
+ <PlusIcon />
113
119
  </Button>
114
120
  </>
115
121
  )}
@@ -1,6 +1,8 @@
1
1
  import React from "react";
2
2
 
3
+ import { AutocompleteFilterField } from "./FilterField/AutocompleteFilterField";
3
4
  import { MultipleSelectFilterField } from "./FilterField/MultipleSelectFilterField";
5
+ import { MultipleValueAutocompleteFilterField } from "./FilterField/MultipleValueAutocompleteFilterField";
4
6
  import { RangeFilterField } from "./FilterField/RangeFilterField";
5
7
  import { SelectFilterField } from "./FilterField/SelectFilterField";
6
8
  import { TextFilterField } from "./FilterField/TextFilterField";
@@ -18,7 +20,12 @@ export const FilterContent: React.FC<FilterContentProps> = ({
18
20
  const { options, range } = filter;
19
21
  const { type, multiple } = options;
20
22
 
21
- if (type === FilterType.Choice) {
23
+ if (type === FilterType.Autocomplete) {
24
+ if (multiple) {
25
+ return <MultipleValueAutocompleteFilterField filter={filter} />;
26
+ }
27
+ return <AutocompleteFilterField filter={filter} />;
28
+ } else if (type === FilterType.Choice) {
22
29
  if (multiple) {
23
30
  return <MultipleSelectFilterField filter={filter} />;
24
31
  }
@@ -0,0 +1,61 @@
1
+ import MenuItem from "@material-ui/core/MenuItem";
2
+ import React from "react";
3
+
4
+ import { SyntheticChangeEvent } from "../../../types/utils";
5
+ import { Autocomplete } from "../../Autocomplete/Autocomplete";
6
+ import { useFilters } from "../context";
7
+ import useStyles from "../styles";
8
+ import { FilterData } from "../types";
9
+
10
+ export interface FilterContentProps {
11
+ filter: FilterData;
12
+ }
13
+
14
+ export const AutocompleteFilterField: React.FC<FilterContentProps> = ({
15
+ filter,
16
+ }) => {
17
+ const classes = useStyles();
18
+ const { onChange } = useFilters();
19
+
20
+ const { name, options } = filter;
21
+ const { choices } = options;
22
+
23
+ if (options.choices === undefined) {
24
+ throw new Error("FilterType.Autocomplete must be used with choices prop");
25
+ }
26
+ if (options.onInputChange === undefined) {
27
+ throw new Error(
28
+ "FilterType.Autocomplete must be used with onInputChange prop"
29
+ );
30
+ }
31
+
32
+ const handleChoiceChange = (event: SyntheticChangeEvent) =>
33
+ onChange(name, event.target.value);
34
+
35
+ return (
36
+ <Autocomplete
37
+ className={classes.filterValue}
38
+ choices={options.choices!}
39
+ InputProps={{
40
+ classes: {
41
+ input: classes.filterInputInner,
42
+ },
43
+ }}
44
+ onChange={handleChoiceChange}
45
+ onInputChange={options.onInputChange}
46
+ value={filter.values}
47
+ >
48
+ {({ getItemProps, highlightedIndex }) =>
49
+ choices!.map((choice, choiceIndex) => (
50
+ <MenuItem
51
+ selected={highlightedIndex === choiceIndex}
52
+ {...getItemProps({ item: choice, index: choiceIndex })}
53
+ >
54
+ {choice.label}
55
+ </MenuItem>
56
+ ))
57
+ }
58
+ </Autocomplete>
59
+ );
60
+ };
61
+ AutocompleteFilterField.displayName = "AutocompleteFilterField";
@@ -18,6 +18,9 @@ export const MultipleSelectFilterField: React.FC<FilterContentProps> = ({
18
18
  }) => {
19
19
  const classes = useStyles();
20
20
  const { onChange } = useFilters();
21
+ const [displayValues] = React.useState(
22
+ filter.options.displayValues || filter.options.choices
23
+ );
21
24
 
22
25
  const { name, options } = filter;
23
26
  const { choices } = options;
@@ -29,7 +32,7 @@ export const MultipleSelectFilterField: React.FC<FilterContentProps> = ({
29
32
  <Select
30
33
  className={classes.filterValue}
31
34
  classes={{
32
- root: classes.filterInputInner,
35
+ root: classes.filterMultipleValueInputInner,
33
36
  }}
34
37
  multiple
35
38
  variant="outlined"
@@ -42,7 +45,8 @@ export const MultipleSelectFilterField: React.FC<FilterContentProps> = ({
42
45
  <div className={classes.filterChipContainer}>
43
46
  {typedValues.map((value) => (
44
47
  <Chip className={classes.filterChip} key={value}>
45
- {value}
48
+ {displayValues?.find((dv) => dv.value === value)?.label ??
49
+ value}
46
50
  </Chip>
47
51
  ))}
48
52
  </div>
@@ -0,0 +1,60 @@
1
+ import MenuItem from "@material-ui/core/MenuItem";
2
+ import React from "react";
3
+
4
+ import { SyntheticChangeEvent } from "../../../types/utils";
5
+ import { MultipleValueAutocomplete } from "../../MultipleValueAutocomplete";
6
+ import { useFilters } from "../context";
7
+ import useStyles from "../styles";
8
+ import { FilterData } from "../types";
9
+
10
+ export interface FilterContentProps {
11
+ filter: FilterData;
12
+ }
13
+
14
+ export const MultipleValueAutocompleteFilterField: React.FC<FilterContentProps> =
15
+ ({ filter }) => {
16
+ const classes = useStyles();
17
+ const { onChange } = useFilters();
18
+
19
+ const { name, options } = filter;
20
+
21
+ if (options.choices === undefined) {
22
+ throw new Error("FilterType.Autocomplete must be used with choices prop");
23
+ }
24
+ if (options.onInputChange === undefined) {
25
+ throw new Error(
26
+ "FilterType.Autocomplete must be used with onInputChange prop"
27
+ );
28
+ }
29
+
30
+ const handleChoiceChange = (event: SyntheticChangeEvent<string[]>) =>
31
+ onChange(name, event.target.value);
32
+
33
+ return (
34
+ <MultipleValueAutocomplete
35
+ className={classes.filterValue}
36
+ choices={options.choices!}
37
+ InputProps={{
38
+ classes: {
39
+ root: classes.filterMultipleValueInputInner,
40
+ },
41
+ }}
42
+ onChange={handleChoiceChange}
43
+ onInputChange={options.onInputChange}
44
+ value={filter.values}
45
+ >
46
+ {({ choices: filteredChoices, getItemProps, highlightedIndex }) =>
47
+ filteredChoices.map((choice, choiceIndex) => (
48
+ <MenuItem
49
+ selected={highlightedIndex === choiceIndex}
50
+ {...getItemProps({ item: choice, index: choiceIndex })}
51
+ >
52
+ {choice.label}
53
+ </MenuItem>
54
+ ))
55
+ }
56
+ </MultipleValueAutocomplete>
57
+ );
58
+ };
59
+ MultipleValueAutocompleteFilterField.displayName =
60
+ "MultipleValueAutocompleteFilterField";
@@ -5,7 +5,7 @@ import { FilterContextType } from "./types";
5
5
  export const FilterContext = createContext<FilterContextType | null>(null);
6
6
  export const useFilters = (): FilterContextType => {
7
7
  const ctx = useContext(FilterContext);
8
- if (ctx === undefined) {
8
+ if (!ctx) {
9
9
  throw new Error("useFilters must be used within a FilterContext");
10
10
  }
11
11
 
@@ -2,18 +2,10 @@ import { Meta, Story } from "@storybook/react";
2
2
  import { debounce } from "lodash";
3
3
  import React from "react";
4
4
 
5
- import { Filter } from "./Filter";
6
- import { FilterBar } from "./FilterBar";
7
- import { FilterType } from "./types";
8
-
9
- const labels = {
10
- addButton: "Add Filter",
11
- header: "Filters",
12
- where: "Where",
13
- and: "and",
14
- is: "is",
15
- range: "between",
16
- };
5
+ import { Filter } from "../Filter";
6
+ import { FilterBar } from "../FilterBar";
7
+ import { FilterType } from "../types";
8
+ import { labels } from "./labels";
17
9
 
18
10
  export const Default: Story = () => (
19
11
  <FilterBar
@@ -63,6 +55,11 @@ export const Default: Story = () => (
63
55
  />
64
56
  </FilterBar>
65
57
  );
58
+
59
+ const attributeGroup = {
60
+ label: "Attribute",
61
+ name: "attribute",
62
+ };
66
63
  export const WithInitialState: Story = () => (
67
64
  <FilterBar
68
65
  labels={labels}
@@ -78,6 +75,11 @@ export const WithInitialState: Story = () => (
78
75
  value: "no",
79
76
  values: null,
80
77
  },
78
+ {
79
+ name: "status",
80
+ values: ["published"],
81
+ value: null,
82
+ },
81
83
  ]}
82
84
  onClose={() => undefined}
83
85
  >
@@ -101,9 +103,41 @@ export const WithInitialState: Story = () => (
101
103
  { label: "Not Available", value: "no" },
102
104
  ]}
103
105
  />
106
+ <Filter
107
+ name="status"
108
+ label="Status"
109
+ type={FilterType.Choice}
110
+ default="scheduled"
111
+ choices={[
112
+ { label: "Published", value: "published" },
113
+ { label: "Scheduled for publishing", value: "scheduled" },
114
+ { label: "Not Published", value: "unpublished" },
115
+ ]}
116
+ multiple
117
+ />
118
+ <Filter
119
+ name="color"
120
+ label="Color"
121
+ group={attributeGroup}
122
+ type={FilterType.Choice}
123
+ choices={[
124
+ { label: "Green", value: "green" },
125
+ { label: "Red", value: "red" },
126
+ ]}
127
+ />
128
+ <Filter
129
+ name="size"
130
+ label="Size"
131
+ group={attributeGroup}
132
+ type={FilterType.Choice}
133
+ choices={[
134
+ { label: "XL", value: "xl" },
135
+ { label: "L", value: "l" },
136
+ ]}
137
+ />
104
138
  </FilterBar>
105
139
  );
106
140
 
107
141
  export default {
108
- title: "Filter",
142
+ title: "Filter / Dummy",
109
143
  } as Meta;
@@ -0,0 +1,97 @@
1
+ import { Meta, Story } from "@storybook/react";
2
+ import { debounce } from "lodash";
3
+ import React from "react";
4
+
5
+ import { useMockAutocomplete } from "../../utils/useMockAutocomplete";
6
+ import { Filter } from "../Filter";
7
+ import { FilterBar } from "../FilterBar";
8
+ import { FilterType } from "../types";
9
+ import { labels } from "./labels";
10
+
11
+ const choices = [
12
+ { label: "Awesome Chair", value: "awesome chair" },
13
+ { label: "Ergonomic Chair", value: "ergonomic chair" },
14
+ { label: "Fantastic Bacon", value: "fantastic bacon" },
15
+ { label: "Fantastic Gloves", value: "fantastic gloves" },
16
+ { label: "Fantastic Hat", value: "fantastic hat" },
17
+ { label: "Fantastic Pants", value: "fantastic pants" },
18
+ { label: "Generic Bacon", value: "generic bacon" },
19
+ { label: "Gorgeous Bacon", value: "gorgeous bacon" },
20
+ { label: "Handcrafted Chair", value: "handcrafted chair" },
21
+ { label: "Handmade Computer", value: "handmade computer" },
22
+ { label: "Handmade Pizza", value: "handmade pizza" },
23
+ { label: "Incredible Shirt", value: "incredible shirt" },
24
+ { label: "Incredible Soap", value: "incredible soap" },
25
+ { label: "Incredible Table", value: "incredible table" },
26
+ { label: "Intelligent Hat", value: "intelligent hat" },
27
+ { label: "Intelligent Mouse", value: "intelligent mouse" },
28
+ { label: "Intelligent Sausages", value: "intelligent sausages" },
29
+ { label: "Licensed Chair", value: "licensed chair" },
30
+ { label: "Practical Hat", value: "practical hat" },
31
+ { label: "Practical Shoes", value: "practical shoes" },
32
+ { label: "Refined Ball", value: "refined ball" },
33
+ { label: "Refined Table", value: "refined table" },
34
+ { label: "Rustic Cheese", value: "rustic cheese" },
35
+ { label: "Rustic Shoes", value: "rustic shoes" },
36
+ { label: "Sleek Car", value: "sleek car" },
37
+ { label: "Small Ball", value: "small ball" },
38
+ { label: "Small Bike", value: "small bike" },
39
+ { label: "Tasty Gloves", value: "tasty gloves" },
40
+ { label: "Tasty Table", value: "tasty table" },
41
+ { label: "Unbranded Gloves", value: "unbranded gloves" },
42
+ ];
43
+
44
+ export const Autocomplete: Story = () => {
45
+ const { results, search } = useMockAutocomplete(choices);
46
+
47
+ return (
48
+ <FilterBar
49
+ labels={labels}
50
+ onChange={debounce((fd) => console.log(fd), 1000)}
51
+ initial={[
52
+ {
53
+ name: "name",
54
+ value: "Lorem Ipsum",
55
+ values: null,
56
+ },
57
+ {
58
+ name: "product",
59
+ value: choices[0].value,
60
+ values: null,
61
+ },
62
+ ]}
63
+ onClose={() => undefined}
64
+ >
65
+ <Filter name="name" label="Name" type={FilterType.Text} />
66
+ <Filter
67
+ name="price"
68
+ label="Price"
69
+ type={FilterType.Range}
70
+ InputProps={{
71
+ InputProps: {
72
+ endAdornment: "USD",
73
+ },
74
+ }}
75
+ />
76
+ <Filter
77
+ name="product"
78
+ label="Product"
79
+ type={FilterType.Autocomplete}
80
+ choices={results}
81
+ onInputChange={search}
82
+ />
83
+ <Filter
84
+ name="references"
85
+ label="Product references"
86
+ type={FilterType.Autocomplete}
87
+ multiple
88
+ choices={results}
89
+ onInputChange={search}
90
+ />
91
+ </FilterBar>
92
+ );
93
+ };
94
+
95
+ export default {
96
+ title: "Filter / Interactive",
97
+ } as Meta;
@@ -0,0 +1,8 @@
1
+ export const labels = {
2
+ addButton: "Add Filter",
3
+ header: "Filters",
4
+ where: "Where",
5
+ and: "and",
6
+ is: "is",
7
+ range: "between",
8
+ };
@@ -14,11 +14,16 @@ const useStyles = makeStyles(
14
14
  },
15
15
 
16
16
  filter: {
17
- alignItems: "center",
17
+ alignItems: "flex-start",
18
18
  display: "flex",
19
19
  columnGap: theme.spacing(2),
20
20
  marginBottom: theme.spacing(2),
21
21
  },
22
+ filterOptions: {
23
+ alignItems: "center",
24
+ columnGap: theme.spacing(2),
25
+ display: "flex",
26
+ },
22
27
  filterChip: {
23
28
  borderRadius: 8,
24
29
  background: theme.palette.primary.main,
@@ -26,17 +31,30 @@ const useStyles = makeStyles(
26
31
  },
27
32
  filterChipContainer: {
28
33
  display: "flex",
29
- columnGap: theme.spacing(1),
34
+ flexWrap: "wrap",
35
+ gap: theme.spacing(1),
30
36
  },
31
- filterDelete: {
37
+ filterDeleteContainer: {
38
+ alignItems: "center",
39
+ columnGap: theme.spacing(2),
40
+ display: "flex",
41
+ height: 51,
32
42
  marginLeft: "auto",
33
43
  },
44
+ filterDelete: {
45
+ position: "relative",
46
+ left: 6,
47
+ },
34
48
  filterName: {
35
49
  width: 180,
36
50
  },
37
51
  filterValue: {
38
- height: 51,
39
- width: 400,
52
+ "& .MuiSelect-root": {
53
+ boxSizing: "border-box",
54
+ },
55
+ boxSizing: "border-box",
56
+ minHeight: 51,
57
+ width: "100%",
40
58
  },
41
59
  filterRange: {
42
60
  width: 115,
@@ -46,6 +64,13 @@ const useStyles = makeStyles(
46
64
  padding: theme.spacing(2),
47
65
  },
48
66
  },
67
+ filterMultipleValueInputInner: {
68
+ "&&": {
69
+ minHeight: 51,
70
+ padding: theme.spacing(1),
71
+ paddingRight: theme.spacing(8),
72
+ },
73
+ },
49
74
  filterConjunction: {
50
75
  minWidth: 80,
51
76
  },
@@ -65,7 +90,13 @@ const useStyles = makeStyles(
65
90
  },
66
91
 
67
92
  bar: {
68
- minWidth: 600,
93
+ minWidth: 100,
94
+ },
95
+ barAddBtn: {
96
+ "& svg": {
97
+ marginLeft: theme.spacing(1),
98
+ marginRight: 0,
99
+ },
69
100
  },
70
101
 
71
102
  selectPaper: {
@@ -4,14 +4,20 @@ export enum FilterType {
4
4
  Text,
5
5
  Choice,
6
6
  Range,
7
+ Autocomplete,
7
8
  }
8
9
 
10
+ export type Choice = Record<"label" | "value", string>;
11
+
9
12
  export interface FilterDetailedOptions {
10
13
  type: FilterType;
11
- choices?: Array<Record<"label" | "value", string>>;
14
+ choices?: Choice[];
12
15
  default?: string;
13
16
  multiple?: boolean;
14
17
  InputProps?: Partial<TextFieldProps>;
18
+ group?: Record<"label" | "name", string>;
19
+ displayValues?: Choice[];
20
+ onInputChange?: (value: string) => void;
15
21
  }
16
22
  export interface FilterOptions {
17
23
  name: string;
@@ -52,6 +58,7 @@ export interface FilterContextType {
52
58
  toggle: (name: string) => void;
53
59
  toggleRange: (name: string) => void;
54
60
  unregister: (name: string) => void;
61
+ swap: (previousFilterName: string, nextFilterName: string) => void;
55
62
  onChange: (
56
63
  name: string,
57
64
  value: string | string[],
@@ -1,4 +1,4 @@
1
- import { uniqBy } from "lodash";
1
+ import { sortBy, uniqBy } from "lodash";
2
2
 
3
3
  import {
4
4
  FilterData,
@@ -8,8 +8,36 @@ import {
8
8
  OnFilterChangeOpts,
9
9
  } from "./types";
10
10
 
11
- export function getAvailableFilters(filterData: FilterData[]) {
12
- return filterData.filter((filter) => !filter.active);
11
+ export function getFilterName(
12
+ name: string,
13
+ options: FilterDetailedOptions
14
+ ): string {
15
+ return options.group ? `${options.group.name}:${name}` : name;
16
+ }
17
+
18
+ export function getAvailableFilterGroups(
19
+ filterData: FilterData[]
20
+ ): Array<Record<"name" | "label", string>> {
21
+ return uniqBy(
22
+ filterData
23
+ .filter((filter) => !filter.active && filter.options.group)
24
+ .map((filter) => filter.options.group!),
25
+ "name"
26
+ );
27
+ }
28
+
29
+ export function getAvailableFilters(
30
+ filterData: FilterData[]
31
+ ): Array<Record<"name" | "label", string>> {
32
+ return sortBy(
33
+ [
34
+ ...filterData.filter(
35
+ (filter) => !(filter.active || filter.options.group)
36
+ ),
37
+ ...getAvailableFilterGroups(filterData),
38
+ ],
39
+ "label"
40
+ );
13
41
  }
14
42
  export function getActiveFilters(filterData: FilterData[]) {
15
43
  return filterData.filter((filter) => filter.active);
@@ -107,15 +135,29 @@ export function change(
107
135
  );
108
136
  }
109
137
 
138
+ function getFilterOrGroup(filterData: FilterData[], name: string): FilterData {
139
+ let selectedFilter = filterData.find((filter) => filter.name === name);
140
+
141
+ if (!selectedFilter) {
142
+ selectedFilter = filterData.find(
143
+ (filter) => !filter.active && filter.options.group?.name === name
144
+ )!;
145
+ }
146
+
147
+ return selectedFilter;
148
+ }
149
+
110
150
  export function toggle(filterData: FilterData[], name: string): FilterData[] {
111
- const selectedFilter = filterData.find((filter) => filter.name === name)!;
151
+ const selectedFilter = getFilterOrGroup(filterData, name);
152
+ const { name: filterName } = selectedFilter;
153
+
112
154
  const sortIndex = selectedFilter.active
113
155
  ? selectedFilter.sortIndex
114
156
  : getActiveFilters(filterData).length;
115
157
  const value = selectedFilter.active ? getDefaultValue(selectedFilter) : {};
116
158
 
117
159
  return filterData.map((filter) =>
118
- filter.name === name
160
+ filter.name === filterName
119
161
  ? {
120
162
  ...filter,
121
163
  active: !filter.active,
@@ -148,3 +190,27 @@ export function toggleRange(
148
190
  : filter
149
191
  );
150
192
  }
193
+
194
+ export function swap(
195
+ filterData: FilterData[],
196
+ previousFilterName: string,
197
+ nextFilterName: string
198
+ ): FilterData[] {
199
+ const previousFilter = getFilterOrGroup(filterData, previousFilterName);
200
+ const nextFilter = getFilterOrGroup(filterData, nextFilterName);
201
+
202
+ return filterData.map((filter) =>
203
+ filter.name === previousFilter.name
204
+ ? {
205
+ ...filter,
206
+ active: false,
207
+ }
208
+ : filter.name === nextFilter.name
209
+ ? {
210
+ ...filter,
211
+ active: true,
212
+ sortIndex: previousFilter.sortIndex,
213
+ }
214
+ : filter
215
+ );
216
+ }