@shopgate/engage 7.32.0-beta.14 → 7.32.0-beta.15
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/filter/components/FilterItem/index.js +9 -2
- package/filter/components/FilterPageContent/components/ApplyButton/index.d.ts +21 -0
- package/filter/components/FilterPageContent/components/ApplyButton/index.d.ts.map +1 -0
- package/filter/components/FilterPageContent/components/ApplyButton/index.js +25 -52
- package/filter/components/FilterPageContent/components/FilterButtonBar/index.d.ts +8 -0
- package/filter/components/FilterPageContent/components/FilterButtonBar/index.d.ts.map +1 -0
- package/filter/components/FilterPageContent/components/FilterButtonBar/index.js +63 -0
- package/filter/components/FilterPageContent/components/ResetButton/index.d.ts +17 -0
- package/filter/components/FilterPageContent/components/ResetButton/index.d.ts.map +1 -0
- package/filter/components/FilterPageContent/components/ResetButton/index.js +24 -46
- package/filter/components/FilterPageContent/components/Selector/components/Selected/index.d.ts +19 -0
- package/filter/components/FilterPageContent/components/Selector/components/Selected/index.d.ts.map +1 -0
- package/filter/components/FilterPageContent/components/Selector/components/Selected/index.js +25 -46
- package/filter/components/FilterPageContent/components/Selector/components/Toggle/index.d.ts +14 -0
- package/filter/components/FilterPageContent/components/Selector/components/Toggle/index.d.ts.map +1 -0
- package/filter/components/FilterPageContent/components/Selector/components/Toggle/index.js +13 -46
- package/filter/components/FilterPageContent/components/Selector/components/ValueCheckbox/index.d.ts +25 -0
- package/filter/components/FilterPageContent/components/Selector/components/ValueCheckbox/index.d.ts.map +1 -0
- package/filter/components/FilterPageContent/components/Selector/components/ValueCheckbox/index.js +77 -0
- package/filter/components/FilterPageContent/components/Selector/index.d.ts +43 -0
- package/filter/components/FilterPageContent/components/Selector/index.d.ts.map +1 -0
- package/filter/components/FilterPageContent/components/Selector/index.js +52 -40
- package/filter/components/FilterPageContent/index.d.ts +16 -0
- package/filter/components/FilterPageContent/index.d.ts.map +1 -0
- package/filter/components/FilterPageContent/index.js +51 -57
- package/filter/components/PriceSlider/components/Label/index.js +69 -94
- package/filter/components/PriceSlider/index.js +43 -33
- package/filter/helpers/buildFilterParamsForFetchFiltersRequest.d.ts +8 -0
- package/filter/helpers/buildFilterParamsForFetchFiltersRequest.d.ts.map +1 -0
- package/filter/helpers/buildInitialFilters.d.ts +7 -0
- package/filter/helpers/buildInitialFilters.d.ts.map +1 -0
- package/filter/helpers/buildUpdatedFilters.d.ts +7 -0
- package/filter/helpers/buildUpdatedFilters.d.ts.map +1 -0
- package/filter/helpers/index.d.ts +5 -0
- package/filter/helpers/index.d.ts.map +1 -0
- package/filter/helpers/translateFilterLabel.d.ts +8 -0
- package/filter/helpers/translateFilterLabel.d.ts.map +1 -0
- package/filter/providers/FilterPageProvider.context.d.ts +157 -0
- package/filter/providers/FilterPageProvider.context.d.ts.map +1 -0
- package/filter/providers/FilterPageProvider.d.ts +24 -0
- package/filter/providers/FilterPageProvider.d.ts.map +1 -0
- package/filter/providers/FilterPageProvider.js +77 -132
- package/locations/components/GlobalLocationSwitcher/GlobalLocationSwitcherBar.js +4 -2
- package/package.json +7 -7
- package/product/components/FilterBar/components/Content/components/FilterButton/index.js +38 -46
- package/product/components/FilterBar/components/Content/components/FilterChips/components/FilterChip/index.d.ts +38 -0
- package/product/components/FilterBar/components/Content/components/FilterChips/components/FilterChip/index.d.ts.map +1 -0
- package/product/components/FilterBar/components/Content/components/FilterChips/components/FilterChip/index.js +88 -0
- package/product/components/FilterBar/components/Content/components/FilterChips/index.js +54 -35
- package/product/components/FilterBar/components/Content/components/Sort/index.js +1 -1
- package/product/components/FilterBar/components/Content/index.js +7 -3
- package/product/components/FilterBar/index.js +11 -22
- package/product/components/ProductFilters/index.js +2 -6
- package/filter/components/FilterPageContent/components/Selector/components/ValueButton/index.js +0 -69
- package/product/components/FilterBar/components/Content/components/FilterChips/connector.js +0 -22
|
@@ -1,28 +1,40 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import "core-js/modules/es.array.includes.js";
|
|
2
|
+
import "core-js/modules/es.string.replace.js";
|
|
3
|
+
import { useMemo, useState, useEffect, useCallback } from 'react';
|
|
3
4
|
import { connect } from 'react-redux';
|
|
4
5
|
import debounce from 'lodash/debounce';
|
|
5
6
|
import isEqual from 'lodash/isEqual';
|
|
6
7
|
import { router } from '@shopgate/engage/core';
|
|
8
|
+
import { useRoute } from '@shopgate/engage/core/hooks';
|
|
9
|
+
import { parseObjectToQueryString } from '@shopgate/engage/core/helpers';
|
|
7
10
|
import { getFiltersByHash } from '@shopgate/engage/filter';
|
|
8
|
-
|
|
9
|
-
import Context, { APIFilter, RouteFilters } from "./FilterPageProvider.context";
|
|
11
|
+
import Context from "./FilterPageProvider.context";
|
|
10
12
|
import { buildInitialFilters, buildUpdatedFilters } from "../helpers";
|
|
13
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
14
|
+
const FILTER_PATH_SUFFIX = '/filter';
|
|
11
15
|
|
|
12
16
|
/**
|
|
13
|
-
*
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
* A single stored filter value carrying id and label.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* A filter as kept in the provider's internal state. `value` holds either the selected values of a
|
|
22
|
+
* list filter or the `[min, max]` tuple of a range filter.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
const buildInitialFiltersTyped = buildInitialFilters;
|
|
26
|
+
const buildUpdatedFiltersTyped = buildUpdatedFilters;
|
|
27
|
+
/**
|
|
28
|
+
* Maps the available filters from the application state onto the provider props.
|
|
29
|
+
* @returns The mapped state props.
|
|
16
30
|
*/
|
|
17
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
18
31
|
const mapStateToProps = (state, props) => ({
|
|
19
32
|
filters: getFiltersByHash(state, props)
|
|
20
33
|
});
|
|
21
34
|
|
|
22
35
|
/**
|
|
23
|
-
*
|
|
24
|
-
* @
|
|
25
|
-
* @returns {boolean}
|
|
36
|
+
* Compares the mapped state props to decide whether the connected component needs to re-render.
|
|
37
|
+
* @returns Whether the state props are considered equal.
|
|
26
38
|
*/
|
|
27
39
|
const areStatePropsEqual = (next, prev) => {
|
|
28
40
|
if (!prev.filters && next.filters || !isEqual(prev.filters, next.filters)) {
|
|
@@ -34,25 +46,19 @@ const areStatePropsEqual = (next, prev) => {
|
|
|
34
46
|
/**
|
|
35
47
|
* The FilterPageProvider component provides all relevant data and callbacks to represent and modify
|
|
36
48
|
* the current state of the "filter" page.
|
|
37
|
-
* @
|
|
38
|
-
* @param {APIFilter[]} props.filters Array of available filters
|
|
39
|
-
* @param {RouteFilters} props.activeFilters Object with the active filters for a filtered product
|
|
40
|
-
* list
|
|
41
|
-
* @param {string} props.parentRouteId Id of the route with the product list that's supposed to be
|
|
42
|
-
* filtered
|
|
43
|
-
* @param {Function} [props.onApply] Callback invoked when users pressed the apply button
|
|
44
|
-
* @param {string} [props.categoryId] A category to be used for filter selection from Redux
|
|
45
|
-
* @param {string} [props.searchPhrase] A search phrase to be used for filter selection from Redux
|
|
46
|
-
* @param {NodeList} children Provider children
|
|
47
|
-
* @returns {JSX.Element}
|
|
49
|
+
* @returns The rendered component.
|
|
48
50
|
*/
|
|
49
51
|
const FilterPageProvider = ({
|
|
50
|
-
filters: filtersProp,
|
|
51
|
-
activeFilters: activeFiltersProp,
|
|
52
|
-
parentRouteId,
|
|
53
|
-
onApply,
|
|
54
|
-
children
|
|
52
|
+
filters: filtersProp = null,
|
|
53
|
+
activeFilters: activeFiltersProp = null,
|
|
54
|
+
parentRouteId = null,
|
|
55
|
+
onApply = () => setTimeout(router.pop, 250),
|
|
56
|
+
children = null
|
|
55
57
|
}) => {
|
|
58
|
+
const {
|
|
59
|
+
pathname,
|
|
60
|
+
query
|
|
61
|
+
} = useRoute();
|
|
56
62
|
const [currentFilters, setCurrentFilters] = useState(activeFiltersProp || {});
|
|
57
63
|
|
|
58
64
|
/**
|
|
@@ -60,7 +66,7 @@ const FilterPageProvider = ({
|
|
|
60
66
|
* It's created from the "filters" array that contains all available filters, and the
|
|
61
67
|
* "activeFilters" object that represents filters with an active value selection.
|
|
62
68
|
*/
|
|
63
|
-
const [initialFilters, setInitialFilters] = useState(
|
|
69
|
+
const [initialFilters, setInitialFilters] = useState(buildInitialFiltersTyped(filtersProp, activeFiltersProp));
|
|
64
70
|
|
|
65
71
|
/**
|
|
66
72
|
* Storage that hosts an object that represents the a partial state of the filters page with
|
|
@@ -82,7 +88,7 @@ const FilterPageProvider = ({
|
|
|
82
88
|
if (Object.keys(currentState).length > 0) {
|
|
83
89
|
return currentState;
|
|
84
90
|
}
|
|
85
|
-
return
|
|
91
|
+
return buildInitialFiltersTyped(filtersProp, activeFiltersProp);
|
|
86
92
|
});
|
|
87
93
|
}, [activeFiltersProp, filtersProp]);
|
|
88
94
|
|
|
@@ -91,37 +97,23 @@ const FilterPageProvider = ({
|
|
|
91
97
|
*
|
|
92
98
|
* Reset is possible whenever filters where selected by the user before, or when filters where
|
|
93
99
|
* modified since the filters page was opened.
|
|
94
|
-
* @type {boolean}
|
|
95
100
|
*/
|
|
96
101
|
const resetPossible = useMemo(() => !!(Object.keys(currentFilters).length || Object.keys(changedFilters).length), [changedFilters, currentFilters]);
|
|
97
102
|
|
|
98
103
|
/**
|
|
99
104
|
* Whether the filter selection has changed since the filters page was opened
|
|
100
|
-
* @type {boolean}
|
|
101
105
|
*/
|
|
102
106
|
const hasChanged = useMemo(() => Object.keys(changedFilters).length > 0 || !!(Object.keys(currentFilters).length === 0 && activeFiltersProp), [activeFiltersProp, changedFilters, currentFilters]);
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Retrieves a list of currently selected values for a filter
|
|
106
|
-
* @callback getSelectedFilterValues
|
|
107
|
-
* @param {string} filterId The id of the filter
|
|
108
|
-
* @returns {string[]}
|
|
109
|
-
*/
|
|
110
|
-
const getSelectedFilterValues = useCallback(
|
|
111
|
-
/**
|
|
112
|
-
* @param {string} filterId The id of the filter
|
|
113
|
-
* @returns {string[]}
|
|
114
|
-
*/
|
|
115
|
-
filterId => {
|
|
107
|
+
const getSelectedFilterValues = useCallback(filterId => {
|
|
116
108
|
const value = changedFilters[filterId] ? changedFilters[filterId].value : initialFilters[filterId]?.value || [];
|
|
117
|
-
return value.map(entry => entry.id
|
|
109
|
+
return value.map(entry => typeof entry === 'object' ? entry.id : entry);
|
|
118
110
|
}, [changedFilters, initialFilters]);
|
|
119
111
|
|
|
120
112
|
/**
|
|
121
113
|
* Resets all filters which have been changed by the user
|
|
122
114
|
*/
|
|
123
115
|
const resetAllFilters = useCallback(() => {
|
|
124
|
-
setInitialFilters(
|
|
116
|
+
setInitialFilters(buildInitialFiltersTyped(filtersProp, {}));
|
|
125
117
|
setCurrentFilters({});
|
|
126
118
|
setChangedFilters({});
|
|
127
119
|
}, [filtersProp]);
|
|
@@ -132,77 +124,33 @@ const FilterPageProvider = ({
|
|
|
132
124
|
const resetChangedFilters = useCallback(() => {
|
|
133
125
|
setChangedFilters({});
|
|
134
126
|
}, []);
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Adds or updates the selection for a changed filter
|
|
138
|
-
* @callback updateChangedFilterInternal
|
|
139
|
-
* @param {string} filterId The id of the filter to be updated
|
|
140
|
-
* @param {string[]} selectedValues The updated selected values
|
|
141
|
-
*/
|
|
142
|
-
const updateChangedFilterInternal = useCallback(
|
|
143
|
-
/**
|
|
144
|
-
* @param {string} filterId The id of the filter to be updated
|
|
145
|
-
* @param {string[]} selectedValues The updated selected values
|
|
146
|
-
*/
|
|
147
|
-
(filterId, selectedValues) => {
|
|
127
|
+
const updateChangedFilterInternal = useCallback((filterId, selectedValues) => {
|
|
148
128
|
setChangedFilters(currentState => ({
|
|
149
129
|
...currentState,
|
|
150
130
|
[filterId]: selectedValues
|
|
151
131
|
}));
|
|
152
132
|
}, []);
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Removes a changed filter
|
|
156
|
-
* @callback removeChangedFilterInternal
|
|
157
|
-
* @param {string} filterId The id of the filter to be updated
|
|
158
|
-
* @param {string[]} selectedValues The updated selected values
|
|
159
|
-
*/
|
|
160
|
-
const removeChangedFilterInternal = useCallback(
|
|
161
|
-
/**
|
|
162
|
-
* @param {string} filterId The id of the filter to be removed
|
|
163
|
-
*/
|
|
164
|
-
filterId => {
|
|
133
|
+
const removeChangedFilterInternal = useCallback(filterId => {
|
|
165
134
|
setChangedFilters(currentState => {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
} = currentState;
|
|
135
|
+
const remainingFilters = {
|
|
136
|
+
...currentState
|
|
137
|
+
};
|
|
138
|
+
delete remainingFilters[filterId];
|
|
171
139
|
return remainingFilters;
|
|
172
140
|
});
|
|
173
141
|
}, []);
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
* @param {string[]} selectedValues The updated selected values
|
|
180
|
-
*/
|
|
181
|
-
const updateSelectedFilterValues = useCallback(debounce(
|
|
182
|
-
/**
|
|
183
|
-
* @param {string} filterId The id of the filter to be updated
|
|
184
|
-
* @param {string[]} selectedValues The updated selected values
|
|
185
|
-
*/
|
|
186
|
-
(filterId, selectedValues) => {
|
|
187
|
-
// Retrieve data of filter to be updated from the filters array.
|
|
188
|
-
const filter = filtersProp.find(entry => entry.id === filterId);
|
|
189
|
-
|
|
190
|
-
// Retrieve the values for the updated filter that where set when the filter page was opened
|
|
142
|
+
const updateSelectedFilterValues = useCallback(debounce((filterId, selectedValues) => {
|
|
143
|
+
const filter = (filtersProp || []).find(entry => entry.id === filterId);
|
|
144
|
+
if (!filter) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
191
147
|
const {
|
|
192
148
|
value: initialValues
|
|
193
149
|
} = initialFilters[filterId];
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* No initial values where set for this filter, and the update contains no values. So we
|
|
200
|
-
* can remove the filter from the changedFilters storage.
|
|
201
|
-
*/
|
|
202
|
-
if (initialValues.length === 0 && selectedValues.length === 0) {
|
|
203
|
-
removeChangedFilterInternal(filterId);
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
150
|
+
const hasValueList = Array.isArray(filter.values);
|
|
151
|
+
const orderByFilter = ids => hasValueList ? filter.values.filter(entry => ids.includes(entry.id)).map(entry => entry.id) : ids;
|
|
152
|
+
const selectedValueIds = orderByFilter(selectedValues);
|
|
153
|
+
const initialValueIds = orderByFilter(initialValues.map(entry => typeof entry === 'object' ? entry.id : entry));
|
|
206
154
|
|
|
207
155
|
/**
|
|
208
156
|
* When the filter update would recreate the state that the filter initially had, we
|
|
@@ -210,25 +158,21 @@ const FilterPageProvider = ({
|
|
|
210
158
|
*
|
|
211
159
|
* That enables proper behavior for the "reset" and "update" button states.
|
|
212
160
|
*/
|
|
213
|
-
if (
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
161
|
+
if (initialValueIds.length === selectedValueIds.length && initialValueIds.every((initial, i) => initial === selectedValueIds[i])) {
|
|
162
|
+
removeChangedFilterInternal(filterId);
|
|
163
|
+
return;
|
|
218
164
|
}
|
|
219
|
-
|
|
165
|
+
let stateValue = [].concat(selectedValueIds);
|
|
166
|
+
if (hasValueList) {
|
|
220
167
|
/**
|
|
221
168
|
* The selectedValues array only contains a list of ids.
|
|
222
169
|
* For the getProducts request that's dispatched after the current filter selection was
|
|
223
170
|
* applied, id and label is required at the filter values level.
|
|
224
171
|
*/
|
|
225
|
-
stateValue =
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
label: match.label
|
|
230
|
-
};
|
|
231
|
-
});
|
|
172
|
+
stateValue = selectedValueIds.map(valueId => filter.values.find(entry => entry.id === valueId)).filter(match => Boolean(match)).map(match => ({
|
|
173
|
+
id: match.id,
|
|
174
|
+
label: match.label
|
|
175
|
+
}));
|
|
232
176
|
}
|
|
233
177
|
updateChangedFilterInternal(filterId, {
|
|
234
178
|
id: filterId,
|
|
@@ -242,15 +186,27 @@ const FilterPageProvider = ({
|
|
|
242
186
|
}, 50), [filtersProp, initialFilters, removeChangedFilterInternal, updateChangedFilterInternal]);
|
|
243
187
|
|
|
244
188
|
/**
|
|
245
|
-
* Applies the current filter selection to the parent route with a product list to be filtered
|
|
189
|
+
* Applies the current filter selection to the parent route with a product list to be filtered.
|
|
190
|
+
* When the filter page was entered directly, no parent route exists in the history stack. In
|
|
191
|
+
* that case the product list route is derived from the current pathname and replaces the
|
|
192
|
+
* filter page.
|
|
246
193
|
*/
|
|
247
194
|
const applyFilters = useCallback(() => {
|
|
248
|
-
const filters =
|
|
195
|
+
const filters = buildUpdatedFiltersTyped(currentFilters, changedFilters);
|
|
196
|
+
if (!parentRouteId) {
|
|
197
|
+
router.replace({
|
|
198
|
+
pathname: `${pathname.slice(0, -FILTER_PATH_SUFFIX.length)}${parseObjectToQueryString(query)}`,
|
|
199
|
+
state: {
|
|
200
|
+
filters
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
249
205
|
router.update(parentRouteId, {
|
|
250
206
|
filters
|
|
251
207
|
});
|
|
252
208
|
onApply(filters);
|
|
253
|
-
}, [changedFilters, currentFilters, onApply, parentRouteId]);
|
|
209
|
+
}, [changedFilters, currentFilters, onApply, parentRouteId, pathname, query]);
|
|
254
210
|
const value = useMemo(() => ({
|
|
255
211
|
resetPossible,
|
|
256
212
|
hasChanged,
|
|
@@ -267,17 +223,6 @@ const FilterPageProvider = ({
|
|
|
267
223
|
children: children
|
|
268
224
|
});
|
|
269
225
|
};
|
|
270
|
-
FilterPageProvider.defaultProps = {
|
|
271
|
-
children: null,
|
|
272
|
-
activeFilters: null,
|
|
273
|
-
parentRouteId: null,
|
|
274
|
-
filters: null,
|
|
275
|
-
onApply: () => setTimeout(router.pop, 250)
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* @type FilterPageProvider
|
|
280
|
-
*/
|
|
281
226
|
export default connect(mapStateToProps, null, null, {
|
|
282
227
|
areStatePropsEqual
|
|
283
228
|
})(FilterPageProvider);
|
|
@@ -8,7 +8,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
8
8
|
const useStyles = makeStyles()(theme => ({
|
|
9
9
|
wrapper: {
|
|
10
10
|
color: theme.palette.text.primary,
|
|
11
|
-
background: theme.palette.background.
|
|
11
|
+
background: theme.palette.background.surface
|
|
12
12
|
},
|
|
13
13
|
inner: {
|
|
14
14
|
display: 'flex',
|
|
@@ -16,7 +16,8 @@ const useStyles = makeStyles()(theme => ({
|
|
|
16
16
|
margin: theme.spacing(0, 2),
|
|
17
17
|
borderBottom: `1px solid ${theme.components.border.light}`,
|
|
18
18
|
alignItems: 'center',
|
|
19
|
-
height: theme.components.filterBar.height
|
|
19
|
+
height: theme.components.filterBar.height,
|
|
20
|
+
justifyContent: 'space-between'
|
|
20
21
|
},
|
|
21
22
|
innerStandalone: {
|
|
22
23
|
borderBottom: 'none'
|
|
@@ -26,6 +27,7 @@ const useStyles = makeStyles()(theme => ({
|
|
|
26
27
|
},
|
|
27
28
|
button: {
|
|
28
29
|
marginLeft: theme.spacing(2),
|
|
30
|
+
marginTop: theme.spacing(0.5),
|
|
29
31
|
textTransform: 'none'
|
|
30
32
|
}
|
|
31
33
|
}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shopgate/engage",
|
|
3
|
-
"version": "7.32.0-beta.
|
|
3
|
+
"version": "7.32.0-beta.15",
|
|
4
4
|
"description": "Shopgate's ENGAGE library.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Shopgate <support@shopgate.com>",
|
|
@@ -18,12 +18,12 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@emotion/react": "^11.14.0",
|
|
20
20
|
"@shopgate/native-modules": "1.0.0-beta.34",
|
|
21
|
-
"@shopgate/pwa-common": "7.32.0-beta.
|
|
22
|
-
"@shopgate/pwa-common-commerce": "7.32.0-beta.
|
|
23
|
-
"@shopgate/pwa-core": "7.32.0-beta.
|
|
24
|
-
"@shopgate/pwa-ui-ios": "7.32.0-beta.
|
|
25
|
-
"@shopgate/pwa-ui-material": "7.32.0-beta.
|
|
26
|
-
"@shopgate/pwa-ui-shared": "7.32.0-beta.
|
|
21
|
+
"@shopgate/pwa-common": "7.32.0-beta.15",
|
|
22
|
+
"@shopgate/pwa-common-commerce": "7.32.0-beta.15",
|
|
23
|
+
"@shopgate/pwa-core": "7.32.0-beta.15",
|
|
24
|
+
"@shopgate/pwa-ui-ios": "7.32.0-beta.15",
|
|
25
|
+
"@shopgate/pwa-ui-material": "7.32.0-beta.15",
|
|
26
|
+
"@shopgate/pwa-ui-shared": "7.32.0-beta.15",
|
|
27
27
|
"@stripe/react-stripe-js": "^1.16.5",
|
|
28
28
|
"@stripe/stripe-js": "^1.44.1",
|
|
29
29
|
"@virtuous/conductor": "~2.5.0",
|
|
@@ -1,35 +1,28 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { makeStyles } from '@shopgate/engage/styles';
|
|
4
|
-
import {
|
|
4
|
+
import { i18n } from '@shopgate/engage/core/helpers';
|
|
5
|
+
import { Badge, I18n, FilterIcon, Typography } from '@shopgate/engage/components';
|
|
5
6
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
6
7
|
const useStyles = makeStyles()(theme => ({
|
|
7
8
|
button: {
|
|
9
|
+
display: 'flex',
|
|
10
|
+
alignItems: 'center',
|
|
11
|
+
gap: theme.spacing(0.75),
|
|
8
12
|
color: 'inherit',
|
|
9
|
-
fontSize: theme.components.icon.medium,
|
|
10
13
|
outline: 0,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
overflow: 'hidden'
|
|
17
|
-
},
|
|
18
|
-
filterButton: {
|
|
19
|
-
display: 'flex'
|
|
14
|
+
flexShrink: 0,
|
|
15
|
+
margin: theme.spacing(0, 1.5),
|
|
16
|
+
padding: theme.spacing(0.25, 1),
|
|
17
|
+
border: `1px solid ${theme.components.border.medium}`,
|
|
18
|
+
borderRadius: theme.shape.borderRadius
|
|
20
19
|
},
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
paddingRight: theme.spacing(1)
|
|
20
|
+
buttonActive: {
|
|
21
|
+
borderColor: theme.components.badge.background
|
|
24
22
|
},
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
width: '100%',
|
|
29
|
-
justifyContent: 'center',
|
|
30
|
-
alignItems: 'center',
|
|
31
|
-
margin: 0,
|
|
32
|
-
padding: '6px 10px'
|
|
23
|
+
icon: {
|
|
24
|
+
fontSize: theme.components.icon.medium,
|
|
25
|
+
display: 'flex'
|
|
33
26
|
}
|
|
34
27
|
}));
|
|
35
28
|
|
|
@@ -39,39 +32,38 @@ const useStyles = makeStyles()(theme => ({
|
|
|
39
32
|
* @return {JSX}
|
|
40
33
|
*/
|
|
41
34
|
function FilterButton({
|
|
42
|
-
openFilters
|
|
35
|
+
openFilters,
|
|
36
|
+
filterCount
|
|
43
37
|
}) {
|
|
44
38
|
const {
|
|
45
39
|
classes,
|
|
46
40
|
cx
|
|
47
41
|
} = useStyles();
|
|
48
|
-
return /*#__PURE__*/
|
|
49
|
-
className: cx(classes.button,
|
|
42
|
+
return /*#__PURE__*/_jsxs("button", {
|
|
43
|
+
className: cx(classes.button, {
|
|
44
|
+
[classes.buttonActive]: filterCount > 0
|
|
45
|
+
}, 'theme__filter-bar__filter-button'),
|
|
50
46
|
onClick: openFilters,
|
|
51
47
|
"data-test-id": "filterButton",
|
|
48
|
+
"aria-label": i18n.text('titles.filter'),
|
|
52
49
|
type: "button",
|
|
53
|
-
children: /*#__PURE__*/_jsx(
|
|
54
|
-
className: classes.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
children: /*#__PURE__*/_jsx(Typography, {
|
|
62
|
-
variant: "subtitle2",
|
|
63
|
-
component: "span",
|
|
64
|
-
className: classes.filterButtonLabel,
|
|
65
|
-
children: /*#__PURE__*/_jsx(I18n.Text, {
|
|
66
|
-
string: "titles.filter"
|
|
67
|
-
})
|
|
68
|
-
})
|
|
69
|
-
}), /*#__PURE__*/_jsx(Grid.Item, {
|
|
70
|
-
component: "div",
|
|
71
|
-
children: /*#__PURE__*/_jsx(FilterIcon, {})
|
|
72
|
-
})]
|
|
50
|
+
children: [/*#__PURE__*/_jsx("span", {
|
|
51
|
+
className: classes.icon,
|
|
52
|
+
children: /*#__PURE__*/_jsx(FilterIcon, {})
|
|
53
|
+
}), /*#__PURE__*/_jsx(Typography, {
|
|
54
|
+
variant: "subtitle2",
|
|
55
|
+
component: "span",
|
|
56
|
+
children: /*#__PURE__*/_jsx(I18n.Text, {
|
|
57
|
+
string: "titles.filter"
|
|
73
58
|
})
|
|
74
|
-
})
|
|
59
|
+
}), /*#__PURE__*/_jsx(Badge, {
|
|
60
|
+
count: filterCount,
|
|
61
|
+
max: 9,
|
|
62
|
+
"aria-hidden": true
|
|
63
|
+
})]
|
|
75
64
|
});
|
|
76
65
|
}
|
|
66
|
+
FilterButton.defaultProps = {
|
|
67
|
+
filterCount: 0
|
|
68
|
+
};
|
|
77
69
|
export default FilterButton;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export interface FilterChipProps {
|
|
3
|
+
/**
|
|
4
|
+
* Id of the filter value. Used as the test id and passed back to `onRemove`.
|
|
5
|
+
*/
|
|
6
|
+
id: string;
|
|
7
|
+
/**
|
|
8
|
+
* The chip label.
|
|
9
|
+
*/
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
/**
|
|
12
|
+
* Whether the chip renders a remove button (default `true`).
|
|
13
|
+
*/
|
|
14
|
+
removable?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Aria label for the label button, which opens the filter page.
|
|
17
|
+
*/
|
|
18
|
+
editLabel?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Aria label for the remove button.
|
|
21
|
+
*/
|
|
22
|
+
removeLabel?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Invoked when the chip label is clicked.
|
|
25
|
+
*/
|
|
26
|
+
onClick?: () => void;
|
|
27
|
+
/**
|
|
28
|
+
* Invoked with the chip id when the remove button is clicked.
|
|
29
|
+
*/
|
|
30
|
+
onRemove?: (id: string) => void;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A removable chip representing one active filter within the filter bar.
|
|
34
|
+
* @returns The rendered component.
|
|
35
|
+
*/
|
|
36
|
+
declare const FilterChip: ({ id, children, removable, editLabel, removeLabel, onClick, onRemove, }: FilterChipProps) => import("react").JSX.Element;
|
|
37
|
+
export default FilterChip;
|
|
38
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../../../product/components/FilterBar/components/Content/components/FilterChips/components/FilterChip/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAC;AAwDtD,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IACpB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAED;;;GAGG;AACH,QAAA,MAAM,UAAU,GAAI,yEAQjB,eAAe,gCAwBjB,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
import noop from 'lodash/noop';
|
|
3
|
+
import Button from '@shopgate/pwa-common/components/Button';
|
|
4
|
+
import { CrossIcon } from '@shopgate/engage/components';
|
|
5
|
+
import { makeStyles } from '@shopgate/engage/styles';
|
|
6
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
7
|
+
const useStyles = makeStyles()((theme, {
|
|
8
|
+
removable
|
|
9
|
+
}) => ({
|
|
10
|
+
chip: {
|
|
11
|
+
display: 'flex',
|
|
12
|
+
alignItems: 'center',
|
|
13
|
+
minWidth: 0,
|
|
14
|
+
maxWidth: '72%',
|
|
15
|
+
height: 30,
|
|
16
|
+
borderRadius: theme.shape.borderRadius,
|
|
17
|
+
border: `1px solid ${theme.palette.secondary.main}`,
|
|
18
|
+
background: theme.palette.background.surface,
|
|
19
|
+
color: theme.palette.text.primary,
|
|
20
|
+
paddingLeft: removable ? theme.spacing(0.75) : theme.spacing(1.25),
|
|
21
|
+
paddingRight: theme.spacing(1.25),
|
|
22
|
+
outline: 0
|
|
23
|
+
},
|
|
24
|
+
name: {
|
|
25
|
+
...theme.typography.body2,
|
|
26
|
+
fontWeight: theme.typography.fontWeightMedium,
|
|
27
|
+
display: 'block',
|
|
28
|
+
color: 'inherit',
|
|
29
|
+
padding: 0,
|
|
30
|
+
paddingLeft: removable ? theme.spacing(0.5) : 0,
|
|
31
|
+
maxWidth: '100%',
|
|
32
|
+
overflow: 'hidden',
|
|
33
|
+
textOverflow: 'ellipsis',
|
|
34
|
+
whiteSpace: 'nowrap'
|
|
35
|
+
},
|
|
36
|
+
removeButton: {
|
|
37
|
+
display: 'flex',
|
|
38
|
+
flexShrink: 0,
|
|
39
|
+
padding: 0,
|
|
40
|
+
color: theme.palette.secondary.main
|
|
41
|
+
}
|
|
42
|
+
}));
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* `Button` is untyped JavaScript whose optional props read as required from TypeScript.
|
|
46
|
+
*/
|
|
47
|
+
const ChipButton = Button;
|
|
48
|
+
/**
|
|
49
|
+
* A removable chip representing one active filter within the filter bar.
|
|
50
|
+
* @returns The rendered component.
|
|
51
|
+
*/
|
|
52
|
+
const FilterChip = ({
|
|
53
|
+
id,
|
|
54
|
+
children,
|
|
55
|
+
removable = true,
|
|
56
|
+
editLabel,
|
|
57
|
+
removeLabel,
|
|
58
|
+
onClick = noop,
|
|
59
|
+
onRemove = noop
|
|
60
|
+
}) => {
|
|
61
|
+
const {
|
|
62
|
+
classes
|
|
63
|
+
} = useStyles({
|
|
64
|
+
removable
|
|
65
|
+
});
|
|
66
|
+
const handleRemove = useCallback(() => {
|
|
67
|
+
onRemove(id);
|
|
68
|
+
}, [onRemove, id]);
|
|
69
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
70
|
+
className: classes.chip,
|
|
71
|
+
"data-test-id": id,
|
|
72
|
+
children: [removable && /*#__PURE__*/_jsx(ChipButton, {
|
|
73
|
+
className: classes.removeButton,
|
|
74
|
+
onClick: handleRemove,
|
|
75
|
+
testId: "removeFilter",
|
|
76
|
+
"aria-label": removeLabel,
|
|
77
|
+
children: /*#__PURE__*/_jsx(CrossIcon, {
|
|
78
|
+
size: 16
|
|
79
|
+
})
|
|
80
|
+
}), /*#__PURE__*/_jsx(ChipButton, {
|
|
81
|
+
className: classes.name,
|
|
82
|
+
onClick: onClick,
|
|
83
|
+
"aria-label": editLabel,
|
|
84
|
+
children: children
|
|
85
|
+
})]
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
export default FilterChip;
|