@riosst100/pwa-marketplace 1.8.0 → 1.8.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.
- package/i18n/id_ID.json +508 -508
- package/package.json +1 -2
- package/src/components/CustomSubCategory/subCategory.js +0 -14
- package/src/components/FilterTop/FilterBlockList/filterTopItemGroup.module.css +1 -1
- package/src/components/FilterTop/filterTop.js +2 -2
- package/src/components/FilterTop/filterTop.module.css +1 -1
- package/src/components/FilterTopBackup/CustomFilters/customFilter.js +83 -83
- package/src/components/FilterTopBackup/CustomFilters/customFilter.module.css +21 -21
- package/src/components/FilterTopBackup/CustomFilters/customFilters.js +131 -131
- package/src/components/FilterTopBackup/CustomFilters/customFilters.module.css +22 -22
- package/src/components/FilterTopBackup/CustomFilters/index.js +1 -1
- package/src/components/FilterTopBackup/filterTop.js +14 -14
- package/src/components/FilterTopBackup/filterTop.module.css +22 -22
- package/src/components/FilterTopBackup/filterTop.shimmer.js +24 -24
- package/src/components/FilterTopBackup/index.js +2 -2
- package/src/components/Header/websiteSwitcher.shimmer.js +6 -6
- package/src/components/Header/websiteSwitcherItem.js +47 -47
- package/src/components/Header/websiteSwitcherItem.module.css +20 -20
- package/src/components/LegoSets/legoSets.js +21 -72
- package/src/components/PhoneTextInput/index.js +1 -1
- package/src/components/PhoneTextInput/phoneTextInput.js +62 -62
- package/src/components/ProductListTab/index.js +4 -4
- package/src/components/ProductListTab/productListTab.module.css +64 -64
- package/src/components/ProductListTab/productListTab.shimmer.js +24 -24
- package/src/components/SellerCountry/index.js +1 -1
- package/src/components/SellerCountry/sellerCountry.js +71 -71
- package/src/components/SellerCountry/sellerCountry.module.css +3 -3
- package/src/components/ShopByCategory/index.js +2 -2
- package/src/components/ShopByCategory/shopByCategory.js +69 -69
- package/src/components/ShopByCategory/shopByCategory.module.css +58 -58
- package/src/components/ShopByCategory/shopByCategory.shimmer.js +24 -24
- package/src/components/SubCategory/subCategory.js +1 -1
- package/src/components/WebsiteSwitcher/websiteSwitcher.shimmer.js +6 -6
- package/src/components/WebsiteSwitcher/websiteSwitcherItem.js +47 -47
- package/src/components/WebsiteSwitcher/websiteSwitcherItem.module.css +20 -20
- package/src/overwrites/peregrine/lib/talons/MegaMenu/megaMenu.gql.js +96 -96
- package/src/overwrites/peregrine/lib/talons/MegaMenu/useMegaMenu.js +199 -199
- package/src/overwrites/peregrine/lib/talons/MegaMenu/useMegaMenuItem.js +66 -66
- package/src/overwrites/peregrine/lib/talons/MegaMenu/useSubMenu.js +20 -20
- package/src/overwrites/peregrine/lib/talons/ProductFullDetail/useProductFullDetail.js +642 -642
- package/src/overwrites/peregrine/lib/talons/RootComponents/Category/category.gql.js +49 -49
- package/src/overwrites/peregrine/lib/talons/RootComponents/Category/useCategory.js +227 -227
- package/src/overwrites/peregrine/lib/talons/RootComponents/Product/product.gql.js +31 -31
- package/src/overwrites/peregrine/lib/talons/RootComponents/Product/productDetailFragment.gql.js +235 -235
- package/src/overwrites/venia-ui/lib/components/Header/cartTrigger.module.css +47 -47
- package/src/overwrites/venia-ui/lib/components/RadioGroup/radio.js +60 -60
- package/src/overwrites/venia-ui/lib/components/RadioGroup/radio.module.css +70 -70
- package/src/talons/AttributesBlock/attributesBlock.gql.js +15 -15
- package/src/talons/CustomFilters/customFilters.gql.js +45 -45
- package/src/talons/CustomFilters/useCustomFilters.js +5 -2
- package/src/talons/FilterTop/filterTop.gql.js +45 -45
- package/src/talons/FilterTop/index.js +1 -1
- package/src/talons/FilterTop/useFilterTop.js +9 -3
- package/src/talons/Header/websiteSwitcher.gql.js +45 -45
- package/src/talons/LegoSets/legoSets.gql.js +2 -2
- package/src/talons/LegoSets/useLegoSets.js +6 -56
- package/src/talons/SellerReview/sellerReview.gql.js +53 -53
- package/src/talons/ShopByCategory/index.js +1 -1
- package/src/talons/ShopByCategory/shopByCategory.gql.js +38 -38
- package/src/talons/ShopByCategory/useShopByCategory.js +69 -69
- package/src/talons/SubCategory/subCategory.gql.js +15 -15
- package/src/talons/SubCategory/useSubCategory.js +3 -3
- package/src/talons/WebsiteSwitcher/websiteSwitcher.gql.js +45 -45
|
@@ -1,199 +1,199 @@
|
|
|
1
|
-
import { useMemo, useState, useCallback, useEffect } from 'react';
|
|
2
|
-
import { useLocation } from 'react-router-dom';
|
|
3
|
-
import { useInternalLink } from '../../hooks/useInternalLink';
|
|
4
|
-
|
|
5
|
-
import { useQuery } from '@apollo/client';
|
|
6
|
-
import { useEventListener } from '../../hooks/useEventListener';
|
|
7
|
-
|
|
8
|
-
import mergeOperations from '../../util/shallowMerge';
|
|
9
|
-
import DEFAULT_OPERATIONS from './megaMenu.gql';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* The useMegaMenu talon complements the MegaMenu component.
|
|
13
|
-
*
|
|
14
|
-
* @param {Object} props
|
|
15
|
-
* @param {*} props.operations GraphQL operations used by talons
|
|
16
|
-
* @param {React.RefObject} props.mainNavRef Reference to main navigation DOM node
|
|
17
|
-
*
|
|
18
|
-
* @return {MegaMenuTalonProps}
|
|
19
|
-
*/
|
|
20
|
-
export const useMegaMenu = (props = {}) => {
|
|
21
|
-
const operations = mergeOperations(DEFAULT_OPERATIONS, props.operations);
|
|
22
|
-
const { getMegaMenuQuery, getStoreConfigQuery } = operations;
|
|
23
|
-
|
|
24
|
-
const location = useLocation();
|
|
25
|
-
const [activeCategoryId, setActiveCategoryId] = useState(null);
|
|
26
|
-
const [subMenuState, setSubMenuState] = useState(false);
|
|
27
|
-
const [disableFocus, setDisableFocus] = useState(false);
|
|
28
|
-
|
|
29
|
-
const { data: storeConfigData } = useQuery(getStoreConfigQuery, {
|
|
30
|
-
fetchPolicy: 'cache-and-network'
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
const { data } = useQuery(getMegaMenuQuery, {
|
|
34
|
-
fetchPolicy: 'cache-and-network',
|
|
35
|
-
nextFetchPolicy: 'cache-first'
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
const categoryUrlSuffix = useMemo(() => {
|
|
39
|
-
if (storeConfigData) {
|
|
40
|
-
return storeConfigData.storeConfig.category_url_suffix;
|
|
41
|
-
}
|
|
42
|
-
}, [storeConfigData]);
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Check if category should be visible on the storefront.
|
|
46
|
-
*
|
|
47
|
-
* @param {MegaMenuCategory} category
|
|
48
|
-
* @returns {boolean}
|
|
49
|
-
*/
|
|
50
|
-
const shouldRenderMegaMenuItem = category => {
|
|
51
|
-
return !!category.include_in_menu;
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Check if category is the active category based on the current location.
|
|
56
|
-
*
|
|
57
|
-
* @param {MegaMenuCategory} category
|
|
58
|
-
* @returns {boolean}
|
|
59
|
-
*/
|
|
60
|
-
|
|
61
|
-
const isActive = useCallback(
|
|
62
|
-
({ url_path }) => {
|
|
63
|
-
if (!url_path) return false;
|
|
64
|
-
|
|
65
|
-
const categoryUrlPath = `/${url_path}${categoryUrlSuffix || ''}`;
|
|
66
|
-
|
|
67
|
-
return location.pathname === categoryUrlPath;
|
|
68
|
-
},
|
|
69
|
-
[location.pathname, categoryUrlSuffix]
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Recursively map data returned by GraphQL query.
|
|
74
|
-
*
|
|
75
|
-
* @param {MegaMenuCategory} category
|
|
76
|
-
* @param {array} - path from the given category to the first level category
|
|
77
|
-
* @param {boolean} isRoot - describes is category a root category
|
|
78
|
-
* @return {MegaMenuCategory}
|
|
79
|
-
*/
|
|
80
|
-
const processData = useCallback(
|
|
81
|
-
(category, path = [], isRoot = true) => {
|
|
82
|
-
if (!category) {
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const megaMenuCategory = Object.assign({}, category);
|
|
87
|
-
|
|
88
|
-
if (!isRoot) {
|
|
89
|
-
megaMenuCategory.path = [...path, category.uid];
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
megaMenuCategory.isActive = isActive(megaMenuCategory);
|
|
93
|
-
|
|
94
|
-
if (megaMenuCategory.children) {
|
|
95
|
-
megaMenuCategory.children = [...megaMenuCategory.children]
|
|
96
|
-
.filter(category => shouldRenderMegaMenuItem(category))
|
|
97
|
-
.sort((a, b) => (a.position > b.position ? 1 : -1))
|
|
98
|
-
.map(child =>
|
|
99
|
-
processData(child, megaMenuCategory.path, false)
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return megaMenuCategory;
|
|
104
|
-
},
|
|
105
|
-
[isActive]
|
|
106
|
-
);
|
|
107
|
-
|
|
108
|
-
const megaMenuData = useMemo(() => {
|
|
109
|
-
return data ? processData(data.categoryList[0]) : {};
|
|
110
|
-
}, [data, processData]);
|
|
111
|
-
|
|
112
|
-
const findActiveCategory = useCallback(
|
|
113
|
-
(pathname, category) => {
|
|
114
|
-
if (isActive(category)) {
|
|
115
|
-
return category;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (category.children) {
|
|
119
|
-
return category.children.find(category =>
|
|
120
|
-
findActiveCategory(pathname, category)
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
},
|
|
124
|
-
[isActive]
|
|
125
|
-
);
|
|
126
|
-
|
|
127
|
-
const handleClickOutside = e => {
|
|
128
|
-
if (!props.mainNavRef.current.contains(e.target)) {
|
|
129
|
-
setSubMenuState(false);
|
|
130
|
-
setDisableFocus(true);
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
useEventListener(globalThis, 'keydown', handleClickOutside);
|
|
135
|
-
|
|
136
|
-
const handleSubMenuFocus = useCallback(() => {
|
|
137
|
-
setSubMenuState(true);
|
|
138
|
-
}, [setSubMenuState]);
|
|
139
|
-
|
|
140
|
-
useEffect(() => {
|
|
141
|
-
const activeCategory = findActiveCategory(
|
|
142
|
-
location.pathname,
|
|
143
|
-
megaMenuData
|
|
144
|
-
);
|
|
145
|
-
|
|
146
|
-
if (activeCategory) {
|
|
147
|
-
setActiveCategoryId(activeCategory.path[0]);
|
|
148
|
-
} else {
|
|
149
|
-
setActiveCategoryId(null);
|
|
150
|
-
}
|
|
151
|
-
}, [findActiveCategory, location.pathname, megaMenuData]);
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Sets next root component to show proper loading effect
|
|
155
|
-
*
|
|
156
|
-
* @returns {void}
|
|
157
|
-
*/
|
|
158
|
-
const { setShimmerType } = useInternalLink('category');
|
|
159
|
-
|
|
160
|
-
return {
|
|
161
|
-
megaMenuData,
|
|
162
|
-
activeCategoryId,
|
|
163
|
-
categoryUrlSuffix,
|
|
164
|
-
handleClickOutside,
|
|
165
|
-
subMenuState,
|
|
166
|
-
disableFocus,
|
|
167
|
-
handleSubMenuFocus,
|
|
168
|
-
handleNavigate: setShimmerType
|
|
169
|
-
};
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
/** JSDocs type definitions */
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* @typedef {Object} MegaMenuTalonProps
|
|
176
|
-
*
|
|
177
|
-
* @property {MegaMenuCategory} megaMenuData - The Object with categories contains only categories
|
|
178
|
-
* with the include_in_menu = 1 flag. The categories are sorted
|
|
179
|
-
* based on the field position.
|
|
180
|
-
* @property {String} activeCategoryId returns the currently selected category uid.
|
|
181
|
-
* @property {String} categoryUrlSuffix store's category url suffix to construct category URL
|
|
182
|
-
* @property {Function} handleClickOutside function to handle mouse/key events.
|
|
183
|
-
* @property {Boolean} subMenuState maintaining sub-menu open/close state
|
|
184
|
-
* @property {Boolean} disableFocus state to disable focus
|
|
185
|
-
* @property {Function} handleSubMenuFocus toggle function to handle sub-menu focus
|
|
186
|
-
* @property {function} handleNavigate - callback to fire on link click
|
|
187
|
-
*/
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Object type returned by the {@link useMegaMenu} talon.
|
|
191
|
-
* @typedef {Object} MegaMenuCategory
|
|
192
|
-
*
|
|
193
|
-
* @property {String} uid - uid of the category
|
|
194
|
-
* @property {int} include_in_menu - describes if category should be included in menu
|
|
195
|
-
* @property {String} name - name of the category
|
|
196
|
-
* @property {int} position - value used for sorting
|
|
197
|
-
* @property {String} url_path - URL path for a category
|
|
198
|
-
* @property {MegaMenuCategory} children - child category
|
|
199
|
-
*/
|
|
1
|
+
import { useMemo, useState, useCallback, useEffect } from 'react';
|
|
2
|
+
import { useLocation } from 'react-router-dom';
|
|
3
|
+
import { useInternalLink } from '../../hooks/useInternalLink';
|
|
4
|
+
|
|
5
|
+
import { useQuery } from '@apollo/client';
|
|
6
|
+
import { useEventListener } from '../../hooks/useEventListener';
|
|
7
|
+
|
|
8
|
+
import mergeOperations from '../../util/shallowMerge';
|
|
9
|
+
import DEFAULT_OPERATIONS from './megaMenu.gql';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The useMegaMenu talon complements the MegaMenu component.
|
|
13
|
+
*
|
|
14
|
+
* @param {Object} props
|
|
15
|
+
* @param {*} props.operations GraphQL operations used by talons
|
|
16
|
+
* @param {React.RefObject} props.mainNavRef Reference to main navigation DOM node
|
|
17
|
+
*
|
|
18
|
+
* @return {MegaMenuTalonProps}
|
|
19
|
+
*/
|
|
20
|
+
export const useMegaMenu = (props = {}) => {
|
|
21
|
+
const operations = mergeOperations(DEFAULT_OPERATIONS, props.operations);
|
|
22
|
+
const { getMegaMenuQuery, getStoreConfigQuery } = operations;
|
|
23
|
+
|
|
24
|
+
const location = useLocation();
|
|
25
|
+
const [activeCategoryId, setActiveCategoryId] = useState(null);
|
|
26
|
+
const [subMenuState, setSubMenuState] = useState(false);
|
|
27
|
+
const [disableFocus, setDisableFocus] = useState(false);
|
|
28
|
+
|
|
29
|
+
const { data: storeConfigData } = useQuery(getStoreConfigQuery, {
|
|
30
|
+
fetchPolicy: 'cache-and-network'
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const { data } = useQuery(getMegaMenuQuery, {
|
|
34
|
+
fetchPolicy: 'cache-and-network',
|
|
35
|
+
nextFetchPolicy: 'cache-first'
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const categoryUrlSuffix = useMemo(() => {
|
|
39
|
+
if (storeConfigData) {
|
|
40
|
+
return storeConfigData.storeConfig.category_url_suffix;
|
|
41
|
+
}
|
|
42
|
+
}, [storeConfigData]);
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Check if category should be visible on the storefront.
|
|
46
|
+
*
|
|
47
|
+
* @param {MegaMenuCategory} category
|
|
48
|
+
* @returns {boolean}
|
|
49
|
+
*/
|
|
50
|
+
const shouldRenderMegaMenuItem = category => {
|
|
51
|
+
return !!category.include_in_menu;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Check if category is the active category based on the current location.
|
|
56
|
+
*
|
|
57
|
+
* @param {MegaMenuCategory} category
|
|
58
|
+
* @returns {boolean}
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
const isActive = useCallback(
|
|
62
|
+
({ url_path }) => {
|
|
63
|
+
if (!url_path) return false;
|
|
64
|
+
|
|
65
|
+
const categoryUrlPath = `/${url_path}${categoryUrlSuffix || ''}`;
|
|
66
|
+
|
|
67
|
+
return location.pathname === categoryUrlPath;
|
|
68
|
+
},
|
|
69
|
+
[location.pathname, categoryUrlSuffix]
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Recursively map data returned by GraphQL query.
|
|
74
|
+
*
|
|
75
|
+
* @param {MegaMenuCategory} category
|
|
76
|
+
* @param {array} - path from the given category to the first level category
|
|
77
|
+
* @param {boolean} isRoot - describes is category a root category
|
|
78
|
+
* @return {MegaMenuCategory}
|
|
79
|
+
*/
|
|
80
|
+
const processData = useCallback(
|
|
81
|
+
(category, path = [], isRoot = true) => {
|
|
82
|
+
if (!category) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const megaMenuCategory = Object.assign({}, category);
|
|
87
|
+
|
|
88
|
+
if (!isRoot) {
|
|
89
|
+
megaMenuCategory.path = [...path, category.uid];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
megaMenuCategory.isActive = isActive(megaMenuCategory);
|
|
93
|
+
|
|
94
|
+
if (megaMenuCategory.children) {
|
|
95
|
+
megaMenuCategory.children = [...megaMenuCategory.children]
|
|
96
|
+
.filter(category => shouldRenderMegaMenuItem(category))
|
|
97
|
+
.sort((a, b) => (a.position > b.position ? 1 : -1))
|
|
98
|
+
.map(child =>
|
|
99
|
+
processData(child, megaMenuCategory.path, false)
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return megaMenuCategory;
|
|
104
|
+
},
|
|
105
|
+
[isActive]
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
const megaMenuData = useMemo(() => {
|
|
109
|
+
return data ? processData(data.categoryList[0]) : {};
|
|
110
|
+
}, [data, processData]);
|
|
111
|
+
|
|
112
|
+
const findActiveCategory = useCallback(
|
|
113
|
+
(pathname, category) => {
|
|
114
|
+
if (isActive(category)) {
|
|
115
|
+
return category;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (category.children) {
|
|
119
|
+
return category.children.find(category =>
|
|
120
|
+
findActiveCategory(pathname, category)
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
[isActive]
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
const handleClickOutside = e => {
|
|
128
|
+
if (!props.mainNavRef.current.contains(e.target)) {
|
|
129
|
+
setSubMenuState(false);
|
|
130
|
+
setDisableFocus(true);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
useEventListener(globalThis, 'keydown', handleClickOutside);
|
|
135
|
+
|
|
136
|
+
const handleSubMenuFocus = useCallback(() => {
|
|
137
|
+
setSubMenuState(true);
|
|
138
|
+
}, [setSubMenuState]);
|
|
139
|
+
|
|
140
|
+
useEffect(() => {
|
|
141
|
+
const activeCategory = findActiveCategory(
|
|
142
|
+
location.pathname,
|
|
143
|
+
megaMenuData
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
if (activeCategory) {
|
|
147
|
+
setActiveCategoryId(activeCategory.path[0]);
|
|
148
|
+
} else {
|
|
149
|
+
setActiveCategoryId(null);
|
|
150
|
+
}
|
|
151
|
+
}, [findActiveCategory, location.pathname, megaMenuData]);
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Sets next root component to show proper loading effect
|
|
155
|
+
*
|
|
156
|
+
* @returns {void}
|
|
157
|
+
*/
|
|
158
|
+
const { setShimmerType } = useInternalLink('category');
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
megaMenuData,
|
|
162
|
+
activeCategoryId,
|
|
163
|
+
categoryUrlSuffix,
|
|
164
|
+
handleClickOutside,
|
|
165
|
+
subMenuState,
|
|
166
|
+
disableFocus,
|
|
167
|
+
handleSubMenuFocus,
|
|
168
|
+
handleNavigate: setShimmerType
|
|
169
|
+
};
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
/** JSDocs type definitions */
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* @typedef {Object} MegaMenuTalonProps
|
|
176
|
+
*
|
|
177
|
+
* @property {MegaMenuCategory} megaMenuData - The Object with categories contains only categories
|
|
178
|
+
* with the include_in_menu = 1 flag. The categories are sorted
|
|
179
|
+
* based on the field position.
|
|
180
|
+
* @property {String} activeCategoryId returns the currently selected category uid.
|
|
181
|
+
* @property {String} categoryUrlSuffix store's category url suffix to construct category URL
|
|
182
|
+
* @property {Function} handleClickOutside function to handle mouse/key events.
|
|
183
|
+
* @property {Boolean} subMenuState maintaining sub-menu open/close state
|
|
184
|
+
* @property {Boolean} disableFocus state to disable focus
|
|
185
|
+
* @property {Function} handleSubMenuFocus toggle function to handle sub-menu focus
|
|
186
|
+
* @property {function} handleNavigate - callback to fire on link click
|
|
187
|
+
*/
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Object type returned by the {@link useMegaMenu} talon.
|
|
191
|
+
* @typedef {Object} MegaMenuCategory
|
|
192
|
+
*
|
|
193
|
+
* @property {String} uid - uid of the category
|
|
194
|
+
* @property {int} include_in_menu - describes if category should be included in menu
|
|
195
|
+
* @property {String} name - name of the category
|
|
196
|
+
* @property {int} position - value used for sorting
|
|
197
|
+
* @property {String} url_path - URL path for a category
|
|
198
|
+
* @property {MegaMenuCategory} children - child category
|
|
199
|
+
*/
|
|
@@ -1,66 +1,66 @@
|
|
|
1
|
-
import { useCallback, useMemo, useState } from 'react';
|
|
2
|
-
|
|
3
|
-
export const useMegaMenuItem = props => {
|
|
4
|
-
const { category, activeCategoryId, subMenuState, disableFocus } = props;
|
|
5
|
-
|
|
6
|
-
const [isFocused, setIsFocused] = useState(false);
|
|
7
|
-
const isActive = category.id === activeCategoryId;
|
|
8
|
-
|
|
9
|
-
const handleMenuItemFocus = useCallback(() => {
|
|
10
|
-
setIsFocused(true);
|
|
11
|
-
}, [setIsFocused]);
|
|
12
|
-
|
|
13
|
-
const handleCloseSubMenu = useCallback(() => {
|
|
14
|
-
setIsFocused(false);
|
|
15
|
-
}, [setIsFocused]);
|
|
16
|
-
|
|
17
|
-
const isMenuActive = useMemo(() => {
|
|
18
|
-
if (!isFocused) {
|
|
19
|
-
return false;
|
|
20
|
-
}
|
|
21
|
-
if (subMenuState) {
|
|
22
|
-
return true;
|
|
23
|
-
} else if (disableFocus) {
|
|
24
|
-
setIsFocused(false);
|
|
25
|
-
}
|
|
26
|
-
return false;
|
|
27
|
-
}, [isFocused, subMenuState, disableFocus]);
|
|
28
|
-
|
|
29
|
-
const handleKeyDown = useCallback(
|
|
30
|
-
event => {
|
|
31
|
-
const { key: pressedKey, shiftKey } = event;
|
|
32
|
-
|
|
33
|
-
// checking down arrow and spacebar
|
|
34
|
-
if (pressedKey === 'ArrowDown' || pressedKey === ' ') {
|
|
35
|
-
event.preventDefault();
|
|
36
|
-
if (category.children.length || category.name == "Lego") {
|
|
37
|
-
setIsFocused(true);
|
|
38
|
-
} else {
|
|
39
|
-
setIsFocused(false);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
//checking up arrow or escape
|
|
46
|
-
if (pressedKey === 'ArrowUp' || pressedKey === 'Escape') {
|
|
47
|
-
setIsFocused(false);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
//checking Tab with Shift
|
|
51
|
-
if (shiftKey && pressedKey === 'Tab') {
|
|
52
|
-
setIsFocused(false);
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
|
-
[category.children.length, category.name]
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
return {
|
|
59
|
-
isFocused,
|
|
60
|
-
isActive,
|
|
61
|
-
handleMenuItemFocus,
|
|
62
|
-
handleCloseSubMenu,
|
|
63
|
-
isMenuActive,
|
|
64
|
-
handleKeyDown
|
|
65
|
-
};
|
|
66
|
-
};
|
|
1
|
+
import { useCallback, useMemo, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
export const useMegaMenuItem = props => {
|
|
4
|
+
const { category, activeCategoryId, subMenuState, disableFocus } = props;
|
|
5
|
+
|
|
6
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
7
|
+
const isActive = category.id === activeCategoryId;
|
|
8
|
+
|
|
9
|
+
const handleMenuItemFocus = useCallback(() => {
|
|
10
|
+
setIsFocused(true);
|
|
11
|
+
}, [setIsFocused]);
|
|
12
|
+
|
|
13
|
+
const handleCloseSubMenu = useCallback(() => {
|
|
14
|
+
setIsFocused(false);
|
|
15
|
+
}, [setIsFocused]);
|
|
16
|
+
|
|
17
|
+
const isMenuActive = useMemo(() => {
|
|
18
|
+
if (!isFocused) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
if (subMenuState) {
|
|
22
|
+
return true;
|
|
23
|
+
} else if (disableFocus) {
|
|
24
|
+
setIsFocused(false);
|
|
25
|
+
}
|
|
26
|
+
return false;
|
|
27
|
+
}, [isFocused, subMenuState, disableFocus]);
|
|
28
|
+
|
|
29
|
+
const handleKeyDown = useCallback(
|
|
30
|
+
event => {
|
|
31
|
+
const { key: pressedKey, shiftKey } = event;
|
|
32
|
+
|
|
33
|
+
// checking down arrow and spacebar
|
|
34
|
+
if (pressedKey === 'ArrowDown' || pressedKey === ' ') {
|
|
35
|
+
event.preventDefault();
|
|
36
|
+
if (category.children.length || category.name == "Lego") {
|
|
37
|
+
setIsFocused(true);
|
|
38
|
+
} else {
|
|
39
|
+
setIsFocused(false);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
//checking up arrow or escape
|
|
46
|
+
if (pressedKey === 'ArrowUp' || pressedKey === 'Escape') {
|
|
47
|
+
setIsFocused(false);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
//checking Tab with Shift
|
|
51
|
+
if (shiftKey && pressedKey === 'Tab') {
|
|
52
|
+
setIsFocused(false);
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
[category.children.length, category.name]
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
isFocused,
|
|
60
|
+
isActive,
|
|
61
|
+
handleMenuItemFocus,
|
|
62
|
+
handleCloseSubMenu,
|
|
63
|
+
isMenuActive,
|
|
64
|
+
handleKeyDown
|
|
65
|
+
};
|
|
66
|
+
};
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import { useKeyboard } from 'react-aria';
|
|
2
|
-
|
|
3
|
-
export const useSubMenu = props => {
|
|
4
|
-
const { isFocused, subMenuState, handleCloseSubMenu } = props;
|
|
5
|
-
|
|
6
|
-
const { keyboardProps } = useKeyboard({
|
|
7
|
-
onKeyDown: e => {
|
|
8
|
-
//checking for Tab without Shift
|
|
9
|
-
if (!e.shiftKey && e.key === 'Tab') {
|
|
10
|
-
e.target.addEventListener('blur', handleCloseSubMenu);
|
|
11
|
-
} else {
|
|
12
|
-
e.target.removeEventListener('blur', handleCloseSubMenu);
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
const isSubMenuActive = isFocused && subMenuState;
|
|
18
|
-
|
|
19
|
-
return { keyboardProps, isSubMenuActive };
|
|
20
|
-
};
|
|
1
|
+
import { useKeyboard } from 'react-aria';
|
|
2
|
+
|
|
3
|
+
export const useSubMenu = props => {
|
|
4
|
+
const { isFocused, subMenuState, handleCloseSubMenu } = props;
|
|
5
|
+
|
|
6
|
+
const { keyboardProps } = useKeyboard({
|
|
7
|
+
onKeyDown: e => {
|
|
8
|
+
//checking for Tab without Shift
|
|
9
|
+
if (!e.shiftKey && e.key === 'Tab') {
|
|
10
|
+
e.target.addEventListener('blur', handleCloseSubMenu);
|
|
11
|
+
} else {
|
|
12
|
+
e.target.removeEventListener('blur', handleCloseSubMenu);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const isSubMenuActive = isFocused && subMenuState;
|
|
18
|
+
|
|
19
|
+
return { keyboardProps, isSubMenuActive };
|
|
20
|
+
};
|