@riosst100/pwa-marketplace 1.2.4 → 1.2.5
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/package.json +1 -1
- package/src/componentOverrideMapping.js +2 -1
- package/src/components/Filter/index.js +7 -7
- package/src/components/OperatingHours/index.js +1 -0
- package/src/components/OperatingHours/operatingHours.js +32 -0
- package/src/components/Pagination/index.js +26 -17
- package/src/components/Search/index.js +1 -1
- package/src/components/Seller/seller.js +137 -46
- package/src/components/Seller/sellerAddressCard.js +48 -0
- package/src/components/SellerDetail/index.js +1 -0
- package/src/components/SellerDetail/sellerDetail.js +158 -0
- package/src/components/SellerInformation/sellerInformation.js +51 -26
- package/src/components/SellerLocation/sellerLocation.js +6 -2
- package/src/components/SellerLocation/sellerLocationItem.js +6 -8
- package/src/components/SellerProducts/sellerProducts.js +33 -12
- package/src/components/SellerReview/sellerReview.js +29 -29
- package/src/components/SellerReviewItem/sellerReviewItem.js +8 -8
- package/src/components/SortBy/index.js +13 -5
- package/src/components/commons/Tabs/index.js +11 -9
- package/src/overwrites/venia-ui/lib/components/Header/header.js +46 -34
- package/src/overwrites/venia-ui/lib/components/MegaMenu/__tests__/MegaMenu.spec.js +91 -0
- package/src/overwrites/venia-ui/lib/components/MegaMenu/__tests__/MegaMenuItem.spec.js +123 -0
- package/src/overwrites/venia-ui/lib/components/MegaMenu/__tests__/Submenu.spec.js +61 -0
- package/src/overwrites/venia-ui/lib/components/MegaMenu/__tests__/SubmenuColumn.spec.js +50 -0
- package/src/overwrites/venia-ui/lib/components/MegaMenu/__tests__/__snapshots__/MegaMenu.spec.js.snap +114 -0
- package/src/overwrites/venia-ui/lib/components/MegaMenu/__tests__/__snapshots__/MegaMenuItem.spec.js.snap +71 -0
- package/src/overwrites/venia-ui/lib/components/MegaMenu/__tests__/__snapshots__/Submenu.spec.js.snap +59 -0
- package/src/overwrites/venia-ui/lib/components/MegaMenu/__tests__/__snapshots__/SubmenuColumn.spec.js.snap +34 -0
- package/src/overwrites/venia-ui/lib/components/MegaMenu/index.js +1 -0
- package/src/overwrites/venia-ui/lib/components/MegaMenu/megaMenu.js +90 -0
- package/src/overwrites/venia-ui/lib/components/MegaMenu/megaMenu.module.css +12 -0
- package/src/overwrites/venia-ui/lib/components/MegaMenu/megaMenuItem.js +156 -0
- package/src/overwrites/venia-ui/lib/components/MegaMenu/megaMenuItem.module.css +31 -0
- package/src/overwrites/venia-ui/lib/components/MegaMenu/submenu.js +89 -0
- package/src/overwrites/venia-ui/lib/components/MegaMenu/submenu.module.css +43 -0
- package/src/overwrites/venia-ui/lib/components/MegaMenu/submenuColumn.js +99 -0
- package/src/overwrites/venia-ui/lib/components/MegaMenu/submenuColumn.module.css +28 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/__stories__/searchBar.js +11 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/__tests__/__snapshots__/searchField.spec.js.snap +72 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/__tests__/__snapshots__/suggestedCategories.spec.js.snap +30 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/__tests__/__snapshots__/suggestedProduct.spec.js.snap +69 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/__tests__/__snapshots__/suggestedProducts.spec.js.snap +7 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/__tests__/__snapshots__/suggestions.spec.js.snap +12 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/__tests__/autocomplete.spec.js +52 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/__tests__/searchBar.spec.js +82 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/__tests__/searchField.spec.js +87 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/__tests__/suggestedCategories.spec.js +45 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/__tests__/suggestedProduct.spec.js +43 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/__tests__/suggestedProducts.spec.js +45 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/__tests__/suggestions.spec.js +110 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/autocomplete.js +172 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/autocomplete.module.css +62 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/index.js +1 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/searchBar.js +74 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/searchBar.module.css +50 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/searchField.js +40 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/suggestedCategories.js +48 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/suggestedCategories.module.css +13 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/suggestedCategory.js +49 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/suggestedCategory.module.css +0 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/suggestedProduct.js +97 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/suggestedProduct.module.css +24 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/suggestedProducts.js +43 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/suggestedProducts.module.css +13 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/suggestions.js +75 -0
- package/src/overwrites/venia-ui/lib/components/SearchBar/suggestions.module.css +6 -0
- package/src/talons/Seller/seller.gql.js +70 -5
- package/src/talons/Seller/useSeller.js +6 -1
- package/src/talons/SellerProducts/useSellerProducts.js +129 -0
- package/src/theme/vars.js +7 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { createTestInstance } from '@magento/peregrine';
|
|
3
|
+
|
|
4
|
+
import Suggestions from '../suggestions';
|
|
5
|
+
|
|
6
|
+
jest.mock('../suggestedCategories', () => () => null);
|
|
7
|
+
jest.mock('../suggestedProducts', () => () => null);
|
|
8
|
+
|
|
9
|
+
test('renders correctly', () => {
|
|
10
|
+
const products = {
|
|
11
|
+
items: [{}]
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const filters = [];
|
|
15
|
+
|
|
16
|
+
const instance = createTestInstance(
|
|
17
|
+
<Suggestions
|
|
18
|
+
displayResult={true}
|
|
19
|
+
filters={filters}
|
|
20
|
+
products={products}
|
|
21
|
+
visible={true}
|
|
22
|
+
/>
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
expect(instance.toJSON()).toMatchSnapshot();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('renders null if there are no items', () => {
|
|
29
|
+
const products = {
|
|
30
|
+
aggregations: [],
|
|
31
|
+
items: null
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const { root } = createTestInstance(
|
|
35
|
+
<Suggestions displayResult={true} products={products} visible={true} />
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
expect(root.children).toEqual([]);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('renders null if displayResult is false', () => {
|
|
42
|
+
const products = {
|
|
43
|
+
aggregations: [],
|
|
44
|
+
items: []
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const { root } = createTestInstance(
|
|
48
|
+
<Suggestions displayResult={false} products={products} visible={true} />
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
expect(root.children).toEqual([]);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('renders null if visible is false', () => {
|
|
55
|
+
const products = {
|
|
56
|
+
items: []
|
|
57
|
+
};
|
|
58
|
+
const filters = [];
|
|
59
|
+
|
|
60
|
+
const { root } = createTestInstance(
|
|
61
|
+
<Suggestions
|
|
62
|
+
displayResult={true}
|
|
63
|
+
filters={filters}
|
|
64
|
+
products={products}
|
|
65
|
+
visible={false}
|
|
66
|
+
/>
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
expect(root.children).toEqual([]);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test('renders null if items array is empty', () => {
|
|
73
|
+
const products = {
|
|
74
|
+
items: []
|
|
75
|
+
};
|
|
76
|
+
const filters = [];
|
|
77
|
+
|
|
78
|
+
const { root } = createTestInstance(
|
|
79
|
+
<Suggestions
|
|
80
|
+
displayResult={true}
|
|
81
|
+
filters={filters}
|
|
82
|
+
products={products}
|
|
83
|
+
visible={true}
|
|
84
|
+
/>
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
expect(root.children).toEqual([]);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('renders a category list', () => {
|
|
91
|
+
const filters = [
|
|
92
|
+
{ label: 'Color', options: [] },
|
|
93
|
+
{ label: 'Category', options: [] }
|
|
94
|
+
];
|
|
95
|
+
|
|
96
|
+
const products = {
|
|
97
|
+
items: [{}]
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const { root } = createTestInstance(
|
|
101
|
+
<Suggestions
|
|
102
|
+
displayResult={true}
|
|
103
|
+
filters={filters}
|
|
104
|
+
products={products}
|
|
105
|
+
visible={true}
|
|
106
|
+
/>
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
expect(root.findByProps({ categories: filters[1].options })).toBeTruthy();
|
|
110
|
+
});
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { gql } from '@apollo/client';
|
|
3
|
+
import { bool, func, shape, string } from 'prop-types';
|
|
4
|
+
import { useAutocomplete } from '@magento/peregrine/lib/talons/SearchBar';
|
|
5
|
+
import { useIntl } from 'react-intl';
|
|
6
|
+
|
|
7
|
+
import defaultClasses from './autocomplete.module.css';
|
|
8
|
+
import { useStyle } from '@magento/venia-ui/lib/classify';
|
|
9
|
+
import Suggestions from './suggestions';
|
|
10
|
+
|
|
11
|
+
const GET_AUTOCOMPLETE_RESULTS = gql`
|
|
12
|
+
query getAutocompleteResults($inputText: String!) {
|
|
13
|
+
# Limit results to first three.
|
|
14
|
+
products(search: $inputText, currentPage: 1, pageSize: 3) {
|
|
15
|
+
aggregations {
|
|
16
|
+
label
|
|
17
|
+
count
|
|
18
|
+
attribute_code
|
|
19
|
+
options {
|
|
20
|
+
label
|
|
21
|
+
value
|
|
22
|
+
}
|
|
23
|
+
position
|
|
24
|
+
}
|
|
25
|
+
# eslint-disable-next-line @graphql-eslint/require-id-when-available
|
|
26
|
+
items {
|
|
27
|
+
id
|
|
28
|
+
uid
|
|
29
|
+
sku
|
|
30
|
+
name
|
|
31
|
+
small_image {
|
|
32
|
+
url
|
|
33
|
+
}
|
|
34
|
+
url_key
|
|
35
|
+
url_suffix
|
|
36
|
+
price {
|
|
37
|
+
regularPrice {
|
|
38
|
+
amount {
|
|
39
|
+
value
|
|
40
|
+
currency
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
price_range {
|
|
45
|
+
maximum_price {
|
|
46
|
+
final_price {
|
|
47
|
+
currency
|
|
48
|
+
value
|
|
49
|
+
}
|
|
50
|
+
discount {
|
|
51
|
+
amount_off
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
page_info {
|
|
57
|
+
total_pages
|
|
58
|
+
}
|
|
59
|
+
total_count
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
`;
|
|
63
|
+
|
|
64
|
+
const Autocomplete = props => {
|
|
65
|
+
const { setVisible, valid, visible } = props;
|
|
66
|
+
const talonProps = useAutocomplete({
|
|
67
|
+
queries: {
|
|
68
|
+
getAutocompleteResults: GET_AUTOCOMPLETE_RESULTS
|
|
69
|
+
},
|
|
70
|
+
valid,
|
|
71
|
+
visible
|
|
72
|
+
});
|
|
73
|
+
const {
|
|
74
|
+
displayResult,
|
|
75
|
+
filters,
|
|
76
|
+
messageType,
|
|
77
|
+
products,
|
|
78
|
+
resultCount,
|
|
79
|
+
value
|
|
80
|
+
} = talonProps;
|
|
81
|
+
|
|
82
|
+
const classes = useStyle(defaultClasses, props.classes);
|
|
83
|
+
const rootClassName = visible ? classes.root_visible : classes.root_hidden;
|
|
84
|
+
|
|
85
|
+
const { formatMessage } = useIntl();
|
|
86
|
+
const MESSAGES = new Map()
|
|
87
|
+
.set(
|
|
88
|
+
'ERROR',
|
|
89
|
+
formatMessage({
|
|
90
|
+
id: 'autocomplete.error',
|
|
91
|
+
defaultMessage: 'An error occurred while fetching results.'
|
|
92
|
+
})
|
|
93
|
+
)
|
|
94
|
+
.set(
|
|
95
|
+
'LOADING',
|
|
96
|
+
formatMessage({
|
|
97
|
+
id: 'autocomplete.loading',
|
|
98
|
+
defaultMessage: 'Fetching results...'
|
|
99
|
+
})
|
|
100
|
+
)
|
|
101
|
+
.set(
|
|
102
|
+
'PROMPT',
|
|
103
|
+
formatMessage({
|
|
104
|
+
id: 'autocomplete.prompt',
|
|
105
|
+
defaultMessage: 'Search for a product'
|
|
106
|
+
})
|
|
107
|
+
)
|
|
108
|
+
.set(
|
|
109
|
+
'EMPTY_RESULT',
|
|
110
|
+
formatMessage({
|
|
111
|
+
id: 'autocomplete.emptyResult',
|
|
112
|
+
defaultMessage: 'No results were found.'
|
|
113
|
+
})
|
|
114
|
+
)
|
|
115
|
+
.set('RESULT_SUMMARY', (_, resultCount) =>
|
|
116
|
+
formatMessage(
|
|
117
|
+
{
|
|
118
|
+
id: 'autocomplete.resultSummary',
|
|
119
|
+
defaultMessage: '{resultCount} items'
|
|
120
|
+
},
|
|
121
|
+
{ resultCount: resultCount }
|
|
122
|
+
)
|
|
123
|
+
)
|
|
124
|
+
.set(
|
|
125
|
+
'INVALID_CHARACTER_LENGTH',
|
|
126
|
+
formatMessage({
|
|
127
|
+
id: 'autocomplete.invalidCharacterLength',
|
|
128
|
+
defaultMessage: 'Search term must be at least three characters'
|
|
129
|
+
})
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
const messageTpl = MESSAGES.get(messageType);
|
|
133
|
+
const message =
|
|
134
|
+
typeof messageTpl === 'function'
|
|
135
|
+
? messageTpl`${resultCount}`
|
|
136
|
+
: messageTpl;
|
|
137
|
+
|
|
138
|
+
return (
|
|
139
|
+
<div data-cy="Autocomplete-root" className={rootClassName}>
|
|
140
|
+
<label
|
|
141
|
+
id="search_query"
|
|
142
|
+
data-cy="Autocomplete-message"
|
|
143
|
+
className={classes.message}
|
|
144
|
+
>
|
|
145
|
+
{message}
|
|
146
|
+
</label>
|
|
147
|
+
<div className={classes.suggestions}>
|
|
148
|
+
<Suggestions
|
|
149
|
+
displayResult={displayResult}
|
|
150
|
+
products={products || {}}
|
|
151
|
+
filters={filters}
|
|
152
|
+
searchValue={value}
|
|
153
|
+
setVisible={setVisible}
|
|
154
|
+
visible={visible}
|
|
155
|
+
/>
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
);
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export default Autocomplete;
|
|
162
|
+
|
|
163
|
+
Autocomplete.propTypes = {
|
|
164
|
+
classes: shape({
|
|
165
|
+
message: string,
|
|
166
|
+
root_hidden: string,
|
|
167
|
+
root_visible: string,
|
|
168
|
+
suggestions: string
|
|
169
|
+
}),
|
|
170
|
+
setVisible: func,
|
|
171
|
+
visible: bool
|
|
172
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
.root {
|
|
2
|
+
composes: absolute from global;
|
|
3
|
+
composes: bg-white from global;
|
|
4
|
+
composes: border-2 from global;
|
|
5
|
+
composes: border-input from global;
|
|
6
|
+
composes: border-solid from global;
|
|
7
|
+
composes: border-t-0 from global;
|
|
8
|
+
composes: gap-3 from global;
|
|
9
|
+
composes: grid from global;
|
|
10
|
+
composes: left-0 from global;
|
|
11
|
+
composes: p-xs from global;
|
|
12
|
+
composes: right-0 from global;
|
|
13
|
+
composes: rounded-b-md from global;
|
|
14
|
+
composes: rounded-t-none from global;
|
|
15
|
+
composes: shadow-inputFocus from global;
|
|
16
|
+
composes: text-sm from global;
|
|
17
|
+
composes: top-9 from global;
|
|
18
|
+
composes: z-menu from global;
|
|
19
|
+
transition-property: opacity, transform, visibility;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.root_hidden {
|
|
23
|
+
composes: root;
|
|
24
|
+
|
|
25
|
+
composes: invisible from global;
|
|
26
|
+
composes: opacity-0 from global;
|
|
27
|
+
transform: translate3d(0, -2rem, 0);
|
|
28
|
+
transition-duration: 192ms;
|
|
29
|
+
transition-timing-function: var(--venia-global-anim-out);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.root_visible {
|
|
33
|
+
composes: root;
|
|
34
|
+
|
|
35
|
+
composes: opacity-100 from global;
|
|
36
|
+
composes: visible from global;
|
|
37
|
+
transform: translate3d(0, 0, 0);
|
|
38
|
+
transition-duration: 224ms;
|
|
39
|
+
transition-timing-function: var(--venia-global-anim-in);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.message {
|
|
43
|
+
composes: px-3 from global;
|
|
44
|
+
composes: py-0 from global;
|
|
45
|
+
composes: text-center from global;
|
|
46
|
+
composes: text-subtle from global;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* TODO @TW: cannot compose */
|
|
50
|
+
.message:empty {
|
|
51
|
+
padding: 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.suggestions {
|
|
55
|
+
composes: gap-2xs from global;
|
|
56
|
+
composes: grid from global;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* TODO @TW: cannot compose */
|
|
60
|
+
.suggestions:empty {
|
|
61
|
+
display: none;
|
|
62
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './searchBar';
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { bool, shape, string } from 'prop-types';
|
|
3
|
+
import { Form } from 'informed';
|
|
4
|
+
import { useIntl } from 'react-intl';
|
|
5
|
+
import { useSearchBar } from '@magento/peregrine/lib/talons/SearchBar';
|
|
6
|
+
|
|
7
|
+
import { useStyle } from '@magento/venia-ui/lib/classify';
|
|
8
|
+
import Autocomplete from './autocomplete';
|
|
9
|
+
import SearchField from './searchField';
|
|
10
|
+
import defaultClasses from './searchBar.module.css';
|
|
11
|
+
|
|
12
|
+
const SearchBar = React.forwardRef((props, ref) => {
|
|
13
|
+
const { isOpen } = props;
|
|
14
|
+
const talonProps = useSearchBar();
|
|
15
|
+
const {
|
|
16
|
+
containerRef,
|
|
17
|
+
handleChange,
|
|
18
|
+
handleFocus,
|
|
19
|
+
handleSubmit,
|
|
20
|
+
initialValues,
|
|
21
|
+
isAutoCompleteOpen,
|
|
22
|
+
setIsAutoCompleteOpen,
|
|
23
|
+
valid
|
|
24
|
+
} = talonProps;
|
|
25
|
+
|
|
26
|
+
const classes = useStyle(defaultClasses, props.classes);
|
|
27
|
+
const rootClassName = isOpen ? classes.root_open : classes.root;
|
|
28
|
+
const { formatMessage } = useIntl();
|
|
29
|
+
return (
|
|
30
|
+
<div className={rootClassName} data-cy="SearchBar-root" ref={ref}>
|
|
31
|
+
<div ref={containerRef} className={classes.container}>
|
|
32
|
+
<Form
|
|
33
|
+
autoComplete="off"
|
|
34
|
+
className={classes.form}
|
|
35
|
+
initialValues={initialValues}
|
|
36
|
+
onSubmit={handleSubmit}
|
|
37
|
+
>
|
|
38
|
+
<div className={classes.search}>
|
|
39
|
+
<SearchField
|
|
40
|
+
addLabel={formatMessage({
|
|
41
|
+
id: 'global.clearText',
|
|
42
|
+
defaultMessage: 'Clear Text'
|
|
43
|
+
})}
|
|
44
|
+
isSearchOpen={isAutoCompleteOpen}
|
|
45
|
+
onChange={handleChange}
|
|
46
|
+
onFocus={handleFocus}
|
|
47
|
+
/>
|
|
48
|
+
<div className={classes.autocomplete}>
|
|
49
|
+
<Autocomplete
|
|
50
|
+
setVisible={setIsAutoCompleteOpen}
|
|
51
|
+
valid={valid}
|
|
52
|
+
visible={isAutoCompleteOpen}
|
|
53
|
+
/>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</Form>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
export default SearchBar;
|
|
63
|
+
|
|
64
|
+
SearchBar.propTypes = {
|
|
65
|
+
classes: shape({
|
|
66
|
+
autocomplete: string,
|
|
67
|
+
container: string,
|
|
68
|
+
form: string,
|
|
69
|
+
root: string,
|
|
70
|
+
root_open: string,
|
|
71
|
+
search: string
|
|
72
|
+
}),
|
|
73
|
+
isOpen: bool
|
|
74
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
.root {
|
|
2
|
+
composes: items-center from global;
|
|
3
|
+
composes: justify-items-center from global;
|
|
4
|
+
composes: justify-self-center from global;
|
|
5
|
+
composes: max-w-site from global;
|
|
6
|
+
composes: px-xs from global;
|
|
7
|
+
composes: py-0 from global;
|
|
8
|
+
composes: w-full from global;
|
|
9
|
+
|
|
10
|
+
/* TODO @TW: review (B6) */
|
|
11
|
+
/* composes: hidden from global; */
|
|
12
|
+
display: none;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.root_open {
|
|
16
|
+
composes: root;
|
|
17
|
+
|
|
18
|
+
composes: z-dropdown from global;
|
|
19
|
+
|
|
20
|
+
/* TODO @TW: review (B6) */
|
|
21
|
+
/* composes: grid from global; */
|
|
22
|
+
display: grid;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.form {
|
|
26
|
+
composes: grid from global;
|
|
27
|
+
composes: items-center from global;
|
|
28
|
+
composes: justify-items-stretch from global;
|
|
29
|
+
composes: w-full from global;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.container {
|
|
33
|
+
composes: inline-flex from global;
|
|
34
|
+
composes: items-center from global;
|
|
35
|
+
composes: justify-center from global;
|
|
36
|
+
composes: max-w-[24rem] from global;
|
|
37
|
+
composes: relative from global;
|
|
38
|
+
composes: w-full from global;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.search {
|
|
42
|
+
composes: grid from global;
|
|
43
|
+
composes: relative from global;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.autocomplete {
|
|
47
|
+
composes: grid from global;
|
|
48
|
+
/* composes: relative from global; */
|
|
49
|
+
composes: z-menu from global;
|
|
50
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { func } from 'prop-types';
|
|
3
|
+
import { useSearchField } from '@magento/peregrine/lib/talons/SearchBar';
|
|
4
|
+
import TextInput from '@magento/venia-ui/lib/components/TextInput';
|
|
5
|
+
import Trigger from '@magento/venia-ui/lib/components/Trigger';
|
|
6
|
+
import { SearchNormal } from 'iconsax-react';
|
|
7
|
+
import cn from 'classnames';
|
|
8
|
+
|
|
9
|
+
const SearchField = props => {
|
|
10
|
+
const { isSearchOpen, onChange, onFocus, addLabel } = props;
|
|
11
|
+
const { inputRef, resetForm, value } = useSearchField({ isSearchOpen });
|
|
12
|
+
|
|
13
|
+
const handleSearch = () => {
|
|
14
|
+
console.log('search');
|
|
15
|
+
}
|
|
16
|
+
const searchButton =
|
|
17
|
+
<Trigger action={handleSearch} addLabel={addLabel}>
|
|
18
|
+
<SearchNormal size="18" color="#280135" variant="Outline" />
|
|
19
|
+
</Trigger>
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<TextInput
|
|
23
|
+
id="search_query"
|
|
24
|
+
after={searchButton}
|
|
25
|
+
field="search_query"
|
|
26
|
+
data-cy="SearchField-textInput"
|
|
27
|
+
onFocus={onFocus}
|
|
28
|
+
onValueChange={onChange}
|
|
29
|
+
forwardedRef={inputRef}
|
|
30
|
+
classes={cn('search input')}
|
|
31
|
+
/>
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default SearchField;
|
|
36
|
+
|
|
37
|
+
SearchField.propTypes = {
|
|
38
|
+
onChange: func,
|
|
39
|
+
onFocus: func
|
|
40
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { arrayOf, func, number, shape, string } from 'prop-types';
|
|
3
|
+
|
|
4
|
+
import { useStyle } from '@magento/venia-ui/lib/classify';
|
|
5
|
+
import SuggestedCategory from './suggestedCategory';
|
|
6
|
+
import defaultClasses from './suggestedCategories.module.css';
|
|
7
|
+
|
|
8
|
+
const SuggestedCategories = props => {
|
|
9
|
+
const { categories, limit, onNavigate, value } = props;
|
|
10
|
+
const classes = useStyle(defaultClasses, props.classes);
|
|
11
|
+
|
|
12
|
+
const items = categories
|
|
13
|
+
.slice(0, limit)
|
|
14
|
+
.map(({ label, value: categoryId }) => (
|
|
15
|
+
<li key={categoryId} className={classes.item}>
|
|
16
|
+
<SuggestedCategory
|
|
17
|
+
categoryId={categoryId}
|
|
18
|
+
label={label}
|
|
19
|
+
onNavigate={onNavigate}
|
|
20
|
+
value={value}
|
|
21
|
+
/>
|
|
22
|
+
</li>
|
|
23
|
+
));
|
|
24
|
+
|
|
25
|
+
return <ul className={classes.root}>{items}</ul>;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default SuggestedCategories;
|
|
29
|
+
|
|
30
|
+
SuggestedCategories.defaultProps = {
|
|
31
|
+
limit: 4
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
SuggestedCategories.propTypes = {
|
|
35
|
+
categories: arrayOf(
|
|
36
|
+
shape({
|
|
37
|
+
label: string.isRequired,
|
|
38
|
+
value: string.isRequired
|
|
39
|
+
})
|
|
40
|
+
).isRequired,
|
|
41
|
+
classes: shape({
|
|
42
|
+
item: string,
|
|
43
|
+
root: string
|
|
44
|
+
}),
|
|
45
|
+
limit: number.isRequired,
|
|
46
|
+
onNavigate: func,
|
|
47
|
+
value: string
|
|
48
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
.root {
|
|
2
|
+
composes: border-t from global;
|
|
3
|
+
composes: border-solid from global;
|
|
4
|
+
composes: border-subtle from global;
|
|
5
|
+
composes: gap-3 from global;
|
|
6
|
+
composes: grid from global;
|
|
7
|
+
composes: pt-3 from global;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/* TODO @TW: cannot compose */
|
|
11
|
+
.root:empty {
|
|
12
|
+
display: none;
|
|
13
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { FormattedMessage } from 'react-intl';
|
|
3
|
+
import { func, shape, string } from 'prop-types';
|
|
4
|
+
import { Link } from 'react-router-dom';
|
|
5
|
+
import { useSuggestedCategory } from '@magento/peregrine/lib/talons/SearchBar';
|
|
6
|
+
|
|
7
|
+
import { useStyle } from '@magento/venia-ui/lib/classify';
|
|
8
|
+
import defaultClasses from './suggestedCategory.module.css';
|
|
9
|
+
|
|
10
|
+
const SuggestedCategory = props => {
|
|
11
|
+
const { categoryId, label, onNavigate, value } = props;
|
|
12
|
+
const talonProps = useSuggestedCategory({
|
|
13
|
+
categoryId,
|
|
14
|
+
label,
|
|
15
|
+
onNavigate,
|
|
16
|
+
searchValue: value
|
|
17
|
+
});
|
|
18
|
+
const { destination, handleClick } = talonProps;
|
|
19
|
+
const classes = useStyle(defaultClasses, props.classes);
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<Link className={classes.root} to={destination} onClick={handleClick}>
|
|
23
|
+
<strong className={classes.value}>{value}</strong>
|
|
24
|
+
<span className={classes.label}>
|
|
25
|
+
<FormattedMessage
|
|
26
|
+
id={'searchBar.label'}
|
|
27
|
+
defaultMessage={' in {label}'}
|
|
28
|
+
values={{
|
|
29
|
+
label
|
|
30
|
+
}}
|
|
31
|
+
/>
|
|
32
|
+
</span>
|
|
33
|
+
</Link>
|
|
34
|
+
);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export default SuggestedCategory;
|
|
38
|
+
|
|
39
|
+
SuggestedCategory.propTypes = {
|
|
40
|
+
categoryId: string,
|
|
41
|
+
classes: shape({
|
|
42
|
+
label: string,
|
|
43
|
+
root: string,
|
|
44
|
+
value: string
|
|
45
|
+
}),
|
|
46
|
+
label: string.isRequired,
|
|
47
|
+
onNavigate: func,
|
|
48
|
+
value: string.isRequired
|
|
49
|
+
};
|
|
File without changes
|