@blocklet/list 0.10.19 → 0.10.21

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.
@@ -37,6 +37,9 @@ const en = {
37
37
  noBlockletPart2: '"were found',
38
38
  noCategoryResults1: 'No "',
39
39
  noCategoryResults2: '" Blocklets'
40
+ },
41
+ autocomplete: {
42
+ expandResult: 'Show {number} search results for "{name}" '
40
43
  }
41
44
  };
42
45
  const zh = {
@@ -69,6 +72,9 @@ const zh = {
69
72
  noBlockletPart2: '"相关的 Blocklets',
70
73
  noCategoryResults1: '无 "',
71
74
  noCategoryResults2: '" 类别的 Blocklets'
75
+ },
76
+ autocomplete: {
77
+ expandResult: '显示 {number} 条 “{name}” 的搜索结果 '
72
78
  }
73
79
  };
74
80
  var _default = {
@@ -15,8 +15,6 @@ var _autocompleteJs = require("@algolia/autocomplete-js");
15
15
 
16
16
  var _reactHotkeysHook = require("react-hotkeys-hook");
17
17
 
18
- var _react2 = require("@emotion/react");
19
-
20
18
  var _styles = require("@mui/material/styles");
21
19
 
22
20
  var _urlJoin = _interopRequireDefault(require("url-join"));
@@ -54,17 +52,26 @@ function Autocomplete(_ref) {
54
52
  t
55
53
  } = (0, _filter.useFilterContext)();
56
54
  const muiTheme = (0, _styles.useTheme)();
57
- const getResults = (0, _react.useCallback)(async params => {
55
+ const getBlocklets = (0, _react.useCallback)(async params => {
58
56
  const {
59
57
  data
60
58
  } = await storeApi.get(_constant.default.blockletsPath, {
61
59
  params
62
60
  });
63
- return data.dataList || [];
61
+ const blocklets = data.dataList || []; // 头部插入的一条 item 用于展示 `点击展开 xx条 结果`,如果没有blocklet 返回,不展示
62
+
63
+ if (blocklets.length > 0) {
64
+ blocklets.unshift({
65
+ type: 'more-result',
66
+ total: data.total || 0
67
+ });
68
+ }
69
+
70
+ return blocklets;
64
71
  }, [storeApi]);
65
72
  const onSubmit = (0, _react.useCallback)(e => {
66
- handleKeyword(e.state.query); // eslint-disable-next-line react-hooks/exhaustive-deps
67
- }, []);
73
+ handleKeyword(e.state.query);
74
+ }, [handleKeyword]);
68
75
 
69
76
  const setFocus = () => {
70
77
  if (containerRef.current) {
@@ -80,10 +87,22 @@ function Autocomplete(_ref) {
80
87
  };
81
88
 
82
89
  const onReset = (0, _react.useCallback)(autocompleteState => {
83
- handleKeyword();
90
+ autocompleteState.setIsOpen(false);
84
91
  setFocus();
85
- autocompleteState.setIsOpen(false); // eslint-disable-next-line react-hooks/exhaustive-deps
86
92
  }, []);
93
+ const onStateChange = (0, _react.useCallback)(_ref2 => {
94
+ let {
95
+ prevState,
96
+ state
97
+ } = _ref2;
98
+
99
+ // eslint-disable-next-line no-console
100
+ if (prevState.query !== state.query) {
101
+ if (!state.query) {
102
+ handleKeyword();
103
+ }
104
+ }
105
+ }, [handleKeyword]);
87
106
  (0, _reactHotkeysHook.useHotkeys)('/, ctrl + k, command + k', e => {
88
107
  e.stopPropagation();
89
108
  e.preventDefault();
@@ -108,10 +127,10 @@ function Autocomplete(_ref) {
108
127
  render: () => {}
109
128
  },
110
129
 
111
- render(_ref2, root) {
130
+ render(_ref3, root) {
112
131
  let {
113
132
  children
114
- } = _ref2;
133
+ } = _ref3;
115
134
 
116
135
  if (!panelRootRef.current || rootRef.current !== root) {
117
136
  var _panelRootRef$current;
@@ -124,7 +143,7 @@ function Autocomplete(_ref) {
124
143
  panelRootRef.current.render(children);
125
144
  },
126
145
 
127
- autoFocus: true,
146
+ autoFocus: false,
128
147
  classNames: {
129
148
  panel: 'bl-autocomplete-panel',
130
149
  label: 'bl-autocomplete-label',
@@ -136,16 +155,21 @@ function Autocomplete(_ref) {
136
155
  initialState: {
137
156
  query: filters.keyword
138
157
  },
158
+
159
+ onStateChange(autocompleteState) {
160
+ onStateChange(autocompleteState);
161
+ },
162
+
139
163
  onSubmit,
140
164
 
141
165
  onReset(autocompleteState) {
142
166
  onReset(autocompleteState);
143
167
  },
144
168
 
145
- getSources(_ref3) {
169
+ getSources(_ref4) {
146
170
  let {
147
171
  query
148
- } = _ref3;
172
+ } = _ref4;
149
173
 
150
174
  const params = _objectSpread(_objectSpread({}, filters), {}, {
151
175
  sortBy: _constant.default[filters.sortBy],
@@ -158,22 +182,33 @@ function Autocomplete(_ref) {
158
182
  sourceId: 'blocklets',
159
183
 
160
184
  getItems() {
161
- return getResults(params);
185
+ return getBlocklets(params);
162
186
  },
163
187
 
164
188
  // 选中后填充 搜索框中值
165
- getItemInputValue(_ref4) {
189
+ getItemInputValue(_ref5) {
166
190
  let {
167
191
  item
168
- } = _ref4;
192
+ } = _ref5;
193
+
194
+ if (item.type === 'more-result') {
195
+ return query;
196
+ }
197
+
169
198
  return item.title;
170
199
  },
171
200
 
172
- onSelect(_ref5) {
201
+ // 选中或者点击自动完成列表中的 item 时触发
202
+ onSelect(_ref6) {
173
203
  let {
174
204
  item
175
- } = _ref5;
176
- onSelect({
205
+ } = _ref6;
206
+
207
+ if (item.type === 'more-result') {
208
+ return handleKeyword(query);
209
+ }
210
+
211
+ return onSelect({
177
212
  blocklet: item,
178
213
  detailUrl: (0, _urlJoin.default)(endpoint, "/blocklets/".concat(item.did)),
179
214
  storeUrl: endpoint
@@ -181,22 +216,28 @@ function Autocomplete(_ref) {
181
216
  },
182
217
 
183
218
  templates: {
184
- // eslint-disable-next-line react/no-unstable-nested-components
185
- item(_ref6) {
219
+ item(_ref7) {
186
220
  let {
187
221
  item
188
- } = _ref6;
222
+ } = _ref7;
189
223
  const logoUrl = item.logo ? (0, _urlJoin.default)(endpoint, 'assets', item.did, item.logo) : null;
224
+
225
+ if (item.type === 'more-result') {
226
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
227
+ children: t('autocomplete.expandResult', {
228
+ name: query,
229
+ number: item.total.toLocaleString()
230
+ })
231
+ });
232
+ }
233
+
190
234
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_styles.ThemeProvider, {
191
235
  theme: muiTheme,
192
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_react2.ThemeProvider, {
193
- theme: muiTheme,
194
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_item.default, {
195
- item: item,
196
- did: item.did,
197
- description: item.description,
198
- cover: logoUrl
199
- })
236
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_item.default, {
237
+ item: item,
238
+ did: item.did,
239
+ description: item.description,
240
+ cover: logoUrl
200
241
  })
201
242
  });
202
243
  },
@@ -213,7 +254,7 @@ function Autocomplete(_ref) {
213
254
  return () => {
214
255
  search.destroy();
215
256
  };
216
- }, [endpoint, filters, getResults, muiTheme, onSubmit, onSelect, t, onReset]);
257
+ }, [endpoint, filters, muiTheme, onSubmit, onSelect, t, onReset, onStateChange, handleKeyword, getBlocklets]);
217
258
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
218
259
  className: "bl-search-container",
219
260
  ref: containerRef
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = Blocklet;
7
7
 
8
- var _styled = _interopRequireDefault(require("@emotion/styled"));
8
+ var _Theme = require("@arcblock/ux/lib/Theme");
9
9
 
10
10
  var _propTypes = _interopRequireDefault(require("prop-types"));
11
11
 
@@ -35,7 +35,7 @@ function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) r
35
35
 
36
36
  function _taggedTemplateLiteral(strings, raw) { if (!raw) { raw = strings.slice(0); } return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
37
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]);
38
+ const Div = (0, _Theme.styled)('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 color: ", ";\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], props => props.theme.palette.primary.main);
39
39
 
40
40
  function Blocklet(_ref) {
41
41
  let {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocklet/list",
3
- "version": "0.10.19",
3
+ "version": "0.10.21",
4
4
  "description": "Common ux components of blocklet",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -42,7 +42,7 @@
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.40",
45
+ "@arcblock/ux": "^2.4.47",
46
46
  "@emotion/react": "^11.10.0",
47
47
  "@emotion/styled": "^11.10.0",
48
48
  "@mui/icons-material": "^5.8.4",
@@ -71,5 +71,5 @@
71
71
  "eslint": "^8.22.0",
72
72
  "prettier": "^2.7.1"
73
73
  },
74
- "gitHead": "813a039894ea2d1b8e1f4897c9f252b85df99091"
74
+ "gitHead": "45ee2abcf83965c9175e14e8eb701a4fdd6a5f57"
75
75
  }
@@ -31,6 +31,9 @@ const en = {
31
31
  noCategoryResults1: 'No "',
32
32
  noCategoryResults2: '" Blocklets',
33
33
  },
34
+ autocomplete: {
35
+ expandResult: 'Show {number} search results for "{name}" ',
36
+ },
34
37
  };
35
38
 
36
39
  const zh = {
@@ -64,6 +67,9 @@ const zh = {
64
67
  noCategoryResults1: '无 "',
65
68
  noCategoryResults2: '" 类别的 Blocklets',
66
69
  },
70
+ autocomplete: {
71
+ expandResult: '显示 {number} 条 “{name}” 的搜索结果 ',
72
+ },
67
73
  };
68
74
 
69
75
  export default {
@@ -4,7 +4,6 @@ import { createRoot } from 'react-dom/client';
4
4
  import { autocomplete } from '@algolia/autocomplete-js';
5
5
  import { useHotkeys } from 'react-hotkeys-hook';
6
6
 
7
- import { ThemeProvider as EmotionThemeProvider } from '@emotion/react';
8
7
  import { ThemeProvider as MuiThemeProvider, useTheme } from '@mui/material/styles';
9
8
  import joinUrl from 'url-join';
10
9
 
@@ -20,18 +19,25 @@ export default function Autocomplete({ onSelect }) {
20
19
  const { storeApi, filters, endpoint, handleKeyword, t } = useFilterContext();
21
20
  const muiTheme = useTheme();
22
21
 
23
- const getResults = useCallback(
22
+ const getBlocklets = useCallback(
24
23
  async (params) => {
25
24
  const { data } = await storeApi.get(constant.blockletsPath, { params });
26
- return data.dataList || [];
25
+ const blocklets = data.dataList || [];
26
+ // 头部插入的一条 item 用于展示 `点击展开 xx条 结果`,如果没有blocklet 返回,不展示
27
+ if (blocklets.length > 0) {
28
+ blocklets.unshift({ type: 'more-result', total: data.total || 0 });
29
+ }
30
+ return blocklets;
27
31
  },
28
32
  [storeApi]
29
33
  );
30
34
 
31
- const onSubmit = useCallback((e) => {
32
- handleKeyword(e.state.query);
33
- // eslint-disable-next-line react-hooks/exhaustive-deps
34
- }, []);
35
+ const onSubmit = useCallback(
36
+ (e) => {
37
+ handleKeyword(e.state.query);
38
+ },
39
+ [handleKeyword]
40
+ );
35
41
 
36
42
  const setFocus = () => {
37
43
  if (containerRef.current) {
@@ -46,12 +52,22 @@ export default function Autocomplete({ onSelect }) {
46
52
  };
47
53
 
48
54
  const onReset = useCallback((autocompleteState) => {
49
- handleKeyword();
50
- setFocus();
51
55
  autocompleteState.setIsOpen(false);
52
- // eslint-disable-next-line react-hooks/exhaustive-deps
56
+ setFocus();
53
57
  }, []);
54
58
 
59
+ const onStateChange = useCallback(
60
+ ({ prevState, state }) => {
61
+ // eslint-disable-next-line no-console
62
+ if (prevState.query !== state.query) {
63
+ if (!state.query) {
64
+ handleKeyword();
65
+ }
66
+ }
67
+ },
68
+ [handleKeyword]
69
+ );
70
+
55
71
  useHotkeys(
56
72
  '/, ctrl + k, command + k',
57
73
  (e) => {
@@ -85,7 +101,7 @@ export default function Autocomplete({ onSelect }) {
85
101
 
86
102
  panelRootRef.current.render(children);
87
103
  },
88
- autoFocus: true,
104
+ autoFocus: false,
89
105
  classNames: {
90
106
  panel: 'bl-autocomplete-panel',
91
107
  label: 'bl-autocomplete-label',
@@ -97,6 +113,9 @@ export default function Autocomplete({ onSelect }) {
97
113
  initialState: {
98
114
  query: filters.keyword,
99
115
  },
116
+ onStateChange(autocompleteState) {
117
+ onStateChange(autocompleteState);
118
+ },
100
119
  onSubmit,
101
120
  onReset(autocompleteState) {
102
121
  onReset(autocompleteState);
@@ -113,24 +132,37 @@ export default function Autocomplete({ onSelect }) {
113
132
  {
114
133
  sourceId: 'blocklets',
115
134
  getItems() {
116
- return getResults(params);
135
+ return getBlocklets(params);
117
136
  },
118
137
  // 选中后填充 搜索框中值
119
138
  getItemInputValue({ item }) {
139
+ if (item.type === 'more-result') {
140
+ return query;
141
+ }
120
142
  return item.title;
121
143
  },
144
+ // 选中或者点击自动完成列表中的 item 时触发
122
145
  onSelect({ item }) {
123
- onSelect({ blocklet: item, detailUrl: joinUrl(endpoint, `/blocklets/${item.did}`), storeUrl: endpoint });
146
+ if (item.type === 'more-result') {
147
+ return handleKeyword(query);
148
+ }
149
+ return onSelect({
150
+ blocklet: item,
151
+ detailUrl: joinUrl(endpoint, `/blocklets/${item.did}`),
152
+ storeUrl: endpoint,
153
+ });
124
154
  },
125
155
  templates: {
126
- // eslint-disable-next-line react/no-unstable-nested-components
127
156
  item({ item }) {
128
157
  const logoUrl = item.logo ? joinUrl(endpoint, 'assets', item.did, item.logo) : null;
158
+ if (item.type === 'more-result') {
159
+ return (
160
+ <div>{t('autocomplete.expandResult', { name: query, number: item.total.toLocaleString() })}</div>
161
+ );
162
+ }
129
163
  return (
130
164
  <MuiThemeProvider theme={muiTheme}>
131
- <EmotionThemeProvider theme={muiTheme}>
132
- <Blocklet item={item} did={item.did} description={item.description} cover={logoUrl} />
133
- </EmotionThemeProvider>
165
+ <Blocklet item={item} did={item.did} description={item.description} cover={logoUrl} />
134
166
  </MuiThemeProvider>
135
167
  );
136
168
  },
@@ -146,7 +178,7 @@ export default function Autocomplete({ onSelect }) {
146
178
  return () => {
147
179
  search.destroy();
148
180
  };
149
- }, [endpoint, filters, getResults, muiTheme, onSubmit, onSelect, t, onReset]);
181
+ }, [endpoint, filters, muiTheme, onSubmit, onSelect, t, onReset, onStateChange, handleKeyword, getBlocklets]);
150
182
 
151
183
  return <div className="bl-search-container" ref={containerRef} />;
152
184
  }
@@ -1,10 +1,10 @@
1
- import styled from '@emotion/styled';
1
+ import { styled } from '@arcblock/ux/lib/Theme';
2
2
  import PropTypes from 'prop-types';
3
3
  import Typography from '@mui/material/Typography';
4
4
  import Img from '@arcblock/ux/lib/Img';
5
5
  import Avatar from '@arcblock/did-connect/lib/Avatar';
6
6
 
7
- const Div = styled.div`
7
+ const Div = styled('div')`
8
8
  &.arcblock-blocklet {
9
9
  padding: ${(props) => props.theme.spacing(2)} ${(props) => props.theme.spacing(2)} 0
10
10
  ${(props) => props.theme.spacing(2)};
@@ -56,7 +56,7 @@ const Div = styled.div`
56
56
  word-break: break-word;
57
57
  }
58
58
  .ms-highlight {
59
- background-color: yellow;
59
+ color: ${(props) => props.theme.palette.primary.main};
60
60
  }
61
61
  `;
62
62
 
package/src/libs/utils.js CHANGED
@@ -117,7 +117,6 @@ function debouncePromise(fn, time) {
117
117
  if (timerId) {
118
118
  clearTimeout(timerId);
119
119
  }
120
-
121
120
  return new Promise((resolve) => {
122
121
  timerId = setTimeout(() => resolve(fn(...args)), time);
123
122
  });