@ne1410s/menu 0.1.3 → 0.1.4

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/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { NeMenu } from './menu/menu';
2
- export { NeMenu as ContextMenu };
1
+ import { NeMenu } from './menu/menu';
2
+ export { NeMenu as ContextMenu };
@@ -1,18 +1,18 @@
1
- import { CustomElementBase } from '@ne1410s/cust-elems';
2
- export declare class NeMenu extends CustomElementBase {
3
- private static readonly Css;
4
- private static readonly Html;
5
- private static readonly CHAR_REF_REGEX;
6
- private readonly top;
7
- private _connected;
8
- constructor();
9
- connectedCallback(): void;
10
- /** Opens the menu. */
11
- open(): void;
12
- /** Closes the menu. */
13
- close(): void;
14
- /** Reloads active contents based on client dom. */
15
- reload(): void;
16
- private onParentContext;
17
- private walk;
18
- }
1
+ import { CustomElementBase } from '@ne1410s/cust-elems';
2
+ export declare class NeMenu extends CustomElementBase {
3
+ private static readonly Css;
4
+ private static readonly Html;
5
+ private static readonly CHAR_REF_REGEX;
6
+ private readonly top;
7
+ private _connected;
8
+ constructor();
9
+ connectedCallback(): void;
10
+ /** Opens the menu. */
11
+ open(): void;
12
+ /** Closes the menu. */
13
+ close(): void;
14
+ /** Reloads active contents based on client dom. */
15
+ reload(): void;
16
+ private onParentContext;
17
+ private walk;
18
+ }
package/dist/models.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export interface MenuEventDetail {
2
- ref: string;
3
- title: string;
4
- origin: HTMLElement;
5
- }
1
+ export interface MenuEventDetail {
2
+ ref: string;
3
+ title: string;
4
+ origin: HTMLElement;
5
+ }
@@ -7,170 +7,170 @@ var markupUrl = "data:text/html;base64,PHNsb3Q+PC9zbG90Pg0KPHVsIGNsYXNzPSJ0b3AiP
7
7
 
8
8
  var stylesUrl = "data:text/css;base64,dWwsDQpsaSB7DQogIHBhZGRpbmc6IDA7DQogIG1hcmdpbjogMDsNCiAgZm9udDogaW5oZXJpdDsNCn0NCnNsb3QsDQpsaS5zcGxpdCAuaWNvbiB7DQogIGRpc3BsYXk6IG5vbmU7DQp9DQoudG9wOm5vdCgub3BlbiksDQp1bDpub3QoLnRvcCkgew0KICB2aXNpYmlsaXR5OiBoaWRkZW47DQp9DQoNCnVsIHsNCiAgYm9yZGVyOiB2YXIoLS1ib3JkZXIsIDFweCBzb2xpZCAjYmJiKTsNCiAgYmFja2dyb3VuZDogdmFyKC0tYmcsICNmZmYpOw0KICBib3gtc2hhZG93OiB2YXIoLS1ib3gtc2hhZG93LCAycHggMnB4IDNweCAjODg4KTsNCiAgdHJhbnNpdGlvbjogYmFja2dyb3VuZCAwLjZzOw0KICB6LWluZGV4OiA5OTk5OTk5Ow0KfQ0KDQoudG9wIHsNCiAgcG9zaXRpb246IGZpeGVkOw0KICBmb250LXNpemU6IHZhcigtLWZvbnQtc2l6ZSwgMC42NXJlbSk7DQogIHVzZXItc2VsZWN0OiBub25lOw0KfQ0KDQouaWNvbi5sZWZ0IHsNCiAgbGVmdDogMWVtOw0KICB0cmFuc2Zvcm06IHRyYW5zbGF0ZSgtNTAlLCAtNTAlKTsNCn0NCi5pY29uLnJpZ2h0IHsNCiAgcmlnaHQ6IDFlbTsNCiAgdHJhbnNmb3JtOiB0cmFuc2xhdGUoNTAlLCAtNTAlKTsNCn0NCi5pY29uIHsNCiAgbWF4LXdpZHRoOiAxZW07DQogIG1heC1oZWlnaHQ6IDFlbTsNCiAgcG9zaXRpb246IGFic29sdXRlOw0KICB0b3A6IDUwJTsNCiAgbGluZS1oZWlnaHQ6IDA7DQp9DQoNCmxpID4gcDpub3QoOmVtcHR5KSB7DQogIG1hcmdpbjogMCAxZW07DQogIHdoaXRlLXNwYWNlOiBub3dyYXA7DQp9DQpsaS5kaXNhYmxlZCB7DQogIGNvbG9yOiB2YXIoLS1kaXNhYmxlZC1mZywgI2JiYik7DQp9DQpsaS5zcGxpdCB7DQogIGJvcmRlci10b3A6IHZhcigtLXNwbGl0LWJvcmRlciwgdmFyKC0tYm9yZGVyLCAxcHggc29saWQgI2JiYikpOw0KICBwYWRkaW5nOiAwOw0KICBtYXJnaW46IDAuM2VtOw0KfQ0KbGkuc3BsaXQ6Zmlyc3QtY2hpbGQsDQpsaS5zcGxpdDpsYXN0LWNoaWxkLA0KbGkuc3BsaXQgKyBsaS5zcGxpdCB7DQogIGRpc3BsYXk6IG5vbmU7DQp9DQpsaS5ob3Zlcjpub3QoLmRpc2FiZWQpOm5vdCguc3BsaXQpIHsNCiAgYmFja2dyb3VuZDogdmFyKC0taG92ZXItaXRlbS1iZywgI2JiYik7DQp9DQoudG9wLm9wZW4gbGkuaG92ZXIgPiB1bCB7DQogIHZpc2liaWxpdHk6IHZpc2libGU7DQp9DQpsaSB7DQogIG1hcmdpbjogMC4yZW0gMDsNCiAgcGFkZGluZzogMC41ZW0gMWVtOw0KICBkaXNwbGF5OiBmbGV4Ow0KICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47DQogIHRleHQtYWxpZ246IGxlZnQ7DQogIHBvc2l0aW9uOiByZWxhdGl2ZTsNCiAgY3Vyc29yOiBkZWZhdWx0Ow0KICBjb2xvcjogdmFyKC0tZmcsICMwMDApOw0KfQ0KDQpsaS5ncm91cDo6YWZ0ZXIgew0KICBjb250ZW50OiAnXDI1YjYnOw0KICBwb3NpdGlvbjogYWJzb2x1dGU7DQogIGZvbnQtc2l6ZTogMC42NWVtOw0KICByaWdodDogMDsNCiAgdG9wOiA1MCU7DQogIHRyYW5zZm9ybTogdHJhbnNsYXRlKC01MCUsIC01MCUpOw0KfQ0KDQp1bDpub3QoLnRvcCkgew0KICBwb3NpdGlvbjogYWJzb2x1dGU7DQogIGxlZnQ6IDEwMCU7DQogIHRvcDogLTAuMjVlbTsNCn0NCg0KdWwubmVzdGxlIHsNCiAgbGVmdDogMC41ZW07DQogIHRvcDogMTAwJTsNCn0NCg==";
9
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));
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
170
  NeMenu.CHAR_REF_REGEX = /^[0-9a-f]{4,5}$/i;
171
171
 
172
- if ('customElements' in window) {
173
- window.customElements.define('ne14-menu', NeMenu);
172
+ if ('customElements' in window) {
173
+ window.customElements.define('ne14-menu', NeMenu);
174
174
  }
175
175
 
176
176
  exports.ContextMenu = NeMenu;