@arcblock/ux 2.12.0 → 2.12.2

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.
Files changed (59) hide show
  1. package/lib/Address/responsive-did-address.d.ts +0 -1
  2. package/lib/Address/responsive-did-address.js +42 -14
  3. package/lib/Header/demo/images/boards.svg +3 -0
  4. package/lib/Header/demo/images/chatbot.svg +3 -0
  5. package/lib/Header/demo/images/gallery.svg +3 -0
  6. package/lib/NavMenu/images/OCAP.svg +16 -0
  7. package/lib/NavMenu/images/abt-network.svg +18 -0
  8. package/lib/NavMenu/images/ai-kit.svg +46 -0
  9. package/lib/NavMenu/images/aigne.svg +8 -0
  10. package/lib/NavMenu/images/aistro.svg +14 -0
  11. package/lib/NavMenu/images/blocklet-framework.svg +25 -0
  12. package/lib/NavMenu/images/blocklet-launcher.svg +9 -0
  13. package/lib/NavMenu/images/blocklet-server.svg +19 -0
  14. package/lib/NavMenu/images/blocklet-store.svg +11 -0
  15. package/lib/NavMenu/images/creator-studio.svg +42 -0
  16. package/lib/NavMenu/images/did-connect.svg +26 -0
  17. package/lib/NavMenu/images/did-name-service.svg +3 -0
  18. package/lib/NavMenu/images/did-wallet.svg +33 -0
  19. package/lib/NavMenu/images/did.svg +3 -0
  20. package/lib/NavMenu/images/nft-studio.svg +19 -0
  21. package/lib/NavMenu/images/vc.svg +7 -0
  22. package/lib/NavMenu/images/web3-kit.svg +56 -0
  23. package/lib/NavMenu/index.d.ts +1 -0
  24. package/lib/NavMenu/index.js +2 -1
  25. package/lib/NavMenu/nav-menu-context.d.ts +17 -0
  26. package/lib/NavMenu/nav-menu-context.js +19 -0
  27. package/lib/NavMenu/nav-menu.d.ts +10 -5
  28. package/lib/NavMenu/nav-menu.js +76 -36
  29. package/lib/NavMenu/products.d.ts +5 -0
  30. package/lib/NavMenu/products.js +1639 -0
  31. package/lib/NavMenu/style.d.ts +8 -3
  32. package/lib/NavMenu/style.js +215 -175
  33. package/lib/NavMenu/sub-item-group.d.ts +5 -0
  34. package/lib/NavMenu/sub-item-group.js +44 -0
  35. package/package.json +5 -5
  36. package/src/Address/responsive-did-address.tsx +40 -12
  37. package/src/NavMenu/images/OCAP.svg +16 -0
  38. package/src/NavMenu/images/abt-network.svg +18 -0
  39. package/src/NavMenu/images/ai-kit.svg +46 -0
  40. package/src/NavMenu/images/aigne.svg +8 -0
  41. package/src/NavMenu/images/aistro.svg +14 -0
  42. package/src/NavMenu/images/blocklet-framework.svg +25 -0
  43. package/src/NavMenu/images/blocklet-launcher.svg +9 -0
  44. package/src/NavMenu/images/blocklet-server.svg +19 -0
  45. package/src/NavMenu/images/blocklet-store.svg +11 -0
  46. package/src/NavMenu/images/creator-studio.svg +42 -0
  47. package/src/NavMenu/images/did-connect.svg +26 -0
  48. package/src/NavMenu/images/did-name-service.svg +3 -0
  49. package/src/NavMenu/images/did-wallet.svg +33 -0
  50. package/src/NavMenu/images/did.svg +3 -0
  51. package/src/NavMenu/images/nft-studio.svg +19 -0
  52. package/src/NavMenu/images/vc.svg +7 -0
  53. package/src/NavMenu/images/web3-kit.svg +56 -0
  54. package/src/NavMenu/index.ts +1 -0
  55. package/src/NavMenu/nav-menu-context.tsx +30 -0
  56. package/src/NavMenu/nav-menu.tsx +98 -61
  57. package/src/NavMenu/products.tsx +378 -0
  58. package/src/NavMenu/style.ts +220 -183
  59. package/src/NavMenu/sub-item-group.tsx +36 -0
@@ -0,0 +1,19 @@
1
+ <svg width="120" height="120" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path opacity="0.8" d="M14.2915 102.867C14.2915 106.298 17.8809 108.047 20.0301 105.663L74.8921 44.8061L59.56 13.3167L14.2915 13.3167L14.2915 102.867Z" fill="url(#paint0_linear_3296_9308)"></path>
3
+ <path opacity="0.8" d="M105.709 17.8485C105.709 14.4202 102.124 12.6709 99.9734 15.0499L45.1025 75.758L60.4403 107.247H105.709V17.8485Z" fill="url(#paint1_linear_3296_9308)"></path>
4
+ <path opacity="0.8" d="M105.709 107.247L59.8421 13.3167L14.2915 13.3167L60.4403 107.247H105.709Z" fill="url(#paint2_linear_3296_9308)"></path>
5
+ <defs>
6
+ <linearGradient id="paint0_linear_3296_9308" x1="58.9505" y1="13.5628" x2="1.14816" y2="99.881" gradientUnits="userSpaceOnUse">
7
+ <stop stop-color="#FF44B4"></stop>
8
+ <stop offset="1" stop-color="#FFAB48"></stop>
9
+ </linearGradient>
10
+ <linearGradient id="paint1_linear_3296_9308" x1="105.788" y1="13.5629" x2="48.8613" y2="100.72" gradientUnits="userSpaceOnUse">
11
+ <stop stop-color="#44B3FF"></stop>
12
+ <stop offset="1" stop-color="#A448FF"></stop>
13
+ </linearGradient>
14
+ <linearGradient id="paint2_linear_3296_9308" x1="38.6355" y1="11.2955" x2="95.5184" y2="102.845" gradientUnits="userSpaceOnUse">
15
+ <stop stop-color="#FF44A9"></stop>
16
+ <stop offset="1" stop-color="#7452FA"></stop>
17
+ </linearGradient>
18
+ </defs>
19
+ </svg>
@@ -0,0 +1,7 @@
1
+ <svg width="76" height="76" viewBox="0 0 76 76" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M6 15C4.89543 15 4 15.8954 4 17V20.1761H0V17C0 13.6863 2.68629 11 6 11H69.23C72.5437 11 75.23 13.6863 75.23 17V59.0689C75.23 62.3826 72.5437 65.0689 69.23 65.0689H6C2.6863 65.0689 0 62.3826 0 59.0689V56.1243H4V59.0689C4 60.1735 4.89543 61.0689 6 61.0689H69.23C70.3346 61.0689 71.23 60.1735 71.23 59.0689V17C71.23 15.8954 70.3346 15 69.23 15H6Z" fill="#4598FA"></path>
3
+ <circle cx="32" cy="31" r="10" stroke="#4598FA" stroke-width="4"></circle>
4
+ <path d="M40.6875 48.384L46.29 53.9864L56.633 43.6434" stroke="#4598FA" stroke-width="4"></path>
5
+ <path d="M49.6667 38.5692C52.9205 38.5692 55.5583 35.4039 55.5583 31.4994C55.5583 27.5948 52.9205 24.4295 49.6667 24.4295" stroke="#4598FA" stroke-width="4"></path>
6
+ <path d="M32 41L24.8527 41C20.9867 41 17.8527 44.134 17.8527 48L17.8527 55.0654" stroke="#4598FA" stroke-width="4"></path>
7
+ </svg>
@@ -0,0 +1,56 @@
1
+ <svg width="120" height="120" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <mask id="mask0_3296_9286" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0" width="120" height="120">
3
+ <rect width="119.883" height="119.883" fill="white"></rect>
4
+ </mask>
5
+ <g mask="url(#mask0_3296_9286)">
6
+ <path d="M62.0254 14.05C62.0254 11.261 64.2864 9 67.0754 9H91.0629C93.8519 9 96.1129 11.261 96.1129 14.05V74.65C96.1129 77.439 93.8519 79.7 91.0629 79.7H67.0754C64.2864 79.7 62.0254 77.439 62.0254 74.65V14.05Z" fill="url(#paint0_linear_3296_9286)"></path>
7
+ <path d="M24.1504 32.9875C24.1504 30.1985 26.4114 27.9375 29.2004 27.9375H69.6004C72.3894 27.9375 74.6504 30.1985 74.6504 32.9875V74.65C74.6504 77.439 72.3894 79.7 69.6004 79.7H29.2004C26.4114 79.7 24.1504 77.439 24.1504 74.65V32.9875Z" fill="url(#paint1_linear_3296_9286)"></path>
8
+ <g filter="url(#filter0_i_3296_9286)">
9
+ <path d="M16.5752 64.55C16.5752 58.9719 21.0971 54.45 26.6752 54.45H91.0627C96.6408 54.45 101.163 58.9719 101.163 64.55V99.8999C101.163 105.478 96.6408 110 91.0627 110H26.6752C21.0971 110 16.5752 105.478 16.5752 99.8999V64.55Z" fill="url(#paint2_linear_3296_9286)"></path>
10
+ </g>
11
+ <g filter="url(#filter1_i_3296_9286)">
12
+ <path d="M10.2627 55.7125C10.2627 51.5289 13.6541 48.1375 17.8377 48.1375H99.9002C104.084 48.1375 107.475 51.5289 107.475 55.7125V65.8124C107.475 69.996 104.084 73.3874 99.9002 73.3874H17.8377C13.6541 73.3874 10.2627 69.996 10.2627 65.8124V55.7125Z" fill="url(#paint3_linear_3296_9286)"></path>
13
+ </g>
14
+ <circle cx="58.869" cy="87.9063" r="6.94375" fill="#6BADFF"></circle>
15
+ </g>
16
+ <defs>
17
+ <filter id="filter0_i_3296_9286" x="16.5752" y="54.45" width="86.5874" height="57.55" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
18
+ <feFlood flood-opacity="0" result="BackgroundImageFix"></feFlood>
19
+ <feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"></feBlend>
20
+ <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"></feColorMatrix>
21
+ <feMorphology radius="4" operator="erode" in="SourceAlpha" result="effect1_innerShadow_3296_9286"></feMorphology>
22
+ <feOffset dx="2" dy="2"></feOffset>
23
+ <feGaussianBlur stdDeviation="3"></feGaussianBlur>
24
+ <feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"></feComposite>
25
+ <feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.25 0"></feColorMatrix>
26
+ <feBlend mode="normal" in2="shape" result="effect1_innerShadow_3296_9286"></feBlend>
27
+ </filter>
28
+ <filter id="filter1_i_3296_9286" x="10.2627" y="48.1375" width="99.2124" height="27.25" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
29
+ <feFlood flood-opacity="0" result="BackgroundImageFix"></feFlood>
30
+ <feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"></feBlend>
31
+ <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"></feColorMatrix>
32
+ <feMorphology radius="4" operator="erode" in="SourceAlpha" result="effect1_innerShadow_3296_9286"></feMorphology>
33
+ <feOffset dx="2" dy="2"></feOffset>
34
+ <feGaussianBlur stdDeviation="3"></feGaussianBlur>
35
+ <feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"></feComposite>
36
+ <feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.25 0"></feColorMatrix>
37
+ <feBlend mode="normal" in2="shape" result="effect1_innerShadow_3296_9286"></feBlend>
38
+ </filter>
39
+ <linearGradient id="paint0_linear_3296_9286" x1="86.0129" y1="9" x2="86.6441" y2="46.875" gradientUnits="userSpaceOnUse">
40
+ <stop stop-color="#FF7575"></stop>
41
+ <stop offset="1" stop-color="#C91C1C"></stop>
42
+ </linearGradient>
43
+ <linearGradient id="paint1_linear_3296_9286" x1="49.4004" y1="56.975" x2="49.4004" y2="27.9375" gradientUnits="userSpaceOnUse">
44
+ <stop stop-color="#ED7F1A"></stop>
45
+ <stop offset="1" stop-color="#FFE074"></stop>
46
+ </linearGradient>
47
+ <linearGradient id="paint2_linear_3296_9286" x1="16.5752" y1="75.2812" x2="101.163" y2="114.419" gradientUnits="userSpaceOnUse">
48
+ <stop stop-color="#54A0FD"></stop>
49
+ <stop offset="1" stop-color="#136EDE"></stop>
50
+ </linearGradient>
51
+ <linearGradient id="paint3_linear_3296_9286" x1="16.5752" y1="55.7124" x2="58.7889" y2="111.945" gradientUnits="userSpaceOnUse">
52
+ <stop stop-color="#83BAFF"></stop>
53
+ <stop offset="1" stop-color="#2482F6"></stop>
54
+ </linearGradient>
55
+ </defs>
56
+ </svg>
@@ -1,2 +1,3 @@
1
1
  // eslint-disable-next-line no-restricted-exports
2
2
  export { default } from './nav-menu';
3
+ export { default as Products } from './products';
@@ -0,0 +1,30 @@
1
+ import { createContext, useContext } from 'react';
2
+
3
+ export type NavMenuContextValue = {
4
+ activeId: string | null;
5
+ openedIds: string[];
6
+ hiddenItemCount: number;
7
+ mode: 'horizontal' | 'vertical' | 'inline';
8
+ textColor: string;
9
+ activeTextColor: string;
10
+ bgColor: string;
11
+ activate: (id: string) => void;
12
+ open: (id: string) => void;
13
+ close: (id: string) => void;
14
+ };
15
+
16
+ const NavMenuContext = createContext<NavMenuContextValue | null>(null);
17
+
18
+ export function NavMenuProvider({ value, children }: { value: NavMenuContextValue; children: React.ReactNode }) {
19
+ return <NavMenuContext.Provider value={value}>{children}</NavMenuContext.Provider>;
20
+ }
21
+
22
+ export function useNavMenuContext() {
23
+ const context = useContext(NavMenuContext);
24
+
25
+ if (!context) {
26
+ throw new Error('NavMenuContext is not found');
27
+ }
28
+
29
+ return context;
30
+ }
@@ -1,29 +1,11 @@
1
- import {
2
- Children,
3
- cloneElement,
4
- useEffect,
5
- createContext,
6
- useContext,
7
- useRef,
8
- forwardRef,
9
- useLayoutEffect,
10
- isValidElement,
11
- } from 'react';
1
+ import { Children, cloneElement, useEffect, useRef, forwardRef, useLayoutEffect, isValidElement } from 'react';
12
2
  import { type SxProps } from '@mui/material';
13
3
  import clsx from 'clsx';
14
4
  import { MoreHoriz as MoreHorizIcon, ExpandMore as ExpandMoreIcon, Menu as MenuIcon } from '@mui/icons-material';
5
+ import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
15
6
  import { useCreation, useMemoizedFn, useReactive, useSize, useThrottleFn } from 'ahooks';
16
- import { HorizontalStyle, InlineStyle } from './style';
17
-
18
- const NavMenuContext = createContext<{
19
- activeId: string | null;
20
- openedIds: string[];
21
- hiddenItemCount: number;
22
- mode: 'horizontal' | 'vertical' | 'inline';
23
- activate: (id: string) => void;
24
- open: (id: string) => void;
25
- close: (id: string) => void;
26
- } | null>(null);
7
+ import { NavMenuProvider, useNavMenuContext } from './nav-menu-context';
8
+ import { NavMenuRoot, NavMenuList, NavMenuItem, NavMenuSub, NavMenuSubList } from './style';
27
9
 
28
10
  // 过滤 children 中的 Item/Sub, 忽略其它类型的 element
29
11
  function filterItems(children: React.ReactNode) {
@@ -48,7 +30,9 @@ export type ItemOptions = {
48
30
  id?: string;
49
31
  icon?: React.ReactNode;
50
32
  label?: React.ReactNode;
33
+ description?: React.ReactNode;
51
34
  active?: boolean;
35
+ variant?: 'default' | 'panel';
52
36
  children?: ItemOptions[];
53
37
  };
54
38
 
@@ -105,11 +89,25 @@ function NavMenu({
105
89
  return {
106
90
  ...currentState,
107
91
  mode,
92
+ textColor,
93
+ activeTextColor,
94
+ bgColor,
108
95
  activate,
109
96
  open,
110
97
  close,
111
98
  };
112
- }, [currentState.activeId, currentState.hiddenItemCount, currentState.openedIds, mode, activate, open, close]);
99
+ }, [
100
+ currentState.activeId,
101
+ currentState.hiddenItemCount,
102
+ currentState.openedIds,
103
+ mode,
104
+ textColor,
105
+ activeTextColor,
106
+ bgColor,
107
+ activate,
108
+ open,
109
+ close,
110
+ ]);
113
111
 
114
112
  const navMenuRef = useRef<HTMLUListElement | null>(null);
115
113
  const itemRefs = useRef<HTMLElement[]>([]);
@@ -206,6 +204,7 @@ function NavMenu({
206
204
  id={item.id}
207
205
  icon={item.icon}
208
206
  label={item.label}
207
+ variant={isTopLevel ? 'default' : 'panel'}
209
208
  ref={
210
209
  isTopLevel
211
210
  ? (el) => {
@@ -213,7 +212,11 @@ function NavMenu({
213
212
  }
214
213
  : undefined
215
214
  }>
216
- {item.children.map((childItem, childIndex: number) => renderItem(childItem, childIndex, false))}
215
+ {typeof item.children === 'function'
216
+ ? item.children
217
+ : item.children.map((childItem, childIndex: number) =>
218
+ renderItem({ ...childItem, variant: 'panel' }, childIndex, false)
219
+ )}
217
220
  </Sub>
218
221
  );
219
222
  }
@@ -225,7 +228,9 @@ function NavMenu({
225
228
  id={item.id}
226
229
  icon={item.icon}
227
230
  label={item.label}
231
+ description={item.description}
228
232
  active={item.active}
233
+ variant={item.variant}
229
234
  ref={
230
235
  isTopLevel
231
236
  ? (el) => {
@@ -241,26 +246,19 @@ function NavMenu({
241
246
  ? items?.slice(-currentState.hiddenItemCount).map((item, index) => renderItem(item, index))
242
247
  : children?.slice(-currentState.hiddenItemCount);
243
248
 
244
- const StyledRoot = mode === 'inline' ? InlineStyle : HorizontalStyle;
245
-
246
249
  return (
247
- <NavMenuContext.Provider value={contextValue}>
248
- <StyledRoot
249
- {...rest}
250
- className={classes}
251
- $textColor={textColor}
252
- $activeTextColor={activeTextColor}
253
- $bgColor={bgColor}>
254
- <ul className="navmenu-root" ref={navMenuRef}>
250
+ <NavMenuProvider value={contextValue}>
251
+ <NavMenuRoot {...rest} className={classes} $textColor={textColor} $bgColor={bgColor}>
252
+ <NavMenuList className={clsx('navmenu-list', `navmenu-list--${mode}`)} ref={navMenuRef}>
255
253
  {items ? items.map((item, index) => renderItem(item, index, true)) : renderChildrenWithRef(children || [])}
256
254
  {currentState.hiddenItemCount > 0 && (
257
255
  <Sub expandIcon={false} icon={icon} label="" ref={moreIconRef} style={style}>
258
256
  {content}
259
257
  </Sub>
260
258
  )}
261
- </ul>
262
- </StyledRoot>
263
- </NavMenuContext.Provider>
259
+ </NavMenuList>
260
+ </NavMenuRoot>
261
+ </NavMenuProvider>
264
262
  );
265
263
  }
266
264
 
@@ -268,16 +266,35 @@ export interface ItemProps extends React.HTMLAttributes<HTMLLIElement> {
268
266
  id?: string;
269
267
  icon?: React.ReactNode;
270
268
  label?: React.ReactNode;
269
+ description?: React.ReactNode;
271
270
  active?: boolean;
271
+ variant?: 'default' | 'panel';
272
272
  onClick?: () => void;
273
273
  }
274
274
 
275
- const Item = forwardRef<HTMLLIElement, ItemProps>(
276
- ({ id: _id = '', icon = null, label = '', active = false, onClick = null, ...rest }, ref) => {
275
+ export const Item = forwardRef<HTMLLIElement, ItemProps>(
276
+ (
277
+ {
278
+ id: _id = '',
279
+ icon = null,
280
+ label = '',
281
+ description,
282
+ active = false,
283
+ variant = 'default',
284
+ onClick = null,
285
+ ...rest
286
+ },
287
+ ref
288
+ ) => {
277
289
  const id = useUniqueId(_id);
278
- const { activeId, activate } = useContext(NavMenuContext) || {};
279
- const classes = clsx('navmenu-item', { 'navmenu-item--active': activeId === id }, rest.className);
280
-
290
+ const { mode, activeId, activate, activeTextColor } = useNavMenuContext();
291
+ const classes = clsx(
292
+ 'navmenu-item',
293
+ { 'navmenu-item--active': activeId === id },
294
+ `navmenu-item--${mode}`,
295
+ `navmenu-item--${variant}`,
296
+ rest.className
297
+ );
281
298
  useEffect(() => {
282
299
  if (active) {
283
300
  activate?.(id);
@@ -292,28 +309,33 @@ const Item = forwardRef<HTMLLIElement, ItemProps>(
292
309
 
293
310
  return (
294
311
  // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
295
- <li {...rest} className={classes} onClick={handleClick} ref={ref}>
296
- {icon && <span className="navmenu-item-icon">{icon}</span>}
297
- <span className="navmenu-item-label">{label}</span>
298
- </li>
312
+ <NavMenuItem {...rest} className={classes} ref={ref} $activeTextColor={activeTextColor} onClick={handleClick}>
313
+ {icon && <span className="navmenu-item__icon">{icon}</span>}
314
+ <div className="navmenu-item__content">
315
+ <span className="navmenu-item__label">
316
+ {label} <ArrowForwardIcon className="navmenu-item__label-arrow" />
317
+ </span>
318
+ {description && <span className="navmenu-item__desc">{description}</span>}
319
+ </div>
320
+ </NavMenuItem>
299
321
  );
300
322
  }
301
323
  );
324
+ Item.displayName = 'NavMenu.Item';
302
325
 
303
- export interface SubProps extends React.HTMLAttributes<HTMLLIElement> {
304
- id?: string;
305
- icon?: React.ReactNode;
306
- label?: React.ReactNode;
307
- children?: Array<React.ReactElement>;
326
+ export interface SubProps extends Omit<ItemProps, 'children' | 'active'> {
327
+ children?: Array<React.ReactElement> | ((props: { isOpen: boolean }) => React.ReactElement | null);
308
328
  expandIcon?: React.ReactNode | ((props: { isOpen: boolean }) => React.ReactNode);
309
329
  }
310
330
 
311
- const Sub = forwardRef<HTMLLIElement, SubProps>(
331
+ export const Sub = forwardRef<HTMLLIElement, SubProps>(
312
332
  (
313
333
  {
314
334
  id: _id = '',
315
335
  icon = null,
316
336
  label = null,
337
+ description,
338
+ variant = 'default',
317
339
  children,
318
340
  expandIcon = ({ isOpen }) => (
319
341
  <ExpandMoreIcon
@@ -327,10 +349,17 @@ const Sub = forwardRef<HTMLLIElement, SubProps>(
327
349
  ref
328
350
  ) => {
329
351
  const id = useUniqueId(_id);
330
- const { openedIds, open, close, mode } = useContext(NavMenuContext) || {};
352
+ const { openedIds, open, close, mode, activeTextColor } = useNavMenuContext();
331
353
  const isOpen = openedIds?.includes(id) ?? false;
332
- const classes = clsx('navmenu-sub', { 'navmenu-sub--opened': isOpen }, rest.className);
333
354
  const isInlineMode = mode === 'inline';
355
+ const classes = clsx(
356
+ 'navmenu-sub',
357
+ 'navmenu-item',
358
+ { 'navmenu-item--panel': variant === 'panel' },
359
+ { 'navmenu-sub--opened': isOpen, 'navmenu-item--inline': isInlineMode },
360
+ rest.className
361
+ );
362
+
334
363
  // inline mode 时使用 click 事件控制收缩/伸展子菜单
335
364
  const props = isInlineMode
336
365
  ? {
@@ -354,21 +383,29 @@ const Sub = forwardRef<HTMLLIElement, SubProps>(
354
383
  : {};
355
384
 
356
385
  return (
357
- <li {...rest} className={classes} {...props} ref={ref}>
358
- {icon && <span className="navmenu-sub-icon">{icon}</span>}
359
- <span className="navmenu-sub-label">{label}</span>
386
+ <NavMenuSub {...rest} className={classes} {...props} ref={ref} $activeTextColor={activeTextColor}>
387
+ {icon && <span className="navmenu-item__icon">{icon}</span>}
388
+ <div className="navmenu-item__content">
389
+ <span className="navmenu-item__label">{label}</span>
390
+ {description && <span className="navmenu-item__desc">{description}</span>}
391
+ </div>
360
392
  {expandIcon && (
361
- <span className="navmenu-sub-expand-icon">
393
+ <span className="navmenu-sub__expand-icon">
362
394
  {typeof expandIcon === 'function' ? expandIcon({ isOpen }) : expandIcon}
363
395
  </span>
364
396
  )}
365
- <div className="navmenu-sub-container" {...containerProps}>
366
- <ul className="navmenu-sub-list">{filterItems(children)}</ul>
397
+ <div className="navmenu-sub__container" {...containerProps}>
398
+ {typeof children === 'function' ? (
399
+ children({ isOpen }) // 自定义渲染
400
+ ) : (
401
+ <NavMenuSubList className="navmenu-sub__list">{filterItems(children)}</NavMenuSubList>
402
+ )}
367
403
  </div>
368
- </li>
404
+ </NavMenuSub>
369
405
  );
370
406
  }
371
407
  );
408
+ Sub.displayName = 'NavMenu.Sub';
372
409
 
373
410
  NavMenu.Item = Item;
374
411
  NavMenu.Sub = Sub;