@nuralyui/menu 0.0.9 → 0.0.15
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/bundle.js +1305 -0
- package/index.d.ts +2 -0
- package/index.js.map +1 -1
- package/menu.component.d.ts +48 -13
- package/menu.component.js +256 -73
- package/menu.component.js.map +1 -1
- package/menu.style.js +316 -79
- package/menu.style.js.map +1 -1
- package/menu.types.d.ts +41 -1
- package/menu.types.js +6 -1
- package/menu.types.js.map +1 -1
- package/package.json +40 -5
- package/react.d.ts +4 -2
- package/react.js +7 -5
- package/react.js.map +1 -1
- package/demo/menus-demo.d.ts +0 -22
- package/demo/menus-demo.d.ts.map +0 -1
- package/demo/menus-demo.js +0 -157
- package/demo/menus-demo.js.map +0 -1
- package/index.d.ts.map +0 -1
- package/menu.component.d.ts.map +0 -1
- package/menu.constants.d.ts.map +0 -1
- package/menu.style.d.ts.map +0 -1
- package/menu.types.d.ts.map +0 -1
- package/react.d.ts.map +0 -1
- package/templates/hy-menu-link.d.ts +0 -29
- package/templates/hy-menu-link.d.ts.map +0 -1
- package/templates/hy-menu-link.js +0 -122
- package/templates/hy-menu-link.js.map +0 -1
- package/templates/hy-sub-menu.d.ts +0 -32
- package/templates/hy-sub-menu.d.ts.map +0 -1
- package/templates/hy-sub-menu.js +0 -121
- package/templates/hy-sub-menu.js.map +0 -1
- package/templates/menu-link.contants.d.ts +0 -5
- package/templates/menu-link.contants.d.ts.map +0 -1
- package/templates/menu-link.contants.js +0 -6
- package/templates/menu-link.contants.js.map +0 -1
- package/templates/menu-link.style.d.ts +0 -2
- package/templates/menu-link.style.d.ts.map +0 -1
- package/templates/menu-link.style.js +0 -98
- package/templates/menu-link.style.js.map +0 -1
- package/templates/sub-menu.style.d.ts +0 -2
- package/templates/sub-menu.style.d.ts.map +0 -1
- package/templates/sub-menu.style.js +0 -88
- package/templates/sub-menu.style.js.map +0 -1
- package/test/menu-link_test.d.ts +0 -2
- package/test/menu-link_test.d.ts.map +0 -1
- package/test/menu-link_test.js +0 -85
- package/test/menu-link_test.js.map +0 -1
- package/test/menu_test.d.ts +0 -2
- package/test/menu_test.d.ts.map +0 -1
- package/test/menu_test.js +0 -81
- package/test/menu_test.js.map +0 -1
- package/test/sub-menu_test.d.ts +0 -2
- package/test/sub-menu_test.d.ts.map +0 -1
- package/test/sub-menu_test.js +0 -72
- package/test/sub-menu_test.js.map +0 -1
package/index.d.ts
CHANGED
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/menu/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC","sourcesContent":["export * from './menu.component.js';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/menu/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC","sourcesContent":["export * from './menu.component.js';\nexport { MenuSize, IconPosition } from './menu.types.js';\nexport type { IMenu, IAction } from './menu.types.js';\n"]}
|
package/menu.component.d.ts
CHANGED
|
@@ -1,19 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2023 Nuraly, Laabidi Aymen
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
1
6
|
import { LitElement } from 'lit';
|
|
2
|
-
import { IMenu } from './menu.types.js';
|
|
3
|
-
import '
|
|
4
|
-
import '
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
import { IMenu, MenuSize } from './menu.types.js';
|
|
8
|
+
import '../icon/icon.component.js';
|
|
9
|
+
import '../dropdown/dropdown.component.js';
|
|
10
|
+
declare const NrMenuElement_base: (new (...args: any[]) => import("../../shared/dependency-mixin.js").DependencyAware) & (new (...args: any[]) => import("../../shared/theme-mixin.js").ThemeAware) & (new (...args: any[]) => import("../../shared/event-handler-mixin.js").EventHandlerCapable) & typeof LitElement;
|
|
11
|
+
/**
|
|
12
|
+
* Versatile menu component for hierarchical navigation with support for nested submenus.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```html
|
|
16
|
+
* <nr-menu .items=${menuItems}></nr-menu>
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @fires change - Menu item selected
|
|
20
|
+
* @fires action-click - Menu action clicked
|
|
21
|
+
*
|
|
22
|
+
* @slot - Menu items (auto-generated from items property)
|
|
23
|
+
*/
|
|
24
|
+
export declare class NrMenuElement extends NrMenuElement_base {
|
|
25
|
+
static styles: import("lit").CSSResult[];
|
|
26
|
+
requiredComponents: string[];
|
|
27
|
+
/** Menu items configuration */
|
|
9
28
|
items: IMenu[];
|
|
29
|
+
/** Menu size variant (small, medium, large) */
|
|
30
|
+
size: MenuSize | string;
|
|
31
|
+
private stateController;
|
|
32
|
+
private keyboardController;
|
|
33
|
+
private accessibilityController;
|
|
34
|
+
private _linkIndex;
|
|
35
|
+
constructor();
|
|
10
36
|
firstUpdated(): void;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
37
|
+
updated(): void;
|
|
38
|
+
private _initializeSelectedState;
|
|
39
|
+
private _findSelectedPath;
|
|
40
|
+
private _handleLinkClick;
|
|
41
|
+
private _handleSubMenuClick;
|
|
42
|
+
private _toggleSubMenu;
|
|
43
|
+
private _handleSubMenuMouseEnter;
|
|
44
|
+
private _handleSubMenuMouseLeave;
|
|
45
|
+
private _handleActionClick;
|
|
46
|
+
private _isPathSelected;
|
|
47
|
+
private _convertActionsToDropdownItems;
|
|
48
|
+
private _renderMenuLink;
|
|
49
|
+
private _renderSubMenu;
|
|
50
|
+
private _renderMenuItems;
|
|
16
51
|
render(): import("lit").TemplateResult<1>;
|
|
17
|
-
static styles: import("lit").CSSResult[][];
|
|
18
52
|
}
|
|
53
|
+
export {};
|
|
19
54
|
//# sourceMappingURL=menu.component.d.ts.map
|
package/menu.component.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2023 Nuraly, Laabidi Aymen
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
1
6
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
7
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
8
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -5,105 +10,283 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
10
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
11
|
};
|
|
7
12
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
8
|
-
|
|
9
|
-
import {
|
|
13
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
14
|
+
import { LitElement, html, nothing } from 'lit';
|
|
15
|
+
import { customElement, property } from 'lit/decorators.js';
|
|
10
16
|
import { styles } from './menu.style.js';
|
|
11
|
-
import '
|
|
12
|
-
import './
|
|
13
|
-
|
|
17
|
+
import { NuralyUIBaseMixin } from '../../shared/base-mixin.js';
|
|
18
|
+
import { StateController, KeyboardController, AccessibilityController } from './controllers/index.js';
|
|
19
|
+
import '../icon/icon.component.js';
|
|
20
|
+
import '../dropdown/dropdown.component.js';
|
|
21
|
+
/**
|
|
22
|
+
* Versatile menu component for hierarchical navigation with support for nested submenus.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```html
|
|
26
|
+
* <nr-menu .items=${menuItems}></nr-menu>
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @fires change - Menu item selected
|
|
30
|
+
* @fires action-click - Menu action clicked
|
|
31
|
+
*
|
|
32
|
+
* @slot - Menu items (auto-generated from items property)
|
|
33
|
+
*/
|
|
34
|
+
let NrMenuElement = class NrMenuElement extends NuralyUIBaseMixin(LitElement) {
|
|
35
|
+
constructor() {
|
|
36
|
+
super();
|
|
37
|
+
this.requiredComponents = ['nr-icon', 'nr-dropdown'];
|
|
38
|
+
/** Menu items configuration */
|
|
39
|
+
this.items = [];
|
|
40
|
+
/** Menu size variant (small, medium, large) */
|
|
41
|
+
this.size = "medium" /* MenuSize.Medium */;
|
|
42
|
+
this._linkIndex = 0;
|
|
43
|
+
this.stateController = new StateController(this);
|
|
44
|
+
this.keyboardController = new KeyboardController(this, this.stateController);
|
|
45
|
+
this.accessibilityController = new AccessibilityController(this, this.stateController);
|
|
46
|
+
}
|
|
14
47
|
firstUpdated() {
|
|
15
|
-
this.
|
|
48
|
+
this._initializeSelectedState();
|
|
49
|
+
this.accessibilityController.updateAriaAttributes();
|
|
50
|
+
}
|
|
51
|
+
updated() {
|
|
52
|
+
this.accessibilityController.updateAriaAttributes();
|
|
16
53
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
this.
|
|
54
|
+
_initializeSelectedState() {
|
|
55
|
+
this._linkIndex = 0;
|
|
56
|
+
this._findSelectedPath(this.items);
|
|
20
57
|
}
|
|
21
|
-
|
|
58
|
+
_findSelectedPath(items, path = []) {
|
|
59
|
+
for (let index = 0; index < items.length; index++) {
|
|
60
|
+
const item = items[index];
|
|
61
|
+
const currentPath = [...path, index];
|
|
62
|
+
if (item.children) {
|
|
63
|
+
if (this._findSelectedPath(item.children, currentPath)) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
if (item.selected) {
|
|
69
|
+
this.stateController.setSelectedPath(currentPath);
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
_handleLinkClick(path, value, event) {
|
|
22
77
|
var _a;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
78
|
+
if ((_a = event === null || event === void 0 ? void 0 : event.target) === null || _a === void 0 ? void 0 : _a.classList.contains('action-icon')) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if ((event === null || event === void 0 ? void 0 : event.type) === 'click') {
|
|
82
|
+
const mouseEvent = event;
|
|
83
|
+
if (mouseEvent.detail > 0) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
this.stateController.setSelectedPath(path);
|
|
32
88
|
this.dispatchEvent(new CustomEvent('change', {
|
|
33
89
|
bubbles: true,
|
|
34
90
|
composed: true,
|
|
35
|
-
detail: { path
|
|
91
|
+
detail: { path, value },
|
|
36
92
|
}));
|
|
93
|
+
this.requestUpdate();
|
|
37
94
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
95
|
+
_handleSubMenuClick(path, value, event) {
|
|
96
|
+
const mouseEvent = event;
|
|
97
|
+
const target = event.target;
|
|
98
|
+
// Don't handle if clicking on toggle icon or its parent container
|
|
99
|
+
if (target.id === 'toggle-icon' || target.closest('#toggle-icon')) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
// If it's a click event
|
|
103
|
+
if (event.type === 'click') {
|
|
104
|
+
// Check if it's keyboard activation (Enter/Space) - detail will be 0
|
|
105
|
+
if (mouseEvent.detail === 0) {
|
|
106
|
+
// Keyboard activation - toggle the submenu
|
|
107
|
+
this.stateController.toggleSubMenu(path);
|
|
108
|
+
this.requestUpdate();
|
|
109
|
+
return;
|
|
42
110
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
_selectMenu(selectMenuEvent) {
|
|
46
|
-
if (this._currentSelectedLink >= 0) {
|
|
47
|
-
this._menuLinks[this._currentSelectedLink].removeAttribute('selected');
|
|
48
|
-
this._currentSelectedLink = -1;
|
|
111
|
+
// Real mouse click - already handled by mousedown, so return
|
|
112
|
+
return;
|
|
49
113
|
}
|
|
50
|
-
|
|
51
|
-
this.
|
|
114
|
+
// This is a mousedown event - highlight and toggle the submenu
|
|
115
|
+
this.stateController.setSelectedPath([]);
|
|
116
|
+
this.stateController.clearHighlights();
|
|
117
|
+
this.stateController.setHighlighted(path, true);
|
|
118
|
+
// Toggle the submenu when clicking on header
|
|
119
|
+
this.stateController.toggleSubMenu(path);
|
|
120
|
+
this.dispatchEvent(new CustomEvent('change', {
|
|
121
|
+
bubbles: true,
|
|
122
|
+
composed: true,
|
|
123
|
+
detail: { path, value },
|
|
124
|
+
}));
|
|
125
|
+
this.requestUpdate();
|
|
126
|
+
}
|
|
127
|
+
_toggleSubMenu(path, event) {
|
|
128
|
+
event.stopPropagation();
|
|
129
|
+
this.stateController.toggleSubMenu(path);
|
|
130
|
+
this.requestUpdate();
|
|
52
131
|
}
|
|
53
|
-
|
|
132
|
+
_handleSubMenuMouseEnter(path) {
|
|
133
|
+
this.stateController.setHovered(path, true);
|
|
134
|
+
this.requestUpdate();
|
|
135
|
+
}
|
|
136
|
+
_handleSubMenuMouseLeave(path) {
|
|
137
|
+
this.stateController.setHovered(path, false);
|
|
138
|
+
this.requestUpdate();
|
|
139
|
+
}
|
|
140
|
+
_handleActionClick(path, event) {
|
|
141
|
+
const item = event.detail.item;
|
|
142
|
+
this.dispatchEvent(new CustomEvent('action-click', {
|
|
143
|
+
detail: { value: item.value, path, item },
|
|
144
|
+
composed: true,
|
|
145
|
+
bubbles: true,
|
|
146
|
+
}));
|
|
147
|
+
}
|
|
148
|
+
_isPathSelected(path) {
|
|
149
|
+
return this.stateController.isPathSelected(path);
|
|
150
|
+
}
|
|
151
|
+
_convertActionsToDropdownItems(actions) {
|
|
152
|
+
return actions.map(action => ({
|
|
153
|
+
id: action.value,
|
|
154
|
+
label: action.label,
|
|
155
|
+
value: action.value
|
|
156
|
+
}));
|
|
157
|
+
}
|
|
158
|
+
_renderMenuLink(menu, path) {
|
|
159
|
+
var _a, _b;
|
|
160
|
+
const pathKey = path.join('-');
|
|
161
|
+
const isSelected = this._isPathSelected(path);
|
|
162
|
+
const linkIndex = this._linkIndex++;
|
|
163
|
+
return html `
|
|
164
|
+
<li
|
|
165
|
+
class="menu-link ${isSelected ? 'selected' : ''} ${menu.disabled ? 'disabled' : ''}"
|
|
166
|
+
data-path=${pathKey}
|
|
167
|
+
data-index=${linkIndex}
|
|
168
|
+
tabindex="0"
|
|
169
|
+
@mousedown=${!menu.disabled ? (e) => this._handleLinkClick(path, menu.text, e) : nothing}
|
|
170
|
+
@click=${!menu.disabled ? (e) => this._handleLinkClick(path, menu.text, e) : nothing}>
|
|
171
|
+
<div class="icon-container">
|
|
172
|
+
${menu.icon ? html `
|
|
173
|
+
${!menu.text
|
|
174
|
+
? html `<div class="icon-only"><nr-icon name="${menu.icon}"></nr-icon></div>`
|
|
175
|
+
: html `<nr-icon name="${menu.icon}"></nr-icon>`}
|
|
176
|
+
` : nothing}
|
|
177
|
+
</div>
|
|
178
|
+
${menu.text ? html `
|
|
179
|
+
<div class="action-text-container">
|
|
180
|
+
<div class="text-container">
|
|
181
|
+
<span>${menu.text}</span>
|
|
182
|
+
</div>
|
|
183
|
+
<div class="icon-container">
|
|
184
|
+
${((_a = menu.status) === null || _a === void 0 ? void 0 : _a.icon) ? html `
|
|
185
|
+
<nr-icon name=${menu.status.icon} class="status-icon"></nr-icon>
|
|
186
|
+
` : nothing}
|
|
187
|
+
${((_b = menu.menu) === null || _b === void 0 ? void 0 : _b.actions) ? html `
|
|
188
|
+
<nr-dropdown
|
|
189
|
+
.items=${this._convertActionsToDropdownItems(menu.menu.actions)}
|
|
190
|
+
trigger="click"
|
|
191
|
+
placement="bottom-end"
|
|
192
|
+
@nr-dropdown-item-click=${(e) => this._handleActionClick(path, e)}>
|
|
193
|
+
<nr-icon name="${menu.menu.icon}" class="action-icon" slot="trigger"></nr-icon>
|
|
194
|
+
</nr-dropdown>
|
|
195
|
+
` : nothing}
|
|
196
|
+
</div>
|
|
197
|
+
</div>
|
|
198
|
+
` : nothing}
|
|
199
|
+
</li>
|
|
200
|
+
`;
|
|
201
|
+
}
|
|
202
|
+
_renderSubMenu(menu, path) {
|
|
203
|
+
var _a, _b;
|
|
204
|
+
const pathKey = path.join('-');
|
|
205
|
+
const isOpen = this.stateController.isSubMenuOpen(path) || menu.opened;
|
|
206
|
+
const isHovered = this.stateController.isSubMenuHovered(path);
|
|
207
|
+
const isHighlighted = this.stateController.isSubMenuHighlighted(path);
|
|
208
|
+
const isSelected = menu.selected;
|
|
209
|
+
return html `
|
|
210
|
+
<ul
|
|
211
|
+
class="sub-menu ${isHighlighted ? 'highlighted' : ''} ${menu.disabled ? 'disabled' : ''} ${isSelected ? 'selected' : ''}"
|
|
212
|
+
data-path=${pathKey}
|
|
213
|
+
tabindex="0"
|
|
214
|
+
@mouseenter=${() => this._handleSubMenuMouseEnter(path)}
|
|
215
|
+
@mouseleave=${() => this._handleSubMenuMouseLeave(path)}
|
|
216
|
+
@click=${!menu.disabled ? (e) => {
|
|
217
|
+
// Handle keyboard activation on the ul element
|
|
218
|
+
const target = e.target;
|
|
219
|
+
const mouseEvent = e;
|
|
220
|
+
// If click is on the ul itself (not children) and it's keyboard-generated
|
|
221
|
+
if (target.classList.contains('sub-menu') && mouseEvent.detail === 0) {
|
|
222
|
+
e.stopPropagation(); // Prevent bubbling to parent submenus
|
|
223
|
+
this.stateController.toggleSubMenu(path);
|
|
224
|
+
this.requestUpdate();
|
|
225
|
+
}
|
|
226
|
+
} : nothing}>
|
|
227
|
+
<div
|
|
228
|
+
class="sub-menu-header"
|
|
229
|
+
@mousedown=${!menu.disabled ? (e) => this._handleSubMenuClick(path, menu.text, e) : nothing}
|
|
230
|
+
@click=${!menu.disabled ? (e) => this._handleSubMenuClick(path, menu.text, e) : nothing}>
|
|
231
|
+
${menu.icon ? html `<nr-icon class="text-icon" name="${menu.icon}"></nr-icon>` : nothing}
|
|
232
|
+
<span>${menu.text}</span>
|
|
233
|
+
<div class="icons-container">
|
|
234
|
+
${((_a = menu.status) === null || _a === void 0 ? void 0 : _a.icon) ? html `
|
|
235
|
+
<nr-icon name=${menu.status.icon} class="status-icon"></nr-icon>
|
|
236
|
+
` : nothing}
|
|
237
|
+
${(isHighlighted || isHovered) && ((_b = menu.menu) === null || _b === void 0 ? void 0 : _b.actions) ? html `
|
|
238
|
+
<nr-dropdown
|
|
239
|
+
.items=${this._convertActionsToDropdownItems(menu.menu.actions)}
|
|
240
|
+
trigger="click"
|
|
241
|
+
placement="bottom-end"
|
|
242
|
+
@nr-dropdown-item-click=${(e) => this._handleActionClick(path, e)}>
|
|
243
|
+
<nr-icon name="${menu.menu.icon}" class="action-icon" slot="trigger"></nr-icon>
|
|
244
|
+
</nr-dropdown>
|
|
245
|
+
` : nothing}
|
|
246
|
+
${menu.children && menu.children.length ? html `
|
|
247
|
+
<nr-icon
|
|
248
|
+
id="toggle-icon"
|
|
249
|
+
name="${isOpen ? 'angle-up' : 'angle-down'}"
|
|
250
|
+
@mousedown=${!menu.disabled ? (e) => this._toggleSubMenu(path, e) : nothing}>
|
|
251
|
+
</nr-icon>
|
|
252
|
+
` : nothing}
|
|
253
|
+
</div>
|
|
254
|
+
</div>
|
|
255
|
+
<div class="sub-menu-children" style="display: ${isOpen ? 'block' : 'none'}">
|
|
256
|
+
${menu.children ? this._renderMenuItems(menu.children, path) : nothing}
|
|
257
|
+
</div>
|
|
258
|
+
</ul>
|
|
259
|
+
`;
|
|
260
|
+
}
|
|
261
|
+
_renderMenuItems(items, parentPath = []) {
|
|
54
262
|
return items.map((menu, index) => {
|
|
55
|
-
const currentPath = [...
|
|
263
|
+
const currentPath = [...parentPath, index];
|
|
56
264
|
if (menu.children) {
|
|
57
|
-
return
|
|
58
|
-
<hy-sub-menu
|
|
59
|
-
.menu=${menu}
|
|
60
|
-
.text=${menu.text}
|
|
61
|
-
.icon=${menu.icon}
|
|
62
|
-
.disabled=${menu.disabled}
|
|
63
|
-
.status=${menu.status}
|
|
64
|
-
?selected=${menu.selected}
|
|
65
|
-
data-path=${currentPath}
|
|
66
|
-
@select-menu=${this._selectMenu}>
|
|
67
|
-
${this._display(menu.children, [...path, index])}
|
|
68
|
-
</hy-sub-menu>
|
|
69
|
-
`;
|
|
265
|
+
return this._renderSubMenu(menu, currentPath);
|
|
70
266
|
}
|
|
71
267
|
else {
|
|
72
|
-
return
|
|
73
|
-
data-path=${currentPath}
|
|
74
|
-
icon=${menu.icon}
|
|
75
|
-
.menu=${menu.menu}
|
|
76
|
-
.status=${menu.status}
|
|
77
|
-
text=${menu.text}
|
|
78
|
-
link=${menu.link}
|
|
79
|
-
iconposition=${menu.iconPosition}
|
|
80
|
-
?selected=${menu.selected}
|
|
81
|
-
?disabled=${menu.disabled}
|
|
82
|
-
@selected-link=${this._updateSelectedLink}
|
|
83
|
-
></hy-menu-link>`;
|
|
268
|
+
return this._renderMenuLink(menu, currentPath);
|
|
84
269
|
}
|
|
85
270
|
});
|
|
86
271
|
}
|
|
87
272
|
render() {
|
|
273
|
+
this._linkIndex = 0;
|
|
88
274
|
return html `
|
|
89
|
-
<ul>
|
|
90
|
-
${this.
|
|
275
|
+
<ul class="menu-root menu--${this.size}">
|
|
276
|
+
${this._renderMenuItems(this.items)}
|
|
91
277
|
</ul>
|
|
92
278
|
`;
|
|
93
279
|
}
|
|
94
280
|
};
|
|
95
|
-
|
|
96
|
-
__decorate([
|
|
97
|
-
queryAll('hy-menu-link')
|
|
98
|
-
], HyMenuComponent.prototype, "_menuLinks", void 0);
|
|
281
|
+
NrMenuElement.styles = styles;
|
|
99
282
|
__decorate([
|
|
100
|
-
|
|
101
|
-
],
|
|
283
|
+
property({ type: Array })
|
|
284
|
+
], NrMenuElement.prototype, "items", void 0);
|
|
102
285
|
__decorate([
|
|
103
|
-
property()
|
|
104
|
-
],
|
|
105
|
-
|
|
106
|
-
customElement('
|
|
107
|
-
],
|
|
108
|
-
export {
|
|
286
|
+
property({ type: String })
|
|
287
|
+
], NrMenuElement.prototype, "size", void 0);
|
|
288
|
+
NrMenuElement = __decorate([
|
|
289
|
+
customElement('nr-menu')
|
|
290
|
+
], NrMenuElement);
|
|
291
|
+
export { NrMenuElement };
|
|
109
292
|
//# sourceMappingURL=menu.component.js.map
|
package/menu.component.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menu.component.js","sourceRoot":"","sources":["../../../src/components/menu/menu.component.ts"],"names":[],"mappings":";;;;;;AAAA,uDAAuD;AACvD,OAAO,EAAC,UAAU,EAAE,IAAI,EAAC,MAAM,KAAK,CAAC;AACrC,OAAO,EAAC,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAC,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAC,MAAM,EAAC,MAAM,iBAAiB,CAAC;AAEvC,OAAO,6BAA6B,CAAC;AACrC,OAAO,4BAA4B,CAAC;AAEpC,IAAa,eAAe,GAA5B,MAAa,eAAgB,SAAQ,UAAU;IAWpC,YAAY;QACnB,IAAI,CAAC,oBAAoB,EAAE,CAAC;IAC9B,CAAC;IAED,oBAAoB;QAClB,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC,oBAAoB,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC;IACnG,CAAC;IAED,mBAAmB,CAAC,uBAAoC;;QACtD,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAC9B,MAAM,gBAAgB,GAAG,uBAAuB,CAAC,MAAM,CAAC,KAAK,CAAC;QAC9D,MAAM,KAAK,GAAG,uBAAuB,CAAC,MAAM,CAAC,KAAK,CAAC;QACnD,IAAI,IAAI,CAAC,oBAAoB,IAAI,CAAC;YAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;QAC3G,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACnE,IAAI,CAAC,oBAAoB,GAAG,gBAAgB,CAAC;QAC7C,MAAM,YAAY,GAAG,MAAA,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC;aACnD,YAAY,CAAC,WAAW,CAAC,0CACxB,KAAK,CAAC,GAAG,EACV,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC;QACtC,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,QAAQ,EAAE;YACxB,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;YACd,MAAM,EAAE,EAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAC;SACpC,CAAC,CACH,CAAC;IACJ,CAAC;IAED,sBAAsB;QACpB,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAClC,IAAI,OAAO,CAAC,YAAY,CAAC,aAAa,CAAC,EAAE;gBACvC,OAAO,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;aACxC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IACD,WAAW,CAAC,eAA2B;QACrC,IAAI,IAAI,CAAC,oBAAoB,IAAI,CAAC,EAClC;YACE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;YACvE,IAAI,CAAC,oBAAoB,GAAG,CAAC,CAAC,CAAC;SAChC;QAED,IAAI,CAAC,sBAAsB,EAAE,CAAA;QAC7B,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,QAAQ,EAAC,EAAC,OAAO,EAAC,IAAI,EAAC,QAAQ,EAAC,IAAI,EAAC,MAAM,EAAC,EAAC,IAAI,EAAC,eAAe,CAAC,MAAM,CAAC,IAAI,EAAC,KAAK,EAAC,eAAe,CAAC,MAAM,CAAC,KAAK,EAAC,EAAC,CAAC,CAAC,CAAC;IAC1J,CAAC;IAED,QAAQ,CAAC,KAAc,EAAE,OAAiB,EAAE;QAC1C,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;YAC/B,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC/C,IAAI,IAAI,CAAC,QAAQ,EAAE;gBACjB,OAAO,IAAI,CAAA;;kBAED,IAAI;kBACJ,IAAI,CAAC,IAAI;kBACT,IAAI,CAAC,IAAI;sBACL,IAAI,CAAC,QAAQ;oBACf,IAAI,CAAC,MAAM;sBACT,IAAI,CAAC,QAAQ;sBACb,WAAW;yBACR,IAAI,CAAC,WAAW;cAC3B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC;;SAEnD,CAAC;aACH;iBAAM;gBACL,OAAO,IAAI,CAAA;sBACG,WAAW;iBAChB,IAAI,CAAC,IAAI;kBACR,IAAI,CAAC,IAAI;oBACP,IAAI,CAAC,MAAM;iBACd,IAAI,CAAC,IAAI;iBACT,IAAI,CAAC,IAAI;yBACD,IAAI,CAAC,YAAY;sBACpB,IAAI,CAAC,QAAQ;sBACb,IAAI,CAAC,QAAQ;2BACR,IAAI,CAAC,mBAAmB;yBAC1B,CAAC;aACnB;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAEQ,MAAM;QACb,OAAO,IAAI,CAAA;;UAEL,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC;;KAE9B,CAAC;IACJ,CAAC;CAGF,CAAA;AADiB,sBAAM,GAAG,CAAC,MAAM,CAAE,CAAA;AAjGlC;IADC,QAAQ,CAAC,cAAc,CAAC;mDACY;AAGrC;IADC,QAAQ,CAAC,aAAa,CAAC;mDACa;AAGrC;IADC,QAAQ,EAAE;8CACK;AATL,eAAe;IAD3B,aAAa,CAAC,SAAS,CAAC;GACZ,eAAe,CAqG3B;SArGY,eAAe","sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {LitElement, html} from 'lit';\nimport {customElement, property, queryAll} from 'lit/decorators.js';\nimport {styles} from './menu.style.js';\nimport {IMenu} from './menu.types.js';\nimport './templates/hy-menu-link.js';\nimport './templates/hy-sub-menu.js';\n@customElement('hy-menu')\nexport class HyMenuComponent extends LitElement {\n private _currentSelectedLink!: number;\n @queryAll('hy-menu-link')\n _menuLinks!: NodeListOf<HTMLElement>;\n\n @queryAll('hy-sub-menu')\n _subMenues!: NodeListOf<HTMLElement>;\n\n @property()\n items!: IMenu[];\n\n override firstUpdated(): void {\n this._getPreSelectedIndex();\n }\n\n _getPreSelectedIndex() {\n const listOfLinks = [...this._menuLinks.values()];\n this._currentSelectedLink = listOfLinks.findIndex((element) => element.hasAttribute('selected'));\n }\n\n _updateSelectedLink(updateSelectedLinkEvent: CustomEvent) {\n this._handleInitHighlighted();\n const newSelectedIndex = updateSelectedLinkEvent.detail.index;\n const value = updateSelectedLinkEvent.detail.value;\n if (this._currentSelectedLink >= 0) this._menuLinks[this._currentSelectedLink].removeAttribute('selected');\n this._menuLinks[newSelectedIndex].setAttribute('selected', 'true');\n this._currentSelectedLink = newSelectedIndex;\n const pathToOption = this._menuLinks[newSelectedIndex]\n .getAttribute('data-path')\n ?.split('-')\n .map((valueString) => +valueString);\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n composed: true,\n detail: {path: pathToOption, value},\n })\n );\n }\n\n _handleInitHighlighted() {\n this._subMenues.forEach((element) => {\n if (element.hasAttribute('highlighted')) {\n element.removeAttribute('highlighted');\n }\n });\n }\n _selectMenu(selectMenuEvent:CustomEvent){\n if (this._currentSelectedLink >= 0) \n {\n this._menuLinks[this._currentSelectedLink].removeAttribute('selected');\n this._currentSelectedLink = -1;\n }\n\n this._handleInitHighlighted()\n this.dispatchEvent(new CustomEvent('change',{bubbles:true,composed:true,detail:{path:selectMenuEvent.detail.path,value:selectMenuEvent.detail.value}}));\n }\n\n _display(items: IMenu[], path: number[] = []): any {\n return items.map((menu, index) => {\n const currentPath = [...path, index].join('-');\n if (menu.children) {\n return html`\n <hy-sub-menu \n .menu=${menu} \n .text=${menu.text} \n .icon=${menu.icon} \n .disabled=${menu.disabled} \n .status=${menu.status}\n ?selected=${menu.selected}\n data-path=${currentPath} \n @select-menu=${this._selectMenu}>\n ${this._display(menu.children, [...path, index])}\n </hy-sub-menu>\n `;\n } else {\n return html` <hy-menu-link\n data-path=${currentPath}\n icon=${menu.icon}\n .menu=${menu.menu}\n .status=${menu.status}\n text=${menu.text}\n link=${menu.link}\n iconposition=${menu.iconPosition}\n ?selected=${menu.selected}\n ?disabled=${menu.disabled}\n @selected-link=${this._updateSelectedLink}\n ></hy-menu-link>`;\n }\n });\n }\n\n override render() {\n return html`\n <ul>\n ${this._display(this.items)}\n </ul>\n `;\n }\n\n static override styles = [styles];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"menu.component.js","sourceRoot":"","sources":["../../../src/components/menu/menu.component.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2023 Nuraly, Laabidi Aymen\n * SPDX-License-Identifier: MIT\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-unused-vars */\nimport { LitElement, html, nothing } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { styles } from './menu.style.js';\nimport { IMenu, IAction, MenuSize } from './menu.types.js';\nimport { NuralyUIBaseMixin } from '../../shared/base-mixin.js';\nimport { StateController, KeyboardController, AccessibilityController } from './controllers/index.js';\nimport '../icon/icon.component.js';\nimport '../dropdown/dropdown.component.js';\n\n/**\n * Versatile menu component for hierarchical navigation with support for nested submenus.\n * \n * @example\n * ```html\n * <nr-menu .items=${menuItems}></nr-menu>\n * ```\n * \n * @fires change - Menu item selected\n * @fires action-click - Menu action clicked\n * \n * @slot - Menu items (auto-generated from items property)\n */\n@customElement('nr-menu')\nexport class NrMenuElement extends NuralyUIBaseMixin(LitElement) {\n static override styles = styles;\n \n override requiredComponents = ['nr-icon', 'nr-dropdown'];\n\n /** Menu items configuration */\n @property({ type: Array })\n items: IMenu[] = [];\n\n /** Menu size variant (small, medium, large) */\n @property({ type: String })\n size: MenuSize | string = MenuSize.Medium;\n\n // Controllers\n private stateController: StateController;\n // Keyboard controller is connected via Lit's controller system and listens to events\n // @ts-ignore - Controller is used via Lit's reactive controller system\n private keyboardController: KeyboardController;\n private accessibilityController: AccessibilityController;\n\n private _linkIndex = 0;\n\n constructor() {\n super();\n this.stateController = new StateController(this);\n this.keyboardController = new KeyboardController(this, this.stateController);\n this.accessibilityController = new AccessibilityController(this, this.stateController);\n }\n\n override firstUpdated(): void {\n this._initializeSelectedState();\n this.accessibilityController.updateAriaAttributes();\n }\n\n override updated(): void {\n this.accessibilityController.updateAriaAttributes();\n }\n\n private _initializeSelectedState() {\n this._linkIndex = 0;\n this._findSelectedPath(this.items);\n }\n\n private _findSelectedPath(items: IMenu[], path: number[] = []): boolean {\n for (let index = 0; index < items.length; index++) {\n const item = items[index];\n const currentPath = [...path, index];\n \n if (item.children) {\n if (this._findSelectedPath(item.children, currentPath)) {\n return true;\n }\n } else {\n if (item.selected) {\n this.stateController.setSelectedPath(currentPath);\n return true;\n }\n }\n }\n return false;\n }\n\n private _handleLinkClick(path: number[], value: string, event?: Event) {\n if ((event?.target as HTMLElement)?.classList.contains('action-icon')) {\n return;\n }\n\n if (event?.type === 'click') {\n const mouseEvent = event as MouseEvent;\n if (mouseEvent.detail > 0) {\n return;\n }\n }\n\n this.stateController.setSelectedPath(path);\n \n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n composed: true,\n detail: { path, value },\n })\n );\n \n this.requestUpdate();\n }\n\n private _handleSubMenuClick(path: number[], value: string, event: Event) {\n const mouseEvent = event as MouseEvent;\n const target = event.target as HTMLElement;\n \n // Don't handle if clicking on toggle icon or its parent container\n if (target.id === 'toggle-icon' || target.closest('#toggle-icon')) {\n return;\n }\n \n // If it's a click event\n if (event.type === 'click') {\n // Check if it's keyboard activation (Enter/Space) - detail will be 0\n if (mouseEvent.detail === 0) {\n // Keyboard activation - toggle the submenu\n this.stateController.toggleSubMenu(path);\n this.requestUpdate();\n return;\n }\n // Real mouse click - already handled by mousedown, so return\n return;\n }\n\n // This is a mousedown event - highlight and toggle the submenu\n \n this.stateController.setSelectedPath([]);\n this.stateController.clearHighlights();\n this.stateController.setHighlighted(path, true);\n \n // Toggle the submenu when clicking on header\n this.stateController.toggleSubMenu(path);\n\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n composed: true,\n detail: { path, value },\n })\n );\n \n this.requestUpdate();\n }\n\n private _toggleSubMenu(path: number[], event: Event) {\n event.stopPropagation();\n this.stateController.toggleSubMenu(path);\n this.requestUpdate();\n }\n\n private _handleSubMenuMouseEnter(path: number[]) {\n this.stateController.setHovered(path, true);\n this.requestUpdate();\n }\n\n private _handleSubMenuMouseLeave(path: number[]) {\n this.stateController.setHovered(path, false);\n this.requestUpdate();\n }\n\n private _handleActionClick(path: number[], event: CustomEvent) {\n const item = event.detail.item;\n this.dispatchEvent(\n new CustomEvent('action-click', {\n detail: { value: item.value, path, item },\n composed: true,\n bubbles: true,\n })\n );\n }\n\n private _isPathSelected(path: number[]): boolean {\n return this.stateController.isPathSelected(path);\n }\n\n private _convertActionsToDropdownItems(actions: IAction[]): any[] {\n return actions.map(action => ({\n id: action.value,\n label: action.label,\n value: action.value\n }));\n }\n\n private _renderMenuLink(menu: IMenu, path: number[]): any {\n const pathKey = path.join('-');\n const isSelected = this._isPathSelected(path);\n const linkIndex = this._linkIndex++;\n \n return html`\n <li \n class=\"menu-link ${isSelected ? 'selected' : ''} ${menu.disabled ? 'disabled' : ''}\"\n data-path=${pathKey}\n data-index=${linkIndex}\n tabindex=\"0\"\n @mousedown=${!menu.disabled ? (e: Event) => this._handleLinkClick(path, menu.text, e) : nothing}\n @click=${!menu.disabled ? (e: Event) => this._handleLinkClick(path, menu.text, e) : nothing}>\n <div class=\"icon-container\">\n ${menu.icon ? html`\n ${!menu.text \n ? html`<div class=\"icon-only\"><nr-icon name=\"${menu.icon}\"></nr-icon></div>`\n : html`<nr-icon name=\"${menu.icon}\"></nr-icon>`}\n ` : nothing}\n </div>\n ${menu.text ? html`\n <div class=\"action-text-container\">\n <div class=\"text-container\">\n <span>${menu.text}</span>\n </div>\n <div class=\"icon-container\">\n ${menu.status?.icon ? html`\n <nr-icon name=${menu.status.icon} class=\"status-icon\"></nr-icon>\n ` : nothing}\n ${menu.menu?.actions ? html`\n <nr-dropdown \n .items=${this._convertActionsToDropdownItems(menu.menu.actions)} \n trigger=\"click\" \n placement=\"bottom-end\"\n @nr-dropdown-item-click=${(e: CustomEvent) => this._handleActionClick(path, e)}>\n <nr-icon name=\"${menu.menu.icon}\" class=\"action-icon\" slot=\"trigger\"></nr-icon>\n </nr-dropdown>\n ` : nothing}\n </div>\n </div>\n ` : nothing}\n </li>\n `;\n }\n\n private _renderSubMenu(menu: IMenu, path: number[]): any {\n const pathKey = path.join('-');\n const isOpen = this.stateController.isSubMenuOpen(path) || menu.opened;\n const isHovered = this.stateController.isSubMenuHovered(path);\n const isHighlighted = this.stateController.isSubMenuHighlighted(path);\n const isSelected = menu.selected;\n \n return html`\n <ul \n class=\"sub-menu ${isHighlighted ? 'highlighted' : ''} ${menu.disabled ? 'disabled' : ''} ${isSelected ? 'selected' : ''}\"\n data-path=${pathKey}\n tabindex=\"0\"\n @mouseenter=${() => this._handleSubMenuMouseEnter(path)}\n @mouseleave=${() => this._handleSubMenuMouseLeave(path)}\n @click=${!menu.disabled ? (e: Event) => {\n // Handle keyboard activation on the ul element\n const target = e.target as HTMLElement;\n const mouseEvent = e as MouseEvent;\n // If click is on the ul itself (not children) and it's keyboard-generated\n if (target.classList.contains('sub-menu') && mouseEvent.detail === 0) {\n e.stopPropagation(); // Prevent bubbling to parent submenus\n this.stateController.toggleSubMenu(path);\n this.requestUpdate();\n }\n } : nothing}>\n <div \n class=\"sub-menu-header\"\n @mousedown=${!menu.disabled ? (e: Event) => this._handleSubMenuClick(path, menu.text, e) : nothing}\n @click=${!menu.disabled ? (e: Event) => this._handleSubMenuClick(path, menu.text, e) : nothing}>\n ${menu.icon ? html`<nr-icon class=\"text-icon\" name=\"${menu.icon}\"></nr-icon>` : nothing}\n <span>${menu.text}</span>\n <div class=\"icons-container\">\n ${menu.status?.icon ? html`\n <nr-icon name=${menu.status.icon} class=\"status-icon\"></nr-icon>\n ` : nothing}\n ${(isHighlighted || isHovered) && menu.menu?.actions ? html`\n <nr-dropdown \n .items=${this._convertActionsToDropdownItems(menu.menu.actions)} \n trigger=\"click\" \n placement=\"bottom-end\"\n @nr-dropdown-item-click=${(e: CustomEvent) => this._handleActionClick(path, e)}>\n <nr-icon name=\"${menu.menu.icon}\" class=\"action-icon\" slot=\"trigger\"></nr-icon>\n </nr-dropdown>\n ` : nothing}\n ${menu.children && menu.children.length ? html`\n <nr-icon \n id=\"toggle-icon\" \n name=\"${isOpen ? 'angle-up' : 'angle-down'}\" \n @mousedown=${!menu.disabled ? (e: Event) => this._toggleSubMenu(path, e) : nothing}>\n </nr-icon>\n ` : nothing}\n </div>\n </div>\n <div class=\"sub-menu-children\" style=\"display: ${isOpen ? 'block' : 'none'}\">\n ${menu.children ? this._renderMenuItems(menu.children, path) : nothing}\n </div>\n </ul>\n `;\n }\n\n private _renderMenuItems(items: IMenu[], parentPath: number[] = []): any {\n return items.map((menu, index) => {\n const currentPath = [...parentPath, index];\n \n if (menu.children) {\n return this._renderSubMenu(menu, currentPath);\n } else {\n return this._renderMenuLink(menu, currentPath);\n }\n });\n }\n\n override render() {\n this._linkIndex = 0;\n return html`\n <ul class=\"menu-root menu--${this.size}\">\n ${this._renderMenuItems(this.items)}\n </ul>\n `;\n }\n}\n"]}
|