Skip to content

Commit fdf27ae

Browse files
committed
feat: init project
0 parents  commit fdf27ae

14 files changed

+6257
-0
lines changed

.fatherrc.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { defineConfig } from 'father';
2+
3+
export default defineConfig({
4+
prebundle: {},
5+
esm: {
6+
input: 'src', // 默认编译目录
7+
platform: 'browser', // 默认构建为 Browser 环境的产物
8+
transformer: 'babel', // 默认使用 babel 以提供更好的兼容性
9+
},
10+
// 以下为 cjs 配置项启用时的默认值,有自定义需求时才需配置
11+
cjs: {
12+
input: 'src', // 默认编译目录
13+
platform: 'node', // 默认构建为 Node.js 环境的产物
14+
transformer: 'esbuild', // 默认使用 esbuild 以获得更快的构建速度
15+
},
16+
});

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/node_modules
2+
/dist
3+
.DS_Store

README.md

+268
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
# react-context-menu
2+
3+
[![NPM version](https://img.shields.io/npm/v/react-use-contextmenu.svg?style=flat)](https://npmjs.org/package/react-use-contextmenu)
4+
[![NPM downloads](http://img.shields.io/npm/dm/react-use-contextmenu.svg?style=flat)](https://npmjs.org/package/react-use-contextmenu)
5+
6+
## Install
7+
8+
```bash
9+
$ pnpm install react-use-contextmenu
10+
```
11+
12+
## run | build
13+
14+
```bash
15+
$ npm run dev
16+
$ npm run build
17+
```
18+
19+
20+
21+
## 为什么会有这个组件而不是用社区的
22+
23+
看了几款react生态下的相关插件,无法适配当前业务的复杂性。
24+
25+
例如:
26+
27+
28+
- 当菜单超出屏幕时需要做UI适配,会导致顶部和底部列表的选项无法全部展示
29+
- 当菜单处于局部滚动条内时,当用户滚动时,菜单也应该对应的滚动,否则无法继续操作 - 未处理
30+
- 需要适配多级菜单和动态展开,展开式也需要对UI做判断,需要适配屏幕(目前只适配了两级,多级情况太复杂了,也不知道交互要怎么搞,几乎不会出现这种情况)
31+
- 菜单禁用状态适配
32+
- 动态生成菜单
33+
34+
35+
其它社区优秀插件: [React ContextMenu](https://github.com/vkbansal/react-contextmenu/issues/339) 2020年已不维护
36+
37+
38+
# ContextMenu 组件描述
39+
40+
用于需要对该项进行多个选项操作时。
41+
42+
## 基础
43+
44+
右键菜单分为多个部分,下面是一些相关概念。你也可以基于此实现其它相关菜单的功能
45+
46+
47+
### MenuItem 数据结构
48+
49+
<API src="./index.tsx" hideTitle exports='["ContextMenuItem"]'></API>
50+
51+
### DEMO
52+
53+
```jsx
54+
import useContextMenu from 'react-use-contextmenu';
55+
import React from 'react'
56+
57+
58+
export default function MyContextMenu () {
59+
const { Trigger, ContextMenu } = useContextMenu()
60+
return <div>
61+
<Trigger data={{id: '1j24iej1h2r23'}}>我是触发器,单击我会把我的data传给右键菜单的处理函数</Trigger>
62+
<ContextMenu menus={[{ label: '操作1', value: '1' }]} onClick={(e, data, menu) => {
63+
alert(`data.id: ${data.id} menu.value: ${menu.value}`)
64+
}}/>
65+
</div>
66+
}
67+
68+
```
69+
70+
### useContextMenu
71+
72+
逻辑解耦, 只负责处理处理右键和定位逻辑, 返回的Trigger和ContextMenu是包含菜单功能逻辑的菜单和触发器,用的时候只要加一些配置即可,可配置唤醒方式,单击,右键等事件,默认右键唤醒
73+
74+
<API src="./useContextMenu.tsx" hideTitle exports='["HooksProps"]'></API>
75+
76+
77+
### Trigger 触发器
78+
79+
用来根据hooks初始化时配置的操作事件唤醒菜单和传递参数。
80+
81+
`注:为了无缝接入其它组件库,所有在Trigger上的参数都会被渲染到子元素的props上`[接入Antd Table](/components/context-menu#table列表右键菜单)
82+
83+
<API src="./useContextMenu.tsx" hideTitle exports='["TriggerProps"]'></API>
84+
85+
### ContextMenu
86+
87+
展示菜单UI的组件和对应的菜单处理函数。
88+
89+
<API src="./useContextMenu.tsx" hideTitle exports='["ContextMenuProps"]'></API>
90+
91+
## 触发方式
92+
93+
可通过初始化hooks时配置触发方式来适配其它激活操作。
94+
95+
```tsx
96+
import useContextMenu from 'react-use-contextmenu';
97+
import React from 'react'
98+
99+
100+
export default function MyContextMenu () {
101+
const { Trigger, ContextMenu } = useContextMenu({ event: 'click' })
102+
const { Trigger: Trigger2, ContextMenu: ContextMenu2 } = useContextMenu({ event: 'mousemove' })
103+
104+
return <div>
105+
<Trigger data={{id: 'click'}}>单击触发</Trigger>
106+
<ContextMenu menus={[{ label: '操作1', value: '1' }]} onClick={(e, data, menu) => {
107+
alert(`data.id: ${data.id} menu.value: ${menu.value}`)
108+
}}/>
109+
<Trigger2 data={{id: 'mousemove'}} tag="span">鼠标移动触发</Trigger2>
110+
<ContextMenu2 menus={[{ label: '操作1', value: '1' }]} onClick={(e, data, menu) => {
111+
alert(`data.id: ${data.id} menu.value: ${menu.value}`)
112+
}}/>
113+
</div>
114+
}
115+
```
116+
117+
## 多级菜单 & 异步动态加载
118+
119+
```tsx
120+
import useContextMenu from 'react-use-contextmenu';
121+
import React from 'react'
122+
import { ReloadOutlined } from '@ant-design/icons';
123+
124+
125+
export default function MyContextMenu () {
126+
const { Trigger, ContextMenu } = useContextMenu()
127+
128+
129+
return <div>
130+
<Trigger data={{id: '123'}}>右键我</Trigger>
131+
<ContextMenu menus={[{ label: '操作1', value: '1' },
132+
{
133+
label: '动态异步菜单',
134+
value: 'key2',
135+
icon: <ReloadOutlined />,
136+
children: () => {
137+
return new Promise((resolve, reject) => {
138+
setTimeout(() => {
139+
resolve([
140+
{ label: '操作2-1',
141+
value: 'key2-1'
142+
},
143+
{ label: '操作2-2',
144+
value: 'key2-2'
145+
},
146+
{ label: '操作2-3',
147+
value: 'key2-3'
148+
},
149+
{ label: '操作2-4',
150+
value: 'key2-4'
151+
}
152+
])
153+
}, 1000)
154+
})
155+
}
156+
},
157+
]} onClick={(e, data, menu) => {
158+
alert(`data.id: ${data.id} menu.value: ${menu.value}`)
159+
}}/>
160+
</div>
161+
}
162+
```
163+
164+
## Table列表右键菜单
165+
166+
无缝接入ant design [Table](https://4x.ant.design/components/table-cn/#components-table-demo-edit-row)组件, 为每项加入菜单, 重写render row方法,把所有属性同步到`Trigger`即可
167+
168+
169+
170+
```tsx
171+
import React, { useState } from 'react';
172+
import useContextMenu from 'react-use-contextmenu';
173+
import { Button, Table } from 'antd'
174+
import { ReloadOutlined } from '@ant-design/icons';
175+
176+
177+
const menus = [{
178+
label: '操作1',
179+
value: 'key1',
180+
children: [
181+
{ label: '操作1-1',
182+
value: 'key1-1',
183+
},
184+
{ label: '操作1-2',
185+
value: 'key1-2'
186+
}
187+
],
188+
icon: <ReloadOutlined />,
189+
},
190+
{
191+
label: '操作3',
192+
value: 'key3',
193+
},
194+
{
195+
label: '操作被禁用',
196+
value: 'key4',
197+
disabled: true,
198+
}]
199+
200+
export default () => {
201+
const { Trigger, ContextMenu } = useContextMenu()
202+
return <div >
203+
<ContextMenu menus={menus} onClick={(e, item, menu)=> {
204+
console.log(item, menu, '----')
205+
}}/>
206+
<Table
207+
dataSource={[
208+
{
209+
key: '1',
210+
name: '胡彦斌',
211+
age: 32,
212+
address: '西湖区湖底公园1号',
213+
},
214+
{
215+
key: '2',
216+
name: '胡彦祖',
217+
age: 42,
218+
address: '西湖区湖底公园1号',
219+
},
220+
]}
221+
columns={ [
222+
{
223+
title: '姓名',
224+
dataIndex: 'name',
225+
key: 'name',
226+
},
227+
{
228+
title: '年龄',
229+
dataIndex: 'age',
230+
key: 'age',
231+
},
232+
{
233+
title: '住址',
234+
dataIndex: 'address',
235+
key: 'address',
236+
},
237+
]}
238+
components={{
239+
body: {
240+
row: (item) => {
241+
const { index,
242+
moveRow,
243+
className,
244+
style,
245+
...restProps} = item;
246+
return <Trigger data={item} tag="tr" className={`${className}`}
247+
style={style}
248+
{...restProps}
249+
>
250+
</Trigger>
251+
}
252+
}
253+
}}
254+
/>
255+
</div>
256+
}
257+
```
258+
259+
260+
## 自定义封装
261+
262+
<Alert type="error">
263+
<span style="color: red">
264+
注:以下API适用于个人封装,与hooks用法无关,可不了解
265+
</span>
266+
</Alert>
267+
<API src="./index.tsx"></API>
268+

package.json

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"name": "react-use-contextmenu",
3+
"version": "0.0.1",
4+
"description": "react-context-menu contextmenu menu react useContextMenu",
5+
"module": "dist/esm/index.js",
6+
"types": "dist/esm/index.d.ts",
7+
"scripts": {
8+
"dev": "father dev",
9+
"build": "father build",
10+
"build:deps": "father prebundle",
11+
"prepublishOnly": "father doctor && npm run build"
12+
},
13+
"keywords": [],
14+
"authors": [
15+
"jery1997@foxmail.com"
16+
],
17+
"license": "MIT",
18+
"main": "dist/index.js",
19+
"files": [
20+
"dist",
21+
"compiled"
22+
],
23+
"publishConfig": {
24+
"access": "public"
25+
},
26+
"dependencies": {
27+
"react": "^18.2.0",
28+
"react-dom": "^18.2.0",
29+
"@babel/runtime": "^7.20.6",
30+
"@ant-design/icons": "^4.8.0"
31+
},
32+
"devDependencies": {
33+
"father": "^4.1.1",
34+
"@types/react": ">=18.0.25",
35+
"@types/react-dom": ">=18.0.9",
36+
"cross-env": "^7.0.3"
37+
}
38+
}

0 commit comments

Comments
 (0)