ng-primitives 0.121.0 → 0.123.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/fesm2022/ng-primitives-combobox.mjs +23 -4
  2. package/fesm2022/ng-primitives-combobox.mjs.map +1 -1
  3. package/fesm2022/ng-primitives-context-menu.mjs +9 -3
  4. package/fesm2022/ng-primitives-context-menu.mjs.map +1 -1
  5. package/fesm2022/ng-primitives-date-picker.mjs +1 -1
  6. package/fesm2022/ng-primitives-date-picker.mjs.map +1 -1
  7. package/fesm2022/ng-primitives-internal.mjs +184 -3
  8. package/fesm2022/ng-primitives-internal.mjs.map +1 -1
  9. package/fesm2022/ng-primitives-menu.mjs +139 -21
  10. package/fesm2022/ng-primitives-menu.mjs.map +1 -1
  11. package/fesm2022/ng-primitives-navigation-menu.mjs +6 -2
  12. package/fesm2022/ng-primitives-navigation-menu.mjs.map +1 -1
  13. package/fesm2022/ng-primitives-popover.mjs +8 -3
  14. package/fesm2022/ng-primitives-popover.mjs.map +1 -1
  15. package/fesm2022/ng-primitives-portal.mjs +74 -12
  16. package/fesm2022/ng-primitives-portal.mjs.map +1 -1
  17. package/fesm2022/ng-primitives-select.mjs +17 -3
  18. package/fesm2022/ng-primitives-select.mjs.map +1 -1
  19. package/fesm2022/ng-primitives-toast.mjs +15 -12
  20. package/fesm2022/ng-primitives-toast.mjs.map +1 -1
  21. package/fesm2022/ng-primitives-tooltip.mjs +28 -123
  22. package/fesm2022/ng-primitives-tooltip.mjs.map +1 -1
  23. package/fesm2022/ng-primitives-utils.mjs +40 -23
  24. package/fesm2022/ng-primitives-utils.mjs.map +1 -1
  25. package/package.json +1 -1
  26. package/schematics/ng-generate/templates/toggle-group/toggle-group.__fileSuffix@dasherize__.ts.template +2 -2
  27. package/types/ng-primitives-combobox.d.ts +11 -1
  28. package/types/ng-primitives-context-menu.d.ts +16 -3
  29. package/types/ng-primitives-internal.d.ts +95 -3
  30. package/types/ng-primitives-menu.d.ts +58 -11
  31. package/types/ng-primitives-navigation-menu.d.ts +22 -9
  32. package/types/ng-primitives-popover.d.ts +9 -2
  33. package/types/ng-primitives-portal.d.ts +31 -1
  34. package/types/ng-primitives-select.d.ts +9 -2
  35. package/types/ng-primitives-toast.d.ts +4 -3
  36. package/types/ng-primitives-tooltip.d.ts +24 -17
  37. package/types/ng-primitives-utils.d.ts +12 -9
@@ -4,13 +4,13 @@ import * as i0 from '@angular/core';
4
4
  import { InjectionToken, inject, Injector, ViewContainerRef, signal, computed, effect, input, booleanAttribute, Directive, output, numberAttribute } from '@angular/core';
5
5
  import { ngpRovingFocusItem, provideRovingFocusItemState, ngpRovingFocusGroup, provideRovingFocusGroupState } from 'ng-primitives/roving-focus';
6
6
  import { ngpButton } from 'ng-primitives/button';
7
- import { injectElementRef } from 'ng-primitives/internal';
7
+ import { injectElementRef, createHoverBridge } from 'ng-primitives/internal';
8
8
  import { createPrimitive, controlled, attrBinding, dataBinding, listener, deprecatedSetter, styleBinding, emitter } from 'ng-primitives/state';
9
9
  import { Directionality } from '@angular/cdk/bidi';
10
10
  import { ngpFocusTrap, provideFocusTrapState } from 'ng-primitives/focus-trap';
11
11
  import { Subject } from 'rxjs';
12
+ import { injectDisposables, safeTakeUntilDestroyed } from 'ng-primitives/utils';
12
13
  import { FocusMonitor } from '@angular/cdk/a11y';
13
- import { safeTakeUntilDestroyed } from 'ng-primitives/utils';
14
14
 
15
15
  const defaultMenuConfig = {
16
16
  offset: 4,
@@ -47,11 +47,12 @@ function injectMenuConfig() {
47
47
  return inject(NgpMenuConfigToken, { optional: true }) ?? defaultMenuConfig;
48
48
  }
49
49
 
50
- const [NgpMenuTriggerStateToken, ngpMenuTrigger, _injectMenuTriggerState, provideMenuTriggerState,] = createPrimitive('NgpMenuTrigger', ({ disabled: _disabled = signal(false), menu: _menu = signal(undefined), placement: _placement = signal('bottom-start'), offset: _offset = signal(4), flip: _flip = signal(true), shift: _shift = signal(undefined), context: _context = signal(undefined), container, scrollBehavior, cooldown, triggers = signal(['click']), showDelay = signal(0), hideDelay = signal(0), }) => {
50
+ const [NgpMenuTriggerStateToken, ngpMenuTrigger, _injectMenuTriggerState, provideMenuTriggerState,] = createPrimitive('NgpMenuTrigger', ({ disabled: _disabled = signal(false), menu: _menu = signal(undefined), placement: _placement = signal('bottom-start'), offset: _offset = signal(4), flip: _flip = signal(true), shift: _shift = signal(undefined), context: _context = signal(undefined), container: _container, scrollBehavior, cooldown, triggers = signal(['click']), showDelay = signal(0), hideDelay = signal(0), }) => {
51
51
  const element = injectElementRef();
52
52
  const injector = inject(Injector);
53
53
  const viewContainerRef = inject(ViewContainerRef);
54
54
  const directionality = inject(Directionality);
55
+ const disposables = injectDisposables();
55
56
  // Controlled properties
56
57
  const menu = controlled(_menu);
57
58
  const disabled = controlled(_disabled);
@@ -60,6 +61,7 @@ const [NgpMenuTriggerStateToken, ngpMenuTrigger, _injectMenuTriggerState, provid
60
61
  const shift = controlled(_shift);
61
62
  const offset = controlled(_offset);
62
63
  const context = controlled(_context);
64
+ const container = controlled(_container, 'body');
63
65
  // Internal state
64
66
  const overlay = signal(null, ...(ngDevMode ? [{ debugName: "overlay" }] : /* istanbul ignore next */ []));
65
67
  const open = computed(() => overlay()?.isOpen() ?? false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
@@ -69,11 +71,21 @@ const [NgpMenuTriggerStateToken, ngpMenuTrigger, _injectMenuTriggerState, provid
69
71
  const pointerOverTrigger = signal(false, ...(ngDevMode ? [{ debugName: "pointerOverTrigger" }] : /* istanbul ignore next */ []));
70
72
  const pointerOverContent = signal(false, ...(ngDevMode ? [{ debugName: "pointerOverContent" }] : /* istanbul ignore next */ []));
71
73
  const isPointerOverMenuArea = computed(() => pointerOverTrigger() || pointerOverContent(), ...(ngDevMode ? [{ debugName: "isPointerOverMenuArea" }] : /* istanbul ignore next */ []));
74
+ // Safe-polygon hover intent: while the pointer travels inside a corridor from
75
+ // the trigger exit point toward the open menu, the menu stays open. Reversing
76
+ // away closes it (requireForwardMovement).
77
+ const hoverBridge = createHoverBridge({
78
+ isPointerInAnchor: isPointerOverMenuArea,
79
+ close: () => hide(),
80
+ requireForwardMovement: true,
81
+ });
72
82
  // Reset pointer tracking when menu closes
73
83
  effect(() => {
74
84
  const isOpen = open();
75
- // When menu closes, reset pointer tracking state
85
+ // When menu closes, reset pointer tracking state and tear down any
86
+ // in-progress hover bridge (and its global listener).
76
87
  if (!isOpen) {
88
+ hoverBridge.clear();
77
89
  pointerOverTrigger.set(false);
78
90
  pointerOverContent.set(false);
79
91
  }
@@ -109,8 +121,10 @@ const [NgpMenuTriggerStateToken, ngpMenuTrigger, _injectMenuTriggerState, provid
109
121
  return;
110
122
  }
111
123
  pointerOverTrigger.set(true);
112
- // If already open, cancel any pending hide
124
+ // If already open, cancel any pending hide - the pointer is back on the
125
+ // trigger, so any in-progress hover bridge is no longer needed.
113
126
  if (open()) {
127
+ hoverBridge.clear();
114
128
  overlay()?.cancelPendingClose();
115
129
  return;
116
130
  }
@@ -125,17 +139,31 @@ const [NgpMenuTriggerStateToken, ngpMenuTrigger, _injectMenuTriggerState, provid
125
139
  return;
126
140
  }
127
141
  pointerOverTrigger.set(false);
142
+ const currentOverlay = overlay();
128
143
  // If the overlay hasn't been created, there's nothing to cancel
129
- if (!overlay()) {
144
+ if (!currentOverlay) {
145
+ return;
146
+ }
147
+ // Build a safe-polygon corridor from the pointer exit point toward the
148
+ // open menu. While the pointer stays inside it the menu stays open, so
149
+ // diagonal travel across the offset gap doesn't collapse the menu.
150
+ const menuElement = open() ? currentOverlay.getElements()[0] : undefined;
151
+ const started = !!menuElement &&
152
+ hoverBridge.track({
153
+ triggerRect: element.nativeElement.getBoundingClientRect(),
154
+ targetRect: menuElement.getBoundingClientRect(),
155
+ exitPoint: { x: event.clientX, y: event.clientY },
156
+ });
157
+ if (started) {
158
+ currentOverlay.cancelPendingClose();
130
159
  return;
131
160
  }
132
- // Use a small delay to allow moving to content
133
- setTimeout(() => {
134
- // Only hide if pointer is not over trigger or content
161
+ // Fall back to a small grace period when we can't build the corridor.
162
+ disposables.setTimeout(() => {
135
163
  if (!isPointerOverMenuArea()) {
136
164
  hide();
137
165
  }
138
- }, 50); // Small grace period for moving between trigger and content
166
+ }, 50);
139
167
  }
140
168
  function onFocus() {
141
169
  if (disabled?.() || !triggers().includes('focus')) {
@@ -261,7 +289,7 @@ const [NgpMenuTriggerStateToken, ngpMenuTrigger, _injectMenuTriggerState, provid
261
289
  viewContainerRef,
262
290
  injector,
263
291
  context,
264
- container: container?.(),
292
+ container: container(),
265
293
  placement: placement,
266
294
  offset: offset(),
267
295
  flip: flip(),
@@ -299,15 +327,23 @@ const [NgpMenuTriggerStateToken, ngpMenuTrigger, _injectMenuTriggerState, provid
299
327
  function setContext(newContext) {
300
328
  context.set(newContext);
301
329
  }
330
+ function setContainer(newContainer) {
331
+ container.set(newContainer);
332
+ }
302
333
  /**
303
334
  * Called by menu content when pointer enters/leaves
304
335
  * @internal
305
336
  */
306
337
  function setPointerOverContent(isOver) {
307
338
  pointerOverContent.set(isOver);
308
- if (!isOver && open() && triggers().includes('hover')) {
339
+ if (isOver) {
340
+ // The pointer reached the menu - the hover bridge has served its purpose.
341
+ hoverBridge.clear();
342
+ return;
343
+ }
344
+ if (open() && triggers().includes('hover')) {
309
345
  // Use a small delay to allow pointer to move back to trigger
310
- setTimeout(() => {
346
+ disposables.setTimeout(() => {
311
347
  // Only hide if pointer is not over trigger or content
312
348
  if (!isPointerOverMenuArea()) {
313
349
  hide();
@@ -332,8 +368,10 @@ const [NgpMenuTriggerStateToken, ngpMenuTrigger, _injectMenuTriggerState, provid
332
368
  setPlacement,
333
369
  setOffset,
334
370
  setContext,
371
+ setContainer,
335
372
  setPointerOverContent,
336
373
  flip,
374
+ container: deprecatedSetter(container, 'setContainer', setContainer),
337
375
  };
338
376
  });
339
377
  function injectMenuTriggerState(options) {
@@ -426,21 +464,48 @@ const [NgpMenuStateToken, ngpMenu, injectMenuState, provideMenuState] = createPr
426
464
  };
427
465
  });
428
466
 
429
- const [NgpSubmenuTriggerStateToken, ngpSubmenuTrigger, injectSubmenuTriggerState, provideSubmenuTriggerState,] = createPrimitive('NgpSubmenuTrigger', ({ disabled: _disabled = signal(false), menu: _menu = signal(undefined), placement: _placement = signal('right-start'), offset: _offset = signal(0), flip: _flip = signal(true), }) => {
467
+ const [NgpSubmenuTriggerStateToken, ngpSubmenuTrigger, injectSubmenuTriggerState, provideSubmenuTriggerState,] = createPrimitive('NgpSubmenuTrigger', ({ disabled: _disabled = signal(false), menu: _menu = signal(undefined), placement: _placement = signal('right-start'), offset: _offset = signal(0), flip: _flip = signal(true), container: _container, }) => {
430
468
  const element = injectElementRef();
431
469
  const injector = inject(Injector);
432
470
  const viewContainerRef = inject(ViewContainerRef);
433
471
  const parentMenu = injectMenuState({ optional: true });
434
472
  const focusMonitor = inject(FocusMonitor);
473
+ const disposables = injectDisposables();
435
474
  // Controlled properties
436
475
  const menu = controlled(_menu);
437
476
  const disabled = controlled(_disabled);
438
477
  const placement = controlled(_placement);
439
478
  const flip = controlled(_flip);
440
479
  const offset = controlled(_offset);
480
+ const container = controlled(_container, 'body');
441
481
  const overlay = signal(null, ...(ngDevMode ? [{ debugName: "overlay" }] : /* istanbul ignore next */ []));
442
482
  const open = computed(() => overlay()?.isOpen() ?? false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
443
483
  const openOrigin = signal('program', ...(ngDevMode ? [{ debugName: "openOrigin" }] : /* istanbul ignore next */ []));
484
+ // Track pointer presence for the safe-polygon hover bridge.
485
+ const pointerOverTrigger = signal(false, ...(ngDevMode ? [{ debugName: "pointerOverTrigger" }] : /* istanbul ignore next */ []));
486
+ const pointerOverContent = signal(false, ...(ngDevMode ? [{ debugName: "pointerOverContent" }] : /* istanbul ignore next */ []));
487
+ const isPointerOverSubmenu = computed(() => pointerOverTrigger() || pointerOverContent(), ...(ngDevMode ? [{ debugName: "isPointerOverSubmenu" }] : /* istanbul ignore next */ []));
488
+ // Safe-polygon hover intent: while the pointer travels inside a corridor from
489
+ // the submenu trigger toward the open submenu, sibling hover events are
490
+ // ignored so the submenu doesn't collapse mid-traversal.
491
+ const hoverBridge = createHoverBridge({
492
+ isPointerInAnchor: isPointerOverSubmenu,
493
+ close: () => hide('mouse'),
494
+ requireForwardMovement: true,
495
+ });
496
+ // Tear down any hover bridge whenever the submenu closes - including close
497
+ // paths that bypass hide() (e.g. an outside click on the overlay), so a
498
+ // stale corridor can't linger or wrongly suppress the next sibling hover.
499
+ // Also reset the pointer flags: destroying the panel under the pointer never
500
+ // fires its pointerleave, and a stuck pointerOverContent would make every
501
+ // future corridor treat the pointer as anchored and never close.
502
+ effect(() => {
503
+ if (!open()) {
504
+ hoverBridge.clear();
505
+ pointerOverTrigger.set(false);
506
+ pointerOverContent.set(false);
507
+ }
508
+ });
444
509
  // Subscribe to parent menu's closeSubmenus
445
510
  parentMenu()
446
511
  ?.closeSubmenus.pipe(safeTakeUntilDestroyed())
@@ -449,6 +514,12 @@ const [NgpSubmenuTriggerStateToken, ngpSubmenuTrigger, injectSubmenuTriggerState
449
514
  if (submenuElement === element.nativeElement) {
450
515
  return;
451
516
  }
517
+ // While the pointer is still inside the safe-polygon corridor toward this
518
+ // submenu, ignore sibling hover-driven closes. The pointer-move listener
519
+ // closes the submenu itself once the pointer actually leaves the corridor.
520
+ if (hoverBridge.isActive()) {
521
+ return;
522
+ }
452
523
  hide('mouse');
453
524
  });
454
525
  // Host bindings
@@ -459,6 +530,7 @@ const [NgpSubmenuTriggerStateToken, ngpSubmenuTrigger, injectSubmenuTriggerState
459
530
  listener(element, 'click', onClick);
460
531
  listener(element, 'keydown', handleArrowKey);
461
532
  listener(element, 'pointerenter', showSubmenuOnHover);
533
+ listener(element, 'pointerleave', onPointerLeave);
462
534
  // Methods
463
535
  function onClick(event) {
464
536
  if (disabled?.()) {
@@ -496,6 +568,8 @@ const [NgpSubmenuTriggerStateToken, ngpSubmenuTrigger, injectSubmenuTriggerState
496
568
  if (disabled?.() || !open()) {
497
569
  return;
498
570
  }
571
+ // The submenu is closing - any active hover bridge is no longer relevant.
572
+ hoverBridge.clear();
499
573
  // Hide the overlay
500
574
  overlay()?.hide({ origin });
501
575
  }
@@ -514,6 +588,7 @@ const [NgpSubmenuTriggerStateToken, ngpSubmenuTrigger, injectSubmenuTriggerState
514
588
  content: menuContent,
515
589
  triggerElement: element.nativeElement,
516
590
  injector,
591
+ container: container(),
517
592
  placement,
518
593
  offset: offset(),
519
594
  flip: flip(),
@@ -546,8 +621,38 @@ const [NgpSubmenuTriggerStateToken, ngpSubmenuTrigger, injectSubmenuTriggerState
546
621
  if (event.pointerType === 'touch') {
547
622
  return;
548
623
  }
624
+ pointerOverTrigger.set(true);
625
+ // The pointer is back on the trigger - drop any in-progress hover bridge.
626
+ hoverBridge.clear();
549
627
  show('mouse');
550
628
  }
629
+ function onPointerLeave(event) {
630
+ if (event instanceof PointerEvent === false || event.pointerType === 'touch') {
631
+ return;
632
+ }
633
+ pointerOverTrigger.set(false);
634
+ const currentOverlay = overlay();
635
+ // Only build a corridor while the submenu is actually open.
636
+ if (!open() || !currentOverlay) {
637
+ return;
638
+ }
639
+ const submenuElement = currentOverlay.getElements()[0];
640
+ const started = !!submenuElement &&
641
+ hoverBridge.track({
642
+ triggerRect: element.nativeElement.getBoundingClientRect(),
643
+ targetRect: submenuElement.getBoundingClientRect(),
644
+ exitPoint: { x: event.clientX, y: event.clientY },
645
+ });
646
+ if (!started) {
647
+ // Defensive fallback: if the corridor can't be built, close after a short
648
+ // grace period rather than leaving the submenu stuck open.
649
+ disposables.setTimeout(() => {
650
+ if (!isPointerOverSubmenu()) {
651
+ hide('mouse');
652
+ }
653
+ }, 50);
654
+ }
655
+ }
551
656
  function setDisabled(isDisabled) {
552
657
  disabled.set(isDisabled);
553
658
  if (isDisabled && open()) {
@@ -566,14 +671,19 @@ const [NgpSubmenuTriggerStateToken, ngpSubmenuTrigger, injectSubmenuTriggerState
566
671
  function setFlip(shouldFlip) {
567
672
  flip.set(shouldFlip);
568
673
  }
674
+ function setContainer(newContainer) {
675
+ container.set(newContainer);
676
+ }
569
677
  function focus(origin) {
570
678
  focusMonitor.focusVia(element.nativeElement, origin, { preventScroll: true });
571
679
  }
572
- // No-op for submenus - hover behavior is handled via showSubmenuOnHover on the trigger element
573
- function setPointerOverContent(_isOver) {
574
- // Submenus don't need pointer tracking on content because:
575
- // 1. The submenu trigger handles hover via showSubmenuOnHover
576
- // 2. Closing on hover-out is handled by the parent menu's closeSubmenus mechanism
680
+ function setPointerOverContent(isOver) {
681
+ pointerOverContent.set(isOver);
682
+ // Reaching the submenu content means the pointer arrived safely, so the
683
+ // hover bridge corridor is no longer needed.
684
+ if (isOver) {
685
+ hoverBridge.clear();
686
+ }
577
687
  }
578
688
  return {
579
689
  placement: deprecatedSetter(placement, 'setPlacement'),
@@ -591,8 +701,10 @@ const [NgpSubmenuTriggerStateToken, ngpSubmenuTrigger, injectSubmenuTriggerState
591
701
  setFlip,
592
702
  setPlacement,
593
703
  setOffset,
704
+ setContainer,
594
705
  focus,
595
706
  setPointerOverContent,
707
+ container: deprecatedSetter(container, 'setContainer', setContainer),
596
708
  };
597
709
  });
598
710
 
@@ -627,6 +739,11 @@ class NgpSubmenuTrigger {
627
739
  */
628
740
  this.flip = input(true, { ...(ngDevMode ? { debugName: "flip" } : /* istanbul ignore next */ {}), alias: 'ngpSubmenuTriggerFlip',
629
741
  transform: coerceFlip });
742
+ /**
743
+ * Define the container in which the menu should be attached.
744
+ * @default document.body
745
+ */
746
+ this.container = input(null, { ...(ngDevMode ? { debugName: "container" } : /* istanbul ignore next */ {}), alias: 'ngpSubmenuTriggerContainer' });
630
747
  /**
631
748
  * Access the menu trigger state.
632
749
  */
@@ -636,6 +753,7 @@ class NgpSubmenuTrigger {
636
753
  placement: this.placement,
637
754
  offset: this.offset,
638
755
  flip: this.flip,
756
+ container: this.container,
639
757
  });
640
758
  }
641
759
  /**
@@ -665,7 +783,7 @@ class NgpSubmenuTrigger {
665
783
  this.state.focus(origin);
666
784
  }
667
785
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NgpSubmenuTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
668
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.14", type: NgpSubmenuTrigger, isStandalone: true, selector: "[ngpSubmenuTrigger]", inputs: { menu: { classPropertyName: "menu", publicName: "ngpSubmenuTrigger", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "ngpSubmenuTriggerDisabled", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "ngpSubmenuTriggerPlacement", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "ngpSubmenuTriggerOffset", isSignal: true, isRequired: false, transformFunction: null }, flip: { classPropertyName: "flip", publicName: "ngpSubmenuTriggerFlip", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
786
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.14", type: NgpSubmenuTrigger, isStandalone: true, selector: "[ngpSubmenuTrigger]", inputs: { menu: { classPropertyName: "menu", publicName: "ngpSubmenuTrigger", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "ngpSubmenuTriggerDisabled", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "ngpSubmenuTriggerPlacement", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "ngpSubmenuTriggerOffset", isSignal: true, isRequired: false, transformFunction: null }, flip: { classPropertyName: "flip", publicName: "ngpSubmenuTriggerFlip", isSignal: true, isRequired: false, transformFunction: null }, container: { classPropertyName: "container", publicName: "ngpSubmenuTriggerContainer", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
669
787
  provideSubmenuTriggerState(),
670
788
  // Also provide as NgpMenuTriggerStateToken so the submenu's menu-state
671
789
  // can find this trigger's openOrigin for :focus-visible styling
@@ -684,7 +802,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
684
802
  { provide: NgpMenuTriggerStateToken, useExisting: NgpSubmenuTriggerStateToken },
685
803
  ],
686
804
  }]
687
- }], propDecorators: { menu: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSubmenuTrigger", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSubmenuTriggerDisabled", required: false }] }], placement: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSubmenuTriggerPlacement", required: false }] }], offset: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSubmenuTriggerOffset", required: false }] }], flip: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSubmenuTriggerFlip", required: false }] }] } });
805
+ }], propDecorators: { menu: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSubmenuTrigger", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSubmenuTriggerDisabled", required: false }] }], placement: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSubmenuTriggerPlacement", required: false }] }], offset: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSubmenuTriggerOffset", required: false }] }], flip: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSubmenuTriggerFlip", required: false }] }], container: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSubmenuTriggerContainer", required: false }] }] } });
688
806
 
689
807
  const [NgpMenuItemStateToken, ngpMenuItem, injectMenuItemState, provideMenuItemState] = createPrimitive('NgpMenuItem', ({ disabled = signal(false), closeOnSelect = signal(true), role = 'menuitem', }) => {
690
808
  const element = injectElementRef();