@blocklet/list 0.9.5 → 0.9.8
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 +7 -10
- package/lib/components/aside.js +1 -1
- package/lib/components/autocomplete/index.js +199 -0
- package/lib/components/autocomplete/item.js +156 -0
- package/lib/components/list/index.js +1 -2
- package/lib/contexts/filter.js +4 -4
- package/lib/index.js +21 -2
- package/lib/libs/constant.js +4 -1
- package/lib/libs/utils.js +31 -2
- package/package.json +10 -3
- package/src/base.js +6 -9
- package/src/components/aside.js +1 -1
- package/src/components/autocomplete/index.js +144 -0
- package/src/components/autocomplete/item.js +133 -0
- package/src/components/list/index.js +0 -1
- package/src/contexts/filter.js +3 -4
- package/src/index.js +44 -0
- package/src/libs/constant.js +3 -0
- package/src/libs/utils.js +23 -0
- package/lib/components/search.js +0 -108
- package/src/components/search.js +0 -93
package/lib/base.js
CHANGED
|
@@ -29,11 +29,11 @@ var _list = _interopRequireDefault(require("./components/list"));
|
|
|
29
29
|
|
|
30
30
|
var _aside = _interopRequireDefault(require("./components/aside"));
|
|
31
31
|
|
|
32
|
-
var
|
|
32
|
+
var _autocomplete = _interopRequireDefault(require("./components/autocomplete"));
|
|
33
33
|
|
|
34
34
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
35
35
|
|
|
36
|
-
var _templateObject, _templateObject2
|
|
36
|
+
var _templateObject, _templateObject2;
|
|
37
37
|
|
|
38
38
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
39
39
|
|
|
@@ -71,10 +71,7 @@ function ListBase() {
|
|
|
71
71
|
className: "filter-bar",
|
|
72
72
|
display: "flex",
|
|
73
73
|
alignItems: "center",
|
|
74
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(
|
|
75
|
-
className: "search-container",
|
|
76
|
-
placeholder: t('common.searchStore')
|
|
77
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.Box, {
|
|
74
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_autocomplete.default, {}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.Box, {
|
|
78
75
|
mt: 0,
|
|
79
76
|
ml: "16px",
|
|
80
77
|
className: "filter-container",
|
|
@@ -131,11 +128,11 @@ function ListBase() {
|
|
|
131
128
|
});
|
|
132
129
|
}
|
|
133
130
|
|
|
134
|
-
const StyledMin = _styled.default.main(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n display: flex;\n flex-direction: column;\n flex: 1;\n width: 100%;\n height: 100%;\n .filter-bar {\n justify-content: space-between;\n margin-bottom: ", ";\n }\n .sort-button {\n white-space: nowrap;\n }\n .search-container {\n flex: 2;\n margin-left: 0px;\n }\n\n .filter-container {\n flex: 1;\n display: flex;\n justify-content: flex-end;\n }\n @media (max-width: ", "px) {\n .search-container {\n width: 100%;\n margin-bottom: ", ";\n }\n .filter-container {\n margin-left: 0;\n display: flex;\n justify-content: flex-start;\n }\n .filter-bar {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n }\n }\n @media (max-width: ", "px) {\n .sort-button {\n font-size: 12px;\n }\n }\n"])), props =>
|
|
131
|
+
const StyledMin = _styled.default.main(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n display: flex;\n flex-direction: column;\n flex: 1;\n width: 100%;\n height: 100%;\n .filter-bar {\n justify-content: space-between;\n margin-bottom: ", ";\n }\n .sort-button {\n white-space: nowrap;\n }\n .search-container {\n flex: 2;\n margin-left: 0px;\n }\n\n .filter-container {\n flex: 1;\n display: flex;\n justify-content: flex-end;\n }\n @media (max-width: ", "px) {\n .search-container {\n width: 100%;\n margin-bottom: ", ";\n }\n .filter-container {\n margin-left: 0;\n display: flex;\n justify-content: flex-start;\n }\n .filter-bar {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n }\n }\n @media (max-width: ", "px) {\n .sort-button {\n font-size: 12px;\n }\n }\n"])), props => {
|
|
132
|
+
return props.theme.spacing(2);
|
|
133
|
+
}, props => props.theme.breakpoints.values.md, props => props.theme.spacing(2), props => props.theme.breakpoints.values.md);
|
|
135
134
|
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
const FilterContainer = _styled.default.div(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n position: sticky;\n top: 0;\n z-index: 999;\n background-color: white;\n"])));
|
|
135
|
+
const FilterContainer = _styled.default.div(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n position: sticky;\n top: 0;\n z-index: 9;\n background-color: white;\n"])));
|
|
139
136
|
|
|
140
137
|
var _default = ListBase;
|
|
141
138
|
exports.default = _default;
|
package/lib/components/aside.js
CHANGED
|
@@ -51,7 +51,7 @@ function Aside() {
|
|
|
51
51
|
});
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
const StyledAside = _styled.default.aside(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n width: 220px;\n margin-right: ", ";\n height: 100%;\n position: sticky;\n top: 0;\n overflow-y: auto;\n z-index:
|
|
54
|
+
const StyledAside = _styled.default.aside(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n width: 220px;\n margin-right: ", ";\n height: 100%;\n position: sticky;\n top: 0;\n overflow-y: auto;\n z-index: auto;\n"])), props => props.theme.spacing(2));
|
|
55
55
|
|
|
56
56
|
Aside.propTypes = {};
|
|
57
57
|
Aside.defaultProps = {};
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = Autocomplete;
|
|
7
|
+
|
|
8
|
+
var _react = require("react");
|
|
9
|
+
|
|
10
|
+
var _client = require("react-dom/client");
|
|
11
|
+
|
|
12
|
+
var _autocompleteJs = require("@algolia/autocomplete-js");
|
|
13
|
+
|
|
14
|
+
var _react2 = require("@emotion/react");
|
|
15
|
+
|
|
16
|
+
var _styles = require("@mui/material/styles");
|
|
17
|
+
|
|
18
|
+
var _urlJoin = _interopRequireDefault(require("url-join"));
|
|
19
|
+
|
|
20
|
+
var _constant = _interopRequireDefault(require("../../libs/constant"));
|
|
21
|
+
|
|
22
|
+
var _filter = require("../../contexts/filter");
|
|
23
|
+
|
|
24
|
+
var _item = _interopRequireDefault(require("./item"));
|
|
25
|
+
|
|
26
|
+
require("@algolia/autocomplete-theme-classic");
|
|
27
|
+
|
|
28
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
29
|
+
|
|
30
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
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 cachePool = new Map();
|
|
39
|
+
|
|
40
|
+
function Autocomplete() {
|
|
41
|
+
const containerRef = (0, _react.useRef)(null);
|
|
42
|
+
const panelRootRef = (0, _react.useRef)(null);
|
|
43
|
+
const rootRef = (0, _react.useRef)(null);
|
|
44
|
+
const {
|
|
45
|
+
storeApi,
|
|
46
|
+
filters,
|
|
47
|
+
endpoint,
|
|
48
|
+
handleKeyword,
|
|
49
|
+
t
|
|
50
|
+
} = (0, _filter.useFilterContext)();
|
|
51
|
+
const muiTheme = (0, _styles.useTheme)();
|
|
52
|
+
const getResults = (0, _react.useCallback)(async params => {
|
|
53
|
+
const key = JSON.stringify(params);
|
|
54
|
+
const target = cachePool.get(key);
|
|
55
|
+
if (target) return target.data;
|
|
56
|
+
const {
|
|
57
|
+
data
|
|
58
|
+
} = await storeApi.get(_constant.default.blockletsPath, {
|
|
59
|
+
params
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
if (cachePool.size > _constant.default.cacheSize) {
|
|
63
|
+
cachePool.clear();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
cachePool.set(key, {
|
|
67
|
+
data: data.dataList
|
|
68
|
+
});
|
|
69
|
+
return data.dataList || [];
|
|
70
|
+
}, [storeApi]);
|
|
71
|
+
|
|
72
|
+
const onClickItem = detailUrl => {
|
|
73
|
+
window.location.href = detailUrl;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const onSubmit = (0, _react.useCallback)(e => {
|
|
77
|
+
handleKeyword(e.state.query);
|
|
78
|
+
}, [handleKeyword]);
|
|
79
|
+
const onReset = (0, _react.useCallback)(() => {
|
|
80
|
+
handleKeyword();
|
|
81
|
+
}, [handleKeyword]);
|
|
82
|
+
(0, _react.useEffect)(() => {
|
|
83
|
+
if (!containerRef.current) {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const search = (0, _autocompleteJs.autocomplete)({
|
|
88
|
+
container: containerRef.current,
|
|
89
|
+
renderer: {
|
|
90
|
+
createElement: _react.createElement,
|
|
91
|
+
Fragment: _react.Fragment,
|
|
92
|
+
render: () => {}
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
render(_ref, root) {
|
|
96
|
+
let {
|
|
97
|
+
children
|
|
98
|
+
} = _ref;
|
|
99
|
+
|
|
100
|
+
if (!panelRootRef.current || rootRef.current !== root) {
|
|
101
|
+
var _panelRootRef$current;
|
|
102
|
+
|
|
103
|
+
rootRef.current = root;
|
|
104
|
+
(_panelRootRef$current = panelRootRef.current) === null || _panelRootRef$current === void 0 ? void 0 : _panelRootRef$current.unmount();
|
|
105
|
+
panelRootRef.current = (0, _client.createRoot)(root);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
panelRootRef.current.render(children);
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
classNames: {
|
|
112
|
+
panel: 'blocklet-list-panel',
|
|
113
|
+
label: 'blocklet-list-label',
|
|
114
|
+
form: 'blocklet-list-form'
|
|
115
|
+
},
|
|
116
|
+
placeholder: t('common.searchStore'),
|
|
117
|
+
initialState: {
|
|
118
|
+
query: filters.keyword
|
|
119
|
+
},
|
|
120
|
+
onSubmit,
|
|
121
|
+
onReset,
|
|
122
|
+
|
|
123
|
+
getSources(_ref2) {
|
|
124
|
+
let {
|
|
125
|
+
query
|
|
126
|
+
} = _ref2;
|
|
127
|
+
|
|
128
|
+
const params = _objectSpread(_objectSpread({}, filters), {}, {
|
|
129
|
+
sortBy: _constant.default[filters.sortBy],
|
|
130
|
+
page: 1,
|
|
131
|
+
pageSize: 10,
|
|
132
|
+
keyword: query
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
return [{
|
|
136
|
+
sourceId: 'blocklets',
|
|
137
|
+
|
|
138
|
+
getItems() {
|
|
139
|
+
return getResults(params);
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
// 选中后填充 搜索框中值
|
|
143
|
+
getItemInputValue(_ref3) {
|
|
144
|
+
let {
|
|
145
|
+
item
|
|
146
|
+
} = _ref3;
|
|
147
|
+
return item.title;
|
|
148
|
+
},
|
|
149
|
+
|
|
150
|
+
getItemUrl(_ref4) {
|
|
151
|
+
let {
|
|
152
|
+
item
|
|
153
|
+
} = _ref4;
|
|
154
|
+
const detailUrl = (0, _urlJoin.default)(endpoint, 'blocklets', item.did);
|
|
155
|
+
return detailUrl;
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
templates: {
|
|
159
|
+
// eslint-disable-next-line react/no-unstable-nested-components
|
|
160
|
+
item(_ref5) {
|
|
161
|
+
let {
|
|
162
|
+
item
|
|
163
|
+
} = _ref5;
|
|
164
|
+
const logoUrl = item.logo ? (0, _urlJoin.default)(endpoint, 'assets', item.did, item.logo) : null;
|
|
165
|
+
const detailUrl = (0, _urlJoin.default)(endpoint, 'blocklets', item.did);
|
|
166
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_styles.ThemeProvider, {
|
|
167
|
+
theme: muiTheme,
|
|
168
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_react2.ThemeProvider, {
|
|
169
|
+
theme: muiTheme,
|
|
170
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_item.default, {
|
|
171
|
+
item: item,
|
|
172
|
+
title: (item === null || item === void 0 ? void 0 : item.title) || (item === null || item === void 0 ? void 0 : item.name),
|
|
173
|
+
did: item.did,
|
|
174
|
+
description: item.description,
|
|
175
|
+
cover: logoUrl,
|
|
176
|
+
onMainClick: () => onClickItem(detailUrl)
|
|
177
|
+
})
|
|
178
|
+
})
|
|
179
|
+
});
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
noResults() {
|
|
183
|
+
return 'No results.';
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
}
|
|
187
|
+
}];
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
});
|
|
191
|
+
return () => {
|
|
192
|
+
search.destroy();
|
|
193
|
+
};
|
|
194
|
+
}, [endpoint, filters, getResults, muiTheme, onReset, onSubmit, t]);
|
|
195
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
196
|
+
className: "search-container",
|
|
197
|
+
ref: containerRef
|
|
198
|
+
});
|
|
199
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = Blocklet;
|
|
7
|
+
|
|
8
|
+
var _styled = _interopRequireDefault(require("@emotion/styled"));
|
|
9
|
+
|
|
10
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
11
|
+
|
|
12
|
+
var _Typography = _interopRequireDefault(require("@mui/material/Typography"));
|
|
13
|
+
|
|
14
|
+
var _Img = _interopRequireDefault(require("@arcblock/ux/lib/Img"));
|
|
15
|
+
|
|
16
|
+
var _Avatar = _interopRequireDefault(require("@arcblock/did-connect/lib/Avatar"));
|
|
17
|
+
|
|
18
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
19
|
+
|
|
20
|
+
const _excluded = ["cover", "onMainClick", "item", "className"];
|
|
21
|
+
|
|
22
|
+
var _templateObject;
|
|
23
|
+
|
|
24
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
25
|
+
|
|
26
|
+
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; }
|
|
27
|
+
|
|
28
|
+
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; }
|
|
29
|
+
|
|
30
|
+
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; }
|
|
31
|
+
|
|
32
|
+
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
|
33
|
+
|
|
34
|
+
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
|
35
|
+
|
|
36
|
+
function _taggedTemplateLiteral(strings, raw) { if (!raw) { raw = strings.slice(0); } return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
|
|
37
|
+
|
|
38
|
+
const Div = _styled.default.div(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n &.arcblock-blocklet {\n padding: ", " ", " 0\n ", ";\n }\n .arcblock-blocklet__content {\n cursor: pointer;\n display: flex;\n }\n .arcblock-blocklet__cover {\n width: 64px;\n height: 64px;\n margin-right: ", ";\n overflow: hidden;\n border-radius: 12px;\n transform: translateZ(0);\n }\n\n .arcblock-blocklet__info {\n flex: 1;\n overflow: hidden;\n border-bottom: 1px solid ", ";\n padding-bottom: ", ";\n }\n .arcblock-blocklet__text {\n height: 57px;\n overflow: hidden;\n }\n /* \u8BBE\u7F6E\u591A\u884C\u6587\u672C\u6EA2\u51FA\u663E\u793A\u7701\u7565\u53F7 \u517C\u5BB9fireFox\u3001safari */\n .arcblock-blocklet__title {\n margin: 0;\n font-size: 16px;\n font-weight: 500;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .arcblock-blocklet__describe {\n margin-top: ", ";\n color: ", ";\n font-size: 14px;\n font-weight: 500;\n line-height: 17px;\n max-height: 34px;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n word-break: break-word;\n }\n .ms-highlight {\n background-color: yellow;\n }\n"])), props => props.theme.spacing(2), props => props.theme.spacing(2), props => props.theme.spacing(2), props => props.theme.spacing(2), props => props.theme.palette.divider, props => props.theme.spacing(2), props => props.theme.spacing(0.5), props => props.theme.palette.grey[600]);
|
|
39
|
+
|
|
40
|
+
function Blocklet(_ref) {
|
|
41
|
+
let {
|
|
42
|
+
cover,
|
|
43
|
+
onMainClick,
|
|
44
|
+
item,
|
|
45
|
+
className
|
|
46
|
+
} = _ref,
|
|
47
|
+
rest = _objectWithoutProperties(_ref, _excluded);
|
|
48
|
+
|
|
49
|
+
const wrapHandler = function wrapHandler(handler) {
|
|
50
|
+
let stopFn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : () => false;
|
|
51
|
+
return function (e) {
|
|
52
|
+
if (stopFn()) {
|
|
53
|
+
e.preventDefault();
|
|
54
|
+
e.stopPropagation();
|
|
55
|
+
} else if (handler instanceof Function) {
|
|
56
|
+
e.preventDefault();
|
|
57
|
+
e.stopPropagation();
|
|
58
|
+
|
|
59
|
+
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
60
|
+
args[_key - 1] = arguments[_key];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
handler(...args);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const _onMainClick = wrapHandler(onMainClick);
|
|
69
|
+
|
|
70
|
+
const {
|
|
71
|
+
did,
|
|
72
|
+
description,
|
|
73
|
+
title,
|
|
74
|
+
name
|
|
75
|
+
} = item;
|
|
76
|
+
const blockletTitle = title || name;
|
|
77
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(Div, _objectSpread(_objectSpread({
|
|
78
|
+
className: "".concat(className, " arcblock-blocklet")
|
|
79
|
+
}, rest), {}, {
|
|
80
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
81
|
+
className: "arcblock-blocklet__content",
|
|
82
|
+
onClick: _onMainClick,
|
|
83
|
+
children: [cover ? /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
84
|
+
className: "arcblock-blocklet__cover",
|
|
85
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Img.default, {
|
|
86
|
+
src: cover
|
|
87
|
+
})
|
|
88
|
+
}) : did && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
89
|
+
className: "arcblock-blocklet__cover",
|
|
90
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Avatar.default, {
|
|
91
|
+
did: did,
|
|
92
|
+
size: 64
|
|
93
|
+
})
|
|
94
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
95
|
+
className: "arcblock-blocklet__info",
|
|
96
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
97
|
+
className: "arcblock-blocklet__text",
|
|
98
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Typography.default, {
|
|
99
|
+
component: "h3",
|
|
100
|
+
variant: "h3",
|
|
101
|
+
className: "arcblock-blocklet__title",
|
|
102
|
+
title: title,
|
|
103
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(ShowAttributes, {
|
|
104
|
+
item: item,
|
|
105
|
+
attribute: "title",
|
|
106
|
+
value: blockletTitle
|
|
107
|
+
})
|
|
108
|
+
}), description && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Typography.default, {
|
|
109
|
+
component: "div",
|
|
110
|
+
variant: "body2",
|
|
111
|
+
className: "arcblock-blocklet__describe",
|
|
112
|
+
title: description,
|
|
113
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(ShowAttributes, {
|
|
114
|
+
item: item,
|
|
115
|
+
attribute: "description",
|
|
116
|
+
value: description
|
|
117
|
+
})
|
|
118
|
+
})]
|
|
119
|
+
})
|
|
120
|
+
})]
|
|
121
|
+
})
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
Blocklet.propTypes = {
|
|
126
|
+
cover: _propTypes.default.string,
|
|
127
|
+
onMainClick: _propTypes.default.func,
|
|
128
|
+
className: _propTypes.default.string,
|
|
129
|
+
item: _propTypes.default.object.isRequired
|
|
130
|
+
};
|
|
131
|
+
Blocklet.defaultProps = {
|
|
132
|
+
cover: null,
|
|
133
|
+
onMainClick: null,
|
|
134
|
+
className: null
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
function ShowAttributes(_ref2) {
|
|
138
|
+
let {
|
|
139
|
+
item,
|
|
140
|
+
attribute,
|
|
141
|
+
value
|
|
142
|
+
} = _ref2;
|
|
143
|
+
// eslint-disable-next-line react/no-danger
|
|
144
|
+
if (item._formatted) return /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
|
|
145
|
+
dangerouslySetInnerHTML: {
|
|
146
|
+
__html: item._formatted[attribute]
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
return value;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
ShowAttributes.propTypes = {
|
|
153
|
+
item: _propTypes.default.object.isRequired,
|
|
154
|
+
attribute: _propTypes.default.string.isRequired,
|
|
155
|
+
value: _propTypes.default.string.isRequired
|
|
156
|
+
};
|
|
@@ -65,8 +65,7 @@ function BlockletList(_ref) {
|
|
|
65
65
|
loadMore,
|
|
66
66
|
endpoint
|
|
67
67
|
} = (0, _filter.useFilterContext)();
|
|
68
|
-
const showFilterTip = !!selectedCategory || !!filters.price;
|
|
69
|
-
|
|
68
|
+
const showFilterTip = !!selectedCategory || !!filters.price;
|
|
70
69
|
const [sentryRef] = (0, _reactInfiniteScrollHook.default)({
|
|
71
70
|
loading: loadings.fetchBlockletsLoading || loadings.loadingMore,
|
|
72
71
|
hasNextPage,
|
package/lib/contexts/filter.js
CHANGED
|
@@ -86,7 +86,7 @@ function FilterProvider(_ref) {
|
|
|
86
86
|
|
|
87
87
|
const {
|
|
88
88
|
data = {}
|
|
89
|
-
} = await storeApi.get(
|
|
89
|
+
} = await storeApi.get(_constant.default.blockletsPath, {
|
|
90
90
|
params
|
|
91
91
|
});
|
|
92
92
|
return data;
|
|
@@ -97,7 +97,6 @@ function FilterProvider(_ref) {
|
|
|
97
97
|
},
|
|
98
98
|
loadMore: true,
|
|
99
99
|
isNoMore: d => d ? d.list.length >= d.total : false,
|
|
100
|
-
// eslint-disable-next-line no-console
|
|
101
100
|
formatResult: response => {
|
|
102
101
|
return {
|
|
103
102
|
list: response === null || response === void 0 ? void 0 : response.dataList,
|
|
@@ -113,7 +112,7 @@ function FilterProvider(_ref) {
|
|
|
113
112
|
} = (0, _ahooks.useRequest)(async () => {
|
|
114
113
|
const {
|
|
115
114
|
data
|
|
116
|
-
} = await storeApi.get(
|
|
115
|
+
} = await storeApi.get(_constant.default.categoriesPath);
|
|
117
116
|
return data;
|
|
118
117
|
}, {
|
|
119
118
|
initialData: []
|
|
@@ -137,7 +136,7 @@ function FilterProvider(_ref) {
|
|
|
137
136
|
let blocklets = blockletsState.list || []; // 用户传入的过滤函数
|
|
138
137
|
|
|
139
138
|
blocklets = extraFilter(blocklets);
|
|
140
|
-
return blocklets;
|
|
139
|
+
return blocklets;
|
|
141
140
|
}, [blockletsState, extraFilter]);
|
|
142
141
|
const categoryOptions = (0, _react.useMemo)(() => (0, _utils.getCategoryOptions)(categoryList, locale), [categoryList, locale]);
|
|
143
142
|
const priceOptions = (0, _utils.getPrices)(translate);
|
|
@@ -161,6 +160,7 @@ function FilterProvider(_ref) {
|
|
|
161
160
|
locale,
|
|
162
161
|
categoryOptions,
|
|
163
162
|
priceOptions,
|
|
163
|
+
storeApi,
|
|
164
164
|
hasNextPage: blockletsState.list.length < blockletsState.total,
|
|
165
165
|
handleSort: sort => {
|
|
166
166
|
const changeData = _objectSpread(_objectSpread({}, finalFilters), {}, {
|
package/lib/index.js
CHANGED
|
@@ -5,14 +5,24 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = BlockletList;
|
|
7
7
|
|
|
8
|
+
var _react = require("@emotion/react");
|
|
9
|
+
|
|
10
|
+
var _styles = require("@mui/material/styles");
|
|
11
|
+
|
|
8
12
|
var _base = _interopRequireDefault(require("./base"));
|
|
9
13
|
|
|
10
14
|
var _filter = require("./contexts/filter");
|
|
11
15
|
|
|
12
16
|
var _propTypes = require("./libs/prop-types");
|
|
13
17
|
|
|
18
|
+
var _utils = require("./libs/utils");
|
|
19
|
+
|
|
20
|
+
require("@algolia/autocomplete-theme-classic");
|
|
21
|
+
|
|
14
22
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
15
23
|
|
|
24
|
+
var _templateObject;
|
|
25
|
+
|
|
16
26
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
27
|
|
|
18
28
|
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; }
|
|
@@ -21,9 +31,18 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
|
|
|
21
31
|
|
|
22
32
|
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; }
|
|
23
33
|
|
|
34
|
+
function _taggedTemplateLiteral(strings, raw) { if (!raw) { raw = strings.slice(0); } return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
|
|
35
|
+
|
|
24
36
|
function BlockletList(props) {
|
|
25
|
-
|
|
26
|
-
|
|
37
|
+
const muiTheme = (0, _styles.useTheme)();
|
|
38
|
+
const primaryColor = (0, _utils.toColorRgb)(muiTheme.palette.primary.main);
|
|
39
|
+
const globalStyles = {
|
|
40
|
+
autocomplete: theme => (0, _react.css)(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n :root {\n --aa-detached-media-query: (max-width: ", "px) !important;\n --aa-detached-modal-media-query: (min-width: ", "px) !important;\n --aa-detached-modal-max-width: ", "px !important;\n --aa-selected-color-rgb: ", ", ", ", ", " !important;\n --aa-primary-color-rgb: ", ", ", ", ", " !important;\n --aa-input-background-color-rgb: 250, 250, 250 !important;\n }\n .blocklet-list-panel {\n z-index: ", " !important;\n }\n .blocklet-list-label {\n .aa-SubmitIcon {\n color: ", " !important;\n }\n }\n .blocklet-list-form {\n border: none !important;\n &:focus-within {\n box-shadow: none !important;\n }\n }\n .aa-DetachedSearchButton {\n border: none !important;\n &:focus-within {\n box-shadow: none !important;\n }\n .aa-SubmitIcon {\n color: ", " !important;\n }\n }\n "])), theme.breakpoints.values.md, theme.breakpoints.values.md, theme.breakpoints.values.md, primaryColor.r, primaryColor.g, primaryColor.b, primaryColor.r, primaryColor.g, primaryColor.b, theme.zIndex.modal + 1, theme.palette.grey[500], theme.palette.grey[500])
|
|
41
|
+
};
|
|
42
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_filter.FilterProvider, _objectSpread(_objectSpread({}, props), {}, {
|
|
43
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_react.Global, {
|
|
44
|
+
styles: globalStyles.autocomplete
|
|
45
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_base.default, {})]
|
|
27
46
|
}));
|
|
28
47
|
}
|
|
29
48
|
|
package/lib/libs/constant.js
CHANGED
|
@@ -11,7 +11,10 @@ const constant = {
|
|
|
11
11
|
publishAt: 'lastPublishedAt',
|
|
12
12
|
mobilePageSize: 10,
|
|
13
13
|
pageSize: 18,
|
|
14
|
-
defaultCurrentPage: 1
|
|
14
|
+
defaultCurrentPage: 1,
|
|
15
|
+
blockletsPath: '/api/v2/blocklets.json',
|
|
16
|
+
categoriesPath: '/api/blocklets/categories',
|
|
17
|
+
cacheSize: 100
|
|
15
18
|
};
|
|
16
19
|
var _default = constant;
|
|
17
20
|
exports.default = _default;
|
package/lib/libs/utils.js
CHANGED
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.urlStringify = exports.replaceTranslate = exports.removeUndefined = exports.isMobileScreen = exports.getStoreDetail = exports.getSortOptions = exports.getPrices = exports.getCurrentPage = exports.getCategoryOptions = exports.formatLogoPath = exports.formatError = exports.filterBlockletByPrice = void 0;
|
|
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
7
|
|
|
8
8
|
var _urlJoin = _interopRequireDefault(require("url-join"));
|
|
9
9
|
|
|
10
10
|
var _cloneDeep = _interopRequireDefault(require("lodash/cloneDeep"));
|
|
11
11
|
|
|
12
|
+
var _color = _interopRequireDefault(require("color"));
|
|
13
|
+
|
|
12
14
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
15
|
|
|
14
16
|
const isFreeBlocklet = blocklet => {
|
|
@@ -152,4 +154,31 @@ const getCurrentPage = (length, pageSize) => {
|
|
|
152
154
|
return 1;
|
|
153
155
|
};
|
|
154
156
|
|
|
155
|
-
exports.getCurrentPage = getCurrentPage;
|
|
157
|
+
exports.getCurrentPage = getCurrentPage;
|
|
158
|
+
|
|
159
|
+
const toColorRgb = colorStr => {
|
|
160
|
+
const color = (0, _color.default)(colorStr);
|
|
161
|
+
return color.rgb().object();
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
exports.toColorRgb = toColorRgb;
|
|
165
|
+
|
|
166
|
+
function debouncePromise(fn, time) {
|
|
167
|
+
let timerId;
|
|
168
|
+
return function debounced() {
|
|
169
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
170
|
+
args[_key] = arguments[_key];
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (timerId) {
|
|
174
|
+
clearTimeout(timerId);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return new Promise(resolve => {
|
|
178
|
+
timerId = setTimeout(() => resolve(fn(...args)), time);
|
|
179
|
+
});
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const debounced = debouncePromise(items => Promise.resolve(items), 300);
|
|
184
|
+
exports.debounced = debounced;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/list",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.8",
|
|
4
4
|
"description": "Common ux components of blocklet",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -33,16 +33,23 @@
|
|
|
33
33
|
"url": "https://github.com/blocklet/blocklet-store/issues"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
+
"@arcblock/did-connect": ">=2.2.0",
|
|
36
37
|
"@mui/material": ">=5.6.4",
|
|
37
|
-
"
|
|
38
|
+
"@mui/styles": ">=5.6.2",
|
|
39
|
+
"react": ">=18.1.0",
|
|
40
|
+
"react-dom": ">=18.2.0"
|
|
38
41
|
},
|
|
39
42
|
"dependencies": {
|
|
43
|
+
"@algolia/autocomplete-js": "^1.7.1",
|
|
44
|
+
"@algolia/autocomplete-theme-classic": "^1.7.1",
|
|
40
45
|
"@arcblock/ux": "^2.4.0",
|
|
41
46
|
"@emotion/react": "^11.10.0",
|
|
42
47
|
"@emotion/styled": "^11.10.0",
|
|
43
48
|
"@mui/icons-material": "^5.8.4",
|
|
44
49
|
"ahooks": "^2.10.14",
|
|
50
|
+
"algoliasearch": "^4.14.2",
|
|
45
51
|
"axios": "^0.27.2",
|
|
52
|
+
"color": "^4.2.3",
|
|
46
53
|
"flat": "^5.0.2",
|
|
47
54
|
"lodash": "^4.17.21",
|
|
48
55
|
"prop-types": "^15.8.1",
|
|
@@ -61,5 +68,5 @@
|
|
|
61
68
|
"eslint": "^8.21.0",
|
|
62
69
|
"prettier": "^2.7.1"
|
|
63
70
|
},
|
|
64
|
-
"gitHead": "
|
|
71
|
+
"gitHead": "ba3bddff0fbbcf7f9a79c9a346dcf1810c0435fc"
|
|
65
72
|
}
|
package/src/base.js
CHANGED
|
@@ -4,14 +4,13 @@ import { Box, Hidden } from '@mui/material';
|
|
|
4
4
|
import FaceIcon from '@mui/icons-material/Face';
|
|
5
5
|
import { ErrorBoundary } from 'react-error-boundary';
|
|
6
6
|
import { ErrorFallback } from '@arcblock/ux/lib/ErrorBoundary';
|
|
7
|
-
|
|
8
7
|
import { useFilterContext } from './contexts/filter';
|
|
9
8
|
import CustomSelect from './components/custom-select';
|
|
10
9
|
import { CustomChip, FilterIcon } from './components/filter';
|
|
11
10
|
import { getSortOptions } from './libs/utils';
|
|
12
11
|
import BlockletList from './components/list';
|
|
13
12
|
import Aside from './components/aside';
|
|
14
|
-
import
|
|
13
|
+
import Autocomplete from './components/autocomplete';
|
|
15
14
|
|
|
16
15
|
function ListBase() {
|
|
17
16
|
const {
|
|
@@ -39,7 +38,7 @@ function ListBase() {
|
|
|
39
38
|
<StyledMin>
|
|
40
39
|
<FilterContainer>
|
|
41
40
|
<Box className="filter-bar" display="flex" alignItems="center">
|
|
42
|
-
<
|
|
41
|
+
<Autocomplete />
|
|
43
42
|
<Box mt={0} ml="16px" className="filter-container">
|
|
44
43
|
<Hidden mdUp>
|
|
45
44
|
{/* 小屏幕下类别 */}
|
|
@@ -97,7 +96,9 @@ const StyledMin = styled.main`
|
|
|
97
96
|
height: 100%;
|
|
98
97
|
.filter-bar {
|
|
99
98
|
justify-content: space-between;
|
|
100
|
-
margin-bottom: ${(props) =>
|
|
99
|
+
margin-bottom: ${(props) => {
|
|
100
|
+
return props.theme.spacing(2);
|
|
101
|
+
}};
|
|
101
102
|
}
|
|
102
103
|
.sort-button {
|
|
103
104
|
white-space: nowrap;
|
|
@@ -135,14 +136,10 @@ const StyledMin = styled.main`
|
|
|
135
136
|
}
|
|
136
137
|
`;
|
|
137
138
|
|
|
138
|
-
const StyledSearch = styled(Search)`
|
|
139
|
-
background-color: ${(props) => props.theme.palette.grey[50]};
|
|
140
|
-
`;
|
|
141
|
-
|
|
142
139
|
const FilterContainer = styled.div`
|
|
143
140
|
position: sticky;
|
|
144
141
|
top: 0;
|
|
145
|
-
z-index:
|
|
142
|
+
z-index: 9;
|
|
146
143
|
background-color: white;
|
|
147
144
|
`;
|
|
148
145
|
|
package/src/components/aside.js
CHANGED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { createElement, Fragment, useEffect, useRef, useCallback } from 'react';
|
|
2
|
+
import { createRoot } from 'react-dom/client';
|
|
3
|
+
import { autocomplete } from '@algolia/autocomplete-js';
|
|
4
|
+
|
|
5
|
+
import { ThemeProvider as EmotionThemeProvider } from '@emotion/react';
|
|
6
|
+
import { ThemeProvider as MuiThemeProvider, useTheme } from '@mui/material/styles';
|
|
7
|
+
import joinUrl from 'url-join';
|
|
8
|
+
|
|
9
|
+
import constant from '../../libs/constant';
|
|
10
|
+
import { useFilterContext } from '../../contexts/filter';
|
|
11
|
+
import Blocklet from './item';
|
|
12
|
+
|
|
13
|
+
import '@algolia/autocomplete-theme-classic';
|
|
14
|
+
|
|
15
|
+
const cachePool = new Map();
|
|
16
|
+
|
|
17
|
+
export default function Autocomplete() {
|
|
18
|
+
const containerRef = useRef(null);
|
|
19
|
+
const panelRootRef = useRef(null);
|
|
20
|
+
const rootRef = useRef(null);
|
|
21
|
+
const { storeApi, filters, endpoint, handleKeyword, t } = useFilterContext();
|
|
22
|
+
const muiTheme = useTheme();
|
|
23
|
+
|
|
24
|
+
const getResults = useCallback(
|
|
25
|
+
async (params) => {
|
|
26
|
+
const key = JSON.stringify(params);
|
|
27
|
+
const target = cachePool.get(key);
|
|
28
|
+
|
|
29
|
+
if (target) return target.data;
|
|
30
|
+
|
|
31
|
+
const { data } = await storeApi.get(constant.blockletsPath, { params });
|
|
32
|
+
|
|
33
|
+
if (cachePool.size > constant.cacheSize) {
|
|
34
|
+
cachePool.clear();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
cachePool.set(key, {
|
|
38
|
+
data: data.dataList,
|
|
39
|
+
});
|
|
40
|
+
return data.dataList || [];
|
|
41
|
+
},
|
|
42
|
+
[storeApi]
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const onClickItem = (detailUrl) => {
|
|
46
|
+
window.location.href = detailUrl;
|
|
47
|
+
};
|
|
48
|
+
const onSubmit = useCallback(
|
|
49
|
+
(e) => {
|
|
50
|
+
handleKeyword(e.state.query);
|
|
51
|
+
},
|
|
52
|
+
[handleKeyword]
|
|
53
|
+
);
|
|
54
|
+
const onReset = useCallback(() => {
|
|
55
|
+
handleKeyword();
|
|
56
|
+
}, [handleKeyword]);
|
|
57
|
+
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
if (!containerRef.current) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const search = autocomplete({
|
|
64
|
+
container: containerRef.current,
|
|
65
|
+
renderer: { createElement, Fragment, render: () => {} },
|
|
66
|
+
render({ children }, root) {
|
|
67
|
+
if (!panelRootRef.current || rootRef.current !== root) {
|
|
68
|
+
rootRef.current = root;
|
|
69
|
+
|
|
70
|
+
panelRootRef.current?.unmount();
|
|
71
|
+
panelRootRef.current = createRoot(root);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
panelRootRef.current.render(children);
|
|
75
|
+
},
|
|
76
|
+
classNames: {
|
|
77
|
+
panel: 'blocklet-list-panel',
|
|
78
|
+
label: 'blocklet-list-label',
|
|
79
|
+
form: 'blocklet-list-form',
|
|
80
|
+
},
|
|
81
|
+
placeholder: t('common.searchStore'),
|
|
82
|
+
initialState: {
|
|
83
|
+
query: filters.keyword,
|
|
84
|
+
},
|
|
85
|
+
onSubmit,
|
|
86
|
+
onReset,
|
|
87
|
+
getSources({ query }) {
|
|
88
|
+
const params = {
|
|
89
|
+
...filters,
|
|
90
|
+
sortBy: constant[filters.sortBy],
|
|
91
|
+
page: 1,
|
|
92
|
+
pageSize: 10,
|
|
93
|
+
keyword: query,
|
|
94
|
+
};
|
|
95
|
+
return [
|
|
96
|
+
{
|
|
97
|
+
sourceId: 'blocklets',
|
|
98
|
+
getItems() {
|
|
99
|
+
return getResults(params);
|
|
100
|
+
},
|
|
101
|
+
// 选中后填充 搜索框中值
|
|
102
|
+
getItemInputValue({ item }) {
|
|
103
|
+
return item.title;
|
|
104
|
+
},
|
|
105
|
+
getItemUrl({ item }) {
|
|
106
|
+
const detailUrl = joinUrl(endpoint, 'blocklets', item.did);
|
|
107
|
+
return detailUrl;
|
|
108
|
+
},
|
|
109
|
+
templates: {
|
|
110
|
+
// eslint-disable-next-line react/no-unstable-nested-components
|
|
111
|
+
item({ item }) {
|
|
112
|
+
const logoUrl = item.logo ? joinUrl(endpoint, 'assets', item.did, item.logo) : null;
|
|
113
|
+
const detailUrl = joinUrl(endpoint, 'blocklets', item.did);
|
|
114
|
+
return (
|
|
115
|
+
<MuiThemeProvider theme={muiTheme}>
|
|
116
|
+
<EmotionThemeProvider theme={muiTheme}>
|
|
117
|
+
<Blocklet
|
|
118
|
+
item={item}
|
|
119
|
+
title={item?.title || item?.name}
|
|
120
|
+
did={item.did}
|
|
121
|
+
description={item.description}
|
|
122
|
+
cover={logoUrl}
|
|
123
|
+
onMainClick={() => onClickItem(detailUrl)}
|
|
124
|
+
/>
|
|
125
|
+
</EmotionThemeProvider>
|
|
126
|
+
</MuiThemeProvider>
|
|
127
|
+
);
|
|
128
|
+
},
|
|
129
|
+
noResults() {
|
|
130
|
+
return 'No results.';
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
];
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
return () => {
|
|
139
|
+
search.destroy();
|
|
140
|
+
};
|
|
141
|
+
}, [endpoint, filters, getResults, muiTheme, onReset, onSubmit, t]);
|
|
142
|
+
|
|
143
|
+
return <div className="search-container" ref={containerRef} />;
|
|
144
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import styled from '@emotion/styled';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import Typography from '@mui/material/Typography';
|
|
4
|
+
import Img from '@arcblock/ux/lib/Img';
|
|
5
|
+
import Avatar from '@arcblock/did-connect/lib/Avatar';
|
|
6
|
+
|
|
7
|
+
const Div = styled.div`
|
|
8
|
+
&.arcblock-blocklet {
|
|
9
|
+
padding: ${(props) => props.theme.spacing(2)} ${(props) => props.theme.spacing(2)} 0
|
|
10
|
+
${(props) => props.theme.spacing(2)};
|
|
11
|
+
}
|
|
12
|
+
.arcblock-blocklet__content {
|
|
13
|
+
cursor: pointer;
|
|
14
|
+
display: flex;
|
|
15
|
+
}
|
|
16
|
+
.arcblock-blocklet__cover {
|
|
17
|
+
width: 64px;
|
|
18
|
+
height: 64px;
|
|
19
|
+
margin-right: ${(props) => props.theme.spacing(2)};
|
|
20
|
+
overflow: hidden;
|
|
21
|
+
border-radius: 12px;
|
|
22
|
+
transform: translateZ(0);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.arcblock-blocklet__info {
|
|
26
|
+
flex: 1;
|
|
27
|
+
overflow: hidden;
|
|
28
|
+
border-bottom: 1px solid ${(props) => props.theme.palette.divider};
|
|
29
|
+
padding-bottom: ${(props) => props.theme.spacing(2)};
|
|
30
|
+
}
|
|
31
|
+
.arcblock-blocklet__text {
|
|
32
|
+
height: 57px;
|
|
33
|
+
overflow: hidden;
|
|
34
|
+
}
|
|
35
|
+
/* 设置多行文本溢出显示省略号 兼容fireFox、safari */
|
|
36
|
+
.arcblock-blocklet__title {
|
|
37
|
+
margin: 0;
|
|
38
|
+
font-size: 16px;
|
|
39
|
+
font-weight: 500;
|
|
40
|
+
overflow: hidden;
|
|
41
|
+
text-overflow: ellipsis;
|
|
42
|
+
white-space: nowrap;
|
|
43
|
+
}
|
|
44
|
+
.arcblock-blocklet__describe {
|
|
45
|
+
margin-top: ${(props) => props.theme.spacing(0.5)};
|
|
46
|
+
color: ${(props) => props.theme.palette.grey[600]};
|
|
47
|
+
font-size: 14px;
|
|
48
|
+
font-weight: 500;
|
|
49
|
+
line-height: 17px;
|
|
50
|
+
max-height: 34px;
|
|
51
|
+
overflow: hidden;
|
|
52
|
+
text-overflow: ellipsis;
|
|
53
|
+
display: -webkit-box;
|
|
54
|
+
-webkit-line-clamp: 2;
|
|
55
|
+
-webkit-box-orient: vertical;
|
|
56
|
+
word-break: break-word;
|
|
57
|
+
}
|
|
58
|
+
.ms-highlight {
|
|
59
|
+
background-color: yellow;
|
|
60
|
+
}
|
|
61
|
+
`;
|
|
62
|
+
|
|
63
|
+
export default function Blocklet({ cover, onMainClick, item, className, ...rest }) {
|
|
64
|
+
const wrapHandler =
|
|
65
|
+
(handler, stopFn = () => false) =>
|
|
66
|
+
(e, ...args) => {
|
|
67
|
+
if (stopFn()) {
|
|
68
|
+
e.preventDefault();
|
|
69
|
+
e.stopPropagation();
|
|
70
|
+
} else if (handler instanceof Function) {
|
|
71
|
+
e.preventDefault();
|
|
72
|
+
e.stopPropagation();
|
|
73
|
+
handler(...args);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const _onMainClick = wrapHandler(onMainClick);
|
|
77
|
+
const { did, description, title, name } = item;
|
|
78
|
+
const blockletTitle = title || name;
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<Div className={`${className} arcblock-blocklet`} {...rest}>
|
|
82
|
+
<div className="arcblock-blocklet__content" onClick={_onMainClick}>
|
|
83
|
+
{cover ? (
|
|
84
|
+
<div className="arcblock-blocklet__cover">
|
|
85
|
+
<Img src={cover} />
|
|
86
|
+
</div>
|
|
87
|
+
) : (
|
|
88
|
+
did && (
|
|
89
|
+
<div className="arcblock-blocklet__cover">
|
|
90
|
+
<Avatar did={did} size={64} />
|
|
91
|
+
</div>
|
|
92
|
+
)
|
|
93
|
+
)}
|
|
94
|
+
<div className="arcblock-blocklet__info">
|
|
95
|
+
<div className="arcblock-blocklet__text">
|
|
96
|
+
<Typography component="h3" variant="h3" className="arcblock-blocklet__title" title={title}>
|
|
97
|
+
<ShowAttributes item={item} attribute="title" value={blockletTitle} />
|
|
98
|
+
</Typography>
|
|
99
|
+
{description && (
|
|
100
|
+
<Typography component="div" variant="body2" className="arcblock-blocklet__describe" title={description}>
|
|
101
|
+
<ShowAttributes item={item} attribute="description" value={description} />
|
|
102
|
+
</Typography>
|
|
103
|
+
)}
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
</Div>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
Blocklet.propTypes = {
|
|
112
|
+
cover: PropTypes.string,
|
|
113
|
+
onMainClick: PropTypes.func,
|
|
114
|
+
className: PropTypes.string,
|
|
115
|
+
item: PropTypes.object.isRequired,
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
Blocklet.defaultProps = {
|
|
119
|
+
cover: null,
|
|
120
|
+
onMainClick: null,
|
|
121
|
+
className: null,
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
function ShowAttributes({ item, attribute, value }) {
|
|
125
|
+
// eslint-disable-next-line react/no-danger
|
|
126
|
+
if (item._formatted) return <span dangerouslySetInnerHTML={{ __html: item._formatted[attribute] }} />;
|
|
127
|
+
return value;
|
|
128
|
+
}
|
|
129
|
+
ShowAttributes.propTypes = {
|
|
130
|
+
item: PropTypes.object.isRequired,
|
|
131
|
+
attribute: PropTypes.string.isRequired,
|
|
132
|
+
value: PropTypes.string.isRequired,
|
|
133
|
+
};
|
|
@@ -27,7 +27,6 @@ export default function BlockletList({ blocklets, ...rest }) {
|
|
|
27
27
|
|
|
28
28
|
const showFilterTip = !!selectedCategory || !!filters.price;
|
|
29
29
|
|
|
30
|
-
// eslint-disable-next-line no-unused-vars
|
|
31
30
|
const [sentryRef] = useInfiniteScroll({
|
|
32
31
|
loading: loadings.fetchBlockletsLoading || loadings.loadingMore,
|
|
33
32
|
hasNextPage,
|
package/src/contexts/filter.js
CHANGED
|
@@ -42,14 +42,13 @@ function FilterProvider({ filters, children, endpoint, locale, blockletRender, o
|
|
|
42
42
|
page: getCurrentPage(d?.list?.length || 0, paginateState.pageSize),
|
|
43
43
|
pageSize: paginateState.pageSize,
|
|
44
44
|
};
|
|
45
|
-
const { data = {} } = await storeApi.get(
|
|
45
|
+
const { data = {} } = await storeApi.get(constant.blockletsPath, { params });
|
|
46
46
|
return data;
|
|
47
47
|
},
|
|
48
48
|
{
|
|
49
49
|
initialData: { list: [], total: 0 },
|
|
50
50
|
loadMore: true,
|
|
51
51
|
isNoMore: (d) => (d ? d.list.length >= d.total : false),
|
|
52
|
-
// eslint-disable-next-line no-console
|
|
53
52
|
formatResult: (response) => {
|
|
54
53
|
return { list: response?.dataList, total: response.total };
|
|
55
54
|
},
|
|
@@ -63,7 +62,7 @@ function FilterProvider({ filters, children, endpoint, locale, blockletRender, o
|
|
|
63
62
|
loading: fetchCategoriesLoading,
|
|
64
63
|
} = useRequest(
|
|
65
64
|
async () => {
|
|
66
|
-
const { data } = await storeApi.get(
|
|
65
|
+
const { data } = await storeApi.get(constant.categoriesPath);
|
|
67
66
|
return data;
|
|
68
67
|
},
|
|
69
68
|
{ initialData: [] }
|
|
@@ -88,7 +87,6 @@ function FilterProvider({ filters, children, endpoint, locale, blockletRender, o
|
|
|
88
87
|
// 用户传入的过滤函数
|
|
89
88
|
blocklets = extraFilter(blocklets);
|
|
90
89
|
return blocklets;
|
|
91
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
92
90
|
}, [blockletsState, extraFilter]);
|
|
93
91
|
|
|
94
92
|
const categoryOptions = useMemo(() => getCategoryOptions(categoryList, locale), [categoryList, locale]);
|
|
@@ -106,6 +104,7 @@ function FilterProvider({ filters, children, endpoint, locale, blockletRender, o
|
|
|
106
104
|
locale,
|
|
107
105
|
categoryOptions,
|
|
108
106
|
priceOptions,
|
|
107
|
+
storeApi,
|
|
109
108
|
hasNextPage: blockletsState.list.length < blockletsState.total,
|
|
110
109
|
handleSort: (sort) => {
|
|
111
110
|
const changeData = {
|
package/src/index.js
CHANGED
|
@@ -1,10 +1,54 @@
|
|
|
1
|
+
import { Global, css } from '@emotion/react';
|
|
2
|
+
import { useTheme } from '@mui/material/styles';
|
|
1
3
|
import SelectBase from './base';
|
|
2
4
|
import { FilterProvider } from './contexts/filter';
|
|
3
5
|
import { propTypes, defaultProps } from './libs/prop-types';
|
|
6
|
+
import { toColorRgb } from './libs/utils';
|
|
7
|
+
|
|
8
|
+
import '@algolia/autocomplete-theme-classic';
|
|
4
9
|
|
|
5
10
|
export default function BlockletList(props) {
|
|
11
|
+
const muiTheme = useTheme();
|
|
12
|
+
const primaryColor = toColorRgb(muiTheme.palette.primary.main);
|
|
13
|
+
|
|
14
|
+
const globalStyles = {
|
|
15
|
+
autocomplete: (theme) => css`
|
|
16
|
+
:root {
|
|
17
|
+
--aa-detached-media-query: (max-width: ${theme.breakpoints.values.md}px) !important;
|
|
18
|
+
--aa-detached-modal-media-query: (min-width: ${theme.breakpoints.values.md}px) !important;
|
|
19
|
+
--aa-detached-modal-max-width: ${theme.breakpoints.values.md}px !important;
|
|
20
|
+
--aa-selected-color-rgb: ${primaryColor.r}, ${primaryColor.g}, ${primaryColor.b} !important;
|
|
21
|
+
--aa-primary-color-rgb: ${primaryColor.r}, ${primaryColor.g}, ${primaryColor.b} !important;
|
|
22
|
+
--aa-input-background-color-rgb: 250, 250, 250 !important;
|
|
23
|
+
}
|
|
24
|
+
.blocklet-list-panel {
|
|
25
|
+
z-index: ${theme.zIndex.modal + 1} !important;
|
|
26
|
+
}
|
|
27
|
+
.blocklet-list-label {
|
|
28
|
+
.aa-SubmitIcon {
|
|
29
|
+
color: ${theme.palette.grey[500]} !important;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
.blocklet-list-form {
|
|
33
|
+
border: none !important;
|
|
34
|
+
&:focus-within {
|
|
35
|
+
box-shadow: none !important;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
.aa-DetachedSearchButton {
|
|
39
|
+
border: none !important;
|
|
40
|
+
&:focus-within {
|
|
41
|
+
box-shadow: none !important;
|
|
42
|
+
}
|
|
43
|
+
.aa-SubmitIcon {
|
|
44
|
+
color: ${theme.palette.grey[500]} !important;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
`,
|
|
48
|
+
};
|
|
6
49
|
return (
|
|
7
50
|
<FilterProvider {...props}>
|
|
51
|
+
<Global styles={globalStyles.autocomplete} />
|
|
8
52
|
<SelectBase />
|
|
9
53
|
</FilterProvider>
|
|
10
54
|
);
|
package/src/libs/constant.js
CHANGED
package/src/libs/utils.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import joinURL from 'url-join';
|
|
2
2
|
import cloneDeep from 'lodash/cloneDeep';
|
|
3
|
+
import Color from 'color';
|
|
3
4
|
|
|
4
5
|
const isFreeBlocklet = (blocklet) => {
|
|
5
6
|
if (!blocklet.payment) {
|
|
@@ -104,6 +105,26 @@ const getCurrentPage = (length, pageSize) => {
|
|
|
104
105
|
return 1;
|
|
105
106
|
};
|
|
106
107
|
|
|
108
|
+
const toColorRgb = (colorStr) => {
|
|
109
|
+
const color = Color(colorStr);
|
|
110
|
+
return color.rgb().object();
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
function debouncePromise(fn, time) {
|
|
114
|
+
let timerId;
|
|
115
|
+
|
|
116
|
+
return function debounced(...args) {
|
|
117
|
+
if (timerId) {
|
|
118
|
+
clearTimeout(timerId);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return new Promise((resolve) => {
|
|
122
|
+
timerId = setTimeout(() => resolve(fn(...args)), time);
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
const debounced = debouncePromise((items) => Promise.resolve(items), 300);
|
|
127
|
+
|
|
107
128
|
export {
|
|
108
129
|
getSortOptions,
|
|
109
130
|
getPrices,
|
|
@@ -117,4 +138,6 @@ export {
|
|
|
117
138
|
getCategoryOptions,
|
|
118
139
|
isMobileScreen,
|
|
119
140
|
getCurrentPage,
|
|
141
|
+
toColorRgb,
|
|
142
|
+
debounced,
|
|
120
143
|
};
|
package/lib/components/search.js
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = void 0;
|
|
7
|
-
|
|
8
|
-
var _react = require("react");
|
|
9
|
-
|
|
10
|
-
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
11
|
-
|
|
12
|
-
var _Search = _interopRequireDefault(require("@mui/icons-material/Search"));
|
|
13
|
-
|
|
14
|
-
var _Close = _interopRequireDefault(require("@mui/icons-material/Close"));
|
|
15
|
-
|
|
16
|
-
var _material = require("@mui/material");
|
|
17
|
-
|
|
18
|
-
var _ahooks = require("ahooks");
|
|
19
|
-
|
|
20
|
-
var _styled = _interopRequireDefault(require("@emotion/styled"));
|
|
21
|
-
|
|
22
|
-
var _filter = require("../contexts/filter");
|
|
23
|
-
|
|
24
|
-
var _jsxRuntime = require("react/jsx-runtime");
|
|
25
|
-
|
|
26
|
-
var _templateObject, _templateObject2, _templateObject3;
|
|
27
|
-
|
|
28
|
-
const _excluded = ["placeholder"];
|
|
29
|
-
|
|
30
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
31
|
-
|
|
32
|
-
function _taggedTemplateLiteral(strings, raw) { if (!raw) { raw = strings.slice(0); } return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
|
|
33
|
-
|
|
34
|
-
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; }
|
|
35
|
-
|
|
36
|
-
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; }
|
|
37
|
-
|
|
38
|
-
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; }
|
|
39
|
-
|
|
40
|
-
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
|
41
|
-
|
|
42
|
-
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
|
43
|
-
|
|
44
|
-
function Search(_ref) {
|
|
45
|
-
let {
|
|
46
|
-
placeholder
|
|
47
|
-
} = _ref,
|
|
48
|
-
rest = _objectWithoutProperties(_ref, _excluded);
|
|
49
|
-
|
|
50
|
-
const {
|
|
51
|
-
filters,
|
|
52
|
-
handleKeyword
|
|
53
|
-
} = (0, _filter.useFilterContext)();
|
|
54
|
-
const [searchStr, setSearchStr] = (0, _react.useState)(filters.keyword || '');
|
|
55
|
-
const debouncedSearch = (0, _ahooks.useDebounceFn)(handleKeyword, {
|
|
56
|
-
wait: 300
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
const handleChange = event => {
|
|
60
|
-
const {
|
|
61
|
-
value
|
|
62
|
-
} = event.target;
|
|
63
|
-
setSearchStr(value);
|
|
64
|
-
debouncedSearch.run(value);
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
const handleClose = () => {
|
|
68
|
-
setSearchStr('');
|
|
69
|
-
handleKeyword();
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
(0, _react.useEffect)(() => {
|
|
73
|
-
setSearchStr(filters.keyword || '');
|
|
74
|
-
}, [filters.keyword]);
|
|
75
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(StyledSearch, _objectSpread({
|
|
76
|
-
inputProps: {
|
|
77
|
-
'data-cy': 'search-blocklet'
|
|
78
|
-
},
|
|
79
|
-
startAdornment: /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.InputAdornment, {
|
|
80
|
-
position: "start",
|
|
81
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(StyledSearchIcon, {})
|
|
82
|
-
}),
|
|
83
|
-
onChange: handleChange,
|
|
84
|
-
placeholder: placeholder,
|
|
85
|
-
value: searchStr,
|
|
86
|
-
title: placeholder,
|
|
87
|
-
"data-cy": "search",
|
|
88
|
-
endAdornment: searchStr && /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.InputAdornment, {
|
|
89
|
-
position: "end",
|
|
90
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(StyledCloseIcon, {
|
|
91
|
-
"data-cy": "search-delete",
|
|
92
|
-
onClick: handleClose
|
|
93
|
-
})
|
|
94
|
-
})
|
|
95
|
-
}, rest));
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
Search.propTypes = {
|
|
99
|
-
placeholder: _propTypes.default.string
|
|
100
|
-
};
|
|
101
|
-
Search.defaultProps = {
|
|
102
|
-
placeholder: 'Type to search...'
|
|
103
|
-
};
|
|
104
|
-
const StyledSearch = (0, _styled.default)(_material.OutlinedInput)(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n background-color: #fff;\n font-size: 14px;\n border-radius: 6px;\n .MuiInputBase-input {\n padding: 8px 0 8px 10px;\n }\n .MuiOutlinedInput-notchedOutline {\n border: none;\n }\n .Mui-focused {\n background-color: #f6f6f6;\n .MuiInputBase-input::placeholder {\n color: transparent;\n }\n }\n"])));
|
|
105
|
-
const StyledSearchIcon = (0, _styled.default)(_Search.default)(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n color: ", ";\n font-size: 28px;\n @media (max-width: ", "px) {\n font-size: 24px;\n }\n"])), props => props.theme.palette.grey[500], props => props.theme.breakpoints.values.md);
|
|
106
|
-
const StyledCloseIcon = (0, _styled.default)(_Close.default)(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n color: ", ";\n font-size: 16px;\n cursor: pointer;\n"])), props => props.theme.palette.grey[500]);
|
|
107
|
-
var _default = Search;
|
|
108
|
-
exports.default = _default;
|
package/src/components/search.js
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
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 Search({ 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
|
-
Search.propTypes = {
|
|
56
|
-
placeholder: PropTypes.string,
|
|
57
|
-
};
|
|
58
|
-
Search.defaultProps = {
|
|
59
|
-
placeholder: 'Type to search...',
|
|
60
|
-
};
|
|
61
|
-
const StyledSearch = styled(OutlinedInput)`
|
|
62
|
-
background-color: #fff;
|
|
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 Search;
|