@hi-ui/menu 4.3.2 → 5.0.0-alpha.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,82 @@
1
1
  # @hi-ui/menu
2
2
 
3
+ ## 5.0.0-alpha.0
4
+
5
+ ### Major Changes
6
+
7
+ - 1b05b44a4: feat: 组件的 package.json 中的 exports 统一加上 types 配置 (5.0)
8
+
9
+ ### Minor Changes
10
+
11
+ - a1ad318d9: feat(menu): 增加 GroupMenu 和 SideMenu 组件 (5.0)
12
+ - d9b2b928c: feat(menu): GroupMenu 组件增加 titleRender 参数 (5.0)
13
+ - 2fec303ab: feat(menu): add showTitleOnMini api (5.0)
14
+ - 0d2737b09: chore(menu): 增加变更记录文件 (5.0)
15
+
16
+ ### Patch Changes
17
+
18
+ - 5de7a848b: chore: 将代码中 v4 改为 v5 (5.0)
19
+ - 307f68517: <br />
20
+ - perf(layout): 优化导航菜单交互体验 (5.0)
21
+ - perf(menu): 优化搜索菜单组件的样式和交互逻辑 & 修改分组菜单样式问题 (5.0)
22
+ - 8116f0304: fix: 修改 UI 问题 (5.0)
23
+ - 46dbd140f: style(layout): 修改 Sider 收起时宽度为 60px & 增加 width 参数 (5.0)
24
+ - 300d1573a: perf(layout&menu): 优化 FloatMenuContainer 组件的折叠逻辑 & 修改 SideMenu 组件 hover 样式 (5.0)
25
+ - 7f8760993: style(menu): 优化 GroupMenu 组件的样式和交互逻辑 (5.0)
26
+ - 61d132802: build: 将 package.json 中 exports 配置中的 types 配置放在最上面 (5.0)
27
+ - Updated dependencies [abebb5eed]
28
+ - Updated dependencies [7bda04e64]
29
+ - Updated dependencies [77ed66eac]
30
+ - Updated dependencies [ddd2acc79]
31
+ - Updated dependencies [5de7a848b]
32
+ - Updated dependencies [1b05b44a4]
33
+ - Updated dependencies [0cd15438e]
34
+ - Updated dependencies [eb69f0baa]
35
+ - Updated dependencies [a01771e8d]
36
+ - Updated dependencies [09451c7d9]
37
+ - Updated dependencies [67960d871]
38
+ - Updated dependencies [43da85a56]
39
+ - Updated dependencies [de7f92b26]
40
+ - Updated dependencies [8116f0304]
41
+ - Updated dependencies [85bb84874]
42
+ - Updated dependencies [5de7a848b]
43
+ - Updated dependencies [77ed66eac]
44
+ - Updated dependencies [632dbda3a]
45
+ - Updated dependencies [36bb992d3]
46
+ - Updated dependencies [1b51c1bbe]
47
+ - Updated dependencies [61d132802]
48
+ - Updated dependencies [6ebf40f96]
49
+ - Updated dependencies [9f2ee08cf]
50
+ - Updated dependencies [6eac4b78b]
51
+ - Updated dependencies [bcd3d08dd]
52
+ - Updated dependencies [4fb586f6f]
53
+ - Updated dependencies [c125e4c48]
54
+ - Updated dependencies [b7ad460d8]
55
+ - Updated dependencies [df25ec39b]
56
+ - @hi-ui/picker@5.0.0-alpha.0
57
+ - @hi-ui/input@5.0.0-alpha.0
58
+ - @hi-ui/tooltip@5.0.0-alpha.0
59
+ - @hi-ui/core@5.0.0-alpha.0
60
+ - @hi-ui/use-id@5.0.0-alpha.0
61
+ - @hi-ui/use-latest@5.0.0-alpha.0
62
+ - @hi-ui/use-merge-refs@5.0.0-alpha.0
63
+ - @hi-ui/use-outside-click@5.0.0-alpha.0
64
+ - @hi-ui/use-resize-observer@5.0.0-alpha.0
65
+ - @hi-ui/use-toggle@5.0.0-alpha.0
66
+ - @hi-ui/use-uncontrolled-state@5.0.0-alpha.0
67
+ - @hi-ui/icons@5.0.0-alpha.0
68
+ - @hi-ui/ellipsis-tooltip@5.0.0-alpha.0
69
+ - @hi-ui/highlighter@5.0.0-alpha.0
70
+ - @hi-ui/icon-button@5.0.0-alpha.0
71
+ - @hi-ui/popper@5.0.0-alpha.0
72
+ - @hi-ui/scrollbar@5.0.0-alpha.0
73
+ - @hi-ui/array-utils@5.0.0-alpha.0
74
+ - @hi-ui/classname@5.0.0-alpha.0
75
+ - @hi-ui/env@5.0.0-alpha.0
76
+ - @hi-ui/times@5.0.0-alpha.0
77
+ - @hi-ui/tree-utils@5.0.0-alpha.0
78
+ - @hi-ui/type-assertion@5.0.0-alpha.0
79
+
3
80
  ## 4.3.2
4
81
 
5
82
  ### Patch Changes
@@ -0,0 +1,44 @@
1
+ /** @LICENSE
2
+ * @hi-ui/menu
3
+ * https://github.com/XiaoMi/hiui/tree/master/packages/ui/menu#readme
4
+ *
5
+ * Copyright (c) HiUI <mi-hiui@xiaomi.com>.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */
10
+ 'use strict';
11
+
12
+ var _typeof = require("@babel/runtime/helpers/typeof");
13
+ Object.defineProperty(exports, '__esModule', {
14
+ value: true
15
+ });
16
+ var React = require('react');
17
+ function _interopDefaultCompat(e) {
18
+ return e && _typeof(e) === 'object' && 'default' in e ? e : {
19
+ 'default': e
20
+ };
21
+ }
22
+ var React__default = /*#__PURE__*/_interopDefaultCompat(React);
23
+ var EnterIcon = function EnterIcon() {
24
+ return /*#__PURE__*/React__default["default"].createElement("svg", {
25
+ width: "12",
26
+ height: "12",
27
+ viewBox: "0 0 12 12",
28
+ fill: "none",
29
+ xmlns: "http://www.w3.org/2000/svg"
30
+ }, /*#__PURE__*/React__default["default"].createElement("path", {
31
+ d: "M4 9L2 7L4 5",
32
+ stroke: "#91959e",
33
+ strokeWidth: "1.2",
34
+ strokeLinecap: "round",
35
+ strokeLinejoin: "round"
36
+ }), /*#__PURE__*/React__default["default"].createElement("path", {
37
+ d: "M10 3L10 6.25C10 6.66422 9.66423 7 9.25 7L2 7",
38
+ stroke: "#91959e",
39
+ strokeWidth: "1.2",
40
+ strokeLinecap: "round",
41
+ strokeLinejoin: "round"
42
+ }));
43
+ };
44
+ exports.EnterIcon = EnterIcon;
@@ -0,0 +1,96 @@
1
+ /** @LICENSE
2
+ * @hi-ui/menu
3
+ * https://github.com/XiaoMi/hiui/tree/master/packages/ui/menu#readme
4
+ *
5
+ * Copyright (c) HiUI <mi-hiui@xiaomi.com>.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */
10
+ 'use strict';
11
+
12
+ var _typeof = require("@babel/runtime/helpers/typeof");
13
+ Object.defineProperty(exports, '__esModule', {
14
+ value: true
15
+ });
16
+ var tslib = require('tslib');
17
+ var React = require('react');
18
+ var classname = require('@hi-ui/classname');
19
+ var env = require('@hi-ui/env');
20
+ var typeAssertion = require('@hi-ui/type-assertion');
21
+ var useLatest = require('@hi-ui/use-latest');
22
+ var useUncontrolledState = require('@hi-ui/use-uncontrolled-state');
23
+ var Scrollbar = require('@hi-ui/scrollbar');
24
+ function _interopDefaultCompat(e) {
25
+ return e && _typeof(e) === 'object' && 'default' in e ? e : {
26
+ 'default': e
27
+ };
28
+ }
29
+ var React__default = /*#__PURE__*/_interopDefaultCompat(React);
30
+ var Scrollbar__default = /*#__PURE__*/_interopDefaultCompat(Scrollbar);
31
+ var _role = 'group-menu';
32
+ var GROUP_MENU_PREFIX = classname.getPrefixCls(_role);
33
+ /**
34
+ * 分组菜单
35
+ */
36
+ var GroupMenu = /*#__PURE__*/React.forwardRef(function (_a, ref) {
37
+ var _a$prefixCls = _a.prefixCls,
38
+ prefixCls = _a$prefixCls === void 0 ? GROUP_MENU_PREFIX : _a$prefixCls,
39
+ _a$role = _a.role,
40
+ role = _a$role === void 0 ? _role : _a$role,
41
+ className = _a.className,
42
+ _a$data = _a.data,
43
+ data = _a$data === void 0 ? [] : _a$data,
44
+ onClick = _a.onClick,
45
+ _a$defaultActiveId = _a.defaultActiveId,
46
+ defaultActiveId = _a$defaultActiveId === void 0 ? '' : _a$defaultActiveId,
47
+ activeIdProp = _a.activeId,
48
+ titleRender = _a.titleRender,
49
+ rest = tslib.__rest(_a, ["prefixCls", "role", "className", "data", "onClick", "defaultActiveId", "activeId", "titleRender"]);
50
+ var _useUncontrolledState = useUncontrolledState.useUncontrolledState(defaultActiveId, activeIdProp),
51
+ activeId = _useUncontrolledState[0],
52
+ tryChangeActiveId = _useUncontrolledState[1];
53
+ var handleClick = useLatest.useLatestCallback(function (evt, id, item) {
54
+ tryChangeActiveId(id);
55
+ onClick === null || onClick === void 0 ? void 0 : onClick(evt, id, item);
56
+ });
57
+ var renderItem = React.useCallback(function (data) {
58
+ return data.map(function (item) {
59
+ var _cx;
60
+ var id = item.id,
61
+ icon = item.icon,
62
+ title = item.title,
63
+ _item$children = item.children,
64
+ children = _item$children === void 0 ? [] : _item$children,
65
+ disabled = item.disabled;
66
+ var isParent = typeAssertion.isArrayNonEmpty(children);
67
+ return /*#__PURE__*/React__default["default"].createElement("div", {
68
+ key: id,
69
+ className: classname.cx(isParent ? prefixCls + "-parent-item" : prefixCls + "-item", (_cx = {}, _cx[prefixCls + "-item--active"] = activeId === id, _cx[prefixCls + "-item--disabled"] = disabled, _cx[prefixCls + "-item--empty"] = !title && !icon, _cx)),
70
+ onClick: function onClick(evt) {
71
+ if (disabled || isParent) return;
72
+ evt.stopPropagation();
73
+ handleClick(evt, id, item);
74
+ }
75
+ }, /*#__PURE__*/React__default["default"].createElement("div", {
76
+ className: classname.cx(prefixCls + "-item__content")
77
+ }, /*#__PURE__*/React__default["default"].createElement("div", {
78
+ className: classname.cx(prefixCls + "-item__icon")
79
+ }, icon), /*#__PURE__*/React__default["default"].createElement("div", {
80
+ className: classname.cx(prefixCls + "-item__title")
81
+ }, typeof titleRender === 'function' ? titleRender(item) : title)), isParent && renderItem(children));
82
+ });
83
+ }, [activeId, handleClick, prefixCls, titleRender]);
84
+ return /*#__PURE__*/React__default["default"].createElement("div", Object.assign({
85
+ className: classname.cx("" + prefixCls, className),
86
+ ref: ref,
87
+ role: role
88
+ }, rest), /*#__PURE__*/React__default["default"].createElement(Scrollbar__default["default"], {
89
+ onlyScrollVisible: true,
90
+ axes: "y"
91
+ }, renderItem(data)));
92
+ });
93
+ if (env.__DEV__) {
94
+ GroupMenu.displayName = 'GroupMenu';
95
+ }
96
+ exports.GroupMenu = GroupMenu;
package/lib/cjs/Menu.js CHANGED
@@ -83,7 +83,9 @@ var Menu = /*#__PURE__*/React.forwardRef(function (_a, ref) {
83
83
  onClick = _a.onClick,
84
84
  _a$size = _a.size,
85
85
  size = _a$size === void 0 ? 'lg' : _a$size,
86
- rest = tslib.__rest(_a, ["prefixCls", "role", "className", "data", "fieldNames", "placement", "showCollapse", "expandedType", "showAllSubMenus", "defaultExpandAll", "defaultExpandedIds", "expandedIds", "onExpand", "defaultActiveId", "activeId", "onClickSubMenu", "collapsed", "defaultCollapsed", "overlayClassName", "onCollapse", "footerRender", "render", "extraHeader", "onClick", "size"]);
86
+ _a$showTitleOnMini = _a.showTitleOnMini,
87
+ showTitleOnMini = _a$showTitleOnMini === void 0 ? false : _a$showTitleOnMini,
88
+ rest = tslib.__rest(_a, ["prefixCls", "role", "className", "data", "fieldNames", "placement", "showCollapse", "expandedType", "showAllSubMenus", "defaultExpandAll", "defaultExpandedIds", "expandedIds", "onExpand", "defaultActiveId", "activeId", "onClickSubMenu", "collapsed", "defaultCollapsed", "overlayClassName", "onCollapse", "footerRender", "render", "extraHeader", "onClick", "size", "showTitleOnMini"]);
87
89
  var i18n = core.useLocaleContext();
88
90
  var _useUncontrolledState = useUncontrolledState.useUncontrolledState(defaultActiveId, activeIdProp, onClick),
89
91
  activeId = _useUncontrolledState[0],
@@ -106,6 +108,7 @@ var Menu = /*#__PURE__*/React.forwardRef(function (_a, ref) {
106
108
  }, expandedIdsProp, onExpand),
107
109
  expandedIds = _useUncontrolledState2[0],
108
110
  updateExpandedIds = _useUncontrolledState2[1];
111
+ var expandedIdsRef = React.useRef(expandedIds);
109
112
  var clickMenu = React.useCallback(function (id, raw) {
110
113
  updateActiveId(id, raw);
111
114
  }, [updateActiveId]);
@@ -114,14 +117,17 @@ var Menu = /*#__PURE__*/React.forwardRef(function (_a, ref) {
114
117
  return expandedId !== id;
115
118
  }) : expandedIds.concat(id);
116
119
  updateExpandedIds(nextExpandedIds);
120
+ expandedIdsRef.current = nextExpandedIds;
117
121
  if (onClickSubMenu) {
118
122
  onClickSubMenu(id, nextExpandedIds);
119
123
  }
120
124
  }, [onClickSubMenu, expandedIds, updateExpandedIds]);
121
125
  var closePopper = React.useCallback(function (id) {
122
- updateExpandedIds(expandedIds.filter(function (expandedId) {
126
+ var nextExpandedIds = expandedIds.filter(function (expandedId) {
123
127
  return expandedId !== id;
124
- }));
128
+ });
129
+ updateExpandedIds(nextExpandedIds);
130
+ expandedIdsRef.current = nextExpandedIds;
125
131
  }, [expandedIds, updateExpandedIds]);
126
132
  var closeAllPopper = React.useCallback(function () {
127
133
  updateExpandedIds([]);
@@ -154,6 +160,13 @@ var Menu = /*#__PURE__*/React.forwardRef(function (_a, ref) {
154
160
  setContainerWidth(width);
155
161
  }
156
162
  });
163
+ React.useEffect(function () {
164
+ if (mini) {
165
+ updateExpandedIds([]);
166
+ } else {
167
+ updateExpandedIds(expandedIdsRef.current);
168
+ }
169
+ }, [mini, updateExpandedIds]);
157
170
  var _useState4 = React.useState(0),
158
171
  tagMaxCount = _useState4[0],
159
172
  setTagMaxCount = _useState4[1];
@@ -168,7 +181,7 @@ var Menu = /*#__PURE__*/React.forwardRef(function (_a, ref) {
168
181
  }, [transformedData, tagMaxCount]);
169
182
  var getTagWidth = React.useCallback(function (index) {
170
183
  if (!containerElement) return MIN_WIDTH;
171
- var elements = containerElement.getElementsByClassName('hi-v4-menu-item');
184
+ var elements = containerElement.getElementsByClassName('hi-v5-menu-item');
172
185
  var element = elements && elements[index];
173
186
  if (!element) return MIN_WIDTH;
174
187
  return element.getBoundingClientRect().width;
@@ -204,9 +217,7 @@ var Menu = /*#__PURE__*/React.forwardRef(function (_a, ref) {
204
217
  var collapseNode = canToggle ? ( /*#__PURE__*/React__default["default"].createElement("div", {
205
218
  className: classname.cx(prefixCls + "__toggle"),
206
219
  onClick: function onClick() {
207
- miniToggleAction.not();
208
- // 关闭所有展开的子菜单,防止切换到 mini 模式后,子菜单还是展开的
209
- updateExpandedIds([]);
220
+ return miniToggleAction.not();
210
221
  }
211
222
  }, mini ? /*#__PURE__*/React__default["default"].createElement(icons.MenuUnfoldOutlined, null) : /*#__PURE__*/React__default["default"].createElement(icons.MenuFoldOutlined, null))) : null;
212
223
  return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, typeAssertion.isFunction(footerRender) ? footerRender({
@@ -216,12 +227,12 @@ var Menu = /*#__PURE__*/React.forwardRef(function (_a, ref) {
216
227
  };
217
228
  var renderItem = React.useCallback(function (menuItem, level) {
218
229
  // 显示缩略内容
219
- if (showMini && level === 1) {
230
+ if (showMini && level === 1 && !showTitleOnMini) {
220
231
  return renderMenuItemMini(menuItem);
221
232
  }
222
233
  return typeAssertion.isFunction(render) ? render(menuItem, level) : menuItem.title;
223
- }, [render, showMini]);
224
- var cls = classname.cx(prefixCls, className, prefixCls + "--" + placement, prefixCls + "--size-" + size, mini && prefixCls + "--mini", (expandedType === 'pop' || showAllSubMenus || mini) && prefixCls + "--popup");
234
+ }, [render, showMini, showTitleOnMini]);
235
+ var cls = classname.cx(prefixCls, className, prefixCls + "--" + placement, prefixCls + "--size-" + size, mini && prefixCls + "--mini", showTitleOnMini && prefixCls + "--show-title-on-mini", (expandedType === 'pop' || showAllSubMenus || mini) && prefixCls + "--popup");
225
236
  return /*#__PURE__*/React__default["default"].createElement("div", Object.assign({
226
237
  ref: useMergeRefs.useMergeRefs(ref, setContainerElement),
227
238
  role: role,
@@ -232,6 +243,7 @@ var Menu = /*#__PURE__*/React.forwardRef(function (_a, ref) {
232
243
  expandedType: expandedType,
233
244
  showAllSubMenus: showAllSubMenus,
234
245
  mini: mini,
246
+ showTitleOnMini: showTitleOnMini,
235
247
  clickMenu: clickMenu,
236
248
  clickSubMenu: clickSubMenu,
237
249
  closePopper: closePopper,
@@ -69,7 +69,8 @@ var MenuItem = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
69
69
  clickSubMenu = _useContext.clickSubMenu,
70
70
  closeAllPopper = _useContext.closeAllPopper,
71
71
  activeParents = _useContext.activeParents,
72
- overlayClassName = _useContext.overlayClassName;
72
+ overlayClassName = _useContext.overlayClassName,
73
+ showTitleOnMini = _useContext.showTitleOnMini;
73
74
  var _parentIds = (parentIds || []).concat(id);
74
75
  var hasChildren = typeAssertion.isArrayNonEmpty(children);
75
76
  var mergedRef = useMergeRefs.useMergeRefs(itemRef, ref);
@@ -135,7 +136,7 @@ var MenuItem = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
135
136
  visible: !!(expandedIds === null || expandedIds === void 0 ? void 0 : expandedIds.includes(id)),
136
137
  attachEl: itemRef.current,
137
138
  placement: 'right-start',
138
- gutterGap: 16,
139
+ gutterGap: showTitleOnMini ? 8 : 16,
139
140
  className: overlayClassName,
140
141
  onClose: function onClose() {
141
142
  closePopper === null || closePopper === void 0 ? void 0 : closePopper(id);
@@ -155,7 +156,7 @@ var MenuItem = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
155
156
  visible: !!(expandedIds === null || expandedIds === void 0 ? void 0 : expandedIds.includes(id)),
156
157
  attachEl: itemRef.current,
157
158
  placement: 'right-start',
158
- gutterGap: 16,
159
+ gutterGap: showTitleOnMini ? 12 : 16,
159
160
  disabledPortal: true,
160
161
  className: overlayClassName,
161
162
  onClose: function onClose() {
@@ -0,0 +1,322 @@
1
+ /** @LICENSE
2
+ * @hi-ui/menu
3
+ * https://github.com/XiaoMi/hiui/tree/master/packages/ui/menu#readme
4
+ *
5
+ * Copyright (c) HiUI <mi-hiui@xiaomi.com>.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */
10
+ 'use strict';
11
+
12
+ var _typeof = require("@babel/runtime/helpers/typeof");
13
+ Object.defineProperty(exports, '__esModule', {
14
+ value: true
15
+ });
16
+ var tslib = require('tslib');
17
+ var React = require('react');
18
+ var core = require('@hi-ui/core');
19
+ var env = require('@hi-ui/env');
20
+ var classname = require('@hi-ui/classname');
21
+ var icons = require('@hi-ui/icons');
22
+ var IconButton = require('@hi-ui/icon-button');
23
+ require('./button/lib/esm/styles/index.scss.js');
24
+ var Button = require('./button/lib/esm/Button.js');
25
+ require('./button/lib/esm/ButtonGroup.js');
26
+ var Input = require('@hi-ui/input');
27
+ var Highlighter = require('@hi-ui/highlighter');
28
+ var useUncontrolledState = require('@hi-ui/use-uncontrolled-state');
29
+ var useToggle = require('@hi-ui/use-toggle');
30
+ var EllipsisTooltip = require('@hi-ui/ellipsis-tooltip');
31
+ var EnterIcon = require('./EnterIcon.js');
32
+ var util = require('./util.js');
33
+ function _interopDefaultCompat(e) {
34
+ return e && _typeof(e) === 'object' && 'default' in e ? e : {
35
+ 'default': e
36
+ };
37
+ }
38
+ var React__default = /*#__PURE__*/_interopDefaultCompat(React);
39
+ var IconButton__default = /*#__PURE__*/_interopDefaultCompat(IconButton);
40
+ var Input__default = /*#__PURE__*/_interopDefaultCompat(Input);
41
+ var Highlighter__default = /*#__PURE__*/_interopDefaultCompat(Highlighter);
42
+ var EllipsisTooltip__default = /*#__PURE__*/_interopDefaultCompat(EllipsisTooltip);
43
+ var _role = 'menu-search';
44
+ var _prefix = classname.getPrefixCls(_role);
45
+ var MenuSearch = /*#__PURE__*/React.forwardRef(function (_a, ref) {
46
+ var _cx, _cx2;
47
+ var _b, _c;
48
+ var innerRef = _a.innerRef,
49
+ _a$prefixCls = _a.prefixCls,
50
+ prefixCls = _a$prefixCls === void 0 ? _prefix : _a$prefixCls,
51
+ className = _a.className,
52
+ placeholder = _a.placeholder,
53
+ width = _a.width,
54
+ style = _a.style,
55
+ visibleProp = _a.visible,
56
+ data = _a.data,
57
+ _a$defaultValue = _a.defaultValue,
58
+ defaultValue = _a$defaultValue === void 0 ? '' : _a$defaultValue,
59
+ valueProp = _a.value,
60
+ onChange = _a.onChange,
61
+ onSelect = _a.onSelect,
62
+ onClear = _a.onClear,
63
+ onClose = _a.onClose,
64
+ onEsc = _a.onEsc;
65
+ tslib.__rest(_a, ["innerRef", "prefixCls", "className", "clearText", "placeholder", "notFoundContent", "width", "style", "visible", "data", "defaultValue", "value", "onChange", "onSearch", "onSelect", "onClear", "onClose", "onEsc"]);
66
+ var i18n = core.useLocaleContext();
67
+ var _useUncontrolledToggl = useToggle.useUncontrolledToggle({
68
+ visible: visibleProp
69
+ }),
70
+ visible = _useUncontrolledToggl[0],
71
+ visibleAction = _useUncontrolledToggl[1];
72
+ var _useUncontrolledState = useUncontrolledState.useUncontrolledState(defaultValue, valueProp, onChange),
73
+ value = _useUncontrolledState[0],
74
+ tryChangeValue = _useUncontrolledState[1];
75
+ var _useState = React.useState(-1),
76
+ currentIndex = _useState[0],
77
+ setCurrentIndex = _useState[1];
78
+ var listRef = React.useRef(null);
79
+ React.useLayoutEffect(function () {
80
+ if (currentIndex === -1 || !listRef.current) return;
81
+ var listContainer = listRef.current;
82
+ var selectedItem = listContainer.children[currentIndex];
83
+ if (!selectedItem) return;
84
+ var containerScrollTop = listContainer.scrollTop;
85
+ var containerHeight = listContainer.clientHeight;
86
+ var itemTop = selectedItem.offsetTop;
87
+ var itemHeight = selectedItem.offsetHeight;
88
+ // 计算元素的可见范围
89
+ var itemBottom = itemTop + itemHeight;
90
+ var visibleTop = containerScrollTop;
91
+ var visibleBottom = containerScrollTop + containerHeight;
92
+ // 判断是否需要滚动
93
+ var isItemAboveViewport = itemTop < visibleTop;
94
+ var isItemBelowViewport = itemBottom > visibleBottom;
95
+ if (isItemAboveViewport) {
96
+ // 如果元素在可视区域上方,滚动到元素顶部
97
+ listContainer.scrollTop = itemTop;
98
+ } else if (isItemBelowViewport) {
99
+ // 如果元素在可视区域下方,滚动到元素底部刚好可见
100
+ listContainer.scrollTop = itemBottom - containerHeight;
101
+ }
102
+ }, [currentIndex]);
103
+ var resultMemo = React__default["default"].useMemo(function () {
104
+ if (!data || !value) return [];
105
+ // 使用新的搜索算法
106
+ var searchResults = util.searchMenuWithPath(data, value);
107
+ return searchResults.map(function (result) {
108
+ return Object.assign(Object.assign({}, result.node), {
109
+ level: result.level,
110
+ path: result.path,
111
+ // 添加路径信息用于显示
112
+ pathTitles: result.path.map(function (p) {
113
+ var _a;
114
+ return (_a = p.title) === null || _a === void 0 ? void 0 : _a.toString();
115
+ }).filter(Boolean)
116
+ });
117
+ });
118
+ }, [data, value]);
119
+ var handleChange = React.useCallback(function (value) {
120
+ tryChangeValue(value);
121
+ }, [tryChangeValue]);
122
+ var handleSelect = React.useCallback(function (id, item, index) {
123
+ var _a;
124
+ setCurrentIndex(index);
125
+ visibleAction.off();
126
+ // 让列表容器获取焦点,确保键盘导航可用
127
+ (_a = listRef.current) === null || _a === void 0 ? void 0 : _a.focus();
128
+ onSelect === null || onSelect === void 0 ? void 0 : onSelect(id, item);
129
+ }, [onSelect, visibleAction]);
130
+ var handleMove = React.useCallback(function (direction) {
131
+ if (!resultMemo) return;
132
+ setCurrentIndex(function (prev) {
133
+ if (direction === 'up') {
134
+ return prev - 1 < 0 ? (resultMemo === null || resultMemo === void 0 ? void 0 : resultMemo.length) - 1 : prev - 1;
135
+ } else {
136
+ return prev + 1 > (resultMemo === null || resultMemo === void 0 ? void 0 : resultMemo.length) - 1 ? 0 : prev + 1;
137
+ }
138
+ });
139
+ }, [resultMemo]);
140
+ var handleEnter = React.useCallback(function () {
141
+ if (!resultMemo) return;
142
+ if (currentIndex === -1) {
143
+ setCurrentIndex(0);
144
+ }
145
+ visibleAction.off();
146
+ onSelect === null || onSelect === void 0 ? void 0 : onSelect(resultMemo[currentIndex].id, resultMemo[currentIndex]);
147
+ }, [resultMemo, currentIndex, onSelect, visibleAction]);
148
+ var handleClear = React.useCallback(function () {
149
+ tryChangeValue('');
150
+ setCurrentIndex(-1);
151
+ onClear === null || onClear === void 0 ? void 0 : onClear();
152
+ }, [onClear, tryChangeValue]);
153
+ var handleClose = React.useCallback(function () {
154
+ visibleAction.off();
155
+ onClose === null || onClose === void 0 ? void 0 : onClose();
156
+ }, [onClose, visibleAction]);
157
+ var handleEscape = React.useCallback(function () {
158
+ handleClose();
159
+ onEsc === null || onEsc === void 0 ? void 0 : onEsc();
160
+ }, [handleClose, onEsc]);
161
+ var handleKeyDown = React.useCallback(function (e) {
162
+ if (e.key === 'ArrowUp') {
163
+ handleMove('up');
164
+ }
165
+ if (e.key === 'ArrowDown') {
166
+ handleMove('down');
167
+ }
168
+ if (e.key === 'Enter') {
169
+ handleEnter();
170
+ }
171
+ if (e.key === 'Escape') {
172
+ handleEscape();
173
+ }
174
+ }, [handleEnter, handleMove, handleEscape]);
175
+ var _useState2 = React.useState(null),
176
+ inputRef = _useState2[0],
177
+ setInputRef = _useState2[1];
178
+ React.useEffect(function () {
179
+ if (!value || !inputRef) {
180
+ visibleAction.off();
181
+ } else {
182
+ visibleAction.on();
183
+ }
184
+ }, [inputRef, value, visibleAction]);
185
+ React.useImperativeHandle(innerRef, function () {
186
+ return {
187
+ show: function show() {
188
+ visibleAction.on();
189
+ },
190
+ hide: function hide() {
191
+ visibleAction.off();
192
+ },
193
+ focus: function focus() {
194
+ inputRef === null || inputRef === void 0 ? void 0 : inputRef.focus();
195
+ }
196
+ };
197
+ });
198
+ var cls = classname.cx(prefixCls, className, (_cx = {}, _cx[prefixCls + "--open"] = visible, _cx));
199
+ return /*#__PURE__*/React__default["default"].createElement("div", {
200
+ className: cls,
201
+ style: style
202
+ }, /*#__PURE__*/React__default["default"].createElement(MenuSearchInput, {
203
+ width: width,
204
+ prefixCls: prefixCls,
205
+ placeholder: placeholder,
206
+ value: value,
207
+ onChange: handleChange,
208
+ onClear: handleClear,
209
+ onClose: handleClose,
210
+ onKeyDown: handleKeyDown,
211
+ inputRef: setInputRef
212
+ }), /*#__PURE__*/React__default["default"].createElement("div", {
213
+ className: classname.cx(prefixCls + "__content", (_cx2 = {}, _cx2[prefixCls + "__content--visible"] = visible, _cx2))
214
+ }, (resultMemo === null || resultMemo === void 0 ? void 0 : resultMemo.length) > 0 ? ( /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement("div", {
215
+ className: prefixCls + "__header"
216
+ }, /*#__PURE__*/React__default["default"].createElement(Highlighter__default["default"], {
217
+ keyword: String((_b = resultMemo === null || resultMemo === void 0 ? void 0 : resultMemo.length) !== null && _b !== void 0 ? _b : 0)
218
+ }, i18n.get('menuSearch.searchResult', {
219
+ count: (_c = resultMemo === null || resultMemo === void 0 ? void 0 : resultMemo.length) !== null && _c !== void 0 ? _c : 0,
220
+ keyword: value
221
+ }))), /*#__PURE__*/React__default["default"].createElement("div", {
222
+ className: prefixCls + "__list",
223
+ ref: listRef,
224
+ tabIndex: -1,
225
+ onKeyDown: handleKeyDown
226
+ }, resultMemo === null || resultMemo === void 0 ? void 0 : resultMemo.map(function (item, index) {
227
+ var _cx3;
228
+ return /*#__PURE__*/React__default["default"].createElement("div", {
229
+ key: item.id,
230
+ className: classname.cx(prefixCls + "__list-item", (_cx3 = {}, _cx3[prefixCls + "__list-item--selected"] = currentIndex === index, _cx3)),
231
+ onClick: function onClick() {
232
+ return handleSelect(item.id, item, index);
233
+ }
234
+ }, /*#__PURE__*/React__default["default"].createElement("div", {
235
+ className: prefixCls + "__list-item__title"
236
+ }, /*#__PURE__*/React__default["default"].createElement(EllipsisTooltip__default["default"], {
237
+ tooltipProps: {
238
+ style: {
239
+ maxWidth: 320
240
+ }
241
+ }
242
+ }, /*#__PURE__*/React__default["default"].createElement(Highlighter__default["default"], {
243
+ keyword: value
244
+ }, item.pathTitles.join('/')))));
245
+ })))) : ( /*#__PURE__*/React__default["default"].createElement("div", {
246
+ className: prefixCls + "__empty"
247
+ }, /*#__PURE__*/React__default["default"].createElement("div", null, i18n.menuSearch.searchEmptyResult)))), (resultMemo === null || resultMemo === void 0 ? void 0 : resultMemo.length) > 0 && ( /*#__PURE__*/React__default["default"].createElement("div", {
248
+ className: prefixCls + "__footer"
249
+ }, /*#__PURE__*/React__default["default"].createElement("div", {
250
+ className: prefixCls + "__footer-item"
251
+ }, /*#__PURE__*/React__default["default"].createElement("div", {
252
+ className: prefixCls + "__footer-item__icon"
253
+ }, /*#__PURE__*/React__default["default"].createElement(icons.ArrowUpOutlined, null), /*#__PURE__*/React__default["default"].createElement(icons.ArrowDownOutlined, null)), /*#__PURE__*/React__default["default"].createElement("span", {
254
+ className: prefixCls + "__footer-item__text"
255
+ }, i18n.menuSearch.moveCursor)), /*#__PURE__*/React__default["default"].createElement("div", {
256
+ className: prefixCls + "__footer-item"
257
+ }, /*#__PURE__*/React__default["default"].createElement("div", {
258
+ className: prefixCls + "__footer-item__icon"
259
+ }, /*#__PURE__*/React__default["default"].createElement(EnterIcon.EnterIcon, null)), /*#__PURE__*/React__default["default"].createElement("span", {
260
+ className: prefixCls + "__footer-item__text"
261
+ }, i18n.menuSearch.confirmSelect)), /*#__PURE__*/React__default["default"].createElement("div", {
262
+ className: prefixCls + "__footer-item"
263
+ }, /*#__PURE__*/React__default["default"].createElement("div", {
264
+ className: prefixCls + "__footer-item__icon"
265
+ }, "esc"), /*#__PURE__*/React__default["default"].createElement("span", {
266
+ className: prefixCls + "__footer-item__text"
267
+ }, i18n.menuSearch.hideWindow)))));
268
+ });
269
+ if (env.__DEV__) {
270
+ MenuSearch.displayName = 'MenuSearch';
271
+ }
272
+ var MenuSearchInput = /*#__PURE__*/React.forwardRef(function (_a, ref) {
273
+ var prefixCls = _a.prefixCls,
274
+ placeholder = _a.placeholder,
275
+ width = _a.width,
276
+ value = _a.value,
277
+ _onChange = _a.onChange,
278
+ onClear = _a.onClear,
279
+ onClose = _a.onClose,
280
+ onKeyDown = _a.onKeyDown,
281
+ inputRef = _a.inputRef,
282
+ rest = tslib.__rest(_a, ["prefixCls", "placeholder", "width", "value", "onChange", "onClear", "onClose", "onKeyDown", "inputRef"]);
283
+ var i18n = core.useLocaleContext();
284
+ return /*#__PURE__*/React__default["default"].createElement("div", {
285
+ ref: ref,
286
+ className: prefixCls + "__input-wrapper",
287
+ style: {
288
+ width: width
289
+ }
290
+ }, /*#__PURE__*/React__default["default"].createElement(Input__default["default"], Object.assign({
291
+ ref: inputRef,
292
+ className: prefixCls + "__input",
293
+ classNames: {
294
+ prefix: prefixCls + "__input-prefix"
295
+ },
296
+ appearance: "unset",
297
+ placeholder: placeholder,
298
+ prefix: /*#__PURE__*/React__default["default"].createElement(icons.SearchOutlined, null),
299
+ suffix: /*#__PURE__*/React__default["default"].createElement(Button.Button, {
300
+ className: prefixCls + "__input-clear",
301
+ appearance: "link",
302
+ size: "xs",
303
+ onClick: onClear
304
+ }, i18n.menuSearch.clear),
305
+ value: value,
306
+ onChange: function onChange(e) {
307
+ return _onChange === null || _onChange === void 0 ? void 0 : _onChange(e.target.value);
308
+ },
309
+ onKeyDown: onKeyDown
310
+ }, rest)), /*#__PURE__*/React__default["default"].createElement("span", {
311
+ className: prefixCls + "__close"
312
+ }, /*#__PURE__*/React__default["default"].createElement(IconButton__default["default"], {
313
+ icon: /*#__PURE__*/React__default["default"].createElement(icons.CloseOutlined, null),
314
+ effect: true,
315
+ onClick: onClose
316
+ })));
317
+ });
318
+ if (env.__DEV__) {
319
+ MenuSearchInput.displayName = 'MenuSearchInput';
320
+ }
321
+ exports.MenuSearch = MenuSearch;
322
+ exports.MenuSearchInput = MenuSearchInput;