@duskmoon-dev/el-menu 0.4.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/dist/cjs/index.js +510 -0
- package/dist/cjs/index.js.map +11 -0
- package/dist/cjs/register.js +513 -0
- package/dist/cjs/register.js.map +12 -0
- package/dist/esm/index.js +478 -0
- package/dist/esm/index.js.map +11 -0
- package/dist/esm/register.js +476 -0
- package/dist/esm/register.js.map +12 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types/el-dm-menu.d.ts +101 -0
- package/dist/types/el-dm-menu.d.ts.map +1 -0
- package/dist/types/index.d.ts +19 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/register.d.ts +2 -0
- package/dist/types/register.d.ts.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
6
|
+
var __toCommonJS = (from) => {
|
|
7
|
+
var entry = __moduleCache.get(from), desc;
|
|
8
|
+
if (entry)
|
|
9
|
+
return entry;
|
|
10
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function")
|
|
12
|
+
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
13
|
+
get: () => from[key],
|
|
14
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
+
}));
|
|
16
|
+
__moduleCache.set(from, entry);
|
|
17
|
+
return entry;
|
|
18
|
+
};
|
|
19
|
+
var __export = (target, all) => {
|
|
20
|
+
for (var name in all)
|
|
21
|
+
__defProp(target, name, {
|
|
22
|
+
get: all[name],
|
|
23
|
+
enumerable: true,
|
|
24
|
+
configurable: true,
|
|
25
|
+
set: (newValue) => all[name] = () => newValue
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// src/index.ts
|
|
30
|
+
var exports_src = {};
|
|
31
|
+
__export(exports_src, {
|
|
32
|
+
register: () => register,
|
|
33
|
+
ElDmMenuItem: () => ElDmMenuItem,
|
|
34
|
+
ElDmMenu: () => ElDmMenu
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(exports_src);
|
|
37
|
+
|
|
38
|
+
// src/el-dm-menu.ts
|
|
39
|
+
var import_el_core = require("@duskmoon-dev/el-core");
|
|
40
|
+
var menuStyles = import_el_core.css`
|
|
41
|
+
:host {
|
|
42
|
+
display: inline-block;
|
|
43
|
+
position: relative;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
:host([hidden]) {
|
|
47
|
+
display: none !important;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.menu-container {
|
|
51
|
+
position: absolute;
|
|
52
|
+
z-index: 1000;
|
|
53
|
+
min-width: 160px;
|
|
54
|
+
max-width: 320px;
|
|
55
|
+
background-color: var(--color-surface, #ffffff);
|
|
56
|
+
border: 1px solid var(--color-outline-variant, #e0e0e0);
|
|
57
|
+
border-radius: 0.5rem;
|
|
58
|
+
box-shadow:
|
|
59
|
+
0 4px 6px -1px rgba(0, 0, 0, 0.1),
|
|
60
|
+
0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
|
61
|
+
padding: 0.25rem 0;
|
|
62
|
+
opacity: 0;
|
|
63
|
+
visibility: hidden;
|
|
64
|
+
transform: scale(0.95);
|
|
65
|
+
transform-origin: top left;
|
|
66
|
+
transition:
|
|
67
|
+
opacity 150ms ease,
|
|
68
|
+
visibility 150ms ease,
|
|
69
|
+
transform 150ms ease;
|
|
70
|
+
font-family: inherit;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.menu-container.visible {
|
|
74
|
+
opacity: 1;
|
|
75
|
+
visibility: visible;
|
|
76
|
+
transform: scale(1);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* Placement styles */
|
|
80
|
+
.placement-bottom,
|
|
81
|
+
.placement-bottom-start,
|
|
82
|
+
.placement-bottom-end {
|
|
83
|
+
top: 100%;
|
|
84
|
+
margin-top: 0.25rem;
|
|
85
|
+
transform-origin: top;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.placement-bottom {
|
|
89
|
+
left: 50%;
|
|
90
|
+
transform: translateX(-50%) scale(0.95);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.placement-bottom.visible {
|
|
94
|
+
transform: translateX(-50%) scale(1);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.placement-bottom-start {
|
|
98
|
+
left: 0;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.placement-bottom-end {
|
|
102
|
+
right: 0;
|
|
103
|
+
left: auto;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.placement-top,
|
|
107
|
+
.placement-top-start,
|
|
108
|
+
.placement-top-end {
|
|
109
|
+
bottom: 100%;
|
|
110
|
+
margin-bottom: 0.25rem;
|
|
111
|
+
transform-origin: bottom;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.placement-top {
|
|
115
|
+
left: 50%;
|
|
116
|
+
transform: translateX(-50%) scale(0.95);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.placement-top.visible {
|
|
120
|
+
transform: translateX(-50%) scale(1);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.placement-top-start {
|
|
124
|
+
left: 0;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.placement-top-end {
|
|
128
|
+
right: 0;
|
|
129
|
+
left: auto;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.placement-left {
|
|
133
|
+
right: 100%;
|
|
134
|
+
top: 0;
|
|
135
|
+
margin-right: 0.25rem;
|
|
136
|
+
transform-origin: right;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.placement-right {
|
|
140
|
+
left: 100%;
|
|
141
|
+
top: 0;
|
|
142
|
+
margin-left: 0.25rem;
|
|
143
|
+
transform-origin: left;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.items-wrapper {
|
|
147
|
+
display: flex;
|
|
148
|
+
flex-direction: column;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
::slotted(el-dm-menu-item) {
|
|
152
|
+
display: block;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
::slotted([role='separator']) {
|
|
156
|
+
height: 1px;
|
|
157
|
+
background-color: var(--color-outline-variant, #e0e0e0);
|
|
158
|
+
margin: 0.25rem 0;
|
|
159
|
+
}
|
|
160
|
+
`;
|
|
161
|
+
|
|
162
|
+
class ElDmMenu extends import_el_core.BaseElement {
|
|
163
|
+
static properties = {
|
|
164
|
+
open: { type: Boolean, reflect: true, default: false },
|
|
165
|
+
anchor: { type: String, reflect: true },
|
|
166
|
+
placement: { type: String, reflect: true, default: "bottom-start" }
|
|
167
|
+
};
|
|
168
|
+
_anchorElement = null;
|
|
169
|
+
_focusedIndex = -1;
|
|
170
|
+
_boundHandleDocumentClick;
|
|
171
|
+
_boundHandleKeydown;
|
|
172
|
+
constructor() {
|
|
173
|
+
super();
|
|
174
|
+
this.attachStyles(menuStyles);
|
|
175
|
+
this._boundHandleDocumentClick = this._handleDocumentClick.bind(this);
|
|
176
|
+
this._boundHandleKeydown = this._handleKeydown.bind(this);
|
|
177
|
+
}
|
|
178
|
+
connectedCallback() {
|
|
179
|
+
super.connectedCallback();
|
|
180
|
+
this._setupAnchor();
|
|
181
|
+
}
|
|
182
|
+
disconnectedCallback() {
|
|
183
|
+
super.disconnectedCallback?.();
|
|
184
|
+
this._removeGlobalListeners();
|
|
185
|
+
}
|
|
186
|
+
_setupAnchor() {
|
|
187
|
+
if (this.anchor) {
|
|
188
|
+
this._anchorElement = document.querySelector(this.anchor) || this.closest(this.anchor) || document.getElementById(this.anchor);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
_addGlobalListeners() {
|
|
192
|
+
document.addEventListener("click", this._boundHandleDocumentClick);
|
|
193
|
+
document.addEventListener("keydown", this._boundHandleKeydown);
|
|
194
|
+
}
|
|
195
|
+
_removeGlobalListeners() {
|
|
196
|
+
document.removeEventListener("click", this._boundHandleDocumentClick);
|
|
197
|
+
document.removeEventListener("keydown", this._boundHandleKeydown);
|
|
198
|
+
}
|
|
199
|
+
_handleDocumentClick(event) {
|
|
200
|
+
const target = event.target;
|
|
201
|
+
if (!this.contains(target) && !this._anchorElement?.contains(target)) {
|
|
202
|
+
this.hide();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
_handleKeydown(event) {
|
|
206
|
+
if (!this.open)
|
|
207
|
+
return;
|
|
208
|
+
const items = this._getMenuItems();
|
|
209
|
+
if (items.length === 0)
|
|
210
|
+
return;
|
|
211
|
+
switch (event.key) {
|
|
212
|
+
case "Escape":
|
|
213
|
+
event.preventDefault();
|
|
214
|
+
this.hide();
|
|
215
|
+
this._anchorElement?.focus();
|
|
216
|
+
break;
|
|
217
|
+
case "ArrowDown":
|
|
218
|
+
event.preventDefault();
|
|
219
|
+
this._focusItem(this._getNextFocusableIndex(this._focusedIndex, 1, items));
|
|
220
|
+
break;
|
|
221
|
+
case "ArrowUp":
|
|
222
|
+
event.preventDefault();
|
|
223
|
+
this._focusItem(this._getNextFocusableIndex(this._focusedIndex, -1, items));
|
|
224
|
+
break;
|
|
225
|
+
case "Home":
|
|
226
|
+
event.preventDefault();
|
|
227
|
+
this._focusItem(this._getNextFocusableIndex(-1, 1, items));
|
|
228
|
+
break;
|
|
229
|
+
case "End":
|
|
230
|
+
event.preventDefault();
|
|
231
|
+
this._focusItem(this._getNextFocusableIndex(items.length, -1, items));
|
|
232
|
+
break;
|
|
233
|
+
case "Enter":
|
|
234
|
+
case " ":
|
|
235
|
+
event.preventDefault();
|
|
236
|
+
if (this._focusedIndex >= 0 && this._focusedIndex < items.length) {
|
|
237
|
+
const item = items[this._focusedIndex];
|
|
238
|
+
if (!item.disabled) {
|
|
239
|
+
this._selectItem(item);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
break;
|
|
243
|
+
case "Tab":
|
|
244
|
+
this.hide();
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
_getMenuItems() {
|
|
249
|
+
const slot = this.shadowRoot?.querySelector("slot");
|
|
250
|
+
if (!slot)
|
|
251
|
+
return [];
|
|
252
|
+
return slot.assignedElements().filter((el) => el.tagName === "EL-DM-MENU-ITEM" && !el.hasAttribute("hidden"));
|
|
253
|
+
}
|
|
254
|
+
_getNextFocusableIndex(currentIndex, direction, items) {
|
|
255
|
+
let nextIndex = currentIndex + direction;
|
|
256
|
+
while (nextIndex >= 0 && nextIndex < items.length) {
|
|
257
|
+
const item = items[nextIndex];
|
|
258
|
+
if (!item.disabled) {
|
|
259
|
+
return nextIndex;
|
|
260
|
+
}
|
|
261
|
+
nextIndex += direction;
|
|
262
|
+
}
|
|
263
|
+
if (direction > 0) {
|
|
264
|
+
return this._getNextFocusableIndex(-1, 1, items);
|
|
265
|
+
} else {
|
|
266
|
+
return this._getNextFocusableIndex(items.length, -1, items);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
_focusItem(index) {
|
|
270
|
+
const items = this._getMenuItems();
|
|
271
|
+
if (index < 0 || index >= items.length)
|
|
272
|
+
return;
|
|
273
|
+
if (this._focusedIndex >= 0 && this._focusedIndex < items.length) {
|
|
274
|
+
items[this._focusedIndex].focused = false;
|
|
275
|
+
}
|
|
276
|
+
this._focusedIndex = index;
|
|
277
|
+
const item = items[index];
|
|
278
|
+
item.focused = true;
|
|
279
|
+
item.focus();
|
|
280
|
+
}
|
|
281
|
+
_selectItem(item) {
|
|
282
|
+
this.emit("select", { value: item.value || item.textContent?.trim() });
|
|
283
|
+
this.hide();
|
|
284
|
+
}
|
|
285
|
+
_updatePosition() {
|
|
286
|
+
const menuContainer = this.shadowRoot?.querySelector(".menu-container");
|
|
287
|
+
if (!menuContainer)
|
|
288
|
+
return;
|
|
289
|
+
requestAnimationFrame(() => {
|
|
290
|
+
const rect = menuContainer.getBoundingClientRect();
|
|
291
|
+
const viewportHeight = window.innerHeight;
|
|
292
|
+
const viewportWidth = window.innerWidth;
|
|
293
|
+
let finalPlacement = this.placement;
|
|
294
|
+
if (finalPlacement.startsWith("bottom") && rect.bottom > viewportHeight) {
|
|
295
|
+
finalPlacement = finalPlacement.replace("bottom", "top");
|
|
296
|
+
} else if (finalPlacement.startsWith("top") && rect.top < 0) {
|
|
297
|
+
finalPlacement = finalPlacement.replace("top", "bottom");
|
|
298
|
+
}
|
|
299
|
+
if (finalPlacement === "right" && rect.right > viewportWidth) {
|
|
300
|
+
finalPlacement = "left";
|
|
301
|
+
} else if (finalPlacement === "left" && rect.left < 0) {
|
|
302
|
+
finalPlacement = "right";
|
|
303
|
+
}
|
|
304
|
+
if (finalPlacement !== this.placement) {
|
|
305
|
+
menuContainer.className = `menu-container placement-${finalPlacement}${this.open ? " visible" : ""}`;
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
show() {
|
|
310
|
+
if (this.open)
|
|
311
|
+
return;
|
|
312
|
+
this.open = true;
|
|
313
|
+
this._focusedIndex = -1;
|
|
314
|
+
this._addGlobalListeners();
|
|
315
|
+
this._updatePosition();
|
|
316
|
+
this.emit("open");
|
|
317
|
+
requestAnimationFrame(() => {
|
|
318
|
+
const items = this._getMenuItems();
|
|
319
|
+
if (items.length > 0) {
|
|
320
|
+
this._focusItem(this._getNextFocusableIndex(-1, 1, items));
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
hide() {
|
|
325
|
+
if (!this.open)
|
|
326
|
+
return;
|
|
327
|
+
this.open = false;
|
|
328
|
+
this._focusedIndex = -1;
|
|
329
|
+
this._removeGlobalListeners();
|
|
330
|
+
this.emit("close");
|
|
331
|
+
const items = this._getMenuItems();
|
|
332
|
+
items.forEach((item) => {
|
|
333
|
+
item.focused = false;
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
toggle() {
|
|
337
|
+
if (this.open) {
|
|
338
|
+
this.hide();
|
|
339
|
+
} else {
|
|
340
|
+
this.show();
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
update() {
|
|
344
|
+
super.update?.();
|
|
345
|
+
const menuContainer = this.shadowRoot?.querySelector(".menu-container");
|
|
346
|
+
if (menuContainer) {
|
|
347
|
+
menuContainer.classList.toggle("visible", this.open);
|
|
348
|
+
if (this.open) {
|
|
349
|
+
this._updatePosition();
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
render() {
|
|
354
|
+
const placementClass = `placement-${this.placement || "bottom-start"}`;
|
|
355
|
+
return `
|
|
356
|
+
<slot name="trigger"></slot>
|
|
357
|
+
<div
|
|
358
|
+
class="menu-container ${placementClass}${this.open ? " visible" : ""}"
|
|
359
|
+
part="menu"
|
|
360
|
+
role="menu"
|
|
361
|
+
aria-hidden="${!this.open}"
|
|
362
|
+
>
|
|
363
|
+
<div class="items-wrapper" part="items">
|
|
364
|
+
<slot></slot>
|
|
365
|
+
</div>
|
|
366
|
+
</div>
|
|
367
|
+
`;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
var menuItemStyles = import_el_core.css`
|
|
371
|
+
:host {
|
|
372
|
+
display: block;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
:host([hidden]) {
|
|
376
|
+
display: none !important;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.menu-item {
|
|
380
|
+
display: flex;
|
|
381
|
+
align-items: center;
|
|
382
|
+
gap: 0.75rem;
|
|
383
|
+
padding: 0.5rem 1rem;
|
|
384
|
+
cursor: pointer;
|
|
385
|
+
color: var(--color-on-surface, #1f1f1f);
|
|
386
|
+
background-color: transparent;
|
|
387
|
+
border: none;
|
|
388
|
+
width: 100%;
|
|
389
|
+
text-align: left;
|
|
390
|
+
font-size: 0.875rem;
|
|
391
|
+
line-height: 1.25rem;
|
|
392
|
+
font-family: inherit;
|
|
393
|
+
transition:
|
|
394
|
+
background-color 150ms ease,
|
|
395
|
+
color 150ms ease;
|
|
396
|
+
outline: none;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
.menu-item:hover:not(.disabled) {
|
|
400
|
+
background-color: var(--color-surface-container-highest, #f5f5f5);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.menu-item:focus:not(.disabled),
|
|
404
|
+
.menu-item.focused:not(.disabled) {
|
|
405
|
+
background-color: var(--color-surface-container-highest, #f5f5f5);
|
|
406
|
+
outline: 2px solid var(--color-primary, #6750a4);
|
|
407
|
+
outline-offset: -2px;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
.menu-item.disabled {
|
|
411
|
+
cursor: not-allowed;
|
|
412
|
+
opacity: 0.5;
|
|
413
|
+
color: var(--color-on-surface-variant, #49454f);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
.icon-wrapper {
|
|
417
|
+
display: flex;
|
|
418
|
+
align-items: center;
|
|
419
|
+
justify-content: center;
|
|
420
|
+
width: 1.25rem;
|
|
421
|
+
height: 1.25rem;
|
|
422
|
+
flex-shrink: 0;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
.icon-wrapper:empty {
|
|
426
|
+
display: none;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
.content-wrapper {
|
|
430
|
+
flex: 1;
|
|
431
|
+
min-width: 0;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
::slotted(svg),
|
|
435
|
+
::slotted(img) {
|
|
436
|
+
width: 1.25rem;
|
|
437
|
+
height: 1.25rem;
|
|
438
|
+
}
|
|
439
|
+
`;
|
|
440
|
+
|
|
441
|
+
class ElDmMenuItem extends import_el_core.BaseElement {
|
|
442
|
+
static properties = {
|
|
443
|
+
value: { type: String, reflect: true },
|
|
444
|
+
disabled: { type: Boolean, reflect: true, default: false },
|
|
445
|
+
focused: { type: Boolean, reflect: true, default: false }
|
|
446
|
+
};
|
|
447
|
+
constructor() {
|
|
448
|
+
super();
|
|
449
|
+
this.attachStyles(menuItemStyles);
|
|
450
|
+
}
|
|
451
|
+
connectedCallback() {
|
|
452
|
+
super.connectedCallback();
|
|
453
|
+
this.setAttribute("role", "menuitem");
|
|
454
|
+
this.setAttribute("tabindex", "-1");
|
|
455
|
+
this.addEventListener("click", this._handleClick.bind(this));
|
|
456
|
+
}
|
|
457
|
+
_handleClick(event) {
|
|
458
|
+
if (this.disabled) {
|
|
459
|
+
event.preventDefault();
|
|
460
|
+
event.stopPropagation();
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
const menu = this.closest("el-dm-menu");
|
|
464
|
+
if (menu) {
|
|
465
|
+
menu.dispatchEvent(new CustomEvent("select", {
|
|
466
|
+
bubbles: true,
|
|
467
|
+
composed: true,
|
|
468
|
+
detail: { value: this.value || this.textContent?.trim() }
|
|
469
|
+
}));
|
|
470
|
+
menu.hide();
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
update() {
|
|
474
|
+
super.update?.();
|
|
475
|
+
this.setAttribute("aria-disabled", String(this.disabled));
|
|
476
|
+
const itemEl = this.shadowRoot?.querySelector(".menu-item");
|
|
477
|
+
if (itemEl) {
|
|
478
|
+
itemEl.classList.toggle("disabled", this.disabled);
|
|
479
|
+
itemEl.classList.toggle("focused", this.focused);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
render() {
|
|
483
|
+
return `
|
|
484
|
+
<div
|
|
485
|
+
class="menu-item${this.disabled ? " disabled" : ""}${this.focused ? " focused" : ""}"
|
|
486
|
+
part="item"
|
|
487
|
+
>
|
|
488
|
+
<span class="icon-wrapper" part="icon">
|
|
489
|
+
<slot name="icon"></slot>
|
|
490
|
+
</span>
|
|
491
|
+
<span class="content-wrapper" part="content">
|
|
492
|
+
<slot></slot>
|
|
493
|
+
</span>
|
|
494
|
+
</div>
|
|
495
|
+
`;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// src/index.ts
|
|
500
|
+
function register() {
|
|
501
|
+
if (!customElements.get("el-dm-menu")) {
|
|
502
|
+
customElements.define("el-dm-menu", ElDmMenu);
|
|
503
|
+
}
|
|
504
|
+
if (!customElements.get("el-dm-menu-item")) {
|
|
505
|
+
customElements.define("el-dm-menu-item", ElDmMenuItem);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
//# debugId=597792FA78F8BC4F64756E2164756E21
|
|
510
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/el-dm-menu.ts", "../../src/index.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * DuskMoon Menu Element\n *\n * A dropdown menu component with menu items supporting keyboard navigation.\n *\n * @element el-dm-menu\n *\n * @attr {boolean} open - Whether the menu is open\n * @attr {string} anchor - Element ref or CSS selector for the anchor element\n * @attr {string} placement - Menu placement: top, bottom, left, right, top-start, top-end, bottom-start, bottom-end\n *\n * @slot - Default slot for menu items\n *\n * @csspart menu - The menu container\n * @csspart items - The menu items wrapper\n *\n * @fires open - Fired when the menu opens\n * @fires close - Fired when the menu closes\n * @fires select - Fired when a menu item is selected (detail: { value: string })\n */\n\nimport { BaseElement, css } from '@duskmoon-dev/el-core';\n\nexport type MenuPlacement =\n | 'top'\n | 'bottom'\n | 'left'\n | 'right'\n | 'top-start'\n | 'top-end'\n | 'bottom-start'\n | 'bottom-end';\n\nconst menuStyles = css`\n :host {\n display: inline-block;\n position: relative;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n\n .menu-container {\n position: absolute;\n z-index: 1000;\n min-width: 160px;\n max-width: 320px;\n background-color: var(--color-surface, #ffffff);\n border: 1px solid var(--color-outline-variant, #e0e0e0);\n border-radius: 0.5rem;\n box-shadow:\n 0 4px 6px -1px rgba(0, 0, 0, 0.1),\n 0 2px 4px -1px rgba(0, 0, 0, 0.06);\n padding: 0.25rem 0;\n opacity: 0;\n visibility: hidden;\n transform: scale(0.95);\n transform-origin: top left;\n transition:\n opacity 150ms ease,\n visibility 150ms ease,\n transform 150ms ease;\n font-family: inherit;\n }\n\n .menu-container.visible {\n opacity: 1;\n visibility: visible;\n transform: scale(1);\n }\n\n /* Placement styles */\n .placement-bottom,\n .placement-bottom-start,\n .placement-bottom-end {\n top: 100%;\n margin-top: 0.25rem;\n transform-origin: top;\n }\n\n .placement-bottom {\n left: 50%;\n transform: translateX(-50%) scale(0.95);\n }\n\n .placement-bottom.visible {\n transform: translateX(-50%) scale(1);\n }\n\n .placement-bottom-start {\n left: 0;\n }\n\n .placement-bottom-end {\n right: 0;\n left: auto;\n }\n\n .placement-top,\n .placement-top-start,\n .placement-top-end {\n bottom: 100%;\n margin-bottom: 0.25rem;\n transform-origin: bottom;\n }\n\n .placement-top {\n left: 50%;\n transform: translateX(-50%) scale(0.95);\n }\n\n .placement-top.visible {\n transform: translateX(-50%) scale(1);\n }\n\n .placement-top-start {\n left: 0;\n }\n\n .placement-top-end {\n right: 0;\n left: auto;\n }\n\n .placement-left {\n right: 100%;\n top: 0;\n margin-right: 0.25rem;\n transform-origin: right;\n }\n\n .placement-right {\n left: 100%;\n top: 0;\n margin-left: 0.25rem;\n transform-origin: left;\n }\n\n .items-wrapper {\n display: flex;\n flex-direction: column;\n }\n\n ::slotted(el-dm-menu-item) {\n display: block;\n }\n\n ::slotted([role='separator']) {\n height: 1px;\n background-color: var(--color-outline-variant, #e0e0e0);\n margin: 0.25rem 0;\n }\n`;\n\nexport class ElDmMenu extends BaseElement {\n static properties = {\n open: { type: Boolean, reflect: true, default: false },\n anchor: { type: String, reflect: true },\n placement: { type: String, reflect: true, default: 'bottom-start' },\n };\n\n declare open: boolean;\n declare anchor: string;\n declare placement: MenuPlacement;\n\n private _anchorElement: HTMLElement | null = null;\n private _focusedIndex = -1;\n private _boundHandleDocumentClick: (e: MouseEvent) => void;\n private _boundHandleKeydown: (e: KeyboardEvent) => void;\n\n constructor() {\n super();\n this.attachStyles(menuStyles);\n this._boundHandleDocumentClick = this._handleDocumentClick.bind(this);\n this._boundHandleKeydown = this._handleKeydown.bind(this);\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n this._setupAnchor();\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback?.();\n this._removeGlobalListeners();\n }\n\n private _setupAnchor(): void {\n if (this.anchor) {\n this._anchorElement =\n document.querySelector(this.anchor) ||\n this.closest(this.anchor) ||\n document.getElementById(this.anchor);\n }\n }\n\n private _addGlobalListeners(): void {\n document.addEventListener('click', this._boundHandleDocumentClick);\n document.addEventListener('keydown', this._boundHandleKeydown);\n }\n\n private _removeGlobalListeners(): void {\n document.removeEventListener('click', this._boundHandleDocumentClick);\n document.removeEventListener('keydown', this._boundHandleKeydown);\n }\n\n private _handleDocumentClick(event: MouseEvent): void {\n const target = event.target as Node;\n if (!this.contains(target) && !this._anchorElement?.contains(target)) {\n this.hide();\n }\n }\n\n private _handleKeydown(event: KeyboardEvent): void {\n if (!this.open) return;\n\n const items = this._getMenuItems();\n if (items.length === 0) return;\n\n switch (event.key) {\n case 'Escape':\n event.preventDefault();\n this.hide();\n this._anchorElement?.focus();\n break;\n\n case 'ArrowDown':\n event.preventDefault();\n this._focusItem(this._getNextFocusableIndex(this._focusedIndex, 1, items));\n break;\n\n case 'ArrowUp':\n event.preventDefault();\n this._focusItem(this._getNextFocusableIndex(this._focusedIndex, -1, items));\n break;\n\n case 'Home':\n event.preventDefault();\n this._focusItem(this._getNextFocusableIndex(-1, 1, items));\n break;\n\n case 'End':\n event.preventDefault();\n this._focusItem(this._getNextFocusableIndex(items.length, -1, items));\n break;\n\n case 'Enter':\n case ' ':\n event.preventDefault();\n if (this._focusedIndex >= 0 && this._focusedIndex < items.length) {\n const item = items[this._focusedIndex] as ElDmMenuItem;\n if (!item.disabled) {\n this._selectItem(item);\n }\n }\n break;\n\n case 'Tab':\n this.hide();\n break;\n }\n }\n\n private _getMenuItems(): Element[] {\n const slot = this.shadowRoot?.querySelector('slot');\n if (!slot) return [];\n return slot\n .assignedElements()\n .filter((el) => el.tagName === 'EL-DM-MENU-ITEM' && !el.hasAttribute('hidden'));\n }\n\n private _getNextFocusableIndex(\n currentIndex: number,\n direction: number,\n items: Element[],\n ): number {\n let nextIndex = currentIndex + direction;\n\n while (nextIndex >= 0 && nextIndex < items.length) {\n const item = items[nextIndex] as ElDmMenuItem;\n if (!item.disabled) {\n return nextIndex;\n }\n nextIndex += direction;\n }\n\n // Wrap around\n if (direction > 0) {\n return this._getNextFocusableIndex(-1, 1, items);\n } else {\n return this._getNextFocusableIndex(items.length, -1, items);\n }\n }\n\n private _focusItem(index: number): void {\n const items = this._getMenuItems();\n if (index < 0 || index >= items.length) return;\n\n // Remove focus from previous item\n if (this._focusedIndex >= 0 && this._focusedIndex < items.length) {\n (items[this._focusedIndex] as ElDmMenuItem).focused = false;\n }\n\n // Focus new item\n this._focusedIndex = index;\n const item = items[index] as ElDmMenuItem;\n item.focused = true;\n item.focus();\n }\n\n private _selectItem(item: ElDmMenuItem): void {\n this.emit('select', { value: item.value || item.textContent?.trim() });\n this.hide();\n }\n\n private _updatePosition(): void {\n const menuContainer = this.shadowRoot?.querySelector('.menu-container') as HTMLElement;\n if (!menuContainer) return;\n\n // Check if menu would go off screen and flip if necessary\n requestAnimationFrame(() => {\n const rect = menuContainer.getBoundingClientRect();\n const viewportHeight = window.innerHeight;\n const viewportWidth = window.innerWidth;\n\n let finalPlacement = this.placement;\n\n // Flip vertical placement if needed\n if (finalPlacement.startsWith('bottom') && rect.bottom > viewportHeight) {\n finalPlacement = finalPlacement.replace('bottom', 'top') as MenuPlacement;\n } else if (finalPlacement.startsWith('top') && rect.top < 0) {\n finalPlacement = finalPlacement.replace('top', 'bottom') as MenuPlacement;\n }\n\n // Flip horizontal placement if needed\n if (finalPlacement === 'right' && rect.right > viewportWidth) {\n finalPlacement = 'left';\n } else if (finalPlacement === 'left' && rect.left < 0) {\n finalPlacement = 'right';\n }\n\n // Update class if flipped\n if (finalPlacement !== this.placement) {\n menuContainer.className = `menu-container placement-${finalPlacement}${this.open ? ' visible' : ''}`;\n }\n });\n }\n\n /**\n * Show the menu\n */\n show(): void {\n if (this.open) return;\n this.open = true;\n this._focusedIndex = -1;\n this._addGlobalListeners();\n this._updatePosition();\n this.emit('open');\n\n // Focus first item after menu opens\n requestAnimationFrame(() => {\n const items = this._getMenuItems();\n if (items.length > 0) {\n this._focusItem(this._getNextFocusableIndex(-1, 1, items));\n }\n });\n }\n\n /**\n * Hide the menu\n */\n hide(): void {\n if (!this.open) return;\n this.open = false;\n this._focusedIndex = -1;\n this._removeGlobalListeners();\n this.emit('close');\n\n // Clear focus from items\n const items = this._getMenuItems();\n items.forEach((item) => {\n (item as ElDmMenuItem).focused = false;\n });\n }\n\n /**\n * Toggle the menu open/closed\n */\n toggle(): void {\n if (this.open) {\n this.hide();\n } else {\n this.show();\n }\n }\n\n update(): void {\n super.update?.();\n const menuContainer = this.shadowRoot?.querySelector('.menu-container');\n if (menuContainer) {\n menuContainer.classList.toggle('visible', this.open);\n if (this.open) {\n this._updatePosition();\n }\n }\n }\n\n render(): string {\n const placementClass = `placement-${this.placement || 'bottom-start'}`;\n\n return `\n <slot name=\"trigger\"></slot>\n <div\n class=\"menu-container ${placementClass}${this.open ? ' visible' : ''}\"\n part=\"menu\"\n role=\"menu\"\n aria-hidden=\"${!this.open}\"\n >\n <div class=\"items-wrapper\" part=\"items\">\n <slot></slot>\n </div>\n </div>\n `;\n }\n}\n\n/**\n * DuskMoon Menu Item Element\n *\n * A menu item component for use within el-dm-menu.\n *\n * @element el-dm-menu-item\n *\n * @attr {string} value - The value associated with this item\n * @attr {boolean} disabled - Whether the item is disabled\n * @attr {boolean} focused - Whether the item is currently focused (internal)\n *\n * @slot - Default slot for item content\n * @slot icon - Slot for an icon before the content\n *\n * @csspart item - The menu item container\n * @csspart icon - The icon wrapper\n * @csspart content - The content wrapper\n */\n\nconst menuItemStyles = css`\n :host {\n display: block;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n\n .menu-item {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.5rem 1rem;\n cursor: pointer;\n color: var(--color-on-surface, #1f1f1f);\n background-color: transparent;\n border: none;\n width: 100%;\n text-align: left;\n font-size: 0.875rem;\n line-height: 1.25rem;\n font-family: inherit;\n transition:\n background-color 150ms ease,\n color 150ms ease;\n outline: none;\n }\n\n .menu-item:hover:not(.disabled) {\n background-color: var(--color-surface-container-highest, #f5f5f5);\n }\n\n .menu-item:focus:not(.disabled),\n .menu-item.focused:not(.disabled) {\n background-color: var(--color-surface-container-highest, #f5f5f5);\n outline: 2px solid var(--color-primary, #6750a4);\n outline-offset: -2px;\n }\n\n .menu-item.disabled {\n cursor: not-allowed;\n opacity: 0.5;\n color: var(--color-on-surface-variant, #49454f);\n }\n\n .icon-wrapper {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1.25rem;\n height: 1.25rem;\n flex-shrink: 0;\n }\n\n .icon-wrapper:empty {\n display: none;\n }\n\n .content-wrapper {\n flex: 1;\n min-width: 0;\n }\n\n ::slotted(svg),\n ::slotted(img) {\n width: 1.25rem;\n height: 1.25rem;\n }\n`;\n\nexport class ElDmMenuItem extends BaseElement {\n static properties = {\n value: { type: String, reflect: true },\n disabled: { type: Boolean, reflect: true, default: false },\n focused: { type: Boolean, reflect: true, default: false },\n };\n\n declare value: string;\n declare disabled: boolean;\n declare focused: boolean;\n\n constructor() {\n super();\n this.attachStyles(menuItemStyles);\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n this.setAttribute('role', 'menuitem');\n this.setAttribute('tabindex', '-1');\n this.addEventListener('click', this._handleClick.bind(this));\n }\n\n private _handleClick(event: MouseEvent): void {\n if (this.disabled) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n // Dispatch select event on parent menu\n const menu = this.closest('el-dm-menu') as ElDmMenu;\n if (menu) {\n menu.dispatchEvent(\n new CustomEvent('select', {\n bubbles: true,\n composed: true,\n detail: { value: this.value || this.textContent?.trim() },\n }),\n );\n menu.hide();\n }\n }\n\n update(): void {\n super.update?.();\n this.setAttribute('aria-disabled', String(this.disabled));\n\n const itemEl = this.shadowRoot?.querySelector('.menu-item');\n if (itemEl) {\n itemEl.classList.toggle('disabled', this.disabled);\n itemEl.classList.toggle('focused', this.focused);\n }\n }\n\n render(): string {\n return `\n <div\n class=\"menu-item${this.disabled ? ' disabled' : ''}${this.focused ? ' focused' : ''}\"\n part=\"item\"\n >\n <span class=\"icon-wrapper\" part=\"icon\">\n <slot name=\"icon\"></slot>\n </span>\n <span class=\"content-wrapper\" part=\"content\">\n <slot></slot>\n </span>\n </div>\n `;\n }\n}\n",
|
|
6
|
+
"/**\n * @duskmoon-dev/el-menu\n *\n * DuskMoon Menu custom elements\n */\n\nimport { ElDmMenu } from './el-dm-menu.js';\nimport { ElDmMenuItem } from './el-dm-menu.js';\n\nexport { ElDmMenu, ElDmMenuItem };\n\n/**\n * Register the el-dm-menu and el-dm-menu-item custom elements\n *\n * @example\n * ```ts\n * import { register } from '@duskmoon-dev/el-menu';\n * register();\n * ```\n */\nexport function register(): void {\n if (!customElements.get('el-dm-menu')) {\n customElements.define('el-dm-menu', ElDmMenu);\n }\n if (!customElements.get('el-dm-menu-item')) {\n customElements.define('el-dm-menu-item', ElDmMenuItem);\n }\n}\n"
|
|
7
|
+
],
|
|
8
|
+
"mappings": "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",
|
|
9
|
+
"debugId": "597792FA78F8BC4F64756E2164756E21",
|
|
10
|
+
"names": []
|
|
11
|
+
}
|