ソースを参照

feat: nav add renderItem support (#1249)

* feat: nav add react-router support

chore: add docs

* docs: change nav renderWrapper docs
代强 2 年 前
コミット
9637e7942e

+ 45 - 2
content/navigation/navigation/index-en-US.md

@@ -227,6 +227,47 @@ class NavApp extends React.Component {
 
 ```
 
+### Use react-router like router lib
+
+In order to use routing components such as react-router, NavItem can be wrapped in the Link or NavLink provided by the routing component to let users click NavItem to trigger the routing component. We need to customize rendering.
+
+Use renderWrapper to customize navigation components in each navigation item. [See CodeSandBox demo](https://codesandbox.io/s/semi-navigation-with-react-router-9kk9dm?file=/src/App.js)
+```jsx
+import { Link } from "react-router-dom";
+
+()=>{
+    return <Nav
+        renderWrapper={({ itemElement, isSubNav, isInSubNav, props }) => {
+            const routerMap = {
+                Home: "/",
+                About: "/about",
+                Dashboard: "/dashboard",
+                "Nothing Here": "/nothing-here"
+            };
+            return (
+                <Link
+                    style={{ textDecoration: "none" }}
+                    to={routerMap[props.itemKey]}
+                >
+                    {itemElement}
+                </Link>
+            );
+        }}
+        items={[
+            { itemKey: "Home", text: "Home" },
+            { itemKey: "About", text: "About" },
+            {
+                text: "Sub",
+
+                itemKey: "Sub",
+                items: ["Dashboard", "Nothing Here"]
+            }
+        ]}
+    ></Nav>
+}
+```
+
+
 ### Navigation Direction
 
 Navigation currently offers navigation in two directions:
@@ -688,7 +729,7 @@ function NavApp (props = {}) {
 ### Nav
 
 | Properties          | Type                                                                                                                                                                                       | Description                                                                                                                      | Default    |
-| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------- | ---------- |
+| ------------------- |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -------------------------------------------------------------------------------------------------------------------------------- | ---------- |
 | bodyStyle           | Custom style for navigation item list                                                                                                                                                      | object                                                                                                                           |            |
 | className           | Style name of outermost element                                                                                                                                                            | boolean                                                                                                                          |            |
 | defaultIsCollapsed  | Whether the default is put away, valid only when `mode = "vertical"`                                                                                                                       | boolean                                                                                                                          | false      |
@@ -698,12 +739,14 @@ function NavApp (props = {}) {
 | header              | Head area configuration objects or elements, see [Nav.Header](#Nav.Header)                                                                                                                 | object\|ReactNode                                                                                                                |            |
 | isCollapsed         | A controlled attribute of whether it is in a put-away state, valid only when `mode = "vertical"`                                                                                           | boolean                                                                                                                          |            |
 | items               | Navigate the list of items, each item can continue with the items property. If it is a string array, each item is taken as text and itemKey                                                | object\|string[]\|[Item](#Nav.Item)[]\|[Sub](#Nav.Sub)[]                                                                         |            |
-| mode                | Navigation type, currently supports horizontal and vertical, optional value: `vertical`\|`horizontal`                                                                                      | string                                                                                                                           | `vertical` |
+| mode                | Navigation type, currently supports horizontal and vertical, optional value: `vertical`\                                                                                                   |`horizontal`                                                                                      | string                                                                                                                           | `vertical` |
 | onClick             | Trigger when clicking on any navigation item                                                                                                                                               | ({ itemKey: string, domEvent: MouseEvent, isOpen: boolean }) => void                                                             | () = > {}  |
 | onCollapseChange    | The callback when the state changes.                                                                                                                                                       | (is Collapsed: boolean) => void                                                                                                  | () = > {}  |
 | onOpenChange        | Triggers when switching the hidden state of a sub navigation project                                                                                                                       | ({ itemKey: string, openKeys: string[], domEvent: MouseEvent, isOpen: boolean }) => void                                         | () = > {}  |
 | onSelect            | Triggers the first time you select an optional navigation project, where the selected Items field version > = 0.17.0 is supported                                                          | ({ itemKey: string, selectedKeys: string[], selectedItems: [Item](#Nav.Item)[], domEvent: MouseEvent, isOpen: boolean }) => void | () = > {}  |
 | openKeys            | Controlled open sub navigation `itemKey` array, expanded with `onOpenChange` callback control sub navigation items, valid only `mode = "vertical"`and the sidebar is in an unfolding state | string[]                                                                                                                         |            |
+| renderWrapper       | Custom navigation item outer component  >=2.24.0                                                                                                                                           | (data:{ itemElement:ReactElement, isSubNav:boolean, isInSubNav:boolean, props:SubNavProps\| ItemProps })=>ReactNode | |
+| prefixCls           | classsname prefix                                                                                                                                                                          | string                                                                                                                                                              | `semi`                  |
 | selectedKeys        | Controlled navigation item `itemKey` array, with `onSelect` callback control navigation item selection                                                                                     | string[]                                                                                                                         |            |
 | style               | Custom styles for outermost elements                                                                                                                                                       | object                                                                                                                           |            |
 | subNavCloseDelay    | Delay of sub navigation floating layer closure. Effective when the limit is true or mode is "limit" in MS                                                                                  | number                                                                                                                           | 100        |

+ 71 - 27
content/navigation/navigation/index.md

@@ -230,6 +230,49 @@ class NavApp extends React.Component {
 
 ```
 
+###  配合 react-router 等路由组件
+
+为了在使用 react-router 等路由组件时,能将 NavItem 包裹在路由组件提供的 Link 或者 NavLink 中来让用户点击 NavItem 时候触发路由组件的点击事件, 我们需要自定义渲染。
+
+使用 renderWrapper 在每个导航项外包裹自定义导航组件 [查看此 CodeSandBox](https://codesandbox.io/s/semi-navigation-with-react-router-9kk9dm?file=/src/App.js)
+
+```jsx
+import { Link } from "react-router-dom";
+
+()=>{
+    return <Nav
+        renderWrapper={({ itemElement, isSubNav, isInSubNav, props }) => {
+            const routerMap = {
+                Home: "/",
+                About: "/about",
+                Dashboard: "/dashboard",
+                "Nothing Here": "/nothing-here"
+            };
+            return (
+                <Link
+                    style={{ textDecoration: "none" }}
+                    to={routerMap[props.itemKey]}
+                >
+                    {itemElement}
+                </Link>
+            );
+        }}
+        items={[
+            { itemKey: "Home", text: "Home" },
+            { itemKey: "About", text: "About" },
+            {
+                text: "Sub",
+
+                itemKey: "Sub",
+                items: ["Dashboard", "Nothing Here"]
+            }
+        ]}
+    ></Nav>
+}
+```
+
+
+
 ### 导航方向
 
 Navigation 目前提供两种方向的导航:
@@ -691,33 +734,34 @@ function NavApp (props = {}) {
 
 ### Nav
 
-| 属性                | 描述                                                                                                                             | 类型                                                                                                                           | 默认值     |
-| ------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ---------- |
-| bodyStyle           | 导航项列表的自定义样式                                                                             | CSSProperties                                                                                                                           |           |
-| className           | 最外层元素的样式名                                                                               | string                                                                                                                          |           |
-| defaultIsCollapsed  | 默认是否处于收起状态,仅 `mode = "vertical"` 时有效                                                    | boolean                                                                                                                          | false     |
-| defaultOpenKeys     | 初始打开的子导航 `itemKey` 数组,仅 `mode = "vertical"` 且侧边栏处于展开状态时有效                               | string[]                                                                                                                         | []        |
-| defaultSelectedKeys | 初始选中的导航项 `itemKey` 数组                                                                   | string[]                                                                                                                         | []        |
-| footer              | 底部区域配置对象或元素,详见 [Nav.Footer](#Nav.Footer)                                                | object\| ReactNode |                      |
-| header              | 头部区域配置对象或元素,详见 [Nav.Header](#Nav.Header)                                                | object\| ReactNode |                      |
-| isCollapsed         | 是否处于收起状态的受控属性,仅 `mode = "vertical"` 时有效                                                 | boolean                                                                                                                          |           |
-| items               | 导航项目列表,每一项可以继续带有 items 属性。如果为 string 数组,则会取每一项作为 text 和 itemKey                         | object\| string[] \| [Item](#Nav.Item)[] \| [Sub](#Nav.Sub)[] |  |
-| limitIndent         | 解除缩进限制,可使用 level 自定义导航项缩进,水平模式只能为true >=1.27.0                                          | boolean                                                                                                                          | true      |
-| mode                | 导航类型,目前支持横向与竖直,可选值:`vertical`/| `horizontal`                                                                                                                     | string    | `vertical`           |
-| openKeys            | 受控的打开的子导航 `itemKey` 数组,配合 `onOpenChange` 回调控制子导航项展开,仅 `mode = "vertical"` 且侧边栏处于展开状态时有效 | string[]                                                                                                                         |           |
-| prefixCls           | 类名前缀                                                                                    | string                                                                                                                           | `semi`    |
-| selectedKeys        | 受控的导航项 `itemKey` 数组,配合 `onSelect` 回调控制导航项选择                                             | string[]                                                                                                                         |           |
-| style               | 最外层元素的自定义样式                                                                             |         CSSProperties                                                                                                                         |           |
-| subNavCloseDelay    | 子导航浮层关闭的延迟。collapse 为 true 或 mode 为 "horizontal" 时有效,单位为 ms                             | number                                                                                                                           | 100       |
-| subNavMotion        | 子导航折叠动画                                                                                 | boolean                                                                                                                          | true      |
-| subNavOpenDelay     | 子导航浮层显示的延迟。collapse 为 true 或 mode 为 "horizontal" 时有效,单位为 ms                             | number                                                                                                                           | 0         |
-| toggleIconPosition  | 带有子导航项的的父级导航项箭头位置 >=1.27.0                                                              | 'left' \| 'right'   | 'right'              |
-| tooltipHideDelay    | tooltip 隐藏的延迟,collapse 为 true 时有效,单位为 ms                                                | number                                                                                                                           | 100       |
-| tooltipShowDelay    | tooltip 显示的延迟,collapse 为 true 时有效,单位为 ms                                                | number                                                                                                                           | 0         |
-| onClick             | 点击任意导航项时触发                                                                              |<ApiType detail='({ itemKey: string, domEvent: MouseEvent, isOpen: boolean }) => void'>(itemKey, event, isOpen)=> void </ApiType>                                                                | () => {}  |
-| onCollapseChange    | 收起状态变化时的回调                                                                              |<ApiType detail='(isCollapsed: boolean) => void'>(isCollapsed)=>{} </ApiType>                                                                                                     | () => {}  |
-| onOpenChange        | 切换某个子导航项目显隐状态时触发                                                                    | <ApiType detail='({ itemKey: string, openKeys: string[], domEvent: MouseEvent, isOpen: boolean }) => void'> ({itemKey, openKeys, event, isOpen})=>{}</ApiType>                                      | () => {}  |
-| onSelect            | 第一次选中某个可选中导航项目时触发,其中 selectedItems 这个字段版本 >= 0.17.0 后才支持 | <ApiType detail='({ itemKey: string, selectedKeys: string[], selectedItems: Item[], domEvent: MouseEvent, isOpen: boolean }) => void'>(onSelectProps)=>{}</ApiType> | () => {}  |
+| 属性                  | 描述                                                                                      | 类型                                                                                                                                                                  | 默认值                     |
+|---------------------|-----------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------|
+| bodyStyle           | 导航项列表的自定义样式                                                                             | CSSProperties                                                                                                                                                       |                         |
+| className           | 最外层元素的样式名                                                                               | string                                                                                                                                                              |                         |
+| defaultIsCollapsed  | 默认是否处于收起状态,仅 `mode = "vertical"` 时有效                                                    | boolean                                                                                                                                                             | false                   |
+| defaultOpenKeys     | 初始打开的子导航 `itemKey` 数组,仅 `mode = "vertical"` 且侧边栏处于展开状态时有效                               | string[]                                                                                                                                                            | []                      |
+| defaultSelectedKeys | 初始选中的导航项 `itemKey` 数组                                                                   | string[]                                                                                                                                                            | []                      |
+| footer              | 底部区域配置对象或元素,详见 [Nav.Footer](#Nav.Footer)                                                | object\                                                                                                                                                             | ReactNode               |                      |
+| header              | 头部区域配置对象或元素,详见 [Nav.Header](#Nav.Header)                                                | object\                                                                                                                                                             | ReactNode               |                      |
+| isCollapsed         | 是否处于收起状态的受控属性,仅 `mode = "vertical"` 时有效                                                 | boolean                                                                                                                                                             |                         |
+| items               | 导航项目列表,每一项可以继续带有 items 属性。如果为 string 数组,则会取每一项作为 text 和 itemKey                         | object\                                                                                                                                                             | string[] \              | [Item](#Nav.Item)[] \| [Sub](#Nav.Sub)[] |  |
+| limitIndent         | 解除缩进限制,可使用 level 自定义导航项缩进,水平模式只能为true >=1.27.0                                          | boolean                                                                                                                                                             | true                    |
+| mode                | 导航类型,目前支持横向与竖直,可选值:`vertical`/                                                          | `horizontal`                                                                                                                                                        | string                  | `vertical`           |
+| openKeys            | 受控的打开的子导航 `itemKey` 数组,配合 `onOpenChange` 回调控制子导航项展开,仅 `mode = "vertical"` 且侧边栏处于展开状态时有效 | string[]                                                                                                                                                            |                         |
+| prefixCls           | 类名前缀                                                                                    | string                                                                                                                                                              | `semi`                  |
+| renderWrapper       | 自定义导航项外层组件  >=2.24.0                                                                    | (data:{ itemElement:ReactElement, isSubNav:boolean, isInSubNav:boolean, props:SubNavProps\| ItemProps })=>ReactNode | |
+| selectedKeys        | 受控的导航项 `itemKey` 数组,配合 `onSelect` 回调控制导航项选择                                             | string[]                                                                                                                                                            |                         |
+| style               | 最外层元素的自定义样式                                                                             | CSSProperties                                                                                                                                                       |                         |
+| subNavCloseDelay    | 子导航浮层关闭的延迟。collapse 为 true 或 mode 为 "horizontal" 时有效,单位为 ms                             | number                                                                                                                                                              | 100                     |
+| subNavMotion        | 子导航折叠动画                                                                                 | boolean                                                                                                                                                             | true                    |
+| subNavOpenDelay     | 子导航浮层显示的延迟。collapse 为 true 或 mode 为 "horizontal" 时有效,单位为 ms                             | number                                                                                                                                                              | 0                       |
+| toggleIconPosition  | 带有子导航项的的父级导航项箭头位置 >=1.27.0                                                              | 'left' \                                                                                                                                                            | 'right'                 | 'right'              |
+| tooltipHideDelay    | tooltip 隐藏的延迟,collapse 为 true 时有效,单位为 ms                                                | number                                                                                                                                                              | 100                     |
+| tooltipShowDelay    | tooltip 显示的延迟,collapse 为 true 时有效,单位为 ms                                                | number                                                                                                                                                              | 0                       |
+| onClick             | 点击任意导航项时触发                                                                              | <ApiType detail='({ itemKey: string, domEvent: MouseEvent, isOpen: boolean }) => void'>(itemKey, event, isOpen)=> void </ApiType>                                   | () => {}                |
+| onCollapseChange    | 收起状态变化时的回调                                                                              | <ApiType detail='(isCollapsed: boolean) => void'>(isCollapsed)=>{} </ApiType>                                                                                       | () => {}                |
+| onOpenChange        | 切换某个子导航项目显隐状态时触发                                                                        | <ApiType detail='({ itemKey: string, openKeys: string[], domEvent: MouseEvent, isOpen: boolean }) => void'> ({itemKey, openKeys, event, isOpen})=>{}</ApiType>      | () => {}                |
+| onSelect            | 第一次选中某个可选中导航项目时触发,其中 selectedItems 这个字段版本 >= 0.17.0 后才支持                                | <ApiType detail='({ itemKey: string, selectedKeys: string[], selectedItems: Item[], domEvent: MouseEvent, isOpen: boolean }) => void'>(onSelectProps)=>{}</ApiType> | () => {}                |
 
 ### Nav.Item
 

+ 11 - 1
packages/semi-ui/navigation/Item.tsx

@@ -34,7 +34,9 @@ export interface NavItemProps extends ItemProps, BaseProps {
     text?: React.ReactNode;
     tooltipHideDelay?: number;
     tooltipShowDelay?: number;
+
     onClick?(clickItems: SelectedData): void;
+
     onMouseEnter?: React.MouseEventHandler<HTMLLIElement>;
     onMouseLeave?: React.MouseEventHandler<HTMLLIElement>
 }
@@ -85,6 +87,7 @@ export default class NavItem extends BaseComponent<NavItemProps, NavItemState> {
 
     foundation: ItemFoundation;
     context: NavContextType;
+
     constructor(props: NavItemProps) {
         super(props);
         this.state = {
@@ -295,7 +298,14 @@ export default class NavItem extends BaseComponent<NavItemProps, NavItemState> {
         if (isCollapsed && !isInSubNav && !isSubNav || isCollapsed && isSubNav && disabled) {
             itemDom = this.wrapTooltip(itemDom);
         }
-
+        if (typeof this.context.renderWrapper === 'function') {
+            return this.context.renderWrapper({
+                itemElement: itemDom,
+                isSubNav: isSubNav,
+                isInSubNav: isInSubNav,
+                props: this.props
+            });
+        }
         return itemDom;
     }
 }

+ 7 - 4
packages/semi-ui/navigation/index.tsx

@@ -1,6 +1,6 @@
 /* eslint-disable max-lines-per-function */
 import BaseComponent, { BaseProps } from '../_base/baseComponent';
-import React, { Children } from 'react';
+import React, { Children, ReactElement, ReactNode } from 'react';
 import PropTypes from 'prop-types';
 import cls from 'classnames';
 import { noop, get, isEqual } from 'lodash';
@@ -67,7 +67,8 @@ export interface NavProps extends BaseProps {
     onCollapseChange?: (isCollapse: boolean) => void;
     onDeselect?: (data?: any) => void;
     onOpenChange?: (data: { itemKey: (string | number); openKeys: (string | number)[]; domEvent: MouseEvent; isOpen: boolean }) => void;
-    onSelect?: (data: OnSelectedData) => void
+    onSelect?: (data: OnSelectedData) => void;
+    renderWrapper?: ({ itemElement, isSubNav, isInSubNav, props }: { itemElement: ReactElement;isInSubNav:boolean; isSubNav: boolean; props: NavItemProps | SubNavProps }) => ReactNode
 }
 
 export interface NavState {
@@ -299,7 +300,8 @@ class Nav extends BaseComponent<NavProps, NavState> {
             footer,
             header,
             toggleIconPosition,
-            limitIndent
+            limitIndent,
+            renderWrapper
         } = this.props;
 
         const { selectedKeys, openKeys, items, isCollapsed } = this.state;
@@ -397,7 +399,8 @@ class Nav extends BaseComponent<NavProps, NavState> {
                             locale,
                             prefixCls,
                             toggleIconPosition,
-                            limitIndent
+                            limitIndent,
+                            renderWrapper
                         } as any}
                     >
                         <div className={finalCls} style={finalStyle}>

+ 3 - 1
packages/semi-ui/navigation/nav-context.ts

@@ -2,6 +2,7 @@ import React from 'react';
 
 import { NavProps } from './index';
 import { Locale } from '../locale/interface';
+ 
 export interface NavContextType {
     isCollapsed?: boolean;
     mode?: NavProps['mode'];
@@ -18,7 +19,8 @@ export interface NavContextType {
     subNavMotion?: NavProps['subNavMotion'];
     subNavCloseDelay?: NavProps['subNavCloseDelay'];
     subNavOpenDelay?: NavProps['subNavOpenDelay'];
-    canUpdateOpenKeys?: boolean
+    canUpdateOpenKeys?: boolean;
+    renderWrapper?: NavProps['renderWrapper']
 }
 
 const NavContext = React.createContext<NavContextType>({