@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
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface FilterValue {
|
|
2
|
+
/**
|
|
3
|
+
* Id of the filter value.
|
|
4
|
+
*/
|
|
5
|
+
id: string;
|
|
6
|
+
/**
|
|
7
|
+
* Display label of the filter value.
|
|
8
|
+
*/
|
|
9
|
+
label: string;
|
|
10
|
+
/**
|
|
11
|
+
* Number of products available for the filter value.
|
|
12
|
+
*/
|
|
13
|
+
hits?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface SelectorProps {
|
|
16
|
+
/**
|
|
17
|
+
* Id of the filter.
|
|
18
|
+
*/
|
|
19
|
+
id: string;
|
|
20
|
+
/**
|
|
21
|
+
* Display label of the filter.
|
|
22
|
+
*/
|
|
23
|
+
label: string;
|
|
24
|
+
/**
|
|
25
|
+
* The selectable values of the filter.
|
|
26
|
+
*/
|
|
27
|
+
values: FilterValue[];
|
|
28
|
+
/**
|
|
29
|
+
* Whether multiple values can be selected at once.
|
|
30
|
+
*/
|
|
31
|
+
multi?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Invoked with the filter id and the updated selection whenever a value is toggled.
|
|
34
|
+
*/
|
|
35
|
+
onChange?: (id: string, selected: string[]) => void;
|
|
36
|
+
/**
|
|
37
|
+
* The currently selected value ids.
|
|
38
|
+
*/
|
|
39
|
+
selected?: string[] | null;
|
|
40
|
+
}
|
|
41
|
+
declare const _default: import("react").MemoExoticComponent<({ id, label, values, multi, onChange, selected: selectedFromProps, }: SelectorProps) => import("react").JSX.Element>;
|
|
42
|
+
export default _default;
|
|
43
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../filter/components/FilterPageContent/components/Selector/index.tsx"],"names":[],"mappings":"AA4CA,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACpD;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;CAC5B;mIAaE,aAAa;AAwFhB,wBAA8B"}
|
|
@@ -1,37 +1,54 @@
|
|
|
1
1
|
import "core-js/modules/es.array.includes.js";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import { useState, useEffect, useCallback, useMemo, memo } from 'react';
|
|
3
|
+
import noop from 'lodash/noop';
|
|
4
4
|
import { Accordion, SurroundPortals } from '@shopgate/engage/components';
|
|
5
5
|
import { i18n } from '@shopgate/engage/core/helpers';
|
|
6
6
|
import { makeStyles } from '@shopgate/engage/styles';
|
|
7
7
|
import { FilterItem } from '@shopgate/engage/filter';
|
|
8
8
|
import { PORTAL_FILTER_SELECTOR } from '@shopgate/engage/filter/constants';
|
|
9
|
-
import
|
|
9
|
+
import ValueCheckbox from "./components/ValueCheckbox";
|
|
10
10
|
import Toggle from "./components/Toggle";
|
|
11
11
|
import Selected from "./components/Selected";
|
|
12
12
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
|
-
const useStyles = makeStyles()(
|
|
13
|
+
const useStyles = makeStyles()(theme => ({
|
|
14
14
|
accordion: {
|
|
15
15
|
overflow: 'hidden'
|
|
16
16
|
},
|
|
17
|
+
chevron: {
|
|
18
|
+
alignSelf: 'flex-start'
|
|
19
|
+
},
|
|
17
20
|
content: {
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
paddingBottom: theme.spacing(1),
|
|
22
|
+
display: 'flex',
|
|
23
|
+
flexDirection: 'column'
|
|
20
24
|
}
|
|
21
25
|
}));
|
|
22
26
|
|
|
23
27
|
/**
|
|
24
|
-
*
|
|
25
|
-
* @param
|
|
26
|
-
* @returns
|
|
28
|
+
* Formats selected filter value labels into a readable enumeration.
|
|
29
|
+
* @param labels Labels of the selected values.
|
|
30
|
+
* @returns The formatted enumeration.
|
|
31
|
+
*/
|
|
32
|
+
const formatSelectedLabels = labels => {
|
|
33
|
+
const {
|
|
34
|
+
ListFormat
|
|
35
|
+
} = Intl;
|
|
36
|
+
if (typeof ListFormat !== 'function') {
|
|
37
|
+
return labels.join(', ');
|
|
38
|
+
}
|
|
39
|
+
return new ListFormat(i18n.getLang()).format(labels);
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* The selector component renders a single filter as an accordion with selectable values.
|
|
43
|
+
* @returns The rendered component.
|
|
27
44
|
*/
|
|
28
45
|
const Selector = ({
|
|
29
46
|
id,
|
|
30
47
|
label,
|
|
31
48
|
values,
|
|
32
|
-
multi,
|
|
33
|
-
onChange,
|
|
34
|
-
selected: selectedFromProps
|
|
49
|
+
multi = false,
|
|
50
|
+
onChange = noop,
|
|
51
|
+
selected: selectedFromProps = null
|
|
35
52
|
}) => {
|
|
36
53
|
const {
|
|
37
54
|
classes
|
|
@@ -40,10 +57,7 @@ const Selector = ({
|
|
|
40
57
|
useEffect(() => {
|
|
41
58
|
setSelected(selectedFromProps || []);
|
|
42
59
|
}, [selectedFromProps]);
|
|
43
|
-
const
|
|
44
|
-
const {
|
|
45
|
-
value
|
|
46
|
-
} = event.target;
|
|
60
|
+
const handleToggle = useCallback(value => {
|
|
47
61
|
setSelected(prev => {
|
|
48
62
|
let newSelected = [].concat(prev, [value]);
|
|
49
63
|
if (!multi && prev.length === 1) {
|
|
@@ -56,21 +70,24 @@ const Selector = ({
|
|
|
56
70
|
return newSelected;
|
|
57
71
|
});
|
|
58
72
|
}, [id, multi, onChange]);
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
target: {
|
|
62
|
-
value: updatedId
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
}, [handleClick]);
|
|
66
|
-
const renderLabel = useCallback(props => /*#__PURE__*/_jsx(Toggle, {
|
|
67
|
-
...props,
|
|
73
|
+
const selectedValues = useMemo(() => values.filter(value => selected.includes(value.id)), [selected, values]);
|
|
74
|
+
const renderLabel = useCallback(() => /*#__PURE__*/_jsx(Toggle, {
|
|
68
75
|
label: label,
|
|
69
76
|
selected: /*#__PURE__*/_jsx(Selected, {
|
|
70
|
-
values:
|
|
71
|
-
selected: selected
|
|
77
|
+
values: selectedValues
|
|
72
78
|
})
|
|
73
|
-
}), [label,
|
|
79
|
+
}), [label, selectedValues]);
|
|
80
|
+
const handleLabel = useMemo(() => {
|
|
81
|
+
if (selectedValues.length === 0) {
|
|
82
|
+
return i18n.text('filter.filter_by', {
|
|
83
|
+
label
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
return i18n.text('filter.filter_by_with_selected', {
|
|
87
|
+
label,
|
|
88
|
+
selected: formatSelectedLabels(selectedValues.map(value => value.label))
|
|
89
|
+
});
|
|
90
|
+
}, [label, selectedValues]);
|
|
74
91
|
return /*#__PURE__*/_jsx(SurroundPortals, {
|
|
75
92
|
portalName: PORTAL_FILTER_SELECTOR,
|
|
76
93
|
portalProps: {
|
|
@@ -81,32 +98,27 @@ const Selector = ({
|
|
|
81
98
|
isMultiSelect: multi
|
|
82
99
|
},
|
|
83
100
|
selectedValueIds: selected,
|
|
84
|
-
onChange:
|
|
101
|
+
onChange: handleToggle
|
|
85
102
|
},
|
|
86
103
|
children: /*#__PURE__*/_jsx(FilterItem, {
|
|
87
104
|
children: /*#__PURE__*/_jsx(Accordion, {
|
|
88
105
|
renderLabel: renderLabel,
|
|
89
106
|
testId: id,
|
|
90
|
-
handleLabel:
|
|
91
|
-
label
|
|
92
|
-
}),
|
|
107
|
+
handleLabel: handleLabel,
|
|
93
108
|
className: classes.accordion,
|
|
109
|
+
chevronClassName: classes.chevron,
|
|
94
110
|
children: /*#__PURE__*/_jsx("div", {
|
|
95
111
|
className: classes.content,
|
|
96
|
-
children: values.map(value => /*#__PURE__*/_jsx(
|
|
112
|
+
children: values.map(value => /*#__PURE__*/_jsx(ValueCheckbox, {
|
|
97
113
|
id: value.id,
|
|
98
114
|
label: value.label,
|
|
99
|
-
|
|
100
|
-
|
|
115
|
+
hits: value.hits,
|
|
116
|
+
isActive: selected.includes(value.id),
|
|
117
|
+
onToggle: handleToggle
|
|
101
118
|
}, value.id))
|
|
102
119
|
})
|
|
103
120
|
})
|
|
104
121
|
})
|
|
105
122
|
});
|
|
106
123
|
};
|
|
107
|
-
Selector.defaultProps = {
|
|
108
|
-
multi: false,
|
|
109
|
-
onChange() {},
|
|
110
|
-
selected: null
|
|
111
|
-
};
|
|
112
124
|
export default /*#__PURE__*/memo(Selector);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ComponentType } from 'react';
|
|
2
|
+
export interface FilterPageContentProps {
|
|
3
|
+
/**
|
|
4
|
+
* The component to be rendered as the app bar.
|
|
5
|
+
*/
|
|
6
|
+
AppBarComponent?: ComponentType<{
|
|
7
|
+
title?: string;
|
|
8
|
+
}> | null;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The FilterPageContent component renders all filters for the filter page.
|
|
12
|
+
* @returns The rendered component.
|
|
13
|
+
*/
|
|
14
|
+
declare const FilterPageContent: ({ AppBarComponent }: FilterPageContentProps) => import("react").JSX.Element;
|
|
15
|
+
export default FilterPageContent;
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../filter/components/FilterPageContent/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAyB3C,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,eAAe,CAAC,EAAE,aAAa,CAAC;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI,CAAC;CAC5D;AAED;;;GAGG;AACH,QAAA,MAAM,iBAAiB,GAAI,qBAA4B,sBAAsB,gCAmD5E,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
|
|
@@ -1,78 +1,72 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import { SurroundPortals, ResponsiveContainer } from '@shopgate/engage/components';
|
|
1
|
+
import { Fragment } from 'react';
|
|
2
|
+
import { SurroundPortals } from '@shopgate/engage/components';
|
|
4
3
|
import { useFilterPage } from '@shopgate/engage/filter/hooks';
|
|
4
|
+
import { makeStyles } from '@shopgate/engage/styles';
|
|
5
5
|
import { PORTAL_FILTER_PRICE_RANGE, PORTAL_FILTER_PAGE_CONTENT, FILTER_TYPE_RANGE, FILTER_TYPE_MULTISELECT, PriceSlider } from '@shopgate/engage/filter';
|
|
6
6
|
import Selector from "./components/Selector";
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
|
|
7
|
+
import FilterButtonBar from "./components/FilterButtonBar";
|
|
8
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
9
|
+
const useStyles = makeStyles()(theme => ({
|
|
10
|
+
content: {
|
|
11
|
+
color: theme.palette.text.primary,
|
|
12
|
+
[theme.breakpoints.up('md')]: {
|
|
13
|
+
width: '100%',
|
|
14
|
+
maxWidth: 640,
|
|
15
|
+
margin: '0 auto'
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}));
|
|
10
19
|
/**
|
|
11
20
|
* The FilterPageContent component renders all filters for the filter page.
|
|
12
|
-
* @
|
|
13
|
-
* @param {React.ComponentType} props.AppBarComponent The component to be rendered as the app bar
|
|
14
|
-
* @returns {JSX.Element}
|
|
21
|
+
* @returns The rendered component.
|
|
15
22
|
*/
|
|
16
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
17
23
|
const FilterPageContent = ({
|
|
18
|
-
AppBarComponent
|
|
24
|
+
AppBarComponent = null
|
|
19
25
|
}) => {
|
|
26
|
+
const {
|
|
27
|
+
classes
|
|
28
|
+
} = useStyles();
|
|
20
29
|
const {
|
|
21
30
|
apiFilters,
|
|
22
|
-
resetPossible,
|
|
23
|
-
hasChanged,
|
|
24
|
-
applyFilters,
|
|
25
|
-
resetAllFilters,
|
|
26
31
|
getSelectedFilterValues,
|
|
27
32
|
updateSelectedFilterValues
|
|
28
33
|
} = useFilterPage();
|
|
29
34
|
return /*#__PURE__*/_jsxs(SurroundPortals, {
|
|
30
35
|
portalName: PORTAL_FILTER_PAGE_CONTENT,
|
|
31
36
|
children: [AppBarComponent && /*#__PURE__*/_jsx(AppBarComponent, {
|
|
32
|
-
title: "titles.filter"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
filter
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
37
|
+
title: "titles.filter"
|
|
38
|
+
}), /*#__PURE__*/_jsx("div", {
|
|
39
|
+
className: classes.content,
|
|
40
|
+
children: apiFilters.map(filter => {
|
|
41
|
+
const portalProps = {
|
|
42
|
+
filter
|
|
43
|
+
};
|
|
44
|
+
const value = getSelectedFilterValues(filter.id);
|
|
45
|
+
if (filter.type === FILTER_TYPE_RANGE) {
|
|
46
|
+
return /*#__PURE__*/_jsx(Fragment, {
|
|
47
|
+
children: /*#__PURE__*/_jsx(SurroundPortals, {
|
|
48
|
+
portalName: PORTAL_FILTER_PRICE_RANGE,
|
|
49
|
+
portalProps: portalProps,
|
|
50
|
+
children: /*#__PURE__*/_jsx(PriceSlider, {
|
|
51
|
+
id: filter.id,
|
|
52
|
+
min: filter.minimum,
|
|
53
|
+
max: filter.maximum,
|
|
54
|
+
onChange: updateSelectedFilterValues,
|
|
55
|
+
value: value
|
|
56
|
+
}, filter.id)
|
|
57
|
+
})
|
|
58
|
+
}, filter.id);
|
|
59
|
+
}
|
|
60
|
+
return /*#__PURE__*/_jsx(Selector, {
|
|
61
|
+
id: filter.id,
|
|
62
|
+
label: filter.label,
|
|
63
|
+
values: filter.values,
|
|
64
|
+
multi: filter.type === FILTER_TYPE_MULTISELECT,
|
|
65
|
+
onChange: updateSelectedFilterValues,
|
|
66
|
+
selected: value
|
|
55
67
|
}, filter.id);
|
|
56
|
-
}
|
|
57
|
-
return /*#__PURE__*/_jsx(Selector, {
|
|
58
|
-
id: filter.id,
|
|
59
|
-
label: filter.label,
|
|
60
|
-
values: filter.values,
|
|
61
|
-
multi: filter.type === FILTER_TYPE_MULTISELECT,
|
|
62
|
-
onChange: updateSelectedFilterValues,
|
|
63
|
-
selected: value
|
|
64
|
-
}, filter.id);
|
|
65
|
-
}), /*#__PURE__*/_jsx(ResponsiveContainer, {
|
|
66
|
-
breakpoint: "<sm",
|
|
67
|
-
appAlways: true,
|
|
68
|
-
children: /*#__PURE__*/_jsx(ResetButton, {
|
|
69
|
-
disabled: !resetPossible,
|
|
70
|
-
onClick: resetAllFilters
|
|
71
68
|
})
|
|
72
|
-
})]
|
|
69
|
+
}), /*#__PURE__*/_jsx(FilterButtonBar, {})]
|
|
73
70
|
});
|
|
74
71
|
};
|
|
75
|
-
FilterPageContent.defaultProps = {
|
|
76
|
-
AppBarComponent: null
|
|
77
|
-
};
|
|
78
72
|
export default FilterPageContent;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "core-js/modules/es.string.replace.js";
|
|
2
|
-
import React, { memo, useState, useEffect
|
|
2
|
+
import React, { memo, useState, useEffect } from 'react';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import appConfig from '@shopgate/pwa-common/helpers/config';
|
|
5
5
|
import { makeStyles, responsiveMediaQuery } from '@shopgate/engage/styles';
|
|
@@ -10,39 +10,23 @@ const {
|
|
|
10
10
|
currency
|
|
11
11
|
} = appConfig;
|
|
12
12
|
const useStyles = makeStyles()(theme => ({
|
|
13
|
-
price: {
|
|
14
|
-
color: theme.palette.secondary.main,
|
|
15
|
-
display: 'inline-block',
|
|
16
|
-
fontWeight: theme.typography.fontWeightMedium,
|
|
17
|
-
textAlign: 'center'
|
|
18
|
-
},
|
|
19
|
-
editableContainer: {
|
|
20
|
-
position: 'relative'
|
|
21
|
-
},
|
|
22
13
|
editableField: {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
left: 0,
|
|
14
|
+
color: theme.palette.text.primary,
|
|
15
|
+
fontWeight: theme.typography.fontWeightMedium,
|
|
26
16
|
textAlign: 'center',
|
|
27
|
-
background:
|
|
28
|
-
zIndex: 2,
|
|
29
|
-
textIndent: -800,
|
|
17
|
+
background: theme.palette.background.surface,
|
|
30
18
|
outline: 'none',
|
|
31
|
-
padding: 0,
|
|
32
|
-
margin: 0,
|
|
33
|
-
border:
|
|
19
|
+
padding: theme.spacing(0.5, 0),
|
|
20
|
+
margin: theme.spacing(0, 0.5),
|
|
21
|
+
border: `1px solid ${theme.components.input.border}`,
|
|
34
22
|
borderRadius: 3,
|
|
35
23
|
':focus': {
|
|
36
|
-
background: theme.components.input.background,
|
|
37
|
-
textIndent: 0,
|
|
38
24
|
borderColor: theme.components.border.medium
|
|
39
25
|
},
|
|
40
26
|
[responsiveMediaQuery('>=xs', {
|
|
41
27
|
webOnly: true
|
|
42
28
|
})]: {
|
|
43
29
|
borderColor: theme.palette.primary.main,
|
|
44
|
-
padding: '4px 0',
|
|
45
|
-
top: -4,
|
|
46
30
|
':focus': {
|
|
47
31
|
borderColor: theme.palette.primary.main
|
|
48
32
|
}
|
|
@@ -58,9 +42,24 @@ const useStyles = makeStyles()(theme => ({
|
|
|
58
42
|
clip: 'rect(0, 0, 0, 0)',
|
|
59
43
|
whiteSpace: 'nowrap',
|
|
60
44
|
border: 0
|
|
45
|
+
},
|
|
46
|
+
priceField: {
|
|
47
|
+
display: 'inline-flex',
|
|
48
|
+
alignItems: 'center'
|
|
49
|
+
},
|
|
50
|
+
currencySymbol: {
|
|
51
|
+
color: theme.palette.text.secondary,
|
|
52
|
+
marginRight: theme.spacing(0.25)
|
|
61
53
|
}
|
|
62
54
|
}));
|
|
63
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Builds the width a price field needs to fit the longer of its value and the highest price.
|
|
58
|
+
* @param {number} length Amount of characters the field has to fit.
|
|
59
|
+
* @returns {string}
|
|
60
|
+
*/
|
|
61
|
+
const fieldWidth = length => `${length + 2}ch`;
|
|
62
|
+
|
|
64
63
|
/**
|
|
65
64
|
* The filter price range slider label component.
|
|
66
65
|
* @param {Object} props The component props.
|
|
@@ -78,10 +77,6 @@ function Label(props) {
|
|
|
78
77
|
} = props;
|
|
79
78
|
const [minValue, setMinValue] = useState(priceMin);
|
|
80
79
|
const [maxValue, setMaxValue] = useState(priceMax);
|
|
81
|
-
const [minOffset, setMinOffset] = useState(0);
|
|
82
|
-
const [maxOffset, setMMaxOffset] = useState(0);
|
|
83
|
-
const minRef = useRef(null);
|
|
84
|
-
const maxRef = useRef(null);
|
|
85
80
|
|
|
86
81
|
// Set new values, when prices change from outside.
|
|
87
82
|
useEffect(() => {
|
|
@@ -89,12 +84,6 @@ function Label(props) {
|
|
|
89
84
|
setMaxValue(priceMax);
|
|
90
85
|
}, [priceMin, priceMax]);
|
|
91
86
|
|
|
92
|
-
// Store the leftOffset when the reference changes.
|
|
93
|
-
useEffect(() => {
|
|
94
|
-
setMinOffset(minRef.current.offsetLeft);
|
|
95
|
-
setMMaxOffset(maxRef.current.offsetLeft);
|
|
96
|
-
}, [minRef, maxRef]);
|
|
97
|
-
|
|
98
87
|
/**
|
|
99
88
|
* Selects the field content on click.
|
|
100
89
|
* @param {SyntheticEvent} event The click event object.
|
|
@@ -102,7 +91,7 @@ function Label(props) {
|
|
|
102
91
|
function handleFieldClick({
|
|
103
92
|
target
|
|
104
93
|
}) {
|
|
105
|
-
target.
|
|
94
|
+
target.select();
|
|
106
95
|
}
|
|
107
96
|
|
|
108
97
|
/**
|
|
@@ -135,7 +124,6 @@ function Label(props) {
|
|
|
135
124
|
currency
|
|
136
125
|
}).format('0').replace('0.00', '');
|
|
137
126
|
return /*#__PURE__*/_jsxs("div", {
|
|
138
|
-
className: classes.editableContainer,
|
|
139
127
|
children: [/*#__PURE__*/_jsx("span", {
|
|
140
128
|
className: classes.srOnly,
|
|
141
129
|
children: i18n.text('price.range', {
|
|
@@ -147,70 +135,57 @@ function Label(props) {
|
|
|
147
135
|
"aria-hidden": true,
|
|
148
136
|
children: [/*#__PURE__*/_jsx(I18n.Placeholder, {
|
|
149
137
|
forKey: "fromPrice",
|
|
150
|
-
children: /*#__PURE__*/
|
|
151
|
-
className: classes.
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
138
|
+
children: /*#__PURE__*/_jsxs("span", {
|
|
139
|
+
className: classes.priceField,
|
|
140
|
+
children: [/*#__PURE__*/_jsx("span", {
|
|
141
|
+
"aria-hidden": true,
|
|
142
|
+
className: classes.currencySymbol,
|
|
143
|
+
id: "price-slider-currency-label-min",
|
|
144
|
+
children: currencySymbol
|
|
145
|
+
}), /*#__PURE__*/_jsx("input", {
|
|
146
|
+
type: "number",
|
|
147
|
+
inputMode: "numeric",
|
|
148
|
+
pattern: "[0-9]*",
|
|
149
|
+
id: "priceMin",
|
|
150
|
+
name: "priceMin",
|
|
151
|
+
value: minValue,
|
|
152
|
+
onChange: handleChangeMin,
|
|
153
|
+
onClick: handleFieldClick,
|
|
154
|
+
style: {
|
|
155
|
+
width: fieldWidth(Math.max(priceLength, String(minValue).length))
|
|
156
|
+
},
|
|
157
|
+
className: classes.editableField,
|
|
158
|
+
"aria-label": i18n.text('price.range_from'),
|
|
159
|
+
"aria-describedby": "price-slider-currency-label-min"
|
|
160
|
+
})]
|
|
161
161
|
})
|
|
162
162
|
}), /*#__PURE__*/_jsx(I18n.Placeholder, {
|
|
163
163
|
forKey: "toPrice",
|
|
164
|
-
children: /*#__PURE__*/
|
|
165
|
-
className: classes.
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
164
|
+
children: /*#__PURE__*/_jsxs("span", {
|
|
165
|
+
className: classes.priceField,
|
|
166
|
+
children: [/*#__PURE__*/_jsx("span", {
|
|
167
|
+
"aria-hidden": true,
|
|
168
|
+
className: classes.currencySymbol,
|
|
169
|
+
id: "price-slider-currency-label-max",
|
|
170
|
+
children: currencySymbol
|
|
171
|
+
}), /*#__PURE__*/_jsx("input", {
|
|
172
|
+
type: "number",
|
|
173
|
+
inputMode: "numeric",
|
|
174
|
+
pattern: "[0-9]*",
|
|
175
|
+
id: "priceMax",
|
|
176
|
+
name: "priceMax",
|
|
177
|
+
value: maxValue,
|
|
178
|
+
onChange: handleChangeMax,
|
|
179
|
+
onClick: handleFieldClick,
|
|
180
|
+
style: {
|
|
181
|
+
width: fieldWidth(Math.max(priceLength, String(maxValue).length))
|
|
182
|
+
},
|
|
183
|
+
className: classes.editableField,
|
|
184
|
+
"aria-label": i18n.text('price.range_to'),
|
|
185
|
+
"aria-describedby": "price-slider-currency-label-max"
|
|
186
|
+
})]
|
|
175
187
|
})
|
|
176
188
|
})]
|
|
177
|
-
}), /*#__PURE__*/_jsx("span", {
|
|
178
|
-
"aria-hidden": true,
|
|
179
|
-
hidden: true,
|
|
180
|
-
id: "price-slider-currency-label",
|
|
181
|
-
children: currencySymbol
|
|
182
|
-
}), /*#__PURE__*/_jsx("input", {
|
|
183
|
-
type: "number",
|
|
184
|
-
inputMode: "numeric",
|
|
185
|
-
pattern: "[0-9]*",
|
|
186
|
-
id: "priceMin",
|
|
187
|
-
name: "priceMin",
|
|
188
|
-
value: minValue,
|
|
189
|
-
onChange: handleChangeMin,
|
|
190
|
-
onClick: handleFieldClick,
|
|
191
|
-
style: {
|
|
192
|
-
width: priceLength,
|
|
193
|
-
left: minOffset
|
|
194
|
-
},
|
|
195
|
-
className: classes.editableField,
|
|
196
|
-
"aria-label": i18n.text('price.range_from'),
|
|
197
|
-
"aria-describedby": "price-slider-currency-label"
|
|
198
|
-
}), /*#__PURE__*/_jsx("input", {
|
|
199
|
-
type: "number",
|
|
200
|
-
inputMode: "numeric",
|
|
201
|
-
pattern: "[0-9]*",
|
|
202
|
-
id: "priceMax",
|
|
203
|
-
name: "priceMax",
|
|
204
|
-
value: maxValue,
|
|
205
|
-
onChange: handleChangeMax,
|
|
206
|
-
onClick: handleFieldClick,
|
|
207
|
-
style: {
|
|
208
|
-
width: priceLength,
|
|
209
|
-
left: maxOffset
|
|
210
|
-
},
|
|
211
|
-
className: classes.editableField,
|
|
212
|
-
"aria-label": i18n.text('price.range_to'),
|
|
213
|
-
"aria-describedby": "price-slider-currency-label"
|
|
214
189
|
})]
|
|
215
190
|
});
|
|
216
191
|
}
|