@blocklet/list 0.8.15 → 0.8.18
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/base.js +21 -24
- package/lib/components/{aside.js → aside/aside.js} +11 -12
- package/lib/components/aside/category-link-list.js +78 -0
- package/lib/components/aside/index.js +13 -0
- package/lib/components/category-select.js +55 -0
- package/lib/components/{button.js → custom-select/button.js} +1 -1
- package/lib/components/{custom-select.js → custom-select/custom-select.js} +8 -6
- package/lib/components/custom-select/index.js +13 -0
- package/lib/components/filter-author.js +2 -3
- package/lib/components/{empty.js → list/empty.js} +6 -8
- package/lib/components/list/index.js +13 -0
- package/lib/components/{list.js → list/list.js} +12 -12
- package/lib/components/search.js +20 -18
- package/lib/contexts/filter.js +268 -0
- package/lib/index.js +6 -16
- package/lib/libs/prop-types.js +34 -0
- package/lib/{tools → libs}/utils.js +6 -6
- package/package.json +60 -64
- package/src/base.js +17 -18
- package/src/components/{aside.js → aside/aside.js} +7 -8
- package/src/components/aside/category-link-list.js +53 -0
- package/src/components/aside/index.js +3 -0
- package/src/components/category-select.js +43 -0
- package/src/components/{button.js → custom-select/button.js} +0 -0
- package/src/components/{custom-select.js → custom-select/custom-select.js} +5 -4
- package/src/components/custom-select/index.js +3 -0
- package/src/components/filter-author.js +2 -3
- package/src/components/{empty.js → list/empty.js} +7 -8
- package/src/components/list/index.js +3 -0
- package/src/components/{list.js → list/list.js} +10 -10
- package/src/components/search.js +17 -13
- package/src/contexts/filter.js +197 -0
- package/src/index.js +6 -16
- package/src/libs/prop-types.js +26 -0
- package/src/{tools → libs}/utils.js +6 -6
- package/lib/components/categories.js +0 -143
- package/lib/contexts/store.js +0 -336
- package/lib/hooks/page-state.js +0 -69
- package/src/components/categories.js +0 -129
- package/src/contexts/store.js +0 -266
- package/src/hooks/page-state.js +0 -53
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.FilterConsumer = void 0;
|
|
7
|
+
exports.FilterProvider = FilterProvider;
|
|
8
|
+
exports.useFilterContext = useFilterContext;
|
|
9
|
+
|
|
10
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
11
|
+
|
|
12
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
13
|
+
|
|
14
|
+
var _ahooks = require("ahooks");
|
|
15
|
+
|
|
16
|
+
var _orderBy = _interopRequireDefault(require("lodash/orderBy"));
|
|
17
|
+
|
|
18
|
+
var _axios = _interopRequireDefault(require("axios"));
|
|
19
|
+
|
|
20
|
+
var _utils = require("../libs/utils");
|
|
21
|
+
|
|
22
|
+
var _locale = _interopRequireDefault(require("../assets/locale"));
|
|
23
|
+
|
|
24
|
+
var _propTypes2 = require("../libs/prop-types");
|
|
25
|
+
|
|
26
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
27
|
+
|
|
28
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
29
|
+
|
|
30
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
31
|
+
|
|
32
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
33
|
+
|
|
34
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
35
|
+
|
|
36
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
37
|
+
|
|
38
|
+
const Filter = /*#__PURE__*/(0, _react.createContext)({});
|
|
39
|
+
const {
|
|
40
|
+
Provider,
|
|
41
|
+
Consumer
|
|
42
|
+
} = Filter;
|
|
43
|
+
exports.FilterConsumer = Consumer;
|
|
44
|
+
|
|
45
|
+
function FilterProvider(_ref) {
|
|
46
|
+
let {
|
|
47
|
+
onSelectBlocklet,
|
|
48
|
+
selectedBlocklets,
|
|
49
|
+
filters,
|
|
50
|
+
children,
|
|
51
|
+
baseUrl,
|
|
52
|
+
endpoint,
|
|
53
|
+
locale,
|
|
54
|
+
blockletRender,
|
|
55
|
+
onFilterChange
|
|
56
|
+
} = _ref;
|
|
57
|
+
|
|
58
|
+
const storeApi = _axios.default.create({
|
|
59
|
+
baseURL: endpoint
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const {
|
|
63
|
+
data: allBlocklets,
|
|
64
|
+
error: fetchBlockletsError,
|
|
65
|
+
loading: fetchBlockletsLoading,
|
|
66
|
+
run: fetchBlocklets
|
|
67
|
+
} = (0, _ahooks.useRequest)(async () => {
|
|
68
|
+
const {
|
|
69
|
+
data: list
|
|
70
|
+
} = await storeApi.get('/api/blocklets.json');
|
|
71
|
+
return list;
|
|
72
|
+
}, {
|
|
73
|
+
initialData: [],
|
|
74
|
+
manual: true
|
|
75
|
+
});
|
|
76
|
+
const {
|
|
77
|
+
data: allCategories,
|
|
78
|
+
error: fetchCategoriesError,
|
|
79
|
+
loading: fetchCategoriesLoading,
|
|
80
|
+
run: fetchCategories
|
|
81
|
+
} = (0, _ahooks.useRequest)(async () => {
|
|
82
|
+
const {
|
|
83
|
+
data: list
|
|
84
|
+
} = await storeApi.get('/api/blocklets/categories');
|
|
85
|
+
return list;
|
|
86
|
+
}, {
|
|
87
|
+
initialData: [],
|
|
88
|
+
manual: true
|
|
89
|
+
});
|
|
90
|
+
const selectedCategory = filters.category;
|
|
91
|
+
const hasDeveloperFilter = !!filters.developer;
|
|
92
|
+
const categoryState = (0, _react.useMemo)(() => {
|
|
93
|
+
return !hasDeveloperFilter ? {
|
|
94
|
+
data: allCategories
|
|
95
|
+
} : (0, _utils.getCategories)(allBlocklets, filters.developer);
|
|
96
|
+
}, [hasDeveloperFilter, allCategories]);
|
|
97
|
+
const blockletList = (0, _react.useMemo)(() => {
|
|
98
|
+
var _filters$keyword;
|
|
99
|
+
|
|
100
|
+
const sortByName = x => {
|
|
101
|
+
var _x$title, _x$name;
|
|
102
|
+
|
|
103
|
+
return (x === null || x === void 0 ? void 0 : (_x$title = x.title) === null || _x$title === void 0 ? void 0 : _x$title.toLocaleLowerCase()) || (x === null || x === void 0 ? void 0 : (_x$name = x.name) === null || _x$name === void 0 ? void 0 : _x$name.toLocaleLowerCase());
|
|
104
|
+
}; // 按名称排序
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
const sortByPopularity = x => x.stats.downloads; // 按下载量排序
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
const sortByPublish = x => x.lastPublishedAt; // 按发布时间
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
const sortMap = {
|
|
114
|
+
nameAsc: sortByName,
|
|
115
|
+
nameDesc: sortByName,
|
|
116
|
+
popularity: sortByPopularity,
|
|
117
|
+
publishAt: sortByPublish
|
|
118
|
+
};
|
|
119
|
+
let result = allBlocklets || []; // 按照付费/免费筛选
|
|
120
|
+
|
|
121
|
+
result = (0, _utils.filterBlockletByPrice)(result, filters.price); // 按照分类筛选
|
|
122
|
+
|
|
123
|
+
result = result.filter(item => {
|
|
124
|
+
var _item$category;
|
|
125
|
+
|
|
126
|
+
return selectedCategory ? (item === null || item === void 0 ? void 0 : (_item$category = item.category) === null || _item$category === void 0 ? void 0 : _item$category.name) === selectedCategory : true;
|
|
127
|
+
}); // 按照作者筛选
|
|
128
|
+
|
|
129
|
+
result = result.filter(item => filters !== null && filters !== void 0 && filters.developer ? item.owner.did === filters.developer : true);
|
|
130
|
+
const lowerSearch = (filters === null || filters === void 0 ? void 0 : (_filters$keyword = filters.keyword) === null || _filters$keyword === void 0 ? void 0 : _filters$keyword.toLocaleLowerCase()) || ''; // 按照搜索筛选
|
|
131
|
+
|
|
132
|
+
result = result.filter(item => {
|
|
133
|
+
var _ref2, _item$description, _item$version;
|
|
134
|
+
|
|
135
|
+
return ((_ref2 = (item === null || item === void 0 ? void 0 : item.title) || (item === null || item === void 0 ? void 0 : item.name)) === null || _ref2 === void 0 ? void 0 : _ref2.toLocaleLowerCase().includes(lowerSearch)) || ((_item$description = item.description) === null || _item$description === void 0 ? void 0 : _item$description.toLocaleLowerCase().includes(lowerSearch)) || (item === null || item === void 0 ? void 0 : (_item$version = item.version) === null || _item$version === void 0 ? void 0 : _item$version.toLocaleLowerCase().includes(lowerSearch));
|
|
136
|
+
}); // 排序
|
|
137
|
+
|
|
138
|
+
return (0, _orderBy.default)(result, [sortMap[filters.sortBy]], [filters.sortDirection]);
|
|
139
|
+
}, [allBlocklets, filters]);
|
|
140
|
+
const categoryList = (0, _react.useMemo)(() => {
|
|
141
|
+
const list = categoryState.data || []; // 分类按照名称排序
|
|
142
|
+
|
|
143
|
+
return (0, _orderBy.default)(list, [i => i.name], ['asc']);
|
|
144
|
+
}, [categoryState.data]);
|
|
145
|
+
|
|
146
|
+
const translate = (key, data) => {
|
|
147
|
+
if (!_locale.default[locale] || !_locale.default[locale][key]) {
|
|
148
|
+
console.warn("Warning: no ".concat(key, " translation of ").concat(locale));
|
|
149
|
+
return key;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return (0, _utils.replaceTranslate)(_locale.default[locale][key], data);
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const filterStore = {
|
|
156
|
+
errors: {
|
|
157
|
+
fetchBlockletsError,
|
|
158
|
+
fetchCategoriesError
|
|
159
|
+
},
|
|
160
|
+
loadings: {
|
|
161
|
+
fetchBlockletsLoading,
|
|
162
|
+
fetchCategoriesLoading
|
|
163
|
+
},
|
|
164
|
+
endpoint,
|
|
165
|
+
blockletList,
|
|
166
|
+
t: translate,
|
|
167
|
+
filters: _objectSpread({
|
|
168
|
+
sortBy: 'popularity',
|
|
169
|
+
sortDirection: 'desc'
|
|
170
|
+
}, filters),
|
|
171
|
+
selectedCategory,
|
|
172
|
+
categoryList,
|
|
173
|
+
baseUrl,
|
|
174
|
+
blockletRender,
|
|
175
|
+
locale,
|
|
176
|
+
selectedBlocklets,
|
|
177
|
+
onSelectBlocklet,
|
|
178
|
+
handleSort: sort => {
|
|
179
|
+
const changeData = _objectSpread(_objectSpread({}, filters), {}, {
|
|
180
|
+
sortBy: sort,
|
|
181
|
+
sortDirection: sort === 'nameAsc' ? 'asc' : 'desc'
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
onFilterChange(changeData);
|
|
185
|
+
},
|
|
186
|
+
handleKeyword: keyWord => {
|
|
187
|
+
const changeData = _objectSpread(_objectSpread({}, filters), {}, {
|
|
188
|
+
keyword: keyWord || undefined
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
onFilterChange(changeData);
|
|
192
|
+
},
|
|
193
|
+
handlePrice: price => {
|
|
194
|
+
const changeData = _objectSpread(_objectSpread({}, filters), {}, {
|
|
195
|
+
price: price === filters.price ? undefined : price
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
onFilterChange(changeData);
|
|
199
|
+
},
|
|
200
|
+
handleCategory: category => {
|
|
201
|
+
if (category === 'all') {
|
|
202
|
+
const changeData = _objectSpread(_objectSpread({}, filters), {}, {
|
|
203
|
+
category: undefined
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
onFilterChange(changeData);
|
|
207
|
+
} else {
|
|
208
|
+
const changeData = _objectSpread(_objectSpread({}, filters), {}, {
|
|
209
|
+
category
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
onFilterChange(changeData);
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
handleDeveloper: developer => {
|
|
216
|
+
const changeData = _objectSpread(_objectSpread({}, filters), {}, {
|
|
217
|
+
developer: developer || undefined
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
onFilterChange(changeData);
|
|
221
|
+
},
|
|
222
|
+
getCategoryLocale: category => {
|
|
223
|
+
if (!category) return null;
|
|
224
|
+
let result = null;
|
|
225
|
+
const find = categoryState.data.find(item => item.name === category);
|
|
226
|
+
|
|
227
|
+
if (find) {
|
|
228
|
+
result = find.locales[locale];
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return result;
|
|
232
|
+
},
|
|
233
|
+
|
|
234
|
+
get developerName() {
|
|
235
|
+
var _allBlocklets$find, _allBlocklets$find$ow;
|
|
236
|
+
|
|
237
|
+
return ((_allBlocklets$find = allBlocklets.find(i => i.owner.did === filters.developer)) === null || _allBlocklets$find === void 0 ? void 0 : (_allBlocklets$find$ow = _allBlocklets$find.owner) === null || _allBlocklets$find$ow === void 0 ? void 0 : _allBlocklets$find$ow.name) || '';
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
};
|
|
241
|
+
(0, _react.useEffect)(() => {
|
|
242
|
+
if (!hasDeveloperFilter) {
|
|
243
|
+
fetchCategories();
|
|
244
|
+
}
|
|
245
|
+
}, [hasDeveloperFilter]);
|
|
246
|
+
(0, _react.useEffect)(() => {
|
|
247
|
+
fetchBlocklets();
|
|
248
|
+
fetchCategories();
|
|
249
|
+
}, [endpoint]);
|
|
250
|
+
return /*#__PURE__*/_react.default.createElement(Provider, {
|
|
251
|
+
value: filterStore
|
|
252
|
+
}, children);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
FilterProvider.propTypes = _objectSpread(_objectSpread({}, _propTypes2.propTypes), {}, {
|
|
256
|
+
children: _propTypes.default.any.isRequired
|
|
257
|
+
});
|
|
258
|
+
FilterProvider.defaultProps = _propTypes2.defaultProps;
|
|
259
|
+
|
|
260
|
+
function useFilterContext() {
|
|
261
|
+
const filterStore = (0, _react.useContext)(Filter);
|
|
262
|
+
|
|
263
|
+
if (!filterStore) {
|
|
264
|
+
return {};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return filterStore;
|
|
268
|
+
}
|
package/lib/index.js
CHANGED
|
@@ -7,27 +7,17 @@ exports.default = BlockletList;
|
|
|
7
7
|
|
|
8
8
|
var _react = _interopRequireDefault(require("react"));
|
|
9
9
|
|
|
10
|
-
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
11
|
-
|
|
12
10
|
var _base = _interopRequireDefault(require("./base"));
|
|
13
11
|
|
|
14
|
-
var
|
|
12
|
+
var _filter = require("./contexts/filter");
|
|
13
|
+
|
|
14
|
+
var _propTypes = require("./libs/prop-types");
|
|
15
15
|
|
|
16
16
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
17
|
|
|
18
18
|
function BlockletList(props) {
|
|
19
|
-
return /*#__PURE__*/_react.default.createElement(
|
|
19
|
+
return /*#__PURE__*/_react.default.createElement(_filter.FilterProvider, props, /*#__PURE__*/_react.default.createElement(_base.default, null));
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
BlockletList.propTypes =
|
|
23
|
-
|
|
24
|
-
endpoint: _propTypes.default.string.isRequired,
|
|
25
|
-
// 组件的类型: page 单独作为页面使用 持久化数据将存储在 url 和 localstorage,select 作为选择器组件使用 数据在存储在内存中
|
|
26
|
-
type: _propTypes.default.oneOf(['select', 'page']).isRequired,
|
|
27
|
-
locale: _propTypes.default.oneOf(['zh', 'en']),
|
|
28
|
-
blockletRender: _propTypes.default.func.isRequired
|
|
29
|
-
};
|
|
30
|
-
BlockletList.defaultProps = {
|
|
31
|
-
baseUrl: null,
|
|
32
|
-
locale: 'zh'
|
|
33
|
-
};
|
|
22
|
+
BlockletList.propTypes = _propTypes.propTypes;
|
|
23
|
+
BlockletList.defaultProps = _propTypes.defaultProps;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.propTypes = exports.defaultProps = void 0;
|
|
7
|
+
|
|
8
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
9
|
+
|
|
10
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
+
|
|
12
|
+
const propTypes = {
|
|
13
|
+
filters: _propTypes.default.shape({
|
|
14
|
+
keyword: _propTypes.default.string,
|
|
15
|
+
sortBy: _propTypes.default.string,
|
|
16
|
+
sortDirection: _propTypes.default.string,
|
|
17
|
+
price: _propTypes.default.string,
|
|
18
|
+
category: _propTypes.default.string,
|
|
19
|
+
developer: _propTypes.default.string
|
|
20
|
+
}),
|
|
21
|
+
endpoint: _propTypes.default.string.isRequired,
|
|
22
|
+
blockletRender: _propTypes.default.func.isRequired,
|
|
23
|
+
onFilterChange: _propTypes.default.func,
|
|
24
|
+
baseUrl: _propTypes.default.string,
|
|
25
|
+
locale: _propTypes.default.oneOf(['zh', 'en'])
|
|
26
|
+
};
|
|
27
|
+
exports.propTypes = propTypes;
|
|
28
|
+
const defaultProps = {
|
|
29
|
+
baseUrl: null,
|
|
30
|
+
locale: 'zh',
|
|
31
|
+
filters: {},
|
|
32
|
+
onFilterChange: () => {}
|
|
33
|
+
};
|
|
34
|
+
exports.defaultProps = defaultProps;
|
|
@@ -7,7 +7,7 @@ exports.urlStringify = exports.replaceTranslate = exports.removeUndefined = expo
|
|
|
7
7
|
|
|
8
8
|
var _urlJoin = _interopRequireDefault(require("url-join"));
|
|
9
9
|
|
|
10
|
-
var _cloneDeep = _interopRequireDefault(require("lodash
|
|
10
|
+
var _cloneDeep = _interopRequireDefault(require("lodash/cloneDeep"));
|
|
11
11
|
|
|
12
12
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
13
|
|
|
@@ -127,13 +127,13 @@ template.replace(/{(\w*)}/g, (m, key) => data.hasOwnProperty(key) ? data[key] :
|
|
|
127
127
|
exports.replaceTranslate = replaceTranslate;
|
|
128
128
|
|
|
129
129
|
const removeUndefined = obj => {
|
|
130
|
-
const
|
|
131
|
-
Object.keys(
|
|
132
|
-
if (
|
|
133
|
-
delete
|
|
130
|
+
const clone = (0, _cloneDeep.default)(obj);
|
|
131
|
+
Object.keys(clone).forEach(key => {
|
|
132
|
+
if (clone[key] === undefined) {
|
|
133
|
+
delete clone[key];
|
|
134
134
|
}
|
|
135
135
|
});
|
|
136
|
-
return
|
|
136
|
+
return clone;
|
|
137
137
|
};
|
|
138
138
|
|
|
139
139
|
exports.removeUndefined = removeUndefined;
|
package/package.json
CHANGED
|
@@ -1,66 +1,62 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
"
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
"babel-plugin-inline-react-svg": "^2.0.1",
|
|
63
|
-
"babel-plugin-styled-components": "^1.10.7"
|
|
64
|
-
},
|
|
65
|
-
"gitHead": "af730b5ec10068e9db333bb8b3083db3c2c978fe"
|
|
2
|
+
"name": "@blocklet/list",
|
|
3
|
+
"version": "0.8.18",
|
|
4
|
+
"description": "Common ux components of blocklet",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"author": "machao <machao@arcblock.io>",
|
|
9
|
+
"homepage": "https://github.com/blocklet/blocklet-store#readme",
|
|
10
|
+
"license": "ISC",
|
|
11
|
+
"main": "lib/index.js",
|
|
12
|
+
"files": [
|
|
13
|
+
"lib",
|
|
14
|
+
"src",
|
|
15
|
+
"LICENSE",
|
|
16
|
+
"package.json",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git@github.com:blocklet/blocklet-store.git"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"lint": "eslint src",
|
|
25
|
+
"build": "rm -rf lib && babel src --out-dir lib --copy-files",
|
|
26
|
+
"watch": "babel src --out-dir lib -w --copy-files",
|
|
27
|
+
"precommit": "CI=1 yarn test",
|
|
28
|
+
"prepush": "CI=1 yarn test",
|
|
29
|
+
"prepublish": "npm run build"
|
|
30
|
+
},
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/blocklet/blocklet-store/issues"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"@mui/material": ">=5.6.4",
|
|
36
|
+
"@mui/styles": ">=5.6.2",
|
|
37
|
+
"react": ">=18.1.0"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@arcblock/ux": "^2.1.4",
|
|
41
|
+
"@emotion/react": "^11.9.0",
|
|
42
|
+
"@emotion/styled": "^11.8.1",
|
|
43
|
+
"@mui/icons-material": "^5.6.2",
|
|
44
|
+
"ahooks": "^2.10.12",
|
|
45
|
+
"axios": "^0.27.2",
|
|
46
|
+
"flat": "^5.0.2",
|
|
47
|
+
"lodash": "^4.17.21",
|
|
48
|
+
"prop-types": "^15.7.2",
|
|
49
|
+
"styled-components": "5.3.5",
|
|
50
|
+
"url-join": "^4.0.1"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@babel/cli": "^7.8.4",
|
|
54
|
+
"@babel/core": "^7.8.4",
|
|
55
|
+
"@babel/preset-env": "^7.8.4",
|
|
56
|
+
"@babel/preset-react": "^7.8.3",
|
|
57
|
+
"@emotion/babel-plugin": "^11.9.2",
|
|
58
|
+
"babel-plugin-inline-react-svg": "^2.0.1",
|
|
59
|
+
"babel-plugin-styled-components": "^1.10.7"
|
|
60
|
+
},
|
|
61
|
+
"gitHead": "3fade57bc35e7abf298ed99812867d832962ed1d"
|
|
66
62
|
}
|
package/src/base.js
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import styled from 'styled-components';
|
|
3
|
-
import
|
|
3
|
+
import SortIcon from '@mui/icons-material/Sort';
|
|
4
4
|
import FilterListIcon from '@mui/icons-material/FilterList';
|
|
5
|
-
import { Box, Hidden
|
|
5
|
+
import { Box, Hidden } from '@mui/material';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { useFilterContext } from './contexts/filter';
|
|
8
8
|
import CustomSelect from './components/custom-select';
|
|
9
9
|
import FilterAuthor from './components/filter-author';
|
|
10
|
-
import { getSortOptions, getPrices } from './
|
|
10
|
+
import { getSortOptions, getPrices } from './libs/utils';
|
|
11
11
|
import BlockletList from './components/list';
|
|
12
12
|
import Aside from './components/aside';
|
|
13
13
|
import Search from './components/search';
|
|
14
|
-
import
|
|
14
|
+
import CategorySelect from './components/category-select';
|
|
15
15
|
|
|
16
16
|
const ListBase = () => {
|
|
17
|
-
const
|
|
18
|
-
const { sortParams, history, blockletList, queryParams, developerName, handleSort, t } = searchStore;
|
|
17
|
+
const { handleDeveloper, blockletList, filters, developerName, handleSort, t, handlePrice } = useFilterContext();
|
|
19
18
|
return (
|
|
20
19
|
<Box display="flex" alignItems="flex-start" height="100%">
|
|
21
20
|
<Hidden mdDown>
|
|
@@ -24,11 +23,11 @@ const ListBase = () => {
|
|
|
24
23
|
<StyledMin>
|
|
25
24
|
<Box className="marketplace-header" display="flex" alignItems="center">
|
|
26
25
|
<Hidden mdDown>
|
|
27
|
-
{!!
|
|
26
|
+
{!!filters.developer && (
|
|
28
27
|
<FilterAuthor
|
|
29
28
|
user={developerName}
|
|
30
29
|
deleteUserTag={() => {
|
|
31
|
-
|
|
30
|
+
handleDeveloper(null);
|
|
32
31
|
}}
|
|
33
32
|
/>
|
|
34
33
|
)}
|
|
@@ -43,10 +42,10 @@ const ListBase = () => {
|
|
|
43
42
|
<CategorySelect />
|
|
44
43
|
</Hidden>
|
|
45
44
|
<CustomSelect
|
|
46
|
-
value={
|
|
45
|
+
value={filters.sortBy}
|
|
47
46
|
options={getSortOptions(t)}
|
|
48
|
-
title={getSortOptions(t).find((f) => f.value ===
|
|
49
|
-
icon={<
|
|
47
|
+
title={getSortOptions(t).find((f) => f.value === filters.sortBy)?.name || t('sort.sort')}
|
|
48
|
+
icon={<SortIcon />}
|
|
50
49
|
onChange={(v) => {
|
|
51
50
|
handleSort(v);
|
|
52
51
|
}}
|
|
@@ -58,24 +57,24 @@ const ListBase = () => {
|
|
|
58
57
|
display="flex"
|
|
59
58
|
flexWrap="wrap"
|
|
60
59
|
alignItems="center"
|
|
61
|
-
justifyContent={
|
|
62
|
-
{!!
|
|
60
|
+
justifyContent={filters.developer ? 'space-between' : 'flex-end'}>
|
|
61
|
+
{!!filters.developer && (
|
|
63
62
|
<FilterAuthor
|
|
64
63
|
user={developerName}
|
|
65
64
|
deleteUserTag={() => {
|
|
66
|
-
|
|
65
|
+
handleDeveloper(null);
|
|
67
66
|
}}
|
|
68
67
|
style={{ marginBottom: '16px' }}
|
|
69
68
|
/>
|
|
70
69
|
)}
|
|
71
70
|
{/* 筛选付费/免费 */}
|
|
72
71
|
<CustomSelect
|
|
73
|
-
value={
|
|
72
|
+
value={filters.price}
|
|
74
73
|
icon={<FilterListIcon />}
|
|
75
74
|
options={getPrices(t)}
|
|
76
|
-
title={getPrices(t).find((f) => f.value ===
|
|
75
|
+
title={getPrices(t).find((f) => f.value === filters.price)?.name || t('common.price')}
|
|
77
76
|
onChange={(v) => {
|
|
78
|
-
|
|
77
|
+
handlePrice(v);
|
|
79
78
|
}}
|
|
80
79
|
style={{ marginBottom: '16px' }}
|
|
81
80
|
/>
|
|
@@ -2,14 +2,13 @@ import React from 'react';
|
|
|
2
2
|
import { Box, List, Checkbox, FormControlLabel } from '@mui/material';
|
|
3
3
|
import styled from 'styled-components';
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import { getPrices } from '
|
|
7
|
-
import Search from '
|
|
8
|
-
import
|
|
5
|
+
import { useFilterContext } from '../../contexts/filter';
|
|
6
|
+
import { getPrices } from '../../libs/utils';
|
|
7
|
+
import Search from '../search';
|
|
8
|
+
import CategoryLinkList from './category-link-list';
|
|
9
9
|
|
|
10
10
|
const Aside = () => {
|
|
11
|
-
const
|
|
12
|
-
const { queryParams, handlePriceFilter, t } = searchStore;
|
|
11
|
+
const { filters, handlePrice, t } = useFilterContext();
|
|
13
12
|
return (
|
|
14
13
|
<StyledAside>
|
|
15
14
|
<Search placeholder={t('common.searchStore')} />
|
|
@@ -21,10 +20,10 @@ const Aside = () => {
|
|
|
21
20
|
control={
|
|
22
21
|
<Checkbox
|
|
23
22
|
onClick={() => {
|
|
24
|
-
|
|
23
|
+
handlePrice(item.value);
|
|
25
24
|
}}
|
|
26
25
|
size="small"
|
|
27
|
-
checked={item.value ===
|
|
26
|
+
checked={item.value === filters.price}
|
|
28
27
|
/>
|
|
29
28
|
}
|
|
30
29
|
label={item.name}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ListItem, ListItemText, Link } from '@mui/material';
|
|
3
|
+
import joinUrl from 'url-join';
|
|
4
|
+
|
|
5
|
+
import { useFilterContext } from '../../contexts/filter';
|
|
6
|
+
import { urlStringify } from '../../libs/utils';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 宽屏幕下的分类列表
|
|
10
|
+
* @returns
|
|
11
|
+
*/
|
|
12
|
+
const CategoryLinkList = () => {
|
|
13
|
+
const { categoryList, selectedCategory, filters, baseUrl, handleCategory, t, locale } = useFilterContext();
|
|
14
|
+
|
|
15
|
+
const handleClick = (e, name) => {
|
|
16
|
+
handleCategory(name);
|
|
17
|
+
e.preventDefault();
|
|
18
|
+
return false;
|
|
19
|
+
};
|
|
20
|
+
const content = (
|
|
21
|
+
<div style={{ marginRight: '16px' }}>
|
|
22
|
+
<ListItem selected={!selectedCategory} button onClick={(e) => handleClick(e, 'all')}>
|
|
23
|
+
<ListItemText primary={t('category.all')} />
|
|
24
|
+
</ListItem>
|
|
25
|
+
{categoryList.map((item) => (
|
|
26
|
+
<ListItem
|
|
27
|
+
key={item._id}
|
|
28
|
+
title={item.locales[locale]}
|
|
29
|
+
component={Link}
|
|
30
|
+
to={`${joinUrl(baseUrl, '/search')}?${urlStringify({
|
|
31
|
+
...filters,
|
|
32
|
+
category: item.name,
|
|
33
|
+
})}`}
|
|
34
|
+
onClick={(e) => handleClick(e, item.name)}
|
|
35
|
+
button
|
|
36
|
+
selected={item.name === selectedCategory}>
|
|
37
|
+
<ListItemText primary={item.locales[locale]} />
|
|
38
|
+
</ListItem>
|
|
39
|
+
))}
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<>
|
|
45
|
+
<ListItem>
|
|
46
|
+
<ListItemText className="category" primary={t('common.category')} />
|
|
47
|
+
</ListItem>
|
|
48
|
+
{content}
|
|
49
|
+
</>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default CategoryLinkList;
|