@ne1410s/menu 0.1.195 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +9 -21
- package/README.md +109 -109
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -0
- package/dist/index.iife.js +1 -0
- package/dist/index.js +1 -0
- package/dist/menu/menu.d.ts +4 -4
- package/dist/menu/menu.d.ts.map +1 -0
- package/package.json +70 -57
- package/dist/models.d.ts +0 -5
- package/dist/ne14_menu.cjs.min.js +0 -176
- package/dist/ne14_menu.esm.min.js +0 -174
- package/dist/ne14_menu.umd.min.js +0 -450
package/LICENSE
CHANGED
|
@@ -1,21 +1,9 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c)
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
|
|
7
|
-
in
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ne1410s
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,109 +1,109 @@
|
|
|
1
|
-
# @ne1410s/demo
|
|
2
|
-
|
|
3
|
-
## A lightweight and customisable context menu.
|
|
4
|
-
|
|
5
|
-
```html
|
|
6
|
-
<ne14-menu>
|
|
7
|
-
<li>Hello world</li>
|
|
8
|
-
<li class="split"></li>
|
|
9
|
-
<li>
|
|
10
|
-
<span>Nested Item</span>
|
|
11
|
-
<ul>
|
|
12
|
-
<li>Item 1</li>
|
|
13
|
-
<li class="disabled">Item 2</li>
|
|
14
|
-
</ul>
|
|
15
|
-
</li>
|
|
16
|
-
</ne14-menu>
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
### What Does It Do?
|
|
20
|
-
|
|
21
|
-
- Provides a context menu with sub-menu support, based on original markup
|
|
22
|
-
- Supports `<a href target>` tags to navigate in new tab or in current tab accordingly
|
|
23
|
-
- Appears and behaves like a browser's "default" context menu
|
|
24
|
-
- Supports item disabling and hiding alike
|
|
25
|
-
- Provides splitters for logical grouping, the presence of which is monitored to strip out orphaned zones / multiple splitters from appearing
|
|
26
|
-
- Supports unicode charset (hex) for icons at either side of the item text, and/or `<img>` tags
|
|
27
|
-
- Displays shortcut keys (the implementation of which is left to the author)
|
|
28
|
-
- Inherits the font family and size (size is ~2/3 that of the html root)
|
|
29
|
-
|
|
30
|
-
### How Do I Use It?
|
|
31
|
-
|
|
32
|
-
1. Include the umd script in the head `<script src="PATH_TO_UMD_SCRIPT"></script>`
|
|
33
|
-
2. Declare (or programatically construct) your markup (using below guide)
|
|
34
|
-
- Whatever click handling you have will be invoked when items are clicked
|
|
35
|
-
3. Position the menu html inside whichever container element(s) the menu applies
|
|
36
|
-
- **Yes you can easily have different menus for different zones!**
|
|
37
|
-
4. If your menu doesn't need to change, that's all you need to do
|
|
38
|
-
5. But if you did wish to effect a change dynamically, then just alter the structure accordingly and call `.reload()` on the menu instance
|
|
39
|
-
|
|
40
|
-
### Guidance, Please
|
|
41
|
-
|
|
42
|
-
- Specify only `<li>` nodes as direct descendants
|
|
43
|
-
- Provide some kind of node text (e.g. either directly or in a `<p>` or `<span>`)
|
|
44
|
-
- Use `li.split` to make a divider line
|
|
45
|
-
- Use `li.disabled` to "grey-out" an item
|
|
46
|
-
- Use `li.hidden` to conceal an item entirely
|
|
47
|
-
- Images & font icons can be included either side of the menu item text:
|
|
48
|
-
- Icons are unicode charset hex references, specified on the `<li>` as either `data-char-left` / `data-char-right`. If present, these supersede images. If _not_ present: ...
|
|
49
|
-
- The first nested `<img>` (to not have a `right` class) is used on the left
|
|
50
|
-
- The first nested `<img class='right'>` is used on the right
|
|
51
|
-
- Use `aria-keyshortcuts` to show a command shortcut (this is _not_ implemented by this component however, it is just to display anything that has been)
|
|
52
|
-
|
|
53
|
-
NB: To extend this library, or import it in node js, use: _npm i -S @ne1410s/menu_
|
|
54
|
-
|
|
55
|
-
### Attributes
|
|
56
|
-
|
|
57
|
-
- _There are no bespoke attributes exposed in this element_
|
|
58
|
-
|
|
59
|
-
### Events
|
|
60
|
-
|
|
61
|
-
```javascript
|
|
62
|
-
const menu = document.querySelector('ne14-menu');
|
|
63
|
-
|
|
64
|
-
// As mentioned, each item click is propagated on the original element.
|
|
65
|
-
// Instead of (or as well as) dedicated handling, one may also proceed via the
|
|
66
|
-
// following generic selection handler
|
|
67
|
-
menu.addEventListener('itemselect', (event) => {
|
|
68
|
-
console.log('Item Selected!', event);
|
|
69
|
-
});
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
- `itemselect` occurs when an item is clicked. The custom event detail contains the text of the menu item, its in-menu reference and the original html element
|
|
73
|
-
- `itemhover` and `itemunhover` occur when mouse enters or leaves an item
|
|
74
|
-
- `menuopen` and `menuclose` occur when the menu is opened or closed
|
|
75
|
-
|
|
76
|
-
### Methods
|
|
77
|
-
|
|
78
|
-
- `open()` Opens the menu (after closing any others)
|
|
79
|
-
- `close()` Closes the menu
|
|
80
|
-
- `reload()` Recreates the menu according to its current content
|
|
81
|
-
|
|
82
|
-
### Properties
|
|
83
|
-
|
|
84
|
-
- _There are no bespoke properties exposed in this element_
|
|
85
|
-
|
|
86
|
-
### CSS Variables
|
|
87
|
-
|
|
88
|
-
Some degree of custom styling can be optionally provided, by way of css variables:
|
|
89
|
-
|
|
90
|
-
```css
|
|
91
|
-
/* Example of 'dark mode': */
|
|
92
|
-
ne14-menu {
|
|
93
|
-
--bg: #333;
|
|
94
|
-
--border: 1px solid #888;
|
|
95
|
-
--box-shadow: 2px 2px 3px #333;
|
|
96
|
-
--hover-item-bg: #666;
|
|
97
|
-
--fg: #eee;
|
|
98
|
-
--disabled-fg: #666;
|
|
99
|
-
}
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
- **`--bg`** _Background for the menu. Defaults to: `#fff`_
|
|
103
|
-
- **`--border`** _Border for the menu. Defaults to: `1px solid #bbb`_
|
|
104
|
-
- **`--box-shadow`** _Box shadow for the menu. Defaults to: `2px 2px 3px #888`_
|
|
105
|
-
- **`--font`** _Font for the menu. Defaults to: `0.65em inherit`_
|
|
106
|
-
- **`--fg`** _Color for menu items. Defaults to: `#000`_
|
|
107
|
-
- **`--disabled-fg`** _Color for disabled menu items. Defaults to: `#bbb`_
|
|
108
|
-
- **`--split-border`** _Border for split lines. Defaults to: `--border` else `1px solid #bbb`_
|
|
109
|
-
- **`--hover-item-bg`** _Background color for items in the hover state. Defaults to: `#bbb`_
|
|
1
|
+
# @ne1410s/demo
|
|
2
|
+
|
|
3
|
+
## A lightweight and customisable context menu.
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<ne14-menu>
|
|
7
|
+
<li>Hello world</li>
|
|
8
|
+
<li class="split"></li>
|
|
9
|
+
<li>
|
|
10
|
+
<span>Nested Item</span>
|
|
11
|
+
<ul>
|
|
12
|
+
<li>Item 1</li>
|
|
13
|
+
<li class="disabled">Item 2</li>
|
|
14
|
+
</ul>
|
|
15
|
+
</li>
|
|
16
|
+
</ne14-menu>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### What Does It Do?
|
|
20
|
+
|
|
21
|
+
- Provides a context menu with sub-menu support, based on original markup
|
|
22
|
+
- Supports `<a href target>` tags to navigate in new tab or in current tab accordingly
|
|
23
|
+
- Appears and behaves like a browser's "default" context menu
|
|
24
|
+
- Supports item disabling and hiding alike
|
|
25
|
+
- Provides splitters for logical grouping, the presence of which is monitored to strip out orphaned zones / multiple splitters from appearing
|
|
26
|
+
- Supports unicode charset (hex) for icons at either side of the item text, and/or `<img>` tags
|
|
27
|
+
- Displays shortcut keys (the implementation of which is left to the author)
|
|
28
|
+
- Inherits the font family and size (size is ~2/3 that of the html root)
|
|
29
|
+
|
|
30
|
+
### How Do I Use It?
|
|
31
|
+
|
|
32
|
+
1. Include the umd script in the head `<script src="PATH_TO_UMD_SCRIPT"></script>`
|
|
33
|
+
2. Declare (or programatically construct) your markup (using below guide)
|
|
34
|
+
- Whatever click handling you have will be invoked when items are clicked
|
|
35
|
+
3. Position the menu html inside whichever container element(s) the menu applies
|
|
36
|
+
- **Yes you can easily have different menus for different zones!**
|
|
37
|
+
4. If your menu doesn't need to change, that's all you need to do
|
|
38
|
+
5. But if you did wish to effect a change dynamically, then just alter the structure accordingly and call `.reload()` on the menu instance
|
|
39
|
+
|
|
40
|
+
### Guidance, Please
|
|
41
|
+
|
|
42
|
+
- Specify only `<li>` nodes as direct descendants
|
|
43
|
+
- Provide some kind of node text (e.g. either directly or in a `<p>` or `<span>`)
|
|
44
|
+
- Use `li.split` to make a divider line
|
|
45
|
+
- Use `li.disabled` to "grey-out" an item
|
|
46
|
+
- Use `li.hidden` to conceal an item entirely
|
|
47
|
+
- Images & font icons can be included either side of the menu item text:
|
|
48
|
+
- Icons are unicode charset hex references, specified on the `<li>` as either `data-char-left` / `data-char-right`. If present, these supersede images. If _not_ present: ...
|
|
49
|
+
- The first nested `<img>` (to not have a `right` class) is used on the left
|
|
50
|
+
- The first nested `<img class='right'>` is used on the right
|
|
51
|
+
- Use `aria-keyshortcuts` to show a command shortcut (this is _not_ implemented by this component however, it is just to display anything that has been)
|
|
52
|
+
|
|
53
|
+
NB: To extend this library, or import it in node js, use: _npm i -S @ne1410s/menu_
|
|
54
|
+
|
|
55
|
+
### Attributes
|
|
56
|
+
|
|
57
|
+
- _There are no bespoke attributes exposed in this element_
|
|
58
|
+
|
|
59
|
+
### Events
|
|
60
|
+
|
|
61
|
+
```javascript
|
|
62
|
+
const menu = document.querySelector('ne14-menu');
|
|
63
|
+
|
|
64
|
+
// As mentioned, each item click is propagated on the original element.
|
|
65
|
+
// Instead of (or as well as) dedicated handling, one may also proceed via the
|
|
66
|
+
// following generic selection handler
|
|
67
|
+
menu.addEventListener('itemselect', (event) => {
|
|
68
|
+
console.log('Item Selected!', event);
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
- `itemselect` occurs when an item is clicked. The custom event detail contains the text of the menu item, its in-menu reference and the original html element
|
|
73
|
+
- `itemhover` and `itemunhover` occur when mouse enters or leaves an item
|
|
74
|
+
- `menuopen` and `menuclose` occur when the menu is opened or closed
|
|
75
|
+
|
|
76
|
+
### Methods
|
|
77
|
+
|
|
78
|
+
- `open()` Opens the menu (after closing any others)
|
|
79
|
+
- `close()` Closes the menu
|
|
80
|
+
- `reload()` Recreates the menu according to its current content
|
|
81
|
+
|
|
82
|
+
### Properties
|
|
83
|
+
|
|
84
|
+
- _There are no bespoke properties exposed in this element_
|
|
85
|
+
|
|
86
|
+
### CSS Variables
|
|
87
|
+
|
|
88
|
+
Some degree of custom styling can be optionally provided, by way of css variables:
|
|
89
|
+
|
|
90
|
+
```css
|
|
91
|
+
/* Example of 'dark mode': */
|
|
92
|
+
ne14-menu {
|
|
93
|
+
--bg: #333;
|
|
94
|
+
--border: 1px solid #888;
|
|
95
|
+
--box-shadow: 2px 2px 3px #333;
|
|
96
|
+
--hover-item-bg: #666;
|
|
97
|
+
--fg: #eee;
|
|
98
|
+
--disabled-fg: #666;
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
- **`--bg`** _Background for the menu. Defaults to: `#fff`_
|
|
103
|
+
- **`--border`** _Border for the menu. Defaults to: `1px solid #bbb`_
|
|
104
|
+
- **`--box-shadow`** _Box shadow for the menu. Defaults to: `2px 2px 3px #888`_
|
|
105
|
+
- **`--font`** _Font for the menu. Defaults to: `0.65em inherit`_
|
|
106
|
+
- **`--fg`** _Color for menu items. Defaults to: `#000`_
|
|
107
|
+
- **`--disabled-fg`** _Color for disabled menu items. Defaults to: `#bbb`_
|
|
108
|
+
- **`--split-border`** _Border for split lines. Defaults to: `--border` else `1px solid #bbb`_
|
|
109
|
+
- **`--hover-item-bg`** _Background color for items in the hover state. Defaults to: `#bbb`_
|
package/dist/index.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAMrC,OAAO,EAAE,MAAM,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var ne_menu=(()=>{var A=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var F=Object.getOwnPropertyNames;var B=Object.prototype.hasOwnProperty;var j=(s,t)=>{for(var e in t)A(s,e,{get:t[e],enumerable:!0})},Q=(s,t,e,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of F(t))!B.call(s,i)&&i!==e&&A(s,i,{get:()=>t[i],enumerable:!(n=z(t,i))||n.enumerable});return s};var V=s=>Q(A({},"__esModule",{value:!0}),s);var K={};j(K,{NeMenu:()=>E});var N='@charset "UTF-8";li,ul{padding:0;margin:0;font:inherit}li.split .icon,slot{display:none}.top:not(.open),ul:not(.top){visibility:hidden}ul{border:var(--border,1px solid #bbb);background:var(--bg,#fff);box-shadow:var(--box-shadow,2px 2px 3px #888);transition:background-color .6s;z-index:9999999}.top{position:fixed;font-size:var(--font-size, .65rem);user-select:none}.icon.left{left:1em;transform:translate(-50%,-50%)}.icon.right{right:1em;transform:translate(50%,-50%)}.icon{max-width:1em;max-height:1em;position:absolute;top:50%;line-height:0}li>p:not(:empty){margin:0 1em;white-space:nowrap}li.disabled{color:var(--disabled-fg,#bbb)}li.split{border-top:var(--split-border,var(--border,1px solid #bbb));padding:0;margin:.3em}li.split+li.split,li.split:first-child,li.split:last-child{display:none}li.hover:not(.disabed):not(.split){background:var(--hover-item-bg,#bbb)}.top.open li.hover>ul{visibility:visible}li{margin:.2em 0;padding:.5em 1em;display:flex;justify-content:space-between;text-align:left;position:relative;cursor:default;color:var(--fg,#000)}li.group::after{content:"\u25B6";position:absolute;font-size:.65em;right:0;top:50%;transform:translate(-50%,-50%)}ul:not(.top){position:absolute;left:100%;top:-.25em}ul.nestle{left:.5em;top:100%}';var _='<slot></slot><ul class="top"></ul>';var f=class s{mapper;static WHITESPACE_RGX=/\s+/;_items=[];get targets(){return this._items.filter(t=>t instanceof EventTarget).map(t=>t)}get elements(){return this._items.filter(t=>t instanceof Element).map(t=>t)}get nodes(){return this._items.filter(t=>t instanceof Node).map(t=>t)}get containers(){return this._items.map(t=>t).filter(t=>typeof t.append=="function")}get length(){return this._items.length}constructor(t,...e){this.mapper=t,this.add(...e)}get=t=>this._items[t];add(...t){return this._items.push(...this.mapper.Map(t)),this}each(t){return this._items.forEach((e,n)=>t(e,n)),this}prop(t,e){return this.each(n=>{t in n&&(n[t]=e)})}fire(t,e){let n=new CustomEvent(t,{detail:e});return this.targets.forEach(i=>i.dispatchEvent(n)),this}on(t,e){let n=t.split(s.WHITESPACE_RGX);return this.targets.forEach(i=>{n.forEach(h=>i.addEventListener(h,e))}),this}attr(t,e,n){return this.elements.forEach(i=>{e!=null?i.setAttributeNS(n??null,t,e):i.removeAttributeNS(n??null,t)}),this}toggle(t,e){return this.elements.forEach(n=>{let i=typeof e=="function"?e(n):!!e;n.classList.toggle(t,i)}),this}empty(){return this.nodes.forEach(t=>{for(;t.firstChild;)t.removeChild(t.firstChild)}),this}remove(){return new s(this.mapper,...this._items.filter(t=>{let e=t instanceof Node;return e&&t?.parentNode?.removeChild(t),!e}))}append(...t){return this.appendIn(...t),this}appendIn(...t){return new s(this.mapper,...this.containers.reduce((e,n)=>{let i=new s(this.mapper,...t).nodes;return n.append(...i),e.push(...i),e},[]))}find(t){return new s(this.mapper,...this.containers.reduce((e,n)=>(e.push(...Array.from(n.querySelectorAll(t))),e),[]))}first(t){return new s(this.mapper,...this.containers.map(e=>e.querySelector(t)).filter(e=>!!e))}};var M=class s{static NAIVE_HTML_RGX=/^\s*<.*>\s*$/m;Map(t){return t.reduce((e,n)=>(typeof n=="string"?e.push(...s.NAIVE_HTML_RGX.test(n)?s.MapHTML(n):s.MapSelector(n)):n.tag?e.push(s.MapParam(n)):n instanceof Node||n instanceof EventTarget?e.push(n):n instanceof f?n.each(i=>e.push(i)):console.warn("Unrecognised item:",n),e),[])}static MapHTML(t){let e=document.createElement("template");return e.innerHTML=t,Array.from(e.content.childNodes)}static MapSelector(t){return Array.from(document.querySelectorAll(t))}static MapParam(t){let e=document.createElement(t.tag);t.text&&(e.textContent=t.text);for(let n in t.attr||{})t.attr?.[n]!=null&&e.setAttribute(n,t.attr[n]);for(let n in t.evts||{})typeof t.evts?.[n]=="function"&&e.addEventListener(n,t.evts[n]);return e}};var J=new M;function a(...s){return new f(J,...s)}var E=class s extends HTMLElement{constructor(){super();this._connected=!1;this.root=this.attachShadow({mode:"open"});let e=new CSSStyleSheet;e.replaceSync(N),this.shadowRoot.adoptedStyleSheets=[e],this.shadowRoot.innerHTML=_,this.top=this.root.querySelector("ul")}static{this.CHAR_REF_REGEX=/^[0-9a-f]{4,5}$/i}connectedCallback(){this._connected||(setTimeout(()=>this.reload()),a(this.parentNode).on("contextmenu",e=>this.onParentContext(e)),a(this,this.parentNode).on("contextmenu wheel",e=>{e.preventDefault(),e.stopPropagation()}),a(this).on("mousedown",e=>e.stopPropagation()),a(window).on("mousedown resize wheel",()=>this.close()),this._connected=!0)}open(){this.parentElement.getRootNode().querySelectorAll("new-demo").forEach(n=>n.close()),this.top.classList.add("open"),a(this).fire("menuopen")}close(){this.top.classList.contains("open")&&(this.top.classList.remove("open"),a(this).fire("menuclose"))}reload(){a(this.top).empty().append(...this.walk(this,!1))}onParentContext(e){if(this.isConnected){let n=e.clientY,i=this.top.offsetHeight,h=n+i+2>window.innerHeight?n-i:n;this.top.style.top=`${Math.max(0,h)}px`;let r=e.clientX,v=this.top.offsetWidth,c=r+v+2>window.innerWidth?r-v:r;this.top.style.left=`${Math.max(0,c)}px`,this.open()}}walk(e,n,i=""){let h=0;return Array.from(e.children).filter(r=>r instanceof HTMLLIElement&&!r.classList.contains("hidden")&&(r.textContent||r.classList.contains("split"))).reduce((r,v)=>{let c=v,L=Array.from(c.children).map(o=>o),b=L.find(o=>o instanceof HTMLAnchorElement),T=L.find(o=>o instanceof HTMLUListElement),l=c.classList.contains("split"),m=!l&&T&&T.querySelector("li"),g=!l&&(n||c.classList.contains("disabled")),P=Array.from(b?.children||[]).map(o=>o),R=L.concat(P).filter(o=>o instanceof HTMLImageElement).map(o=>o);l||h++;let d=[];l?d.push("split"):(g&&d.push("disabled"),m&&d.push("group"),b?.target==="_blank"?d.push("click-out"):b&&d.push("click-in"));let X=[...L,c].find(o=>o.innerText),u=l?void 0:X?.innerText??`Item ${h}`,H=l||m?null:c.getAttribute("aria-keyshortcuts"),S=`${i}${h}`,x={ref:S,title:u,origin:b||c},q=()=>{!g&&!m&&!l&&(x.origin.click(),a(this).fire("itemselect",x),this.close())},G=o=>{if(!g&&!l){let C=o.target;if(m){let $=Array.from(C.children).find(W=>W instanceof HTMLUListElement),D=C.getBoundingClientRect();$.classList.toggle("nestle",D.right+$.clientWidth+2>window.innerWidth)}C.classList.add("hover"),a(this).fire("itemhover",x)}},U=o=>{!g&&!l&&(o.target.classList.remove("hover"),a(this).fire("itemunhover",x))},p=a({tag:"li"}).attr("class",d.length?d.join(" "):null).attr("aria-keyshortcuts",H).on("click contextmenu",q).on("mouseenter",G).on("mouseleave",U),y=c.dataset.charLeft||"",w=c.dataset.charRight||"",k=R.find(o=>!o.classList.contains("right")),I=R.find(o=>o.classList.contains("right"));return!l&&!m&&u&&(s.CHAR_REF_REGEX.test(y)?p.append(`<span class='icon left'>&#x${y};</span>`):y?console.warn(`ne14-menu: Bad hex code '${y}' to left of '${u}'.`):k&&p.append(`<img class='icon left' src='${k.src}'/>`),s.CHAR_REF_REGEX.test(w)?p.append(`<span class='icon right'>&#x${w};</span>`):w?console.warn(`ne14-menu: Bad hex code '${w}' to right of '${u}'.`):I&&p.append(`<img class='icon right' src='${I.src}'/>`)),u&&p.append({tag:"p",text:u}),H&&p.append({tag:"p",text:H}),m&&p.appendIn({tag:"ul"}).append(...this.walk(T,g,`${S}-`)),(!l||!r[r.length-1]?.classList?.contains("split"))&&r.push(p.elements[0]),r},[])}};customElements.get("ne14-menu")||customElements.define("ne14-menu",E);return V(K);})();
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var $='@charset "UTF-8";li,ul{padding:0;margin:0;font:inherit}li.split .icon,slot{display:none}.top:not(.open),ul:not(.top){visibility:hidden}ul{border:var(--border,1px solid #bbb);background:var(--bg,#fff);box-shadow:var(--box-shadow,2px 2px 3px #888);transition:background-color .6s;z-index:9999999}.top{position:fixed;font-size:var(--font-size, .65rem);user-select:none}.icon.left{left:1em;transform:translate(-50%,-50%)}.icon.right{right:1em;transform:translate(50%,-50%)}.icon{max-width:1em;max-height:1em;position:absolute;top:50%;line-height:0}li>p:not(:empty){margin:0 1em;white-space:nowrap}li.disabled{color:var(--disabled-fg,#bbb)}li.split{border-top:var(--split-border,var(--border,1px solid #bbb));padding:0;margin:.3em}li.split+li.split,li.split:first-child,li.split:last-child{display:none}li.hover:not(.disabed):not(.split){background:var(--hover-item-bg,#bbb)}.top.open li.hover>ul{visibility:visible}li{margin:.2em 0;padding:.5em 1em;display:flex;justify-content:space-between;text-align:left;position:relative;cursor:default;color:var(--fg,#000)}li.group::after{content:"\u25B6";position:absolute;font-size:.65em;right:0;top:50%;transform:translate(-50%,-50%)}ul:not(.top){position:absolute;left:100%;top:-.25em}ul.nestle{left:.5em;top:100%}';var N='<slot></slot><ul class="top"></ul>';var f=class o{mapper;static WHITESPACE_RGX=/\s+/;_items=[];get targets(){return this._items.filter(t=>t instanceof EventTarget).map(t=>t)}get elements(){return this._items.filter(t=>t instanceof Element).map(t=>t)}get nodes(){return this._items.filter(t=>t instanceof Node).map(t=>t)}get containers(){return this._items.map(t=>t).filter(t=>typeof t.append=="function")}get length(){return this._items.length}constructor(t,...e){this.mapper=t,this.add(...e)}get=t=>this._items[t];add(...t){return this._items.push(...this.mapper.Map(t)),this}each(t){return this._items.forEach((e,n)=>t(e,n)),this}prop(t,e){return this.each(n=>{t in n&&(n[t]=e)})}fire(t,e){let n=new CustomEvent(t,{detail:e});return this.targets.forEach(i=>i.dispatchEvent(n)),this}on(t,e){let n=t.split(o.WHITESPACE_RGX);return this.targets.forEach(i=>{n.forEach(h=>i.addEventListener(h,e))}),this}attr(t,e,n){return this.elements.forEach(i=>{e!=null?i.setAttributeNS(n??null,t,e):i.removeAttributeNS(n??null,t)}),this}toggle(t,e){return this.elements.forEach(n=>{let i=typeof e=="function"?e(n):!!e;n.classList.toggle(t,i)}),this}empty(){return this.nodes.forEach(t=>{for(;t.firstChild;)t.removeChild(t.firstChild)}),this}remove(){return new o(this.mapper,...this._items.filter(t=>{let e=t instanceof Node;return e&&t?.parentNode?.removeChild(t),!e}))}append(...t){return this.appendIn(...t),this}appendIn(...t){return new o(this.mapper,...this.containers.reduce((e,n)=>{let i=new o(this.mapper,...t).nodes;return n.append(...i),e.push(...i),e},[]))}find(t){return new o(this.mapper,...this.containers.reduce((e,n)=>(e.push(...Array.from(n.querySelectorAll(t))),e),[]))}first(t){return new o(this.mapper,...this.containers.map(e=>e.querySelector(t)).filter(e=>!!e))}};var w=class o{static NAIVE_HTML_RGX=/^\s*<.*>\s*$/m;Map(t){return t.reduce((e,n)=>(typeof n=="string"?e.push(...o.NAIVE_HTML_RGX.test(n)?o.MapHTML(n):o.MapSelector(n)):n.tag?e.push(o.MapParam(n)):n instanceof Node||n instanceof EventTarget?e.push(n):n instanceof f?n.each(i=>e.push(i)):console.warn("Unrecognised item:",n),e),[])}static MapHTML(t){let e=document.createElement("template");return e.innerHTML=t,Array.from(e.content.childNodes)}static MapSelector(t){return Array.from(document.querySelectorAll(t))}static MapParam(t){let e=document.createElement(t.tag);t.text&&(e.textContent=t.text);for(let n in t.attr||{})t.attr?.[n]!=null&&e.setAttribute(n,t.attr[n]);for(let n in t.evts||{})typeof t.evts?.[n]=="function"&&e.addEventListener(n,t.evts[n]);return e}};var z=new w;function a(...o){return new f(z,...o)}var M=class o extends HTMLElement{constructor(){super();this._connected=!1;this.root=this.attachShadow({mode:"open"});let e=new CSSStyleSheet;e.replaceSync($),this.shadowRoot.adoptedStyleSheets=[e],this.shadowRoot.innerHTML=N,this.top=this.root.querySelector("ul")}static{this.CHAR_REF_REGEX=/^[0-9a-f]{4,5}$/i}connectedCallback(){this._connected||(setTimeout(()=>this.reload()),a(this.parentNode).on("contextmenu",e=>this.onParentContext(e)),a(this,this.parentNode).on("contextmenu wheel",e=>{e.preventDefault(),e.stopPropagation()}),a(this).on("mousedown",e=>e.stopPropagation()),a(window).on("mousedown resize wheel",()=>this.close()),this._connected=!0)}open(){this.parentElement.getRootNode().querySelectorAll("new-demo").forEach(n=>n.close()),this.top.classList.add("open"),a(this).fire("menuopen")}close(){this.top.classList.contains("open")&&(this.top.classList.remove("open"),a(this).fire("menuclose"))}reload(){a(this.top).empty().append(...this.walk(this,!1))}onParentContext(e){if(this.isConnected){let n=e.clientY,i=this.top.offsetHeight,h=n+i+2>window.innerHeight?n-i:n;this.top.style.top=`${Math.max(0,h)}px`;let r=e.clientX,E=this.top.offsetWidth,c=r+E+2>window.innerWidth?r-E:r;this.top.style.left=`${Math.max(0,c)}px`,this.open()}}walk(e,n,i=""){let h=0;return Array.from(e.children).filter(r=>r instanceof HTMLLIElement&&!r.classList.contains("hidden")&&(r.textContent||r.classList.contains("split"))).reduce((r,E)=>{let c=E,v=Array.from(c.children).map(s=>s),L=v.find(s=>s instanceof HTMLAnchorElement),T=v.find(s=>s instanceof HTMLUListElement),l=c.classList.contains("split"),m=!l&&T&&T.querySelector("li"),g=!l&&(n||c.classList.contains("disabled")),_=Array.from(L?.children||[]).map(s=>s),A=v.concat(_).filter(s=>s instanceof HTMLImageElement).map(s=>s);l||h++;let d=[];l?d.push("split"):(g&&d.push("disabled"),m&&d.push("group"),L?.target==="_blank"?d.push("click-out"):L&&d.push("click-in"));let P=[...v,c].find(s=>s.innerText),u=l?void 0:P?.innerText??`Item ${h}`,H=l||m?null:c.getAttribute("aria-keyshortcuts"),R=`${i}${h}`,b={ref:R,title:u,origin:L||c},X=()=>{!g&&!m&&!l&&(b.origin.click(),a(this).fire("itemselect",b),this.close())},q=s=>{if(!g&&!l){let C=s.target;if(m){let I=Array.from(C.children).find(D=>D instanceof HTMLUListElement),U=C.getBoundingClientRect();I.classList.toggle("nestle",U.right+I.clientWidth+2>window.innerWidth)}C.classList.add("hover"),a(this).fire("itemhover",b)}},G=s=>{!g&&!l&&(s.target.classList.remove("hover"),a(this).fire("itemunhover",b))},p=a({tag:"li"}).attr("class",d.length?d.join(" "):null).attr("aria-keyshortcuts",H).on("click contextmenu",X).on("mouseenter",q).on("mouseleave",G),x=c.dataset.charLeft||"",y=c.dataset.charRight||"",S=A.find(s=>!s.classList.contains("right")),k=A.find(s=>s.classList.contains("right"));return!l&&!m&&u&&(o.CHAR_REF_REGEX.test(x)?p.append(`<span class='icon left'>&#x${x};</span>`):x?console.warn(`ne14-menu: Bad hex code '${x}' to left of '${u}'.`):S&&p.append(`<img class='icon left' src='${S.src}'/>`),o.CHAR_REF_REGEX.test(y)?p.append(`<span class='icon right'>&#x${y};</span>`):y?console.warn(`ne14-menu: Bad hex code '${y}' to right of '${u}'.`):k&&p.append(`<img class='icon right' src='${k.src}'/>`)),u&&p.append({tag:"p",text:u}),H&&p.append({tag:"p",text:H}),m&&p.appendIn({tag:"ul"}).append(...this.walk(T,g,`${R}-`)),(!l||!r[r.length-1]?.classList?.contains("split"))&&r.push(p.elements[0]),r},[])}};customElements.get("ne14-menu")||customElements.define("ne14-menu",M);export{M as NeMenu};
|
package/dist/menu/menu.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
export declare class NeMenu extends
|
|
3
|
-
private static readonly Css;
|
|
4
|
-
private static readonly Html;
|
|
1
|
+
/** Customisable context menu component. */
|
|
2
|
+
export declare class NeMenu extends HTMLElement {
|
|
5
3
|
private static readonly CHAR_REF_REGEX;
|
|
4
|
+
private readonly root;
|
|
6
5
|
private readonly top;
|
|
7
6
|
private _connected;
|
|
8
7
|
constructor();
|
|
@@ -16,3 +15,4 @@ export declare class NeMenu extends CustomElementBase {
|
|
|
16
15
|
private onParentContext;
|
|
17
16
|
private walk;
|
|
18
17
|
}
|
|
18
|
+
//# sourceMappingURL=menu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"menu.d.ts","sourceRoot":"","sources":["../../src/menu/menu.ts"],"names":[],"mappings":"AAUA,2CAA2C;AAC3C,qBAAa,MAAO,SAAQ,WAAW;IACrC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAsB;IAE5D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAmB;IACvC,OAAO,CAAC,UAAU,CAAkB;IAMpC,cAQC;IAED,iBAAiB,SAahB;IAED,uBAAuB;IACvB,IAAI,IAAI,IAAI,CAQX;IAED,uBAAuB;IACvB,KAAK,IAAI,IAAI,CAKZ;IAED,mDAAmD;IACnD,MAAM,IAAI,IAAI,CAIb;IAED,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,IAAI;CAuGb"}
|
package/package.json
CHANGED
|
@@ -1,57 +1,70 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@ne1410s/menu",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
},
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
|
|
57
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@ne1410s/menu",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"displayName": "ne_menu",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
},
|
|
14
|
+
"./iife": "./dist/index.iife.js"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"description": "An element that provides customisable context menu.",
|
|
20
|
+
"author": "ne1410s <pgj646@gmail.com> (http://ne1410s.co.uk)",
|
|
21
|
+
"keywords": [
|
|
22
|
+
"Text",
|
|
23
|
+
"Utils"
|
|
24
|
+
],
|
|
25
|
+
"homepage": "https://github.com/ne14-fed/elem.menu#readme",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/ne14-fed/elem.menu.git"
|
|
30
|
+
},
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/ne14-fed/elem.menu/issues"
|
|
33
|
+
},
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=20"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"dev": "npm link && concurrently \"npm run build:watch\" \"npm run demo:iife\" \"npm run demo:vite\"",
|
|
39
|
+
"clean": "del-cli dist",
|
|
40
|
+
"is-pretty": "prettier -l .",
|
|
41
|
+
"prettify": "prettier -w .",
|
|
42
|
+
"build": "npm run clean && tsc && node esbuild.mjs",
|
|
43
|
+
"build:watch": "concurrently \"tsc --watch\" \"node esbuild.mjs --watch\"",
|
|
44
|
+
"demo:vite": "cd demo/vite && npm i && npm link @ne1410s/menu && npx vite",
|
|
45
|
+
"demo:iife": "npx live-server demo/iife --mount=/package:dist --no-css-inject",
|
|
46
|
+
"test": "npm run typecheck && npm run is-pretty",
|
|
47
|
+
"typecheck": "tsc --noEmit",
|
|
48
|
+
"publish-local": "npm run build && npm pack",
|
|
49
|
+
"publish-patch": "npm run build && npm version patch && npm publish --access public",
|
|
50
|
+
"publish-minor": "npm run build && npm version minor && npm publish --access public",
|
|
51
|
+
"publish-major": "npm run build && npm version major && npm publish --access public"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"clean-css": "^5.3.3",
|
|
55
|
+
"concurrently": "^10.0.4",
|
|
56
|
+
"del-cli": "^7.0.0",
|
|
57
|
+
"esbuild": "^0.28.2",
|
|
58
|
+
"esbuild-sass-plugin": "^3.7.0",
|
|
59
|
+
"html-minifier-terser": "^7.2.0",
|
|
60
|
+
"prettier": "^3.9.6",
|
|
61
|
+
"typescript": "^7.0.2"
|
|
62
|
+
},
|
|
63
|
+
"dependencies": {
|
|
64
|
+
"@ne1410s/dom": "^0.3.184"
|
|
65
|
+
},
|
|
66
|
+
"allowScripts": {
|
|
67
|
+
"esbuild@0.28.2": true,
|
|
68
|
+
"@parcel/watcher@2.6.0": true
|
|
69
|
+
}
|
|
70
|
+
}
|
package/dist/models.d.ts
DELETED
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var dom = require('@ne1410s/dom');
|
|
4
|
-
var custElems = require('@ne1410s/cust-elems');
|
|
5
|
-
|
|
6
|
-
var markupUrl = "data:text/html;base64,PHNsb3Q+PC9zbG90Pg0KPHVsIGNsYXNzPSJ0b3AiPjwvdWw+DQo=";
|
|
7
|
-
|
|
8
|
-
var stylesUrl = "data:text/css;base64,dWwsDQpsaSB7DQogIHBhZGRpbmc6IDA7DQogIG1hcmdpbjogMDsNCiAgZm9udDogaW5oZXJpdDsNCn0NCnNsb3QsDQpsaS5zcGxpdCAuaWNvbiB7DQogIGRpc3BsYXk6IG5vbmU7DQp9DQoudG9wOm5vdCgub3BlbiksDQp1bDpub3QoLnRvcCkgew0KICB2aXNpYmlsaXR5OiBoaWRkZW47DQp9DQoNCnVsIHsNCiAgYm9yZGVyOiB2YXIoLS1ib3JkZXIsIDFweCBzb2xpZCAjYmJiKTsNCiAgYmFja2dyb3VuZDogdmFyKC0tYmcsICNmZmYpOw0KICBib3gtc2hhZG93OiB2YXIoLS1ib3gtc2hhZG93LCAycHggMnB4IDNweCAjODg4KTsNCiAgdHJhbnNpdGlvbjogYmFja2dyb3VuZCAwLjZzOw0KICB6LWluZGV4OiA5OTk5OTk5Ow0KfQ0KDQoudG9wIHsNCiAgcG9zaXRpb246IGZpeGVkOw0KICBmb250LXNpemU6IHZhcigtLWZvbnQtc2l6ZSwgMC42NXJlbSk7DQogIHVzZXItc2VsZWN0OiBub25lOw0KfQ0KDQouaWNvbi5sZWZ0IHsNCiAgbGVmdDogMWVtOw0KICB0cmFuc2Zvcm06IHRyYW5zbGF0ZSgtNTAlLCAtNTAlKTsNCn0NCi5pY29uLnJpZ2h0IHsNCiAgcmlnaHQ6IDFlbTsNCiAgdHJhbnNmb3JtOiB0cmFuc2xhdGUoNTAlLCAtNTAlKTsNCn0NCi5pY29uIHsNCiAgbWF4LXdpZHRoOiAxZW07DQogIG1heC1oZWlnaHQ6IDFlbTsNCiAgcG9zaXRpb246IGFic29sdXRlOw0KICB0b3A6IDUwJTsNCiAgbGluZS1oZWlnaHQ6IDA7DQp9DQoNCmxpID4gcDpub3QoOmVtcHR5KSB7DQogIG1hcmdpbjogMCAxZW07DQogIHdoaXRlLXNwYWNlOiBub3dyYXA7DQp9DQpsaS5kaXNhYmxlZCB7DQogIGNvbG9yOiB2YXIoLS1kaXNhYmxlZC1mZywgI2JiYik7DQp9DQpsaS5zcGxpdCB7DQogIGJvcmRlci10b3A6IHZhcigtLXNwbGl0LWJvcmRlciwgdmFyKC0tYm9yZGVyLCAxcHggc29saWQgI2JiYikpOw0KICBwYWRkaW5nOiAwOw0KICBtYXJnaW46IDAuM2VtOw0KfQ0KbGkuc3BsaXQ6Zmlyc3QtY2hpbGQsDQpsaS5zcGxpdDpsYXN0LWNoaWxkLA0KbGkuc3BsaXQgKyBsaS5zcGxpdCB7DQogIGRpc3BsYXk6IG5vbmU7DQp9DQpsaS5ob3Zlcjpub3QoLmRpc2FiZWQpOm5vdCguc3BsaXQpIHsNCiAgYmFja2dyb3VuZDogdmFyKC0taG92ZXItaXRlbS1iZywgI2JiYik7DQp9DQoudG9wLm9wZW4gbGkuaG92ZXIgPiB1bCB7DQogIHZpc2liaWxpdHk6IHZpc2libGU7DQp9DQpsaSB7DQogIG1hcmdpbjogMC4yZW0gMDsNCiAgcGFkZGluZzogMC41ZW0gMWVtOw0KICBkaXNwbGF5OiBmbGV4Ow0KICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47DQogIHRleHQtYWxpZ246IGxlZnQ7DQogIHBvc2l0aW9uOiByZWxhdGl2ZTsNCiAgY3Vyc29yOiBkZWZhdWx0Ow0KICBjb2xvcjogdmFyKC0tZmcsICMwMDApOw0KfQ0KDQpsaS5ncm91cDo6YWZ0ZXIgew0KICBjb250ZW50OiAnXDI1YjYnOw0KICBwb3NpdGlvbjogYWJzb2x1dGU7DQogIGZvbnQtc2l6ZTogMC42NWVtOw0KICByaWdodDogMDsNCiAgdG9wOiA1MCU7DQogIHRyYW5zZm9ybTogdHJhbnNsYXRlKC01MCUsIC01MCUpOw0KfQ0KDQp1bDpub3QoLnRvcCkgew0KICBwb3NpdGlvbjogYWJzb2x1dGU7DQogIGxlZnQ6IDEwMCU7DQogIHRvcDogLTAuMjVlbTsNCn0NCg0KdWwubmVzdGxlIHsNCiAgbGVmdDogMC41ZW07DQogIHRvcDogMTAwJTsNCn0NCg==";
|
|
9
|
-
|
|
10
|
-
class NeMenu extends custElems.CustomElementBase {
|
|
11
|
-
constructor() {
|
|
12
|
-
super(NeMenu.Css, NeMenu.Html);
|
|
13
|
-
this.top = this.root.querySelector('ul');
|
|
14
|
-
}
|
|
15
|
-
connectedCallback() {
|
|
16
|
-
if (!this._connected) {
|
|
17
|
-
setTimeout(() => this.reload());
|
|
18
|
-
dom.q(this.parentNode).on('contextmenu', (e) => this.onParentContext(e));
|
|
19
|
-
dom.q(this, this.parentNode).on('contextmenu wheel', (e) => {
|
|
20
|
-
e.preventDefault();
|
|
21
|
-
e.stopPropagation();
|
|
22
|
-
});
|
|
23
|
-
dom.q(this).on('mousedown', (e) => e.stopPropagation());
|
|
24
|
-
dom.q(window).on('mousedown resize wheel', () => this.close());
|
|
25
|
-
this._connected = true;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
/** Opens the menu. */
|
|
29
|
-
open() {
|
|
30
|
-
// close all menus
|
|
31
|
-
const doc = this.parentElement.getRootNode();
|
|
32
|
-
doc.querySelectorAll('ne14-menu').forEach((m) => m.close());
|
|
33
|
-
// style this one as open
|
|
34
|
-
this.top.classList.add('open');
|
|
35
|
-
dom.q(this).fire('menuopen');
|
|
36
|
-
}
|
|
37
|
-
/** Closes the menu. */
|
|
38
|
-
close() {
|
|
39
|
-
if (this.top.classList.contains('open')) {
|
|
40
|
-
this.top.classList.remove('open');
|
|
41
|
-
dom.q(this).fire('menuclose');
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
/** Reloads active contents based on client dom. */
|
|
45
|
-
reload() {
|
|
46
|
-
dom.q(this.top)
|
|
47
|
-
.empty()
|
|
48
|
-
.append(...this.walk(this, false));
|
|
49
|
-
}
|
|
50
|
-
onParentContext(event) {
|
|
51
|
-
if (this.isConnected) {
|
|
52
|
-
// update position (y)
|
|
53
|
-
const y = event.clientY;
|
|
54
|
-
const height = this.top.offsetHeight;
|
|
55
|
-
const posY = y + height + 2 > window.innerHeight ? y - height : y;
|
|
56
|
-
this.top.style.top = `${Math.max(0, posY)}px`;
|
|
57
|
-
// update position (x)
|
|
58
|
-
const x = event.clientX;
|
|
59
|
-
const width = this.top.offsetWidth;
|
|
60
|
-
const posX = x + width + 2 > window.innerWidth ? x - width : x;
|
|
61
|
-
this.top.style.left = `${Math.max(0, posX)}px`;
|
|
62
|
-
// open
|
|
63
|
-
this.open();
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
walk(ul, parentDisabled, ref = '') {
|
|
67
|
-
let levelItemNo = 0;
|
|
68
|
-
return Array.from(ul.children)
|
|
69
|
-
.filter((c) => c instanceof HTMLLIElement &&
|
|
70
|
-
!c.classList.contains('hidden') &&
|
|
71
|
-
(c.textContent || c.classList.contains('split')))
|
|
72
|
-
.reduce((acc, li) => {
|
|
73
|
-
var _a, _b, _c;
|
|
74
|
-
const children = Array.from(li.children).map((el) => el);
|
|
75
|
-
const a = children.find((n) => n instanceof HTMLAnchorElement);
|
|
76
|
-
const ul = children.find((n) => n instanceof HTMLUListElement);
|
|
77
|
-
const isSplit = li.classList.contains('split');
|
|
78
|
-
const isGrouper = !isSplit && ul && ul.querySelector('li');
|
|
79
|
-
const isDisabled = !isSplit && (parentDisabled || li.classList.contains('disabled'));
|
|
80
|
-
const aChildren = Array.from((a === null || a === void 0 ? void 0 : a.children) || []).map((el) => el);
|
|
81
|
-
const imgs = children
|
|
82
|
-
.concat(aChildren)
|
|
83
|
-
.filter((n) => n instanceof HTMLImageElement)
|
|
84
|
-
.map((n) => n);
|
|
85
|
-
if (!isSplit)
|
|
86
|
-
levelItemNo++;
|
|
87
|
-
const classes = [];
|
|
88
|
-
if (isSplit)
|
|
89
|
-
classes.push('split');
|
|
90
|
-
else {
|
|
91
|
-
if (isDisabled)
|
|
92
|
-
classes.push('disabled');
|
|
93
|
-
if (isGrouper)
|
|
94
|
-
classes.push('group');
|
|
95
|
-
if ((a === null || a === void 0 ? void 0 : a.target) === '_blank')
|
|
96
|
-
classes.push('click-out');
|
|
97
|
-
else if (a)
|
|
98
|
-
classes.push('click-in');
|
|
99
|
-
}
|
|
100
|
-
const bestTextNode = [...children, li].find((c) => c.innerText);
|
|
101
|
-
const bestText = isSplit ? null : ((_a = bestTextNode === null || bestTextNode === void 0 ? void 0 : bestTextNode.innerText) !== null && _a !== void 0 ? _a : `Item ${levelItemNo}`);
|
|
102
|
-
const shortcut = isSplit || isGrouper ? null : li.getAttribute('aria-keyshortcuts');
|
|
103
|
-
const liRef = `${ref}${levelItemNo}`;
|
|
104
|
-
const eventDetail = { ref: liRef, title: bestText, origin: a || li };
|
|
105
|
-
const handleClick = () => {
|
|
106
|
-
if (!isDisabled && !isGrouper && !isSplit) {
|
|
107
|
-
eventDetail.origin.click();
|
|
108
|
-
dom.q(this).fire('itemselect', eventDetail);
|
|
109
|
-
this.close();
|
|
110
|
-
}
|
|
111
|
-
};
|
|
112
|
-
const handleMouseEnter = (e) => {
|
|
113
|
-
if (!isDisabled && !isSplit) {
|
|
114
|
-
const domLi = e.target;
|
|
115
|
-
if (isGrouper) {
|
|
116
|
-
const domUl = Array.from(domLi.children).find((n) => n instanceof HTMLUListElement);
|
|
117
|
-
const liRect = domLi.getBoundingClientRect();
|
|
118
|
-
domUl.classList.toggle('nestle', liRect.right + domUl.clientWidth + 2 > window.innerWidth);
|
|
119
|
-
}
|
|
120
|
-
domLi.classList.add('hover');
|
|
121
|
-
dom.q(this).fire('itemhover', eventDetail);
|
|
122
|
-
}
|
|
123
|
-
};
|
|
124
|
-
const handleMouseLeave = (e) => {
|
|
125
|
-
if (!isDisabled && !isSplit) {
|
|
126
|
-
e.target.classList.remove('hover');
|
|
127
|
-
dom.q(this).fire('itemunhover', eventDetail);
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
const $domItem = dom.q({ tag: 'li' })
|
|
131
|
-
.attr('class', classes.length ? classes.join(' ') : null)
|
|
132
|
-
.attr('aria-keyshortcuts', shortcut)
|
|
133
|
-
.on('click contextmenu', handleClick)
|
|
134
|
-
.on('mouseenter', handleMouseEnter)
|
|
135
|
-
.on('mouseleave', handleMouseLeave);
|
|
136
|
-
const charLeft = li.dataset.charLeft;
|
|
137
|
-
const charRight = li.dataset.charRight;
|
|
138
|
-
const imgLeft = imgs.find((i) => !i.classList.contains('right'));
|
|
139
|
-
const imgRight = imgs.find((i) => i.classList.contains('right'));
|
|
140
|
-
if (!isSplit && !isGrouper && bestText) {
|
|
141
|
-
if (NeMenu.CHAR_REF_REGEX.test(charLeft))
|
|
142
|
-
$domItem.append(`<span class='icon left'>&#x${charLeft};</span>`);
|
|
143
|
-
else if (charLeft)
|
|
144
|
-
console.warn(`ne14-menu: Bad hex code '${charLeft}' to left of '${bestText}'.`);
|
|
145
|
-
else if (imgLeft)
|
|
146
|
-
$domItem.append(`<img class='icon left' src='${imgLeft.src}'/>`);
|
|
147
|
-
if (NeMenu.CHAR_REF_REGEX.test(charRight))
|
|
148
|
-
$domItem.append(`<span class='icon right'>&#x${charRight};</span>`);
|
|
149
|
-
else if (charRight)
|
|
150
|
-
console.warn(`ne14-menu: Bad hex code '${charRight}' to right of '${bestText}'.`);
|
|
151
|
-
else if (imgRight)
|
|
152
|
-
$domItem.append(`<img class='icon right' src='${imgRight.src}'/>`);
|
|
153
|
-
}
|
|
154
|
-
if (bestText)
|
|
155
|
-
$domItem.append({ tag: 'p', text: bestText });
|
|
156
|
-
if (shortcut)
|
|
157
|
-
$domItem.append({ tag: 'p', text: shortcut });
|
|
158
|
-
if (isGrouper)
|
|
159
|
-
$domItem.appendIn({ tag: 'ul' }).append(...this.walk(ul, isDisabled, `${liRef}-`));
|
|
160
|
-
// Do not push two consecutive splits
|
|
161
|
-
if (!isSplit || !((_c = (_b = acc[acc.length - 1]) === null || _b === void 0 ? void 0 : _b.classList) === null || _c === void 0 ? void 0 : _c.contains('split'))) {
|
|
162
|
-
acc.push($domItem.elements[0]);
|
|
163
|
-
}
|
|
164
|
-
return acc;
|
|
165
|
-
}, []);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
NeMenu.Css = custElems.reduceCss(custElems.decode(stylesUrl));
|
|
169
|
-
NeMenu.Html = custElems.reduceHtml(custElems.decode(markupUrl));
|
|
170
|
-
NeMenu.CHAR_REF_REGEX = /^[0-9a-f]{4,5}$/i;
|
|
171
|
-
|
|
172
|
-
if ('customElements' in window) {
|
|
173
|
-
window.customElements.define('ne14-menu', NeMenu);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
exports.ContextMenu = NeMenu;
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import { q } from '@ne1410s/dom';
|
|
2
|
-
import { reduceCss, decode, reduceHtml, CustomElementBase } from '@ne1410s/cust-elems';
|
|
3
|
-
|
|
4
|
-
var markupUrl = "data:text/html;base64,PHNsb3Q+PC9zbG90Pg0KPHVsIGNsYXNzPSJ0b3AiPjwvdWw+DQo=";
|
|
5
|
-
|
|
6
|
-
var stylesUrl = "data:text/css;base64,dWwsDQpsaSB7DQogIHBhZGRpbmc6IDA7DQogIG1hcmdpbjogMDsNCiAgZm9udDogaW5oZXJpdDsNCn0NCnNsb3QsDQpsaS5zcGxpdCAuaWNvbiB7DQogIGRpc3BsYXk6IG5vbmU7DQp9DQoudG9wOm5vdCgub3BlbiksDQp1bDpub3QoLnRvcCkgew0KICB2aXNpYmlsaXR5OiBoaWRkZW47DQp9DQoNCnVsIHsNCiAgYm9yZGVyOiB2YXIoLS1ib3JkZXIsIDFweCBzb2xpZCAjYmJiKTsNCiAgYmFja2dyb3VuZDogdmFyKC0tYmcsICNmZmYpOw0KICBib3gtc2hhZG93OiB2YXIoLS1ib3gtc2hhZG93LCAycHggMnB4IDNweCAjODg4KTsNCiAgdHJhbnNpdGlvbjogYmFja2dyb3VuZCAwLjZzOw0KICB6LWluZGV4OiA5OTk5OTk5Ow0KfQ0KDQoudG9wIHsNCiAgcG9zaXRpb246IGZpeGVkOw0KICBmb250LXNpemU6IHZhcigtLWZvbnQtc2l6ZSwgMC42NXJlbSk7DQogIHVzZXItc2VsZWN0OiBub25lOw0KfQ0KDQouaWNvbi5sZWZ0IHsNCiAgbGVmdDogMWVtOw0KICB0cmFuc2Zvcm06IHRyYW5zbGF0ZSgtNTAlLCAtNTAlKTsNCn0NCi5pY29uLnJpZ2h0IHsNCiAgcmlnaHQ6IDFlbTsNCiAgdHJhbnNmb3JtOiB0cmFuc2xhdGUoNTAlLCAtNTAlKTsNCn0NCi5pY29uIHsNCiAgbWF4LXdpZHRoOiAxZW07DQogIG1heC1oZWlnaHQ6IDFlbTsNCiAgcG9zaXRpb246IGFic29sdXRlOw0KICB0b3A6IDUwJTsNCiAgbGluZS1oZWlnaHQ6IDA7DQp9DQoNCmxpID4gcDpub3QoOmVtcHR5KSB7DQogIG1hcmdpbjogMCAxZW07DQogIHdoaXRlLXNwYWNlOiBub3dyYXA7DQp9DQpsaS5kaXNhYmxlZCB7DQogIGNvbG9yOiB2YXIoLS1kaXNhYmxlZC1mZywgI2JiYik7DQp9DQpsaS5zcGxpdCB7DQogIGJvcmRlci10b3A6IHZhcigtLXNwbGl0LWJvcmRlciwgdmFyKC0tYm9yZGVyLCAxcHggc29saWQgI2JiYikpOw0KICBwYWRkaW5nOiAwOw0KICBtYXJnaW46IDAuM2VtOw0KfQ0KbGkuc3BsaXQ6Zmlyc3QtY2hpbGQsDQpsaS5zcGxpdDpsYXN0LWNoaWxkLA0KbGkuc3BsaXQgKyBsaS5zcGxpdCB7DQogIGRpc3BsYXk6IG5vbmU7DQp9DQpsaS5ob3Zlcjpub3QoLmRpc2FiZWQpOm5vdCguc3BsaXQpIHsNCiAgYmFja2dyb3VuZDogdmFyKC0taG92ZXItaXRlbS1iZywgI2JiYik7DQp9DQoudG9wLm9wZW4gbGkuaG92ZXIgPiB1bCB7DQogIHZpc2liaWxpdHk6IHZpc2libGU7DQp9DQpsaSB7DQogIG1hcmdpbjogMC4yZW0gMDsNCiAgcGFkZGluZzogMC41ZW0gMWVtOw0KICBkaXNwbGF5OiBmbGV4Ow0KICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47DQogIHRleHQtYWxpZ246IGxlZnQ7DQogIHBvc2l0aW9uOiByZWxhdGl2ZTsNCiAgY3Vyc29yOiBkZWZhdWx0Ow0KICBjb2xvcjogdmFyKC0tZmcsICMwMDApOw0KfQ0KDQpsaS5ncm91cDo6YWZ0ZXIgew0KICBjb250ZW50OiAnXDI1YjYnOw0KICBwb3NpdGlvbjogYWJzb2x1dGU7DQogIGZvbnQtc2l6ZTogMC42NWVtOw0KICByaWdodDogMDsNCiAgdG9wOiA1MCU7DQogIHRyYW5zZm9ybTogdHJhbnNsYXRlKC01MCUsIC01MCUpOw0KfQ0KDQp1bDpub3QoLnRvcCkgew0KICBwb3NpdGlvbjogYWJzb2x1dGU7DQogIGxlZnQ6IDEwMCU7DQogIHRvcDogLTAuMjVlbTsNCn0NCg0KdWwubmVzdGxlIHsNCiAgbGVmdDogMC41ZW07DQogIHRvcDogMTAwJTsNCn0NCg==";
|
|
7
|
-
|
|
8
|
-
class NeMenu extends CustomElementBase {
|
|
9
|
-
constructor() {
|
|
10
|
-
super(NeMenu.Css, NeMenu.Html);
|
|
11
|
-
this.top = this.root.querySelector('ul');
|
|
12
|
-
}
|
|
13
|
-
connectedCallback() {
|
|
14
|
-
if (!this._connected) {
|
|
15
|
-
setTimeout(() => this.reload());
|
|
16
|
-
q(this.parentNode).on('contextmenu', (e) => this.onParentContext(e));
|
|
17
|
-
q(this, this.parentNode).on('contextmenu wheel', (e) => {
|
|
18
|
-
e.preventDefault();
|
|
19
|
-
e.stopPropagation();
|
|
20
|
-
});
|
|
21
|
-
q(this).on('mousedown', (e) => e.stopPropagation());
|
|
22
|
-
q(window).on('mousedown resize wheel', () => this.close());
|
|
23
|
-
this._connected = true;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
/** Opens the menu. */
|
|
27
|
-
open() {
|
|
28
|
-
// close all menus
|
|
29
|
-
const doc = this.parentElement.getRootNode();
|
|
30
|
-
doc.querySelectorAll('ne14-menu').forEach((m) => m.close());
|
|
31
|
-
// style this one as open
|
|
32
|
-
this.top.classList.add('open');
|
|
33
|
-
q(this).fire('menuopen');
|
|
34
|
-
}
|
|
35
|
-
/** Closes the menu. */
|
|
36
|
-
close() {
|
|
37
|
-
if (this.top.classList.contains('open')) {
|
|
38
|
-
this.top.classList.remove('open');
|
|
39
|
-
q(this).fire('menuclose');
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
/** Reloads active contents based on client dom. */
|
|
43
|
-
reload() {
|
|
44
|
-
q(this.top)
|
|
45
|
-
.empty()
|
|
46
|
-
.append(...this.walk(this, false));
|
|
47
|
-
}
|
|
48
|
-
onParentContext(event) {
|
|
49
|
-
if (this.isConnected) {
|
|
50
|
-
// update position (y)
|
|
51
|
-
const y = event.clientY;
|
|
52
|
-
const height = this.top.offsetHeight;
|
|
53
|
-
const posY = y + height + 2 > window.innerHeight ? y - height : y;
|
|
54
|
-
this.top.style.top = `${Math.max(0, posY)}px`;
|
|
55
|
-
// update position (x)
|
|
56
|
-
const x = event.clientX;
|
|
57
|
-
const width = this.top.offsetWidth;
|
|
58
|
-
const posX = x + width + 2 > window.innerWidth ? x - width : x;
|
|
59
|
-
this.top.style.left = `${Math.max(0, posX)}px`;
|
|
60
|
-
// open
|
|
61
|
-
this.open();
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
walk(ul, parentDisabled, ref = '') {
|
|
65
|
-
let levelItemNo = 0;
|
|
66
|
-
return Array.from(ul.children)
|
|
67
|
-
.filter((c) => c instanceof HTMLLIElement &&
|
|
68
|
-
!c.classList.contains('hidden') &&
|
|
69
|
-
(c.textContent || c.classList.contains('split')))
|
|
70
|
-
.reduce((acc, li) => {
|
|
71
|
-
var _a, _b, _c;
|
|
72
|
-
const children = Array.from(li.children).map((el) => el);
|
|
73
|
-
const a = children.find((n) => n instanceof HTMLAnchorElement);
|
|
74
|
-
const ul = children.find((n) => n instanceof HTMLUListElement);
|
|
75
|
-
const isSplit = li.classList.contains('split');
|
|
76
|
-
const isGrouper = !isSplit && ul && ul.querySelector('li');
|
|
77
|
-
const isDisabled = !isSplit && (parentDisabled || li.classList.contains('disabled'));
|
|
78
|
-
const aChildren = Array.from((a === null || a === void 0 ? void 0 : a.children) || []).map((el) => el);
|
|
79
|
-
const imgs = children
|
|
80
|
-
.concat(aChildren)
|
|
81
|
-
.filter((n) => n instanceof HTMLImageElement)
|
|
82
|
-
.map((n) => n);
|
|
83
|
-
if (!isSplit)
|
|
84
|
-
levelItemNo++;
|
|
85
|
-
const classes = [];
|
|
86
|
-
if (isSplit)
|
|
87
|
-
classes.push('split');
|
|
88
|
-
else {
|
|
89
|
-
if (isDisabled)
|
|
90
|
-
classes.push('disabled');
|
|
91
|
-
if (isGrouper)
|
|
92
|
-
classes.push('group');
|
|
93
|
-
if ((a === null || a === void 0 ? void 0 : a.target) === '_blank')
|
|
94
|
-
classes.push('click-out');
|
|
95
|
-
else if (a)
|
|
96
|
-
classes.push('click-in');
|
|
97
|
-
}
|
|
98
|
-
const bestTextNode = [...children, li].find((c) => c.innerText);
|
|
99
|
-
const bestText = isSplit ? null : ((_a = bestTextNode === null || bestTextNode === void 0 ? void 0 : bestTextNode.innerText) !== null && _a !== void 0 ? _a : `Item ${levelItemNo}`);
|
|
100
|
-
const shortcut = isSplit || isGrouper ? null : li.getAttribute('aria-keyshortcuts');
|
|
101
|
-
const liRef = `${ref}${levelItemNo}`;
|
|
102
|
-
const eventDetail = { ref: liRef, title: bestText, origin: a || li };
|
|
103
|
-
const handleClick = () => {
|
|
104
|
-
if (!isDisabled && !isGrouper && !isSplit) {
|
|
105
|
-
eventDetail.origin.click();
|
|
106
|
-
q(this).fire('itemselect', eventDetail);
|
|
107
|
-
this.close();
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
const handleMouseEnter = (e) => {
|
|
111
|
-
if (!isDisabled && !isSplit) {
|
|
112
|
-
const domLi = e.target;
|
|
113
|
-
if (isGrouper) {
|
|
114
|
-
const domUl = Array.from(domLi.children).find((n) => n instanceof HTMLUListElement);
|
|
115
|
-
const liRect = domLi.getBoundingClientRect();
|
|
116
|
-
domUl.classList.toggle('nestle', liRect.right + domUl.clientWidth + 2 > window.innerWidth);
|
|
117
|
-
}
|
|
118
|
-
domLi.classList.add('hover');
|
|
119
|
-
q(this).fire('itemhover', eventDetail);
|
|
120
|
-
}
|
|
121
|
-
};
|
|
122
|
-
const handleMouseLeave = (e) => {
|
|
123
|
-
if (!isDisabled && !isSplit) {
|
|
124
|
-
e.target.classList.remove('hover');
|
|
125
|
-
q(this).fire('itemunhover', eventDetail);
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
const $domItem = q({ tag: 'li' })
|
|
129
|
-
.attr('class', classes.length ? classes.join(' ') : null)
|
|
130
|
-
.attr('aria-keyshortcuts', shortcut)
|
|
131
|
-
.on('click contextmenu', handleClick)
|
|
132
|
-
.on('mouseenter', handleMouseEnter)
|
|
133
|
-
.on('mouseleave', handleMouseLeave);
|
|
134
|
-
const charLeft = li.dataset.charLeft;
|
|
135
|
-
const charRight = li.dataset.charRight;
|
|
136
|
-
const imgLeft = imgs.find((i) => !i.classList.contains('right'));
|
|
137
|
-
const imgRight = imgs.find((i) => i.classList.contains('right'));
|
|
138
|
-
if (!isSplit && !isGrouper && bestText) {
|
|
139
|
-
if (NeMenu.CHAR_REF_REGEX.test(charLeft))
|
|
140
|
-
$domItem.append(`<span class='icon left'>&#x${charLeft};</span>`);
|
|
141
|
-
else if (charLeft)
|
|
142
|
-
console.warn(`ne14-menu: Bad hex code '${charLeft}' to left of '${bestText}'.`);
|
|
143
|
-
else if (imgLeft)
|
|
144
|
-
$domItem.append(`<img class='icon left' src='${imgLeft.src}'/>`);
|
|
145
|
-
if (NeMenu.CHAR_REF_REGEX.test(charRight))
|
|
146
|
-
$domItem.append(`<span class='icon right'>&#x${charRight};</span>`);
|
|
147
|
-
else if (charRight)
|
|
148
|
-
console.warn(`ne14-menu: Bad hex code '${charRight}' to right of '${bestText}'.`);
|
|
149
|
-
else if (imgRight)
|
|
150
|
-
$domItem.append(`<img class='icon right' src='${imgRight.src}'/>`);
|
|
151
|
-
}
|
|
152
|
-
if (bestText)
|
|
153
|
-
$domItem.append({ tag: 'p', text: bestText });
|
|
154
|
-
if (shortcut)
|
|
155
|
-
$domItem.append({ tag: 'p', text: shortcut });
|
|
156
|
-
if (isGrouper)
|
|
157
|
-
$domItem.appendIn({ tag: 'ul' }).append(...this.walk(ul, isDisabled, `${liRef}-`));
|
|
158
|
-
// Do not push two consecutive splits
|
|
159
|
-
if (!isSplit || !((_c = (_b = acc[acc.length - 1]) === null || _b === void 0 ? void 0 : _b.classList) === null || _c === void 0 ? void 0 : _c.contains('split'))) {
|
|
160
|
-
acc.push($domItem.elements[0]);
|
|
161
|
-
}
|
|
162
|
-
return acc;
|
|
163
|
-
}, []);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
NeMenu.Css = reduceCss(decode(stylesUrl));
|
|
167
|
-
NeMenu.Html = reduceHtml(decode(markupUrl));
|
|
168
|
-
NeMenu.CHAR_REF_REGEX = /^[0-9a-f]{4,5}$/i;
|
|
169
|
-
|
|
170
|
-
if ('customElements' in window) {
|
|
171
|
-
window.customElements.define('ne14-menu', NeMenu);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
export { NeMenu as ContextMenu };
|
|
@@ -1,450 +0,0 @@
|
|
|
1
|
-
(function (global, factory) {
|
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
3
|
-
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ne_menu = {}));
|
|
5
|
-
})(this, (function (exports) { 'use strict';
|
|
6
|
-
|
|
7
|
-
/******************************************************************************
|
|
8
|
-
Copyright (c) Microsoft Corporation.
|
|
9
|
-
|
|
10
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
11
|
-
purpose with or without fee is hereby granted.
|
|
12
|
-
|
|
13
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
14
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
15
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
16
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
17
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
18
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
19
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
20
|
-
***************************************************************************** */
|
|
21
|
-
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
function __spreadArray(to, from, pack) {
|
|
25
|
-
if (arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
26
|
-
if (ar || !(i in from)) {
|
|
27
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
28
|
-
ar[i] = from[i];
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
35
|
-
var e = new Error(message);
|
|
36
|
-
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
var ChainedQuery = /** @class */ (function () {
|
|
40
|
-
function ChainedQuery(mapper) {
|
|
41
|
-
var sources = [];
|
|
42
|
-
for (var _i = 1; _i < arguments.length; _i++) {
|
|
43
|
-
sources[_i - 1] = arguments[_i];
|
|
44
|
-
}
|
|
45
|
-
var _this = this;
|
|
46
|
-
this.mapper = mapper;
|
|
47
|
-
this._items = [];
|
|
48
|
-
this.get = function (index) { return _this._items[index]; };
|
|
49
|
-
this.add.apply(this, sources);
|
|
50
|
-
}
|
|
51
|
-
Object.defineProperty(ChainedQuery.prototype, "targets", {
|
|
52
|
-
get: function () {
|
|
53
|
-
return this._items.filter(function (it) { return it instanceof EventTarget; }).map(function (it) { return it; });
|
|
54
|
-
},
|
|
55
|
-
enumerable: false,
|
|
56
|
-
configurable: true
|
|
57
|
-
});
|
|
58
|
-
Object.defineProperty(ChainedQuery.prototype, "elements", {
|
|
59
|
-
get: function () {
|
|
60
|
-
return this._items.filter(function (it) { return it instanceof Element; }).map(function (it) { return it; });
|
|
61
|
-
},
|
|
62
|
-
enumerable: false,
|
|
63
|
-
configurable: true
|
|
64
|
-
});
|
|
65
|
-
Object.defineProperty(ChainedQuery.prototype, "nodes", {
|
|
66
|
-
get: function () {
|
|
67
|
-
return this._items.filter(function (it) { return it instanceof Node; }).map(function (it) { return it; });
|
|
68
|
-
},
|
|
69
|
-
enumerable: false,
|
|
70
|
-
configurable: true
|
|
71
|
-
});
|
|
72
|
-
Object.defineProperty(ChainedQuery.prototype, "containers", {
|
|
73
|
-
get: function () {
|
|
74
|
-
return this._items.map(function (it) { return it; }).filter(function (p) { return typeof p.append === 'function'; });
|
|
75
|
-
},
|
|
76
|
-
enumerable: false,
|
|
77
|
-
configurable: true
|
|
78
|
-
});
|
|
79
|
-
Object.defineProperty(ChainedQuery.prototype, "length", {
|
|
80
|
-
get: function () {
|
|
81
|
-
return this._items.length;
|
|
82
|
-
},
|
|
83
|
-
enumerable: false,
|
|
84
|
-
configurable: true
|
|
85
|
-
});
|
|
86
|
-
ChainedQuery.prototype.add = function () {
|
|
87
|
-
var _a;
|
|
88
|
-
var sources = [];
|
|
89
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
90
|
-
sources[_i] = arguments[_i];
|
|
91
|
-
}
|
|
92
|
-
(_a = this._items).push.apply(_a, this.mapper.Map(sources));
|
|
93
|
-
return this;
|
|
94
|
-
};
|
|
95
|
-
// TODO: This must not fall over if trying to perform an action
|
|
96
|
-
// on an inappropriate type. eg setting an attribute on window, or
|
|
97
|
-
// trying to query a non-parent node..
|
|
98
|
-
ChainedQuery.prototype.each = function (func) {
|
|
99
|
-
this._items.forEach(function (item, i) { return func(item, i); });
|
|
100
|
-
return this;
|
|
101
|
-
};
|
|
102
|
-
ChainedQuery.prototype.prop = function (name, value) {
|
|
103
|
-
return this.each(function (item) {
|
|
104
|
-
if (name in item) {
|
|
105
|
-
item[name] = value;
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
};
|
|
109
|
-
//#region Targets
|
|
110
|
-
ChainedQuery.prototype.fire = function (eventName, detail) {
|
|
111
|
-
var evt = new CustomEvent(eventName, { detail: detail });
|
|
112
|
-
this.targets.forEach(function (t) { return t.dispatchEvent(evt); });
|
|
113
|
-
return this;
|
|
114
|
-
};
|
|
115
|
-
ChainedQuery.prototype.on = function (eventNames, func) {
|
|
116
|
-
var evts = eventNames.split(ChainedQuery.WHITESPACE_RGX);
|
|
117
|
-
this.targets.forEach(function (t) {
|
|
118
|
-
evts.forEach(function (name) { return t.addEventListener(name, func); });
|
|
119
|
-
});
|
|
120
|
-
return this;
|
|
121
|
-
};
|
|
122
|
-
//#endregion
|
|
123
|
-
//#region Elements
|
|
124
|
-
ChainedQuery.prototype.attr = function (name, value, ns) {
|
|
125
|
-
this.elements.forEach(function (elem) {
|
|
126
|
-
if (value != null)
|
|
127
|
-
elem.setAttributeNS(ns, name, value);
|
|
128
|
-
else
|
|
129
|
-
elem.removeAttributeNS(ns, name);
|
|
130
|
-
});
|
|
131
|
-
return this;
|
|
132
|
-
};
|
|
133
|
-
ChainedQuery.prototype.toggle = function (className, doSet) {
|
|
134
|
-
this.elements.forEach(function (elem) {
|
|
135
|
-
var force = typeof doSet === 'function' ? doSet(elem) : !!doSet;
|
|
136
|
-
elem.classList.toggle(className, force);
|
|
137
|
-
});
|
|
138
|
-
return this;
|
|
139
|
-
};
|
|
140
|
-
//#endregion
|
|
141
|
-
//#region Nodes
|
|
142
|
-
ChainedQuery.prototype.empty = function () {
|
|
143
|
-
this.nodes.forEach(function (n) {
|
|
144
|
-
while (n.firstChild) {
|
|
145
|
-
n.removeChild(n.firstChild);
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
return this;
|
|
149
|
-
};
|
|
150
|
-
ChainedQuery.prototype.remove = function () {
|
|
151
|
-
return new (ChainedQuery.bind.apply(ChainedQuery, __spreadArray([void 0, this.mapper], this._items.filter(function (it) {
|
|
152
|
-
var handle = it instanceof Node;
|
|
153
|
-
if (handle)
|
|
154
|
-
it.parentNode.removeChild(it);
|
|
155
|
-
return !handle;
|
|
156
|
-
}), false)))();
|
|
157
|
-
};
|
|
158
|
-
//#endregion
|
|
159
|
-
//#region Containers
|
|
160
|
-
ChainedQuery.prototype.append = function () {
|
|
161
|
-
var sources = [];
|
|
162
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
163
|
-
sources[_i] = arguments[_i];
|
|
164
|
-
}
|
|
165
|
-
this.appendIn.apply(this, sources);
|
|
166
|
-
return this;
|
|
167
|
-
};
|
|
168
|
-
ChainedQuery.prototype.appendIn = function () {
|
|
169
|
-
var _this = this;
|
|
170
|
-
var sources = [];
|
|
171
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
172
|
-
sources[_i] = arguments[_i];
|
|
173
|
-
}
|
|
174
|
-
return new (ChainedQuery.bind.apply(ChainedQuery, __spreadArray([void 0, this.mapper], this.containers.reduce(function (acc, parent) {
|
|
175
|
-
var nodes = new (ChainedQuery.bind.apply(ChainedQuery, __spreadArray([void 0, _this.mapper], sources, false)))().nodes;
|
|
176
|
-
parent.append.apply(parent, nodes);
|
|
177
|
-
acc.push.apply(acc, nodes);
|
|
178
|
-
return acc;
|
|
179
|
-
}, []), false)))();
|
|
180
|
-
};
|
|
181
|
-
ChainedQuery.prototype.find = function (selector) {
|
|
182
|
-
return new (ChainedQuery.bind.apply(ChainedQuery, __spreadArray([void 0, this.mapper], this.containers.reduce(function (acc, parent) {
|
|
183
|
-
acc.push.apply(acc, Array.from(parent.querySelectorAll(selector)));
|
|
184
|
-
return acc;
|
|
185
|
-
}, []), false)))();
|
|
186
|
-
};
|
|
187
|
-
ChainedQuery.prototype.first = function (selector) {
|
|
188
|
-
return new (ChainedQuery.bind.apply(ChainedQuery, __spreadArray([void 0, this.mapper], this.containers.map(function (parent) { return parent.querySelector(selector); }).filter(function (found) { return !!found; }), false)))();
|
|
189
|
-
};
|
|
190
|
-
ChainedQuery.WHITESPACE_RGX = /\s+/;
|
|
191
|
-
return ChainedQuery;
|
|
192
|
-
}());
|
|
193
|
-
|
|
194
|
-
var SourceMapper = /** @class */ (function () {
|
|
195
|
-
function SourceMapper() {
|
|
196
|
-
}
|
|
197
|
-
SourceMapper.prototype.Map = function (sources) {
|
|
198
|
-
return sources.reduce(function (acc, item) {
|
|
199
|
-
if (typeof item === 'string') {
|
|
200
|
-
acc.push.apply(acc, (SourceMapper.NAIVE_HTML_RGX.test(item)
|
|
201
|
-
? SourceMapper.MapHTML(item)
|
|
202
|
-
: SourceMapper.MapSelector(item)));
|
|
203
|
-
}
|
|
204
|
-
else if (item.tag)
|
|
205
|
-
acc.push(SourceMapper.MapParam(item));
|
|
206
|
-
else if (item instanceof Node)
|
|
207
|
-
acc.push(item);
|
|
208
|
-
else if (item instanceof EventTarget)
|
|
209
|
-
acc.push(item);
|
|
210
|
-
else if (item instanceof ChainedQuery)
|
|
211
|
-
item.each(function (i) { return acc.push(i); });
|
|
212
|
-
else
|
|
213
|
-
console.warn('Unrecognised item:', item);
|
|
214
|
-
return acc;
|
|
215
|
-
}, []);
|
|
216
|
-
};
|
|
217
|
-
SourceMapper.MapHTML = function (html) {
|
|
218
|
-
var template = document.createElement('template');
|
|
219
|
-
template.innerHTML = html;
|
|
220
|
-
return Array.from(template.content.childNodes);
|
|
221
|
-
};
|
|
222
|
-
SourceMapper.MapSelector = function (selector) {
|
|
223
|
-
return Array.from(document.querySelectorAll(selector));
|
|
224
|
-
};
|
|
225
|
-
SourceMapper.MapParam = function (p) {
|
|
226
|
-
var n = document.createElement(p.tag);
|
|
227
|
-
if (p.text)
|
|
228
|
-
n.textContent = p.text;
|
|
229
|
-
for (var key in p.attr || {}) {
|
|
230
|
-
if (p.attr[key] != null) {
|
|
231
|
-
n.setAttribute(key, p.attr[key]);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
for (var key in p.evts || {}) {
|
|
235
|
-
if (typeof p.evts[key] === 'function') {
|
|
236
|
-
n.addEventListener(key, p.evts[key]);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
return n;
|
|
240
|
-
};
|
|
241
|
-
SourceMapper.NAIVE_HTML_RGX = /^\s*<.*>\s*$/m;
|
|
242
|
-
return SourceMapper;
|
|
243
|
-
}());
|
|
244
|
-
var mapper = new SourceMapper();
|
|
245
|
-
function q() {
|
|
246
|
-
var input = [];
|
|
247
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
248
|
-
input[_i] = arguments[_i];
|
|
249
|
-
}
|
|
250
|
-
return new (ChainedQuery.bind.apply(ChainedQuery, __spreadArray([void 0, mapper], input, false)))();
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
class CustomElementBase extends HTMLElement {
|
|
254
|
-
constructor(css, html, mode = 'closed') {
|
|
255
|
-
super();
|
|
256
|
-
this.root = this.attachShadow({ mode });
|
|
257
|
-
this.root.innerHTML = html;
|
|
258
|
-
const style = document.createElement('style');
|
|
259
|
-
style.textContent = css;
|
|
260
|
-
this.root.appendChild(style);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
function decode(b64) {
|
|
265
|
-
const bIndex = (b64 + '').indexOf('base64,');
|
|
266
|
-
return bIndex === -1 ? b64 : window.atob(b64.substring(bIndex + 7));
|
|
267
|
-
}
|
|
268
|
-
function reduceCss(cssIn) {
|
|
269
|
-
return cssIn
|
|
270
|
-
.replace(/\s+/g, ' ')
|
|
271
|
-
.replace(/([,{}:;])\s/g, '$1')
|
|
272
|
-
.replace(/\s([{])/g, '$1');
|
|
273
|
-
}
|
|
274
|
-
function reduceHtml(htmlIn) {
|
|
275
|
-
return htmlIn.replace(/\s+/g, ' ').replace(/(^|>)\s+(<|$)/g, '$1$2');
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
var markupUrl = "data:text/html;base64,PHNsb3Q+PC9zbG90Pg0KPHVsIGNsYXNzPSJ0b3AiPjwvdWw+DQo=";
|
|
279
|
-
|
|
280
|
-
var stylesUrl = "data:text/css;base64,dWwsDQpsaSB7DQogIHBhZGRpbmc6IDA7DQogIG1hcmdpbjogMDsNCiAgZm9udDogaW5oZXJpdDsNCn0NCnNsb3QsDQpsaS5zcGxpdCAuaWNvbiB7DQogIGRpc3BsYXk6IG5vbmU7DQp9DQoudG9wOm5vdCgub3BlbiksDQp1bDpub3QoLnRvcCkgew0KICB2aXNpYmlsaXR5OiBoaWRkZW47DQp9DQoNCnVsIHsNCiAgYm9yZGVyOiB2YXIoLS1ib3JkZXIsIDFweCBzb2xpZCAjYmJiKTsNCiAgYmFja2dyb3VuZDogdmFyKC0tYmcsICNmZmYpOw0KICBib3gtc2hhZG93OiB2YXIoLS1ib3gtc2hhZG93LCAycHggMnB4IDNweCAjODg4KTsNCiAgdHJhbnNpdGlvbjogYmFja2dyb3VuZCAwLjZzOw0KICB6LWluZGV4OiA5OTk5OTk5Ow0KfQ0KDQoudG9wIHsNCiAgcG9zaXRpb246IGZpeGVkOw0KICBmb250LXNpemU6IHZhcigtLWZvbnQtc2l6ZSwgMC42NXJlbSk7DQogIHVzZXItc2VsZWN0OiBub25lOw0KfQ0KDQouaWNvbi5sZWZ0IHsNCiAgbGVmdDogMWVtOw0KICB0cmFuc2Zvcm06IHRyYW5zbGF0ZSgtNTAlLCAtNTAlKTsNCn0NCi5pY29uLnJpZ2h0IHsNCiAgcmlnaHQ6IDFlbTsNCiAgdHJhbnNmb3JtOiB0cmFuc2xhdGUoNTAlLCAtNTAlKTsNCn0NCi5pY29uIHsNCiAgbWF4LXdpZHRoOiAxZW07DQogIG1heC1oZWlnaHQ6IDFlbTsNCiAgcG9zaXRpb246IGFic29sdXRlOw0KICB0b3A6IDUwJTsNCiAgbGluZS1oZWlnaHQ6IDA7DQp9DQoNCmxpID4gcDpub3QoOmVtcHR5KSB7DQogIG1hcmdpbjogMCAxZW07DQogIHdoaXRlLXNwYWNlOiBub3dyYXA7DQp9DQpsaS5kaXNhYmxlZCB7DQogIGNvbG9yOiB2YXIoLS1kaXNhYmxlZC1mZywgI2JiYik7DQp9DQpsaS5zcGxpdCB7DQogIGJvcmRlci10b3A6IHZhcigtLXNwbGl0LWJvcmRlciwgdmFyKC0tYm9yZGVyLCAxcHggc29saWQgI2JiYikpOw0KICBwYWRkaW5nOiAwOw0KICBtYXJnaW46IDAuM2VtOw0KfQ0KbGkuc3BsaXQ6Zmlyc3QtY2hpbGQsDQpsaS5zcGxpdDpsYXN0LWNoaWxkLA0KbGkuc3BsaXQgKyBsaS5zcGxpdCB7DQogIGRpc3BsYXk6IG5vbmU7DQp9DQpsaS5ob3Zlcjpub3QoLmRpc2FiZWQpOm5vdCguc3BsaXQpIHsNCiAgYmFja2dyb3VuZDogdmFyKC0taG92ZXItaXRlbS1iZywgI2JiYik7DQp9DQoudG9wLm9wZW4gbGkuaG92ZXIgPiB1bCB7DQogIHZpc2liaWxpdHk6IHZpc2libGU7DQp9DQpsaSB7DQogIG1hcmdpbjogMC4yZW0gMDsNCiAgcGFkZGluZzogMC41ZW0gMWVtOw0KICBkaXNwbGF5OiBmbGV4Ow0KICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47DQogIHRleHQtYWxpZ246IGxlZnQ7DQogIHBvc2l0aW9uOiByZWxhdGl2ZTsNCiAgY3Vyc29yOiBkZWZhdWx0Ow0KICBjb2xvcjogdmFyKC0tZmcsICMwMDApOw0KfQ0KDQpsaS5ncm91cDo6YWZ0ZXIgew0KICBjb250ZW50OiAnXDI1YjYnOw0KICBwb3NpdGlvbjogYWJzb2x1dGU7DQogIGZvbnQtc2l6ZTogMC42NWVtOw0KICByaWdodDogMDsNCiAgdG9wOiA1MCU7DQogIHRyYW5zZm9ybTogdHJhbnNsYXRlKC01MCUsIC01MCUpOw0KfQ0KDQp1bDpub3QoLnRvcCkgew0KICBwb3NpdGlvbjogYWJzb2x1dGU7DQogIGxlZnQ6IDEwMCU7DQogIHRvcDogLTAuMjVlbTsNCn0NCg0KdWwubmVzdGxlIHsNCiAgbGVmdDogMC41ZW07DQogIHRvcDogMTAwJTsNCn0NCg==";
|
|
281
|
-
|
|
282
|
-
class NeMenu extends CustomElementBase {
|
|
283
|
-
constructor() {
|
|
284
|
-
super(NeMenu.Css, NeMenu.Html);
|
|
285
|
-
this.top = this.root.querySelector('ul');
|
|
286
|
-
}
|
|
287
|
-
connectedCallback() {
|
|
288
|
-
if (!this._connected) {
|
|
289
|
-
setTimeout(() => this.reload());
|
|
290
|
-
q(this.parentNode).on('contextmenu', (e) => this.onParentContext(e));
|
|
291
|
-
q(this, this.parentNode).on('contextmenu wheel', (e) => {
|
|
292
|
-
e.preventDefault();
|
|
293
|
-
e.stopPropagation();
|
|
294
|
-
});
|
|
295
|
-
q(this).on('mousedown', (e) => e.stopPropagation());
|
|
296
|
-
q(window).on('mousedown resize wheel', () => this.close());
|
|
297
|
-
this._connected = true;
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
/** Opens the menu. */
|
|
301
|
-
open() {
|
|
302
|
-
// close all menus
|
|
303
|
-
const doc = this.parentElement.getRootNode();
|
|
304
|
-
doc.querySelectorAll('ne14-menu').forEach((m) => m.close());
|
|
305
|
-
// style this one as open
|
|
306
|
-
this.top.classList.add('open');
|
|
307
|
-
q(this).fire('menuopen');
|
|
308
|
-
}
|
|
309
|
-
/** Closes the menu. */
|
|
310
|
-
close() {
|
|
311
|
-
if (this.top.classList.contains('open')) {
|
|
312
|
-
this.top.classList.remove('open');
|
|
313
|
-
q(this).fire('menuclose');
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
/** Reloads active contents based on client dom. */
|
|
317
|
-
reload() {
|
|
318
|
-
q(this.top)
|
|
319
|
-
.empty()
|
|
320
|
-
.append(...this.walk(this, false));
|
|
321
|
-
}
|
|
322
|
-
onParentContext(event) {
|
|
323
|
-
if (this.isConnected) {
|
|
324
|
-
// update position (y)
|
|
325
|
-
const y = event.clientY;
|
|
326
|
-
const height = this.top.offsetHeight;
|
|
327
|
-
const posY = y + height + 2 > window.innerHeight ? y - height : y;
|
|
328
|
-
this.top.style.top = `${Math.max(0, posY)}px`;
|
|
329
|
-
// update position (x)
|
|
330
|
-
const x = event.clientX;
|
|
331
|
-
const width = this.top.offsetWidth;
|
|
332
|
-
const posX = x + width + 2 > window.innerWidth ? x - width : x;
|
|
333
|
-
this.top.style.left = `${Math.max(0, posX)}px`;
|
|
334
|
-
// open
|
|
335
|
-
this.open();
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
walk(ul, parentDisabled, ref = '') {
|
|
339
|
-
let levelItemNo = 0;
|
|
340
|
-
return Array.from(ul.children)
|
|
341
|
-
.filter((c) => c instanceof HTMLLIElement &&
|
|
342
|
-
!c.classList.contains('hidden') &&
|
|
343
|
-
(c.textContent || c.classList.contains('split')))
|
|
344
|
-
.reduce((acc, li) => {
|
|
345
|
-
var _a, _b, _c;
|
|
346
|
-
const children = Array.from(li.children).map((el) => el);
|
|
347
|
-
const a = children.find((n) => n instanceof HTMLAnchorElement);
|
|
348
|
-
const ul = children.find((n) => n instanceof HTMLUListElement);
|
|
349
|
-
const isSplit = li.classList.contains('split');
|
|
350
|
-
const isGrouper = !isSplit && ul && ul.querySelector('li');
|
|
351
|
-
const isDisabled = !isSplit && (parentDisabled || li.classList.contains('disabled'));
|
|
352
|
-
const aChildren = Array.from((a === null || a === void 0 ? void 0 : a.children) || []).map((el) => el);
|
|
353
|
-
const imgs = children
|
|
354
|
-
.concat(aChildren)
|
|
355
|
-
.filter((n) => n instanceof HTMLImageElement)
|
|
356
|
-
.map((n) => n);
|
|
357
|
-
if (!isSplit)
|
|
358
|
-
levelItemNo++;
|
|
359
|
-
const classes = [];
|
|
360
|
-
if (isSplit)
|
|
361
|
-
classes.push('split');
|
|
362
|
-
else {
|
|
363
|
-
if (isDisabled)
|
|
364
|
-
classes.push('disabled');
|
|
365
|
-
if (isGrouper)
|
|
366
|
-
classes.push('group');
|
|
367
|
-
if ((a === null || a === void 0 ? void 0 : a.target) === '_blank')
|
|
368
|
-
classes.push('click-out');
|
|
369
|
-
else if (a)
|
|
370
|
-
classes.push('click-in');
|
|
371
|
-
}
|
|
372
|
-
const bestTextNode = [...children, li].find((c) => c.innerText);
|
|
373
|
-
const bestText = isSplit ? null : ((_a = bestTextNode === null || bestTextNode === void 0 ? void 0 : bestTextNode.innerText) !== null && _a !== void 0 ? _a : `Item ${levelItemNo}`);
|
|
374
|
-
const shortcut = isSplit || isGrouper ? null : li.getAttribute('aria-keyshortcuts');
|
|
375
|
-
const liRef = `${ref}${levelItemNo}`;
|
|
376
|
-
const eventDetail = { ref: liRef, title: bestText, origin: a || li };
|
|
377
|
-
const handleClick = () => {
|
|
378
|
-
if (!isDisabled && !isGrouper && !isSplit) {
|
|
379
|
-
eventDetail.origin.click();
|
|
380
|
-
q(this).fire('itemselect', eventDetail);
|
|
381
|
-
this.close();
|
|
382
|
-
}
|
|
383
|
-
};
|
|
384
|
-
const handleMouseEnter = (e) => {
|
|
385
|
-
if (!isDisabled && !isSplit) {
|
|
386
|
-
const domLi = e.target;
|
|
387
|
-
if (isGrouper) {
|
|
388
|
-
const domUl = Array.from(domLi.children).find((n) => n instanceof HTMLUListElement);
|
|
389
|
-
const liRect = domLi.getBoundingClientRect();
|
|
390
|
-
domUl.classList.toggle('nestle', liRect.right + domUl.clientWidth + 2 > window.innerWidth);
|
|
391
|
-
}
|
|
392
|
-
domLi.classList.add('hover');
|
|
393
|
-
q(this).fire('itemhover', eventDetail);
|
|
394
|
-
}
|
|
395
|
-
};
|
|
396
|
-
const handleMouseLeave = (e) => {
|
|
397
|
-
if (!isDisabled && !isSplit) {
|
|
398
|
-
e.target.classList.remove('hover');
|
|
399
|
-
q(this).fire('itemunhover', eventDetail);
|
|
400
|
-
}
|
|
401
|
-
};
|
|
402
|
-
const $domItem = q({ tag: 'li' })
|
|
403
|
-
.attr('class', classes.length ? classes.join(' ') : null)
|
|
404
|
-
.attr('aria-keyshortcuts', shortcut)
|
|
405
|
-
.on('click contextmenu', handleClick)
|
|
406
|
-
.on('mouseenter', handleMouseEnter)
|
|
407
|
-
.on('mouseleave', handleMouseLeave);
|
|
408
|
-
const charLeft = li.dataset.charLeft;
|
|
409
|
-
const charRight = li.dataset.charRight;
|
|
410
|
-
const imgLeft = imgs.find((i) => !i.classList.contains('right'));
|
|
411
|
-
const imgRight = imgs.find((i) => i.classList.contains('right'));
|
|
412
|
-
if (!isSplit && !isGrouper && bestText) {
|
|
413
|
-
if (NeMenu.CHAR_REF_REGEX.test(charLeft))
|
|
414
|
-
$domItem.append(`<span class='icon left'>&#x${charLeft};</span>`);
|
|
415
|
-
else if (charLeft)
|
|
416
|
-
console.warn(`ne14-menu: Bad hex code '${charLeft}' to left of '${bestText}'.`);
|
|
417
|
-
else if (imgLeft)
|
|
418
|
-
$domItem.append(`<img class='icon left' src='${imgLeft.src}'/>`);
|
|
419
|
-
if (NeMenu.CHAR_REF_REGEX.test(charRight))
|
|
420
|
-
$domItem.append(`<span class='icon right'>&#x${charRight};</span>`);
|
|
421
|
-
else if (charRight)
|
|
422
|
-
console.warn(`ne14-menu: Bad hex code '${charRight}' to right of '${bestText}'.`);
|
|
423
|
-
else if (imgRight)
|
|
424
|
-
$domItem.append(`<img class='icon right' src='${imgRight.src}'/>`);
|
|
425
|
-
}
|
|
426
|
-
if (bestText)
|
|
427
|
-
$domItem.append({ tag: 'p', text: bestText });
|
|
428
|
-
if (shortcut)
|
|
429
|
-
$domItem.append({ tag: 'p', text: shortcut });
|
|
430
|
-
if (isGrouper)
|
|
431
|
-
$domItem.appendIn({ tag: 'ul' }).append(...this.walk(ul, isDisabled, `${liRef}-`));
|
|
432
|
-
// Do not push two consecutive splits
|
|
433
|
-
if (!isSplit || !((_c = (_b = acc[acc.length - 1]) === null || _b === void 0 ? void 0 : _b.classList) === null || _c === void 0 ? void 0 : _c.contains('split'))) {
|
|
434
|
-
acc.push($domItem.elements[0]);
|
|
435
|
-
}
|
|
436
|
-
return acc;
|
|
437
|
-
}, []);
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
NeMenu.Css = reduceCss(decode(stylesUrl));
|
|
441
|
-
NeMenu.Html = reduceHtml(decode(markupUrl));
|
|
442
|
-
NeMenu.CHAR_REF_REGEX = /^[0-9a-f]{4,5}$/i;
|
|
443
|
-
|
|
444
|
-
if ('customElements' in window) {
|
|
445
|
-
window.customElements.define('ne14-menu', NeMenu);
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
exports.ContextMenu = NeMenu;
|
|
449
|
-
|
|
450
|
-
}));
|