npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@jeryqwq/react-use-contextmenu

v0.0.23

Published

react-context-menu contextmenu menu react useContextMenu

Downloads

2

Readme

react-context-menu

NPM version NPM downloads

Install

$ pnpm install @jeryqwq/react-use-contextmenu

run | build

$ npm run dev
$ npm run build

为什么会有这个组件而不是用社区的

看了几款react生态下的相关插件,无法适配当前业务的复杂性。

例如:

  • 当菜单超出屏幕时需要做UI适配,会导致顶部和底部列表的选项无法全部展示
  • 当菜单处于局部滚动条内时,当用户滚动时,菜单也应该对应的滚动,否则无法继续操作 - 未处理
  • 需要适配多级菜单和动态展开,展开式也需要对UI做判断,需要适配屏幕
  • 菜单禁用状态适配
  • 动态生成菜单

其它社区优秀插件: React ContextMenu 2020年已不维护

ContextMenu 组件描述

用于需要对该项进行多个功能选项操作时, 包含有禁用,多级,动态加载,列表右键菜单等,可以使用右键菜单进行对应的操作和展示。

基础

右键菜单分为多个部分,下面是一些相关概念。你也可以基于此实现其它相关菜单的功能

MenuItem 数据结构

DEMO

import useContextMenu from '@jeryqwq/react-use-contextmenu';
import React from 'react'


export default function MyContextMenu () {
  const { Trigger, ContextMenu } = useContextMenu()
  return <div>
    <Trigger data={{id: '1j24iej1h2r23'}}>我是触发器,单击我会把我的data传给右键菜单的处理函数</Trigger>
    <ContextMenu menus={[{ label: '操作1', value: '1' }]} onClick={(e, data, menu) => {
      alert(`data.id: ${data.id} menu.value: ${menu.value}`)
    }}/>
  </div>
}

useContextMenu

逻辑解耦, 只负责处理处理右键和定位逻辑, 返回的Trigger和ContextMenu是包含菜单功能逻辑的菜单和触发器,用的时候只要加一些配置即可,可配置唤醒方式,单击,右键等事件,默认右键唤醒

Trigger 触发器

用来根据hooks初始化时配置的操作事件唤醒菜单和传递参数。

注:为了无缝接入其它组件库,所有在Trigger上的参数都会被渲染到子元素的props上接入Antd Table

ContextMenu

展示菜单UI的组件和对应的菜单处理函数。

触发方式

可通过初始化hooks时配置触发方式来适配其它激活操作。

import useContextMenu from '@jeryqwq/react-use-contextmenu';
import React from 'react'


export default function MyContextMenu () {
  const { Trigger, ContextMenu } = useContextMenu({ event: 'click' })
  const { Trigger: Trigger2, ContextMenu: ContextMenu2 } = useContextMenu({ event: 'mousemove' })

  return <div>
    <Trigger data={{id: 'click'}}>单击触发</Trigger>
    <ContextMenu menus={[{ label: '操作1', value: '1' }]} onClick={(e, data, menu) => {
      alert(`data.id: ${data.id} menu.value: ${menu.value}`)
    }}/>
    <Trigger2 data={{id: 'mousemove'}} tag="span">鼠标移动触发</Trigger2>
    <ContextMenu2 menus={[{ label: '操作1', value: '1' }]} onClick={(e, data, menu) => {
      alert(`data.id: ${data.id} menu.value: ${menu.value}`)
    }}/>
  </div>
}

多级菜单 & 异步动态加载

import useContextMenu from '@jeryqwq/react-use-contextmenu';
import React from 'react'
import { ReloadOutlined } from '@ant-design/icons';


export default function MyContextMenu () {
  const { Trigger, ContextMenu } = useContextMenu()


  return <div>
    <Trigger data={{id: '123'}}>右键我</Trigger>
    <ContextMenu menus={[{ label: '操作1', value: '1' },
    {
  label: '动态异步菜单',
  value: 'key2',
  icon: <ReloadOutlined />,
  children: () => {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve([
          { label: '操作2-1',
            value: 'key2-1'
          },
          { label: '操作2-2',
            value: 'key2-2'
          },
          { label: '操作2-3',
            value: 'key2-3'
          },
          { label: '操作2-4',
            value: 'key2-4'
          }
        ])
      }, 1000)
    })
  }
},
    ]} onClick={(e, data, menu) => {
      alert(`data.id: ${data.id} menu.value: ${menu.value}`)
    }}/>
  </div>
}

已存在DOM节点触发

给任意已渲染的dom添加触发器

import useContextMenu from '@jeryqwq/react-use-contextmenu';
import React, { useState, useLayoutEffect } from 'react'

export default function MyContextMenu () {
  const { Trigger, ContextMenu } = useContextMenu()

  return <div>
    <Trigger data={{id: '1j24iej1h2r23'}} getEl={() => { return document.getElementsByClassName('any class name')[0] }}></Trigger>
    <ContextMenu menus={[{ label: '操作1', value: '1' }]} onClick={(e, data, menu) => {
      alert(`data.id: ${data.id} menu.value: ${menu.value}`)
    }}/>
  </div>
}

Antd Table列表右键菜单

无缝接入ant design Table组件, 为每项加入菜单, 重写render row方法,把所有属性同步到Trigger即可

import React, {  useState } from 'react';
import useContextMenu from '@jeryqwq/react-use-contextmenu';
import { Button, Table  } from 'antd'
import { ReloadOutlined } from '@ant-design/icons';


const menus = [{
  label: '操作1',
  value: 'key1',
  children: [
    { label: '操作1-1',
      value: 'key1-1',
    },
    { label: '操作1-2',
      value: 'key1-2'
    }
  ],
  icon: <ReloadOutlined />,
},
{
  label: '操作3',
  value: 'key3',
},
{
  label: '操作被禁用',
  value: 'key4',
  disabled: true,
}]

export default () => {
  const { Trigger, ContextMenu } = useContextMenu()
  return <div >
    <ContextMenu menus={menus} onClick={(e, item, menu)=> {
      console.log(item, menu, '----')
    }}/>
    <Table 
      dataSource={[
      {
        key: '1',
        name: '胡彦斌',
        age: 32,
        address: '西湖区湖底公园1号',
      },
      {
        key: '2',
        name: '胡彦祖',
        age: 42,
        address: '西湖区湖底公园1号',
      },
    ]}
    columns={ [
      {
        title: '姓名',
        dataIndex: 'name',
        key: 'name',
      },
      {
        title: '年龄',
        dataIndex: 'age',
        key: 'age',
      },
      {
        title: '住址',
        dataIndex: 'address',
        key: 'address',
      },
    ]}
    components={{
      body: {
        row: (item) => {
          const { index,
          moveRow,
          className,
          style,
          ...restProps} = item;
          return <Trigger data={item} tag="tr" className={`${className}`}
            style={style}
            {...restProps}
            >
          </Trigger>
        }
      }
    }}
    />
  </div>
}

指定父元素渲染 | getMenuContainer

菜单渲染父节点。默认fixed渲染到 元素中,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。

import { useContextMenu } from '@vis/components';
import React from 'react'

export default function MyContextMenu () {
  const { Trigger, ContextMenu } = useContextMenu({
    getMenuContainer() {
      return document.getElementById('my-el')
    }
  })

  return <div style={{height: 200, overflow: 'scroll'}}>
    <div  id="my-el" style={{width: 500, height: 800, background: 'red', position: 'relative'}}>
      <Trigger data={{id: 'click'}}>单击触发</Trigger>
      <ContextMenu menus={[{ label: '操作1', value: '1' }]} onClick={(e, data, menu) => {
        alert(`data.id: ${data.id} menu.value: ${menu.value}`)
      }}/>
    </div>
    
  </div>
}