@ngrdt/menu 0.0.17 → 0.0.19
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/README.md +160 -160
- package/fesm2022/ngrdt-menu.mjs +324 -358
- 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,12 @@ class RdtMenuBaseComponent {
|
|
|
1012
1009
|
}
|
|
1013
1010
|
// Closes menu if user navigates outside it using Tab.
|
|
1014
1011
|
checkActiveElement(event) {
|
|
1015
|
-
|
|
1016
|
-
|
|
1012
|
+
const closeOnFocusOut = untracked(this.closeOnFocusOut);
|
|
1013
|
+
if (closeOnFocusOut && !this.openOnHover) {
|
|
1017
1014
|
const thisEl = this.elRef.nativeElement;
|
|
1018
1015
|
const target = event.relatedTarget;
|
|
1019
1016
|
if (!(target instanceof HTMLElement) || !thisEl.contains(target)) {
|
|
1020
|
-
this.expandedChild
|
|
1017
|
+
this.expandedChild.set(null);
|
|
1021
1018
|
}
|
|
1022
1019
|
}
|
|
1023
1020
|
}
|
|
@@ -1070,14 +1067,13 @@ class RdtMenuBaseComponent {
|
|
|
1070
1067
|
});
|
|
1071
1068
|
}
|
|
1072
1069
|
listenShortcuts() {
|
|
1073
|
-
const
|
|
1074
|
-
const
|
|
1075
|
-
|
|
1076
|
-
this.
|
|
1077
|
-
|
|
1078
|
-
.listen(shortcuts)
|
|
1079
|
-
.
|
|
1080
|
-
.subscribe((evt) => this.onShortcut(evt.shortcut));
|
|
1070
|
+
const filteredItems$ = toObservable(this.filteredItems);
|
|
1071
|
+
const itemsWithShortcuts$ = filteredItems$.pipe(map(getMenuItemsShortcuts));
|
|
1072
|
+
const shortcuts$ = itemsWithShortcuts$.pipe(map((items) => items.map((it) => it.shortcut)));
|
|
1073
|
+
const map$ = itemsWithShortcuts$.pipe(map((items) => this.getShortcutMap(items)));
|
|
1074
|
+
shortcuts$
|
|
1075
|
+
.pipe(switchMap((shortcuts) => this.shortcutService.listen(shortcuts)), withLatestFrom(map$), takeUntilDestroyed(this.destroyRef))
|
|
1076
|
+
.subscribe(([evt, map]) => this.onShortcut(evt.shortcut, map));
|
|
1081
1077
|
}
|
|
1082
1078
|
getShortcutMap(itemsWithShortcuts) {
|
|
1083
1079
|
const shortcutMap = {};
|
|
@@ -1086,10 +1082,10 @@ class RdtMenuBaseComponent {
|
|
|
1086
1082
|
});
|
|
1087
1083
|
return shortcutMap;
|
|
1088
1084
|
}
|
|
1089
|
-
onShortcut(shortcut) {
|
|
1090
|
-
const path =
|
|
1085
|
+
onShortcut(shortcut, map) {
|
|
1086
|
+
const path = map[shortcut.hotkeysValue];
|
|
1091
1087
|
if (!path) {
|
|
1092
|
-
console.warn(`Menu shortcut ${shortcut.hotkeysValue} was detected, but there is no path associated with it.`,
|
|
1088
|
+
console.warn(`Menu shortcut ${shortcut.hotkeysValue} was detected, but there is no path associated with it.`, map);
|
|
1093
1089
|
}
|
|
1094
1090
|
const last = path[path.length - 1];
|
|
1095
1091
|
const hasRoute = menuItemHasRoute(last);
|
|
@@ -1108,8 +1104,9 @@ class RdtMenuBaseComponent {
|
|
|
1108
1104
|
}
|
|
1109
1105
|
}
|
|
1110
1106
|
activateItemRecursively(path, src) {
|
|
1107
|
+
const shortcutMode = untracked(this.shortcutMode);
|
|
1111
1108
|
const children = [...path];
|
|
1112
|
-
if (
|
|
1109
|
+
if (shortcutMode === RdtMenuShortcutMode.OPEN_SUBMENU) {
|
|
1113
1110
|
const last = children[children.length - 1];
|
|
1114
1111
|
if (menuItemHasChildren(last) && last.items[0]) {
|
|
1115
1112
|
children.push(last.items[0]);
|
|
@@ -1117,12 +1114,12 @@ class RdtMenuBaseComponent {
|
|
|
1117
1114
|
}
|
|
1118
1115
|
const thisItem = children.shift();
|
|
1119
1116
|
if (children.length > 0) {
|
|
1120
|
-
this.expandedChild
|
|
1121
|
-
const overlay = this.children.find((child) => child.item === thisItem);
|
|
1117
|
+
this.expandedChild.set({ item: thisItem, src });
|
|
1118
|
+
const overlay = this.children.find((child) => untracked(child.item) === thisItem);
|
|
1122
1119
|
overlay.focusItemRecursively(children);
|
|
1123
1120
|
}
|
|
1124
1121
|
else {
|
|
1125
|
-
this.expandedChild
|
|
1122
|
+
this.expandedChild.set(null);
|
|
1126
1123
|
this.focusItem(thisItem);
|
|
1127
1124
|
}
|
|
1128
1125
|
}
|
|
@@ -1130,10 +1127,11 @@ class RdtMenuBaseComponent {
|
|
|
1130
1127
|
const rect = hitbox;
|
|
1131
1128
|
const x = event.clientX;
|
|
1132
1129
|
const y = event.clientY;
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
y
|
|
1130
|
+
const margin = untracked(this.hitboxMargin);
|
|
1131
|
+
return (x >= rect.left - margin &&
|
|
1132
|
+
x <= rect.right + margin &&
|
|
1133
|
+
y >= rect.top - margin &&
|
|
1134
|
+
y <= rect.bottom + margin);
|
|
1137
1135
|
}
|
|
1138
1136
|
getHitboxes() {
|
|
1139
1137
|
const boxes = this.getOpenMenuBoundingBoxes();
|
|
@@ -1151,7 +1149,7 @@ class RdtMenuBaseComponent {
|
|
|
1151
1149
|
return boxes;
|
|
1152
1150
|
}
|
|
1153
1151
|
getOpenMenuBoundingBoxesRec(overlay, boxes) {
|
|
1154
|
-
if (overlay.expanded) {
|
|
1152
|
+
if (overlay.expanded()) {
|
|
1155
1153
|
let someByClick = false;
|
|
1156
1154
|
overlay.children.forEach((child) => (someByClick ||= this.getOpenMenuBoundingBoxesRec(child, boxes)));
|
|
1157
1155
|
const fixed = someByClick || overlay.selfExpandSrc === RdtMenuExpandSource.Click;
|
|
@@ -1164,44 +1162,25 @@ class RdtMenuBaseComponent {
|
|
|
1164
1162
|
}
|
|
1165
1163
|
return false;
|
|
1166
1164
|
}
|
|
1167
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1168
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "
|
|
1165
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuBaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1166
|
+
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
1167
|
}
|
|
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: [{
|
|
1168
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuBaseComponent, decorators: [{
|
|
1169
|
+
type: Directive,
|
|
1170
|
+
args: [{
|
|
1171
|
+
host: {
|
|
1172
|
+
class: 'rdt-menu-base',
|
|
1173
|
+
'(window:pointermove)': 'onPointerMove($event)',
|
|
1174
|
+
'(document:click)': 'onDocumentClick($event)',
|
|
1175
|
+
'(window:focusout)': 'checkActiveElement($event)',
|
|
1176
|
+
},
|
|
1177
|
+
}]
|
|
1178
|
+
}], ctorParameters: () => [], propDecorators: { children: [{
|
|
1188
1179
|
type: ViewChildren,
|
|
1189
1180
|
args: [RdtMenuOverlayComponent]
|
|
1190
1181
|
}], focusableElements: [{
|
|
1191
1182
|
type: ViewChildren,
|
|
1192
1183
|
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
1184
|
}] } });
|
|
1206
1185
|
|
|
1207
1186
|
class RdtMenuBarComponent extends RdtMenuBaseComponent {
|
|
@@ -1209,149 +1188,136 @@ class RdtMenuBarComponent extends RdtMenuBaseComponent {
|
|
|
1209
1188
|
get buttonContainer() {
|
|
1210
1189
|
return this.buttonContainerRef?.nativeElement;
|
|
1211
1190
|
}
|
|
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: [
|
|
1191
|
+
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : []));
|
|
1192
|
+
allParsedItems = computed(() => parseMenuItems(this.items(), this.injector), ...(ngDevMode ? [{ debugName: "allParsedItems" }] : []));
|
|
1193
|
+
headerHeight = input(0, ...(ngDevMode ? [{ debugName: "headerHeight", transform: numberAttribute }] : [{ transform: numberAttribute }]));
|
|
1194
|
+
footerHeight = input(0, ...(ngDevMode ? [{ debugName: "footerHeight", transform: numberAttribute }] : [{ transform: numberAttribute }]));
|
|
1195
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuBarComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1196
|
+
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
1197
|
{
|
|
1227
1198
|
provide: RdtMenuBaseComponent,
|
|
1228
1199
|
useExisting: RdtMenuBarComponent,
|
|
1229
1200
|
},
|
|
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
|
|
1201
|
+
], 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
1202
|
}
|
|
1232
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1203
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuBarComponent, decorators: [{
|
|
1233
1204
|
type: Component,
|
|
1234
1205
|
args: [{ selector: 'rdt-menu-bar', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
|
|
1235
1206
|
{
|
|
1236
1207
|
provide: RdtMenuBaseComponent,
|
|
1237
1208
|
useExisting: RdtMenuBarComponent,
|
|
1238
1209
|
},
|
|
1239
|
-
],
|
|
1210
|
+
], standalone: false, host: {
|
|
1211
|
+
role: 'menubar',
|
|
1212
|
+
}, 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
1213
|
}], propDecorators: { buttonContainerRef: [{
|
|
1241
1214
|
type: ViewChild,
|
|
1242
1215
|
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
1216
|
}] } });
|
|
1255
1217
|
|
|
1256
1218
|
class RdtMenuComponent extends RdtMenuBaseComponent {
|
|
1257
1219
|
buttonClass = inject(RDT_BUTTON_BASE_PROVIDER);
|
|
1258
|
-
trigger;
|
|
1259
|
-
dataTestId = '';
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
set items(value) {
|
|
1264
|
-
this._items = value;
|
|
1220
|
+
trigger = input.required(...(ngDevMode ? [{ debugName: "trigger" }] : []));
|
|
1221
|
+
dataTestId = input('', ...(ngDevMode ? [{ debugName: "dataTestId" }] : []));
|
|
1222
|
+
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : []));
|
|
1223
|
+
allParsedItems = computed(() => {
|
|
1224
|
+
const items = this.items();
|
|
1265
1225
|
const wrapper = {
|
|
1266
1226
|
label: '',
|
|
1267
1227
|
icon: '',
|
|
1268
|
-
items:
|
|
1228
|
+
items: items,
|
|
1269
1229
|
};
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
}
|
|
1273
|
-
_items;
|
|
1230
|
+
return parseMenuItems([wrapper], this.injector);
|
|
1231
|
+
}, ...(ngDevMode ? [{ debugName: "allParsedItems" }] : []));
|
|
1274
1232
|
focusableElements = new QueryList();
|
|
1275
1233
|
get buttonContainer() {
|
|
1276
|
-
return this.anchorElement ?? undefined;
|
|
1234
|
+
return this.anchorElement() ?? undefined;
|
|
1277
1235
|
}
|
|
1278
1236
|
get parsedItem() {
|
|
1279
|
-
return this.
|
|
1237
|
+
return this.filteredItems()[0];
|
|
1280
1238
|
}
|
|
1281
1239
|
get anchorElement() {
|
|
1282
|
-
return this.trigger.anchorElement;
|
|
1240
|
+
return this.trigger().anchorElement;
|
|
1283
1241
|
}
|
|
1284
|
-
|
|
1285
|
-
super
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1242
|
+
constructor() {
|
|
1243
|
+
super();
|
|
1244
|
+
afterNextRender(() => {
|
|
1245
|
+
this.listenPointerOver();
|
|
1246
|
+
this.updateFocusableElements();
|
|
1247
|
+
});
|
|
1248
|
+
this.subscribeClicks();
|
|
1249
|
+
}
|
|
1250
|
+
triggerTabIndexEffect = effect(() => {
|
|
1251
|
+
const trigger = this.trigger();
|
|
1252
|
+
trigger.tabIndex.set(0);
|
|
1253
|
+
}, ...(ngDevMode ? [{ debugName: "triggerTabIndexEffect" }] : []));
|
|
1254
|
+
triggerDataTestIdEffect = effect(() => {
|
|
1255
|
+
const trigger = this.trigger();
|
|
1256
|
+
const dataTestId = this.dataTestId();
|
|
1257
|
+
trigger.dataTestId.set(dataTestId);
|
|
1258
|
+
}, ...(ngDevMode ? [{ debugName: "triggerDataTestIdEffect" }] : []));
|
|
1259
|
+
triggerAriaEffect = effect(() => {
|
|
1260
|
+
const trigger = this.trigger();
|
|
1261
|
+
const expandedChild = this.expandedChild();
|
|
1262
|
+
trigger.aria.set({
|
|
1263
|
+
role: 'menuitem',
|
|
1264
|
+
'aria-haspopup': 'true',
|
|
1265
|
+
'aria-expanded': expandedChild?.item === this.parsedItem,
|
|
1266
|
+
});
|
|
1267
|
+
}, ...(ngDevMode ? [{ debugName: "triggerAriaEffect" }] : []));
|
|
1268
|
+
subscribeClicks() {
|
|
1269
|
+
toObservable(this.trigger)
|
|
1270
|
+
.pipe(switchMap((trigger) => trigger.click$), takeUntilDestroyed(this.destroyRef))
|
|
1271
|
+
.subscribe(() => this.toggle());
|
|
1303
1272
|
}
|
|
1304
1273
|
toggle() {
|
|
1305
1274
|
this.onItemClick(this.parsedItem);
|
|
1306
|
-
this.cd.markForCheck();
|
|
1307
1275
|
}
|
|
1308
1276
|
listenPointerOver() {
|
|
1309
|
-
const target = this.anchorElement;
|
|
1277
|
+
const target = this.anchorElement();
|
|
1310
1278
|
const listener = this.renderer.listen(target, 'pointerover', (event) => {
|
|
1311
1279
|
this.onItemPointerEnter(this.parsedItem);
|
|
1312
1280
|
this.cd.markForCheck();
|
|
1313
1281
|
});
|
|
1314
1282
|
this.destroyRef.onDestroy(() => listener());
|
|
1315
1283
|
}
|
|
1316
|
-
|
|
1317
|
-
|
|
1284
|
+
updateFocusableElements() {
|
|
1285
|
+
const anchor = this.anchorElement();
|
|
1286
|
+
if (anchor) {
|
|
1287
|
+
this.focusableElements.reset([{ nativeElement: anchor }]);
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1291
|
+
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
1292
|
{
|
|
1319
1293
|
provide: RdtMenuBaseComponent,
|
|
1320
1294
|
useExisting: RdtMenuComponent,
|
|
1321
1295
|
},
|
|
1322
|
-
], usesInheritance: true, ngImport: i0, template: "<rdt-menu-overlay\r\n
|
|
1296
|
+
], 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
1297
|
}
|
|
1324
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1298
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuComponent, decorators: [{
|
|
1325
1299
|
type: Component,
|
|
1326
1300
|
args: [{ selector: 'rdt-menu', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
|
|
1327
1301
|
{
|
|
1328
1302
|
provide: RdtMenuBaseComponent,
|
|
1329
1303
|
useExisting: RdtMenuComponent,
|
|
1330
1304
|
},
|
|
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
|
-
}] } });
|
|
1305
|
+
], 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"] }]
|
|
1306
|
+
}], ctorParameters: () => [] });
|
|
1341
1307
|
|
|
1342
1308
|
class RdtMenuModule {
|
|
1343
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1344
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "
|
|
1309
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1310
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuModule, declarations: [RdtMenuOverlayComponent,
|
|
1345
1311
|
RdtMenuComponent,
|
|
1346
1312
|
RdtMenuBarComponent], imports: [CommonModule,
|
|
1347
1313
|
RouterModule,
|
|
1348
1314
|
RdtAnyRouteActiveDirective,
|
|
1349
1315
|
RdtKeyListenerDirective,
|
|
1350
1316
|
RdtButtonOutletDirective], exports: [RdtMenuComponent, RdtMenuBarComponent] });
|
|
1351
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "
|
|
1317
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuModule, imports: [CommonModule,
|
|
1352
1318
|
RouterModule] });
|
|
1353
1319
|
}
|
|
1354
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1320
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuModule, decorators: [{
|
|
1355
1321
|
type: NgModule,
|
|
1356
1322
|
args: [{
|
|
1357
1323
|
imports: [
|