@ngrdt/menu 0.0.16 → 0.0.18
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/fesm2022/ngrdt-menu.mjs +324 -357
- package/fesm2022/ngrdt-menu.mjs.map +1 -1
- package/index.d.ts +335 -4
- package/package.json +1 -3
- package/esm2022/index.mjs +0 -5
- package/esm2022/lib/menu/rdt-menu.component.mjs +0 -93
- package/esm2022/lib/menu-bar/rdt-menu-bar.component.mjs +0 -58
- package/esm2022/lib/menu-base/rdt-menu-base.component.mjs +0 -458
- package/esm2022/lib/menu-overlay/rdt-menu-overlay.component.mjs +0 -597
- package/esm2022/lib/models.mjs +0 -15
- package/esm2022/lib/private-models.mjs +0 -73
- package/esm2022/lib/rdt-menu.module.mjs +0 -41
- package/esm2022/lib/utils.mjs +0 -79
- package/esm2022/ngrdt-menu.mjs +0 -5
- package/lib/menu/rdt-menu.component.d.ts +0 -23
- package/lib/menu-bar/rdt-menu-bar.component.d.ts +0 -18
- package/lib/menu-base/rdt-menu-base.component.d.ts +0 -103
- package/lib/menu-overlay/rdt-menu-overlay.component.d.ts +0 -85
- package/lib/models.d.ts +0 -35
- package/lib/private-models.d.ts +0 -53
- package/lib/rdt-menu.module.d.ts +0 -14
- package/lib/utils.d.ts +0 -36
package/fesm2022/ngrdt-menu.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, inject, ElementRef, DestroyRef, Renderer2, ChangeDetectorRef,
|
|
2
|
+
import { InjectionToken, inject, ElementRef, DestroyRef, Renderer2, ChangeDetectorRef, input, linkedSignal, computed, signal, untracked, effect, afterRenderEffect, afterNextRender, HostListener, ViewChild, ViewChildren, ChangeDetectionStrategy, Component, booleanAttribute, numberAttribute, EnvironmentInjector, Directive, ViewEncapsulation, QueryList, NgModule } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/common';
|
|
4
4
|
import { DOCUMENT, CommonModule } from '@angular/common';
|
|
5
|
-
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
5
|
+
import { takeUntilDestroyed, toSignal, toObservable } from '@angular/core/rxjs-interop';
|
|
6
6
|
import * as i2 from '@angular/router';
|
|
7
7
|
import { Router, RouterModule } from '@angular/router';
|
|
8
8
|
import * as i3 from '@ngrdt/router';
|
|
@@ -10,7 +10,7 @@ import { RdtRouterService, RdtAnyRouteActiveDirective } from '@ngrdt/router';
|
|
|
10
10
|
import * as i4 from '@ngrdt/shortcuts';
|
|
11
11
|
import { RdtShortcutService, RdtShortcut, RdtKeyListenerDirective } from '@ngrdt/shortcuts';
|
|
12
12
|
import { RdtStringUtils, KB_CODE, RdtObjectUtils } from '@ngrdt/utils';
|
|
13
|
-
import { delay, of, map, first,
|
|
13
|
+
import { delay, of, map, first, fromEvent, throttleTime, animationFrameScheduler, switchMap, withLatestFrom } from 'rxjs';
|
|
14
14
|
import { RDT_BUTTON_BASE_PROVIDER, RdtButtonOutletDirective } from '@ngrdt/button';
|
|
15
15
|
|
|
16
16
|
var RdtMenuShortcutMode;
|
|
@@ -195,24 +195,25 @@ class RdtMenuOverlayComponent {
|
|
|
195
195
|
children;
|
|
196
196
|
focusableElements;
|
|
197
197
|
menuItemContainer;
|
|
198
|
-
item;
|
|
199
|
-
level;
|
|
200
|
-
preferredHorizontalDir = DEFAULT_MENU_HORIZONTAL_DIR;
|
|
201
|
-
preferredVerticalDir = DEFAULT_MENU_VERTICAL_DIR;
|
|
202
|
-
|
|
203
|
-
|
|
198
|
+
item = input.required(...(ngDevMode ? [{ debugName: "item" }] : []));
|
|
199
|
+
level = input.required(...(ngDevMode ? [{ debugName: "level" }] : []));
|
|
200
|
+
preferredHorizontalDir = input(DEFAULT_MENU_HORIZONTAL_DIR, ...(ngDevMode ? [{ debugName: "preferredHorizontalDir" }] : []));
|
|
201
|
+
preferredVerticalDir = input(DEFAULT_MENU_VERTICAL_DIR, ...(ngDevMode ? [{ debugName: "preferredVerticalDir" }] : []));
|
|
202
|
+
expandedInput = input(false, ...(ngDevMode ? [{ debugName: "expandedInput", alias: 'expanded' }] : [{ alias: 'expanded' }]));
|
|
203
|
+
expanded = linkedSignal(() => this.expandedInput());
|
|
204
|
+
autofocusItemInput = input(null, ...(ngDevMode ? [{ debugName: "autofocusItemInput", alias: 'autofocusItem' }] : [{
|
|
205
|
+
alias: 'autofocusItem',
|
|
206
|
+
}]));
|
|
207
|
+
autofocusItem = linkedSignal(() => this.autofocusItemInput());
|
|
204
208
|
// Element used to relatively position menu,
|
|
205
209
|
// typically parent element.
|
|
206
210
|
// If not specified, parent element is used.
|
|
207
|
-
anchorElement
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
}
|
|
213
|
-
get isRootLevel() {
|
|
214
|
-
return this.level === 0;
|
|
215
|
-
}
|
|
211
|
+
anchorElementInput = input(null, ...(ngDevMode ? [{ debugName: "anchorElementInput", alias: 'anchorElement' }] : [{
|
|
212
|
+
alias: 'anchorElement',
|
|
213
|
+
}]));
|
|
214
|
+
anchorElement = computed(() => this.anchorElementInput() ?? this.elRef.nativeElement.parentElement, ...(ngDevMode ? [{ debugName: "anchorElement" }] : []));
|
|
215
|
+
zIndex = computed(() => this.level() + 10, ...(ngDevMode ? [{ debugName: "zIndex" }] : []));
|
|
216
|
+
isRootLevel = computed(() => this.level() === 0, ...(ngDevMode ? [{ debugName: "isRootLevel" }] : []));
|
|
216
217
|
// Bounding box of this excluding any extra offset.
|
|
217
218
|
_box;
|
|
218
219
|
get box() {
|
|
@@ -221,72 +222,69 @@ class RdtMenuOverlayComponent {
|
|
|
221
222
|
// Bounding box of parent element.
|
|
222
223
|
_anchorBox;
|
|
223
224
|
_containerPadding = { top: 0, bottom: 0 };
|
|
224
|
-
// Recalculate child components only after they are initialized.
|
|
225
|
-
_viewWasInit = false;
|
|
226
225
|
// Currently applied vertical and horizontal directions.
|
|
227
|
-
verticalDir = null
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
226
|
+
verticalDir = signal(null, ...(ngDevMode ? [{ debugName: "verticalDir", equal: areVertDirsEqual }] : [{
|
|
227
|
+
equal: areVertDirsEqual,
|
|
228
|
+
}]));
|
|
229
|
+
horizontalDir = signal(null, ...(ngDevMode ? [{ debugName: "horizontalDir", equal: areHorDirsEqual }] : [{
|
|
230
|
+
equal: areHorDirsEqual,
|
|
231
|
+
}]));
|
|
232
|
+
expandedChild = signal(null, ...(ngDevMode ? [{ debugName: "expandedChild" }] : []));
|
|
233
|
+
autofocusSubmenuItem = signal(null, ...(ngDevMode ? [{ debugName: "autofocusSubmenuItem" }] : []));
|
|
231
234
|
keyActions = {
|
|
232
235
|
[KB_CODE.ARROW.UP]: (index) => this.focusPrevItem(index),
|
|
233
236
|
[KB_CODE.ARROW.DOWN]: (index) => this.focusNextItem(index),
|
|
234
237
|
[KB_CODE.ARROW.RIGHT]: (index) => this.openSubmenu(index, 'first', RdtMenuExpandSource.Shortcut),
|
|
235
238
|
[KB_CODE.ARROW.LEFT]: () => this.closeSelf(),
|
|
236
239
|
[KB_CODE.HOME]: () => this.focusItem(0),
|
|
237
|
-
[KB_CODE.END]: () => this.focusItem(this.item.items.length - 1),
|
|
240
|
+
[KB_CODE.END]: () => this.focusItem(untracked(this.item).items.length - 1),
|
|
238
241
|
[KB_CODE.ESCAPE]: () => this.closeSelf(),
|
|
239
242
|
[KB_CODE.ENTER]: (index) => this.invokeItemClickByIndex(index),
|
|
240
243
|
[KB_CODE.SPACEBAR]: (index) => this.invokeItemClickByIndex(index),
|
|
241
244
|
};
|
|
242
245
|
get selfExpandSrc() {
|
|
243
|
-
if (this.expanded) {
|
|
246
|
+
if (this.expanded()) {
|
|
244
247
|
if (this.parentMenu) {
|
|
245
|
-
return this.parentMenu.expandedChild?.src;
|
|
248
|
+
return this.parentMenu.expandedChild()?.src;
|
|
246
249
|
}
|
|
247
250
|
else {
|
|
248
|
-
return this.topLevelMenu.expandedChild?.src;
|
|
251
|
+
return this.topLevelMenu.expandedChild()?.src;
|
|
249
252
|
}
|
|
250
253
|
}
|
|
251
254
|
return undefined;
|
|
252
255
|
}
|
|
253
|
-
|
|
254
|
-
this.
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
if (
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
case 'first':
|
|
278
|
-
this.focusItem(0, true);
|
|
279
|
-
break;
|
|
280
|
-
case 'last':
|
|
281
|
-
this.focusItem(this.item.items.length - 1, true);
|
|
282
|
-
}
|
|
283
|
-
});
|
|
256
|
+
recalcEffect = effect(() => {
|
|
257
|
+
this.recalculatePosition(this.preferredHorizontalDir(), this.preferredVerticalDir());
|
|
258
|
+
}, ...(ngDevMode ? [{ debugName: "recalcEffect" }] : []));
|
|
259
|
+
expandedEffect = effect(() => {
|
|
260
|
+
if (!this.expanded()) {
|
|
261
|
+
this.expandedChild.set(null);
|
|
262
|
+
}
|
|
263
|
+
}, ...(ngDevMode ? [{ debugName: "expandedEffect" }] : []));
|
|
264
|
+
expandedFocusEffect = afterRenderEffect(() => {
|
|
265
|
+
const rootItem = untracked(this.item);
|
|
266
|
+
this.expandedInput();
|
|
267
|
+
const expanded = untracked(this.expanded);
|
|
268
|
+
const autofocusItem = untracked(this.autofocusItem);
|
|
269
|
+
if (expanded) {
|
|
270
|
+
switch (autofocusItem) {
|
|
271
|
+
case null:
|
|
272
|
+
this.focusItem(0, false);
|
|
273
|
+
break;
|
|
274
|
+
case 'first':
|
|
275
|
+
this.focusItem(0, true);
|
|
276
|
+
break;
|
|
277
|
+
case 'last':
|
|
278
|
+
this.focusItem(rootItem.items.length - 1, true);
|
|
279
|
+
}
|
|
284
280
|
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
281
|
+
});
|
|
282
|
+
constructor() {
|
|
283
|
+
afterNextRender(() => {
|
|
284
|
+
this.measureContainerPadding();
|
|
285
|
+
this.recalculatePosition(this.preferredHorizontalDir(), this.preferredVerticalDir());
|
|
286
|
+
this.listenTabKeyPress();
|
|
287
|
+
});
|
|
290
288
|
}
|
|
291
289
|
getMinOffsetLeft() {
|
|
292
290
|
return this.topLevelMenu.bodyMargin.left;
|
|
@@ -305,9 +303,11 @@ class RdtMenuOverlayComponent {
|
|
|
305
303
|
this.topLevelMenu.bodyMargin.bottom);
|
|
306
304
|
}
|
|
307
305
|
recalculatePosition(preferredHorizontalDir, preferredVerticalDir) {
|
|
308
|
-
|
|
306
|
+
const isRoot = untracked(this.isRootLevel);
|
|
307
|
+
const horizontalDir = untracked(this.horizontalDir);
|
|
308
|
+
const verticalDir = untracked(this.verticalDir);
|
|
309
309
|
this.measureBoundingRect();
|
|
310
|
-
if (!this._box || !this._anchorBox) {
|
|
310
|
+
if (!this._box || !this._anchorBox || !this.topLevelMenu.clientSize) {
|
|
311
311
|
return;
|
|
312
312
|
}
|
|
313
313
|
const newHorDir = this.getRealHorizontalDir(preferredHorizontalDir);
|
|
@@ -315,13 +315,13 @@ class RdtMenuOverlayComponent {
|
|
|
315
315
|
// Horizontal direction
|
|
316
316
|
if (newHorDir.dir === 'right') {
|
|
317
317
|
newHorDir.left += this._anchorBox.left;
|
|
318
|
-
if (!
|
|
318
|
+
if (!isRoot) {
|
|
319
319
|
newHorDir.left += this._anchorBox.width;
|
|
320
320
|
}
|
|
321
321
|
}
|
|
322
322
|
else if (newHorDir.dir === 'left') {
|
|
323
323
|
newHorDir.left += this._anchorBox.left - this._box.width;
|
|
324
|
-
if (
|
|
324
|
+
if (isRoot) {
|
|
325
325
|
newHorDir.left += this._anchorBox.width;
|
|
326
326
|
}
|
|
327
327
|
}
|
|
@@ -330,7 +330,7 @@ class RdtMenuOverlayComponent {
|
|
|
330
330
|
// Vertical direction
|
|
331
331
|
if (newVertDir.dir === 'down') {
|
|
332
332
|
newVertDir.top = this._anchorBox.top;
|
|
333
|
-
if (
|
|
333
|
+
if (isRoot) {
|
|
334
334
|
newVertDir.top += this._anchorBox.height;
|
|
335
335
|
}
|
|
336
336
|
else {
|
|
@@ -339,45 +339,54 @@ class RdtMenuOverlayComponent {
|
|
|
339
339
|
}
|
|
340
340
|
else if (newVertDir.dir === 'up') {
|
|
341
341
|
newVertDir.top = this._anchorBox.top - this._box.height;
|
|
342
|
-
if (!
|
|
342
|
+
if (!isRoot) {
|
|
343
343
|
newVertDir.top += this._anchorBox.height + this._containerPadding.top;
|
|
344
344
|
}
|
|
345
345
|
}
|
|
346
346
|
// Restrictions from header and footer
|
|
347
347
|
newVertDir.top = Math.min(Math.max(this.getMinOffsetTop(), newVertDir.top), this.getMaxOffsetTop());
|
|
348
|
-
if (!areHorDirsEqual(
|
|
349
|
-
!areVertDirsEqual(
|
|
350
|
-
this.horizontalDir
|
|
351
|
-
this.verticalDir
|
|
348
|
+
if (!areHorDirsEqual(horizontalDir, newHorDir) ||
|
|
349
|
+
!areVertDirsEqual(verticalDir, newVertDir)) {
|
|
350
|
+
this.horizontalDir.set(newHorDir);
|
|
351
|
+
this.verticalDir.set(newVertDir);
|
|
352
352
|
this.setClasses();
|
|
353
353
|
this.measureBoundingRect();
|
|
354
354
|
}
|
|
355
355
|
this.recalculateChildren();
|
|
356
356
|
}
|
|
357
|
+
recalculateChildren() {
|
|
358
|
+
const horizontalDir = untracked(this.horizontalDir);
|
|
359
|
+
const verticalDir = untracked(this.verticalDir);
|
|
360
|
+
if (this.children && horizontalDir && verticalDir) {
|
|
361
|
+
this.children.forEach((child) => child.recalculatePosition(horizontalDir.dir, verticalDir.dir));
|
|
362
|
+
}
|
|
363
|
+
}
|
|
357
364
|
onItemPointerEnter(item) {
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
365
|
+
const expandedChild = untracked(this.expandedChild);
|
|
366
|
+
const openOnHover = untracked(this.topLevelMenu.openOnHover);
|
|
367
|
+
if (openOnHover && expandedChild?.src !== RdtMenuExpandSource.Click) {
|
|
368
|
+
this.autofocusSubmenuItem.set(null);
|
|
361
369
|
if (menuItemHasChildren(item)) {
|
|
362
|
-
this.expandedChild
|
|
363
|
-
this.expanded
|
|
370
|
+
this.expandedChild.set({ item, src: RdtMenuExpandSource.Hover });
|
|
371
|
+
this.expanded.set(true);
|
|
364
372
|
}
|
|
365
373
|
else {
|
|
366
374
|
//console.log('expanded child', this.expandedChild);
|
|
367
|
-
this.expandedChild
|
|
375
|
+
this.expandedChild.set(null);
|
|
368
376
|
}
|
|
369
377
|
}
|
|
370
378
|
}
|
|
371
379
|
onItemClick(item) {
|
|
380
|
+
const expandedChild = untracked(this.expandedChild);
|
|
372
381
|
const hasChildren = menuItemHasChildren(item);
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
this.autofocusSubmenuItem
|
|
377
|
-
this.expandedChild
|
|
382
|
+
const openOnHover = this.topLevelMenu.openOnHover();
|
|
383
|
+
if ((hasChildren && expandedChild?.item !== item) ||
|
|
384
|
+
(openOnHover && expandedChild?.src === RdtMenuExpandSource.Hover)) {
|
|
385
|
+
this.autofocusSubmenuItem.set(null);
|
|
386
|
+
this.expandedChild.set({ item, src: RdtMenuExpandSource.Click });
|
|
378
387
|
}
|
|
379
388
|
else {
|
|
380
|
-
this.expandedChild
|
|
389
|
+
this.expandedChild.set(null);
|
|
381
390
|
}
|
|
382
391
|
// Could also listen to router events, but might be triggered by
|
|
383
392
|
// child router navigation.
|
|
@@ -393,23 +402,24 @@ class RdtMenuOverlayComponent {
|
|
|
393
402
|
this.router.navigate(item.routerLink);
|
|
394
403
|
}
|
|
395
404
|
this.onItemClick(item);
|
|
396
|
-
this.autofocusSubmenuItem
|
|
405
|
+
this.autofocusSubmenuItem.set('first');
|
|
397
406
|
}
|
|
398
407
|
getChildRoutes(item) {
|
|
399
408
|
return this.topLevelMenu.getChildRoutes(item);
|
|
400
409
|
}
|
|
401
410
|
closeSubmenus(focusExpanded = false) {
|
|
402
|
-
|
|
403
|
-
|
|
411
|
+
const expandedChild = this.expandedChild();
|
|
412
|
+
if (focusExpanded && expandedChild) {
|
|
413
|
+
this.focusItem(expandedChild.item);
|
|
404
414
|
}
|
|
405
|
-
this.expandedChild
|
|
415
|
+
this.expandedChild.set(null);
|
|
406
416
|
this.cd.markForCheck();
|
|
407
417
|
}
|
|
408
418
|
focusItemRecursively(path) {
|
|
409
419
|
const children = [...path];
|
|
410
420
|
const thisItem = children.shift();
|
|
411
|
-
this.autofocusSubmenuItem
|
|
412
|
-
this.autofocusItem
|
|
421
|
+
this.autofocusSubmenuItem.set(null);
|
|
422
|
+
this.autofocusItem.set(null);
|
|
413
423
|
if (children.length > 0) {
|
|
414
424
|
this.expandAndGetChild(thisItem, RdtMenuExpandSource.Focus)
|
|
415
425
|
.pipe(delay(1))
|
|
@@ -429,20 +439,22 @@ class RdtMenuOverlayComponent {
|
|
|
429
439
|
}
|
|
430
440
|
}
|
|
431
441
|
expandAndGetChild(item, src) {
|
|
432
|
-
|
|
442
|
+
const rootItem = untracked(this.item);
|
|
443
|
+
if (rootItem.items.indexOf(item) < 0) {
|
|
433
444
|
throw new Error('Attempting to expand item that is not child item of this.item');
|
|
434
445
|
}
|
|
435
|
-
this.expandedChild
|
|
446
|
+
this.expandedChild.set({ item, src });
|
|
436
447
|
this.cd.markForCheck();
|
|
437
|
-
const child = this.children.find((child) => child.item === item);
|
|
448
|
+
const child = this.children.find((child) => untracked(child.item) === item);
|
|
438
449
|
if (child) {
|
|
439
450
|
return of(child);
|
|
440
451
|
}
|
|
441
452
|
else {
|
|
442
|
-
return this.children.changes.pipe(map(() => this.children.find((child) => child.item === item)), first(RdtObjectUtils.notNullGuard));
|
|
453
|
+
return this.children.changes.pipe(map(() => this.children.find((child) => untracked(child.item) === item)), first(RdtObjectUtils.notNullGuard));
|
|
443
454
|
}
|
|
444
455
|
}
|
|
445
456
|
onKeyDown(itemIndex, event) {
|
|
457
|
+
const rootItem = untracked(this.item);
|
|
446
458
|
const hasAction = event.code in this.keyActions;
|
|
447
459
|
const isLetter = RdtStringUtils.isAlphabetCharacter(event.key) ||
|
|
448
460
|
RdtStringUtils.isNumericCharacter(event.key);
|
|
@@ -456,7 +468,7 @@ class RdtMenuOverlayComponent {
|
|
|
456
468
|
this.keyActions[event.code](itemIndex);
|
|
457
469
|
}
|
|
458
470
|
else if (isLetter) {
|
|
459
|
-
const next = findNextItemWithPrefix(
|
|
471
|
+
const next = findNextItemWithPrefix(rootItem.items, itemIndex, event.key);
|
|
460
472
|
if (next !== null) {
|
|
461
473
|
this.focusItem(next);
|
|
462
474
|
}
|
|
@@ -473,7 +485,8 @@ class RdtMenuOverlayComponent {
|
|
|
473
485
|
}, 1);
|
|
474
486
|
}
|
|
475
487
|
invokeItemClickByIndex(itemIndex) {
|
|
476
|
-
const
|
|
488
|
+
const rootItem = untracked(this.item);
|
|
489
|
+
const item = rootItem.items[itemIndex];
|
|
477
490
|
if (!item) {
|
|
478
491
|
return;
|
|
479
492
|
}
|
|
@@ -485,7 +498,7 @@ class RdtMenuOverlayComponent {
|
|
|
485
498
|
itemIndex = item;
|
|
486
499
|
}
|
|
487
500
|
else {
|
|
488
|
-
itemIndex = this.item.items.indexOf(item);
|
|
501
|
+
itemIndex = this.item().items.indexOf(item);
|
|
489
502
|
}
|
|
490
503
|
if (itemIndex >= 0 && itemIndex < this.focusableElements.length) {
|
|
491
504
|
this.blurAllFocusable();
|
|
@@ -505,18 +518,21 @@ class RdtMenuOverlayComponent {
|
|
|
505
518
|
}
|
|
506
519
|
}
|
|
507
520
|
focusNextItem(itemIndex) {
|
|
508
|
-
const
|
|
521
|
+
const rootItem = untracked(this.item);
|
|
522
|
+
const next = (itemIndex + 1) % rootItem.items.length;
|
|
509
523
|
this.focusItem(next);
|
|
510
524
|
}
|
|
511
525
|
focusPrevItem(itemIndex) {
|
|
512
|
-
const
|
|
526
|
+
const rootItem = untracked(this.item);
|
|
527
|
+
const prev = (itemIndex - 1 + rootItem.items.length) % rootItem.items.length;
|
|
513
528
|
this.focusItem(prev);
|
|
514
529
|
}
|
|
515
530
|
openSubmenu(itemIndex, visibleFocus, src) {
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
this.
|
|
531
|
+
const rootItem = untracked(this.item);
|
|
532
|
+
if (itemIndex < rootItem.items.length &&
|
|
533
|
+
menuItemHasChildren(rootItem.items[itemIndex])) {
|
|
534
|
+
this.expandedChild.set({ item: rootItem.items[itemIndex], src });
|
|
535
|
+
this.autofocusSubmenuItem.set(visibleFocus);
|
|
520
536
|
}
|
|
521
537
|
}
|
|
522
538
|
closeSelf(focusExpanded = true) {
|
|
@@ -528,21 +544,23 @@ class RdtMenuOverlayComponent {
|
|
|
528
544
|
}
|
|
529
545
|
}
|
|
530
546
|
checkActiveElement(event) {
|
|
531
|
-
|
|
547
|
+
const closeOnFocusOut = untracked(this.topLevelMenu.closeOnFocusOut);
|
|
548
|
+
if (closeOnFocusOut && !this.topLevelMenu.openOnHover) {
|
|
532
549
|
const thisEl = this.elRef.nativeElement;
|
|
533
550
|
const target = event.relatedTarget;
|
|
534
551
|
if (!(target instanceof HTMLElement) || !thisEl.contains(target)) {
|
|
535
|
-
this.expandedChild
|
|
552
|
+
this.expandedChild.set(null);
|
|
536
553
|
}
|
|
537
554
|
}
|
|
538
555
|
}
|
|
539
556
|
// Calculates direction of this menu and offset in case
|
|
540
557
|
// menu won't fit in left nor right of parent menu.
|
|
541
558
|
getRealHorizontalDir(preferredHorizontalDir) {
|
|
559
|
+
const isRoot = untracked(this.isRootLevel);
|
|
542
560
|
let left;
|
|
543
561
|
let right;
|
|
544
562
|
// This menu is directly under menubar
|
|
545
|
-
if (
|
|
563
|
+
if (isRoot) {
|
|
546
564
|
left = this._anchorBox.right - this._box.width;
|
|
547
565
|
right =
|
|
548
566
|
this.topLevelMenu.clientSize.width -
|
|
@@ -602,9 +620,10 @@ class RdtMenuOverlayComponent {
|
|
|
602
620
|
}
|
|
603
621
|
}
|
|
604
622
|
getRealVerticalDir(preferredVerticalDir) {
|
|
623
|
+
const isRoot = untracked(this.isRootLevel);
|
|
605
624
|
let bottom;
|
|
606
625
|
let top;
|
|
607
|
-
if (
|
|
626
|
+
if (isRoot) {
|
|
608
627
|
bottom =
|
|
609
628
|
this.topLevelMenu.clientSize.height +
|
|
610
629
|
this._anchorBox.bottom -
|
|
@@ -647,7 +666,7 @@ class RdtMenuOverlayComponent {
|
|
|
647
666
|
// Should always be called after parent menu has already been measured.
|
|
648
667
|
measureBoundingRect() {
|
|
649
668
|
this._box = this.elRef.nativeElement.getBoundingClientRect();
|
|
650
|
-
const anchor = this.anchorElement
|
|
669
|
+
const anchor = this.anchorElement();
|
|
651
670
|
this._anchorBox = anchor.getBoundingClientRect();
|
|
652
671
|
}
|
|
653
672
|
measureContainerPadding() {
|
|
@@ -656,14 +675,12 @@ class RdtMenuOverlayComponent {
|
|
|
656
675
|
const paddingBottom = parseFloat(computedStyles.paddingBottom);
|
|
657
676
|
this._containerPadding = { top: paddingTop, bottom: paddingBottom };
|
|
658
677
|
}
|
|
659
|
-
recalculateChildren() {
|
|
660
|
-
if (this.expanded && this.horizontalDir && this.verticalDir) {
|
|
661
|
-
this.children.forEach((child) => child.recalculatePosition(this.horizontalDir.dir, this.verticalDir.dir));
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
678
|
setClasses() {
|
|
665
|
-
|
|
666
|
-
|
|
679
|
+
const isRoot = this.isRootLevel();
|
|
680
|
+
const vertical = this.verticalDir();
|
|
681
|
+
const horizontal = this.horizontalDir();
|
|
682
|
+
if (vertical) {
|
|
683
|
+
if (vertical.dir === 'up') {
|
|
667
684
|
this.setClass('rdt-overlay-up');
|
|
668
685
|
this.removeClass('rdt-overlay-down');
|
|
669
686
|
}
|
|
@@ -671,10 +688,10 @@ class RdtMenuOverlayComponent {
|
|
|
671
688
|
this.removeClass('rdt-overlay-up');
|
|
672
689
|
this.setClass('rdt-overlay-down');
|
|
673
690
|
}
|
|
674
|
-
this.setOffset('top',
|
|
691
|
+
this.setOffset('top', vertical.top);
|
|
675
692
|
}
|
|
676
|
-
if (
|
|
677
|
-
if (
|
|
693
|
+
if (horizontal) {
|
|
694
|
+
if (horizontal.dir === 'left') {
|
|
678
695
|
this.setClass('rdt-overlay-left');
|
|
679
696
|
this.removeClass('rdt-overlay-right');
|
|
680
697
|
}
|
|
@@ -682,9 +699,9 @@ class RdtMenuOverlayComponent {
|
|
|
682
699
|
this.removeClass('rdt-overlay-left');
|
|
683
700
|
this.setClass('rdt-overlay-right');
|
|
684
701
|
}
|
|
685
|
-
this.setOffset('left',
|
|
702
|
+
this.setOffset('left', horizontal.left);
|
|
686
703
|
}
|
|
687
|
-
if (
|
|
704
|
+
if (isRoot) {
|
|
688
705
|
this.setClass('rdt-menu-root');
|
|
689
706
|
this.removeClass('rdt-menu-sub');
|
|
690
707
|
}
|
|
@@ -713,13 +730,18 @@ class RdtMenuOverlayComponent {
|
|
|
713
730
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
714
731
|
.subscribe((event) => this.onTabKeyPress(event));
|
|
715
732
|
}
|
|
716
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
717
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
733
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuOverlayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
734
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: RdtMenuOverlayComponent, isStandalone: false, selector: "rdt-menu-overlay", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, level: { classPropertyName: "level", publicName: "level", isSignal: true, isRequired: true, transformFunction: null }, preferredHorizontalDir: { classPropertyName: "preferredHorizontalDir", publicName: "preferredHorizontalDir", isSignal: true, isRequired: false, transformFunction: null }, preferredVerticalDir: { classPropertyName: "preferredVerticalDir", publicName: "preferredVerticalDir", isSignal: true, isRequired: false, transformFunction: null }, expandedInput: { classPropertyName: "expandedInput", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, autofocusItemInput: { classPropertyName: "autofocusItemInput", publicName: "autofocusItem", isSignal: true, isRequired: false, transformFunction: null }, anchorElementInput: { classPropertyName: "anchorElementInput", publicName: "anchorElement", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "tabindex": "-1", "role": "menu" }, listeners: { "window:focusout": "checkActiveElement($event)" }, properties: { "class.expanded": "expanded()", "style.z-index": "zIndex()" } }, viewQueries: [{ propertyName: "menuItemContainer", first: true, predicate: ["menuItemContainer"], descendants: true }, { propertyName: "children", predicate: RdtMenuOverlayComponent, descendants: true }, { propertyName: "focusableElements", predicate: ["focusableItem"], descendants: true }], ngImport: i0, template: "<ul class=\"menu-item-container\" role=\"presentation\" #menuItemContainer>\r\n @for(item of item().items; track item; let i = $index) {\r\n <li\r\n role=\"presentation\"\r\n class=\"menu-item\"\r\n (rdtKeyListener)=\"onKeyDown(i, $event)\"\r\n (pointerenter)=\"onItemPointerEnter(item)\"\r\n rdtAnyRouteActive=\"menu-item-route-active\"\r\n [watchedRoutes]=\"getChildRoutes(item)\"\r\n #anchorEl\r\n >\r\n @if(!item.routerLink && !item.externalLink) {\r\n <button\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [attr.aria-haspopup]=\"item.items ? 'menu' : null\"\r\n [attr.aria-expanded]=\"item === expandedChild()?.item\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n {{ item.label }}\r\n\r\n <div class=\"menu-item-right-content\">\r\n @if (item.shortcut) {\r\n <span class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n }\r\n <!-- TODO:\r\n <rdt-icon\r\n *ngIf=\"item.items\"\r\n name=\"chevron_right\"\r\n class=\"menu-item-icon\"\r\n />\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-item-icon\"\r\n />\r\n -->\r\n @if (item.items) {\r\n <span class=\"menu-item-icon rdt-menu-icon-right\"></span>\r\n }\r\n </div>\r\n </button>\r\n }\r\n\r\n <ng-template #linkBody let-item>\r\n {{ item.label }}\r\n\r\n <div class=\"menu-item-right-content\">\r\n @if(item.shortcut) {\r\n <span class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n }\r\n <!-- TODO:\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-item-icon\"\r\n />\r\n --></div>\r\n </ng-template>\r\n\r\n @if (item.routerLink) {\r\n <a\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [routerLink]=\"item.routerLink\"\r\n [queryParams]=\"item.queryParams\"\r\n [target]=\"item.target\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n } @if (item.externalLink) {\r\n <a\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [href]=\"item.externalLink\"\r\n [target]=\"item.target\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n }\r\n\r\n <!-- Child menus exist only if this menu is expanded. -->\r\n <!-- Only one invisible level is always attached to DOM, the rest does not exist. -->\r\n @if (item.items && expanded()) {\r\n <rdt-menu-overlay\r\n [item]=\"$any(item)\"\r\n [expanded]=\"item === expandedChild()?.item\"\r\n [autofocusItem]=\"autofocusSubmenuItem()\"\r\n [preferredHorizontalDir]=\"horizontalDir()?.dir!\"\r\n [preferredVerticalDir]=\"verticalDir()?.dir!\"\r\n [level]=\"level() + 1\"\r\n [anchorElement]=\"anchorEl\"\r\n />\r\n }\r\n </li>\r\n }\r\n</ul>\r\n", styles: [":host{visibility:hidden;position:fixed;min-width:var(--rdt-menu-min-width);box-shadow:var(--rdt-menu-box-shadow);border-radius:var(--rdt-menu-border-radius);overflow-x:hidden;overflow-y:auto;max-height:calc(100vh - var(--rdt-menu-margin-top, 0px) - var(--rdt-menu-margin-bottom, 0px))}:host.expanded{visibility:visible}ul.menu-item-container{list-style-type:none;padding:var(--rdt-menu-padding-horizontal-padding) 0;border-radius:var(--rdt-menu-border-radius);background-color:var(--rdt-menu-background);margin-top:0;margin-bottom:0;margin-block-start:0;margin-block-end:0}.menu-item-content{cursor:pointer;display:flex;align-items:center;width:100%;padding:var(--rdt-menu-item-padding);background-color:var(--rdt-menu-item-background);color:var(--rdt-menu-item-text-color);font-size:var(--rdt-menu-item-font-size);font-weight:var(--rdt-menu-item-font-weight);border:var(--rdt-menu-item-border);outline:var(--rdt-menu-item-outline)}.menu-item{display:flex;position:relative;box-sizing:border-box}.menu-item.menu-item-route-active>.menu-item-content{--rdt-menu-item-background: var(--rdt-menu-item-route-active-background);--rdt-menu-item-text-color: var(--rdt-menu-item-route-active-text-color);--rdt-menu-item-border: var(--rdt-menu-item-route-active-border);--rdt-menu-item-outline: var(--rdt-menu-item-route-active-outline)}.menu-item .menu-item-content:hover{--rdt-menu-item-background: var(--rdt-menu-item-hover-background);--rdt-menu-item-text-color: var(--rdt-menu-item-hover-text-color);--rdt-menu-item-border: var(--rdt-menu-item-hover-border);--rdt-menu-item-outline: var(--rdt-menu-item-hover-outline)}.menu-item [aria-expanded=true].menu-item-content{--rdt-menu-item-background: var(--rdt-menu-item-expanded-background);--rdt-menu-item-text-color: var(--rdt-menu-item-expanded-text-color);--rdt-menu-item-border: var(--rdt-menu-item-expanded-border);--rdt-menu-item-outline: var(--rdt-menu-item-expanded-outline)}.menu-item .menu-item-content.focus-visible:focus,.menu-item .menu-item-content:focus-visible{--rdt-menu-item-background: var(--rdt-menu-item-focus-background);--rdt-menu-item-text-color: var(--rdt-menu-item-focus-text-color);--rdt-menu-item-border: var(--rdt-menu-item-focus-border);--rdt-menu-item-outline: var(--rdt-menu-item-focus-outline)}.menu-item-icon.rdt-menu-icon-right{width:0;height:0;border-top:var(--rdt-menu-default-icon-size) solid transparent;border-bottom:var(--rdt-menu-default-icon-size) solid transparent;border-left:var(--rdt-menu-default-icon-size) solid var(--rdt-menu-item-text-color)}\n"], dependencies: [{ kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i3.RdtAnyRouteActiveDirective, selector: "[rdtAnyRouteActive]", inputs: ["rdtAnyRouteActive", "watchedRoutes", "anyRouteActiveOptions", "ariaCurrentWhenActive"] }, { kind: "directive", type: i4.RdtKeyListenerDirective, selector: "[rdtKeyListener]", outputs: ["rdtKeyListener"] }, { kind: "component", type: RdtMenuOverlayComponent, selector: "rdt-menu-overlay", inputs: ["item", "level", "preferredHorizontalDir", "preferredVerticalDir", "expanded", "autofocusItem", "anchorElement"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
718
735
|
}
|
|
719
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
736
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuOverlayComponent, decorators: [{
|
|
720
737
|
type: Component,
|
|
721
|
-
args: [{ selector: 'rdt-menu-overlay', changeDetection: ChangeDetectionStrategy.OnPush,
|
|
722
|
-
|
|
738
|
+
args: [{ selector: 'rdt-menu-overlay', changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, host: {
|
|
739
|
+
'[class.expanded]': 'expanded()',
|
|
740
|
+
'[style.z-index]': 'zIndex()',
|
|
741
|
+
tabindex: '-1',
|
|
742
|
+
role: 'menu',
|
|
743
|
+
}, template: "<ul class=\"menu-item-container\" role=\"presentation\" #menuItemContainer>\r\n @for(item of item().items; track item; let i = $index) {\r\n <li\r\n role=\"presentation\"\r\n class=\"menu-item\"\r\n (rdtKeyListener)=\"onKeyDown(i, $event)\"\r\n (pointerenter)=\"onItemPointerEnter(item)\"\r\n rdtAnyRouteActive=\"menu-item-route-active\"\r\n [watchedRoutes]=\"getChildRoutes(item)\"\r\n #anchorEl\r\n >\r\n @if(!item.routerLink && !item.externalLink) {\r\n <button\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [attr.aria-haspopup]=\"item.items ? 'menu' : null\"\r\n [attr.aria-expanded]=\"item === expandedChild()?.item\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n {{ item.label }}\r\n\r\n <div class=\"menu-item-right-content\">\r\n @if (item.shortcut) {\r\n <span class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n }\r\n <!-- TODO:\r\n <rdt-icon\r\n *ngIf=\"item.items\"\r\n name=\"chevron_right\"\r\n class=\"menu-item-icon\"\r\n />\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-item-icon\"\r\n />\r\n -->\r\n @if (item.items) {\r\n <span class=\"menu-item-icon rdt-menu-icon-right\"></span>\r\n }\r\n </div>\r\n </button>\r\n }\r\n\r\n <ng-template #linkBody let-item>\r\n {{ item.label }}\r\n\r\n <div class=\"menu-item-right-content\">\r\n @if(item.shortcut) {\r\n <span class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n }\r\n <!-- TODO:\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-item-icon\"\r\n />\r\n --></div>\r\n </ng-template>\r\n\r\n @if (item.routerLink) {\r\n <a\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [routerLink]=\"item.routerLink\"\r\n [queryParams]=\"item.queryParams\"\r\n [target]=\"item.target\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n } @if (item.externalLink) {\r\n <a\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [href]=\"item.externalLink\"\r\n [target]=\"item.target\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n }\r\n\r\n <!-- Child menus exist only if this menu is expanded. -->\r\n <!-- Only one invisible level is always attached to DOM, the rest does not exist. -->\r\n @if (item.items && expanded()) {\r\n <rdt-menu-overlay\r\n [item]=\"$any(item)\"\r\n [expanded]=\"item === expandedChild()?.item\"\r\n [autofocusItem]=\"autofocusSubmenuItem()\"\r\n [preferredHorizontalDir]=\"horizontalDir()?.dir!\"\r\n [preferredVerticalDir]=\"verticalDir()?.dir!\"\r\n [level]=\"level() + 1\"\r\n [anchorElement]=\"anchorEl\"\r\n />\r\n }\r\n </li>\r\n }\r\n</ul>\r\n", styles: [":host{visibility:hidden;position:fixed;min-width:var(--rdt-menu-min-width);box-shadow:var(--rdt-menu-box-shadow);border-radius:var(--rdt-menu-border-radius);overflow-x:hidden;overflow-y:auto;max-height:calc(100vh - var(--rdt-menu-margin-top, 0px) - var(--rdt-menu-margin-bottom, 0px))}:host.expanded{visibility:visible}ul.menu-item-container{list-style-type:none;padding:var(--rdt-menu-padding-horizontal-padding) 0;border-radius:var(--rdt-menu-border-radius);background-color:var(--rdt-menu-background);margin-top:0;margin-bottom:0;margin-block-start:0;margin-block-end:0}.menu-item-content{cursor:pointer;display:flex;align-items:center;width:100%;padding:var(--rdt-menu-item-padding);background-color:var(--rdt-menu-item-background);color:var(--rdt-menu-item-text-color);font-size:var(--rdt-menu-item-font-size);font-weight:var(--rdt-menu-item-font-weight);border:var(--rdt-menu-item-border);outline:var(--rdt-menu-item-outline)}.menu-item{display:flex;position:relative;box-sizing:border-box}.menu-item.menu-item-route-active>.menu-item-content{--rdt-menu-item-background: var(--rdt-menu-item-route-active-background);--rdt-menu-item-text-color: var(--rdt-menu-item-route-active-text-color);--rdt-menu-item-border: var(--rdt-menu-item-route-active-border);--rdt-menu-item-outline: var(--rdt-menu-item-route-active-outline)}.menu-item .menu-item-content:hover{--rdt-menu-item-background: var(--rdt-menu-item-hover-background);--rdt-menu-item-text-color: var(--rdt-menu-item-hover-text-color);--rdt-menu-item-border: var(--rdt-menu-item-hover-border);--rdt-menu-item-outline: var(--rdt-menu-item-hover-outline)}.menu-item [aria-expanded=true].menu-item-content{--rdt-menu-item-background: var(--rdt-menu-item-expanded-background);--rdt-menu-item-text-color: var(--rdt-menu-item-expanded-text-color);--rdt-menu-item-border: var(--rdt-menu-item-expanded-border);--rdt-menu-item-outline: var(--rdt-menu-item-expanded-outline)}.menu-item .menu-item-content.focus-visible:focus,.menu-item .menu-item-content:focus-visible{--rdt-menu-item-background: var(--rdt-menu-item-focus-background);--rdt-menu-item-text-color: var(--rdt-menu-item-focus-text-color);--rdt-menu-item-border: var(--rdt-menu-item-focus-border);--rdt-menu-item-outline: var(--rdt-menu-item-focus-outline)}.menu-item-icon.rdt-menu-icon-right{width:0;height:0;border-top:var(--rdt-menu-default-icon-size) solid transparent;border-bottom:var(--rdt-menu-default-icon-size) solid transparent;border-left:var(--rdt-menu-default-icon-size) solid var(--rdt-menu-item-text-color)}\n"] }]
|
|
744
|
+
}], ctorParameters: () => [], propDecorators: { children: [{
|
|
723
745
|
type: ViewChildren,
|
|
724
746
|
args: [RdtMenuOverlayComponent]
|
|
725
747
|
}], focusableElements: [{
|
|
@@ -728,48 +750,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
|
|
|
728
750
|
}], menuItemContainer: [{
|
|
729
751
|
type: ViewChild,
|
|
730
752
|
args: ['menuItemContainer']
|
|
731
|
-
}], item: [{
|
|
732
|
-
type: Input
|
|
733
|
-
}], level: [{
|
|
734
|
-
type: Input
|
|
735
|
-
}], preferredHorizontalDir: [{
|
|
736
|
-
type: Input
|
|
737
|
-
}], preferredVerticalDir: [{
|
|
738
|
-
type: Input
|
|
739
|
-
}], expanded: [{
|
|
740
|
-
type: HostBinding,
|
|
741
|
-
args: ['class.expanded']
|
|
742
|
-
}, {
|
|
743
|
-
type: Input
|
|
744
|
-
}], autofocusItem: [{
|
|
745
|
-
type: Input
|
|
746
|
-
}], anchorElement: [{
|
|
747
|
-
type: Input
|
|
748
|
-
}], roleAttr: [{
|
|
749
|
-
type: HostBinding,
|
|
750
|
-
args: ['attr.role']
|
|
751
|
-
}], tabindexAttr: [{
|
|
752
|
-
type: HostBinding,
|
|
753
|
-
args: ['attr.tabindex']
|
|
754
|
-
}], zIndex: [{
|
|
755
|
-
type: HostBinding,
|
|
756
|
-
args: ['style.z-index']
|
|
757
753
|
}], checkActiveElement: [{
|
|
758
754
|
type: HostListener,
|
|
759
755
|
args: ['window:focusout', ['$event']]
|
|
760
756
|
}] } });
|
|
761
757
|
|
|
762
758
|
class RdtMenuBaseComponent {
|
|
763
|
-
preferredVerticalDir = DEFAULT_MENU_VERTICAL_DIR;
|
|
764
|
-
preferredHorizontalDir = DEFAULT_MENU_HORIZONTAL_DIR;
|
|
759
|
+
preferredVerticalDir = input(DEFAULT_MENU_VERTICAL_DIR, ...(ngDevMode ? [{ debugName: "preferredVerticalDir" }] : []));
|
|
760
|
+
preferredHorizontalDir = input(DEFAULT_MENU_HORIZONTAL_DIR, ...(ngDevMode ? [{ debugName: "preferredHorizontalDir" }] : []));
|
|
765
761
|
// Mode only matters if item has shortcut and only children, no command nor routerLink
|
|
766
762
|
// FOCUS_ITEM will put focus on item with shortcut
|
|
767
763
|
// OPEN_SUBMENU will open its submenu and put focus on the first item in it
|
|
768
764
|
// If item has command or routerLink, it will always be activated and everything closed
|
|
769
|
-
shortcutMode = RdtMenuShortcutMode.OPEN_SUBMENU;
|
|
770
|
-
closeOnFocusOut = false;
|
|
771
|
-
openOnHover = false;
|
|
772
|
-
hitboxMargin = 10;
|
|
765
|
+
shortcutMode = input(RdtMenuShortcutMode.OPEN_SUBMENU, ...(ngDevMode ? [{ debugName: "shortcutMode" }] : []));
|
|
766
|
+
closeOnFocusOut = input(false, ...(ngDevMode ? [{ debugName: "closeOnFocusOut", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
767
|
+
openOnHover = input(false, ...(ngDevMode ? [{ debugName: "openOnHover", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
768
|
+
hitboxMargin = input(10, ...(ngDevMode ? [{ debugName: "hitboxMargin", transform: numberAttribute }] : [{ transform: numberAttribute }]));
|
|
773
769
|
cd = inject(ChangeDetectorRef);
|
|
774
770
|
destroyRef = inject(DestroyRef);
|
|
775
771
|
rdtRouter = inject(RdtRouterService);
|
|
@@ -781,10 +777,19 @@ class RdtMenuBaseComponent {
|
|
|
781
777
|
injector = inject(EnvironmentInjector);
|
|
782
778
|
children;
|
|
783
779
|
focusableElements;
|
|
784
|
-
|
|
785
|
-
expandedChild = null;
|
|
780
|
+
expandedChild = signal(null, ...(ngDevMode ? [{ debugName: "expandedChild" }] : []));
|
|
786
781
|
autofocusSubmenuItem = null;
|
|
787
|
-
|
|
782
|
+
filteredItems = computed(() => {
|
|
783
|
+
this.navigationEnd();
|
|
784
|
+
const items = this.allParsedItems();
|
|
785
|
+
const current = this.rdtRouter.parseAbsoluteUrl();
|
|
786
|
+
if (!current) {
|
|
787
|
+
return items;
|
|
788
|
+
}
|
|
789
|
+
else {
|
|
790
|
+
return this.filterRec(items, current);
|
|
791
|
+
}
|
|
792
|
+
}, ...(ngDevMode ? [{ debugName: "filteredItems" }] : []));
|
|
788
793
|
get clientSize() {
|
|
789
794
|
return this._clientSize;
|
|
790
795
|
}
|
|
@@ -797,78 +802,74 @@ class RdtMenuBaseComponent {
|
|
|
797
802
|
return this._buttonContainerRect;
|
|
798
803
|
}
|
|
799
804
|
_buttonContainerRect;
|
|
800
|
-
|
|
801
|
-
childRoutesMap = new Map();
|
|
802
|
-
shortcutSub = new Subscription();
|
|
803
|
-
shortcutMap = {};
|
|
805
|
+
childRoutesMap = computed(() => getChildRoutesMap(this.filteredItems()), ...(ngDevMode ? [{ debugName: "childRoutesMap" }] : []));
|
|
804
806
|
keyActions = {
|
|
805
807
|
[KB_CODE.ARROW.LEFT]: (index) => this.focusPrevItem(index),
|
|
806
808
|
[KB_CODE.ARROW.RIGHT]: (index) => this.focusNextItem(index),
|
|
807
809
|
[KB_CODE.ARROW.DOWN]: (index) => this.openSubmenu(index, 'first', RdtMenuExpandSource.Shortcut),
|
|
808
810
|
[KB_CODE.ARROW.UP]: (index) => this.openSubmenu(index, 'last', RdtMenuExpandSource.Shortcut),
|
|
809
811
|
[KB_CODE.HOME]: () => this.focusItem(0),
|
|
810
|
-
[KB_CODE.END]: () => this.focusItem(this.
|
|
812
|
+
[KB_CODE.END]: () => this.focusItem(untracked(this.filteredItems).length - 1),
|
|
811
813
|
[KB_CODE.ENTER]: (index) => this.invokeItemClickByIndex(index),
|
|
812
814
|
[KB_CODE.SPACEBAR]: (index) => this.invokeItemClickByIndex(index),
|
|
813
815
|
};
|
|
816
|
+
navigationEnd = toSignal(this.rdtRouter.navigationEnd$);
|
|
814
817
|
// Returns all routes asociated with item or its subitems.
|
|
815
818
|
getChildRoutes(item) {
|
|
816
|
-
return this.childRoutesMap.get(item) ?? [];
|
|
819
|
+
return this.childRoutesMap().get(item) ?? [];
|
|
817
820
|
}
|
|
818
|
-
|
|
819
|
-
this.
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
this.measure();
|
|
823
|
-
}
|
|
824
|
-
ngOnChanges(changes) {
|
|
825
|
-
if (this.children) {
|
|
826
|
-
this.recalculateChildren();
|
|
827
|
-
}
|
|
828
|
-
}
|
|
829
|
-
ngAfterViewInit() {
|
|
830
|
-
this.listenWindowResize();
|
|
831
|
-
// Not using timeout results in horizontal overflow on html element
|
|
832
|
-
setTimeout(() => {
|
|
821
|
+
constructor() {
|
|
822
|
+
this.listenShortcuts();
|
|
823
|
+
afterNextRender(() => {
|
|
824
|
+
this.listenWindowResize();
|
|
833
825
|
this.measure();
|
|
834
826
|
this.recalculateChildren();
|
|
835
|
-
}
|
|
827
|
+
});
|
|
836
828
|
}
|
|
829
|
+
recalcChildrenEffect = effect(() => {
|
|
830
|
+
this.recalculateChildren();
|
|
831
|
+
}, ...(ngDevMode ? [{ debugName: "recalcChildrenEffect" }] : []));
|
|
837
832
|
recalculateChildren() {
|
|
838
|
-
this.children
|
|
839
|
-
|
|
840
|
-
|
|
833
|
+
if (this.children) {
|
|
834
|
+
this.children.forEach((child) => {
|
|
835
|
+
child.recalculatePosition(this.preferredHorizontalDir(), this.preferredVerticalDir());
|
|
836
|
+
});
|
|
837
|
+
}
|
|
841
838
|
}
|
|
842
839
|
closeSubmenus(focusExpanded = false) {
|
|
843
|
-
|
|
844
|
-
|
|
840
|
+
const expandedChild = untracked(this.expandedChild);
|
|
841
|
+
if (focusExpanded && expandedChild) {
|
|
842
|
+
this.focusItem(expandedChild.item);
|
|
845
843
|
}
|
|
846
|
-
this.expandedChild
|
|
844
|
+
this.expandedChild.set(null);
|
|
847
845
|
this.cd.markForCheck();
|
|
848
846
|
}
|
|
849
847
|
onItemClick(item) {
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
848
|
+
const expandedChild = untracked(this.expandedChild);
|
|
849
|
+
const openOnHover = untracked(this.openOnHover);
|
|
850
|
+
if ((menuItemHasChildren(item) && expandedChild?.item !== item) ||
|
|
851
|
+
(openOnHover && expandedChild?.src === RdtMenuExpandSource.Hover)) {
|
|
853
852
|
this.autofocusSubmenuItem = null;
|
|
854
|
-
this.expandedChild
|
|
853
|
+
this.expandedChild.set({ item, src: RdtMenuExpandSource.Click });
|
|
855
854
|
}
|
|
856
855
|
else {
|
|
857
|
-
this.expandedChild
|
|
856
|
+
this.expandedChild.set(null);
|
|
858
857
|
}
|
|
859
858
|
if (typeof item.command === 'function') {
|
|
860
859
|
item.command();
|
|
861
860
|
}
|
|
862
861
|
}
|
|
863
862
|
onItemPointerEnter(item) {
|
|
864
|
-
|
|
863
|
+
const expandedChild = untracked(this.expandedChild);
|
|
864
|
+
const openOnHover = untracked(this.openOnHover);
|
|
865
|
+
if (openOnHover) {
|
|
865
866
|
if (menuItemHasChildren(item) &&
|
|
866
|
-
|
|
867
|
+
expandedChild?.src !== RdtMenuExpandSource.Click) {
|
|
867
868
|
this.autofocusSubmenuItem = null;
|
|
868
|
-
this.expandedChild
|
|
869
|
+
this.expandedChild.set({ item, src: RdtMenuExpandSource.Hover });
|
|
869
870
|
}
|
|
870
871
|
else {
|
|
871
|
-
this.expandedChild
|
|
872
|
+
this.expandedChild.set(null);
|
|
872
873
|
}
|
|
873
874
|
}
|
|
874
875
|
}
|
|
@@ -886,7 +887,8 @@ class RdtMenuBaseComponent {
|
|
|
886
887
|
this.keyActions[event.code](itemIndex);
|
|
887
888
|
}
|
|
888
889
|
else if (isLetter) {
|
|
889
|
-
const
|
|
890
|
+
const filteredItems = untracked(this.filteredItems);
|
|
891
|
+
const next = findNextItemWithPrefix(filteredItems, itemIndex, event.key);
|
|
890
892
|
if (next !== null) {
|
|
891
893
|
this.focusItem(next);
|
|
892
894
|
}
|
|
@@ -899,18 +901,6 @@ class RdtMenuBaseComponent {
|
|
|
899
901
|
this.onItemClick(item);
|
|
900
902
|
this.autofocusSubmenuItem = 'first';
|
|
901
903
|
}
|
|
902
|
-
filterItems() {
|
|
903
|
-
const current = this.rdtRouter.parseAbsoluteUrl();
|
|
904
|
-
if (!current) {
|
|
905
|
-
this.parsedItems = this.allParsedItems;
|
|
906
|
-
}
|
|
907
|
-
else {
|
|
908
|
-
this.parsedItems = this.filterRec(this.allParsedItems, current);
|
|
909
|
-
}
|
|
910
|
-
this.childRoutesMap = getChildRoutesMap(this.parsedItems);
|
|
911
|
-
this.listenShortcuts();
|
|
912
|
-
this.cd.markForCheck();
|
|
913
|
-
}
|
|
914
904
|
filterRec(items, current) {
|
|
915
905
|
let currentParent = current.route;
|
|
916
906
|
const currentParams = current.params;
|
|
@@ -952,27 +942,30 @@ class RdtMenuBaseComponent {
|
|
|
952
942
|
});
|
|
953
943
|
}
|
|
954
944
|
invokeItemClickByIndex(itemIndex) {
|
|
955
|
-
const
|
|
945
|
+
const filteredItems = untracked(this.filteredItems);
|
|
946
|
+
const item = filteredItems[itemIndex];
|
|
956
947
|
if (!item) {
|
|
957
948
|
return;
|
|
958
949
|
}
|
|
959
950
|
this.invokeItemClick(item);
|
|
960
951
|
}
|
|
961
952
|
openSubmenu(itemIndex, visibleFocus, src) {
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
953
|
+
const filteredItems = untracked(this.filteredItems);
|
|
954
|
+
if (itemIndex < filteredItems.length &&
|
|
955
|
+
menuItemHasChildren(filteredItems[itemIndex])) {
|
|
956
|
+
const item = filteredItems[itemIndex];
|
|
965
957
|
this.autofocusSubmenuItem = visibleFocus;
|
|
966
|
-
this.expandedChild
|
|
958
|
+
this.expandedChild.set({ item, src });
|
|
967
959
|
}
|
|
968
960
|
}
|
|
969
961
|
focusItem(item) {
|
|
962
|
+
const filteredItems = untracked(this.filteredItems);
|
|
970
963
|
let itemIndex;
|
|
971
964
|
if (typeof item === 'number') {
|
|
972
965
|
itemIndex = item;
|
|
973
966
|
}
|
|
974
967
|
else {
|
|
975
|
-
itemIndex =
|
|
968
|
+
itemIndex = filteredItems.indexOf(item);
|
|
976
969
|
}
|
|
977
970
|
if (itemIndex >= 0 && itemIndex < this.focusableElements.length) {
|
|
978
971
|
this.blurAllFocusable();
|
|
@@ -980,11 +973,13 @@ class RdtMenuBaseComponent {
|
|
|
980
973
|
}
|
|
981
974
|
}
|
|
982
975
|
focusNextItem(itemIndex) {
|
|
983
|
-
const
|
|
976
|
+
const filteredItems = untracked(this.filteredItems);
|
|
977
|
+
const next = (itemIndex + 1) % filteredItems.length;
|
|
984
978
|
this.focusItem(next);
|
|
985
979
|
}
|
|
986
980
|
focusPrevItem(itemIndex) {
|
|
987
|
-
const
|
|
981
|
+
const filteredItems = untracked(this.filteredItems);
|
|
982
|
+
const prev = (itemIndex - 1 + filteredItems.length) % filteredItems.length;
|
|
988
983
|
this.focusItem(prev);
|
|
989
984
|
}
|
|
990
985
|
blurAllFocusable() {
|
|
@@ -998,7 +993,9 @@ class RdtMenuBaseComponent {
|
|
|
998
993
|
}
|
|
999
994
|
}
|
|
1000
995
|
onPointerMove(event) {
|
|
1001
|
-
|
|
996
|
+
const expandedChild = untracked(this.expandedChild);
|
|
997
|
+
const openOnHover = untracked(this.openOnHover);
|
|
998
|
+
if (openOnHover && expandedChild) {
|
|
1002
999
|
const hitboxes = this.getHitboxes();
|
|
1003
1000
|
const isInside = hitboxes.some((hitbox) => this.isPointerInsideHitbox(hitbox.rect, event));
|
|
1004
1001
|
for (let i = hitboxes.length - 1; i >= 0; i--) {
|
|
@@ -1012,12 +1009,13 @@ class RdtMenuBaseComponent {
|
|
|
1012
1009
|
}
|
|
1013
1010
|
// Closes menu if user navigates outside it using Tab.
|
|
1014
1011
|
checkActiveElement(event) {
|
|
1015
|
-
|
|
1012
|
+
const closeOnFocusOut = untracked(this.closeOnFocusOut);
|
|
1013
|
+
if (closeOnFocusOut && !this.openOnHover) {
|
|
1016
1014
|
console.log('focusout', event);
|
|
1017
1015
|
const thisEl = this.elRef.nativeElement;
|
|
1018
1016
|
const target = event.relatedTarget;
|
|
1019
1017
|
if (!(target instanceof HTMLElement) || !thisEl.contains(target)) {
|
|
1020
|
-
this.expandedChild
|
|
1018
|
+
this.expandedChild.set(null);
|
|
1021
1019
|
}
|
|
1022
1020
|
}
|
|
1023
1021
|
}
|
|
@@ -1070,14 +1068,13 @@ class RdtMenuBaseComponent {
|
|
|
1070
1068
|
});
|
|
1071
1069
|
}
|
|
1072
1070
|
listenShortcuts() {
|
|
1073
|
-
const
|
|
1074
|
-
const
|
|
1075
|
-
|
|
1076
|
-
this.
|
|
1077
|
-
|
|
1078
|
-
.listen(shortcuts)
|
|
1079
|
-
.
|
|
1080
|
-
.subscribe((evt) => this.onShortcut(evt.shortcut));
|
|
1071
|
+
const filteredItems$ = toObservable(this.filteredItems);
|
|
1072
|
+
const itemsWithShortcuts$ = filteredItems$.pipe(map(getMenuItemsShortcuts));
|
|
1073
|
+
const shortcuts$ = itemsWithShortcuts$.pipe(map((items) => items.map((it) => it.shortcut)));
|
|
1074
|
+
const map$ = itemsWithShortcuts$.pipe(map((items) => this.getShortcutMap(items)));
|
|
1075
|
+
shortcuts$
|
|
1076
|
+
.pipe(switchMap((shortcuts) => this.shortcutService.listen(shortcuts)), withLatestFrom(map$), takeUntilDestroyed(this.destroyRef))
|
|
1077
|
+
.subscribe(([evt, map]) => this.onShortcut(evt.shortcut, map));
|
|
1081
1078
|
}
|
|
1082
1079
|
getShortcutMap(itemsWithShortcuts) {
|
|
1083
1080
|
const shortcutMap = {};
|
|
@@ -1086,10 +1083,10 @@ class RdtMenuBaseComponent {
|
|
|
1086
1083
|
});
|
|
1087
1084
|
return shortcutMap;
|
|
1088
1085
|
}
|
|
1089
|
-
onShortcut(shortcut) {
|
|
1090
|
-
const path =
|
|
1086
|
+
onShortcut(shortcut, map) {
|
|
1087
|
+
const path = map[shortcut.hotkeysValue];
|
|
1091
1088
|
if (!path) {
|
|
1092
|
-
console.warn(`Menu shortcut ${shortcut.hotkeysValue} was detected, but there is no path associated with it.`,
|
|
1089
|
+
console.warn(`Menu shortcut ${shortcut.hotkeysValue} was detected, but there is no path associated with it.`, map);
|
|
1093
1090
|
}
|
|
1094
1091
|
const last = path[path.length - 1];
|
|
1095
1092
|
const hasRoute = menuItemHasRoute(last);
|
|
@@ -1108,8 +1105,9 @@ class RdtMenuBaseComponent {
|
|
|
1108
1105
|
}
|
|
1109
1106
|
}
|
|
1110
1107
|
activateItemRecursively(path, src) {
|
|
1108
|
+
const shortcutMode = untracked(this.shortcutMode);
|
|
1111
1109
|
const children = [...path];
|
|
1112
|
-
if (
|
|
1110
|
+
if (shortcutMode === RdtMenuShortcutMode.OPEN_SUBMENU) {
|
|
1113
1111
|
const last = children[children.length - 1];
|
|
1114
1112
|
if (menuItemHasChildren(last) && last.items[0]) {
|
|
1115
1113
|
children.push(last.items[0]);
|
|
@@ -1117,12 +1115,12 @@ class RdtMenuBaseComponent {
|
|
|
1117
1115
|
}
|
|
1118
1116
|
const thisItem = children.shift();
|
|
1119
1117
|
if (children.length > 0) {
|
|
1120
|
-
this.expandedChild
|
|
1121
|
-
const overlay = this.children.find((child) => child.item === thisItem);
|
|
1118
|
+
this.expandedChild.set({ item: thisItem, src });
|
|
1119
|
+
const overlay = this.children.find((child) => untracked(child.item) === thisItem);
|
|
1122
1120
|
overlay.focusItemRecursively(children);
|
|
1123
1121
|
}
|
|
1124
1122
|
else {
|
|
1125
|
-
this.expandedChild
|
|
1123
|
+
this.expandedChild.set(null);
|
|
1126
1124
|
this.focusItem(thisItem);
|
|
1127
1125
|
}
|
|
1128
1126
|
}
|
|
@@ -1130,10 +1128,11 @@ class RdtMenuBaseComponent {
|
|
|
1130
1128
|
const rect = hitbox;
|
|
1131
1129
|
const x = event.clientX;
|
|
1132
1130
|
const y = event.clientY;
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
y
|
|
1131
|
+
const margin = untracked(this.hitboxMargin);
|
|
1132
|
+
return (x >= rect.left - margin &&
|
|
1133
|
+
x <= rect.right + margin &&
|
|
1134
|
+
y >= rect.top - margin &&
|
|
1135
|
+
y <= rect.bottom + margin);
|
|
1137
1136
|
}
|
|
1138
1137
|
getHitboxes() {
|
|
1139
1138
|
const boxes = this.getOpenMenuBoundingBoxes();
|
|
@@ -1151,7 +1150,7 @@ class RdtMenuBaseComponent {
|
|
|
1151
1150
|
return boxes;
|
|
1152
1151
|
}
|
|
1153
1152
|
getOpenMenuBoundingBoxesRec(overlay, boxes) {
|
|
1154
|
-
if (overlay.expanded) {
|
|
1153
|
+
if (overlay.expanded()) {
|
|
1155
1154
|
let someByClick = false;
|
|
1156
1155
|
overlay.children.forEach((child) => (someByClick ||= this.getOpenMenuBoundingBoxesRec(child, boxes)));
|
|
1157
1156
|
const fixed = someByClick || overlay.selfExpandSrc === RdtMenuExpandSource.Click;
|
|
@@ -1164,44 +1163,25 @@ class RdtMenuBaseComponent {
|
|
|
1164
1163
|
}
|
|
1165
1164
|
return false;
|
|
1166
1165
|
}
|
|
1167
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1168
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "
|
|
1166
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuBaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1167
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.1.7", type: RdtMenuBaseComponent, isStandalone: true, inputs: { preferredVerticalDir: { classPropertyName: "preferredVerticalDir", publicName: "preferredVerticalDir", isSignal: true, isRequired: false, transformFunction: null }, preferredHorizontalDir: { classPropertyName: "preferredHorizontalDir", publicName: "preferredHorizontalDir", isSignal: true, isRequired: false, transformFunction: null }, shortcutMode: { classPropertyName: "shortcutMode", publicName: "shortcutMode", isSignal: true, isRequired: false, transformFunction: null }, closeOnFocusOut: { classPropertyName: "closeOnFocusOut", publicName: "closeOnFocusOut", isSignal: true, isRequired: false, transformFunction: null }, openOnHover: { classPropertyName: "openOnHover", publicName: "openOnHover", isSignal: true, isRequired: false, transformFunction: null }, hitboxMargin: { classPropertyName: "hitboxMargin", publicName: "hitboxMargin", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "window:pointermove": "onPointerMove($event)", "document:click": "onDocumentClick($event)", "window:focusout": "checkActiveElement($event)" }, classAttribute: "rdt-menu-base" }, viewQueries: [{ propertyName: "children", predicate: RdtMenuOverlayComponent, descendants: true }, { propertyName: "focusableElements", predicate: ["focusableItem"], descendants: true }], ngImport: i0 });
|
|
1169
1168
|
}
|
|
1170
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1171
|
-
type: Directive
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
}], openOnHover: [{
|
|
1182
|
-
type: Input,
|
|
1183
|
-
args: [{ transform: booleanAttribute }]
|
|
1184
|
-
}], hitboxMargin: [{
|
|
1185
|
-
type: Input,
|
|
1186
|
-
args: [{ transform: numberAttribute }]
|
|
1187
|
-
}], children: [{
|
|
1169
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuBaseComponent, decorators: [{
|
|
1170
|
+
type: Directive,
|
|
1171
|
+
args: [{
|
|
1172
|
+
host: {
|
|
1173
|
+
class: 'rdt-menu-base',
|
|
1174
|
+
'(window:pointermove)': 'onPointerMove($event)',
|
|
1175
|
+
'(document:click)': 'onDocumentClick($event)',
|
|
1176
|
+
'(window:focusout)': 'checkActiveElement($event)',
|
|
1177
|
+
},
|
|
1178
|
+
}]
|
|
1179
|
+
}], ctorParameters: () => [], propDecorators: { children: [{
|
|
1188
1180
|
type: ViewChildren,
|
|
1189
1181
|
args: [RdtMenuOverlayComponent]
|
|
1190
1182
|
}], focusableElements: [{
|
|
1191
1183
|
type: ViewChildren,
|
|
1192
1184
|
args: ['focusableItem']
|
|
1193
|
-
}], classes: [{
|
|
1194
|
-
type: HostBinding,
|
|
1195
|
-
args: ['class']
|
|
1196
|
-
}], onPointerMove: [{
|
|
1197
|
-
type: HostListener,
|
|
1198
|
-
args: ['window:pointermove', ['$event']]
|
|
1199
|
-
}], checkActiveElement: [{
|
|
1200
|
-
type: HostListener,
|
|
1201
|
-
args: ['window:focusout', ['$event']]
|
|
1202
|
-
}], onDocumentClick: [{
|
|
1203
|
-
type: HostListener,
|
|
1204
|
-
args: ['document:click', ['$event']]
|
|
1205
1185
|
}] } });
|
|
1206
1186
|
|
|
1207
1187
|
class RdtMenuBarComponent extends RdtMenuBaseComponent {
|
|
@@ -1209,149 +1189,136 @@ class RdtMenuBarComponent extends RdtMenuBaseComponent {
|
|
|
1209
1189
|
get buttonContainer() {
|
|
1210
1190
|
return this.buttonContainerRef?.nativeElement;
|
|
1211
1191
|
}
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
}
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
this.filterItems();
|
|
1219
|
-
}
|
|
1220
|
-
_items;
|
|
1221
|
-
headerHeight = 0;
|
|
1222
|
-
footerHeight = 0;
|
|
1223
|
-
roleAttr = 'menubar';
|
|
1224
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtMenuBarComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1225
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: RdtMenuBarComponent, selector: "rdt-menu-bar", inputs: { items: "items", headerHeight: ["headerHeight", "headerHeight", numberAttribute], footerHeight: ["footerHeight", "footerHeight", numberAttribute] }, host: { properties: { "attr.role": "this.roleAttr" } }, providers: [
|
|
1192
|
+
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : []));
|
|
1193
|
+
allParsedItems = computed(() => parseMenuItems(this.items(), this.injector), ...(ngDevMode ? [{ debugName: "allParsedItems" }] : []));
|
|
1194
|
+
headerHeight = input(0, ...(ngDevMode ? [{ debugName: "headerHeight", transform: numberAttribute }] : [{ transform: numberAttribute }]));
|
|
1195
|
+
footerHeight = input(0, ...(ngDevMode ? [{ debugName: "footerHeight", transform: numberAttribute }] : [{ transform: numberAttribute }]));
|
|
1196
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuBarComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1197
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: RdtMenuBarComponent, isStandalone: false, selector: "rdt-menu-bar", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, headerHeight: { classPropertyName: "headerHeight", publicName: "headerHeight", isSignal: true, isRequired: false, transformFunction: null }, footerHeight: { classPropertyName: "footerHeight", publicName: "footerHeight", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "menubar" } }, providers: [
|
|
1226
1198
|
{
|
|
1227
1199
|
provide: RdtMenuBaseComponent,
|
|
1228
1200
|
useExisting: RdtMenuBarComponent,
|
|
1229
1201
|
},
|
|
1230
|
-
], viewQueries: [{ propertyName: "buttonContainerRef", first: true, predicate: ["buttonContainer"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<ul class=\"menu-bar-item-container\" role=\"presentation\" #buttonContainer>\r\n @for(item of
|
|
1202
|
+
], viewQueries: [{ propertyName: "buttonContainerRef", first: true, predicate: ["buttonContainer"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<ul class=\"menu-bar-item-container\" role=\"presentation\" #buttonContainer>\r\n @for(item of filteredItems(); track item; let i = $index) {\r\n <li\r\n class=\"menu-bar-item\"\r\n role=\"presentation\"\r\n rdtAnyRouteActive=\"menu-bar-item-route-active\"\r\n [watchedRoutes]=\"getChildRoutes(item)\"\r\n (rdtKeyListener)=\"onKeyDown(i, $event)\"\r\n #anchorEl\r\n >\r\n @if(!item.routerLink && !item.externalLink) {\r\n <button\r\n #focusableItem\r\n class=\"menu-bar-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n (pointerenter)=\"onItemPointerEnter(item)\"\r\n [attr.aria-haspopup]=\"item.items ? 'menu' : null\"\r\n [attr.aria-expanded]=\"item === expandedChild()?.item\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n {{ item.label }}\r\n\r\n <div class=\"menu-bar-item-right-content\">\r\n @if(item.shortcut) {\r\n <span class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n }\r\n <!-- TODO\r\n <rdt-icon\r\n *ngIf=\"item.items\"\r\n name=\"expand_more\"\r\n class=\"menu-bar-item-icon\"\r\n inverted\r\n />\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-bar-item-icon\"\r\n inverted\r\n />\r\n -->\r\n @if(item.items) {\r\n <span class=\"menu-bar-item-icon rdt-menu-icon-down\"></span>\r\n }\r\n </div>\r\n </button>\r\n }\r\n\r\n <ng-template #linkBody let-item>\r\n {{ item.label }}\r\n\r\n <div class=\"menu-bar-item-right-content\">\r\n @if(item.shortcut) {\r\n <span class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n }\r\n <!--\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-bar-item-icon\"\r\n inverted\r\n />\r\n --></div>\r\n </ng-template>\r\n\r\n @if(item.routerLink) {\r\n <a\r\n #focusableItem\r\n class=\"menu-bar-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [routerLink]=\"item.routerLink\"\r\n [target]=\"item.target!\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n } @if(item.externalLink) {\r\n <a\r\n #focusableItem\r\n class=\"menu-bar-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [href]=\"item.externalLink\"\r\n [target]=\"item.target\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n } @if (item.items) {\r\n <rdt-menu-overlay\r\n [item]=\"$any(item)\"\r\n [expanded]=\"item === expandedChild()?.item\"\r\n [autofocusItem]=\"autofocusSubmenuItem\"\r\n [preferredHorizontalDir]=\"preferredHorizontalDir()\"\r\n [preferredVerticalDir]=\"preferredVerticalDir()\"\r\n [level]=\"0\"\r\n [anchorElement]=\"anchorEl\"\r\n />\r\n }\r\n </li>\r\n }\r\n</ul>\r\n", styles: ["a.menu-bar-item-content,a.menu-item-content,button.menu-bar-item-content,button.menu-item-content{white-space:nowrap;appearance:none;text-decoration:none;box-sizing:border-box}.menu-item-right-content,.menu-bar-item-right-content{margin-left:auto;display:flex;align-items:center}.menu-item-shortcut,.menu-bar-item-shortcut{margin-left:2rem}.menu-item-icon,.menu-bar-item-icon{margin-left:.5rem;font-size:1.2rem}.dp3-menu-base ul{margin-bottom:0}.rdt-menu-root{margin-left:0}.rdt-menu-root.rdt-overlay-down{margin-top:var(--rdt-menu-overlay-margin-y)}.rdt-menu-root.rdt-overlay-up{margin-top:calc(-1 * var(--rdt-menu-overlay-margin-y))}.rdt-menu-sub.rdt-overlay-left{margin-left:calc(-1 * var(--rdt-menu-overlay-margin-x))}.rdt-menu-sub.rdt-overlay-right{margin-left:var(--rdt-menu-overlay-margin-x)}rdt-menu-bar{-webkit-user-select:none;user-select:none;pointer-events:none;padding:var(--rdt-menu-bar-padding)}.menu-bar-item-container{display:flex;list-style-type:none;margin-bottom:0;margin-top:0;margin-block-start:0;margin-block-end:0;padding-left:0}.menu-bar-item{pointer-events:all;margin:var(--rdt-menu-bar-item-margin);position:relative;display:flex;align-items:center;justify-content:center}.menu-bar-item.menu-bar-item-route-active .menu-bar-item-content{--rdt-menu-bar-item-background: var( --rdt-menu-bar-item-route-active-background );--rdt-menu-bar-item-text-color: var( --rdt-menu-bar-item-route-active-text-color );--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-route-active-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-route-active-outline)}.menu-bar-item [aria-expanded=true].menu-bar-item-content{--rdt-menu-bar-item-background: var( --rdt-menu-bar-item-expanded-background );--rdt-menu-bar-item-text-color: var( --rdt-menu-bar-item-expanded-text-color );--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-expanded-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-expanded-outline)}.menu-bar-item-content{cursor:pointer;display:flex;align-items:center;overflow:hidden;padding:var(--rdt-menu-bar-item-padding);border-radius:var(--rdt-menu-bar-item-border-radius);border:var(--rdt-menu-bar-item-border);background-color:var(--rdt-menu-bar-item-background);color:var(--rdt-menu-bar-item-text-color);font-weight:var(--rdt-menu-bar-item-font-weight);font-size:var(--rdt-menu-bar-item-font-size, inherit);outline:var(--rdt-menu-bar-item-outline)}.menu-bar-item-content:hover{--rdt-menu-bar-item-background: var(--rdt-menu-bar-item-hover-background);--rdt-menu-bar-item-text-color: var(--rdt-menu-bar-item-hover-text-color);--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-hover-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-hover-outline)}.menu-bar-item .menu-bar-item-content.focus-visible:focus,.menu-bar-item .menu-bar-item-content:focus-visible{--rdt-menu-bar-item-background: var(--rdt-menu-bar-item-focus-background);--rdt-menu-bar-item-text-color: var(--rdt-menu-bar-item-focus-text-color);--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-focus-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-focus-outline)}.menu-bar-item-icon.rdt-menu-icon-down{width:0;height:0;border-left:var(--rdt-menu-default-icon-size) solid transparent;border-right:var(--rdt-menu-default-icon-size) solid transparent;border-top:var(--rdt-menu-default-icon-size) solid var(--rdt-menu-bar-item-text-color)}\n"], dependencies: [{ kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i3.RdtAnyRouteActiveDirective, selector: "[rdtAnyRouteActive]", inputs: ["rdtAnyRouteActive", "watchedRoutes", "anyRouteActiveOptions", "ariaCurrentWhenActive"] }, { kind: "directive", type: i4.RdtKeyListenerDirective, selector: "[rdtKeyListener]", outputs: ["rdtKeyListener"] }, { kind: "component", type: RdtMenuOverlayComponent, selector: "rdt-menu-overlay", inputs: ["item", "level", "preferredHorizontalDir", "preferredVerticalDir", "expanded", "autofocusItem", "anchorElement"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
1231
1203
|
}
|
|
1232
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1204
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuBarComponent, decorators: [{
|
|
1233
1205
|
type: Component,
|
|
1234
1206
|
args: [{ selector: 'rdt-menu-bar', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
|
|
1235
1207
|
{
|
|
1236
1208
|
provide: RdtMenuBaseComponent,
|
|
1237
1209
|
useExisting: RdtMenuBarComponent,
|
|
1238
1210
|
},
|
|
1239
|
-
],
|
|
1211
|
+
], standalone: false, host: {
|
|
1212
|
+
role: 'menubar',
|
|
1213
|
+
}, template: "<ul class=\"menu-bar-item-container\" role=\"presentation\" #buttonContainer>\r\n @for(item of filteredItems(); track item; let i = $index) {\r\n <li\r\n class=\"menu-bar-item\"\r\n role=\"presentation\"\r\n rdtAnyRouteActive=\"menu-bar-item-route-active\"\r\n [watchedRoutes]=\"getChildRoutes(item)\"\r\n (rdtKeyListener)=\"onKeyDown(i, $event)\"\r\n #anchorEl\r\n >\r\n @if(!item.routerLink && !item.externalLink) {\r\n <button\r\n #focusableItem\r\n class=\"menu-bar-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n (pointerenter)=\"onItemPointerEnter(item)\"\r\n [attr.aria-haspopup]=\"item.items ? 'menu' : null\"\r\n [attr.aria-expanded]=\"item === expandedChild()?.item\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n {{ item.label }}\r\n\r\n <div class=\"menu-bar-item-right-content\">\r\n @if(item.shortcut) {\r\n <span class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n }\r\n <!-- TODO\r\n <rdt-icon\r\n *ngIf=\"item.items\"\r\n name=\"expand_more\"\r\n class=\"menu-bar-item-icon\"\r\n inverted\r\n />\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-bar-item-icon\"\r\n inverted\r\n />\r\n -->\r\n @if(item.items) {\r\n <span class=\"menu-bar-item-icon rdt-menu-icon-down\"></span>\r\n }\r\n </div>\r\n </button>\r\n }\r\n\r\n <ng-template #linkBody let-item>\r\n {{ item.label }}\r\n\r\n <div class=\"menu-bar-item-right-content\">\r\n @if(item.shortcut) {\r\n <span class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n }\r\n <!--\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-bar-item-icon\"\r\n inverted\r\n />\r\n --></div>\r\n </ng-template>\r\n\r\n @if(item.routerLink) {\r\n <a\r\n #focusableItem\r\n class=\"menu-bar-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [routerLink]=\"item.routerLink\"\r\n [target]=\"item.target!\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n } @if(item.externalLink) {\r\n <a\r\n #focusableItem\r\n class=\"menu-bar-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [href]=\"item.externalLink\"\r\n [target]=\"item.target\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n } @if (item.items) {\r\n <rdt-menu-overlay\r\n [item]=\"$any(item)\"\r\n [expanded]=\"item === expandedChild()?.item\"\r\n [autofocusItem]=\"autofocusSubmenuItem\"\r\n [preferredHorizontalDir]=\"preferredHorizontalDir()\"\r\n [preferredVerticalDir]=\"preferredVerticalDir()\"\r\n [level]=\"0\"\r\n [anchorElement]=\"anchorEl\"\r\n />\r\n }\r\n </li>\r\n }\r\n</ul>\r\n", styles: ["a.menu-bar-item-content,a.menu-item-content,button.menu-bar-item-content,button.menu-item-content{white-space:nowrap;appearance:none;text-decoration:none;box-sizing:border-box}.menu-item-right-content,.menu-bar-item-right-content{margin-left:auto;display:flex;align-items:center}.menu-item-shortcut,.menu-bar-item-shortcut{margin-left:2rem}.menu-item-icon,.menu-bar-item-icon{margin-left:.5rem;font-size:1.2rem}.dp3-menu-base ul{margin-bottom:0}.rdt-menu-root{margin-left:0}.rdt-menu-root.rdt-overlay-down{margin-top:var(--rdt-menu-overlay-margin-y)}.rdt-menu-root.rdt-overlay-up{margin-top:calc(-1 * var(--rdt-menu-overlay-margin-y))}.rdt-menu-sub.rdt-overlay-left{margin-left:calc(-1 * var(--rdt-menu-overlay-margin-x))}.rdt-menu-sub.rdt-overlay-right{margin-left:var(--rdt-menu-overlay-margin-x)}rdt-menu-bar{-webkit-user-select:none;user-select:none;pointer-events:none;padding:var(--rdt-menu-bar-padding)}.menu-bar-item-container{display:flex;list-style-type:none;margin-bottom:0;margin-top:0;margin-block-start:0;margin-block-end:0;padding-left:0}.menu-bar-item{pointer-events:all;margin:var(--rdt-menu-bar-item-margin);position:relative;display:flex;align-items:center;justify-content:center}.menu-bar-item.menu-bar-item-route-active .menu-bar-item-content{--rdt-menu-bar-item-background: var( --rdt-menu-bar-item-route-active-background );--rdt-menu-bar-item-text-color: var( --rdt-menu-bar-item-route-active-text-color );--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-route-active-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-route-active-outline)}.menu-bar-item [aria-expanded=true].menu-bar-item-content{--rdt-menu-bar-item-background: var( --rdt-menu-bar-item-expanded-background );--rdt-menu-bar-item-text-color: var( --rdt-menu-bar-item-expanded-text-color );--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-expanded-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-expanded-outline)}.menu-bar-item-content{cursor:pointer;display:flex;align-items:center;overflow:hidden;padding:var(--rdt-menu-bar-item-padding);border-radius:var(--rdt-menu-bar-item-border-radius);border:var(--rdt-menu-bar-item-border);background-color:var(--rdt-menu-bar-item-background);color:var(--rdt-menu-bar-item-text-color);font-weight:var(--rdt-menu-bar-item-font-weight);font-size:var(--rdt-menu-bar-item-font-size, inherit);outline:var(--rdt-menu-bar-item-outline)}.menu-bar-item-content:hover{--rdt-menu-bar-item-background: var(--rdt-menu-bar-item-hover-background);--rdt-menu-bar-item-text-color: var(--rdt-menu-bar-item-hover-text-color);--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-hover-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-hover-outline)}.menu-bar-item .menu-bar-item-content.focus-visible:focus,.menu-bar-item .menu-bar-item-content:focus-visible{--rdt-menu-bar-item-background: var(--rdt-menu-bar-item-focus-background);--rdt-menu-bar-item-text-color: var(--rdt-menu-bar-item-focus-text-color);--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-focus-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-focus-outline)}.menu-bar-item-icon.rdt-menu-icon-down{width:0;height:0;border-left:var(--rdt-menu-default-icon-size) solid transparent;border-right:var(--rdt-menu-default-icon-size) solid transparent;border-top:var(--rdt-menu-default-icon-size) solid var(--rdt-menu-bar-item-text-color)}\n"] }]
|
|
1240
1214
|
}], propDecorators: { buttonContainerRef: [{
|
|
1241
1215
|
type: ViewChild,
|
|
1242
1216
|
args: ['buttonContainer', { static: true }]
|
|
1243
|
-
}], items: [{
|
|
1244
|
-
type: Input
|
|
1245
|
-
}], headerHeight: [{
|
|
1246
|
-
type: Input,
|
|
1247
|
-
args: [{ transform: numberAttribute }]
|
|
1248
|
-
}], footerHeight: [{
|
|
1249
|
-
type: Input,
|
|
1250
|
-
args: [{ transform: numberAttribute }]
|
|
1251
|
-
}], roleAttr: [{
|
|
1252
|
-
type: HostBinding,
|
|
1253
|
-
args: ['attr.role']
|
|
1254
1217
|
}] } });
|
|
1255
1218
|
|
|
1256
1219
|
class RdtMenuComponent extends RdtMenuBaseComponent {
|
|
1257
1220
|
buttonClass = inject(RDT_BUTTON_BASE_PROVIDER);
|
|
1258
|
-
trigger;
|
|
1259
|
-
dataTestId = '';
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
set items(value) {
|
|
1264
|
-
this._items = value;
|
|
1221
|
+
trigger = input.required(...(ngDevMode ? [{ debugName: "trigger" }] : []));
|
|
1222
|
+
dataTestId = input('', ...(ngDevMode ? [{ debugName: "dataTestId" }] : []));
|
|
1223
|
+
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : []));
|
|
1224
|
+
allParsedItems = computed(() => {
|
|
1225
|
+
const items = this.items();
|
|
1265
1226
|
const wrapper = {
|
|
1266
1227
|
label: '',
|
|
1267
1228
|
icon: '',
|
|
1268
|
-
items:
|
|
1229
|
+
items: items,
|
|
1269
1230
|
};
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
}
|
|
1273
|
-
_items;
|
|
1231
|
+
return parseMenuItems([wrapper], this.injector);
|
|
1232
|
+
}, ...(ngDevMode ? [{ debugName: "allParsedItems" }] : []));
|
|
1274
1233
|
focusableElements = new QueryList();
|
|
1275
1234
|
get buttonContainer() {
|
|
1276
|
-
return this.anchorElement ?? undefined;
|
|
1235
|
+
return this.anchorElement() ?? undefined;
|
|
1277
1236
|
}
|
|
1278
1237
|
get parsedItem() {
|
|
1279
|
-
return this.
|
|
1238
|
+
return this.filteredItems()[0];
|
|
1280
1239
|
}
|
|
1281
1240
|
get anchorElement() {
|
|
1282
|
-
return this.trigger.anchorElement;
|
|
1241
|
+
return this.trigger().anchorElement;
|
|
1283
1242
|
}
|
|
1284
|
-
|
|
1285
|
-
super
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1243
|
+
constructor() {
|
|
1244
|
+
super();
|
|
1245
|
+
afterNextRender(() => {
|
|
1246
|
+
this.listenPointerOver();
|
|
1247
|
+
this.updateFocusableElements();
|
|
1248
|
+
});
|
|
1249
|
+
this.subscribeClicks();
|
|
1250
|
+
}
|
|
1251
|
+
triggerTabIndexEffect = effect(() => {
|
|
1252
|
+
const trigger = this.trigger();
|
|
1253
|
+
trigger.tabIndex.set(0);
|
|
1254
|
+
}, ...(ngDevMode ? [{ debugName: "triggerTabIndexEffect" }] : []));
|
|
1255
|
+
triggerDataTestIdEffect = effect(() => {
|
|
1256
|
+
const trigger = this.trigger();
|
|
1257
|
+
const dataTestId = this.dataTestId();
|
|
1258
|
+
trigger.dataTestId.set(dataTestId);
|
|
1259
|
+
}, ...(ngDevMode ? [{ debugName: "triggerDataTestIdEffect" }] : []));
|
|
1260
|
+
triggerAriaEffect = effect(() => {
|
|
1261
|
+
const trigger = this.trigger();
|
|
1262
|
+
const expandedChild = this.expandedChild();
|
|
1263
|
+
trigger.aria.set({
|
|
1264
|
+
role: 'menuitem',
|
|
1265
|
+
'aria-haspopup': 'true',
|
|
1266
|
+
'aria-expanded': expandedChild?.item === this.parsedItem,
|
|
1267
|
+
});
|
|
1268
|
+
}, ...(ngDevMode ? [{ debugName: "triggerAriaEffect" }] : []));
|
|
1269
|
+
subscribeClicks() {
|
|
1270
|
+
toObservable(this.trigger)
|
|
1271
|
+
.pipe(switchMap((trigger) => trigger.click$), takeUntilDestroyed(this.destroyRef))
|
|
1272
|
+
.subscribe(() => this.toggle());
|
|
1303
1273
|
}
|
|
1304
1274
|
toggle() {
|
|
1305
1275
|
this.onItemClick(this.parsedItem);
|
|
1306
|
-
this.cd.markForCheck();
|
|
1307
1276
|
}
|
|
1308
1277
|
listenPointerOver() {
|
|
1309
|
-
const target = this.anchorElement;
|
|
1278
|
+
const target = this.anchorElement();
|
|
1310
1279
|
const listener = this.renderer.listen(target, 'pointerover', (event) => {
|
|
1311
1280
|
this.onItemPointerEnter(this.parsedItem);
|
|
1312
1281
|
this.cd.markForCheck();
|
|
1313
1282
|
});
|
|
1314
1283
|
this.destroyRef.onDestroy(() => listener());
|
|
1315
1284
|
}
|
|
1316
|
-
|
|
1317
|
-
|
|
1285
|
+
updateFocusableElements() {
|
|
1286
|
+
const anchor = this.anchorElement();
|
|
1287
|
+
if (anchor) {
|
|
1288
|
+
this.focusableElements.reset([{ nativeElement: anchor }]);
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1292
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: RdtMenuComponent, isStandalone: false, selector: "rdt-menu", inputs: { trigger: { classPropertyName: "trigger", publicName: "trigger", isSignal: true, isRequired: true, transformFunction: null }, dataTestId: { classPropertyName: "dataTestId", publicName: "dataTestId", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null } }, providers: [
|
|
1318
1293
|
{
|
|
1319
1294
|
provide: RdtMenuBaseComponent,
|
|
1320
1295
|
useExisting: RdtMenuComponent,
|
|
1321
1296
|
},
|
|
1322
|
-
], usesInheritance: true, ngImport: i0, template: "<rdt-menu-overlay\r\n
|
|
1297
|
+
], usesInheritance: true, ngImport: i0, template: "@if (parsedItem) {\r\n<rdt-menu-overlay\r\n [anchorElement]=\"anchorElement()\"\r\n [item]=\"$any(parsedItem)\"\r\n [expanded]=\"expandedChild()?.item === parsedItem\"\r\n [autofocusItem]=\"autofocusSubmenuItem\"\r\n [preferredHorizontalDir]=\"preferredHorizontalDir()\"\r\n [preferredVerticalDir]=\"preferredVerticalDir()\"\r\n [level]=\"0\"\r\n/>\r\n}\r\n", styles: ["a.menu-bar-item-content,a.menu-item-content,button.menu-bar-item-content,button.menu-item-content{white-space:nowrap;appearance:none;text-decoration:none;box-sizing:border-box}.menu-item-right-content,.menu-bar-item-right-content{margin-left:auto;display:flex;align-items:center}.menu-item-shortcut,.menu-bar-item-shortcut{margin-left:2rem}.menu-item-icon,.menu-bar-item-icon{margin-left:.5rem;font-size:1.2rem}.dp3-menu-base ul{margin-bottom:0}.rdt-menu-root{margin-left:0}.rdt-menu-root.rdt-overlay-down{margin-top:var(--rdt-menu-overlay-margin-y)}.rdt-menu-root.rdt-overlay-up{margin-top:calc(-1 * var(--rdt-menu-overlay-margin-y))}.rdt-menu-sub.rdt-overlay-left{margin-left:calc(-1 * var(--rdt-menu-overlay-margin-x))}.rdt-menu-sub.rdt-overlay-right{margin-left:var(--rdt-menu-overlay-margin-x)}rdt-menu{display:block;position:relative}\n"], dependencies: [{ kind: "component", type: RdtMenuOverlayComponent, selector: "rdt-menu-overlay", inputs: ["item", "level", "preferredHorizontalDir", "preferredVerticalDir", "expanded", "autofocusItem", "anchorElement"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
1323
1298
|
}
|
|
1324
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1299
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuComponent, decorators: [{
|
|
1325
1300
|
type: Component,
|
|
1326
1301
|
args: [{ selector: 'rdt-menu', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
|
|
1327
1302
|
{
|
|
1328
1303
|
provide: RdtMenuBaseComponent,
|
|
1329
1304
|
useExisting: RdtMenuComponent,
|
|
1330
1305
|
},
|
|
1331
|
-
], template: "<rdt-menu-overlay\r\n
|
|
1332
|
-
}],
|
|
1333
|
-
type: Input,
|
|
1334
|
-
args: [{ required: true }]
|
|
1335
|
-
}], dataTestId: [{
|
|
1336
|
-
type: Input
|
|
1337
|
-
}], items: [{
|
|
1338
|
-
type: Input,
|
|
1339
|
-
args: [{ required: true }]
|
|
1340
|
-
}] } });
|
|
1306
|
+
], standalone: false, template: "@if (parsedItem) {\r\n<rdt-menu-overlay\r\n [anchorElement]=\"anchorElement()\"\r\n [item]=\"$any(parsedItem)\"\r\n [expanded]=\"expandedChild()?.item === parsedItem\"\r\n [autofocusItem]=\"autofocusSubmenuItem\"\r\n [preferredHorizontalDir]=\"preferredHorizontalDir()\"\r\n [preferredVerticalDir]=\"preferredVerticalDir()\"\r\n [level]=\"0\"\r\n/>\r\n}\r\n", styles: ["a.menu-bar-item-content,a.menu-item-content,button.menu-bar-item-content,button.menu-item-content{white-space:nowrap;appearance:none;text-decoration:none;box-sizing:border-box}.menu-item-right-content,.menu-bar-item-right-content{margin-left:auto;display:flex;align-items:center}.menu-item-shortcut,.menu-bar-item-shortcut{margin-left:2rem}.menu-item-icon,.menu-bar-item-icon{margin-left:.5rem;font-size:1.2rem}.dp3-menu-base ul{margin-bottom:0}.rdt-menu-root{margin-left:0}.rdt-menu-root.rdt-overlay-down{margin-top:var(--rdt-menu-overlay-margin-y)}.rdt-menu-root.rdt-overlay-up{margin-top:calc(-1 * var(--rdt-menu-overlay-margin-y))}.rdt-menu-sub.rdt-overlay-left{margin-left:calc(-1 * var(--rdt-menu-overlay-margin-x))}.rdt-menu-sub.rdt-overlay-right{margin-left:var(--rdt-menu-overlay-margin-x)}rdt-menu{display:block;position:relative}\n"] }]
|
|
1307
|
+
}], ctorParameters: () => [] });
|
|
1341
1308
|
|
|
1342
1309
|
class RdtMenuModule {
|
|
1343
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1344
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "
|
|
1310
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1311
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuModule, declarations: [RdtMenuOverlayComponent,
|
|
1345
1312
|
RdtMenuComponent,
|
|
1346
1313
|
RdtMenuBarComponent], imports: [CommonModule,
|
|
1347
1314
|
RouterModule,
|
|
1348
1315
|
RdtAnyRouteActiveDirective,
|
|
1349
1316
|
RdtKeyListenerDirective,
|
|
1350
1317
|
RdtButtonOutletDirective], exports: [RdtMenuComponent, RdtMenuBarComponent] });
|
|
1351
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "
|
|
1318
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuModule, imports: [CommonModule,
|
|
1352
1319
|
RouterModule] });
|
|
1353
1320
|
}
|
|
1354
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1321
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuModule, decorators: [{
|
|
1355
1322
|
type: NgModule,
|
|
1356
1323
|
args: [{
|
|
1357
1324
|
imports: [
|