ding-react-admin 2.1.0 → 2.2.1

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.
@@ -1,8 +1,17 @@
1
+ import { FlatNavItem } from '../layouts/navFilter';
1
2
  import { NavItem } from '../types';
2
3
  export type AppHubProps = {
3
4
  apps: NavItem[];
5
+ /** Flattened leaf menus from all apps — enables cross-app search when set. */
6
+ menuItems?: FlatNavItem[];
4
7
  onAppClick?: (app: NavItem) => void;
8
+ onMenuClick?: (item: FlatNavItem) => void;
9
+ menuSearchPlaceholder?: string;
5
10
  className?: string;
11
+ /** Max width of the centered hub content. Default `960`. */
12
+ maxWidth?: number;
13
+ /** When true, shows a centered spinner instead of the app grid. */
14
+ loading?: boolean;
6
15
  };
7
- export declare function AppHub({ apps, onAppClick, className }: AppHubProps): import("react/jsx-runtime").JSX.Element;
16
+ export declare function AppHub({ apps, menuItems, onAppClick, onMenuClick, menuSearchPlaceholder, className, maxWidth, loading, }: AppHubProps): import("react/jsx-runtime").JSX.Element;
8
17
  //# sourceMappingURL=AppHub.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AppHub.d.ts","sourceRoot":"","sources":["../../../src/components/AppHub.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAExC,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,wBAAgB,MAAM,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,WAAW,2CAoClE"}
1
+ {"version":3,"file":"AppHub.d.ts","sourceRoot":"","sources":["../../../src/components/AppHub.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAGxC,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,8EAA8E;IAC9E,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC;IAC1B,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IACpC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IAC1C,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,wBAAgB,MAAM,CAAC,EACrB,IAAI,EACJ,SAAS,EACT,UAAU,EACV,WAAW,EACX,qBAAmD,EACnD,SAAS,EACT,QAAc,EACd,OAAe,GAChB,EAAE,WAAW,2CA+Gb"}
@@ -17,6 +17,8 @@ export { applyInMemoryListParams, filterRows, getById as getRowById, } from './d
17
17
  export type { CombineResourceHandlersOptions, ResourceAction, ResourceGuard, ResourceHandlerEntry, ResourceHandlerMap, ResourceHandlers, } from './data/resourceHandlers';
18
18
  export type { ResourcePermissions } from './permissions/resourcePermissions';
19
19
  export { filterNavByPermission } from './permissions/resourcePermissions';
20
+ export { flattenNavLeaves, filterFlatNavItems, filterNavItems, getNavItemLabel, } from './layouts/navFilter';
21
+ export type { FlatNavItem } from './layouts/navFilter';
20
22
  export type { MemoryResourceHandlersConfig } from './data/createMemoryResourceHandlers';
21
23
  export type { PermissionsChecker } from './context/PermissionsProvider';
22
24
  export { LoginPage } from './pages/LoginPage';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EACL,YAAY,EACZ,+BAA+B,EAC/B,OAAO,EACP,KAAK,iBAAiB,GACvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,YAAY,EACZ,eAAe,EACf,KAAK,iBAAiB,GACvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,MAAM,EACN,cAAc,EACd,KAAK,wBAAwB,GAC9B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,gBAAgB,EAChB,YAAY,GACb,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,YAAY,EACZ,YAAY,IAAI,oBAAoB,EACpC,YAAY,EACZ,aAAa,EACb,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,mBAAmB,EACnB,YAAY,EACZ,gBAAgB,EAChB,wBAAwB,EACxB,gBAAgB,EAChB,kBAAkB,EAClB,iCAAiC,EACjC,6BAA6B,GAC9B,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,4BAA4B,EAAE,MAAM,qCAAqC,CAAC;AACnF,OAAO,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAC/E,YAAY,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AACpF,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,aAAa,GACd,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,uBAAuB,EACvB,UAAU,EACV,OAAO,IAAI,UAAU,GACtB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,8BAA8B,EAC9B,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,YAAY,EAAE,4BAA4B,EAAE,MAAM,qCAAqC,CAAC;AACxF,YAAY,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EACL,MAAM,EACN,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,YAAY,GACb,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EACL,eAAe,EACf,cAAc,EACd,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,WAAW,EACX,gBAAgB,EAChB,aAAa,EACb,wBAAwB,EACxB,WAAW,EACX,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,cAAc,EACd,OAAO,EACP,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,SAAS,GACV,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,oBAAoB,EACpB,QAAQ,EACR,OAAO,EACP,SAAS,EACT,QAAQ,EACR,SAAS,EACT,aAAa,EACb,WAAW,EACX,YAAY,EACZ,SAAS,EACT,aAAa,EACb,SAAS,EACT,WAAW,EACX,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,UAAU,EACV,SAAS,EACT,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,aAAa,EACb,UAAU,EACV,eAAe,EACf,mBAAmB,EACnB,WAAW,EACX,YAAY,EACZ,UAAU,EACV,+BAA+B,EAC/B,YAAY,EACZ,aAAa,EACb,UAAU,EACV,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,UAAU,EACV,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,sBAAsB,EACtB,2BAA2B,EAC3B,qBAAqB,EACrB,UAAU,EACV,eAAe,EACf,eAAe,EACf,sBAAsB,EACtB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,QAAQ,CAAC;AAChB,YAAY,EACV,iBAAiB,EACjB,sBAAsB,EACtB,kBAAkB,EAClB,yBAAyB,EACzB,aAAa,EACb,YAAY,EACZ,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,uBAAuB,EACvB,YAAY,EACZ,QAAQ,EACR,UAAU,EACV,iBAAiB,EACjB,eAAe,EACf,sBAAsB,EACtB,gBAAgB,EAChB,uBAAuB,EACvB,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,4BAA4B,EAC5B,0BAA0B,EAC1B,sBAAsB,EACtB,6BAA6B,EAC7B,6BAA6B,EAC7B,cAAc,EACd,gBAAgB,GACjB,MAAM,QAAQ,CAAC"}
@@ -1,5 +1,17 @@
1
+ import { ReactNode } from 'react';
1
2
  import { NavItem } from '../types';
2
- export declare function getNavItemLabel(item: NavItem): string;
3
+ export type FlatNavItem = {
4
+ path: string;
5
+ label: ReactNode;
6
+ group?: string;
7
+ Icon?: NavItem["Icon"];
8
+ };
9
+ export declare function getNavItemLabel(item: Pick<NavItem, "label">): string;
3
10
  export declare function filterNavItems(items: NavItem[], query: string): NavItem[];
11
+ /** Leaf menu rows from a nav tree, optionally tagged with an app/group name. */
12
+ export declare function flattenNavLeaves(items: NavItem[], options?: {
13
+ group?: string;
14
+ }): FlatNavItem[];
15
+ export declare function filterFlatNavItems(items: FlatNavItem[], query: string): FlatNavItem[];
4
16
  export declare function collectSubmenuKeys(items: NavItem[]): string[];
5
17
  //# sourceMappingURL=navFilter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"navFilter.d.ts","sourceRoot":"","sources":["../../../src/layouts/navFilter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAExC,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAKrD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,EAAE,CAyBzE;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,CAY7D"}
1
+ {"version":3,"file":"navFilter.d.ts","sourceRoot":"","sources":["../../../src/layouts/navFilter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAExC,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;CACxB,CAAC;AAEF,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,MAAM,CAKpE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,EAAE,CAyBzE;AAED,gFAAgF;AAChF,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,OAAO,EAAE,EAChB,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3B,WAAW,EAAE,CAqBf;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,WAAW,EAAE,EACpB,KAAK,EAAE,MAAM,GACZ,WAAW,EAAE,CASf;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,CAY7D"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ding-react-admin",
3
- "version": "2.1.0",
3
+ "version": "2.2.1",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Composable admin shell (Ant Design + React Router): quick-start AdminApp or build your own layout.",
@@ -1,17 +1,43 @@
1
- import { Card, Col, Row, Space, Typography } from "antd";
1
+ import { Card, Col, List, Row, Space, Spin, Typography, theme } from "antd";
2
+ import { useMemo, useState } from "react";
2
3
  import { useNavigate } from "react-router-dom";
4
+ import {
5
+ filterFlatNavItems,
6
+ getNavItemLabel,
7
+ } from "../layouts/navFilter";
8
+ import type { FlatNavItem } from "../layouts/navFilter";
3
9
  import type { NavItem } from "../types";
10
+ import { NavMenuSearch } from "./NavMenuSearch";
4
11
 
5
12
  export type AppHubProps = {
6
13
  apps: NavItem[];
14
+ /** Flattened leaf menus from all apps — enables cross-app search when set. */
15
+ menuItems?: FlatNavItem[];
7
16
  onAppClick?: (app: NavItem) => void;
17
+ onMenuClick?: (item: FlatNavItem) => void;
18
+ menuSearchPlaceholder?: string;
8
19
  className?: string;
20
+ /** Max width of the centered hub content. Default `960`. */
21
+ maxWidth?: number;
22
+ /** When true, shows a centered spinner instead of the app grid. */
23
+ loading?: boolean;
9
24
  };
10
25
 
11
- export function AppHub({ apps, onAppClick, className }: AppHubProps) {
26
+ export function AppHub({
27
+ apps,
28
+ menuItems,
29
+ onAppClick,
30
+ onMenuClick,
31
+ menuSearchPlaceholder = "Search menus across apps…",
32
+ className,
33
+ maxWidth = 960,
34
+ loading = false,
35
+ }: AppHubProps) {
12
36
  const navigate = useNavigate();
37
+ const { token } = theme.useToken();
38
+ const [query, setQuery] = useState("");
13
39
 
14
- const handleClick = (app: NavItem) => {
40
+ const handleAppClick = (app: NavItem) => {
15
41
  if (onAppClick) {
16
42
  onAppClick(app);
17
43
  return;
@@ -19,29 +45,102 @@ export function AppHub({ apps, onAppClick, className }: AppHubProps) {
19
45
  navigate(app.path);
20
46
  };
21
47
 
48
+ const handleMenuClick = (item: FlatNavItem) => {
49
+ if (onMenuClick) {
50
+ onMenuClick(item);
51
+ return;
52
+ }
53
+ navigate(item.path);
54
+ };
55
+
56
+ const trimmedQuery = query.trim();
57
+ const menuResults = useMemo(
58
+ () =>
59
+ menuItems && trimmedQuery
60
+ ? filterFlatNavItems(menuItems, trimmedQuery)
61
+ : [],
62
+ [menuItems, trimmedQuery],
63
+ );
64
+ const isSearching = Boolean(menuItems && trimmedQuery);
65
+
22
66
  return (
23
- <Row gutter={[16, 16]} className={className}>
24
- {apps.map((app) => {
25
- const Icon = app.Icon;
26
- return (
27
- <Col key={app.path} xs={12} sm={8} md={6} lg={4}>
28
- <Card
29
- hoverable
30
- onClick={() => handleClick(app)}
31
- styles={{ body: { textAlign: "center" } }}
32
- >
33
- <Space orientation="vertical" size="small">
34
- {Icon ? (
35
- <span style={{ fontSize: 32, lineHeight: 1 }}>
36
- <Icon />
37
- </span>
38
- ) : null}
39
- <Typography.Text strong>{app.label}</Typography.Text>
40
- </Space>
41
- </Card>
42
- </Col>
43
- );
44
- })}
45
- </Row>
67
+ <div
68
+ className={className}
69
+ style={{
70
+ width: "100%",
71
+ maxWidth,
72
+ marginInline: "auto",
73
+ paddingInline: token.paddingMD,
74
+ }}
75
+ >
76
+ {menuItems?.length && !loading ? (
77
+ <div style={{ maxWidth: 480, margin: "0 auto 24px" }}>
78
+ <NavMenuSearch
79
+ value={query}
80
+ onChange={setQuery}
81
+ placeholder={menuSearchPlaceholder}
82
+ variant="app"
83
+ />
84
+ </div>
85
+ ) : null}
86
+
87
+ {loading ? (
88
+ <div style={{ display: "flex", justifyContent: "center", padding: token.paddingXL }}>
89
+ <Spin size="large" />
90
+ </div>
91
+ ) : isSearching ? (
92
+ <List
93
+ bordered
94
+ dataSource={menuResults}
95
+ locale={{ emptyText: "No menus match your search." }}
96
+ style={{ background: token.colorBgContainer, borderRadius: token.borderRadiusLG }}
97
+ renderItem={(item) => {
98
+ const Icon = item.Icon;
99
+ return (
100
+ <List.Item
101
+ style={{ cursor: "pointer" }}
102
+ onClick={() => handleMenuClick(item)}
103
+ >
104
+ <List.Item.Meta
105
+ avatar={
106
+ Icon ? (
107
+ <span style={{ fontSize: 20, lineHeight: 1 }}>
108
+ <Icon />
109
+ </span>
110
+ ) : undefined
111
+ }
112
+ title={getNavItemLabel(item)}
113
+ description={item.group}
114
+ />
115
+ </List.Item>
116
+ );
117
+ }}
118
+ />
119
+ ) : (
120
+ <Row gutter={[16, 16]} justify="center">
121
+ {apps.map((app) => {
122
+ const Icon = app.Icon;
123
+ return (
124
+ <Col key={app.path} xs={12} sm={8} md={6} lg={4} style={{ maxWidth: 200 }}>
125
+ <Card
126
+ hoverable
127
+ onClick={() => handleAppClick(app)}
128
+ styles={{ body: { textAlign: "center", padding: token.paddingLG } }}
129
+ >
130
+ <Space orientation="vertical" size="middle">
131
+ {Icon ? (
132
+ <span style={{ fontSize: 40, lineHeight: 1 }}>
133
+ <Icon />
134
+ </span>
135
+ ) : null}
136
+ <Typography.Text strong>{app.label}</Typography.Text>
137
+ </Space>
138
+ </Card>
139
+ </Col>
140
+ );
141
+ })}
142
+ </Row>
143
+ )}
144
+ </div>
46
145
  );
47
146
  }
package/src/index.ts CHANGED
@@ -83,6 +83,13 @@ export type {
83
83
  } from "./data/resourceHandlers";
84
84
  export type { ResourcePermissions } from "./permissions/resourcePermissions";
85
85
  export { filterNavByPermission } from "./permissions/resourcePermissions";
86
+ export {
87
+ flattenNavLeaves,
88
+ filterFlatNavItems,
89
+ filterNavItems,
90
+ getNavItemLabel,
91
+ } from "./layouts/navFilter";
92
+ export type { FlatNavItem } from "./layouts/navFilter";
86
93
  export type { MemoryResourceHandlersConfig } from "./data/createMemoryResourceHandlers";
87
94
  export type { PermissionsChecker } from "./context/PermissionsProvider";
88
95
  export { LoginPage } from "./pages/LoginPage";
@@ -1,6 +1,14 @@
1
+ import type { ReactNode } from "react";
1
2
  import type { NavItem } from "../types";
2
3
 
3
- export function getNavItemLabel(item: NavItem): string {
4
+ export type FlatNavItem = {
5
+ path: string;
6
+ label: ReactNode;
7
+ group?: string;
8
+ Icon?: NavItem["Icon"];
9
+ };
10
+
11
+ export function getNavItemLabel(item: Pick<NavItem, "label">): string {
4
12
  const { label } = item;
5
13
  if (typeof label === "string") return label;
6
14
  if (typeof label === "number") return String(label);
@@ -34,6 +42,47 @@ export function filterNavItems(items: NavItem[], query: string): NavItem[] {
34
42
  return walk(items);
35
43
  }
36
44
 
45
+ /** Leaf menu rows from a nav tree, optionally tagged with an app/group name. */
46
+ export function flattenNavLeaves(
47
+ items: NavItem[],
48
+ options?: { group?: string },
49
+ ): FlatNavItem[] {
50
+ const group = options?.group;
51
+ const result: FlatNavItem[] = [];
52
+
53
+ function walk(nodes: NavItem[]) {
54
+ for (const node of nodes) {
55
+ if (node.children?.length) {
56
+ walk(node.children);
57
+ } else {
58
+ result.push({
59
+ path: node.path,
60
+ label: node.label,
61
+ Icon: node.Icon,
62
+ group,
63
+ });
64
+ }
65
+ }
66
+ }
67
+
68
+ walk(items);
69
+ return result;
70
+ }
71
+
72
+ export function filterFlatNavItems(
73
+ items: FlatNavItem[],
74
+ query: string,
75
+ ): FlatNavItem[] {
76
+ const q = query.trim().toLowerCase();
77
+ if (!q) return [];
78
+
79
+ return items.filter((item) => {
80
+ const label = getNavItemLabel(item).toLowerCase();
81
+ const group = (item.group ?? "").toLowerCase();
82
+ return label.includes(q) || group.includes(q);
83
+ });
84
+ }
85
+
37
86
  export function collectSubmenuKeys(items: NavItem[]): string[] {
38
87
  const keys: string[] = [];
39
88
  function walk(nodes: NavItem[]) {