@hi-ui/menu 5.0.0-canary.2 → 5.0.0-canary.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.
package/lib/esm/util.js CHANGED
@@ -8,7 +8,39 @@
8
8
  * LICENSE file in the root directory of this source tree.
9
9
  */
10
10
  import { cloneTree, filterTree, getTreeNodesWithChildren } from '@hi-ui/tree-utils';
11
-
11
+ function _createForOfIteratorHelperLoose(o, allowArrayLike) {
12
+ var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
13
+ if (it) return (it = it.call(o)).next.bind(it);
14
+ if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
15
+ if (it) o = it;
16
+ var i = 0;
17
+ return function () {
18
+ if (i >= o.length) return {
19
+ done: true
20
+ };
21
+ return {
22
+ done: false,
23
+ value: o[i++]
24
+ };
25
+ };
26
+ }
27
+ throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
28
+ }
29
+ function _unsupportedIterableToArray(o, minLen) {
30
+ if (!o) return;
31
+ if (typeof o === "string") return _arrayLikeToArray(o, minLen);
32
+ var n = Object.prototype.toString.call(o).slice(8, -1);
33
+ if (n === "Object" && o.constructor) n = o.constructor.name;
34
+ if (n === "Map" || n === "Set") return Array.from(o);
35
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
36
+ }
37
+ function _arrayLikeToArray(arr, len) {
38
+ if (len == null || len > arr.length) len = arr.length;
39
+ for (var i = 0, arr2 = new Array(len); i < len; i++) {
40
+ arr2[i] = arr[i];
41
+ }
42
+ return arr2;
43
+ }
12
44
  // 寻找某一节点的父节点
13
45
  var getParentId = function getParentId(id, data) {
14
46
  var parentId = '';
@@ -85,4 +117,65 @@ var transformTreeData = function transformTreeData(data, fieldNames) {
85
117
  };
86
118
  return data.map(traverseTreeNode);
87
119
  };
88
- export { filterTreeData, getAncestorIds, getIdsWithChildren, getParentId, transformTreeData };
120
+ /**
121
+ * 增强版搜索函数,返回包含路径信息的结果
122
+ */
123
+ function searchMenuWithPath(data, keyword) {
124
+ if (!keyword || !data || data.length === 0) {
125
+ return [];
126
+ }
127
+ var results = [];
128
+ var processedIds = new Set();
129
+ function searchInTree(nodes, currentPath) {
130
+ if (currentPath === void 0) {
131
+ currentPath = [];
132
+ }
133
+ var _a;
134
+ for (var _iterator3 = _createForOfIteratorHelperLoose(nodes), _step3; !(_step3 = _iterator3()).done;) {
135
+ var node = _step3.value;
136
+ var nodePath = [].concat(currentPath, [node]);
137
+ var isMatched = (_a = node.title) === null || _a === void 0 ? void 0 : _a.toString().toLowerCase().includes(keyword.toLowerCase());
138
+ if (isMatched) {
139
+ if (!node.children || node.children.length === 0) {
140
+ // 叶子节点
141
+ if (!processedIds.has(node.id)) {
142
+ results.push({
143
+ node: node,
144
+ path: nodePath,
145
+ level: nodePath.length - 1
146
+ });
147
+ processedIds.add(node.id);
148
+ }
149
+ } else {
150
+ // 父节点,添加所有子节点
151
+ addAllDescendantsWithPath(node.children, nodePath);
152
+ }
153
+ } else {
154
+ // 继续搜索子节点
155
+ if (node.children && node.children.length > 0) {
156
+ searchInTree(node.children, nodePath);
157
+ }
158
+ }
159
+ }
160
+ }
161
+ function addAllDescendantsWithPath(children, parentPath) {
162
+ for (var _iterator4 = _createForOfIteratorHelperLoose(children), _step4; !(_step4 = _iterator4()).done;) {
163
+ var child = _step4.value;
164
+ var childPath = [].concat(parentPath, [child]);
165
+ if (!processedIds.has(child.id)) {
166
+ results.push({
167
+ node: child,
168
+ path: childPath,
169
+ level: childPath.length - 1
170
+ });
171
+ processedIds.add(child.id);
172
+ }
173
+ if (child.children && child.children.length > 0) {
174
+ addAllDescendantsWithPath(child.children, childPath);
175
+ }
176
+ }
177
+ }
178
+ searchInTree(data);
179
+ return results;
180
+ }
181
+ export { filterTreeData, getAncestorIds, getIdsWithChildren, getParentId, searchMenuWithPath, transformTreeData };
@@ -0,0 +1 @@
1
+ export declare const EnterIcon: () => JSX.Element;
@@ -0,0 +1,34 @@
1
+ import React from 'react';
2
+ import { HiBaseHTMLProps } from '@hi-ui/core';
3
+ import type { ComponentSemantic, SemanticClassNamesType, SemanticStylesType } from '@hi-ui/use-merge-semantic';
4
+ import { MenuDataItem } from './types';
5
+ /**
6
+ * 分组菜单
7
+ */
8
+ export declare const GroupMenu: React.ForwardRefExoticComponent<GroupMenuProps & React.RefAttributes<HTMLDivElement | null>>;
9
+ export declare type GroupMenuSemanticName = 'root' | 'wrapper' | 'item' | 'itemContent' | 'itemIcon' | 'itemTitle';
10
+ export declare type GroupMenuSemanticClassNames = SemanticClassNamesType<GroupMenuProps, GroupMenuSemanticName>;
11
+ export declare type GroupMenuSemanticStyles = SemanticStylesType<GroupMenuProps, GroupMenuSemanticName>;
12
+ export declare type GroupMenuSemantic = ComponentSemantic<GroupMenuSemanticClassNames, GroupMenuSemanticStyles>;
13
+ export interface GroupMenuProps extends Omit<HiBaseHTMLProps<'div'>, 'onClick'>, GroupMenuSemantic {
14
+ /**
15
+ * 菜单项数据列表
16
+ */
17
+ data: MenuDataItem[];
18
+ /**
19
+ * 默认激活的菜单项 id
20
+ */
21
+ defaultActiveId?: React.ReactText;
22
+ /**
23
+ * 激活的菜单项 id
24
+ */
25
+ activeId?: React.ReactText;
26
+ /**
27
+ * 点击菜单选项时的回调
28
+ */
29
+ onClick?: (evt: React.MouseEvent<HTMLDivElement>, menuId: React.ReactText, menuItem: MenuDataItem) => void;
30
+ /**
31
+ * 自定义渲染菜单项标题
32
+ */
33
+ titleRender?: (menuItem: MenuDataItem) => React.ReactNode;
34
+ }
@@ -1,11 +1,16 @@
1
1
  import React from 'react';
2
2
  import { HiBaseFieldNames, HiBaseHTMLProps, HiBaseSizeEnum } from '@hi-ui/core';
3
+ import type { ComponentSemantic, SemanticClassNamesType, SemanticStylesType } from '@hi-ui/use-merge-semantic';
3
4
  import { MenuDataItem, MenuFooterRenderProps } from './types';
4
5
  /**
5
6
  * 菜单
6
7
  */
7
8
  export declare const Menu: React.ForwardRefExoticComponent<MenuProps & React.RefAttributes<HTMLDivElement | null>>;
8
- export interface MenuProps extends Omit<HiBaseHTMLProps<'div'>, 'onClick'> {
9
+ export declare type MenuSemanticName = 'root' | 'wrapper' | 'footer' | 'toggle' | 'item' | 'itemInner' | 'itemIcon' | 'itemContent' | 'itemArrow' | 'submenu' | 'popmenu';
10
+ export declare type MenuSemanticClassNames = SemanticClassNamesType<MenuProps, MenuSemanticName>;
11
+ export declare type MenuSemanticStyles = SemanticStylesType<MenuProps, MenuSemanticName>;
12
+ export declare type MenuSemantic = ComponentSemantic<MenuSemanticClassNames, MenuSemanticStyles>;
13
+ export interface MenuProps extends Omit<HiBaseHTMLProps<'div'>, 'onClick'>, MenuSemantic {
9
14
  /**
10
15
  * 菜单项数据列表
11
16
  */
@@ -97,5 +102,9 @@ export interface MenuProps extends Omit<HiBaseHTMLProps<'div'>, 'onClick'> {
97
102
  /**
98
103
  * 设置菜单项的尺寸
99
104
  */
100
- size?: HiBaseSizeEnum;
105
+ size?: Omit<HiBaseSizeEnum, 'xs'>;
106
+ /**
107
+ * 是否在 mini 模式下显示菜单项的标题
108
+ */
109
+ showTitleOnMini?: boolean;
101
110
  }
@@ -12,5 +12,5 @@ export interface MenuItemProps extends Omit<HiBaseHTMLProps<'li'>, 'id'> {
12
12
  parentIds?: React.ReactText[];
13
13
  render?: (node: MenuDataItem, level?: number) => React.ReactNode;
14
14
  raw?: MenuDataItem;
15
- size?: HiBaseSizeEnum;
15
+ size?: Omit<HiBaseSizeEnum, 'xs'>;
16
16
  }
@@ -0,0 +1,44 @@
1
+ import React from 'react';
2
+ import { HiBaseHTMLProps } from '@hi-ui/core';
3
+ import type { ComponentSemantic, SemanticClassNamesType, SemanticStylesType } from '@hi-ui/use-merge-semantic';
4
+ import { MenuDataItem } from './types';
5
+ export declare const MenuSearch: React.ForwardRefExoticComponent<MenuSearchProps & React.RefAttributes<HTMLDivElement | null>>;
6
+ export interface MenuSearchHelper {
7
+ show: () => void;
8
+ hide: () => void;
9
+ focus: () => void;
10
+ }
11
+ export declare type MenuSearchSemanticName = 'root' | 'inputWrapper' | 'input' | 'inputClear' | 'close' | 'content' | 'header' | 'list' | 'listItem' | 'listItemTitle' | 'empty' | 'footer' | 'footerItem' | 'footerItemIcon' | 'footerItemText';
12
+ export declare type MenuSearchSemanticClassNames = SemanticClassNamesType<MenuSearchProps, MenuSearchSemanticName>;
13
+ export declare type MenuSearchSemanticStyles = SemanticStylesType<MenuSearchProps, MenuSearchSemanticName>;
14
+ export declare type MenuSearchSemantic = ComponentSemantic<MenuSearchSemanticClassNames, MenuSearchSemanticStyles>;
15
+ export interface MenuSearchProps extends HiBaseHTMLProps<'div'>, MenuSearchSemantic {
16
+ innerRef?: React.RefObject<MenuSearchHelper>;
17
+ clearText?: React.ReactNode;
18
+ placeholder?: string;
19
+ notFoundContent?: React.ReactNode;
20
+ width?: React.CSSProperties['width'];
21
+ visible?: boolean;
22
+ data?: MenuDataItem[];
23
+ defaultValue?: string;
24
+ value?: string;
25
+ onChange?: (value: string) => void;
26
+ onSearch?: (value: string) => void;
27
+ onSelect?: (id: React.ReactText, item: MenuDataItem) => void;
28
+ onClear?: () => void;
29
+ onClose?: () => void;
30
+ onEsc?: () => void;
31
+ }
32
+ export declare const MenuSearchInput: React.ForwardRefExoticComponent<{
33
+ prefixCls: string;
34
+ placeholder?: string | undefined;
35
+ inputRef?: React.Dispatch<React.SetStateAction<HTMLInputElement | null>> | undefined;
36
+ width?: React.CSSProperties['width'];
37
+ value?: string | undefined;
38
+ onChange?: ((value: string) => void) | undefined;
39
+ onClear?: (() => void) | undefined;
40
+ onClose?: (() => void) | undefined;
41
+ onKeyDown?: ((e: React.KeyboardEvent<HTMLInputElement>) => void) | undefined;
42
+ semanticClassNames?: Record<string, string | undefined> | undefined;
43
+ semanticStyles?: Record<string, React.CSSProperties | undefined> | undefined;
44
+ } & React.RefAttributes<HTMLInputElement>>;
@@ -0,0 +1,63 @@
1
+ import React from 'react';
2
+ import { HiBaseHTMLProps } from '@hi-ui/core';
3
+ import type { ComponentSemantic, SemanticClassNamesType, SemanticStylesType } from '@hi-ui/use-merge-semantic';
4
+ import { MenuDataItem } from './types';
5
+ /**
6
+ * 侧边菜单组件
7
+ */
8
+ export declare const SideMenu: React.ForwardRefExoticComponent<SideMenuProps & React.RefAttributes<HTMLDivElement | null>>;
9
+ export declare type SideMenuSemanticName = 'root' | 'wrapper' | 'itemWrapper' | 'item' | 'itemIcon' | 'itemTitle';
10
+ export declare type SideMenuSemanticClassNames = SemanticClassNamesType<SideMenuProps, SideMenuSemanticName>;
11
+ export declare type SideMenuSemanticStyles = SemanticStylesType<SideMenuProps, SideMenuSemanticName>;
12
+ export declare type SideMenuSemantic = ComponentSemantic<SideMenuSemanticClassNames, SideMenuSemanticStyles>;
13
+ export interface SideMenuProps extends Omit<HiBaseHTMLProps<'div'>, 'onClick' | 'onMouseEnter' | 'onMouseLeave'>, SideMenuSemantic {
14
+ /**
15
+ * 侧边菜单宽度
16
+ */
17
+ width?: number;
18
+ /**
19
+ * 是否为迷你模式
20
+ */
21
+ mini?: boolean;
22
+ /**
23
+ * 默认激活的菜单项
24
+ */
25
+ defaultActiveId?: React.ReactText | null;
26
+ /**
27
+ * 激活的菜单项
28
+ */
29
+ activeId?: React.ReactText | null;
30
+ /**
31
+ * 选中的菜单项
32
+ */
33
+ selectedId?: React.ReactText | null;
34
+ /**
35
+ * 侧边菜单数据
36
+ */
37
+ data: MenuDataItem[];
38
+ /**
39
+ * 子菜单容器引用
40
+ */
41
+ childrenContainerRef?: React.RefObject<HTMLDivElement>;
42
+ /**
43
+ * 点击侧边菜单项
44
+ */
45
+ onClick?: (event: React.MouseEvent<HTMLDivElement>, id: React.ReactText, item: MenuDataItem) => void;
46
+ /**
47
+ * 鼠标移入侧边菜单项
48
+ */
49
+ onMouseEnter?: (event: React.MouseEvent<HTMLDivElement>, id: React.ReactText, item: MenuDataItem) => void;
50
+ /**
51
+ * 鼠标移出侧边菜单项
52
+ */
53
+ onMouseLeave?: (event: React.MouseEvent<HTMLDivElement>, id: React.ReactText, item: MenuDataItem) => void;
54
+ }
55
+ export declare const useSideMenuCascade: ({ data, selectId, activeId, }: {
56
+ data: MenuDataItem[];
57
+ selectId: React.ReactText;
58
+ activeId: React.ReactText;
59
+ }) => {
60
+ submenuData: MenuDataItem[];
61
+ selectParentId: string | number;
62
+ activeParentId: string | number;
63
+ };
@@ -1,10 +1,16 @@
1
1
  import React from 'react';
2
2
  import { MenuDataItem } from './types';
3
+ /** 供 MenuItem 使用的语义化 classNames/styles,由 Menu 通过 useMergeSemantic 合并后注入 */
4
+ export interface MenuSemanticContext {
5
+ semanticClassNames?: Record<string, string | undefined>;
6
+ semanticStyles?: Record<string, React.CSSProperties | undefined>;
7
+ }
3
8
  declare const MenuContext: React.Context<{
4
- placement?: "vertical" | "horizontal" | undefined;
9
+ placement?: "horizontal" | "vertical" | undefined;
5
10
  expandedType?: "collapse" | "pop" | undefined;
6
11
  showAllSubMenus?: boolean | undefined;
7
12
  mini?: boolean | undefined;
13
+ showTitleOnMini?: boolean | undefined;
8
14
  expandedIds?: React.ReactText[] | undefined;
9
15
  activeId?: React.ReactText | undefined;
10
16
  activeParents?: React.ReactText[] | undefined;
@@ -13,5 +19,5 @@ declare const MenuContext: React.Context<{
13
19
  clickSubMenu?: ((id: React.ReactText) => void) | undefined;
14
20
  closePopper?: ((id: React.ReactText) => void) | undefined;
15
21
  closeAllPopper?: (() => void) | undefined;
16
- }>;
22
+ } & MenuSemanticContext>;
17
23
  export default MenuContext;
@@ -2,5 +2,8 @@ import './styles/index.scss';
2
2
  export * from './Menu';
3
3
  export { Menu as default } from './Menu';
4
4
  export * from './Sidebar';
5
+ export * from './MenuSearch';
6
+ export * from './GroupMenu';
7
+ export * from './SideMenu';
5
8
  export { filterTreeData, getParentId, getAncestorIds } from './util';
6
9
  export * from './types';
@@ -6,3 +6,19 @@ export declare const getAncestorIds: (id: string | number, data: Record<string,
6
6
  export declare const getIdsWithChildren: (treeData: MenuDataItem[]) => React.ReactText[];
7
7
  export declare const filterTreeData: (treeData: MenuDataItem[], searchKey: string, activeId: string | number) => MenuDataItem[];
8
8
  export declare const transformTreeData: (data: MenuDataItem[], fieldNames?: HiBaseFieldNames | undefined) => MenuDataItem[];
9
+ /**
10
+ * 根据关键字匹配菜单数据的算法
11
+ * @param data 菜单数据数组
12
+ * @param keyword 搜索关键字
13
+ * @returns 匹配结果数组
14
+ */
15
+ export declare function searchMenuByKeyword(data: MenuDataItem[], keyword: string): MenuDataItem[];
16
+ export interface MenuSearchResult {
17
+ node: MenuDataItem;
18
+ path: MenuDataItem[];
19
+ level: number;
20
+ }
21
+ /**
22
+ * 增强版搜索函数,返回包含路径信息的结果
23
+ */
24
+ export declare function searchMenuWithPath(data: MenuDataItem[], keyword: string): MenuSearchResult[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hi-ui/menu",
3
- "version": "5.0.0-canary.2",
3
+ "version": "5.0.0-canary.21",
4
4
  "description": "A sub-package for @hi-ui/hiui.",
5
5
  "keywords": [],
6
6
  "author": "HiUI <mi-hiui@xiaomi.com>",
@@ -44,31 +44,40 @@
44
44
  "url": "https://github.com/XiaoMi/hiui/issues"
45
45
  },
46
46
  "dependencies": {
47
- "@hi-ui/array-utils": "^5.0.0-canary.1",
48
- "@hi-ui/classname": "^5.0.0-canary.1",
49
- "@hi-ui/env": "^5.0.0-canary.1",
50
- "@hi-ui/icons": "^5.0.0-canary.1",
51
- "@hi-ui/popper": "^5.0.0-canary.2",
52
- "@hi-ui/scrollbar": "^5.0.0-canary.1",
53
- "@hi-ui/times": "^5.0.0-canary.1",
54
- "@hi-ui/tooltip": "^5.0.0-canary.2",
55
- "@hi-ui/tree-utils": "^5.0.0-canary.1",
56
- "@hi-ui/type-assertion": "^5.0.0-canary.1",
57
- "@hi-ui/use-id": "^5.0.0-canary.1",
58
- "@hi-ui/use-merge-refs": "^5.0.0-canary.1",
59
- "@hi-ui/use-resize-observer": "^5.0.0-canary.1",
60
- "@hi-ui/use-toggle": "^5.0.0-canary.1",
61
- "@hi-ui/use-uncontrolled-state": "^5.0.0-canary.1",
62
- "react-transition-group": "^4.4.2"
47
+ "@hi-ui/array-utils": "^5.0.0-canary.2",
48
+ "@hi-ui/button": "^5.0.0-canary.14",
49
+ "@hi-ui/classname": "^5.0.0-canary.2",
50
+ "@hi-ui/ellipsis-tooltip": "^5.0.0-canary.7",
51
+ "@hi-ui/env": "^5.0.0-canary.2",
52
+ "@hi-ui/highlighter": "^5.0.0-canary.5",
53
+ "@hi-ui/icon-button": "^5.0.0-canary.9",
54
+ "@hi-ui/icons": "^5.0.0-canary.10",
55
+ "@hi-ui/input": "^5.0.0-canary.19",
56
+ "@hi-ui/picker": "^5.0.0-canary.16",
57
+ "@hi-ui/popper": "^5.0.0-canary.13",
58
+ "@hi-ui/scrollbar": "^5.0.0-canary.8",
59
+ "@hi-ui/times": "^5.0.0-canary.2",
60
+ "@hi-ui/tooltip": "^5.0.0-canary.11",
61
+ "@hi-ui/tree-utils": "^5.0.0-canary.2",
62
+ "@hi-ui/type-assertion": "^5.0.0-canary.2",
63
+ "@hi-ui/use-id": "^5.0.0-canary.2",
64
+ "@hi-ui/use-latest": "^5.0.0-canary.2",
65
+ "@hi-ui/use-merge-refs": "^5.0.0-canary.2",
66
+ "@hi-ui/use-merge-semantic": "^5.0.0-canary.1",
67
+ "@hi-ui/use-outside-click": "^5.0.0-canary.2",
68
+ "@hi-ui/use-resize-observer": "^5.0.0-canary.2",
69
+ "@hi-ui/use-toggle": "^5.0.0-canary.2",
70
+ "@hi-ui/use-uncontrolled-state": "^5.0.0-canary.2",
71
+ "react-transition-group": "^4.4.5"
63
72
  },
64
73
  "peerDependencies": {
65
- "@hi-ui/core": ">=5.0.0-canary.1",
74
+ "@hi-ui/core": ">=5.0.0-canary.7",
66
75
  "react": ">=16.8.6",
67
76
  "react-dom": ">=16.8.6"
68
77
  },
69
78
  "devDependencies": {
70
- "@hi-ui/core": "^5.0.0-canary.1",
71
- "@hi-ui/core-css": "^5.0.0-canary.5",
79
+ "@hi-ui/core": "^5.0.0-canary.7",
80
+ "@hi-ui/core-css": "^5.0.0-canary.11",
72
81
  "react": "^17.0.1",
73
82
  "react-dom": "^17.0.1"
74
83
  }