@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/lib/cjs/util.js CHANGED
@@ -13,7 +13,39 @@ Object.defineProperty(exports, '__esModule', {
13
13
  value: true
14
14
  });
15
15
  var treeUtils = require('@hi-ui/tree-utils');
16
-
16
+ function _createForOfIteratorHelperLoose(o, allowArrayLike) {
17
+ var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
18
+ if (it) return (it = it.call(o)).next.bind(it);
19
+ if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
20
+ if (it) o = it;
21
+ var i = 0;
22
+ return function () {
23
+ if (i >= o.length) return {
24
+ done: true
25
+ };
26
+ return {
27
+ done: false,
28
+ value: o[i++]
29
+ };
30
+ };
31
+ }
32
+ throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
33
+ }
34
+ function _unsupportedIterableToArray(o, minLen) {
35
+ if (!o) return;
36
+ if (typeof o === "string") return _arrayLikeToArray(o, minLen);
37
+ var n = Object.prototype.toString.call(o).slice(8, -1);
38
+ if (n === "Object" && o.constructor) n = o.constructor.name;
39
+ if (n === "Map" || n === "Set") return Array.from(o);
40
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
41
+ }
42
+ function _arrayLikeToArray(arr, len) {
43
+ if (len == null || len > arr.length) len = arr.length;
44
+ for (var i = 0, arr2 = new Array(len); i < len; i++) {
45
+ arr2[i] = arr[i];
46
+ }
47
+ return arr2;
48
+ }
17
49
  // 寻找某一节点的父节点
18
50
  var getParentId = function getParentId(id, data) {
19
51
  var parentId = '';
@@ -90,8 +122,70 @@ var transformTreeData = function transformTreeData(data, fieldNames) {
90
122
  };
91
123
  return data.map(traverseTreeNode);
92
124
  };
125
+ /**
126
+ * 增强版搜索函数,返回包含路径信息的结果
127
+ */
128
+ function searchMenuWithPath(data, keyword) {
129
+ if (!keyword || !data || data.length === 0) {
130
+ return [];
131
+ }
132
+ var results = [];
133
+ var processedIds = new Set();
134
+ function searchInTree(nodes, currentPath) {
135
+ if (currentPath === void 0) {
136
+ currentPath = [];
137
+ }
138
+ var _a;
139
+ for (var _iterator3 = _createForOfIteratorHelperLoose(nodes), _step3; !(_step3 = _iterator3()).done;) {
140
+ var node = _step3.value;
141
+ var nodePath = [].concat(currentPath, [node]);
142
+ var isMatched = (_a = node.title) === null || _a === void 0 ? void 0 : _a.toString().toLowerCase().includes(keyword.toLowerCase());
143
+ if (isMatched) {
144
+ if (!node.children || node.children.length === 0) {
145
+ // 叶子节点
146
+ if (!processedIds.has(node.id)) {
147
+ results.push({
148
+ node: node,
149
+ path: nodePath,
150
+ level: nodePath.length - 1
151
+ });
152
+ processedIds.add(node.id);
153
+ }
154
+ } else {
155
+ // 父节点,添加所有子节点
156
+ addAllDescendantsWithPath(node.children, nodePath);
157
+ }
158
+ } else {
159
+ // 继续搜索子节点
160
+ if (node.children && node.children.length > 0) {
161
+ searchInTree(node.children, nodePath);
162
+ }
163
+ }
164
+ }
165
+ }
166
+ function addAllDescendantsWithPath(children, parentPath) {
167
+ for (var _iterator4 = _createForOfIteratorHelperLoose(children), _step4; !(_step4 = _iterator4()).done;) {
168
+ var child = _step4.value;
169
+ var childPath = [].concat(parentPath, [child]);
170
+ if (!processedIds.has(child.id)) {
171
+ results.push({
172
+ node: child,
173
+ path: childPath,
174
+ level: childPath.length - 1
175
+ });
176
+ processedIds.add(child.id);
177
+ }
178
+ if (child.children && child.children.length > 0) {
179
+ addAllDescendantsWithPath(child.children, childPath);
180
+ }
181
+ }
182
+ }
183
+ searchInTree(data);
184
+ return results;
185
+ }
93
186
  exports.filterTreeData = filterTreeData;
94
187
  exports.getAncestorIds = getAncestorIds;
95
188
  exports.getIdsWithChildren = getIdsWithChildren;
96
189
  exports.getParentId = getParentId;
190
+ exports.searchMenuWithPath = searchMenuWithPath;
97
191
  exports.transformTreeData = transformTreeData;
@@ -0,0 +1,32 @@
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
+ import React from 'react';
11
+ var EnterIcon = function EnterIcon() {
12
+ return /*#__PURE__*/React.createElement("svg", {
13
+ width: "12",
14
+ height: "12",
15
+ viewBox: "0 0 12 12",
16
+ fill: "none",
17
+ xmlns: "http://www.w3.org/2000/svg"
18
+ }, /*#__PURE__*/React.createElement("path", {
19
+ d: "M4 9L2 7L4 5",
20
+ stroke: "#91959e",
21
+ strokeWidth: "1.2",
22
+ strokeLinecap: "round",
23
+ strokeLinejoin: "round"
24
+ }), /*#__PURE__*/React.createElement("path", {
25
+ d: "M10 3L10 6.25C10 6.66422 9.66423 7 9.25 7L2 7",
26
+ stroke: "#91959e",
27
+ strokeWidth: "1.2",
28
+ strokeLinecap: "round",
29
+ strokeLinejoin: "round"
30
+ }));
31
+ };
32
+ export { EnterIcon };
@@ -0,0 +1,83 @@
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
+ import { __rest } from 'tslib';
11
+ import React, { forwardRef, useCallback } from 'react';
12
+ import { getPrefixCls, cx } from '@hi-ui/classname';
13
+ import { __DEV__ } from '@hi-ui/env';
14
+ import { isArrayNonEmpty } from '@hi-ui/type-assertion';
15
+ import { useLatestCallback } from '@hi-ui/use-latest';
16
+ import { useUncontrolledState } from '@hi-ui/use-uncontrolled-state';
17
+ import Scrollbar from '@hi-ui/scrollbar';
18
+ var _role = 'group-menu';
19
+ var GROUP_MENU_PREFIX = getPrefixCls(_role);
20
+ /**
21
+ * 分组菜单
22
+ */
23
+ var GroupMenu = /*#__PURE__*/forwardRef(function (_a, ref) {
24
+ var _a$prefixCls = _a.prefixCls,
25
+ prefixCls = _a$prefixCls === void 0 ? GROUP_MENU_PREFIX : _a$prefixCls,
26
+ _a$role = _a.role,
27
+ role = _a$role === void 0 ? _role : _a$role,
28
+ className = _a.className,
29
+ _a$data = _a.data,
30
+ data = _a$data === void 0 ? [] : _a$data,
31
+ onClick = _a.onClick,
32
+ _a$defaultActiveId = _a.defaultActiveId,
33
+ defaultActiveId = _a$defaultActiveId === void 0 ? '' : _a$defaultActiveId,
34
+ activeIdProp = _a.activeId,
35
+ titleRender = _a.titleRender,
36
+ rest = __rest(_a, ["prefixCls", "role", "className", "data", "onClick", "defaultActiveId", "activeId", "titleRender"]);
37
+ var _useUncontrolledState = useUncontrolledState(defaultActiveId, activeIdProp),
38
+ activeId = _useUncontrolledState[0],
39
+ tryChangeActiveId = _useUncontrolledState[1];
40
+ var handleClick = useLatestCallback(function (evt, id, item) {
41
+ tryChangeActiveId(id);
42
+ onClick === null || onClick === void 0 ? void 0 : onClick(evt, id, item);
43
+ });
44
+ var renderItem = useCallback(function (data) {
45
+ return data.map(function (item) {
46
+ var _cx;
47
+ var id = item.id,
48
+ icon = item.icon,
49
+ title = item.title,
50
+ _item$children = item.children,
51
+ children = _item$children === void 0 ? [] : _item$children,
52
+ disabled = item.disabled;
53
+ var isParent = isArrayNonEmpty(children);
54
+ return /*#__PURE__*/React.createElement("div", {
55
+ key: id,
56
+ 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)),
57
+ onClick: function onClick(evt) {
58
+ if (disabled || isParent) return;
59
+ evt.stopPropagation();
60
+ handleClick(evt, id, item);
61
+ }
62
+ }, /*#__PURE__*/React.createElement("div", {
63
+ className: cx(prefixCls + "-item__content")
64
+ }, /*#__PURE__*/React.createElement("div", {
65
+ className: cx(prefixCls + "-item__icon")
66
+ }, icon), /*#__PURE__*/React.createElement("div", {
67
+ className: cx(prefixCls + "-item__title")
68
+ }, typeof titleRender === 'function' ? titleRender(item) : title)), isParent && renderItem(children));
69
+ });
70
+ }, [activeId, handleClick, prefixCls, titleRender]);
71
+ return /*#__PURE__*/React.createElement("div", Object.assign({
72
+ className: cx("" + prefixCls, className),
73
+ ref: ref,
74
+ role: role
75
+ }, rest), /*#__PURE__*/React.createElement(Scrollbar, {
76
+ onlyScrollVisible: true,
77
+ axes: "y"
78
+ }, renderItem(data)));
79
+ });
80
+ if (__DEV__) {
81
+ GroupMenu.displayName = 'GroupMenu';
82
+ }
83
+ export { GroupMenu };
package/lib/esm/Menu.js CHANGED
@@ -8,7 +8,7 @@
8
8
  * LICENSE file in the root directory of this source tree.
9
9
  */
10
10
  import { __rest } from 'tslib';
11
- import React, { forwardRef, useState, useMemo, useEffect, useCallback, useLayoutEffect } from 'react';
11
+ import React, { forwardRef, useState, useMemo, useEffect, useRef, useCallback, useLayoutEffect } from 'react';
12
12
  import { getPrefixCls, cx } from '@hi-ui/classname';
13
13
  import { MenuUnfoldOutlined, MenuFoldOutlined } from '@hi-ui/icons';
14
14
  import { __DEV__ } from '@hi-ui/env';
@@ -70,7 +70,9 @@ var Menu = /*#__PURE__*/forwardRef(function (_a, ref) {
70
70
  onClick = _a.onClick,
71
71
  _a$size = _a.size,
72
72
  size = _a$size === void 0 ? 'lg' : _a$size,
73
- rest = __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"]);
73
+ _a$showTitleOnMini = _a.showTitleOnMini,
74
+ showTitleOnMini = _a$showTitleOnMini === void 0 ? false : _a$showTitleOnMini,
75
+ rest = __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"]);
74
76
  var i18n = useLocaleContext();
75
77
  var _useUncontrolledState = useUncontrolledState(defaultActiveId, activeIdProp, onClick),
76
78
  activeId = _useUncontrolledState[0],
@@ -93,6 +95,7 @@ var Menu = /*#__PURE__*/forwardRef(function (_a, ref) {
93
95
  }, expandedIdsProp, onExpand),
94
96
  expandedIds = _useUncontrolledState2[0],
95
97
  updateExpandedIds = _useUncontrolledState2[1];
98
+ var expandedIdsRef = useRef(expandedIds);
96
99
  var clickMenu = useCallback(function (id, raw) {
97
100
  updateActiveId(id, raw);
98
101
  }, [updateActiveId]);
@@ -101,14 +104,17 @@ var Menu = /*#__PURE__*/forwardRef(function (_a, ref) {
101
104
  return expandedId !== id;
102
105
  }) : expandedIds.concat(id);
103
106
  updateExpandedIds(nextExpandedIds);
107
+ expandedIdsRef.current = nextExpandedIds;
104
108
  if (onClickSubMenu) {
105
109
  onClickSubMenu(id, nextExpandedIds);
106
110
  }
107
111
  }, [onClickSubMenu, expandedIds, updateExpandedIds]);
108
112
  var closePopper = useCallback(function (id) {
109
- updateExpandedIds(expandedIds.filter(function (expandedId) {
113
+ var nextExpandedIds = expandedIds.filter(function (expandedId) {
110
114
  return expandedId !== id;
111
- }));
115
+ });
116
+ updateExpandedIds(nextExpandedIds);
117
+ expandedIdsRef.current = nextExpandedIds;
112
118
  }, [expandedIds, updateExpandedIds]);
113
119
  var closeAllPopper = useCallback(function () {
114
120
  updateExpandedIds([]);
@@ -141,6 +147,13 @@ var Menu = /*#__PURE__*/forwardRef(function (_a, ref) {
141
147
  setContainerWidth(width);
142
148
  }
143
149
  });
150
+ useEffect(function () {
151
+ if (mini) {
152
+ updateExpandedIds([]);
153
+ } else {
154
+ updateExpandedIds(expandedIdsRef.current);
155
+ }
156
+ }, [mini, updateExpandedIds]);
144
157
  var _useState4 = useState(0),
145
158
  tagMaxCount = _useState4[0],
146
159
  setTagMaxCount = _useState4[1];
@@ -155,7 +168,7 @@ var Menu = /*#__PURE__*/forwardRef(function (_a, ref) {
155
168
  }, [transformedData, tagMaxCount]);
156
169
  var getTagWidth = useCallback(function (index) {
157
170
  if (!containerElement) return MIN_WIDTH;
158
- var elements = containerElement.getElementsByClassName('hi-v4-menu-item');
171
+ var elements = containerElement.getElementsByClassName('hi-v5-menu-item');
159
172
  var element = elements && elements[index];
160
173
  if (!element) return MIN_WIDTH;
161
174
  return element.getBoundingClientRect().width;
@@ -191,9 +204,7 @@ var Menu = /*#__PURE__*/forwardRef(function (_a, ref) {
191
204
  var collapseNode = canToggle ? ( /*#__PURE__*/React.createElement("div", {
192
205
  className: cx(prefixCls + "__toggle"),
193
206
  onClick: function onClick() {
194
- miniToggleAction.not();
195
- // 关闭所有展开的子菜单,防止切换到 mini 模式后,子菜单还是展开的
196
- updateExpandedIds([]);
207
+ return miniToggleAction.not();
197
208
  }
198
209
  }, mini ? /*#__PURE__*/React.createElement(MenuUnfoldOutlined, null) : /*#__PURE__*/React.createElement(MenuFoldOutlined, null))) : null;
199
210
  return /*#__PURE__*/React.createElement(React.Fragment, null, isFunction(footerRender) ? footerRender({
@@ -203,12 +214,12 @@ var Menu = /*#__PURE__*/forwardRef(function (_a, ref) {
203
214
  };
204
215
  var renderItem = useCallback(function (menuItem, level) {
205
216
  // 显示缩略内容
206
- if (showMini && level === 1) {
217
+ if (showMini && level === 1 && !showTitleOnMini) {
207
218
  return renderMenuItemMini(menuItem);
208
219
  }
209
220
  return isFunction(render) ? render(menuItem, level) : menuItem.title;
210
- }, [render, showMini]);
211
- var cls = cx(prefixCls, className, prefixCls + "--" + placement, prefixCls + "--size-" + size, mini && prefixCls + "--mini", (expandedType === 'pop' || showAllSubMenus || mini) && prefixCls + "--popup");
221
+ }, [render, showMini, showTitleOnMini]);
222
+ var cls = cx(prefixCls, className, prefixCls + "--" + placement, prefixCls + "--size-" + size, mini && prefixCls + "--mini", showTitleOnMini && prefixCls + "--show-title-on-mini", (expandedType === 'pop' || showAllSubMenus || mini) && prefixCls + "--popup");
212
223
  return /*#__PURE__*/React.createElement("div", Object.assign({
213
224
  ref: useMergeRefs(ref, setContainerElement),
214
225
  role: role,
@@ -219,6 +230,7 @@ var Menu = /*#__PURE__*/forwardRef(function (_a, ref) {
219
230
  expandedType: expandedType,
220
231
  showAllSubMenus: showAllSubMenus,
221
232
  mini: mini,
233
+ showTitleOnMini: showTitleOnMini,
222
234
  clickMenu: clickMenu,
223
235
  clickSubMenu: clickSubMenu,
224
236
  closePopper: closePopper,
@@ -56,7 +56,8 @@ var MenuItem = /*#__PURE__*/forwardRef(function (_ref, ref) {
56
56
  clickSubMenu = _useContext.clickSubMenu,
57
57
  closeAllPopper = _useContext.closeAllPopper,
58
58
  activeParents = _useContext.activeParents,
59
- overlayClassName = _useContext.overlayClassName;
59
+ overlayClassName = _useContext.overlayClassName,
60
+ showTitleOnMini = _useContext.showTitleOnMini;
60
61
  var _parentIds = (parentIds || []).concat(id);
61
62
  var hasChildren = isArrayNonEmpty(children);
62
63
  var mergedRef = useMergeRefs(itemRef, ref);
@@ -122,7 +123,7 @@ var MenuItem = /*#__PURE__*/forwardRef(function (_ref, ref) {
122
123
  visible: !!(expandedIds === null || expandedIds === void 0 ? void 0 : expandedIds.includes(id)),
123
124
  attachEl: itemRef.current,
124
125
  placement: 'right-start',
125
- gutterGap: 16,
126
+ gutterGap: showTitleOnMini ? 8 : 16,
126
127
  className: overlayClassName,
127
128
  onClose: function onClose() {
128
129
  closePopper === null || closePopper === void 0 ? void 0 : closePopper(id);
@@ -142,7 +143,7 @@ var MenuItem = /*#__PURE__*/forwardRef(function (_ref, ref) {
142
143
  visible: !!(expandedIds === null || expandedIds === void 0 ? void 0 : expandedIds.includes(id)),
143
144
  attachEl: itemRef.current,
144
145
  placement: 'right-start',
145
- gutterGap: 16,
146
+ gutterGap: showTitleOnMini ? 12 : 16,
146
147
  disabledPortal: true,
147
148
  className: overlayClassName,
148
149
  onClose: function onClose() {
@@ -0,0 +1,305 @@
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
+ import { __rest } from 'tslib';
11
+ import React, { forwardRef, useState, useRef, useLayoutEffect, useCallback, useEffect, useImperativeHandle } from 'react';
12
+ import { useLocaleContext } from '@hi-ui/core';
13
+ import { __DEV__ } from '@hi-ui/env';
14
+ import { getPrefixCls, cx } from '@hi-ui/classname';
15
+ import { ArrowUpOutlined, ArrowDownOutlined, SearchOutlined, CloseOutlined } from '@hi-ui/icons';
16
+ import IconButton from '@hi-ui/icon-button';
17
+ import './button/lib/esm/styles/index.scss.js';
18
+ import { Button } from './button/lib/esm/Button.js';
19
+ import './button/lib/esm/ButtonGroup.js';
20
+ import Input from '@hi-ui/input';
21
+ import Highlighter from '@hi-ui/highlighter';
22
+ import { useUncontrolledState } from '@hi-ui/use-uncontrolled-state';
23
+ import { useUncontrolledToggle } from '@hi-ui/use-toggle';
24
+ import EllipsisTooltip from '@hi-ui/ellipsis-tooltip';
25
+ import { EnterIcon } from './EnterIcon.js';
26
+ import { searchMenuWithPath } from './util.js';
27
+ var _role = 'menu-search';
28
+ var _prefix = getPrefixCls(_role);
29
+ var MenuSearch = /*#__PURE__*/forwardRef(function (_a, ref) {
30
+ var _cx, _cx2;
31
+ var _b, _c;
32
+ var innerRef = _a.innerRef,
33
+ _a$prefixCls = _a.prefixCls,
34
+ prefixCls = _a$prefixCls === void 0 ? _prefix : _a$prefixCls,
35
+ className = _a.className,
36
+ placeholder = _a.placeholder,
37
+ width = _a.width,
38
+ style = _a.style,
39
+ visibleProp = _a.visible,
40
+ data = _a.data,
41
+ _a$defaultValue = _a.defaultValue,
42
+ defaultValue = _a$defaultValue === void 0 ? '' : _a$defaultValue,
43
+ valueProp = _a.value,
44
+ onChange = _a.onChange,
45
+ onSelect = _a.onSelect,
46
+ onClear = _a.onClear,
47
+ onClose = _a.onClose,
48
+ onEsc = _a.onEsc;
49
+ __rest(_a, ["innerRef", "prefixCls", "className", "clearText", "placeholder", "notFoundContent", "width", "style", "visible", "data", "defaultValue", "value", "onChange", "onSearch", "onSelect", "onClear", "onClose", "onEsc"]);
50
+ var i18n = useLocaleContext();
51
+ var _useUncontrolledToggl = useUncontrolledToggle({
52
+ visible: visibleProp
53
+ }),
54
+ visible = _useUncontrolledToggl[0],
55
+ visibleAction = _useUncontrolledToggl[1];
56
+ var _useUncontrolledState = useUncontrolledState(defaultValue, valueProp, onChange),
57
+ value = _useUncontrolledState[0],
58
+ tryChangeValue = _useUncontrolledState[1];
59
+ var _useState = useState(-1),
60
+ currentIndex = _useState[0],
61
+ setCurrentIndex = _useState[1];
62
+ var listRef = useRef(null);
63
+ useLayoutEffect(function () {
64
+ if (currentIndex === -1 || !listRef.current) return;
65
+ var listContainer = listRef.current;
66
+ var selectedItem = listContainer.children[currentIndex];
67
+ if (!selectedItem) return;
68
+ var containerScrollTop = listContainer.scrollTop;
69
+ var containerHeight = listContainer.clientHeight;
70
+ var itemTop = selectedItem.offsetTop;
71
+ var itemHeight = selectedItem.offsetHeight;
72
+ // 计算元素的可见范围
73
+ var itemBottom = itemTop + itemHeight;
74
+ var visibleTop = containerScrollTop;
75
+ var visibleBottom = containerScrollTop + containerHeight;
76
+ // 判断是否需要滚动
77
+ var isItemAboveViewport = itemTop < visibleTop;
78
+ var isItemBelowViewport = itemBottom > visibleBottom;
79
+ if (isItemAboveViewport) {
80
+ // 如果元素在可视区域上方,滚动到元素顶部
81
+ listContainer.scrollTop = itemTop;
82
+ } else if (isItemBelowViewport) {
83
+ // 如果元素在可视区域下方,滚动到元素底部刚好可见
84
+ listContainer.scrollTop = itemBottom - containerHeight;
85
+ }
86
+ }, [currentIndex]);
87
+ var resultMemo = React.useMemo(function () {
88
+ if (!data || !value) return [];
89
+ // 使用新的搜索算法
90
+ var searchResults = searchMenuWithPath(data, value);
91
+ return searchResults.map(function (result) {
92
+ return Object.assign(Object.assign({}, result.node), {
93
+ level: result.level,
94
+ path: result.path,
95
+ // 添加路径信息用于显示
96
+ pathTitles: result.path.map(function (p) {
97
+ var _a;
98
+ return (_a = p.title) === null || _a === void 0 ? void 0 : _a.toString();
99
+ }).filter(Boolean)
100
+ });
101
+ });
102
+ }, [data, value]);
103
+ var handleChange = useCallback(function (value) {
104
+ tryChangeValue(value);
105
+ }, [tryChangeValue]);
106
+ var handleSelect = useCallback(function (id, item, index) {
107
+ var _a;
108
+ setCurrentIndex(index);
109
+ visibleAction.off();
110
+ // 让列表容器获取焦点,确保键盘导航可用
111
+ (_a = listRef.current) === null || _a === void 0 ? void 0 : _a.focus();
112
+ onSelect === null || onSelect === void 0 ? void 0 : onSelect(id, item);
113
+ }, [onSelect, visibleAction]);
114
+ var handleMove = useCallback(function (direction) {
115
+ if (!resultMemo) return;
116
+ setCurrentIndex(function (prev) {
117
+ if (direction === 'up') {
118
+ return prev - 1 < 0 ? (resultMemo === null || resultMemo === void 0 ? void 0 : resultMemo.length) - 1 : prev - 1;
119
+ } else {
120
+ return prev + 1 > (resultMemo === null || resultMemo === void 0 ? void 0 : resultMemo.length) - 1 ? 0 : prev + 1;
121
+ }
122
+ });
123
+ }, [resultMemo]);
124
+ var handleEnter = useCallback(function () {
125
+ if (!resultMemo) return;
126
+ if (currentIndex === -1) {
127
+ setCurrentIndex(0);
128
+ }
129
+ visibleAction.off();
130
+ onSelect === null || onSelect === void 0 ? void 0 : onSelect(resultMemo[currentIndex].id, resultMemo[currentIndex]);
131
+ }, [resultMemo, currentIndex, onSelect, visibleAction]);
132
+ var handleClear = useCallback(function () {
133
+ tryChangeValue('');
134
+ setCurrentIndex(-1);
135
+ onClear === null || onClear === void 0 ? void 0 : onClear();
136
+ }, [onClear, tryChangeValue]);
137
+ var handleClose = useCallback(function () {
138
+ visibleAction.off();
139
+ onClose === null || onClose === void 0 ? void 0 : onClose();
140
+ }, [onClose, visibleAction]);
141
+ var handleEscape = useCallback(function () {
142
+ handleClose();
143
+ onEsc === null || onEsc === void 0 ? void 0 : onEsc();
144
+ }, [handleClose, onEsc]);
145
+ var handleKeyDown = useCallback(function (e) {
146
+ if (e.key === 'ArrowUp') {
147
+ handleMove('up');
148
+ }
149
+ if (e.key === 'ArrowDown') {
150
+ handleMove('down');
151
+ }
152
+ if (e.key === 'Enter') {
153
+ handleEnter();
154
+ }
155
+ if (e.key === 'Escape') {
156
+ handleEscape();
157
+ }
158
+ }, [handleEnter, handleMove, handleEscape]);
159
+ var _useState2 = useState(null),
160
+ inputRef = _useState2[0],
161
+ setInputRef = _useState2[1];
162
+ useEffect(function () {
163
+ if (!value || !inputRef) {
164
+ visibleAction.off();
165
+ } else {
166
+ visibleAction.on();
167
+ }
168
+ }, [inputRef, value, visibleAction]);
169
+ useImperativeHandle(innerRef, function () {
170
+ return {
171
+ show: function show() {
172
+ visibleAction.on();
173
+ },
174
+ hide: function hide() {
175
+ visibleAction.off();
176
+ },
177
+ focus: function focus() {
178
+ inputRef === null || inputRef === void 0 ? void 0 : inputRef.focus();
179
+ }
180
+ };
181
+ });
182
+ var cls = cx(prefixCls, className, (_cx = {}, _cx[prefixCls + "--open"] = visible, _cx));
183
+ return /*#__PURE__*/React.createElement("div", {
184
+ className: cls,
185
+ style: style
186
+ }, /*#__PURE__*/React.createElement(MenuSearchInput, {
187
+ width: width,
188
+ prefixCls: prefixCls,
189
+ placeholder: placeholder,
190
+ value: value,
191
+ onChange: handleChange,
192
+ onClear: handleClear,
193
+ onClose: handleClose,
194
+ onKeyDown: handleKeyDown,
195
+ inputRef: setInputRef
196
+ }), /*#__PURE__*/React.createElement("div", {
197
+ className: cx(prefixCls + "__content", (_cx2 = {}, _cx2[prefixCls + "__content--visible"] = visible, _cx2))
198
+ }, (resultMemo === null || resultMemo === void 0 ? void 0 : resultMemo.length) > 0 ? ( /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
199
+ className: prefixCls + "__header"
200
+ }, /*#__PURE__*/React.createElement(Highlighter, {
201
+ keyword: String((_b = resultMemo === null || resultMemo === void 0 ? void 0 : resultMemo.length) !== null && _b !== void 0 ? _b : 0)
202
+ }, i18n.get('menuSearch.searchResult', {
203
+ count: (_c = resultMemo === null || resultMemo === void 0 ? void 0 : resultMemo.length) !== null && _c !== void 0 ? _c : 0,
204
+ keyword: value
205
+ }))), /*#__PURE__*/React.createElement("div", {
206
+ className: prefixCls + "__list",
207
+ ref: listRef,
208
+ tabIndex: -1,
209
+ onKeyDown: handleKeyDown
210
+ }, resultMemo === null || resultMemo === void 0 ? void 0 : resultMemo.map(function (item, index) {
211
+ var _cx3;
212
+ return /*#__PURE__*/React.createElement("div", {
213
+ key: item.id,
214
+ className: cx(prefixCls + "__list-item", (_cx3 = {}, _cx3[prefixCls + "__list-item--selected"] = currentIndex === index, _cx3)),
215
+ onClick: function onClick() {
216
+ return handleSelect(item.id, item, index);
217
+ }
218
+ }, /*#__PURE__*/React.createElement("div", {
219
+ className: prefixCls + "__list-item__title"
220
+ }, /*#__PURE__*/React.createElement(EllipsisTooltip, {
221
+ tooltipProps: {
222
+ style: {
223
+ maxWidth: 320
224
+ }
225
+ }
226
+ }, /*#__PURE__*/React.createElement(Highlighter, {
227
+ keyword: value
228
+ }, item.pathTitles.join('/')))));
229
+ })))) : ( /*#__PURE__*/React.createElement("div", {
230
+ className: prefixCls + "__empty"
231
+ }, /*#__PURE__*/React.createElement("div", null, i18n.menuSearch.searchEmptyResult)))), (resultMemo === null || resultMemo === void 0 ? void 0 : resultMemo.length) > 0 && ( /*#__PURE__*/React.createElement("div", {
232
+ className: prefixCls + "__footer"
233
+ }, /*#__PURE__*/React.createElement("div", {
234
+ className: prefixCls + "__footer-item"
235
+ }, /*#__PURE__*/React.createElement("div", {
236
+ className: prefixCls + "__footer-item__icon"
237
+ }, /*#__PURE__*/React.createElement(ArrowUpOutlined, null), /*#__PURE__*/React.createElement(ArrowDownOutlined, null)), /*#__PURE__*/React.createElement("span", {
238
+ className: prefixCls + "__footer-item__text"
239
+ }, i18n.menuSearch.moveCursor)), /*#__PURE__*/React.createElement("div", {
240
+ className: prefixCls + "__footer-item"
241
+ }, /*#__PURE__*/React.createElement("div", {
242
+ className: prefixCls + "__footer-item__icon"
243
+ }, /*#__PURE__*/React.createElement(EnterIcon, null)), /*#__PURE__*/React.createElement("span", {
244
+ className: prefixCls + "__footer-item__text"
245
+ }, i18n.menuSearch.confirmSelect)), /*#__PURE__*/React.createElement("div", {
246
+ className: prefixCls + "__footer-item"
247
+ }, /*#__PURE__*/React.createElement("div", {
248
+ className: prefixCls + "__footer-item__icon"
249
+ }, "esc"), /*#__PURE__*/React.createElement("span", {
250
+ className: prefixCls + "__footer-item__text"
251
+ }, i18n.menuSearch.hideWindow)))));
252
+ });
253
+ if (__DEV__) {
254
+ MenuSearch.displayName = 'MenuSearch';
255
+ }
256
+ var MenuSearchInput = /*#__PURE__*/forwardRef(function (_a, ref) {
257
+ var prefixCls = _a.prefixCls,
258
+ placeholder = _a.placeholder,
259
+ width = _a.width,
260
+ value = _a.value,
261
+ _onChange = _a.onChange,
262
+ onClear = _a.onClear,
263
+ onClose = _a.onClose,
264
+ onKeyDown = _a.onKeyDown,
265
+ inputRef = _a.inputRef,
266
+ rest = __rest(_a, ["prefixCls", "placeholder", "width", "value", "onChange", "onClear", "onClose", "onKeyDown", "inputRef"]);
267
+ var i18n = useLocaleContext();
268
+ return /*#__PURE__*/React.createElement("div", {
269
+ ref: ref,
270
+ className: prefixCls + "__input-wrapper",
271
+ style: {
272
+ width: width
273
+ }
274
+ }, /*#__PURE__*/React.createElement(Input, Object.assign({
275
+ ref: inputRef,
276
+ className: prefixCls + "__input",
277
+ classNames: {
278
+ prefix: prefixCls + "__input-prefix"
279
+ },
280
+ appearance: "unset",
281
+ placeholder: placeholder,
282
+ prefix: /*#__PURE__*/React.createElement(SearchOutlined, null),
283
+ suffix: /*#__PURE__*/React.createElement(Button, {
284
+ className: prefixCls + "__input-clear",
285
+ appearance: "link",
286
+ size: "xs",
287
+ onClick: onClear
288
+ }, i18n.menuSearch.clear),
289
+ value: value,
290
+ onChange: function onChange(e) {
291
+ return _onChange === null || _onChange === void 0 ? void 0 : _onChange(e.target.value);
292
+ },
293
+ onKeyDown: onKeyDown
294
+ }, rest)), /*#__PURE__*/React.createElement("span", {
295
+ className: prefixCls + "__close"
296
+ }, /*#__PURE__*/React.createElement(IconButton, {
297
+ icon: /*#__PURE__*/React.createElement(CloseOutlined, null),
298
+ effect: true,
299
+ onClick: onClose
300
+ })));
301
+ });
302
+ if (__DEV__) {
303
+ MenuSearchInput.displayName = 'MenuSearchInput';
304
+ }
305
+ export { MenuSearch, MenuSearchInput };