ng-primitives 0.44.0 → 0.45.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 (45) hide show
  1. package/combobox/combobox/combobox-state.d.ts +3 -2
  2. package/combobox/combobox/combobox.d.ts +9 -3
  3. package/combobox/combobox-button/combobox-button.d.ts +3 -2
  4. package/combobox/combobox-dropdown/combobox-dropdown.d.ts +52 -2
  5. package/combobox/combobox-input/combobox-input.d.ts +3 -2
  6. package/combobox/combobox-option/combobox-option.d.ts +3 -2
  7. package/combobox/combobox-portal/combobox-portal.d.ts +8 -21
  8. package/example-theme/index.css +1 -0
  9. package/fesm2022/ng-primitives-combobox.mjs +63 -87
  10. package/fesm2022/ng-primitives-combobox.mjs.map +1 -1
  11. package/fesm2022/ng-primitives-focus-trap.mjs +9 -1
  12. package/fesm2022/ng-primitives-focus-trap.mjs.map +1 -1
  13. package/fesm2022/ng-primitives-listbox.mjs +1 -1
  14. package/fesm2022/ng-primitives-listbox.mjs.map +1 -1
  15. package/fesm2022/ng-primitives-menu.mjs +372 -63
  16. package/fesm2022/ng-primitives-menu.mjs.map +1 -1
  17. package/fesm2022/ng-primitives-popover.mjs +62 -332
  18. package/fesm2022/ng-primitives-popover.mjs.map +1 -1
  19. package/fesm2022/ng-primitives-portal.mjs +359 -2
  20. package/fesm2022/ng-primitives-portal.mjs.map +1 -1
  21. package/fesm2022/ng-primitives-tooltip.mjs +51 -176
  22. package/fesm2022/ng-primitives-tooltip.mjs.map +1 -1
  23. package/focus-trap/focus-trap/focus-trap-state.d.ts +1 -0
  24. package/focus-trap/focus-trap/focus-trap.d.ts +5 -0
  25. package/menu/config/menu-config.d.ts +42 -0
  26. package/menu/index.d.ts +5 -1
  27. package/menu/menu/menu.d.ts +6 -2
  28. package/menu/menu-trigger/menu-trigger-state.d.ts +37 -0
  29. package/menu/menu-trigger/menu-trigger.d.ts +87 -13
  30. package/menu/submenu-trigger/submenu-trigger-state.d.ts +56 -0
  31. package/menu/submenu-trigger/submenu-trigger.d.ts +62 -10
  32. package/package.json +1 -1
  33. package/popover/index.d.ts +1 -2
  34. package/popover/popover/popover.d.ts +2 -43
  35. package/popover/popover-trigger/popover-trigger.d.ts +13 -107
  36. package/portal/index.d.ts +2 -0
  37. package/portal/overlay-token.d.ts +12 -0
  38. package/portal/overlay.d.ts +170 -0
  39. package/schematics/ng-generate/templates/combobox/combobox.__fileSuffix@dasherize__.ts.template +31 -0
  40. package/tooltip/index.d.ts +1 -1
  41. package/tooltip/tooltip/tooltip.d.ts +3 -25
  42. package/tooltip/tooltip-trigger/tooltip-trigger.d.ts +12 -63
  43. package/popover/popover/popover-token.d.ts +0 -10
  44. package/popover/utils/transform-origin.d.ts +0 -2
  45. package/tooltip/tooltip/tooltip-token.d.ts +0 -10
@@ -1 +1 @@
1
- {"version":3,"file":"ng-primitives-menu.mjs","sources":["../../../../packages/ng-primitives/menu/src/menu/menu-token.ts","../../../../packages/ng-primitives/menu/src/submenu-trigger/submenu-trigger.ts","../../../../packages/ng-primitives/menu/src/menu-item/menu-item.ts","../../../../packages/ng-primitives/menu/src/menu-trigger/menu-trigger.ts","../../../../packages/ng-primitives/menu/src/menu/menu.ts","../../../../packages/ng-primitives/menu/src/ng-primitives-menu.ts"],"sourcesContent":["import { ExistingProvider, inject, InjectionToken, Type } from '@angular/core';\nimport type { NgpMenu } from './menu';\n\nexport const NgpMenuToken = new InjectionToken<NgpMenu>('NgpMenuToken');\n\n/**\n * Inject the Menu directive instance\n */\nexport function injectMenu(): NgpMenu {\n return inject(NgpMenuToken);\n}\n\n/**\n * Provide the Menu directive instance\n */\nexport function provideMenu(type: Type<NgpMenu>): ExistingProvider {\n return { provide: NgpMenuToken, useExisting: type };\n}\n","import { FocusOrigin } from '@angular/cdk/a11y';\nimport { Directive, HostListener, inject } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { injectElementRef } from 'ng-primitives/internal';\nimport { injectPopoverTriggerState, NgpPopoverTrigger } from 'ng-primitives/popover';\nimport { NgpMenuToken } from '../menu/menu-token';\n\n@Directive({\n selector: '[ngpSubmenuTrigger]',\n exportAs: 'ngpSubmenuTrigger',\n hostDirectives: [\n { directive: NgpPopoverTrigger, inputs: ['ngpPopoverTrigger:ngpSubmenuTrigger'] },\n ],\n host: {\n 'aria-haspopup': 'true',\n },\n})\nexport class NgpSubmenuTrigger {\n /** Access the popover trigger element. */\n private readonly trigger = injectElementRef();\n\n /** Access the popover trigger state */\n private readonly popoverTrigger = injectPopoverTriggerState();\n\n /** Access the parent menu */\n private readonly parentMenu = inject(NgpMenuToken, { optional: true });\n\n constructor() {\n // by default the popover opens below and to the center of the trigger,\n // but as this is a submenu we want to default to opening to the right\n // and to the start\n this.popoverTrigger().placement.set('right-start');\n\n this.parentMenu?.closeSubmenus.pipe(takeUntilDestroyed()).subscribe(element => {\n // if the element is not the trigger, we want to close the menu\n if (element === this.trigger.nativeElement) {\n return;\n }\n\n this.closeMenu('mouse');\n });\n }\n\n /**\n * @internal\n */\n openMenu(origin: FocusOrigin): void {\n // if the menu is already open, we don't want to do anything\n if (this.popoverTrigger().open()) {\n return;\n }\n\n this.popoverTrigger().show(origin);\n }\n\n /**\n * @internal\n */\n closeMenu(origin: FocusOrigin): void {\n this.popoverTrigger().hide(origin);\n }\n\n /**\n * If the user presses the right arrow key, we want to open the submenu\n * and focus the first item in the submenu.\n * This behavior will be inverted if the direction is RTL.\n * @param event\n */\n @HostListener('keydown.ArrowRight', ['$event'])\n @HostListener('keydown.ArrowLeft', ['$event'])\n protected showSubmenuOnArrow(event: KeyboardEvent): void {\n const direction = getComputedStyle(this.trigger.nativeElement).direction;\n\n const isRtl = direction === 'rtl';\n\n const isRightArrow = event.key === 'ArrowRight';\n const isLeftArrow = event.key === 'ArrowLeft';\n\n if ((isRightArrow && !isRtl) || (isLeftArrow && isRtl)) {\n event.preventDefault();\n this.openMenu('keyboard');\n }\n }\n\n /**\n * If the user hovers over the trigger, we want to open the submenu\n */\n @HostListener('mouseenter')\n protected showSubmenuOnHover(): void {\n this.openMenu('mouse');\n }\n}\n","import { FocusOrigin } from '@angular/cdk/a11y';\nimport { Directive, HostListener, inject, Injector } from '@angular/core';\nimport { NgpButton } from 'ng-primitives/button';\nimport { injectElementRef } from 'ng-primitives/internal';\nimport { NgpRovingFocusItem } from 'ng-primitives/roving-focus';\nimport { injectMenu } from '../menu/menu-token';\nimport { NgpSubmenuTrigger } from '../submenu-trigger/submenu-trigger';\n\n/**\n * The `NgpMenuItem` directive represents a menu item.\n */\n@Directive({\n selector: '[ngpMenuItem]',\n exportAs: 'ngpMenuItem',\n hostDirectives: [\n { directive: NgpButton, inputs: ['disabled: ngpMenuItemDisabled'] },\n NgpRovingFocusItem,\n ],\n host: {\n role: 'menuitem',\n '(click)': 'onClick($event)',\n '(keydown.ArrowLeft)': 'handleArrowKey($event)',\n '(keydown.ArrowRight)': 'handleArrowKey($event)',\n },\n})\nexport class NgpMenuItem {\n /** Access the injector */\n private readonly injector = inject(Injector);\n /** Access the button element */\n private readonly elementRef = injectElementRef();\n\n /** Access the parent menu */\n private readonly parentMenu = injectMenu();\n\n /** Close the menu when the item is clicked */\n protected onClick(event: MouseEvent): void {\n // we do this here to avoid circular dependency issues\n const trigger = this.injector.get(NgpSubmenuTrigger, null, { self: true, optional: true });\n\n const origin: FocusOrigin = event.detail === 0 ? 'keyboard' : 'mouse';\n\n // if this is a submenu trigger, we don't want to close the menu, we want to open the submenu\n if (!trigger) {\n this.parentMenu?.closeAllMenus(origin);\n }\n }\n\n /**\n * If the user presses the left arrow key (in LTR) and there is a parent menu,\n * we want to close the menu and focus the parent menu item.\n */\n protected handleArrowKey(event: KeyboardEvent): void {\n // if there is no parent menu, we don't want to do anything\n const trigger = this.injector.get(NgpSubmenuTrigger, null, { optional: true });\n\n if (!trigger) {\n return;\n }\n\n const direction = getComputedStyle(this.elementRef.nativeElement).direction;\n const isRtl = direction === 'rtl';\n\n const isLeftArrow = event.key === 'ArrowLeft';\n const isRightArrow = event.key === 'ArrowRight';\n\n if ((isLeftArrow && !isRtl) || (isRightArrow && isRtl)) {\n event.preventDefault();\n\n if (trigger) {\n trigger.closeMenu('keyboard');\n }\n }\n }\n\n /**\n * If the user hovers over the trigger, we want to open the submenu\n */\n @HostListener('mouseenter')\n protected showSubmenuOnHover(): void {\n this.parentMenu?.closeSubmenus.next(this.elementRef.nativeElement);\n }\n}\n","import { Directive, inject } from '@angular/core';\nimport { injectPopoverTriggerState, NgpPopoverTrigger } from 'ng-primitives/popover';\nimport { NgpMenuToken } from '../menu/menu-token';\n\n/**\n * The `NgpMenuTrigger` directive allows you to turn an element into a menu trigger.\n */\n@Directive({\n selector: '[ngpMenuTrigger]',\n exportAs: 'ngpMenuTrigger',\n hostDirectives: [\n {\n directive: NgpPopoverTrigger,\n inputs: [\n 'ngpPopoverTrigger:ngpMenuTrigger',\n 'ngpPopoverTriggerDisabled:ngpMenuTriggerDisabled',\n 'ngpPopoverTriggerPlacement:ngpMenuTriggerPlacement',\n 'ngpPopoverTriggerOffset:ngpMenuTriggerOffset',\n 'ngpPopoverTriggerShowDelay:ngpMenuTriggerShowDelay',\n 'ngpPopoverTriggerHideDelay:ngpMenuTriggerHideDelay',\n 'ngpPopoverTriggerFlip:ngpMenuTriggerFlip',\n 'ngpPopoverTriggerContainer:ngpMenuTriggerContainer',\n 'ngpPopoverTriggerScrollBehavior:ngpMenuTriggerScrollBehavior',\n ],\n },\n ],\n host: {\n 'aria-haspopup': 'true',\n '(document:keydown.escape)': 'closeOnEscape()',\n },\n})\nexport class NgpMenuTrigger {\n /** Access the popover trigger state */\n private readonly state = injectPopoverTriggerState();\n\n /** Access any parent menus */\n private readonly parentMenu = inject(NgpMenuToken, { optional: true });\n\n constructor() {\n // by default the popover opens below and to the center of the trigger,\n // but as this is a menu we want to default to opening below and to the start\n this.state().placement.set('bottom-start');\n // for menus we want to default to blocking the scroll behavior\n this.state().scrollBehavior.set('block');\n }\n\n /**\n * Close the menu and any parent menus\n */\n closeOnEscape(): void {\n this.parentMenu?.closeAllMenus('keyboard');\n }\n}\n","import { FocusOrigin } from '@angular/cdk/a11y';\nimport { Directive, inject } from '@angular/core';\nimport { injectPopoverTriggerState, NgpPopover } from 'ng-primitives/popover';\nimport { NgpRovingFocusGroup, provideRovingFocusGroup } from 'ng-primitives/roving-focus';\nimport { Subject } from 'rxjs';\nimport { NgpMenuToken, provideMenu } from './menu-token';\n\n/**\n * The `NgpMenu` is a container for menu items.\n */\n@Directive({\n selector: '[ngpMenu]',\n exportAs: 'ngpMenu',\n hostDirectives: [NgpPopover, NgpRovingFocusGroup],\n providers: [\n // ensure we don't inherit the focus group from the parent menu if there is one\n provideRovingFocusGroup(NgpRovingFocusGroup, { inherit: false }),\n provideMenu(NgpMenu),\n ],\n})\nexport class NgpMenu {\n /** Access the popover trigger state */\n private readonly popover = injectPopoverTriggerState();\n\n /** Access any parent menus */\n private readonly parentMenu = inject(NgpMenuToken, { optional: true, skipSelf: true });\n\n /** @internal Whether we should close submenus */\n readonly closeSubmenus = new Subject<HTMLElement>();\n\n /** Close the menu and any parent menus */\n closeAllMenus(origin: FocusOrigin): void {\n this.popover().hide(origin);\n this.parentMenu?.closeAllMenus(origin);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1"],"mappings":";;;;;;;;;;;;MAGa,YAAY,GAAG,IAAI,cAAc,CAAU,cAAc;AAEtE;;AAEG;SACa,UAAU,GAAA;AACxB,IAAA,OAAO,MAAM,CAAC,YAAY,CAAC;AAC7B;AAEA;;AAEG;AACG,SAAU,WAAW,CAAC,IAAmB,EAAA;IAC7C,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE;AACrD;;MCAa,iBAAiB,CAAA;AAU5B,IAAA,WAAA,GAAA;;QARiB,IAAO,CAAA,OAAA,GAAG,gBAAgB,EAAE;;QAG5B,IAAc,CAAA,cAAA,GAAG,yBAAyB,EAAE;;QAG5C,IAAU,CAAA,UAAA,GAAG,MAAM,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;;;QAMpE,IAAI,CAAC,cAAc,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,aAAa,CAAC;AAElD,QAAA,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,SAAS,CAAC,OAAO,IAAG;;YAE5E,IAAI,OAAO,KAAK,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE;gBAC1C;;AAGF,YAAA,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;AACzB,SAAC,CAAC;;AAGJ;;AAEG;AACH,IAAA,QAAQ,CAAC,MAAmB,EAAA;;QAE1B,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC,IAAI,EAAE,EAAE;YAChC;;QAGF,IAAI,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;;AAGpC;;AAEG;AACH,IAAA,SAAS,CAAC,MAAmB,EAAA;QAC3B,IAAI,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;;AAGpC;;;;;AAKG;AAGO,IAAA,kBAAkB,CAAC,KAAoB,EAAA;AAC/C,QAAA,MAAM,SAAS,GAAG,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,SAAS;AAExE,QAAA,MAAM,KAAK,GAAG,SAAS,KAAK,KAAK;AAEjC,QAAA,MAAM,YAAY,GAAG,KAAK,CAAC,GAAG,KAAK,YAAY;AAC/C,QAAA,MAAM,WAAW,GAAG,KAAK,CAAC,GAAG,KAAK,WAAW;AAE7C,QAAA,IAAI,CAAC,YAAY,IAAI,CAAC,KAAK,MAAM,WAAW,IAAI,KAAK,CAAC,EAAE;YACtD,KAAK,CAAC,cAAc,EAAE;AACtB,YAAA,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;;;AAI7B;;AAEG;IAEO,kBAAkB,GAAA;AAC1B,QAAA,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;;+GAxEb,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;mGAAjB,iBAAiB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,qBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,eAAA,EAAA,MAAA,EAAA,EAAA,SAAA,EAAA,EAAA,oBAAA,EAAA,4BAAA,EAAA,mBAAA,EAAA,4BAAA,EAAA,YAAA,EAAA,sBAAA,EAAA,EAAA,EAAA,QAAA,EAAA,CAAA,mBAAA,CAAA,EAAA,cAAA,EAAA,CAAA,EAAA,SAAA,EAAA,EAAA,CAAA,iBAAA,EAAA,MAAA,EAAA,CAAA,mBAAA,EAAA,mBAAA,CAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;4FAAjB,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAV7B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,qBAAqB;AAC/B,oBAAA,QAAQ,EAAE,mBAAmB;AAC7B,oBAAA,cAAc,EAAE;wBACd,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,EAAE,CAAC,qCAAqC,CAAC,EAAE;AAClF,qBAAA;AACD,oBAAA,IAAI,EAAE;AACJ,wBAAA,eAAe,EAAE,MAAM;AACxB,qBAAA;AACF,iBAAA;wDAsDW,kBAAkB,EAAA,CAAA;sBAF3B,YAAY;uBAAC,oBAAoB,EAAE,CAAC,QAAQ,CAAC;;sBAC7C,YAAY;uBAAC,mBAAmB,EAAE,CAAC,QAAQ,CAAC;gBAmBnC,kBAAkB,EAAA,CAAA;sBAD3B,YAAY;uBAAC,YAAY;;;AC/E5B;;AAEG;MAeU,WAAW,CAAA;AAdxB,IAAA,WAAA,GAAA;;AAgBmB,QAAA,IAAA,CAAA,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;;QAE3B,IAAU,CAAA,UAAA,GAAG,gBAAgB,EAAE;;QAG/B,IAAU,CAAA,UAAA,GAAG,UAAU,EAAE;AAiD3C;;AA9CW,IAAA,OAAO,CAAC,KAAiB,EAAA;;QAEjC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAE1F,QAAA,MAAM,MAAM,GAAgB,KAAK,CAAC,MAAM,KAAK,CAAC,GAAG,UAAU,GAAG,OAAO;;QAGrE,IAAI,CAAC,OAAO,EAAE;AACZ,YAAA,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,MAAM,CAAC;;;AAI1C;;;AAGG;AACO,IAAA,cAAc,CAAC,KAAoB,EAAA;;AAE3C,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QAE9E,IAAI,CAAC,OAAO,EAAE;YACZ;;AAGF,QAAA,MAAM,SAAS,GAAG,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,SAAS;AAC3E,QAAA,MAAM,KAAK,GAAG,SAAS,KAAK,KAAK;AAEjC,QAAA,MAAM,WAAW,GAAG,KAAK,CAAC,GAAG,KAAK,WAAW;AAC7C,QAAA,MAAM,YAAY,GAAG,KAAK,CAAC,GAAG,KAAK,YAAY;AAE/C,QAAA,IAAI,CAAC,WAAW,IAAI,CAAC,KAAK,MAAM,YAAY,IAAI,KAAK,CAAC,EAAE;YACtD,KAAK,CAAC,cAAc,EAAE;YAEtB,IAAI,OAAO,EAAE;AACX,gBAAA,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC;;;;AAKnC;;AAEG;IAEO,kBAAkB,GAAA;AAC1B,QAAA,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC;;+GAtDzD,WAAW,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;mGAAX,WAAW,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,eAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,MAAA,EAAA,UAAA,EAAA,EAAA,SAAA,EAAA,EAAA,OAAA,EAAA,iBAAA,EAAA,mBAAA,EAAA,wBAAA,EAAA,oBAAA,EAAA,wBAAA,EAAA,YAAA,EAAA,sBAAA,EAAA,EAAA,EAAA,QAAA,EAAA,CAAA,aAAA,CAAA,EAAA,cAAA,EAAA,CAAA,EAAA,SAAA,EAAAA,IAAA,CAAA,SAAA,EAAA,MAAA,EAAA,CAAA,UAAA,EAAA,qBAAA,CAAA,EAAA,EAAA,EAAA,SAAA,EAAA,EAAA,CAAA,kBAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;4FAAX,WAAW,EAAA,UAAA,EAAA,CAAA;kBAdvB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,eAAe;AACzB,oBAAA,QAAQ,EAAE,aAAa;AACvB,oBAAA,cAAc,EAAE;wBACd,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,+BAA+B,CAAC,EAAE;wBACnE,kBAAkB;AACnB,qBAAA;AACD,oBAAA,IAAI,EAAE;AACJ,wBAAA,IAAI,EAAE,UAAU;AAChB,wBAAA,SAAS,EAAE,iBAAiB;AAC5B,wBAAA,qBAAqB,EAAE,wBAAwB;AAC/C,wBAAA,sBAAsB,EAAE,wBAAwB;AACjD,qBAAA;AACF,iBAAA;8BAsDW,kBAAkB,EAAA,CAAA;sBAD3B,YAAY;uBAAC,YAAY;;;ACzE5B;;AAEG;MAyBU,cAAc,CAAA;AAOzB,IAAA,WAAA,GAAA;;QALiB,IAAK,CAAA,KAAA,GAAG,yBAAyB,EAAE;;QAGnC,IAAU,CAAA,UAAA,GAAG,MAAM,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;;QAKpE,IAAI,CAAC,KAAK,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,cAAc,CAAC;;QAE1C,IAAI,CAAC,KAAK,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC;;AAG1C;;AAEG;IACH,aAAa,GAAA;AACX,QAAA,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,UAAU,CAAC;;+GAnBjC,cAAc,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;mGAAd,cAAc,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,kBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,eAAA,EAAA,MAAA,EAAA,EAAA,SAAA,EAAA,EAAA,yBAAA,EAAA,iBAAA,EAAA,EAAA,EAAA,QAAA,EAAA,CAAA,gBAAA,CAAA,EAAA,cAAA,EAAA,CAAA,EAAA,SAAA,EAAA,EAAA,CAAA,iBAAA,EAAA,MAAA,EAAA,CAAA,mBAAA,EAAA,gBAAA,EAAA,2BAAA,EAAA,wBAAA,EAAA,4BAAA,EAAA,yBAAA,EAAA,yBAAA,EAAA,sBAAA,EAAA,4BAAA,EAAA,yBAAA,EAAA,4BAAA,EAAA,yBAAA,EAAA,uBAAA,EAAA,oBAAA,EAAA,4BAAA,EAAA,yBAAA,EAAA,iCAAA,EAAA,8BAAA,CAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;4FAAd,cAAc,EAAA,UAAA,EAAA,CAAA;kBAxB1B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,kBAAkB;AAC5B,oBAAA,QAAQ,EAAE,gBAAgB;AAC1B,oBAAA,cAAc,EAAE;AACd,wBAAA;AACE,4BAAA,SAAS,EAAE,iBAAiB;AAC5B,4BAAA,MAAM,EAAE;gCACN,kCAAkC;gCAClC,kDAAkD;gCAClD,oDAAoD;gCACpD,8CAA8C;gCAC9C,oDAAoD;gCACpD,oDAAoD;gCACpD,0CAA0C;gCAC1C,oDAAoD;gCACpD,8DAA8D;AAC/D,6BAAA;AACF,yBAAA;AACF,qBAAA;AACD,oBAAA,IAAI,EAAE;AACJ,wBAAA,eAAe,EAAE,MAAM;AACvB,wBAAA,2BAA2B,EAAE,iBAAiB;AAC/C,qBAAA;AACF,iBAAA;;;ACvBD;;AAEG;MAWU,OAAO,CAAA;AAVpB,IAAA,WAAA,GAAA;;QAYmB,IAAO,CAAA,OAAA,GAAG,yBAAyB,EAAE;;AAGrC,QAAA,IAAA,CAAA,UAAU,GAAG,MAAM,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;AAG7E,QAAA,IAAA,CAAA,aAAa,GAAG,IAAI,OAAO,EAAe;AAOpD;;AAJC,IAAA,aAAa,CAAC,MAAmB,EAAA;QAC/B,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;AAC3B,QAAA,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,MAAM,CAAC;;+GAb7B,OAAO,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAAP,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,OAAO,EANP,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,WAAA,EAAA,SAAA,EAAA;;YAET,uBAAuB,CAAC,mBAAmB,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YAChE,WAAW,CAAC,OAAO,CAAC;AACrB,SAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,cAAA,EAAA,CAAA,EAAA,SAAA,EAAA,EAAA,CAAA,UAAA,EAAA,EAAA,EAAA,SAAA,EAAA,EAAA,CAAA,mBAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;4FAEU,OAAO,EAAA,UAAA,EAAA,CAAA;kBAVnB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,WAAW;AACrB,oBAAA,QAAQ,EAAE,SAAS;AACnB,oBAAA,cAAc,EAAE,CAAC,UAAU,EAAE,mBAAmB,CAAC;AACjD,oBAAA,SAAS,EAAE;;wBAET,uBAAuB,CAAC,mBAAmB,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAChE,wBAAA,WAAW,CAAS,OAAA,CAAA;AACrB,qBAAA;AACF,iBAAA;;;ACnBD;;AAEG;;;;"}
1
+ {"version":3,"file":"ng-primitives-menu.mjs","sources":["../../../../packages/ng-primitives/menu/src/config/menu-config.ts","../../../../packages/ng-primitives/menu/src/menu/menu-token.ts","../../../../packages/ng-primitives/menu/src/menu-trigger/menu-trigger-state.ts","../../../../packages/ng-primitives/menu/src/submenu-trigger/submenu-trigger-state.ts","../../../../packages/ng-primitives/menu/src/submenu-trigger/submenu-trigger.ts","../../../../packages/ng-primitives/menu/src/menu-item/menu-item.ts","../../../../packages/ng-primitives/menu/src/menu-trigger/menu-trigger.ts","../../../../packages/ng-primitives/menu/src/menu/menu.ts","../../../../packages/ng-primitives/menu/src/ng-primitives-menu.ts"],"sourcesContent":["import { InjectionToken, Provider, inject } from '@angular/core';\nimport { Placement } from '@floating-ui/dom';\n\nexport interface NgpMenuConfig {\n /**\n * Define the offset of the menu relative to the trigger.\n * @default 4\n */\n offset: number;\n\n /**\n * Define the placement of the menu relative to the trigger.\n * @default 'bottom-start'\n */\n placement: Placement;\n\n /**\n * Define whether the menu should flip when there is not enough space for the menu.\n * @default true\n */\n flip: boolean;\n\n /**\n * Define the container in to which the menu should be attached.\n * @default document.body\n */\n container: HTMLElement | null;\n\n /**\n * Defines how the menu behaves when the window is scrolled.\n * @default scroll\n */\n scrollBehavior: 'reposition' | 'block';\n}\n\nexport const defaultMenuConfig: NgpMenuConfig = {\n offset: 4,\n placement: 'bottom-start',\n flip: true,\n container: null,\n scrollBehavior: 'block',\n};\n\nexport const NgpMenuConfigToken = new InjectionToken<NgpMenuConfig>('NgpMenuConfigToken');\n\n/**\n * Provide the default Menu configuration\n * @param config The Menu configuration\n * @returns The provider\n */\nexport function provideMenuConfig(config: Partial<NgpMenuConfig>): Provider[] {\n return [\n {\n provide: NgpMenuConfigToken,\n useValue: { ...defaultMenuConfig, ...config },\n },\n ];\n}\n\n/**\n * Inject the Menu configuration\n * @returns The global Menu configuration\n */\nexport function injectMenuConfig(): NgpMenuConfig {\n return inject(NgpMenuConfigToken, { optional: true }) ?? defaultMenuConfig;\n}\n","import { ExistingProvider, inject, InjectionToken, Type } from '@angular/core';\nimport type { NgpMenu } from './menu';\n\nexport const NgpMenuToken = new InjectionToken<NgpMenu>('NgpMenuToken');\n\n/**\n * Inject the Menu directive instance\n */\nexport function injectMenu(): NgpMenu {\n return inject(NgpMenuToken);\n}\n\n/**\n * Provide the Menu directive instance\n */\nexport function provideMenu(type: Type<NgpMenu>): ExistingProvider {\n return { provide: NgpMenuToken, useExisting: type };\n}\n","import {\n createState,\n createStateInjector,\n createStateProvider,\n createStateToken,\n} from 'ng-primitives/state';\nimport type { NgpMenuTrigger } from './menu-trigger';\n\n/**\n * The state token for the MenuTrigger primitive.\n */\nexport const NgpMenuTriggerStateToken = createStateToken<NgpMenuTrigger>('MenuTrigger');\n\n/**\n * Provides the MenuTrigger state.\n */\nexport const provideMenuTriggerState = createStateProvider(NgpMenuTriggerStateToken);\n\n/**\n * Injects the MenuTrigger state.\n */\nexport const injectMenuTriggerState = createStateInjector(NgpMenuTriggerStateToken);\n\n/**\n * The MenuTrigger state registration function.\n */\nexport const menuTriggerState = createState(NgpMenuTriggerStateToken);\n","import {\n createState,\n createStateInjector,\n createStateProvider,\n createStateToken,\n} from 'ng-primitives/state';\nimport type { NgpSubmenuTrigger } from './submenu-trigger';\n\n/**\n * The state token for the SubmenuTrigger primitive.\n */\nexport const NgpSubmenuTriggerStateToken = createStateToken<NgpSubmenuTrigger>('SubmenuTrigger');\n\n/**\n * Provides the SubmenuTrigger state.\n */\nexport const provideSubmenuTriggerState = createStateProvider(NgpSubmenuTriggerStateToken);\n\n/**\n * Injects the SubmenuTrigger state.\n */\nexport const injectSubmenuTriggerState = createStateInjector(NgpSubmenuTriggerStateToken);\n\n/**\n * The SubmenuTrigger state registration function.\n */\nexport const submenuTriggerState = createState(NgpSubmenuTriggerStateToken);\n","import { FocusOrigin } from '@angular/cdk/a11y';\nimport { BooleanInput, NumberInput } from '@angular/cdk/coercion';\nimport {\n booleanAttribute,\n computed,\n Directive,\n HostListener,\n inject,\n Injector,\n input,\n numberAttribute,\n signal,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { Placement } from '@floating-ui/dom';\nimport { injectElementRef, provideExitAnimationManager } from 'ng-primitives/internal';\nimport {\n createOverlay,\n NgpOverlay,\n NgpOverlayConfig,\n NgpOverlayContent,\n} from 'ng-primitives/portal';\nimport { injectMenuTriggerState } from '../menu-trigger/menu-trigger-state';\nimport { NgpMenuToken } from '../menu/menu-token';\nimport { provideSubmenuTriggerState, submenuTriggerState } from './submenu-trigger-state';\n\n@Directive({\n selector: '[ngpSubmenuTrigger]',\n exportAs: 'ngpSubmenuTrigger',\n providers: [provideSubmenuTriggerState({ inherit: false }), provideExitAnimationManager()],\n host: {\n 'aria-haspopup': 'true',\n '[attr.aria-expanded]': 'open() ? \"true\" : \"false\"',\n '[attr.data-open]': 'open() ? \"\" : null',\n '(click)': 'toggle($event)',\n },\n})\nexport class NgpSubmenuTrigger<T = unknown> {\n /**\n * Access the menu trigger element.\n */\n private readonly trigger = injectElementRef();\n\n /**\n * Access the injector.\n */\n private readonly injector = inject(Injector);\n\n /** Access the menu trigger state */\n private readonly menuTrigger = injectMenuTriggerState();\n\n /** Access the parent menu */\n private readonly parentMenu = inject(NgpMenuToken, { optional: true });\n\n /**\n * Access the submenu template ref.\n */\n readonly menu = input<NgpOverlayContent<T>>(undefined, {\n alias: 'ngpSubmenuTrigger',\n });\n\n /**\n * Define if the trigger should be disabled.\n * @default false\n */\n readonly disabled = input<boolean, BooleanInput>(false, {\n alias: 'ngpMenuTriggerDisabled',\n transform: booleanAttribute,\n });\n\n /**\n * Define the placement of the menu relative to the trigger.\n * @default 'right-start'\n */\n readonly placement = input<Placement>('right-start', {\n alias: 'ngpMenuTriggerPlacement',\n });\n\n /**\n * Define the offset of the menu relative to the trigger.\n * @default 0\n */\n readonly offset = input<number, NumberInput>(0, {\n alias: 'ngpMenuTriggerOffset',\n transform: numberAttribute,\n });\n\n /**\n * Define whether the menu should flip when there is not enough space for the menu.\n * @default true\n */\n readonly flip = input<boolean, BooleanInput>(true, {\n alias: 'ngpMenuTriggerFlip',\n transform: booleanAttribute,\n });\n\n /**\n * The overlay that manages the menu\n * @internal\n */\n readonly overlay = signal<NgpOverlay<T> | null>(null);\n\n /**\n * The open state of the menu.\n * @internal\n */\n readonly open = computed(() => this.overlay()?.isOpen() ?? false);\n\n /**\n * Access the menu trigger state.\n */\n readonly state = submenuTriggerState<NgpSubmenuTrigger<T>>(this);\n\n constructor() {\n // by default the menu opens below and to the center of the trigger,\n // but as this is a submenu we want to default to opening to the right\n // and to the start\n this.menuTrigger().placement.set('right-start');\n\n this.parentMenu?.closeSubmenus.pipe(takeUntilDestroyed()).subscribe(element => {\n // if the element is not the trigger, we want to close the menu\n if (element === this.trigger.nativeElement) {\n return;\n }\n\n this.hide('mouse');\n });\n }\n\n protected toggle(event: MouseEvent): void {\n // if the trigger is disabled then do not toggle the menu\n if (this.state.disabled()) {\n return;\n }\n\n // determine the origin of the event, 0 is keyboard, 1 is mouse\n const origin: FocusOrigin = event.detail === 0 ? 'keyboard' : 'mouse';\n\n // if the menu is open then hide it\n if (this.open()) {\n this.hide(origin);\n } else {\n this.show();\n }\n }\n\n /**\n * Show the menu.\n */\n show(): void {\n // If the trigger is disabled, don't show the menu\n if (this.state.disabled()) {\n return;\n }\n\n // Create the overlay if it doesn't exist yet\n if (!this.overlay()) {\n this.createOverlay();\n }\n\n // Show the overlay\n this.overlay()?.show();\n }\n\n /**\n * @internal\n * Hide the menu.\n */\n hide(origin: FocusOrigin = 'program'): void {\n // If the trigger is disabled or the menu is not open, do nothing\n if (this.state.disabled() || !this.open()) {\n return;\n }\n\n // Hide the overlay\n this.overlay()?.hide({ origin });\n }\n\n /**\n * Create the overlay that will contain the menu\n */\n private createOverlay(): void {\n const menu = this.state.menu();\n\n if (!menu) {\n throw new Error('Menu must be either a TemplateRef or a ComponentType');\n }\n\n // Create config for the overlay\n const config: NgpOverlayConfig<T> = {\n content: menu,\n triggerElement: this.trigger.nativeElement,\n injector: this.injector,\n placement: this.state.placement(),\n offset: this.state.offset(),\n flip: this.state.flip(),\n closeOnOutsideClick: true,\n closeOnEscape: true,\n restoreFocus: true,\n };\n\n this.overlay.set(createOverlay(config));\n }\n\n /**\n * If the user presses the right arrow key, we want to open the submenu\n * and focus the first item in the submenu.\n * This behavior will be inverted if the direction is RTL.\n * @param event\n */\n @HostListener('keydown.ArrowRight', ['$event'])\n @HostListener('keydown.ArrowLeft', ['$event'])\n protected showSubmenuOnArrow(event: KeyboardEvent): void {\n const direction = getComputedStyle(this.trigger.nativeElement).direction;\n\n const isRtl = direction === 'rtl';\n\n const isRightArrow = event.key === 'ArrowRight';\n const isLeftArrow = event.key === 'ArrowLeft';\n\n if ((isRightArrow && !isRtl) || (isLeftArrow && isRtl)) {\n event.preventDefault();\n this.show();\n }\n }\n\n /**\n * If the user hovers over the trigger, we want to open the submenu\n */\n @HostListener('mouseenter')\n protected showSubmenuOnHover(): void {\n this.show();\n }\n}\n","import { FocusOrigin } from '@angular/cdk/a11y';\nimport { Directive, HostListener, inject, Injector } from '@angular/core';\nimport { NgpButton } from 'ng-primitives/button';\nimport { injectElementRef } from 'ng-primitives/internal';\nimport { NgpRovingFocusItem } from 'ng-primitives/roving-focus';\nimport { injectMenu } from '../menu/menu-token';\nimport { NgpSubmenuTrigger } from '../submenu-trigger/submenu-trigger';\n\n/**\n * The `NgpMenuItem` directive represents a menu item.\n */\n@Directive({\n selector: '[ngpMenuItem]',\n exportAs: 'ngpMenuItem',\n hostDirectives: [\n { directive: NgpButton, inputs: ['disabled: ngpMenuItemDisabled'] },\n NgpRovingFocusItem,\n ],\n host: {\n role: 'menuitem',\n '(click)': 'onClick($event)',\n '(keydown.ArrowLeft)': 'handleArrowKey($event)',\n '(keydown.ArrowRight)': 'handleArrowKey($event)',\n },\n})\nexport class NgpMenuItem {\n /** Access the injector */\n private readonly injector = inject(Injector);\n /** Access the button element */\n private readonly elementRef = injectElementRef();\n\n /** Access the parent menu */\n private readonly parentMenu = injectMenu();\n\n /** Close the menu when the item is clicked */\n protected onClick(event: MouseEvent): void {\n // we do this here to avoid circular dependency issues\n const trigger = this.injector.get(NgpSubmenuTrigger, null, { self: true, optional: true });\n\n const origin: FocusOrigin = event.detail === 0 ? 'keyboard' : 'mouse';\n\n // if this is a submenu trigger, we don't want to close the menu, we want to open the submenu\n if (!trigger) {\n this.parentMenu?.closeAllMenus(origin);\n }\n }\n\n /**\n * If the user presses the left arrow key (in LTR) and there is a parent menu,\n * we want to close the menu and focus the parent menu item.\n */\n protected handleArrowKey(event: KeyboardEvent): void {\n // if there is no parent menu, we don't want to do anything\n const trigger = this.injector.get(NgpSubmenuTrigger, null, { optional: true });\n\n if (!trigger) {\n return;\n }\n\n const direction = getComputedStyle(this.elementRef.nativeElement).direction;\n const isRtl = direction === 'rtl';\n\n const isLeftArrow = event.key === 'ArrowLeft';\n const isRightArrow = event.key === 'ArrowRight';\n\n if ((isLeftArrow && !isRtl) || (isRightArrow && isRtl)) {\n event.preventDefault();\n\n if (trigger) {\n trigger.hide('keyboard');\n }\n }\n }\n\n /**\n * If the user hovers over the trigger, we want to open the submenu\n */\n @HostListener('mouseenter')\n protected showSubmenuOnHover(): void {\n this.parentMenu?.closeSubmenus.next(this.elementRef.nativeElement);\n }\n}\n","import { FocusOrigin } from '@angular/cdk/a11y';\nimport { BooleanInput, NumberInput } from '@angular/cdk/coercion';\nimport {\n booleanAttribute,\n computed,\n Directive,\n inject,\n Injector,\n input,\n numberAttribute,\n OnDestroy,\n signal,\n} from '@angular/core';\nimport { Placement } from '@floating-ui/dom';\nimport { injectElementRef, provideExitAnimationManager } from 'ng-primitives/internal';\nimport {\n createOverlay,\n NgpOverlay,\n NgpOverlayConfig,\n NgpOverlayContent,\n} from 'ng-primitives/portal';\nimport { injectMenuConfig } from '../config/menu-config';\nimport { menuTriggerState, provideMenuTriggerState } from './menu-trigger-state';\n\n/**\n * The `NgpMenuTrigger` directive allows you to turn an element into a menu trigger.\n */\n@Directive({\n selector: '[ngpMenuTrigger]',\n exportAs: 'ngpMenuTrigger',\n providers: [provideMenuTriggerState({ inherit: false }), provideExitAnimationManager()],\n host: {\n 'aria-haspopup': 'true',\n '[attr.aria-expanded]': 'open() ? \"true\" : \"false\"',\n '[attr.data-open]': 'open() ? \"\" : null',\n '[attr.data-placement]': 'state.placement()',\n '(click)': 'toggle($event)',\n },\n})\nexport class NgpMenuTrigger<T = unknown> implements OnDestroy {\n /**\n * Access the trigger element\n */\n private readonly trigger = injectElementRef();\n\n /**\n * Access the injector.\n */\n private readonly injector = inject(Injector);\n\n /**\n * Access the global menu configuration.\n */\n private readonly config = injectMenuConfig();\n\n /**\n * Access the menu template ref.\n */\n readonly menu = input<NgpOverlayContent<T>>(undefined, {\n alias: 'ngpMenuTrigger',\n });\n\n /**\n * Define if the trigger should be disabled.\n * @default false\n */\n readonly disabled = input<boolean, BooleanInput>(false, {\n alias: 'ngpMenuTriggerDisabled',\n transform: booleanAttribute,\n });\n\n /**\n * Define the placement of the menu relative to the trigger.\n * @default 'bottom-start'\n */\n readonly placement = input<Placement>(this.config.placement, {\n alias: 'ngpMenuTriggerPlacement',\n });\n\n /**\n * Define the offset of the menu relative to the trigger.\n * @default 0\n */\n readonly offset = input<number, NumberInput>(this.config.offset, {\n alias: 'ngpMenuTriggerOffset',\n transform: numberAttribute,\n });\n\n /**\n * Define whether the menu should flip when there is not enough space for the menu.\n * @default true\n */\n readonly flip = input<boolean, BooleanInput>(this.config.flip, {\n alias: 'ngpMenuTriggerFlip',\n transform: booleanAttribute,\n });\n\n /**\n * Define the container in which the menu should be attached.\n * @default document.body\n */\n readonly container = input<HTMLElement | null>(this.config.container, {\n alias: 'ngpMenuTriggerContainer',\n });\n\n /**\n * Defines how the menu behaves when the window is scrolled.\n * @default 'block'\n */\n readonly scrollBehavior = input<'reposition' | 'block'>(this.config.scrollBehavior, {\n alias: 'ngpMenuTriggerScrollBehavior',\n });\n\n /**\n * Provide context to the menu. This can be used to pass data to the menu content.\n */\n readonly context = input<T>(undefined, {\n alias: 'ngpMenuTriggerContext',\n });\n\n /**\n * The overlay that manages the menu\n * @internal\n */\n readonly overlay = signal<NgpOverlay<T> | null>(null);\n\n /**\n * The open state of the menu.\n * @internal\n */\n readonly open = computed(() => this.overlay()?.isOpen() ?? false);\n\n /**\n * The menu trigger state.\n */\n readonly state = menuTriggerState<NgpMenuTrigger<T>>(this);\n\n ngOnDestroy(): void {\n this.overlay()?.destroy();\n }\n\n protected toggle(event: MouseEvent): void {\n // if the trigger is disabled then do not toggle the menu\n if (this.state.disabled()) {\n return;\n }\n\n // determine the origin of the event, 0 is keyboard, 1 is mouse\n const origin: FocusOrigin = event.detail === 0 ? 'keyboard' : 'mouse';\n\n // if the menu is open then hide it\n if (this.open()) {\n this.hide(origin);\n } else {\n this.show();\n }\n }\n\n /**\n * Show the menu.\n */\n show(): void {\n // If the trigger is disabled, don't show the menu\n if (this.state.disabled()) {\n return;\n }\n\n // Create the overlay if it doesn't exist yet\n if (!this.overlay()) {\n this.createOverlay();\n }\n\n // Show the overlay\n this.overlay()?.show();\n }\n\n /**\n * @internal\n * Hide the menu.\n */\n hide(origin: FocusOrigin = 'program'): void {\n // If the trigger is disabled or the menu is not open, do nothing\n if (this.state.disabled() || !this.open()) {\n return;\n }\n\n // Hide the overlay\n this.overlay()?.hide({ origin });\n }\n\n /**\n * Create the overlay that will contain the menu\n */\n private createOverlay(): void {\n const menu = this.state.menu();\n\n if (!menu) {\n throw new Error('Menu must be either a TemplateRef or a ComponentType');\n }\n\n // Create config for the overlay\n const config: NgpOverlayConfig<T> = {\n content: menu,\n triggerElement: this.trigger.nativeElement,\n injector: this.injector,\n context: this.state.context(),\n container: this.state.container(),\n placement: this.state.placement(),\n offset: this.state.offset(),\n flip: this.state.flip(),\n closeOnOutsideClick: true,\n closeOnEscape: true,\n restoreFocus: true,\n scrollBehaviour: this.state.scrollBehavior(),\n };\n\n this.overlay.set(createOverlay(config));\n }\n}\n","import { FocusOrigin } from '@angular/cdk/a11y';\nimport { Directive, inject } from '@angular/core';\nimport { NgpPopover } from 'ng-primitives/popover';\nimport { injectOverlay } from 'ng-primitives/portal';\nimport { NgpRovingFocusGroup, provideRovingFocusGroup } from 'ng-primitives/roving-focus';\nimport { Subject } from 'rxjs';\nimport { injectMenuTriggerState } from '../menu-trigger/menu-trigger-state';\nimport { NgpMenuToken, provideMenu } from './menu-token';\n\n/**\n * The `NgpMenu` is a container for menu items.\n */\n@Directive({\n selector: '[ngpMenu]',\n exportAs: 'ngpMenu',\n hostDirectives: [NgpPopover, NgpRovingFocusGroup],\n providers: [\n // ensure we don't inherit the focus group from the parent menu if there is one\n provideRovingFocusGroup(NgpRovingFocusGroup, { inherit: false }),\n provideMenu(NgpMenu),\n ],\n host: {\n role: 'menu',\n '[style.left.px]': 'overlay.position().x',\n '[style.top.px]': 'overlay.position().y',\n '[style.--ngp-menu-trigger-width.px]': 'overlay.triggerWidth()',\n '[style.--ngp-menu-transform-origin]': 'overlay.transformOrigin()',\n },\n})\nexport class NgpMenu {\n /**\n * Access the overlay.\n */\n protected readonly overlay = injectOverlay();\n\n /** Access the menu trigger state */\n private readonly menuTrigger = injectMenuTriggerState();\n\n /** Access any parent menus */\n private readonly parentMenu = inject(NgpMenuToken, { optional: true, skipSelf: true });\n\n /** @internal Whether we should close submenus */\n readonly closeSubmenus = new Subject<HTMLElement>();\n\n /** Close the menu and any parent menus */\n closeAllMenus(origin: FocusOrigin): void {\n this.menuTrigger().hide(origin);\n this.parentMenu?.closeAllMenus(origin);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1"],"mappings":"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"}
@@ -1,18 +1,12 @@
1
+ import { createOverlay, injectOverlay } from 'ng-primitives/portal';
2
+ export { injectOverlayContext as injectPopoverContext } from 'ng-primitives/portal';
1
3
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, ViewContainerRef, Injector, input, booleanAttribute, numberAttribute, signal, computed, Directive } from '@angular/core';
3
- import { FocusMonitor, InteractivityChecker } from '@angular/cdk/a11y';
4
- import { ViewportRuler, BlockScrollStrategy, NoopScrollStrategy } from '@angular/cdk/overlay';
5
- import { DOCUMENT } from '@angular/common';
6
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
7
- import { offset, shift, flip, autoUpdate, computePosition } from '@floating-ui/dom';
4
+ import { InjectionToken, inject, Injector, input, booleanAttribute, numberAttribute, signal, computed, Directive } from '@angular/core';
8
5
  import * as i2 from 'ng-primitives/internal';
9
- import { injectElementRef, injectExitAnimationManager, provideExitAnimationManager, NgpExitAnimation } from 'ng-primitives/internal';
10
- import { createPortal } from 'ng-primitives/portal';
11
- import { fromResizeEvent } from 'ng-primitives/resize';
12
- import { injectDisposables } from 'ng-primitives/utils';
6
+ import { injectElementRef, provideExitAnimationManager, NgpExitAnimation } from 'ng-primitives/internal';
13
7
  import { createStateToken, createStateProvider, createStateInjector, createState } from 'ng-primitives/state';
14
8
  import * as i1 from 'ng-primitives/focus-trap';
15
- import { injectFocusTrapState, NgpFocusTrap } from 'ng-primitives/focus-trap';
9
+ import { NgpFocusTrap } from 'ng-primitives/focus-trap';
16
10
 
17
11
  const defaultPopoverConfig = {
18
12
  offset: 4,
@@ -47,20 +41,6 @@ function injectPopoverConfig() {
47
41
  return inject(NgpPopoverConfigToken, { optional: true }) ?? defaultPopoverConfig;
48
42
  }
49
43
 
50
- const NgpPopoverContextToken = new InjectionToken('NgpPopoverContextToken');
51
- /**
52
- * Inject the Popover context
53
- */
54
- function injectPopoverContext() {
55
- return inject(NgpPopoverContextToken);
56
- }
57
- /**
58
- * Provide the Popover context
59
- */
60
- function providePopoverContext(context) {
61
- return { provide: NgpPopoverContextToken, useValue: context };
62
- }
63
-
64
44
  /**
65
45
  * The state token for the PopoverTrigger primitive.
66
46
  */
@@ -87,29 +67,6 @@ class NgpPopoverTrigger {
87
67
  * Access the trigger element
88
68
  */
89
69
  this.trigger = injectElementRef();
90
- /**
91
- * Access the exit animation state.
92
- */
93
- this.exitAnimationState = injectExitAnimationManager();
94
- /**
95
- * Inject the parent popover trigger if available.
96
- */
97
- this.parentTrigger = injectPopoverTriggerState({
98
- skipSelf: true,
99
- optional: true,
100
- });
101
- /**
102
- * Access the view container ref.
103
- */
104
- this.viewContainerRef = inject(ViewContainerRef);
105
- /**
106
- * Access the document.
107
- */
108
- this.document = inject(DOCUMENT);
109
- /**
110
- * Access the viewport ruler.
111
- */
112
- this.viewportRuler = inject(ViewportRuler);
113
70
  /**
114
71
  * Access the injector.
115
72
  */
@@ -118,18 +75,10 @@ class NgpPopoverTrigger {
118
75
  * Access the global popover configuration.
119
76
  */
120
77
  this.config = injectPopoverConfig();
121
- /**
122
- * Access the disposable utilities
123
- */
124
- this.disposables = injectDisposables();
125
- /**
126
- * Access the focus monitor.
127
- */
128
- this.focusMonitor = inject(FocusMonitor);
129
78
  /**
130
79
  * Access the popover template ref.
131
80
  */
132
- this.popover = input(null, {
81
+ this.popover = input(undefined, {
133
82
  alias: 'ngpPopoverTrigger',
134
83
  });
135
84
  /**
@@ -210,77 +159,30 @@ class NgpPopoverTrigger {
210
159
  alias: 'ngpPopoverTriggerScrollBehavior',
211
160
  });
212
161
  /**
213
- * Provide context to the popover.
214
- * @default null
162
+ * Provide context to the popover. This can be used to pass data to the popover content.
215
163
  */
216
- this.context = input(null, {
164
+ this.context = input(undefined, {
217
165
  alias: 'ngpPopoverTriggerContext',
218
166
  });
219
167
  /**
220
- * Store the popover view ref.
221
- */
222
- this.viewRef = signal(undefined);
223
- /**
224
- * Determines if the popover is open.
225
- */
226
- this.open = computed(() => this.viewRef()?.getAttached() ?? false);
227
- /**
228
- * Derive the popover middleware from the provided configuration.
229
- */
230
- this.middleware = computed(() => {
231
- const middleware = [offset(this.state.offset()), shift()];
232
- if (this.state.flip()) {
233
- middleware.push(flip());
234
- }
235
- return middleware;
236
- });
237
- /**
238
- * Store the computed position of the popover.
239
- * @internal
240
- */
241
- this.position = signal({
242
- x: 0,
243
- y: 0,
244
- });
245
- /**
168
+ * The overlay that manages the popover
246
169
  * @internal
247
- * Store the trigger width.
248
170
  */
249
- this.width = signal(null);
171
+ this.overlay = signal(null);
250
172
  /**
251
- * Store the popover instance.
173
+ * The open state of the popover.
252
174
  * @internal
253
175
  */
254
- this.popoverInstance = null;
255
- /**
256
- * Get the scroll strategy based on the configuration.
257
- */
258
- this.scrollStrategy = computed(() => this.state.scrollBehavior() === 'block'
259
- ? new BlockScrollStrategy(this.viewportRuler, this.document)
260
- : new NoopScrollStrategy());
261
- /**
262
- * @internal
263
- * Register any child popover to the stack.
264
- */
265
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
266
- this.stack = [];
176
+ this.open = computed(() => this.overlay()?.isOpen() ?? false);
267
177
  /**
268
178
  * The popover trigger state.
269
179
  */
270
180
  this.state = popoverTriggerState(this);
271
- // if the trigger has a parent trigger then register it to the stack
272
- this.parentTrigger()?.stack.push(this);
273
- // update the width of the trigger when it resizes
274
- fromResizeEvent(this.trigger.nativeElement)
275
- .pipe(takeUntilDestroyed())
276
- .subscribe(() => this.width.set(this.trigger.nativeElement.offsetWidth));
277
181
  }
278
182
  ngOnDestroy() {
279
- // remove the trigger from the parent trigger's stack
280
- this.parentTrigger()?.stack.splice(this.parentTrigger()?.stack.indexOf(this), 1);
281
- this.destroyPopover();
183
+ this.overlay()?.destroy();
282
184
  }
283
- toggleOpenState(event) {
185
+ toggle(event) {
284
186
  // if the trigger is disabled then do not toggle the popover
285
187
  if (this.state.disabled()) {
286
188
  return;
@@ -292,150 +194,65 @@ class NgpPopoverTrigger {
292
194
  this.hide(origin);
293
195
  }
294
196
  else {
295
- this.show(origin);
197
+ this.show();
296
198
  }
297
199
  }
298
200
  /**
299
201
  * Show the popover.
300
202
  */
301
- show(origin) {
302
- // if closing is in progress then clear the timeout to stop the popover from closing
303
- this.closeTimeout?.();
304
- // if the trigger is disabled or the popover is already open then do not show the popover
305
- if (this.state.disabled() || this.openTimeout) {
203
+ show() {
204
+ // If the trigger is disabled, don't show the popover
205
+ if (this.state.disabled()) {
306
206
  return;
307
207
  }
308
- this.openTimeout = this.disposables.setTimeout(() => {
309
- this.openTimeout = undefined;
310
- this.createPopover(origin);
311
- }, this.state.showDelay());
312
- // Add document click listener to detect outside clicks
313
- if (this.state.closeOnOutsideClick()) {
314
- this.documentClickListener = this.onDocumentClick.bind(this);
315
- this.document.addEventListener('mouseup', this.documentClickListener, true);
208
+ // Create the overlay if it doesn't exist yet
209
+ if (!this.overlay()) {
210
+ this.createOverlay();
316
211
  }
212
+ // Show the overlay
213
+ this.overlay()?.show();
317
214
  }
318
215
  /**
319
216
  * @internal
320
217
  * Hide the popover.
321
218
  */
322
219
  hide(origin = 'program') {
323
- // if opening is in progress then clear the timeout to stop the popover from opening
324
- this.openTimeout?.();
325
- // if the trigger is disabled or the popover is not open then do not hide the popover
326
- if (this.state.disabled() || this.closeTimeout || !this.open()) {
220
+ // If the trigger is disabled or the popover is not open, do nothing
221
+ if (this.state.disabled() || !this.open()) {
327
222
  return;
328
223
  }
329
- // we must disable the focus trap before closing the popover, otherwise
330
- // focus will be moved back to the popover rather than the trigger
331
- this.popoverInstance?.disableFocusTrap();
332
- // close all child popovers
333
- for (const child of this.stack) {
334
- child.hide(origin);
335
- }
336
- // ensure the trigger is focused after closing the popover
337
- this.focusTrigger(origin);
338
- this.closeTimeout = this.disposables.setTimeout(async () => {
339
- this.closeTimeout = undefined;
340
- await this.destroyPopover();
341
- }, this.state.hideDelay());
342
- }
343
- onDocumentClick(event) {
344
- const target = event.target;
345
- const viewRef = this.viewRef();
346
- // get the popover element
347
- const popoverElement = viewRef?.getElements()[0];
348
- // Check if the click is outside the trigger or the popover
349
- const isOutside = !this.trigger.nativeElement.contains(target) && !popoverElement?.contains(target);
350
- // Determine if this is a click inside another popover
351
- if (isOutside) {
352
- // Close the popover
353
- this.hide('mouse');
354
- }
224
+ // Hide the overlay
225
+ this.overlay()?.hide({ origin });
355
226
  }
356
- createPopover(origin) {
357
- // clear the open timeout
358
- this.openTimeout = undefined;
227
+ /**
228
+ * Create the overlay that will contain the popover
229
+ */
230
+ createOverlay() {
359
231
  const popover = this.state.popover();
360
232
  if (!popover) {
361
233
  throw new Error('Popover must be either a TemplateRef or a ComponentType');
362
234
  }
363
- // Create a new inject with the tooltip context
364
- const injector = Injector.create({
365
- parent: this.injector,
366
- providers: [providePopoverContext(this.state.context())],
367
- });
368
- const portal = createPortal(popover, this.viewContainerRef, injector, {
369
- $implicit: this.state.context(),
370
- });
371
- const viewRef = portal.attach(this.state.container() ?? this.document.body);
372
- this.viewRef.set(viewRef);
373
- viewRef.detectChanges();
374
- const outletElement = viewRef.getElements()[0];
375
- if (!outletElement) {
376
- throw new Error('Outlet element is not available.');
377
- }
378
- if (viewRef.getElements().length > 1) {
379
- throw new Error('Popover must have only one root element.');
380
- }
381
- // determine if the popover is fixed or absolute
382
- const strategy = getComputedStyle(outletElement).position === 'fixed' ? 'fixed' : 'absolute';
383
- this.dispose = autoUpdate(this.trigger.nativeElement, outletElement, async () => {
384
- const position = await computePosition(this.trigger.nativeElement, outletElement, {
385
- placement: this.state.placement(),
386
- middleware: this.middleware(),
387
- strategy,
388
- });
389
- this.position.set({ x: position.x, y: position.y });
390
- viewRef?.detectChanges();
391
- });
392
- // activate the scroll strategy
393
- this.scrollStrategy().enable();
394
- // set the initial focus to the first tabbable element in the popover
395
- this.popoverInstance?.setInitialFocus(origin);
396
- }
397
- async destroyPopover() {
398
- // clear the close timeout
399
- this.closeTimeout = undefined;
400
- const viewRef = this.viewRef();
401
- if (!viewRef) {
402
- return;
403
- }
404
- // we remove this to prevent the popover from being destroyed twice
405
- // because ngOnDestroy will be called on the viewRef
406
- // when the popover is destroyed triggering this method again
407
- this.viewRef.set(undefined);
408
- // destroy the view ref
409
- viewRef.detach();
410
- this.dispose?.();
411
- // deactivate the scroll strategy
412
- this.scrollStrategy().disable();
413
- // Remove the document click listener when the popover is hidden
414
- if (this.documentClickListener) {
415
- this.document.removeEventListener('mouseup', this.documentClickListener, true);
416
- }
417
- }
418
- /**
419
- * @internal
420
- * Handle escape key press to close the popover.
421
- */
422
- handleEscapeKey() {
423
- if (this.state.closeOnEscape()) {
424
- this.hide('keyboard');
425
- }
426
- }
427
- focusTrigger(origin) {
428
- this.focusMonitor.focusVia(this.trigger.nativeElement, origin);
429
- }
430
- /**
431
- * Set the popover instance.
432
- * @internal
433
- */
434
- setPopover(instance) {
435
- this.popoverInstance = instance;
235
+ // Create config for the overlay
236
+ const config = {
237
+ content: popover,
238
+ triggerElement: this.trigger.nativeElement,
239
+ injector: this.injector,
240
+ context: this.state.context(),
241
+ container: this.state.container(),
242
+ placement: this.state.placement(),
243
+ offset: this.state.offset(),
244
+ flip: this.state.flip(),
245
+ showDelay: this.state.showDelay(),
246
+ hideDelay: this.state.hideDelay(),
247
+ closeOnOutsideClick: this.state.closeOnOutsideClick(),
248
+ closeOnEscape: this.state.closeOnEscape(),
249
+ restoreFocus: true,
250
+ scrollBehaviour: this.state.scrollBehavior(),
251
+ };
252
+ this.overlay.set(createOverlay(config));
436
253
  }
437
254
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: NgpPopoverTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
438
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.11", type: NgpPopoverTrigger, isStandalone: true, selector: "[ngpPopoverTrigger]", inputs: { popover: { classPropertyName: "popover", publicName: "ngpPopoverTrigger", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "ngpPopoverTriggerDisabled", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "ngpPopoverTriggerPlacement", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "ngpPopoverTriggerOffset", isSignal: true, isRequired: false, transformFunction: null }, showDelay: { classPropertyName: "showDelay", publicName: "ngpPopoverTriggerShowDelay", isSignal: true, isRequired: false, transformFunction: null }, hideDelay: { classPropertyName: "hideDelay", publicName: "ngpPopoverTriggerHideDelay", isSignal: true, isRequired: false, transformFunction: null }, flip: { classPropertyName: "flip", publicName: "ngpPopoverTriggerFlip", isSignal: true, isRequired: false, transformFunction: null }, container: { classPropertyName: "container", publicName: "ngpPopoverTriggerContainer", isSignal: true, isRequired: false, transformFunction: null }, closeOnOutsideClick: { classPropertyName: "closeOnOutsideClick", publicName: "ngpPopoverTriggerCloseOnOutsideClick", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "ngpPopoverTriggerCloseOnEscape", isSignal: true, isRequired: false, transformFunction: null }, scrollBehavior: { classPropertyName: "scrollBehavior", publicName: "ngpPopoverTriggerScrollBehavior", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "ngpPopoverTriggerContext", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "toggleOpenState($event)", "document:keydown.escape": "handleEscapeKey()" }, properties: { "attr.aria-expanded": "open() ? \"true\" : \"false\"", "attr.data-open": "open() ? \"\" : null", "attr.data-placement": "state.placement()" } }, providers: [providePopoverTriggerState({ inherit: false }), provideExitAnimationManager()], exportAs: ["ngpPopoverTrigger"], ngImport: i0 }); }
255
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.11", type: NgpPopoverTrigger, isStandalone: true, selector: "[ngpPopoverTrigger]", inputs: { popover: { classPropertyName: "popover", publicName: "ngpPopoverTrigger", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "ngpPopoverTriggerDisabled", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "ngpPopoverTriggerPlacement", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "ngpPopoverTriggerOffset", isSignal: true, isRequired: false, transformFunction: null }, showDelay: { classPropertyName: "showDelay", publicName: "ngpPopoverTriggerShowDelay", isSignal: true, isRequired: false, transformFunction: null }, hideDelay: { classPropertyName: "hideDelay", publicName: "ngpPopoverTriggerHideDelay", isSignal: true, isRequired: false, transformFunction: null }, flip: { classPropertyName: "flip", publicName: "ngpPopoverTriggerFlip", isSignal: true, isRequired: false, transformFunction: null }, container: { classPropertyName: "container", publicName: "ngpPopoverTriggerContainer", isSignal: true, isRequired: false, transformFunction: null }, closeOnOutsideClick: { classPropertyName: "closeOnOutsideClick", publicName: "ngpPopoverTriggerCloseOnOutsideClick", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "ngpPopoverTriggerCloseOnEscape", isSignal: true, isRequired: false, transformFunction: null }, scrollBehavior: { classPropertyName: "scrollBehavior", publicName: "ngpPopoverTriggerScrollBehavior", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "ngpPopoverTriggerContext", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "toggle($event)" }, properties: { "attr.aria-expanded": "open() ? \"true\" : \"false\"", "attr.data-open": "open() ? \"\" : null", "attr.data-placement": "state.placement()" } }, providers: [providePopoverTriggerState({ inherit: false }), provideExitAnimationManager()], exportAs: ["ngpPopoverTrigger"], ngImport: i0 }); }
439
256
  }
440
257
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: NgpPopoverTrigger, decorators: [{
441
258
  type: Directive,
@@ -447,39 +264,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImpo
447
264
  '[attr.aria-expanded]': 'open() ? "true" : "false"',
448
265
  '[attr.data-open]': 'open() ? "" : null',
449
266
  '[attr.data-placement]': 'state.placement()',
450
- '(click)': 'toggleOpenState($event)',
451
- '(document:keydown.escape)': 'handleEscapeKey()',
267
+ '(click)': 'toggle($event)',
452
268
  },
453
269
  }]
454
- }], ctorParameters: () => [] });
455
-
456
- function getTransformOrigin(placement) {
457
- const basePlacement = placement.split('-')[0]; // Extract "top", "bottom", etc.
458
- const alignment = placement.split('-')[1]; // Extract "start" or "end"
459
- const map = {
460
- top: 'bottom',
461
- bottom: 'top',
462
- left: 'right',
463
- right: 'left',
464
- };
465
- let x = 'center';
466
- let y = 'center';
467
- if (basePlacement === 'top' || basePlacement === 'bottom') {
468
- y = map[basePlacement];
469
- if (alignment === 'start')
470
- x = 'left';
471
- else if (alignment === 'end')
472
- x = 'right';
473
- }
474
- else {
475
- x = map[basePlacement];
476
- if (alignment === 'start')
477
- y = 'top';
478
- else if (alignment === 'end')
479
- y = 'bottom';
480
- }
481
- return `${y} ${x}`;
482
- }
270
+ }] });
483
271
 
484
272
  /**
485
273
  * Apply the `ngpPopover` directive to an element that represents the popover. This typically would be a `div` inside an `ng-template`.
@@ -487,69 +275,12 @@ function getTransformOrigin(placement) {
487
275
  class NgpPopover {
488
276
  constructor() {
489
277
  /**
490
- * Access the popover element.
491
- */
492
- this.popover = injectElementRef();
493
- /**
494
- * Access the focus trap.
495
- */
496
- this.focusTrap = injectFocusTrapState();
497
- /**
498
- * Access the interactivity checker.
499
- */
500
- this.interactivity = inject(InteractivityChecker);
501
- /**
502
- * Access the focus monitor.
503
- */
504
- this.focusMonitor = inject(FocusMonitor);
505
- /**
506
- * Access the trigger instance.
507
- */
508
- this.trigger = injectPopoverTriggerState();
509
- /**
510
- * Compute the x position of the popover.
511
- */
512
- this.x = computed(() => this.trigger().position().x);
513
- /**
514
- * Compute the y position of the popover.
278
+ * Access the overlay.
515
279
  */
516
- this.y = computed(() => this.trigger().position().y);
517
- /**
518
- * Derive the transform origin of the popover.
519
- */
520
- this.transformOrigin = computed(() => getTransformOrigin(this.trigger().placement()));
521
- this.trigger().setPopover(this);
522
- }
523
- /**
524
- * Focus the first tabbable element inside the popover.
525
- * If no tabbable element is found, focus the popover itself.
526
- * @internal
527
- */
528
- setInitialFocus(origin) {
529
- // use a tree walker to find the first tabbable child
530
- const treeWalker = document.createTreeWalker(this.popover.nativeElement, NodeFilter.SHOW_ELEMENT, {
531
- acceptNode: node => node instanceof HTMLElement && this.interactivity.isTabbable(node)
532
- ? NodeFilter.FILTER_ACCEPT
533
- : NodeFilter.FILTER_SKIP,
534
- });
535
- const tabbableNode = treeWalker.nextNode();
536
- if (tabbableNode) {
537
- this.focusMonitor.focusVia(tabbableNode, origin);
538
- }
539
- else {
540
- // if no tabbable child is found, focus the popover element itself
541
- this.popover.nativeElement.focus();
542
- }
543
- }
544
- /**
545
- * Disable the focus trap.
546
- * @internal
547
- */
548
- disableFocusTrap() {
549
- this.focusTrap().disabled.set(true);
280
+ this.overlay = injectOverlay();
550
281
  }
551
282
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: NgpPopover, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
552
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.11", type: NgpPopover, isStandalone: true, selector: "[ngpPopover]", host: { attributes: { "role": "menu" }, listeners: { "keydown.escape": "trigger().handleEscapeKey()" }, properties: { "style.left.px": "x()", "style.top.px": "y()", "style.--ngp-popover-trigger-width.px": "trigger().width()", "style.--ngp-popover-transform-origin": "transformOrigin()" } }, exportAs: ["ngpPopover"], hostDirectives: [{ directive: i1.NgpFocusTrap }, { directive: i2.NgpExitAnimation }], ngImport: i0 }); }
283
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.11", type: NgpPopover, isStandalone: true, selector: "[ngpPopover]", host: { attributes: { "role": "dialog" }, properties: { "style.left.px": "overlay.position().x", "style.top.px": "overlay.position().y", "style.--ngp-popover-trigger-width.px": "overlay.triggerWidth()", "style.--ngp-popover-transform-origin": "overlay.transformOrigin()" } }, exportAs: ["ngpPopover"], hostDirectives: [{ directive: i1.NgpFocusTrap }, { directive: i2.NgpExitAnimation }], ngImport: i0 }); }
553
284
  }
554
285
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: NgpPopover, decorators: [{
555
286
  type: Directive,
@@ -558,19 +289,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImpo
558
289
  exportAs: 'ngpPopover',
559
290
  hostDirectives: [NgpFocusTrap, NgpExitAnimation],
560
291
  host: {
561
- role: 'menu',
562
- '[style.left.px]': 'x()',
563
- '[style.top.px]': 'y()',
564
- '[style.--ngp-popover-trigger-width.px]': 'trigger().width()',
565
- '[style.--ngp-popover-transform-origin]': 'transformOrigin()',
566
- '(keydown.escape)': 'trigger().handleEscapeKey()',
292
+ role: 'dialog',
293
+ '[style.left.px]': 'overlay.position().x',
294
+ '[style.top.px]': 'overlay.position().y',
295
+ '[style.--ngp-popover-trigger-width.px]': 'overlay.triggerWidth()',
296
+ '[style.--ngp-popover-transform-origin]': 'overlay.transformOrigin()',
567
297
  },
568
298
  }]
569
- }], ctorParameters: () => [] });
299
+ }] });
570
300
 
571
301
  /**
572
302
  * Generated bundle index. Do not edit.
573
303
  */
574
304
 
575
- export { NgpPopover, NgpPopoverContextToken, NgpPopoverTrigger, getTransformOrigin, injectPopoverContext, injectPopoverTriggerState, providePopoverConfig, providePopoverTriggerState };
305
+ export { NgpPopover, NgpPopoverTrigger, injectPopoverTriggerState, providePopoverConfig, providePopoverTriggerState };
576
306
  //# sourceMappingURL=ng-primitives-popover.mjs.map