@blocklet/list 0.10.32 → 0.10.34
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/lib/assets/locale.js +0 -2
- package/lib/base.js +7 -24
- package/lib/components/aside.js +0 -10
- package/lib/components/autocomplete/index.js +8 -61
- package/lib/components/base-search.js +84 -0
- package/lib/components/custom-select/button.js +6 -22
- package/lib/components/custom-select/custom-select.js +9 -35
- package/lib/components/custom-select/index.js +0 -3
- package/lib/components/filter/custom-chip.js +5 -22
- package/lib/components/filter/group.js +0 -9
- package/lib/components/filter/icon.js +0 -18
- package/lib/components/filter/index.js +0 -4
- package/lib/components/list/empty.js +0 -13
- package/lib/components/list/index.js +3 -34
- package/lib/contexts/filter.js +9 -42
- package/lib/index.js +0 -16
- package/lib/libs/prop-types.js +4 -5
- package/lib/libs/utils.js +3 -44
- package/package.json +3 -4
- package/src/base.js +8 -1
- package/src/components/base-search.js +93 -0
- package/src/contexts/filter.js +2 -0
- package/src/libs/prop-types.js +2 -0
package/lib/libs/utils.js
CHANGED
|
@@ -4,24 +4,17 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.urlStringify = exports.toColorRgb = exports.replaceTranslate = exports.removeUndefined = exports.isMobileScreen = exports.getStoreDetail = exports.getSortOptions = exports.getPrices = exports.getCurrentPage = exports.getCategoryOptions = exports.formatLogoPath = exports.formatError = exports.filterBlockletByPrice = exports.debounced = void 0;
|
|
7
|
-
|
|
8
7
|
var _urlJoin = _interopRequireDefault(require("url-join"));
|
|
9
|
-
|
|
10
8
|
var _cloneDeep = _interopRequireDefault(require("lodash/cloneDeep"));
|
|
11
|
-
|
|
12
9
|
var _color = _interopRequireDefault(require("color"));
|
|
13
|
-
|
|
14
10
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
|
-
|
|
16
11
|
const isFreeBlocklet = blocklet => {
|
|
17
12
|
if (!blocklet.payment) {
|
|
18
13
|
return true;
|
|
19
14
|
}
|
|
20
|
-
|
|
21
15
|
const priceList = (blocklet.payment.price || []).map(x => x.value || 0);
|
|
22
16
|
return priceList.every(x => x === 0);
|
|
23
17
|
};
|
|
24
|
-
|
|
25
18
|
const getSortOptions = t => {
|
|
26
19
|
return [{
|
|
27
20
|
name: t('sort.popularity'),
|
|
@@ -37,9 +30,7 @@ const getSortOptions = t => {
|
|
|
37
30
|
value: 'nameDesc'
|
|
38
31
|
}];
|
|
39
32
|
};
|
|
40
|
-
|
|
41
33
|
exports.getSortOptions = getSortOptions;
|
|
42
|
-
|
|
43
34
|
const getPrices = t => {
|
|
44
35
|
return [{
|
|
45
36
|
name: t('blocklet.free'),
|
|
@@ -49,9 +40,7 @@ const getPrices = t => {
|
|
|
49
40
|
value: 'payment'
|
|
50
41
|
}];
|
|
51
42
|
};
|
|
52
|
-
|
|
53
43
|
exports.getPrices = getPrices;
|
|
54
|
-
|
|
55
44
|
const getCategoryOptions = function getCategoryOptions() {
|
|
56
45
|
let list = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
57
46
|
let locale = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'en';
|
|
@@ -60,66 +49,50 @@ const getCategoryOptions = function getCategoryOptions() {
|
|
|
60
49
|
value: item._id
|
|
61
50
|
}));
|
|
62
51
|
};
|
|
52
|
+
|
|
63
53
|
/**
|
|
64
54
|
* 根据 是否付费 过滤 blocklet list
|
|
65
55
|
* @param {*} list
|
|
66
56
|
* @param {*} price
|
|
67
57
|
* @returns
|
|
68
58
|
*/
|
|
69
|
-
|
|
70
|
-
|
|
71
59
|
exports.getCategoryOptions = getCategoryOptions;
|
|
72
|
-
|
|
73
60
|
const filterBlockletByPrice = function filterBlockletByPrice() {
|
|
74
61
|
let list = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
75
62
|
let price = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
|
|
76
63
|
let result = list;
|
|
77
64
|
if (!price) return result;
|
|
78
|
-
|
|
79
65
|
if (price === 'free') {
|
|
80
66
|
result = list.filter(blocklet => isFreeBlocklet(blocklet));
|
|
81
67
|
} else {
|
|
82
68
|
result = list.filter(blocklet => !isFreeBlocklet(blocklet));
|
|
83
69
|
}
|
|
84
|
-
|
|
85
70
|
return result;
|
|
86
71
|
};
|
|
87
|
-
|
|
88
72
|
exports.filterBlockletByPrice = filterBlockletByPrice;
|
|
89
|
-
|
|
90
73
|
const formatError = error => {
|
|
91
74
|
if (Array.isArray(error.errors)) {
|
|
92
75
|
return error.errors.map(x => x.message).join('\n');
|
|
93
76
|
}
|
|
94
|
-
|
|
95
77
|
return error.message;
|
|
96
78
|
};
|
|
97
|
-
|
|
98
79
|
exports.formatError = formatError;
|
|
99
|
-
|
|
100
80
|
const getStoreDetail = (storeUrl, blocklet) => {
|
|
101
81
|
return (0, _urlJoin.default)(storeUrl, "/blocklets/".concat(blocklet.did));
|
|
102
82
|
};
|
|
103
|
-
|
|
104
83
|
exports.getStoreDetail = getStoreDetail;
|
|
105
|
-
|
|
106
84
|
const formatLogoPath = function formatLogoPath(did, asset) {
|
|
107
85
|
let target = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'assets';
|
|
108
|
-
|
|
109
86
|
if (asset.startsWith(target)) {
|
|
110
87
|
return asset;
|
|
111
88
|
}
|
|
112
|
-
|
|
113
89
|
return "".concat(target, "/").concat(did, "/").concat(asset);
|
|
114
90
|
};
|
|
115
|
-
|
|
116
91
|
exports.formatLogoPath = formatLogoPath;
|
|
117
|
-
|
|
118
|
-
|
|
92
|
+
const replaceTranslate = (template, data) =>
|
|
93
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
119
94
|
template.replace(/{(\w*)}/g, (m, key) => data.hasOwnProperty(key) ? data[key] : '');
|
|
120
|
-
|
|
121
95
|
exports.replaceTranslate = replaceTranslate;
|
|
122
|
-
|
|
123
96
|
const removeUndefined = obj => {
|
|
124
97
|
const clone = (0, _cloneDeep.default)(obj);
|
|
125
98
|
Object.keys(clone).forEach(key => {
|
|
@@ -129,56 +102,42 @@ const removeUndefined = obj => {
|
|
|
129
102
|
});
|
|
130
103
|
return clone;
|
|
131
104
|
};
|
|
132
|
-
|
|
133
105
|
exports.removeUndefined = removeUndefined;
|
|
134
|
-
|
|
135
106
|
const urlStringify = obj => {
|
|
136
107
|
if (!obj) {
|
|
137
108
|
throw new Error('obj is required in urlStringify ');
|
|
138
109
|
}
|
|
139
|
-
|
|
140
110
|
return new URLSearchParams(removeUndefined(obj)).toString();
|
|
141
111
|
};
|
|
142
|
-
|
|
143
112
|
exports.urlStringify = urlStringify;
|
|
144
|
-
|
|
145
113
|
const isMobileScreen = () => {
|
|
146
114
|
return window.innerWidth <= 600;
|
|
147
115
|
};
|
|
148
|
-
|
|
149
116
|
exports.isMobileScreen = isMobileScreen;
|
|
150
|
-
|
|
151
117
|
const getCurrentPage = (length, pageSize) => {
|
|
152
118
|
const page = (length + pageSize) / pageSize;
|
|
153
119
|
if (page > 1) return page.toFixed();
|
|
154
120
|
return 1;
|
|
155
121
|
};
|
|
156
|
-
|
|
157
122
|
exports.getCurrentPage = getCurrentPage;
|
|
158
|
-
|
|
159
123
|
const toColorRgb = colorStr => {
|
|
160
124
|
const color = (0, _color.default)(colorStr);
|
|
161
125
|
return color.rgb().object();
|
|
162
126
|
};
|
|
163
|
-
|
|
164
127
|
exports.toColorRgb = toColorRgb;
|
|
165
|
-
|
|
166
128
|
function debouncePromise(fn, time) {
|
|
167
129
|
let timerId;
|
|
168
130
|
return function debounced() {
|
|
169
131
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
170
132
|
args[_key] = arguments[_key];
|
|
171
133
|
}
|
|
172
|
-
|
|
173
134
|
if (timerId) {
|
|
174
135
|
clearTimeout(timerId);
|
|
175
136
|
}
|
|
176
|
-
|
|
177
137
|
return new Promise(resolve => {
|
|
178
138
|
timerId = setTimeout(() => resolve(fn(...args)), time);
|
|
179
139
|
});
|
|
180
140
|
};
|
|
181
141
|
}
|
|
182
|
-
|
|
183
142
|
const debounced = debouncePromise(items => Promise.resolve(items), 300);
|
|
184
143
|
exports.debounced = debounced;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/list",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.34",
|
|
4
4
|
"description": "Common ux components of blocklet",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -42,12 +42,11 @@
|
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@algolia/autocomplete-js": "^1.7.1",
|
|
44
44
|
"@algolia/autocomplete-theme-classic": "^1.7.1",
|
|
45
|
-
"@arcblock/ux": "^2.4.
|
|
45
|
+
"@arcblock/ux": "^2.4.52",
|
|
46
46
|
"@emotion/react": "^11.10.0",
|
|
47
47
|
"@emotion/styled": "^11.10.0",
|
|
48
48
|
"@mui/icons-material": "^5.8.4",
|
|
49
49
|
"ahooks": "^3.7.0",
|
|
50
|
-
"algoliasearch": "^4.14.2",
|
|
51
50
|
"axios": "^0.27.2",
|
|
52
51
|
"color": "^4.2.3",
|
|
53
52
|
"flat": "^5.0.2",
|
|
@@ -71,5 +70,5 @@
|
|
|
71
70
|
"eslint": "^8.22.0",
|
|
72
71
|
"prettier": "^2.7.1"
|
|
73
72
|
},
|
|
74
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "a937d5fcacee474b9f024440587a94975f8c0361"
|
|
75
74
|
}
|
package/src/base.js
CHANGED
|
@@ -11,6 +11,7 @@ import { CustomChip, FilterIcon } from './components/filter';
|
|
|
11
11
|
import { getSortOptions } from './libs/utils';
|
|
12
12
|
import BlockletList from './components/list';
|
|
13
13
|
import Aside from './components/aside';
|
|
14
|
+
import BaseSearch from './components/base-search';
|
|
14
15
|
import Autocomplete from './components/autocomplete';
|
|
15
16
|
|
|
16
17
|
function ListBase() {
|
|
@@ -27,6 +28,7 @@ function ListBase() {
|
|
|
27
28
|
getCategoryLocale,
|
|
28
29
|
priceOptions,
|
|
29
30
|
wrapChildren,
|
|
31
|
+
baseSearch,
|
|
30
32
|
} = useFilterContext();
|
|
31
33
|
const sortOptions = getSortOptions(t);
|
|
32
34
|
const sortLocale = sortOptions.find((f) => f.value === filters.sortBy)?.name || t('sort.sort');
|
|
@@ -40,7 +42,12 @@ function ListBase() {
|
|
|
40
42
|
<StyledMin>
|
|
41
43
|
<FilterContainer>
|
|
42
44
|
<Box className="filter-bar" display="flex" alignItems="center">
|
|
43
|
-
|
|
45
|
+
{/* see: https://github.com/blocklet/blocklet-store/pull/852 */}
|
|
46
|
+
{baseSearch ? (
|
|
47
|
+
<BaseSearch className="bl-search-container" placeholder={t('common.searchStore')} />
|
|
48
|
+
) : (
|
|
49
|
+
<Autocomplete onSelect={handleSearchSelect} wrapChildren={wrapChildren} />
|
|
50
|
+
)}
|
|
44
51
|
<Box mt={0} ml="16px" className="filter-container">
|
|
45
52
|
<Hidden mdUp>
|
|
46
53
|
{/* 小屏幕下类别 */}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import SearchIcon from '@mui/icons-material/Search';
|
|
4
|
+
import CloseIcon from '@mui/icons-material/Close';
|
|
5
|
+
import { OutlinedInput, InputAdornment } from '@mui/material';
|
|
6
|
+
import { useDebounceFn } from 'ahooks';
|
|
7
|
+
import styled from '@emotion/styled';
|
|
8
|
+
|
|
9
|
+
import { useFilterContext } from '../contexts/filter';
|
|
10
|
+
|
|
11
|
+
function BaseSearch({ placeholder, ...rest }) {
|
|
12
|
+
const { filters, handleKeyword } = useFilterContext();
|
|
13
|
+
const [searchStr, setSearchStr] = useState(filters.keyword || '');
|
|
14
|
+
|
|
15
|
+
const debouncedSearch = useDebounceFn(handleKeyword, { wait: 300 });
|
|
16
|
+
const handleChange = (event) => {
|
|
17
|
+
const { value } = event.target;
|
|
18
|
+
setSearchStr(value);
|
|
19
|
+
debouncedSearch.run(value);
|
|
20
|
+
};
|
|
21
|
+
const handleClose = () => {
|
|
22
|
+
setSearchStr('');
|
|
23
|
+
handleKeyword();
|
|
24
|
+
};
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
setSearchStr(filters.keyword || '');
|
|
27
|
+
}, [filters.keyword]);
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<StyledSearch
|
|
31
|
+
inputProps={{
|
|
32
|
+
'data-cy': 'search-blocklet',
|
|
33
|
+
}}
|
|
34
|
+
startAdornment={
|
|
35
|
+
<InputAdornment position="start">
|
|
36
|
+
<StyledSearchIcon />
|
|
37
|
+
</InputAdornment>
|
|
38
|
+
}
|
|
39
|
+
onChange={handleChange}
|
|
40
|
+
placeholder={placeholder}
|
|
41
|
+
value={searchStr}
|
|
42
|
+
title={placeholder}
|
|
43
|
+
data-cy="search"
|
|
44
|
+
endAdornment={
|
|
45
|
+
searchStr && (
|
|
46
|
+
<InputAdornment position="end">
|
|
47
|
+
<StyledCloseIcon data-cy="search-delete" onClick={handleClose} />
|
|
48
|
+
</InputAdornment>
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
{...rest}
|
|
52
|
+
/>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
BaseSearch.propTypes = {
|
|
56
|
+
placeholder: PropTypes.string,
|
|
57
|
+
};
|
|
58
|
+
BaseSearch.defaultProps = {
|
|
59
|
+
placeholder: 'Type to search...',
|
|
60
|
+
};
|
|
61
|
+
const StyledSearch = styled(OutlinedInput)`
|
|
62
|
+
background-color: ${(props) => props.theme.palette.grey[50]};
|
|
63
|
+
font-size: 14px;
|
|
64
|
+
border-radius: 6px;
|
|
65
|
+
.MuiInputBase-input {
|
|
66
|
+
padding: 8px 0 8px 10px;
|
|
67
|
+
}
|
|
68
|
+
.MuiOutlinedInput-notchedOutline {
|
|
69
|
+
border: none;
|
|
70
|
+
}
|
|
71
|
+
.Mui-focused {
|
|
72
|
+
background-color: #f6f6f6;
|
|
73
|
+
.MuiInputBase-input::placeholder {
|
|
74
|
+
color: transparent;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
`;
|
|
78
|
+
|
|
79
|
+
const StyledSearchIcon = styled(SearchIcon)`
|
|
80
|
+
color: ${(props) => props.theme.palette.grey[500]};
|
|
81
|
+
font-size: 28px;
|
|
82
|
+
@media (max-width: ${(props) => props.theme.breakpoints.values.md}px) {
|
|
83
|
+
font-size: 24px;
|
|
84
|
+
}
|
|
85
|
+
`;
|
|
86
|
+
|
|
87
|
+
const StyledCloseIcon = styled(CloseIcon)`
|
|
88
|
+
color: ${(props) => props.theme.palette.grey[500]};
|
|
89
|
+
font-size: 16px;
|
|
90
|
+
cursor: pointer;
|
|
91
|
+
`;
|
|
92
|
+
|
|
93
|
+
export default BaseSearch;
|
package/src/contexts/filter.js
CHANGED
|
@@ -21,6 +21,7 @@ function FilterProvider({
|
|
|
21
21
|
onSearchSelect,
|
|
22
22
|
extraFilter,
|
|
23
23
|
wrapChildren,
|
|
24
|
+
baseSearch,
|
|
24
25
|
}) {
|
|
25
26
|
const storeApi = useMemo(() => {
|
|
26
27
|
return axios.create({
|
|
@@ -118,6 +119,7 @@ function FilterProvider({
|
|
|
118
119
|
categoryOptions,
|
|
119
120
|
priceOptions,
|
|
120
121
|
storeApi,
|
|
122
|
+
baseSearch,
|
|
121
123
|
hasNextPage: blockletsState.list.length < blockletsState.total,
|
|
122
124
|
handleSort: (sort) => {
|
|
123
125
|
const changeData = {
|
package/src/libs/prop-types.js
CHANGED
|
@@ -16,6 +16,7 @@ const propTypes = {
|
|
|
16
16
|
onFilterChange: PropTypes.func,
|
|
17
17
|
onSearchSelect: PropTypes.func,
|
|
18
18
|
locale: PropTypes.oneOf(['zh', 'en']),
|
|
19
|
+
baseSearch: PropTypes.bool,
|
|
19
20
|
};
|
|
20
21
|
|
|
21
22
|
const defaultProps = {
|
|
@@ -27,6 +28,7 @@ const defaultProps = {
|
|
|
27
28
|
},
|
|
28
29
|
wrapChildren: (children) => children,
|
|
29
30
|
extraFilter: (list) => list,
|
|
31
|
+
baseSearch: false,
|
|
30
32
|
};
|
|
31
33
|
|
|
32
34
|
export { propTypes, defaultProps };
|