mirror of
https://github.com/tenrok/vue-context.git
synced 2026-06-23 14:20:33 +03:00
Release/v5 (#43)
This commit is contained in:
+2
-1
@@ -1,4 +1,5 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
.idea
|
.idea
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
**/mix-manifest.json
|
**/mix-manifest.json
|
||||||
|
test/js/dist/
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
docs/
|
|
||||||
src/
|
|
||||||
test/
|
test/
|
||||||
build/
|
build/
|
||||||
.idea
|
.idea
|
||||||
|
|||||||
+44
-26
@@ -2,12 +2,30 @@
|
|||||||
|
|
||||||
All notable changes to this project will be documented here.
|
All notable changes to this project will be documented here.
|
||||||
|
|
||||||
|
<a name="5.0.0"></a>
|
||||||
|
## [5.0.0](https://github.com/rawilk/vue-context/releases/tag/5.0.0)
|
||||||
|
|
||||||
|
Released 2019-11-14
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Add default export in entry point ([#41](https://github.com/rawilk/vue-context/issues/41)).
|
||||||
|
- Add support for nested context menus ([#37](https://github.com/rawilk/vue-context/pull/37)).
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
- Update entry point to source ([#33](https://github.com/rawilk/vue-context/issues/33)).
|
||||||
|
- No longer build component with webpack ([#33](https://github.com/rawilk/vue-context/issues/33)).
|
||||||
|
- Component source is available through npm now, including the sass files.
|
||||||
|
|
||||||
|
### Release notes
|
||||||
|
- Even though there shouldn't be any breaking changes in this release, it's a major release because
|
||||||
|
breaking changes were introduced in version 4.1.0, which should have been a major release instead.
|
||||||
|
|
||||||
<a name="4.1.1"></a>
|
<a name="4.1.1"></a>
|
||||||
## [4.1.1](https://github.com/rawilk/vue-context/releases/tag/4.1.1)
|
## [4.1.1](https://github.com/rawilk/vue-context/releases/tag/4.1.1)
|
||||||
|
|
||||||
Released 2019-10-20
|
Released 2019-10-20
|
||||||
|
|
||||||
### Bug Fixes 4.1.1
|
### Bug Fixes
|
||||||
- Fix bug of "Unknown custom element" ([#40](https://github.com/rawilk/vue-context/issues/40)).
|
- Fix bug of "Unknown custom element" ([#40](https://github.com/rawilk/vue-context/issues/40)).
|
||||||
|
|
||||||
<a name="4.1.0"></a>
|
<a name="4.1.0"></a>
|
||||||
@@ -15,10 +33,10 @@ Released 2019-10-20
|
|||||||
|
|
||||||
Released 2019-10-11
|
Released 2019-10-11
|
||||||
|
|
||||||
### Breaking Changes 4.1.0
|
### Breaking Changes
|
||||||
- Move menu styles from js to its own stylesheet ([#36](https://github.com/rawilk/vue-context/issues/36))
|
- Move menu styles from js to its own stylesheet ([#36](https://github.com/rawilk/vue-context/issues/36))
|
||||||
|
|
||||||
### Changes 4.1.0
|
### Changes
|
||||||
- Remove core-js as a dependency in favor of local polyfills for a smaller build size ([#33](https://github.com/rawilk/vue-context/issues/33))
|
- Remove core-js as a dependency in favor of local polyfills for a smaller build size ([#33](https://github.com/rawilk/vue-context/issues/33))
|
||||||
|
|
||||||
<a name="4.0.3"></a>
|
<a name="4.0.3"></a>
|
||||||
@@ -26,10 +44,10 @@ Released 2019-10-11
|
|||||||
|
|
||||||
Released 2019-07-28
|
Released 2019-07-28
|
||||||
|
|
||||||
### Bug Fixes 4.0.3
|
### Bug Fixes
|
||||||
- Make `localItemSelector` reactive to changes from `itemSelector` prop ([#30](https://github.com/rawilk/vue-context/issues/30)).
|
- Make `localItemSelector` reactive to changes from `itemSelector` prop ([#30](https://github.com/rawilk/vue-context/issues/30)).
|
||||||
|
|
||||||
### Updates 4.0.3
|
### Updates
|
||||||
- Update dev dependencies
|
- Update dev dependencies
|
||||||
|
|
||||||
<a name="4.0.2"></a>
|
<a name="4.0.2"></a>
|
||||||
@@ -37,7 +55,7 @@ Released 2019-07-28
|
|||||||
|
|
||||||
Released 2019-06-22
|
Released 2019-06-22
|
||||||
|
|
||||||
### Bug Fixes 4.0.2
|
### Bug Fixes
|
||||||
- Fix menu item width issues ([#26](https://github.com/rawilk/vue-context/issues/26)).
|
- Fix menu item width issues ([#26](https://github.com/rawilk/vue-context/issues/26)).
|
||||||
- Remove outline from menu and menu items when given focus ([#26](https://github.com/rawilk/vue-context/issues/26)).
|
- Remove outline from menu and menu items when given focus ([#26](https://github.com/rawilk/vue-context/issues/26)).
|
||||||
|
|
||||||
@@ -46,7 +64,7 @@ Released 2019-06-22
|
|||||||
|
|
||||||
Released 2019-06-03
|
Released 2019-06-03
|
||||||
|
|
||||||
### Bug Fixes 4.0.1
|
### Bug Fixes
|
||||||
- Always emit the close event on click. See issue [#23](https://github.com/rawilk/vue-context/issues/23)
|
- Always emit the close event on click. See issue [#23](https://github.com/rawilk/vue-context/issues/23)
|
||||||
|
|
||||||
<a name="4.0.0"></a>
|
<a name="4.0.0"></a>
|
||||||
@@ -54,17 +72,17 @@ Released 2019-06-03
|
|||||||
|
|
||||||
Released 2019-05-18
|
Released 2019-05-18
|
||||||
|
|
||||||
### Added 4.0.0
|
### Added
|
||||||
- Added support for keyboard navigation (up and down arrows).
|
- Added support for keyboard navigation (up and down arrows).
|
||||||
- Added ability to close menu on esc.
|
- Added ability to close menu on esc.
|
||||||
- Added `lazy` prop as an alternative to `v-show`.
|
- Added `lazy` prop as an alternative to `v-show`.
|
||||||
- Added `tag` prop to specify menu tag (defaults to `<ul>`).
|
- Added `tag` prop to specify menu tag (defaults to `<ul>`).
|
||||||
|
|
||||||
### Changes 4.0.0
|
### Changes
|
||||||
- Default menu tag is now `<ul>` and menu is now the top-level element.
|
- Default menu tag is now `<ul>` and menu is now the top-level element.
|
||||||
- Changed how the menu is styled.
|
- Changed how the menu is styled.
|
||||||
|
|
||||||
### Updates 4.0.0
|
### Updates
|
||||||
- Updated build process and project structure.
|
- Updated build process and project structure.
|
||||||
- Ran `npm audit fix` to fix vulnerabilities found from dependencies.
|
- Ran `npm audit fix` to fix vulnerabilities found from dependencies.
|
||||||
|
|
||||||
@@ -73,7 +91,7 @@ Released 2019-05-18
|
|||||||
|
|
||||||
Released 2019-04-05
|
Released 2019-04-05
|
||||||
|
|
||||||
### Bug Fixes 3.4.2
|
### Bug Fixes
|
||||||
- Only add scroll event listener on `closeOnScroll` prop value change if the menu is open.
|
- Only add scroll event listener on `closeOnScroll` prop value change if the menu is open.
|
||||||
|
|
||||||
<a name="3.4.1"></a>
|
<a name="3.4.1"></a>
|
||||||
@@ -81,7 +99,7 @@ Released 2019-04-05
|
|||||||
|
|
||||||
Released 2019-04-03
|
Released 2019-04-03
|
||||||
|
|
||||||
### Updates 3.4.1
|
### Updates
|
||||||
- **Scroll Listener:** Only attach the close scroll event listener when opened and immediately remove it when menu is closed
|
- **Scroll Listener:** Only attach the close scroll event listener when opened and immediately remove it when menu is closed
|
||||||
to prevent it being called unnecessarily.
|
to prevent it being called unnecessarily.
|
||||||
- **Dependencies:** Removed Vue as a dependency as it never really was one since v3.0.0.
|
- **Dependencies:** Removed Vue as a dependency as it never really was one since v3.0.0.
|
||||||
@@ -92,7 +110,7 @@ to prevent it being called unnecessarily.
|
|||||||
|
|
||||||
Released 2018-11-19
|
Released 2018-11-19
|
||||||
|
|
||||||
### Bug fixes 3.4.0
|
### Bug fixes
|
||||||
- **Close event:** only emit the event if menu is actually open (fixes [#13](https://github.com/rawilk/vue-context/issues/13))
|
- **Close event:** only emit the event if menu is actually open (fixes [#13](https://github.com/rawilk/vue-context/issues/13))
|
||||||
|
|
||||||
<a name="3.3.1"></a>
|
<a name="3.3.1"></a>
|
||||||
@@ -100,10 +118,10 @@ Released 2018-11-19
|
|||||||
|
|
||||||
Released 2018-10-23
|
Released 2018-10-23
|
||||||
|
|
||||||
### Changes 3.3.1
|
### Changes
|
||||||
- Context menu now closes via [clickaway](https://github.com/simplesmiler/vue-clickaway) instead of a blur event. Credit: [robjbrain](https://github.com/robjbrain)
|
- Context menu now closes via [clickaway](https://github.com/simplesmiler/vue-clickaway) instead of a blur event. Credit: [robjbrain](https://github.com/robjbrain)
|
||||||
|
|
||||||
### Updates 3.3.1
|
### Updates
|
||||||
- Updated vue and other dev dependencies.
|
- Updated vue and other dev dependencies.
|
||||||
|
|
||||||
<a name="3.3.0"></a>
|
<a name="3.3.0"></a>
|
||||||
@@ -111,7 +129,7 @@ Released 2018-10-23
|
|||||||
|
|
||||||
Released 2018-10-15
|
Released 2018-10-15
|
||||||
|
|
||||||
### Features 3.3.0
|
### Features
|
||||||
- **Events:** both open and close events are now emitted by the component. ([#10](https://github.com/rawilk/vue-context/issues/10))
|
- **Events:** both open and close events are now emitted by the component. ([#10](https://github.com/rawilk/vue-context/issues/10))
|
||||||
|
|
||||||
<a name="3.2.0"></a>
|
<a name="3.2.0"></a>
|
||||||
@@ -119,7 +137,7 @@ Released 2018-10-15
|
|||||||
|
|
||||||
Released 2018-09-12
|
Released 2018-09-12
|
||||||
|
|
||||||
### Features 3.2.0
|
### Features
|
||||||
- **Close on click prop:** added a prop to prevent closing the context menu on click. ([#8](https://github.com/rawilk/vue-context/issues/8))
|
- **Close on click prop:** added a prop to prevent closing the context menu on click. ([#8](https://github.com/rawilk/vue-context/issues/8))
|
||||||
|
|
||||||
<a name="3.1.1"></a>
|
<a name="3.1.1"></a>
|
||||||
@@ -127,7 +145,7 @@ Released 2018-09-12
|
|||||||
|
|
||||||
Released 2018-06-23
|
Released 2018-06-23
|
||||||
|
|
||||||
### Updates 3.1.1
|
### Updates
|
||||||
- Updated README.md
|
- Updated README.md
|
||||||
- Added code comments
|
- Added code comments
|
||||||
|
|
||||||
@@ -136,7 +154,7 @@ Released 2018-06-23
|
|||||||
|
|
||||||
Released 2018-05-29
|
Released 2018-05-29
|
||||||
|
|
||||||
### Features 3.1.0
|
### Features
|
||||||
- **Scroll prop:** added a prop to close the context menu automatically on window scroll. ([#2](https://github.com/rawilk/vue-context/issues/2))
|
- **Scroll prop:** added a prop to close the context menu automatically on window scroll. ([#2](https://github.com/rawilk/vue-context/issues/2))
|
||||||
|
|
||||||
<a name="3.0.2"></a>
|
<a name="3.0.2"></a>
|
||||||
@@ -144,10 +162,10 @@ Released 2018-05-29
|
|||||||
|
|
||||||
Released 2018-05-29
|
Released 2018-05-29
|
||||||
|
|
||||||
### Updates 3.0.2
|
### Updates
|
||||||
- Updated documentation
|
- Updated documentation
|
||||||
|
|
||||||
### Added 3.0.2
|
### Added
|
||||||
- Added [demos](https://vue-context.randallwilk.com) for the component.
|
- Added [demos](https://vue-context.randallwilk.com) for the component.
|
||||||
|
|
||||||
<a name="3.0.0"></a>
|
<a name="3.0.0"></a>
|
||||||
@@ -155,15 +173,15 @@ Released 2018-05-29
|
|||||||
|
|
||||||
Released 2018-05-26
|
Released 2018-05-26
|
||||||
|
|
||||||
### Breaking changes 3.0.0
|
### Breaking changes
|
||||||
- Changed slot scope definition from `userData` to just `data`.
|
- Changed slot scope definition from `userData` to just `data`.
|
||||||
- Component gets imported as `{ VueContext }` instead of `VContext` now.
|
- Component gets imported as `{ VueContext }` instead of `VContext` now.
|
||||||
|
|
||||||
### Updates 3.0.0
|
### Updates
|
||||||
- Updated dependencies
|
- Updated dependencies
|
||||||
- Updated documentation
|
- Updated documentation
|
||||||
|
|
||||||
### Changes 3.0.0
|
### Changes
|
||||||
- Changed code structure and build process.
|
- Changed code structure and build process.
|
||||||
|
|
||||||
<a name="2.0.1"></a>
|
<a name="2.0.1"></a>
|
||||||
@@ -171,11 +189,11 @@ Released 2018-05-26
|
|||||||
|
|
||||||
Released 2017-08-18
|
Released 2017-08-18
|
||||||
|
|
||||||
### Added 2.0.1
|
### Added
|
||||||
- License file
|
- License file
|
||||||
- Changelog file
|
- Changelog file
|
||||||
|
|
||||||
### Removed 2.0.1
|
### Removed
|
||||||
- Removed bottom border from context menu line items.
|
- Removed bottom border from context menu line items.
|
||||||
|
|
||||||
<a name="2.0.0"></a>
|
<a name="2.0.0"></a>
|
||||||
|
|||||||
@@ -75,12 +75,22 @@ Next add an element to the page that will trigger the context menu to appear, an
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
@import '~vue-context/dist/css/vue-context.css';
|
@import '~vue-context/dist/css/vue-context.css';
|
||||||
|
|
||||||
|
// Or
|
||||||
|
@import '~vue-context/src/sass/vue-context';
|
||||||
```
|
```
|
||||||
|
|
||||||
## Documentation/Demo
|
## Documentation/Demo
|
||||||
|
|
||||||
For full documentation and demos, go here: https://vue-context.com/docs
|
For full documentation and demos, go here: https://vue-context.com/docs
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
This project exists thanks to all the people who contribute. [[Contribute]](CONTRIBUTING.md).
|
||||||
|
|
||||||
|
- [rawilk](https://github.com/rawilk)
|
||||||
|
- [wol-soft](https://github.com/wol-soft)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
`vue-context` uses the MIT License (MIT). Please see the [license file](https://github.com/rawilk/vue-context/blob/master/LICENSE) for more information.
|
`vue-context` uses the MIT License (MIT). Please see the [license file](https://github.com/rawilk/vue-context/blob/master/LICENSE) for more information.
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
const mix = require('laravel-mix');
|
|
||||||
|
|
||||||
mix
|
|
||||||
.setPublicPath('dist/css')
|
|
||||||
.sass('src/sass/vue-context.scss', 'vue-context.css');
|
|
||||||
+2
-11
@@ -1,14 +1,5 @@
|
|||||||
const mix = require('laravel-mix');
|
const mix = require('laravel-mix');
|
||||||
|
|
||||||
const inProduction = mix.inProduction();
|
|
||||||
|
|
||||||
mix
|
mix
|
||||||
.setPublicPath('dist/js')
|
.setPublicPath('dist/css')
|
||||||
.js('src/js/index.js', 'vue-context.js')
|
.sass('src/sass/vue-context.scss', 'vue-context.css');
|
||||||
.sourceMaps(! inProduction)
|
|
||||||
.webpackConfig({
|
|
||||||
output: {
|
|
||||||
libraryTarget: 'umd',
|
|
||||||
umdNamedDefine: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
.v-context{background-color:#fff;background-clip:padding-box;border-radius:.25rem;border:1px solid rgba(0,0,0,.15);box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);display:block;margin:0;padding:10px 0;min-width:10rem;z-index:1500;position:fixed;list-style:none;box-sizing:border-box}.v-context>li{margin:0}.v-context>li>a{display:block;padding:.5rem 1.5rem;font-weight:400;color:#212529;text-decoration:none;white-space:nowrap;background-color:transparent;border:0}.v-context>li>a:focus,.v-context>li>a:hover{text-decoration:none;color:#212529;background-color:#f8f9fa}.v-context:focus,.v-context>li>a:focus{outline:0}
|
.v-context,.v-context ul{background-color:#fff;background-clip:padding-box;border-radius:.25rem;border:1px solid rgba(0,0,0,.15);box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);display:block;margin:0;padding:10px 0;min-width:10rem;z-index:1500;position:fixed;list-style:none;box-sizing:border-box;max-height:calc(100% - 50px);overflow-y:auto}.v-context>li,.v-context ul>li{margin:0;position:relative}.v-context>li>a,.v-context ul>li>a{display:block;padding:.5rem 1.5rem;font-weight:400;color:#212529;text-decoration:none;white-space:nowrap;background-color:transparent;border:0}.v-context>li>a:focus,.v-context>li>a:hover,.v-context ul>li>a:focus,.v-context ul>li>a:hover{text-decoration:none;color:#212529;background-color:#f8f9fa}.v-context:focus,.v-context>li>a:focus,.v-context ul:focus,.v-context ul>li>a:focus{outline:0}.v-context__sub>a:after{content:"\2BC8";float:right;padding-left:1rem}.v-context__sub>ul{display:none}
|
||||||
Vendored
-1
File diff suppressed because one or more lines are too long
+2
-3
@@ -2,13 +2,12 @@
|
|||||||
"name": "vue-context",
|
"name": "vue-context",
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"description": "A simple vue context menu component.",
|
"description": "A simple vue context menu component.",
|
||||||
"main": "dist/js/vue-context.js",
|
"main": "src/js/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --env.mixfile=build/webpack.mix.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
|
"dev": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --env.mixfile=build/webpack.mix.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
|
||||||
"dev-test": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --env.mixfile=build/webpack-test.mix.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
|
"dev-test": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --env.mixfile=build/webpack-test.mix.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
|
||||||
"watch-test": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --env.mixfile=build/webpack-test.mix.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
|
"watch-test": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --env.mixfile=build/webpack-test.mix.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
|
||||||
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --env.mixfile=build/webpack.mix.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
|
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --env.mixfile=build/webpack.mix.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
|
||||||
"styles": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --env.mixfile=build/webpack-styles.mix.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
|
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Vue",
|
"Vue",
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
|
export { default } from './vue-context';
|
||||||
export { default as VueContext } from './vue-context';
|
export { default as VueContext } from './vue-context';
|
||||||
|
|||||||
+13
-1
@@ -17,7 +17,9 @@ export const isArray = Array.isArray;
|
|||||||
|
|
||||||
export const keyCodes = {
|
export const keyCodes = {
|
||||||
ESC: 27,
|
ESC: 27,
|
||||||
|
LEFT: 37,
|
||||||
UP: 38,
|
UP: 38,
|
||||||
|
RIGHT: 39,
|
||||||
DOWN: 40
|
DOWN: 40
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -51,7 +53,7 @@ export const filterVisible = elements => (elements || []).filter(isVisible);
|
|||||||
|
|
||||||
// Return the Bounding Client Rect of an element
|
// Return the Bounding Client Rect of an element
|
||||||
// Returns `null` if not an element
|
// Returns `null` if not an element
|
||||||
const getBCR = el => (isElement(el) ? el.getBoundingClientRect() : null);
|
export const getBCR = el => (isElement(el) ? el.getBoundingClientRect() : null);
|
||||||
|
|
||||||
// Determine if an element is an HTML element
|
// Determine if an element is an HTML element
|
||||||
const isElement = el => Boolean(el && el.nodeType === Node.ELEMENT_NODE);
|
const isElement = el => Boolean(el && el.nodeType === Node.ELEMENT_NODE);
|
||||||
@@ -81,3 +83,13 @@ export const setAttr = (el, attr, value) => {
|
|||||||
el.setAttribute(attr, value);
|
el.setAttribute(attr, value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const parentElementByClassName = (element, className) => {
|
||||||
|
let parentElement = element.parentElement;
|
||||||
|
|
||||||
|
while (parentElement !== null && !parentElement.classList.contains(className)) {
|
||||||
|
parentElement = parentElement.parentElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parentElement;
|
||||||
|
};
|
||||||
|
|||||||
+119
-9
@@ -1,5 +1,15 @@
|
|||||||
import { directive as onClickaway } from 'vue-clickaway/index';
|
import { directive as onClickaway } from 'vue-clickaway/index';
|
||||||
import { eventOff, eventOn, filterVisible, isArray, keyCodes, selectAll, setAttr } from './utils';
|
import {
|
||||||
|
eventOff,
|
||||||
|
eventOn,
|
||||||
|
filterVisible,
|
||||||
|
isArray,
|
||||||
|
keyCodes,
|
||||||
|
selectAll,
|
||||||
|
setAttr,
|
||||||
|
getBCR,
|
||||||
|
parentElementByClassName
|
||||||
|
} from './utils';
|
||||||
import { normalizeSlot } from './normalize-slot';
|
import { normalizeSlot } from './normalize-slot';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -48,7 +58,8 @@ export default {
|
|||||||
left: null,
|
left: null,
|
||||||
show: false,
|
show: false,
|
||||||
data: null,
|
data: null,
|
||||||
localItemSelector: ''
|
localItemSelector: '',
|
||||||
|
activeSubMenu: null
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -67,12 +78,27 @@ export default {
|
|||||||
eventOn(window, 'scroll', this.close);
|
eventOn(window, 'scroll', this.close);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
addHoverEventListener(element) {
|
||||||
|
element.querySelectorAll('.v-context__sub').forEach(
|
||||||
|
subMenuNode => {
|
||||||
|
eventOn(subMenuNode, 'mouseenter', this.openSubMenu);
|
||||||
|
eventOn(subMenuNode, 'mouseleave', this.closeSubMenu);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
if (! this.show) {
|
if (! this.show) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// make sure all sub menus are closed
|
||||||
|
while (this.activeSubMenu !== null) {
|
||||||
|
parentElementByClassName(this.activeSubMenu, 'v-context__sub').dispatchEvent(new Event('mouseleave'));
|
||||||
|
}
|
||||||
|
|
||||||
this.resetData();
|
this.resetData();
|
||||||
|
this.removeHoverEventListener(this.$el);
|
||||||
|
|
||||||
if (this.closeOnScroll) {
|
if (this.closeOnScroll) {
|
||||||
this.removeScrollEventListener();
|
this.removeScrollEventListener();
|
||||||
@@ -118,7 +144,8 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getItems() {
|
getItems() {
|
||||||
return filterVisible(selectAll(this.localItemSelector, this.$el));
|
// if a sub menu is active only return the elements of the sub menu to keep the scope
|
||||||
|
return filterVisible(selectAll(this.localItemSelector, this.activeSubMenu || this.$el));
|
||||||
},
|
},
|
||||||
|
|
||||||
mapItemSelector(itemSelector) {
|
mapItemSelector(itemSelector) {
|
||||||
@@ -147,6 +174,27 @@ export default {
|
|||||||
} else if (key === keyCodes.UP) {
|
} else if (key === keyCodes.UP) {
|
||||||
// Up arrow
|
// Up arrow
|
||||||
this.focusNext(event, true);
|
this.focusNext(event, true);
|
||||||
|
} else if (key === keyCodes.RIGHT) {
|
||||||
|
// check if a parent element which is associated with a sub menu can be found.
|
||||||
|
const menuContainer = parentElementByClassName(event.target, 'v-context__sub');
|
||||||
|
|
||||||
|
// try to open a sub menu if the sub menu isn't the current sub menu
|
||||||
|
if (menuContainer && menuContainer.getElementsByClassName('v-context')[0] !== this.activeSubMenu) {
|
||||||
|
menuContainer.dispatchEvent(new Event('mouseenter'));
|
||||||
|
this.focusNext(event, false);
|
||||||
|
}
|
||||||
|
} else if (key === keyCodes.LEFT) {
|
||||||
|
if (!this.activeSubMenu) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const parentMenu = parentElementByClassName(this.activeSubMenu, 'v-context__sub');
|
||||||
|
parentMenu.dispatchEvent(new Event('mouseleave'));
|
||||||
|
|
||||||
|
const items = this.getItems(),
|
||||||
|
index = items.indexOf(parentMenu.getElementsByTagName('a')[0]);
|
||||||
|
|
||||||
|
this.focusItem(index, items);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -155,9 +203,11 @@ export default {
|
|||||||
this.show = true;
|
this.show = true;
|
||||||
|
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.positionMenu(event.clientY, event.clientX);
|
[this.top, this.left] = this.positionMenu(event.clientY, event.clientX, this.$el);
|
||||||
|
|
||||||
this.$el.focus();
|
this.$el.focus();
|
||||||
this.setItemRoles();
|
this.setItemRoles();
|
||||||
|
this.addHoverEventListener(this.$el);
|
||||||
|
|
||||||
if (this.closeOnScroll) {
|
if (this.closeOnScroll) {
|
||||||
this.addScrollEventListener();
|
this.addScrollEventListener();
|
||||||
@@ -167,9 +217,61 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
positionMenu(top, left) {
|
openSubMenu(event) {
|
||||||
const largestHeight = window.innerHeight - this.$el.offsetHeight - 25;
|
const subMenuElement = this.getSubMenuElementByEvent(event),
|
||||||
const largestWidth = window.innerWidth - this.$el.offsetWidth - 25;
|
parentMenu = parentElementByClassName(subMenuElement.parentElement, 'v-context'),
|
||||||
|
bcr = getBCR(event.target);
|
||||||
|
|
||||||
|
// check if another sub menu is open. In this case make sure no other as well as no nested sub menu is open
|
||||||
|
if (this.activeSubMenu !== parentMenu) {
|
||||||
|
while (this.activeSubMenu !== null
|
||||||
|
&& this.activeSubMenu !== parentMenu
|
||||||
|
&& this.activeSubMenu !== subMenuElement
|
||||||
|
) {
|
||||||
|
parentElementByClassName(this.activeSubMenu, 'v-context__sub')
|
||||||
|
.dispatchEvent(new Event('mouseleave'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// first set the display and afterwards execute position calculation for correct element offsets
|
||||||
|
subMenuElement.style.display = 'block';
|
||||||
|
|
||||||
|
let [elementTop, elementLeft] = this.positionMenu(bcr.top, bcr.right - 10, subMenuElement);
|
||||||
|
|
||||||
|
subMenuElement.style.left = `${elementLeft}px`;
|
||||||
|
subMenuElement.style.top = `${elementTop}px`;
|
||||||
|
|
||||||
|
this.activeSubMenu = subMenuElement;
|
||||||
|
},
|
||||||
|
|
||||||
|
closeSubMenu(event) {
|
||||||
|
const subMenuElement = this.getSubMenuElementByEvent(event),
|
||||||
|
parentMenu = parentElementByClassName(subMenuElement, 'v-context');
|
||||||
|
|
||||||
|
// if a sub menu is closed and it's not the currently active sub menu (eg. a lowe layered sub menu closed
|
||||||
|
// by a mouseleave event) close all nested sub menus
|
||||||
|
if (this.activeSubMenu !== subMenuElement) {
|
||||||
|
while (this.activeSubMenu !== null && this.activeSubMenu !== subMenuElement) {
|
||||||
|
parentElementByClassName(this.activeSubMenu, 'v-context__sub')
|
||||||
|
.dispatchEvent(new Event('mouseleave'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
subMenuElement.style.display = 'none';
|
||||||
|
|
||||||
|
// check if a parent menu exists and the parent menu is a sub menu to keep track of the correct sub menu
|
||||||
|
this.activeSubMenu = parentMenu && parentElementByClassName(parentMenu, 'v-context__sub')
|
||||||
|
? parentMenu
|
||||||
|
: null;
|
||||||
|
},
|
||||||
|
|
||||||
|
getSubMenuElementByEvent (event) {
|
||||||
|
return event.target.getElementsByTagName('ul')[0];
|
||||||
|
},
|
||||||
|
|
||||||
|
positionMenu(top, left, element) {
|
||||||
|
const largestHeight = window.innerHeight - element.offsetHeight - 25;
|
||||||
|
const largestWidth = window.innerWidth - element.offsetWidth - 25;
|
||||||
|
|
||||||
if (top > largestHeight) {
|
if (top > largestHeight) {
|
||||||
top = largestHeight;
|
top = largestHeight;
|
||||||
@@ -179,14 +281,22 @@ export default {
|
|||||||
left = largestWidth;
|
left = largestWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.top = top;
|
return [top, left];
|
||||||
this.left = left;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
removeScrollEventListener() {
|
removeScrollEventListener() {
|
||||||
eventOff(window, 'scroll', this.close);
|
eventOff(window, 'scroll', this.close);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
removeHoverEventListener(element) {
|
||||||
|
element.querySelectorAll('.v-context__sub').forEach(
|
||||||
|
(subMenuNode) => {
|
||||||
|
eventOff(subMenuNode, 'mouseenter', this.openSubMenu);
|
||||||
|
eventOff(subMenuNode, 'mouseleave', this.closeSubMenu);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
resetData() {
|
resetData() {
|
||||||
this.top = null;
|
this.top = null;
|
||||||
this.left = null;
|
this.left = null;
|
||||||
|
|||||||
+50
-33
@@ -1,47 +1,64 @@
|
|||||||
@import "config";
|
@import "config";
|
||||||
|
|
||||||
.v-context {
|
.v-context {
|
||||||
background-color: $menu-bg;
|
&, & ul {
|
||||||
background-clip: padding-box;
|
background-color: $menu-bg;
|
||||||
border-radius: .25rem;
|
background-clip: padding-box;
|
||||||
border: 1px solid $menu-border;
|
border-radius: .25rem;
|
||||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
|
border: 1px solid $menu-border;
|
||||||
display: block;
|
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
|
||||||
margin: 0;
|
display: block;
|
||||||
padding: 10px 0;
|
|
||||||
min-width: 10rem;
|
|
||||||
z-index: 1500;
|
|
||||||
position: fixed;
|
|
||||||
list-style: none;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
> li {
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
padding: 10px 0;
|
||||||
|
min-width: 10rem;
|
||||||
|
z-index: 1500;
|
||||||
|
position: fixed;
|
||||||
|
list-style: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
max-height: calc(100% - 50px);
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
> a {
|
> li {
|
||||||
display: block;
|
margin: 0;
|
||||||
padding: .5rem 1.5rem;
|
position: relative;
|
||||||
font-weight: 400;
|
|
||||||
color: $item-color;
|
|
||||||
text-decoration: none;
|
|
||||||
white-space: nowrap;
|
|
||||||
background-color: transparent;
|
|
||||||
border: 0;
|
|
||||||
|
|
||||||
&:hover,
|
> a {
|
||||||
&:focus {
|
display: block;
|
||||||
|
padding: .5rem 1.5rem;
|
||||||
|
font-weight: 400;
|
||||||
|
color: $item-color;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: $item-hover-color;
|
white-space: nowrap;
|
||||||
background-color: $item-hover-bg;
|
background-color: transparent;
|
||||||
}
|
border: 0;
|
||||||
|
|
||||||
&:focus {
|
&:hover,
|
||||||
outline: 0;
|
&:focus {
|
||||||
|
text-decoration: none;
|
||||||
|
color: $item-hover-color;
|
||||||
|
background-color: $item-hover-bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
&__sub {
|
||||||
outline: 0;
|
> a:after {
|
||||||
|
content: "\2bc8";
|
||||||
|
float: right;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
> ul {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+58
-1
@@ -27,12 +27,69 @@
|
|||||||
Do something
|
Do something
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li class="v-context__sub">
|
||||||
<a href="#" class="v-context-item"
|
<a href="#" class="v-context-item"
|
||||||
@click.prevent="onClick('item 2')"
|
@click.prevent="onClick('item 2')"
|
||||||
>
|
>
|
||||||
Do something else
|
Do something else
|
||||||
</a>
|
</a>
|
||||||
|
<ul class="v-context">
|
||||||
|
<li tabindex="0">
|
||||||
|
<a href="#" class="v-context-item"
|
||||||
|
@click.prevent="onClick('sub item 1')"
|
||||||
|
>
|
||||||
|
Submenu
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="v-context__sub">
|
||||||
|
<a href="#" class="v-context-item"
|
||||||
|
@click.prevent="onClick('sub item 2')"
|
||||||
|
>
|
||||||
|
Submenu next
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<ul class="v-context">
|
||||||
|
<li tabindex="0">
|
||||||
|
<a href="#" class="v-context-item"
|
||||||
|
@click.prevent="onClick('sub sub item 1')"
|
||||||
|
>
|
||||||
|
We need to go deeper
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li tabindex="0">
|
||||||
|
<a href="#" class="v-context-item"
|
||||||
|
@click.prevent="onClick('sub sub item 2')"
|
||||||
|
>
|
||||||
|
double nested Submenu
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#" class="v-context-item"
|
||||||
|
@click.prevent="onClick('sub item 3')"
|
||||||
|
>
|
||||||
|
Submenu next
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="v-context__sub">
|
||||||
|
<a href="#" class="v-context-item"
|
||||||
|
@click.prevent="onClick('sub item 4')"
|
||||||
|
>
|
||||||
|
second nested Submenu
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<ul class="v-context">
|
||||||
|
<li tabindex="0">
|
||||||
|
<a href="#" class="v-context-item"
|
||||||
|
@click.prevent="onClick('sub sub item 3')"
|
||||||
|
>
|
||||||
|
sub sub
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#" class="v-context-item"
|
<a href="#" class="v-context-item"
|
||||||
|
|||||||
Vendored
-46
@@ -1,46 +0,0 @@
|
|||||||
.v-context {
|
|
||||||
background-color: #fff;
|
|
||||||
background-clip: padding-box;
|
|
||||||
border-radius: 0.25rem;
|
|
||||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
|
||||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
|
|
||||||
display: block;
|
|
||||||
margin: 0;
|
|
||||||
padding: 10px 0;
|
|
||||||
min-width: 10rem;
|
|
||||||
z-index: 1500;
|
|
||||||
position: fixed;
|
|
||||||
list-style: none;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v-context > li {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v-context > li > a {
|
|
||||||
display: block;
|
|
||||||
padding: 0.5rem 1.5rem;
|
|
||||||
font-weight: 400;
|
|
||||||
color: #212529;
|
|
||||||
text-decoration: none;
|
|
||||||
white-space: nowrap;
|
|
||||||
background-color: transparent;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v-context > li > a:hover,
|
|
||||||
.v-context > li > a:focus {
|
|
||||||
text-decoration: none;
|
|
||||||
color: #212529;
|
|
||||||
background-color: #f8f9fa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v-context > li > a:focus {
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v-context:focus {
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vendored
-214
File diff suppressed because one or more lines are too long
@@ -1,6 +1,5 @@
|
|||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
// import { VueContext } from '../../../src/js/index';
|
import VueContext from '../../../src/js/index';
|
||||||
import { VueContext } from '../../../dist/js/vue-context';
|
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
components: {
|
components: {
|
||||||
|
|||||||
Reference in New Issue
Block a user