@joanroucoux/cairn-ui 0.11.0 → 0.11.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.11.1
4
+
5
+ ### Fixed
6
+
7
+ - `ui-menu` keeps its 8px margin from the edge of the page, not from the window, so a classic scrollbar no longer covers part of it near the right edge.
8
+
3
9
  ## 0.11.0
4
10
 
5
11
  ### Changed
@@ -193,16 +193,17 @@ var UiMenu = class UiMenu {
193
193
  }
194
194
  #position(trigger) {
195
195
  const margin = 8;
196
+ const { clientWidth: viewportWidth, clientHeight: viewportHeight } = document.documentElement;
196
197
  const triggerRect = trigger.getBoundingClientRect();
197
198
  const menuRect = {
198
199
  width: this.#layoutWidth(),
199
200
  height: this.#host.offsetHeight
200
201
  };
201
- const fitsBelow = window.innerHeight - triggerRect.bottom >= menuRect.height + margin;
202
+ const fitsBelow = viewportHeight - triggerRect.bottom >= menuRect.height + margin;
202
203
  const top = fitsBelow ? triggerRect.bottom + 4 : Math.max(margin, triggerRect.top - menuRect.height - 4);
203
- const left = Math.min(Math.max(triggerRect.right - menuRect.width, margin), window.innerWidth - menuRect.width - margin);
204
+ const left = Math.min(Math.max(triggerRect.right - menuRect.width, margin), viewportWidth - menuRect.width - margin);
204
205
  this.#host.style.position = "fixed";
205
- this.#host.style.top = `${Math.min(top, window.innerHeight - menuRect.height - margin)}px`;
206
+ this.#host.style.top = `${Math.min(top, viewportHeight - menuRect.height - margin)}px`;
206
207
  this.#host.style.left = `${left}px`;
207
208
  this.#host.style.right = "auto";
208
209
  this.#host.style.bottom = "auto";
@@ -1 +1 @@
1
- {"version":3,"file":"joanroucoux-cairn-ui-menu.mjs","names":[],"sources":["../../../projects/ui/menu/menu.ts"],"sourcesContent":["import {\n Component,\n Directive,\n ElementRef,\n booleanAttribute,\n computed,\n contentChildren,\n inject,\n input,\n numberAttribute,\n signal,\n} from '@angular/core';\n\nconst MENU_CLASSES =\n 'm-0 min-w-44 p-1 rounded-container bg-(--elevated) shadow-[0_8px_24px_rgb(0_0_0/0.16),inset_0_0_0_1px_var(--border)] text-(--foreground) transition-[opacity,scale,overlay,display] transition-discrete duration-(--duration-fast) not-open:duration-[120ms] ease-out starting:open:opacity-0 starting:open:scale-(--enter-scale) opacity-0 scale-(--enter-scale) open:opacity-100 open:scale-100';\n\nconst SHEET_CLASSES =\n 'max-lg:fixed max-lg:inset-x-4 max-lg:top-auto max-lg:w-auto max-lg:bottom-[calc(76px+env(safe-area-inset-bottom))] max-lg:min-w-0 max-lg:p-1.5 max-lg:bg-(--card) max-lg:shadow-[0_12px_32px_rgb(0_0_0/0.2),inset_0_0_0_1px_var(--border)] max-lg:backdrop:bg-[rgb(0_0_0/0.36)] max-lg:transition-[opacity,translate,overlay,display] max-lg:scale-100 max-lg:translate-y-4 max-lg:open:translate-y-0 max-lg:starting:open:scale-100 max-lg:starting:open:translate-y-4 max-lg:motion-reduce:translate-y-0 max-lg:motion-reduce:starting:open:translate-y-0';\n\nconst SHEET_ITEM_CLASSES =\n 'flex w-full items-center gap-3 lg:pointer-fine:gap-2.5 min-h-12 lg:min-h-11 lg:pointer-fine:min-h-9 px-3 lg:pointer-fine:px-2.5 rounded-[calc(var(--radius-container)-6px)] lg:rounded-[calc(var(--radius-container)-4px)] text-body lg:pointer-fine:text-label text-left whitespace-nowrap hover:bg-(--glow) focus-visible:bg-(--glow) active:bg-(--soft) transition-[background-color] duration-(--duration-fast) ease-out outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-(--ring) [:where(&>svg)]:size-5 [:where(&>svg)]:flex-none lg:[:where(&>svg)]:size-[18px] lg:pointer-fine:[:where(&>svg)]:size-4';\n\nconst ITEM_CLASSES =\n 'flex w-full items-center gap-3 pointer-fine:gap-2.5 min-h-11 pointer-fine:min-h-9 px-3 pointer-fine:px-2.5 rounded-[calc(var(--radius-container)-4px)] text-body pointer-fine:text-label text-left whitespace-nowrap hover:bg-(--glow) focus-visible:bg-(--glow) active:bg-(--soft) transition-[background-color] duration-(--duration-fast) ease-out outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-(--ring) [:where(&>svg)]:size-[18px] [:where(&>svg)]:flex-none pointer-fine:[:where(&>svg)]:size-4';\n\nconst CHECK_CLASSES =\n \"after:ms-auto after:block after:h-3 after:w-1.5 after:flex-none after:rotate-45 after:border-r-2 after:border-b-2 after:border-current after:content-['']\";\n\nconst nextId = (() => {\n let count = 0;\n\n return () => `ui-menu-${++count}`;\n})();\n\n/**\n * One action of a `ui-menu`; `destructive` paints it in `--negative`. Giving it `checked` makes it a radio\n * choice (`menuitemradio`): the current one carries a check mark and `aria-checked=\"true\"`.\n *\n * @example\n * <button uiMenuItem destructive (click)=\"remove()\">Delete the holding</button>\n * <button uiMenuItem [checked]=\"account() === 'pea'\" (click)=\"account.set('pea')\">Northwind PEA</button>\n */\n@Directive({\n selector: 'button[uiMenuItem]',\n host: {\n '[attr.role]': 'role()',\n '[attr.aria-checked]': 'checked() === undefined ? null : checked()',\n tabindex: '-1',\n '[class]': 'classes()',\n '(click)': 'onClick()',\n },\n})\nexport class UiMenuItem {\n readonly destructive = input(false, { transform: booleanAttribute });\n readonly checked = input<boolean>();\n\n readonly #host = inject<ElementRef<HTMLButtonElement>>(ElementRef).nativeElement;\n readonly #menu = inject(UiMenu);\n\n protected readonly role = computed(() => (this.checked() === undefined ? 'menuitem' : 'menuitemradio'));\n\n protected readonly classes = computed(\n () =>\n `${this.#menu.sheet() ? SHEET_ITEM_CLASSES : ITEM_CLASSES}${this.destructive() ? ' text-(--negative)' : ''}${this.checked() ? ` ${CHECK_CLASSES}` : ''}`,\n );\n\n focus(): void {\n this.#host.focus();\n }\n\n hasFocus(): boolean {\n return this.#host === document.activeElement;\n }\n\n protected onClick(): void {\n this.#menu.close();\n }\n}\n\n/**\n * Secondary actions menu, opened from its trigger through the native Popover API. With `sheet`, below\n * 64rem it opens as a bottom action sheet instead of beside its trigger, and `heading` names what\n * the actions apply to. `width` fixes the popover width in pixels; without it the menu fits its content.\n *\n * @example\n * <button ui-button size=\"icon\" aria-label=\"More\" [uiMenuTrigger]=\"menu\">...</button>\n * <ui-menu #menu label=\"Holding actions\">\n * <button uiMenuItem (click)=\"edit()\">Edit</button>\n * <button uiMenuItem destructive (click)=\"remove()\">Delete the holding</button>\n * </ui-menu>\n */\n@Component({\n selector: 'ui-menu',\n template: `\n @if (sheet() && heading()) {\n <div aria-hidden=\"true\" class=\"text-label px-3 pt-2 pb-1.5 leading-[17px] text-(--muted-foreground) lg:hidden\">\n {{ heading() }}\n </div>\n }\n <ng-content />\n `,\n host: {\n role: 'menu',\n popover: 'auto',\n '[id]': 'menuId',\n '[style.--ui-menu-width]': 'widthVar()',\n '[class]': 'classes()',\n '[attr.aria-label]': 'label()',\n '(toggle)': 'onToggle($event)',\n '(keydown)': 'onKeydown($event)',\n },\n})\nexport class UiMenu {\n readonly label = input.required<string>();\n readonly sheet = input(false, { transform: booleanAttribute });\n readonly heading = input<string>();\n readonly width = input<number | undefined, unknown>(undefined, { transform: numberAttribute });\n\n readonly menuId = nextId();\n readonly isOpen = signal(false);\n\n protected readonly hasWidth = computed(() => Number.isFinite(this.width()));\n protected readonly widthVar = computed(() => (this.hasWidth() ? `${this.width()}px` : null));\n protected readonly classes = computed(() => {\n const width = !this.hasWidth() ? '' : this.sheet() ? ' lg:w-(--ui-menu-width)' : ' w-(--ui-menu-width)';\n return `${MENU_CLASSES}${this.sheet() ? ` ${SHEET_CLASSES}` : ''}${width}`;\n });\n protected readonly items = contentChildren(UiMenuItem);\n\n readonly #host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n #trigger: HTMLElement | null = null;\n\n open(trigger: HTMLElement): void {\n this.#trigger = trigger;\n this.isOpen.set(true);\n if (typeof this.#host.showPopover === 'function') {\n this.#host.showPopover();\n }\n if (this.#isSheet()) {\n this.#host.style.position = '';\n this.#host.style.top = '';\n this.#host.style.left = '';\n this.#host.style.right = '';\n this.#host.style.bottom = '';\n } else {\n this.#position(trigger);\n }\n (this.items().find((item) => item.checked()) ?? this.items()[0])?.focus();\n }\n\n close(): void {\n const wasOpen = this.isOpen();\n\n this.#applyClosed();\n\n if (wasOpen && typeof this.#host.hidePopover === 'function') {\n this.#host.hidePopover();\n }\n }\n\n #applyClosed(): void {\n this.isOpen.set(false);\n this.#trigger?.focus();\n this.#trigger = null;\n }\n\n protected onToggle(event: Event): void {\n if ((event as ToggleEvent).newState === 'closed') {\n this.#applyClosed();\n }\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Tab' || event.key === 'Escape') {\n event.preventDefault();\n this.close();\n return;\n }\n\n const items = this.items();\n const currentIndex = items.findIndex((item) => item.hasFocus());\n const lastIndex = items.length - 1;\n\n let nextIndex: number | undefined;\n switch (event.key) {\n case 'ArrowDown':\n nextIndex = currentIndex >= lastIndex ? 0 : currentIndex + 1;\n break;\n case 'ArrowUp':\n nextIndex = currentIndex <= 0 ? lastIndex : currentIndex - 1;\n break;\n case 'Home':\n nextIndex = 0;\n break;\n case 'End':\n nextIndex = lastIndex;\n break;\n }\n\n if (nextIndex === undefined) {\n return;\n }\n event.preventDefault();\n items[nextIndex]?.focus();\n }\n\n #isSheet(): boolean {\n return this.sheet() && typeof window.matchMedia === 'function' && !window.matchMedia('(min-width: 64rem)').matches;\n }\n\n #layoutWidth(): number {\n const style = getComputedStyle(this.#host);\n const width = parseFloat(style.width);\n\n if (Number.isNaN(width)) {\n return this.#host.offsetWidth;\n }\n\n if (style.boxSizing === 'border-box') {\n return width;\n }\n\n return (\n width +\n parseFloat(style.paddingLeft) +\n parseFloat(style.paddingRight) +\n parseFloat(style.borderLeftWidth) +\n parseFloat(style.borderRightWidth)\n );\n }\n\n #position(trigger: HTMLElement): void {\n const margin = 8;\n const triggerRect = trigger.getBoundingClientRect();\n const menuRect = { width: this.#layoutWidth(), height: this.#host.offsetHeight };\n const fitsBelow = window.innerHeight - triggerRect.bottom >= menuRect.height + margin;\n\n const top = fitsBelow ? triggerRect.bottom + 4 : Math.max(margin, triggerRect.top - menuRect.height - 4);\n const left = Math.min(\n Math.max(triggerRect.right - menuRect.width, margin),\n window.innerWidth - menuRect.width - margin,\n );\n\n this.#host.style.position = 'fixed';\n this.#host.style.top = `${Math.min(top, window.innerHeight - menuRect.height - margin)}px`;\n this.#host.style.left = `${left}px`;\n this.#host.style.right = 'auto';\n this.#host.style.bottom = 'auto';\n this.#host.style.transformOrigin = fitsBelow ? 'top right' : 'bottom right';\n }\n}\n\n/**\n * Opens a `ui-menu` from a trigger element and wires its ARIA attributes.\n *\n * @example\n * <button ui-button size=\"icon\" aria-label=\"More\" [uiMenuTrigger]=\"menu\">...</button>\n */\n@Directive({\n selector: '[uiMenuTrigger]',\n host: {\n 'aria-haspopup': 'menu',\n '[attr.aria-expanded]': 'uiMenuTrigger().isOpen()',\n '[attr.aria-controls]': 'uiMenuTrigger().menuId',\n '(click)': 'toggle()',\n },\n})\nexport class UiMenuTrigger {\n readonly uiMenuTrigger = input.required<UiMenu>();\n\n readonly #host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n\n protected toggle(): void {\n const menu = this.uiMenuTrigger();\n\n if (menu.isOpen()) {\n menu.close();\n } else {\n menu.open(this.#host);\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"joanroucoux-cairn-ui-menu.mjs","names":[],"sources":["../../../projects/ui/menu/menu.ts"],"sourcesContent":["import {\n Component,\n Directive,\n ElementRef,\n booleanAttribute,\n computed,\n contentChildren,\n inject,\n input,\n numberAttribute,\n signal,\n} from '@angular/core';\n\nconst MENU_CLASSES =\n 'm-0 min-w-44 p-1 rounded-container bg-(--elevated) shadow-[0_8px_24px_rgb(0_0_0/0.16),inset_0_0_0_1px_var(--border)] text-(--foreground) transition-[opacity,scale,overlay,display] transition-discrete duration-(--duration-fast) not-open:duration-[120ms] ease-out starting:open:opacity-0 starting:open:scale-(--enter-scale) opacity-0 scale-(--enter-scale) open:opacity-100 open:scale-100';\n\nconst SHEET_CLASSES =\n 'max-lg:fixed max-lg:inset-x-4 max-lg:top-auto max-lg:w-auto max-lg:bottom-[calc(76px+env(safe-area-inset-bottom))] max-lg:min-w-0 max-lg:p-1.5 max-lg:bg-(--card) max-lg:shadow-[0_12px_32px_rgb(0_0_0/0.2),inset_0_0_0_1px_var(--border)] max-lg:backdrop:bg-[rgb(0_0_0/0.36)] max-lg:transition-[opacity,translate,overlay,display] max-lg:scale-100 max-lg:translate-y-4 max-lg:open:translate-y-0 max-lg:starting:open:scale-100 max-lg:starting:open:translate-y-4 max-lg:motion-reduce:translate-y-0 max-lg:motion-reduce:starting:open:translate-y-0';\n\nconst SHEET_ITEM_CLASSES =\n 'flex w-full items-center gap-3 lg:pointer-fine:gap-2.5 min-h-12 lg:min-h-11 lg:pointer-fine:min-h-9 px-3 lg:pointer-fine:px-2.5 rounded-[calc(var(--radius-container)-6px)] lg:rounded-[calc(var(--radius-container)-4px)] text-body lg:pointer-fine:text-label text-left whitespace-nowrap hover:bg-(--glow) focus-visible:bg-(--glow) active:bg-(--soft) transition-[background-color] duration-(--duration-fast) ease-out outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-(--ring) [:where(&>svg)]:size-5 [:where(&>svg)]:flex-none lg:[:where(&>svg)]:size-[18px] lg:pointer-fine:[:where(&>svg)]:size-4';\n\nconst ITEM_CLASSES =\n 'flex w-full items-center gap-3 pointer-fine:gap-2.5 min-h-11 pointer-fine:min-h-9 px-3 pointer-fine:px-2.5 rounded-[calc(var(--radius-container)-4px)] text-body pointer-fine:text-label text-left whitespace-nowrap hover:bg-(--glow) focus-visible:bg-(--glow) active:bg-(--soft) transition-[background-color] duration-(--duration-fast) ease-out outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-(--ring) [:where(&>svg)]:size-[18px] [:where(&>svg)]:flex-none pointer-fine:[:where(&>svg)]:size-4';\n\nconst CHECK_CLASSES =\n \"after:ms-auto after:block after:h-3 after:w-1.5 after:flex-none after:rotate-45 after:border-r-2 after:border-b-2 after:border-current after:content-['']\";\n\nconst nextId = (() => {\n let count = 0;\n\n return () => `ui-menu-${++count}`;\n})();\n\n/**\n * One action of a `ui-menu`; `destructive` paints it in `--negative`. Giving it `checked` makes it a radio\n * choice (`menuitemradio`): the current one carries a check mark and `aria-checked=\"true\"`.\n *\n * @example\n * <button uiMenuItem destructive (click)=\"remove()\">Delete the holding</button>\n * <button uiMenuItem [checked]=\"account() === 'pea'\" (click)=\"account.set('pea')\">Northwind PEA</button>\n */\n@Directive({\n selector: 'button[uiMenuItem]',\n host: {\n '[attr.role]': 'role()',\n '[attr.aria-checked]': 'checked() === undefined ? null : checked()',\n tabindex: '-1',\n '[class]': 'classes()',\n '(click)': 'onClick()',\n },\n})\nexport class UiMenuItem {\n readonly destructive = input(false, { transform: booleanAttribute });\n readonly checked = input<boolean>();\n\n readonly #host = inject<ElementRef<HTMLButtonElement>>(ElementRef).nativeElement;\n readonly #menu = inject(UiMenu);\n\n protected readonly role = computed(() => (this.checked() === undefined ? 'menuitem' : 'menuitemradio'));\n\n protected readonly classes = computed(\n () =>\n `${this.#menu.sheet() ? SHEET_ITEM_CLASSES : ITEM_CLASSES}${this.destructive() ? ' text-(--negative)' : ''}${this.checked() ? ` ${CHECK_CLASSES}` : ''}`,\n );\n\n focus(): void {\n this.#host.focus();\n }\n\n hasFocus(): boolean {\n return this.#host === document.activeElement;\n }\n\n protected onClick(): void {\n this.#menu.close();\n }\n}\n\n/**\n * Secondary actions menu, opened from its trigger through the native Popover API. With `sheet`, below\n * 64rem it opens as a bottom action sheet instead of beside its trigger, and `heading` names what\n * the actions apply to. `width` fixes the popover width in pixels; without it the menu fits its content.\n *\n * @example\n * <button ui-button size=\"icon\" aria-label=\"More\" [uiMenuTrigger]=\"menu\">...</button>\n * <ui-menu #menu label=\"Holding actions\">\n * <button uiMenuItem (click)=\"edit()\">Edit</button>\n * <button uiMenuItem destructive (click)=\"remove()\">Delete the holding</button>\n * </ui-menu>\n */\n@Component({\n selector: 'ui-menu',\n template: `\n @if (sheet() && heading()) {\n <div aria-hidden=\"true\" class=\"text-label px-3 pt-2 pb-1.5 leading-[17px] text-(--muted-foreground) lg:hidden\">\n {{ heading() }}\n </div>\n }\n <ng-content />\n `,\n host: {\n role: 'menu',\n popover: 'auto',\n '[id]': 'menuId',\n '[style.--ui-menu-width]': 'widthVar()',\n '[class]': 'classes()',\n '[attr.aria-label]': 'label()',\n '(toggle)': 'onToggle($event)',\n '(keydown)': 'onKeydown($event)',\n },\n})\nexport class UiMenu {\n readonly label = input.required<string>();\n readonly sheet = input(false, { transform: booleanAttribute });\n readonly heading = input<string>();\n readonly width = input<number | undefined, unknown>(undefined, { transform: numberAttribute });\n\n readonly menuId = nextId();\n readonly isOpen = signal(false);\n\n protected readonly hasWidth = computed(() => Number.isFinite(this.width()));\n protected readonly widthVar = computed(() => (this.hasWidth() ? `${this.width()}px` : null));\n protected readonly classes = computed(() => {\n const width = !this.hasWidth() ? '' : this.sheet() ? ' lg:w-(--ui-menu-width)' : ' w-(--ui-menu-width)';\n return `${MENU_CLASSES}${this.sheet() ? ` ${SHEET_CLASSES}` : ''}${width}`;\n });\n protected readonly items = contentChildren(UiMenuItem);\n\n readonly #host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n #trigger: HTMLElement | null = null;\n\n open(trigger: HTMLElement): void {\n this.#trigger = trigger;\n this.isOpen.set(true);\n if (typeof this.#host.showPopover === 'function') {\n this.#host.showPopover();\n }\n if (this.#isSheet()) {\n this.#host.style.position = '';\n this.#host.style.top = '';\n this.#host.style.left = '';\n this.#host.style.right = '';\n this.#host.style.bottom = '';\n } else {\n this.#position(trigger);\n }\n (this.items().find((item) => item.checked()) ?? this.items()[0])?.focus();\n }\n\n close(): void {\n const wasOpen = this.isOpen();\n\n this.#applyClosed();\n\n if (wasOpen && typeof this.#host.hidePopover === 'function') {\n this.#host.hidePopover();\n }\n }\n\n #applyClosed(): void {\n this.isOpen.set(false);\n this.#trigger?.focus();\n this.#trigger = null;\n }\n\n protected onToggle(event: Event): void {\n if ((event as ToggleEvent).newState === 'closed') {\n this.#applyClosed();\n }\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Tab' || event.key === 'Escape') {\n event.preventDefault();\n this.close();\n return;\n }\n\n const items = this.items();\n const currentIndex = items.findIndex((item) => item.hasFocus());\n const lastIndex = items.length - 1;\n\n let nextIndex: number | undefined;\n switch (event.key) {\n case 'ArrowDown':\n nextIndex = currentIndex >= lastIndex ? 0 : currentIndex + 1;\n break;\n case 'ArrowUp':\n nextIndex = currentIndex <= 0 ? lastIndex : currentIndex - 1;\n break;\n case 'Home':\n nextIndex = 0;\n break;\n case 'End':\n nextIndex = lastIndex;\n break;\n }\n\n if (nextIndex === undefined) {\n return;\n }\n event.preventDefault();\n items[nextIndex]?.focus();\n }\n\n #isSheet(): boolean {\n return this.sheet() && typeof window.matchMedia === 'function' && !window.matchMedia('(min-width: 64rem)').matches;\n }\n\n #layoutWidth(): number {\n const style = getComputedStyle(this.#host);\n const width = parseFloat(style.width);\n\n if (Number.isNaN(width)) {\n return this.#host.offsetWidth;\n }\n\n if (style.boxSizing === 'border-box') {\n return width;\n }\n\n return (\n width +\n parseFloat(style.paddingLeft) +\n parseFloat(style.paddingRight) +\n parseFloat(style.borderLeftWidth) +\n parseFloat(style.borderRightWidth)\n );\n }\n\n #position(trigger: HTMLElement): void {\n const margin = 8;\n const { clientWidth: viewportWidth, clientHeight: viewportHeight } = document.documentElement;\n const triggerRect = trigger.getBoundingClientRect();\n const menuRect = { width: this.#layoutWidth(), height: this.#host.offsetHeight };\n const fitsBelow = viewportHeight - triggerRect.bottom >= menuRect.height + margin;\n\n const top = fitsBelow ? triggerRect.bottom + 4 : Math.max(margin, triggerRect.top - menuRect.height - 4);\n const left = Math.min(\n Math.max(triggerRect.right - menuRect.width, margin),\n viewportWidth - menuRect.width - margin,\n );\n\n this.#host.style.position = 'fixed';\n this.#host.style.top = `${Math.min(top, viewportHeight - menuRect.height - margin)}px`;\n this.#host.style.left = `${left}px`;\n this.#host.style.right = 'auto';\n this.#host.style.bottom = 'auto';\n this.#host.style.transformOrigin = fitsBelow ? 'top right' : 'bottom right';\n }\n}\n\n/**\n * Opens a `ui-menu` from a trigger element and wires its ARIA attributes.\n *\n * @example\n * <button ui-button size=\"icon\" aria-label=\"More\" [uiMenuTrigger]=\"menu\">...</button>\n */\n@Directive({\n selector: '[uiMenuTrigger]',\n host: {\n 'aria-haspopup': 'menu',\n '[attr.aria-expanded]': 'uiMenuTrigger().isOpen()',\n '[attr.aria-controls]': 'uiMenuTrigger().menuId',\n '(click)': 'toggle()',\n },\n})\nexport class UiMenuTrigger {\n readonly uiMenuTrigger = input.required<UiMenu>();\n\n readonly #host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n\n protected toggle(): void {\n const menu = this.uiMenuTrigger();\n\n if (menu.isOpen()) {\n menu.close();\n } else {\n menu.open(this.#host);\n }\n }\n}\n"],"mappings":"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"}