@blocklet/list 0.8.43 → 0.8.46

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.
@@ -15,21 +15,15 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
15
15
 
16
16
  var _material = require("@mui/material");
17
17
 
18
- var _Check = _interopRequireDefault(require("@mui/icons-material/Check"));
19
-
20
18
  var _KeyboardArrowDown = _interopRequireDefault(require("@mui/icons-material/KeyboardArrowDown"));
21
19
 
22
- var _cloneDeep = _interopRequireDefault(require("lodash/cloneDeep"));
23
-
24
20
  var _isEmpty = _interopRequireDefault(require("lodash/isEmpty"));
25
21
 
26
- var _isEqual = _interopRequireDefault(require("lodash/isEqual"));
27
-
28
22
  var _button = _interopRequireDefault(require("./button"));
29
23
 
30
24
  var _jsxRuntime = require("react/jsx-runtime");
31
25
 
32
- const _excluded = ["title", "value", "icon", "prepend", "options", "multiple", "onClose", "onShow", "onChange", "onInput", "itemRender"];
26
+ const _excluded = ["title", "value", "icon", "prepend", "options", "onChange", "itemRender"];
33
27
 
34
28
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
35
29
 
@@ -50,62 +44,37 @@ function CustomSelect(_ref) {
50
44
  icon,
51
45
  prepend,
52
46
  options,
53
- multiple,
54
- onClose,
55
- onShow,
56
47
  onChange,
57
- onInput,
58
48
  itemRender
59
49
  } = _ref,
60
50
  buttonProps = _objectWithoutProperties(_ref, _excluded);
61
51
 
62
52
  const anchorRef = (0, _react.useRef)(null);
63
53
  const theme = (0, _useTheme.default)();
64
- const [open, setOpen] = (0, _react.useState)(false); // eslint-disable-next-line no-nested-ternary
65
-
66
- const [currentValue, setCurrentValue] = (0, _react.useState)(value !== null ? value : multiple ? [] : '');
54
+ const [open, setOpen] = (0, _react.useState)(false);
55
+ const [currentValue, setCurrentValue] = (0, _react.useState)(value !== null ? value : '');
67
56
  const isSm = (0, _material.useMediaQuery)(theme.breakpoints.down('sm'));
68
57
  (0, _react.useEffect)(() => {
69
- // eslint-disable-next-line no-nested-ternary
70
- setCurrentValue(value !== null ? value : multiple ? [] : '');
58
+ setCurrentValue(value !== null ? value : '');
71
59
  }, [value]);
72
-
73
- function closeMenu() {
74
- (0, _isEqual.default)(value, currentValue) || onInput(currentValue);
75
- onClose();
60
+ const closeMenu = (0, _react.useCallback)(() => {
76
61
  setOpen(false);
77
- }
78
-
79
- function openMenu() {
62
+ }, []);
63
+ const openMenu = (0, _react.useCallback)(() => {
80
64
  setOpen(true);
81
- onShow();
82
- }
65
+ }, []);
83
66
 
84
67
  function toggle(option) {
85
- if (multiple) {
86
- const copyValue = (0, _cloneDeep.default)(currentValue);
87
- const index = copyValue.indexOf(option.value);
88
-
89
- if (index >= 0) {
90
- copyValue.splice(index, 1);
91
- } else {
92
- copyValue.push(option.value);
93
- }
68
+ setCurrentValue(option.value);
69
+ onChange(option.value);
94
70
 
95
- setCurrentValue(copyValue);
96
- onChange(copyValue);
97
- } else {
98
- setCurrentValue(option.value);
99
- onChange(option.value);
100
-
101
- if (isSm) {
102
- closeMenu();
103
- }
71
+ if (isSm) {
72
+ closeMenu();
104
73
  }
105
74
  }
106
75
 
107
76
  function containsValue(optionValue) {
108
- return multiple ? currentValue.includes(optionValue) : optionValue === currentValue;
77
+ return optionValue === currentValue;
109
78
  }
110
79
 
111
80
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
@@ -119,7 +88,7 @@ function CustomSelect(_ref) {
119
88
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
120
89
  className: "my-select__icon",
121
90
  children: icon
122
- }), title, multiple && currentValue.length > 1 && " (".concat(currentValue.length, ")"), /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.SvgIcon, {
91
+ }), title, /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.SvgIcon, {
123
92
  className: "my-select__arrowdown",
124
93
  component: _KeyboardArrowDown.default,
125
94
  fontSize: "small"
@@ -152,13 +121,10 @@ function CustomSelect(_ref) {
152
121
  return itemRender(option);
153
122
  }
154
123
 
155
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.MenuItem, {
124
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.MenuItem, {
156
125
  onClick: () => toggle(option),
157
126
  className: ['my-select__option', containsValue(option.value) ? 'my-select__option--active' : ''].join(' '),
158
- children: [multiple && /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.SvgIcon, {
159
- component: _Check.default,
160
- className: ['my-select__option__icon', containsValue(option.value) ? 'my-select__option__icon--active' : ''].join(' ')
161
- }), option.name]
127
+ children: option.name
162
128
  }, option.value);
163
129
  })]
164
130
  })
@@ -172,11 +138,7 @@ function CustomSelect(_ref) {
172
138
 
173
139
  CustomSelect.propTypes = {
174
140
  options: _propTypes.default.array.isRequired,
175
- multiple: _propTypes.default.bool,
176
141
  value: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number, _propTypes.default.array]),
177
- onShow: _propTypes.default.func,
178
- onClose: _propTypes.default.func,
179
- onInput: _propTypes.default.func,
180
142
  onChange: _propTypes.default.func,
181
143
  itemRender: _propTypes.default.func,
182
144
  title: _propTypes.default.string.isRequired,
@@ -184,14 +146,10 @@ CustomSelect.propTypes = {
184
146
  prepend: _propTypes.default.any
185
147
  };
186
148
  CustomSelect.defaultProps = {
187
- multiple: false,
188
149
  value: null,
189
150
  icon: null,
190
151
  prepend: null,
191
152
  itemRender: null,
192
- onShow: () => {},
193
- onClose: () => {},
194
- onInput: () => {},
195
153
  onChange: () => {}
196
154
  };
197
155
  const StyledButton = (0, _styledComponents.default)(_button.default).withConfig({
@@ -99,7 +99,8 @@ function FilterProvider(_ref) {
99
99
  currentPage: 1,
100
100
  pageSize: (0, _utils.isMobileScreen)() ? 10 : 18,
101
101
  defaultCurrentPage: 1
102
- });
102
+ }); // TODO: 这里如果用 useMemo 包裹,滚动分页会异常
103
+ // eslint-disable-next-line react-hooks/exhaustive-deps
103
104
 
104
105
  const finalFilters = _objectSpread({
105
106
  sortBy: 'popularity',
@@ -113,7 +114,7 @@ function FilterProvider(_ref) {
113
114
  return !hasDeveloperFilter ? {
114
115
  data: allCategories
115
116
  } : (0, _utils.getCategoriesByAuthor)(allBlocklets, finalFilters.developer);
116
- }, [hasDeveloperFilter, allCategories, allBlocklets]);
117
+ }, [hasDeveloperFilter, allCategories, allBlocklets, finalFilters.developer]);
117
118
  const blockletList = (0, _react.useMemo)(() => {
118
119
  var _finalFilters$keyword;
119
120
 
@@ -158,7 +159,7 @@ function FilterProvider(_ref) {
158
159
  blocklets = extraFilter(blocklets); // 排序
159
160
 
160
161
  return (0, _orderBy.default)(blocklets, [sortMap[finalFilters.sortBy]], [finalFilters.sortDirection]);
161
- }, [allBlocklets, finalFilters]);
162
+ }, [allBlocklets, finalFilters, selectedCategory, extraFilter]);
162
163
  const finalBlockletList = (0, _react.useMemo)(() => {
163
164
  // 前端分页 currentPage 当前页数 pageSize 每页条数
164
165
  return blockletList.slice((paginateState.defaultCurrentPage - 1) * paginateState.pageSize, paginateState.currentPage * paginateState.pageSize);
@@ -281,11 +282,12 @@ function FilterProvider(_ref) {
281
282
  (0, _react.useEffect)(() => {
282
283
  if (!hasDeveloperFilter) {
283
284
  fetchCategories();
284
- }
285
+ } // eslint-disable-next-line react-hooks/exhaustive-deps
286
+
285
287
  }, [hasDeveloperFilter]);
286
288
  (0, _react.useEffect)(() => {
287
289
  fetchBlocklets();
288
- fetchCategories();
290
+ fetchCategories(); // eslint-disable-next-line react-hooks/exhaustive-deps
289
291
  }, [endpoint]);
290
292
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(Provider, {
291
293
  value: filterStore,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocklet/list",
3
- "version": "0.8.43",
3
+ "version": "0.8.46",
4
4
  "description": "Common ux components of blocklet",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -38,7 +38,7 @@
38
38
  "react": ">=18.1.0"
39
39
  },
40
40
  "dependencies": {
41
- "@arcblock/ux": "^2.1.37",
41
+ "@arcblock/ux": "^2.1.38",
42
42
  "@emotion/react": "^11.9.0",
43
43
  "@emotion/styled": "^11.8.1",
44
44
  "@mui/icons-material": "^5.6.2",
@@ -64,5 +64,5 @@
64
64
  "eslint": "^8.16.0",
65
65
  "prettier": "^2.6.2"
66
66
  },
67
- "gitHead": "092de42814fb2c3930edba71145f4e7a634e8cd0"
67
+ "gitHead": "caf5f978210ea33249edd11182d5b1898ac2b732"
68
68
  }
@@ -1,74 +1,41 @@
1
1
  /* eslint-disable no-unused-expressions */
2
- import { useEffect, useRef, useState } from 'react';
2
+ import { useCallback, useEffect, useRef, useState } from 'react';
3
3
  import useTheme from '@mui/styles/useTheme';
4
4
  import styled from 'styled-components';
5
5
  import PropTypes from 'prop-types';
6
6
  import { ClickAwayListener, Grow, MenuItem, MenuList, Paper, Popper, SvgIcon, useMediaQuery } from '@mui/material';
7
- import CheckIcon from '@mui/icons-material/Check';
8
7
  import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
9
- import cloneDeep from 'lodash/cloneDeep';
10
8
  import isEmpty from 'lodash/isEmpty';
11
- import isEqual from 'lodash/isEqual';
12
9
 
13
10
  import Button from './button';
14
11
 
15
- function CustomSelect({
16
- title,
17
- value,
18
- icon,
19
- prepend,
20
- options,
21
- multiple,
22
- onClose,
23
- onShow,
24
- onChange,
25
- onInput,
26
- itemRender,
27
- ...buttonProps
28
- }) {
12
+ function CustomSelect({ title, value, icon, prepend, options, onChange, itemRender, ...buttonProps }) {
29
13
  const anchorRef = useRef(null);
30
14
  const theme = useTheme();
31
15
  const [open, setOpen] = useState(false);
32
- // eslint-disable-next-line no-nested-ternary
33
- const [currentValue, setCurrentValue] = useState(value !== null ? value : multiple ? [] : '');
16
+ const [currentValue, setCurrentValue] = useState(value !== null ? value : '');
34
17
  const isSm = useMediaQuery(theme.breakpoints.down('sm'));
35
18
 
36
19
  useEffect(() => {
37
- // eslint-disable-next-line no-nested-ternary
38
- setCurrentValue(value !== null ? value : multiple ? [] : '');
20
+ setCurrentValue(value !== null ? value : '');
39
21
  }, [value]);
40
22
 
41
- function closeMenu() {
42
- isEqual(value, currentValue) || onInput(currentValue);
43
- onClose();
23
+ const closeMenu = useCallback(() => {
44
24
  setOpen(false);
45
- }
46
- function openMenu() {
25
+ }, []);
26
+ const openMenu = useCallback(() => {
47
27
  setOpen(true);
48
- onShow();
49
- }
28
+ }, []);
50
29
 
51
30
  function toggle(option) {
52
- if (multiple) {
53
- const copyValue = cloneDeep(currentValue);
54
- const index = copyValue.indexOf(option.value);
55
- if (index >= 0) {
56
- copyValue.splice(index, 1);
57
- } else {
58
- copyValue.push(option.value);
59
- }
60
- setCurrentValue(copyValue);
61
- onChange(copyValue);
62
- } else {
63
- setCurrentValue(option.value);
64
- onChange(option.value);
65
- if (isSm) {
66
- closeMenu();
67
- }
31
+ setCurrentValue(option.value);
32
+ onChange(option.value);
33
+ if (isSm) {
34
+ closeMenu();
68
35
  }
69
36
  }
70
37
  function containsValue(optionValue) {
71
- return multiple ? currentValue.includes(optionValue) : optionValue === currentValue;
38
+ return optionValue === currentValue;
72
39
  }
73
40
 
74
41
  return (
@@ -82,7 +49,6 @@ function CustomSelect({
82
49
  {...buttonProps}>
83
50
  <div className="my-select__icon">{icon}</div>
84
51
  {title}
85
- {multiple && currentValue.length > 1 && ` (${currentValue.length})`}
86
52
  <SvgIcon className="my-select__arrowdown" component={KeyboardArrowDownIcon} fontSize="small" />
87
53
  </StyledButton>
88
54
  <Popper open={open} anchorEl={anchorRef.current} transition style={{ zIndex: '9999' }}>
@@ -106,15 +72,6 @@ function CustomSelect({
106
72
  'my-select__option',
107
73
  containsValue(option.value) ? 'my-select__option--active' : '',
108
74
  ].join(' ')}>
109
- {multiple && (
110
- <SvgIcon
111
- component={CheckIcon}
112
- className={[
113
- 'my-select__option__icon',
114
- containsValue(option.value) ? 'my-select__option__icon--active' : '',
115
- ].join(' ')}
116
- />
117
- )}
118
75
  {option.name}
119
76
  </MenuItem>
120
77
  );
@@ -131,11 +88,7 @@ function CustomSelect({
131
88
 
132
89
  CustomSelect.propTypes = {
133
90
  options: PropTypes.array.isRequired,
134
- multiple: PropTypes.bool,
135
91
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.array]),
136
- onShow: PropTypes.func,
137
- onClose: PropTypes.func,
138
- onInput: PropTypes.func,
139
92
  onChange: PropTypes.func,
140
93
  itemRender: PropTypes.func,
141
94
  title: PropTypes.string.isRequired,
@@ -143,14 +96,10 @@ CustomSelect.propTypes = {
143
96
  prepend: PropTypes.any,
144
97
  };
145
98
  CustomSelect.defaultProps = {
146
- multiple: false,
147
99
  value: null,
148
100
  icon: null,
149
101
  prepend: null,
150
102
  itemRender: null,
151
- onShow: () => {},
152
- onClose: () => {},
153
- onInput: () => {},
154
103
  onChange: () => {},
155
104
  };
156
105
 
@@ -55,13 +55,16 @@ function FilterProvider({ filters, children, endpoint, locale, blockletRender, o
55
55
  );
56
56
 
57
57
  const paginateState = useReactive({ currentPage: 1, pageSize: isMobileScreen() ? 10 : 18, defaultCurrentPage: 1 });
58
+ // TODO: 这里如果用 useMemo 包裹,滚动分页会异常
59
+ // eslint-disable-next-line react-hooks/exhaustive-deps
58
60
  const finalFilters = { sortBy: 'popularity', sortDirection: 'desc', ...filters };
61
+
59
62
  const selectedCategory = finalFilters.category;
60
63
  const hasDeveloperFilter = !!finalFilters.developer;
61
64
  const categoryState = useMemo(() => {
62
65
  // 当按作者过滤时,需要从所有blocklets中找出属于作者的分类
63
66
  return !hasDeveloperFilter ? { data: allCategories } : getCategoriesByAuthor(allBlocklets, finalFilters.developer);
64
- }, [hasDeveloperFilter, allCategories, allBlocklets]);
67
+ }, [hasDeveloperFilter, allCategories, allBlocklets, finalFilters.developer]);
65
68
 
66
69
  const blockletList = useMemo(() => {
67
70
  const sortByName = (x) => x?.title?.toLocaleLowerCase() || x?.name?.toLocaleLowerCase(); // 按名称排序
@@ -95,7 +98,7 @@ function FilterProvider({ filters, children, endpoint, locale, blockletRender, o
95
98
  blocklets = extraFilter(blocklets);
96
99
  // 排序
97
100
  return orderBy(blocklets, [sortMap[finalFilters.sortBy]], [finalFilters.sortDirection]);
98
- }, [allBlocklets, finalFilters]);
101
+ }, [allBlocklets, finalFilters, selectedCategory, extraFilter]);
99
102
 
100
103
  const finalBlockletList = useMemo(() => {
101
104
  // 前端分页 currentPage 当前页数 pageSize 每页条数
@@ -197,11 +200,13 @@ function FilterProvider({ filters, children, endpoint, locale, blockletRender, o
197
200
  if (!hasDeveloperFilter) {
198
201
  fetchCategories();
199
202
  }
203
+ // eslint-disable-next-line react-hooks/exhaustive-deps
200
204
  }, [hasDeveloperFilter]);
201
205
 
202
206
  useEffect(() => {
203
207
  fetchBlocklets();
204
208
  fetchCategories();
209
+ // eslint-disable-next-line react-hooks/exhaustive-deps
205
210
  }, [endpoint]);
206
211
 
207
212
  return <Provider value={filterStore}>{children}</Provider>;