GithubHelp home page GithubHelp logo

rawilk / vue-context Goto Github PK

View Code? Open in Web Editor NEW
257.0 6.0 58.0 3 MB

A simple vue context menu component.

Home Page: https://randallwilk.dev/docs/vue-context

License: MIT License

JavaScript 48.11% HTML 12.35% Vue 35.37% SCSS 4.18%
vue vue-context context-menu

vue-context's People

Contributors

dependabot[bot] avatar nachodd avatar nberezhnoy avatar rawilk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

vue-context's Issues

Sintax error in normalize-slot.js in IE 11

Getting a Syntax error (not a lot of information) in the line that contains this file.
vue-context/src/js/normalize-slot.js

Any idea why this might be happening?

We are using core-js as a polyfill for ES6

Thanks!

Type definition for typescript

Description

Type definition

Steps to Reproduce

Any plan to have type definition? Let me know if I can help you with that by any chance.

Version

6.0.0

OnClose event

Description

Maybe It would be better if we have an OnClose event to handle menu closing?

close () {
  this.top = null;
  this.left = null;
  this.data = null;
  this.show = false;
  this.$emit('close');
},

Window scrolls on activating context menu

Description

The window scrolls when context menu shows

Steps to Reproduce

  1. I actually have two divs. One with a height of say 50px and a div that has an height of calc(100vh - 50px)
  2. Then I have a table with height of 100% inside that second div which activates the context menu on row click
  3. This behaviour appears in these circumstances

Expected behavior:

Do not scroll

Actual behavior:

The window scrolls

Can be seen here:
https://gyazo.com/f78f5eaa2b03eeef4b8d0af2e52bb1f0

Version

"vue-context": "^3.1.0",

Vue 3 Support

As Vue 3 has RC It will be a good idea to add support for Vue 3.

I haven't tested it yet but we will surely do it within a month so I wanted to know will this package get Vue 3 support?

Double export brakes jest test

Description

Hello! i faced a strange issue while testing my application. i've got wrapping component named as 'ContextMenu' which contains imported 'vue-context' and renders menu items in a loop. Everything works fine, but jest test fails because vue-context module is exported twice. Here is the error:

\node_modules\vue-context\src\js\index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){export { default } from './vue-context';
SyntaxError: Unexpected token 'export'

Full description of the error - http://prntscr.com/tcirgu

As i understand the problem is in the module here

export { default } from './vue-context'; 
export { default as VueContext } from './vue-context';

If needed, the full code of the component:

<template>
  <vue-context
    ref="menu"
    @close="clear"
    class="c-context-menu position-fixed bg-white shadow-light rounded-sm border-0"
  >
    <div
      v-for="(m, index) in filteredData"
      :key="index"
      @click.prevent="m.handler(item.id)"
      class="c-context-menu__item position-relative pl-4 pr-4 pt-3 pb-3 cursor-pointer"
    >
      <i :class="`c-context-menu__item-icon mr-2 ${m.icon}`" />
      {{ m.title }}
    </div>
  </vue-context>
</template>

<script>
import VueContext from 'vue-context'

export default {
  name: 'ContextMenu',

  components: { VueContext },

  data() {
    return {
      item: {},
      data: []
    }
  },

  mounted() {
    this.$bus.$on('contextMenuOpen', this.open)
  },

  computed: {
    filteredData() {
      if (Object.prototype.hasOwnProperty.call(this.item, 'deleted_at')) {
        if (this.item.deleted_at === null) {
          return this.data.filter(m => m.title !== 'Восстановить')
        }

        return this.data.filter(m => m.title !== 'В архив')
      }

      return this.data
    }
  },

  methods: {
    open(event, item, data) {
      console.log(event, item, data)
      this.data = data
      this.item = { ...item }
      this.$refs.menu.open(event)
    },

    close() {
      this.$refs.menu.close()
      this.clear()
    },

    clear() {
      this.item = {}
      this.data = []
    }
  },

  beforeDestroy() {
    this.$bus.$off('contextMenuOpen')
  }
}
</script>

And the minimal jest test code to reproduce the issue:

import {
  mount,
  createLocalVue,
  enableAutoDestroy
} from '@vue/test-utils'

import ContextMenu from '@/components/ContextMenu' // wrapping component for 'vue-context'

let wrapper
let testHandler

let spyOnMenuOpen
let spyOnMenuClear

const localVue = createLocalVue()

describe('ContextMenu', () => {
  enableAutoDestroy(afterEach)

  beforeEach(() => {
    wrapper = mount(ContextMenu, {
      mocks: {
        $bus: {
          $on: jest.fn(),
          $off: jest.fn(),
          $emit: jest.fn()
        }
      },
      localVue
    })

    testHandler = jest.fn()

    spyOnMenuOpen = jest.spyOn(wrapper.vm.$refs.menu, 'open')
    spyOnMenuClear = jest.spyOn(wrapper.vm, 'clear')

    wrapper.vm.open({}, { id: 1, name: 'test' }, [
      {
        icon: 'el-icon-edit',
        title: 'test1',
        handler: testHandler
      },
      {
        icon: 'el-icon-s-cooperation',
        title: 'test2',
        handler: testHandler 
      }
    ])
  })

  it('Render menu items', (done) => {
    wrapper.vm.$nextTick(() => {
      expect(wrapper.find('.c-context-menu__item').length).toBe(2)
    })
  })
})

Steps to Reproduce

  1. Create simpe jest test
  2. Run test
  3. Before test start, you can see the error

Version

5.2.0

npm install can't be styled

If you install vue-context using npm, it's not possible to style it.

The styling is baked in dist/index.js, and the SASS files are not included (due to .npmignore)

Add keyboard support

Description

Most context menus allow using the up and down arrows to change the selected context menu item as well as using the enter key to select the selected item.

[Vue warn]: Error in nextTick: "TypeError: Cannot read property 'clientY' of undefined"

Hello,

I can't get vue-context to work with buefy Table's. (buefy = bulma css framework for vue; https://github.com/buefy/buefy)

I get the following error:

[Vue warn]: Error in nextTick: "TypeError: Cannot read property 'clientY' of undefined"

<b-table :data="clients_filtered" :paginated="true" :per-page="perPage" :current-page.sync="currentPage" :pagination-simple="false" :pagination-position="'bottom'" :default-sort-direction="'asc'" @contextmenu="rightClickClient" sort-icon="caret-down" sort-icon-size="is-small" aria-current-label="Current page"> </b-table>

And the function:

rightClickClient: function(client, event) { event.preventDefault() this.$refs.menu.open() }

<vue-context ref="menu"> <li> <a href="#" @click.prevent="onClick($event.target.innerText)">Option 1</a> </li> <li> <a href="#" @click.prevent="onClick($event.target.innerText)">Option 2</a> </li> </vue-context>

Close other existing context-menu when right-clicking

Hi,

I'm using the context-menu in multiple equal components. The is a small issue:

When I open the context-menu on one component and then right-click on another component the previous menu stays open.

What I could do is that every time time a new menu is open an event is emitted to all other components and close the other menus, but this solution doesn't seems really practical.

Is there another way?

Animation while hiding

I know this is silly, but when the :lazy="true" prop is set, is it possible for the animation to hide the menu to be smoother?

By the way, awesome plugin!

Context menu does not auto close when inside of a popover

Description

I'm using the popover in ElementUI, which uses popper.js. When I put a vue-context menu inside of the popper, it does not close if i click somewhere else in the popover.

Steps to Reproduce

https://codesandbox.io/s/vue-template-g80uj

  1. Click on the button to open the popover
  2. Right click on the text
  3. Click on the text below, or anywhere else on the popover

Expected behavior:
The vue-context menu to close

Actual behavior:
It stays open

Reproduces how often:
100%

Version

4.0.1

Two context menu components - old one not closing on open

Hi,
Might be an edge case, but I thought I'll let you know.
If there are two menu components on the same page:

<VueContext ref="menu1"></VueContext>
<VueContext ref="menu2"></VueContext>

If you right click on an element to open menu1, and then go and click on something else to open menu2, the menu1 remains open. Expected (intuitive) behavior would be for old menu to close.

Also, with either or both menus open, if you right-click on an element that is not handled by vue-context (you get default browser right-menu), the vue-context menus remain open. Expected (intuitive) behavior would be for vue-context menu(s) to close.

Thanks for making the component!

Use of clickaway removes ability to open a context menu with a left click

Description

Obviously the main purpose of this package is to allow for a right click to open a contextmenu.

However it should in theory work for left clicks as well.

I thought this would be a simple case of replacing @contextmenu with @click.

However I found that clickaway is detecting the click and closing the context menu instantly.

Removing v-on-clickaway allows for a left click context menu but obviously the context menu just stays open indefinitely.

I also tested the old branch that used @blur and a left click was possible. So removing this ability may have been an unintentional side effect of using clickaway.

I haven't been able to figure out a way to fix this yet.

The nested menu is not visible in Safari/MacOS

Description

The nested menu doesn't render on Safari/MacOS.

nested-context-menu-on-safari

Steps to Reproduce

  1. Open Safari browser (if you have an Apple device)
  2. Visit the demo example: https://randallwilk.dev/docs/vue-context/v6/demos/advanced#nested-menus
  3. Try to open the nested menu.

Expected behavior: The nested menu is visible.

Actual behavior: Only the first (non-nested) menu is visible. The nested menu (the second one) is not visible, except a very tiny part of it, which seems to be the part of it that is overlapping with the first (non-nested) menu.

Version

Seen in versions 5.2.0 and 6.0.0

Tested on:

  • MacOS Catalina 10.15.6
  • Safari 13.1.2

Additional information

I unfortunately don't have a Mac myself that could possibly run Safari, so I can't really test and debug it myself, but I've added a screenshot.

Why not exporting as default when there's no need to use destructuring

First, thank you for all your work on this lib, it is greatly appreciated 👍

export { default as VueContext } from './vue-context';

Why not just export this as default instead of making it so that we have to use destructuring to import it?

Reason I ask is if we are doing code splitting it requires more code, when it could just be exported as default since there's nothing else being exported (so even tree shaking wouldn't matter in this situation)
#33 (comment)

This could be both a named export and default export (to maintain backwards compatibility)

How to open context menu with Left Click?

My template

<div>
  <button @click="open" @contextmenu.prevent="open">
  <v-context ref="menu">
    <ul>
      <li>Delete</li>
    </ul>
  </v-context>
</div>

My method

open(event) {
  this.$refs.menu.open(event)
}

Both left & right click are excute function "open", but only right click can show the context menu.

Please help me, thank you!

Emitting "close" events on scroll with menu closed

v.3.3.1

I'm seeing a ton of "close" events being emitted on scroll, even when the context menu is closed. Is this normal behavior? Do I need to worry about the flurry of emitted events impacting performance or memory?

Documentation site is down?

I know that this it won't be the right place, sorry... but, is the documentation site down? it keeps on giving error 500
Thanks!

Prevent context menu close on click

Add a prop similar to CloseOnScroll that allows the customization of whether the context menu closes on click

<template>
    <div class="v-context"
         v-show="show"
         :style="style"
         tabindex="-1"
         @blur="close"
         @click="tryCloseOnClick"
         @contextmenu.capture.prevent
    >
        <slot :data="data"></slot>
    </div>
</template>

<script>
    export default {
        props: {
            closeOnClick: {
                type: Boolean,
                default: true
            },
            closeOnScroll: {
                type: Boolean,
                default: true
            }
        },

        computed: {
...

        methods: {
            /**
             * Add scroll event listener to close context menu.
             */
            addScrollEventListener () {
                window.addEventListener('scroll', this.close);
            },

            /**
             * Close the context menu.
             */
            close () {
                this.top = null;
                this.left = null;
                this.data = null;
                this.show = false;
            },

            tryCloseOnClick () {
                if (this.closeOnClick) {
                    this.close();
                }
            },


NOT FOUND node_modules/vue-context/dist/js/vue-context.js

dist/js directory seems to be missing from 5.0.0

When I upgraded from a very early version to 5.0.0 I got the message
ERROR in ./node_modules/vue-context/dist/js/vue-context.js
Module build failed: Error: ENOENT: no such file or directory, open '/Users/......../node_modules/vue-context/dist/js/vue-context.js'

There is a src/js directory and when I copy that one into dist, the error message disappears but the menu appears before clicking on it
I also get the following warning:
[Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.

And obviously, when I right click :
[Vue warn]: Error in v-on handler: "TypeError: this.$refs.menu.open is not a function"

So it seems the vue-context is not properly recognized.

4.1.1 though has the proper structure

Contextmenu won't close after open another one

Hello!

I'm stuck on working with the vue-context. I don't know if it is a bug or if i wrote something false, if i open one contextmenu everything happens fine but if i start opening another one the first one opened should normally close automatically but in my case now both are opened.

Is it supposed to work like this? If yes, how can i achieve that only one is opened?

Thanks 👍

Context Menu stays open if you click in an iframe

Description

Context-Menu won't close if you click on an iframe after you opened the Context-Menu.

Steps to Reproduce

  1. Open a context menu
  2. Left click into an iframe
  3. Watch the context menu not close

**Expected behavior: Close Context Menu

**Actual behavior: Context Menu stays open

**Reproduces how often: 100%

Version

^5.0.0
Electron

How to use it in Script Tag

i am using a Vue-Tree and its render in Script tag like this

tpl(...args) {
      const { 0: node, 2: parent, 3: index } = args;
      let titleClass = node.selected
        ? "node-title node-selected"
        : "node-title";
      if (node.searched) titleClass += " node-searched"; //search

      return (
        <span>
          <span
            class="tree-expand"
            onClick={() => {
              this.popupActive2 = true;
              this.waitFor(_ => this.confirmClose === true).then(_ =>
                this.AsyncaddNode(node)
              );
            }}
          >
            <b class="text-xl">+</b>
          </span>

          <span
            class={titleClass}
            domPropsInnerHTML={node.title}
            onClick={() => {
             HERE I WANT TO DO THE RIGHT CLICK FUNCTION
            }}
          ></span>
</span

i want to use the right click Function

Vue global install not support.

Description

I tried to install it globally in main.js like this.

import { VueContext } from 'vue-context';
Vue.use(VueContext);

Steps to Reproduce

  1. install globally as above.
  2. add the following vue-context in the template
<vue-context ref="menu">
            <li>
              <a href="#" @click.prevent="onClick($event.target.innerText)">Option 1</a>
            </li>
            <li>
              <a href="#" @click.prevent="onClick($event.target.innerText)">Option 2</a>
            </li>
          </vue-context>

Expected behavior: [What did you expect to happen]
The vue-context did not render correctly.

Actual behavior: [What actually happens]
The vue-context should render correctly.

Reproduces how often: [What percentage of the time does it reproduce?]
Always

Version

^5.1.0

LocalItemSelector data doesn't update when itemSelector prop does

Description

I'm having an issue where I want to dynamically update the item selector in the component under certain conditions (I have a submenu in my context menu, and when it's open, I only want the keyboard nav to cycle through the sub menu items, which have a different class)

As you can see in the cache, the itemSelector property gets updated by the parent component, but the internal localItemSelector data remains cached, and doesn't update.

2019-07-26_11-39-36

This prevents the keyboard navigation from cycling through the elements I need under those conditions.

Steps to Reproduce

  1. In the parent component, add a computed property that is set to different classnames under different conditions. Here's my code:
contextItemSelector() {
     return this.subMenuOpen ? '.context-option--submenu' : '.context-option';
 },
  1. Set the itemSelector property on the vue-context component to the computed property
<vue-context ref="menu" :item-selector="contextItemSelector">

Expected behavior: I expect the class selector to update

Actual behavior: The component gets the initial state, but doesn't update.

Reproduces how often: 100% of the time

Version

Package : 4.0.1
Browser: Chromium (Electron)

Big bundle size due to core-js

Using vue-context increases bundle size by 41 KB (gzipped). It seems tree-shaking is not working properly, and the whole core-js in bundled in, not just the two functions used.

Unable to pass data from the contextmenu.

Description

Hello,
I'm unable to pass data from the contextmenu, taken from the advanced usage part in usage examples.
I don't get any errors, but console log returns undefined.

Steps to Reproduce

  1. [Take code from the advanced usage section.]
  2. [Run Vue app]
  3. [Check console output]

Expected behavior: [Debug console to return value 'foo'.]

Actual behavior: [Console returns undefined.]

Additional Information

I'm using vue-context as Nuxt plugin. Everything works great, but this one feature.
I'm also using template slot-scope="child" instead of template scope="child"

Does not work inside v-for

Note that I am using vue-context version 4.0.2.

This component will fail when used inside of a v-for loop. Per Vue's documentation on ref:

When used on elements/components with v-for, the registered reference will be an Array containing DOM nodes or component instances.

I have attempted to get around the issue by using a method openMenu.

<ul>
    <li v-for="item in items" :key="item.index">
        <vs-button @contextmenu.prevent="openMenu(item.index)">{{item.label}}</vs-button>
        <vue-context ref="menu" :data="item.index">
            <ul>
                <li @click="unpinItem(item.index)">Unpin</li>
            </ul>
        </vue-context>
    </li>
</ul>
methods: {
    openMenu(itemIndex) {
        for (const [index, VueComponent] of this.$refs.menu.entries()) {
            if (VueComponent.$attrs.data === itemIndex) {
                this.$refs.menu[index].open();
                break;
            }
        }
    },
    unpinItem(itemIndex) {
        this.$store.dispatch('unpinItem', {
            index: itemIndex,
        });
    },
}

However, I get a couple errors when I try and fire the open event this.$refs.menu[index].open();

Error in nextTick: "TypeError: Cannot read property 'clientY' of undefined"
TypeError: Cannot read property 'clientY' of undefined

I was reading through your advanced documentation, but I see no mention of using this context menu inside of a v-for loop.

How do you recommend this be handled?

Change color on hover

Hi, thanks for this useful component.
How can i change hover color?Is any prop to set?

Context menu can't be closed by click outside menu and shown in wrong place

Description

When UI element is draggable - context menu can't be closed by click outside menu and shown in wrong place.

Steps to Reproduce

  1. Right Mouse Click to open menu
  2. mousedown outside menu, move, mouseup
  3. The context menu is shown and placed in the wrong spot
    Demo in video https://monosnap.com/file/YlyygeJbHYiGMxhA3gtSwZAn2fqRj1

Expected behavior:
The context menu is hidden

Actual behavior:
The context menu is shown and placed in the wrong spot

Reproduces how often: [What percentage of the time does it reproduce?]
100%

Version

5.0.0
Chrome 78.0.3904.108 64bit

Register vue-context globally

Hello,
I just started using your plugin and I might need it in a lot of components. Is it possible to globally define your component?

I tried registering it with Vue.component, but weirdly it didnt't work.

Best wishes

Nested Menu

Description

First of all thanks for this package. It is by far the best context menu for vue! :)
But I miss the ability to create nested menus. I already tried to add another list on hover, but it still fires the click event of the parent element. And it feels hacky the way I did it.
Do you have any plans to add such a feature? If you need any help/testing I'd love to help. 😀

Doesn't work after upgrading to 4.1.0: Unknown custom element: <VueContext>

After upgrading from 4.0.3 to 4.1.0, VueContext doesn't work anymore.

The console shows the following error when loading the app:

vue.runtime.esm.js:619 [Vue warn]: Unknown custom element: <VueContext> - did you register the component correctly? For recursive components, make sure to provide the "name" option.

And the menu doesn't show up, instead I get this error:

Uncaught TypeError: open is not a function

Not working with Nuxt

NOTE: ISSUES ARE NOT FOR CODE HELP - Ask for help at
https://stackoverflow.com

Description

As per title, not working with Nuxt. It works fine unless you refresh the page. Once the page is refreshed it crash with error: "Window is not defined". I tried using it as suggested by you and also as suggested by Nuxt, including it in the plugins section. Nothing...

Steps to Reproduce

  1. Install it with nuxt
  2. refresh the page where you are using the plugin
  3. please suggest a fix

Expected behavior: The app should not crash on page refresh

Actual behavior: It crash on page refresh

Reproduces how often: Every time. 100%.

Versio 4.0.3

Additional Information /

The button is wider than the context menu when not using bootstrap-vue

Description

When I use the context menu in a project, the buttons seem to be wider than the context menu holding them:
image

In addition, when running in chrome, there is a blue outline to the menu.

Steps to Reproduce

Either clone https://github.com/guyguy2001/vue-context-reproduction and run it via npm i, npm run serve, or:

  1. Init a new vue project via vue create vue-context-reproduction (I used the default babel + eslint setup).
  2. Copy the html and the javascript into either App.vue or HelloWorld.vue, and modify them to fit inside the component (Make sure to remove the li styling from the example component).
  3. Run via npm install vue-context, npm install, npm run serve.

Expected behavior: [What did you expect to happen]
A normal context menu appearing, like in the example screenshots.

Actual behavior: [What actually happens]
The context menu appears, but has a blue outline (Only on chrome), and the buttons are wider than the context box, meaning that the text is centered weirdly, and when I hover over a button, its background is too wide.

Reproduces how often: [What percentage of the time does it reproduce?]
The problem occurs consistantly, whenever I run the project.

Version

Version: 4.0.1 (doesn't happen on 3.4.0)
Chrome: Version 74.0.3729.169 (Official Build) (64-bit)
Firefox: 64.0 (64-bit)

Export declarations may only appear at top level of a module

I'm building little app in meteor+vue.js. As soon as I add

import { VueContext } from 'vue-context';

or

import VueContext from 'vue-context';

to component it start to crash with error message:

SyntaxError: export declarations may only appear at top level of a module

Any way to fix it?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.