@vadem/ui 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -8
- package/fesm2022/vadem-ui-menu.mjs +21 -1
- package/fesm2022/vadem-ui-menu.mjs.map +1 -1
- package/package.json +24 -1
- package/types/vadem-ui-menu.d.ts +2 -0
package/README.md
CHANGED
|
@@ -1,20 +1,94 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Vadem UI
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@vadem/ui)
|
|
4
|
+
[](https://github.com/Demchuk12/vadem-ui-angular/actions/workflows/ci.yml)
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
A modern Angular component library for forms, dashboards, and data-rich applications.
|
|
7
|
+
Vadem combines a consistent visual language with native HTML semantics, reusable CSS
|
|
8
|
+
design tokens, and components built with standalone APIs, signals, and OnPush change detection.
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- **Components for everyday product UI:** buttons, form controls, selects, calendars,
|
|
13
|
+
dialogs, notifications, navigation, tables, charts, and file interactions.
|
|
14
|
+
- **Dark and light themes:** a shared token system for colors, typography, spacing,
|
|
15
|
+
shape, and motion, customizable through CSS custom properties.
|
|
16
|
+
- **Accessibility-focused interactions:** keyboard navigation, focus management,
|
|
17
|
+
ARIA semantics, and support for reduced motion and forced colors where applicable.
|
|
18
|
+
- **Localization:** English and Ukrainian locale packs, with RTL-aware layouts and controls.
|
|
19
|
+
- **Angular forms:** native controls and custom value accessors where appropriate,
|
|
20
|
+
with Reactive Forms and Signal Forms examples in the gallery.
|
|
21
|
+
- **Plain CSS:** no Tailwind or third-party UI framework; shared styles are independent
|
|
22
|
+
of Angular view encapsulation.
|
|
23
|
+
- **Bundled assets:** self-hosted Manrope and JetBrains Mono fonts, plus a vendored Lucide
|
|
24
|
+
icon subset. No runtime font or icon CDN is required.
|
|
25
|
+
- **Separate entry points:** import the components you need from `@vadem/ui/button`,
|
|
26
|
+
`@vadem/ui/dialog`, and other component-specific paths.
|
|
27
|
+
|
|
28
|
+
## Requirements
|
|
29
|
+
|
|
30
|
+
Angular **22.2 or later within major version 22**, matching the package's peer dependencies.
|
|
31
|
+
Browser targets: the last two Chrome, Edge, and Firefox versions, and Safari 26+.
|
|
32
|
+
|
|
33
|
+
## Installation
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
npm install @vadem/ui
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Add the shared stylesheet to your application's global CSS:
|
|
7
40
|
|
|
8
41
|
```css
|
|
9
42
|
@import '@vadem/ui/styles.css';
|
|
10
43
|
```
|
|
11
44
|
|
|
12
|
-
|
|
45
|
+
## Quick start
|
|
13
46
|
|
|
14
47
|
```ts
|
|
48
|
+
import { Component } from '@angular/core';
|
|
15
49
|
import { VdButton } from '@vadem/ui/button';
|
|
50
|
+
|
|
51
|
+
@Component({
|
|
52
|
+
selector: 'app-root',
|
|
53
|
+
imports: [VdButton],
|
|
54
|
+
template: `<button vdButton variant="primary">Save changes</button>`,
|
|
55
|
+
})
|
|
56
|
+
export class App {}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Themes and customization
|
|
60
|
+
|
|
61
|
+
Apply a theme to the document or a section of your application:
|
|
62
|
+
|
|
63
|
+
```html
|
|
64
|
+
<html data-theme="dark"></html>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Use `data-theme="light"` for light mode or `data-theme="auto"` to follow the system preference.
|
|
68
|
+
Customize the accent through the shared token:
|
|
69
|
+
|
|
70
|
+
```css
|
|
71
|
+
:root {
|
|
72
|
+
--vd-hue-accent: 270;
|
|
73
|
+
}
|
|
16
74
|
```
|
|
17
75
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
76
|
+
## Documentation and examples
|
|
77
|
+
|
|
78
|
+
- [Source repository](https://github.com/Demchuk12/vadem-ui-angular)
|
|
79
|
+
- [Component contracts](https://github.com/Demchuk12/vadem-ui-angular/tree/main/specs)
|
|
80
|
+
- [Demo gallery source](https://github.com/Demchuk12/vadem-ui-angular/tree/main/projects/demo)
|
|
81
|
+
- [Issues](https://github.com/Demchuk12/vadem-ui-angular/issues)
|
|
82
|
+
|
|
83
|
+
To explore the gallery locally, clone the repository, run `npm ci`, then `npm start`.
|
|
84
|
+
|
|
85
|
+
## Release status
|
|
86
|
+
|
|
87
|
+
Vadem UI is in early development. APIs may change between releases before version 1.0.
|
|
88
|
+
|
|
89
|
+
## Third-party assets
|
|
90
|
+
|
|
91
|
+
Manrope and JetBrains Mono are distributed under SIL OFL 1.1; their notices are included
|
|
92
|
+
in `fonts/`. Lucide icon geometry is distributed under ISC; see `LICENSE-lucide.txt`.
|
|
93
|
+
|
|
94
|
+
Getting started and copyable application examples: [usage guide](https://github.com/Demchuk12/vadem-ui-angular/blob/main/docs/GETTING_STARTED.md).
|
|
@@ -479,18 +479,38 @@ var VdContextMenu = class VdContextMenu {
|
|
|
479
479
|
el = inject(ElementRef).nativeElement;
|
|
480
480
|
doc = inject(DOCUMENT);
|
|
481
481
|
entry = null;
|
|
482
|
+
pendingPointerOpen = null;
|
|
482
483
|
pressTimer;
|
|
483
484
|
constructor() {
|
|
484
485
|
inject(DestroyRef).onDestroy(() => {
|
|
485
486
|
clearTimeout(this.pressTimer);
|
|
487
|
+
this.cancelPointerOpen();
|
|
486
488
|
if (this.entry) release(this.vdContextMenu());
|
|
487
489
|
});
|
|
488
490
|
}
|
|
489
491
|
onContextMenu(event) {
|
|
490
492
|
if (event.shiftKey && event.button === 2) return;
|
|
491
493
|
event.preventDefault();
|
|
492
|
-
this.
|
|
494
|
+
this.cancelPointerOpen();
|
|
495
|
+
const { clientX: x, clientY: y } = event;
|
|
496
|
+
const origin = event.target;
|
|
497
|
+
if (event.buttons & 2) {
|
|
498
|
+
this.pendingPointerOpen = (release) => {
|
|
499
|
+
if (release.button !== 2) return;
|
|
500
|
+
this.cancelPointerOpen();
|
|
501
|
+
if (origin.isConnected) this.openAt(x, y, origin);
|
|
502
|
+
};
|
|
503
|
+
this.doc.addEventListener("pointerup", this.pendingPointerOpen);
|
|
504
|
+
this.doc.addEventListener("pointercancel", this.cancelPointerOpen);
|
|
505
|
+
} else this.openAt(x, y, origin);
|
|
493
506
|
}
|
|
507
|
+
cancelPointerOpen = () => {
|
|
508
|
+
if (this.pendingPointerOpen) {
|
|
509
|
+
this.doc.removeEventListener("pointerup", this.pendingPointerOpen);
|
|
510
|
+
this.pendingPointerOpen = null;
|
|
511
|
+
}
|
|
512
|
+
this.doc.removeEventListener("pointercancel", this.cancelPointerOpen);
|
|
513
|
+
};
|
|
494
514
|
onKeydown(event) {
|
|
495
515
|
if (!(event.key === "ContextMenu" || event.shiftKey && event.key === "F10")) return;
|
|
496
516
|
event.preventDefault();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vadem-ui-menu.mjs","names":[],"sources":["../../../projects/ui/menu/src/core/menu-controller.ts","../../../projects/ui/menu/src/menu.ts","../../../projects/ui/menu/src/context-menu.ts"],"sourcesContent":["/**\n * Framework-agnostic menu button (APG): trigger + `popover=\"auto\"` menu. Focus moves into the\n * menu (roving focus over items), arrows loop, typeahead jumps, activation or Escape closes and\n * returns focus to the trigger, Tab closes and lets focus move on.\n */\nimport { VdTypeahead, vdListTarget } from '@vadem/ui/keyboard';\n\nexport interface VdMenuControllerOptions {\n /** Items in DOM order (role=\"menuitem\", including disabled ones). */\n items(): HTMLElement[];\n onOpenChange?(open: boolean): void;\n /** Where focus returns on close; defaults to the trigger (context menus return to the opener). */\n returnFocusTo?(): HTMLElement | null;\n}\n\nconst ITEM = '[role=\"menuitem\"]';\n\nfunction isDisabled(el: HTMLElement): boolean {\n return el.getAttribute('aria-disabled') === 'true' || (el as HTMLButtonElement).disabled;\n}\n\nexport class VdMenuController {\n private readonly typeahead = new VdTypeahead();\n private returnFocus = false;\n /** Light dismiss closes on pointerdown over the trigger; the click must not reopen. */\n private wasOpen = false;\n\n constructor(\n private readonly trigger: HTMLElement,\n private readonly menu: HTMLElement,\n private readonly options: VdMenuControllerOptions,\n ) {\n trigger.addEventListener('pointerdown', this.onTriggerPointerDown);\n trigger.addEventListener('click', this.onTriggerClick);\n trigger.addEventListener('keydown', this.onTriggerKeydown);\n menu.addEventListener('keydown', this.onMenuKeydown);\n menu.addEventListener('click', this.onMenuClick);\n menu.addEventListener('pointermove', this.onPointerMove);\n menu.addEventListener('toggle', this.onToggle);\n }\n\n get isOpen(): boolean {\n return this.menu.matches(':popover-open');\n }\n\n open(focus: 'first' | 'last' = 'first'): void {\n if (!this.isOpen) {\n this.menu.showPopover({ source: this.trigger } as ShowPopoverOptions);\n this.options.onOpenChange?.(true);\n }\n const items = this.enabledItems();\n (focus === 'first' ? items[0] : items[items.length - 1])?.focus();\n }\n\n close(returnFocus: boolean): void {\n this.returnFocus = returnFocus;\n if (this.isOpen) this.menu.hidePopover();\n }\n\n destroy(): void {\n this.trigger.removeEventListener('pointerdown', this.onTriggerPointerDown);\n this.trigger.removeEventListener('click', this.onTriggerClick);\n this.trigger.removeEventListener('keydown', this.onTriggerKeydown);\n this.menu.removeEventListener('keydown', this.onMenuKeydown);\n this.menu.removeEventListener('click', this.onMenuClick);\n this.menu.removeEventListener('pointermove', this.onPointerMove);\n this.menu.removeEventListener('toggle', this.onToggle);\n }\n\n private enabledItems(): HTMLElement[] {\n return this.options.items().filter((i) => !isDisabled(i));\n }\n\n private readonly onTriggerPointerDown = () => {\n this.wasOpen = this.isOpen;\n };\n\n private readonly onTriggerClick = (event: MouseEvent) => {\n if (this.wasOpen || this.isOpen) {\n this.wasOpen = false;\n this.close(false);\n return;\n }\n // Enter/Space are handled in keydown (and prevented), so this is a pointer click.\n this.open('first');\n event.preventDefault();\n };\n\n private readonly onTriggerKeydown = (event: KeyboardEvent) => {\n const { key } = event;\n if (key === 'ArrowDown' || key === 'Enter' || key === ' ') {\n event.preventDefault();\n this.open('first');\n } else if (key === 'ArrowUp') {\n event.preventDefault();\n this.open('last');\n }\n };\n\n private readonly onMenuKeydown = (event: KeyboardEvent) => {\n const items = this.options.items();\n const current = items.indexOf(event.target as HTMLElement);\n const { key } = event;\n\n if (key === 'Escape') {\n event.preventDefault();\n this.close(true);\n return;\n }\n if (key === 'Tab') {\n this.close(false);\n return;\n }\n const target = vdListTarget(key, current, items.map(isDisabled), { loop: true, pageSize: 10 });\n if (target !== null) {\n event.preventDefault();\n items[target]?.focus();\n return;\n }\n if (VdTypeahead.accepts(event)) {\n const idx = this.typeahead.match(\n key,\n items.map((i) => i.textContent?.trim() ?? ''),\n items.map(isDisabled),\n current,\n );\n if (idx !== null) items[idx]?.focus();\n }\n };\n\n private readonly onMenuClick = (event: MouseEvent) => {\n const item = (event.target as Element).closest<HTMLElement>(ITEM);\n if (!item || !this.menu.contains(item)) return;\n if (isDisabled(item)) {\n event.preventDefault();\n event.stopImmediatePropagation();\n return;\n }\n // Item handlers already ran (bubbling reached the menu): close and restore focus.\n this.close(true);\n };\n\n /** Pointer and keyboard share one \"current\" item: hovering focuses it. */\n private readonly onPointerMove = (event: PointerEvent) => {\n if (event.pointerType === 'touch') return;\n const item = (event.target as Element).closest<HTMLElement>(ITEM);\n if (item && !isDisabled(item) && item !== this.menu.ownerDocument.activeElement) item.focus();\n };\n\n private readonly onToggle = (event: Event) => {\n if ((event as ToggleEvent).newState !== 'closed') return;\n this.typeahead.reset();\n this.options.onOpenChange?.(false);\n if (this.returnFocus) (this.options.returnFocusTo?.() ?? this.trigger).focus();\n this.returnFocus = false;\n };\n}\n","import {\n DestroyRef,\n Directive,\n ElementRef,\n afterNextRender,\n booleanAttribute,\n inject,\n input,\n signal,\n} from '@angular/core';\nimport { vdUniqueId } from '@vadem/ui/field';\nimport { VdMenuController } from './core/menu-controller';\n\n/** Menu panel: a `popover=\"auto\"` with `role=\"menu\"`. Open it with `vdMenuTrigger`. */\n@Directive({\n selector: '[vdMenu]',\n exportAs: 'vdMenu',\n host: {\n class: 'vd-menu',\n role: 'menu',\n popover: 'auto',\n tabindex: '-1',\n '[id]': 'id',\n '[attr.aria-labelledby]': 'labelledBy()',\n },\n})\nexport class VdMenu {\n readonly id = vdUniqueId('vd-menu');\n readonly el: HTMLElement = inject(ElementRef).nativeElement;\n readonly labelledBy = signal<string | null>(null);\n\n items(): HTMLElement[] {\n return Array.from(this.el.querySelectorAll<HTMLElement>('[role=\"menuitem\"]'));\n }\n}\n\n/** Opens a `vdMenu`. Use on a button (works with `vdButton`). Spec: specs/menu.md */\n@Directive({\n selector: 'button[vdMenuTrigger]',\n host: {\n 'aria-haspopup': 'menu',\n '[attr.aria-expanded]': 'open()',\n '[attr.aria-controls]': 'vdMenuTrigger().id',\n '[attr.data-state]': 'open() ? \"open\" : \"closed\"',\n },\n})\nexport class VdMenuTrigger {\n readonly vdMenuTrigger = input.required<VdMenu>();\n protected readonly open = signal(false);\n private readonly el: HTMLButtonElement = inject(ElementRef).nativeElement;\n\n constructor() {\n const destroyRef = inject(DestroyRef);\n afterNextRender(() => {\n const menu = this.vdMenuTrigger();\n if (!this.el.id) this.el.id = vdUniqueId('vd-menu-trigger');\n menu.labelledBy.set(this.el.id);\n const name = `--${menu.id}`;\n this.el.style.setProperty('anchor-name', name);\n menu.el.style.setProperty('position-anchor', name);\n const controller = new VdMenuController(this.el, menu.el, {\n items: () => menu.items(),\n onOpenChange: (open) => this.open.set(open),\n });\n destroyRef.onDestroy(() => controller.destroy());\n });\n }\n}\n\nexport type VdMenuItemVariant = 'default' | 'danger';\n\n@Directive({\n selector: 'button[vdMenuItem], a[vdMenuItem]',\n host: {\n class: 'vd-menu__item',\n role: 'menuitem',\n tabindex: '-1',\n '[attr.type]': 'isButton ? \"button\" : null',\n '[attr.data-variant]': 'variant()',\n '[attr.aria-disabled]': 'disabled() || null',\n },\n})\nexport class VdMenuItem {\n readonly variant = input<VdMenuItemVariant>('default');\n /** Disabled items stay in the menu (discoverable) but are skipped and inert. */\n readonly disabled = input(false, { transform: booleanAttribute });\n protected readonly isButton =\n (inject(ElementRef).nativeElement as HTMLElement).tagName === 'BUTTON';\n}\n\n@Directive({\n selector: '[vdMenuSeparator]',\n host: { class: 'vd-menu__separator', role: 'separator' },\n})\nexport class VdMenuSeparator {}\n\n/** Group heading inside a menu (mono eyebrow). Presentational. */\n@Directive({\n selector: '[vdMenuLabel]',\n host: { class: 'vd-menu__label', role: 'presentation' },\n})\nexport class VdMenuLabel {}\n\nexport const VD_MENU = [VdMenu, VdMenuTrigger, VdMenuItem, VdMenuSeparator, VdMenuLabel] as const;\n","import { DOCUMENT } from '@angular/common';\nimport { DestroyRef, Directive, ElementRef, inject, input, output } from '@angular/core';\nimport { vdUniqueId } from '@vadem/ui/field';\nimport { vdTexts } from '@vadem/ui/locale';\nimport { VdMenuController } from './core/menu-controller';\nimport type { VdMenu } from './menu';\n\n/** Touch hold that opens the menu where `contextmenu` does not fire (iOS Safari). */\nconst LONG_PRESS_MS = 500;\nconst LONG_PRESS_SLOP = 10;\n\n/** One controller and one virtual anchor per menu, shared by every region that opens it. */\ninterface Shared {\n anchor: HTMLElement;\n controller: VdMenuController;\n opener: HTMLElement | null;\n users: number;\n}\nconst shared = new WeakMap<HTMLElement, Shared>();\n\nfunction acquire(menu: VdMenu, doc: Document): Shared {\n let entry = shared.get(menu.el);\n if (!entry) {\n const anchor = doc.createElement('span');\n anchor.className = 'vd-context-menu__anchor';\n anchor.setAttribute('aria-hidden', 'true');\n const name = `--${vdUniqueId('vd-context-anchor')}`;\n anchor.style.setProperty('anchor-name', name);\n menu.el.style.setProperty('position-anchor', name);\n // Next to the menu, so it shares any dialog's top layer and inert state.\n (menu.el.parentElement ?? doc.body).appendChild(anchor);\n const created: Shared = {\n anchor,\n opener: null,\n users: 0,\n controller: new VdMenuController(anchor, menu.el, {\n items: () => menu.items(),\n returnFocusTo: () => created.opener,\n }),\n };\n entry = created;\n shared.set(menu.el, entry);\n }\n entry.users++;\n return entry;\n}\n\nfunction release(menu: VdMenu): void {\n const entry = shared.get(menu.el);\n if (!entry || --entry.users > 0) return;\n entry.controller.destroy();\n entry.anchor.remove();\n shared.delete(menu.el);\n}\n\n/**\n * Opens a `vdMenu` at the pointer on right-click / long-press, or at the focused element on\n * the ContextMenu key and Shift+F10. Spec: specs/menu.md\n */\n@Directive({\n selector: '[vdContextMenu]',\n host: {\n class: 'vd-context-menu-target',\n '(contextmenu)': 'onContextMenu($event)',\n '(keydown)': 'onKeydown($event)',\n '(pointerdown)': 'onPointerDown($event)',\n },\n})\nexport class VdContextMenu {\n readonly vdContextMenu = input.required<VdMenu>();\n /** Accessible name of the menu while this region opened it. */\n readonly label = input<string>();\n /** Fires before the menu opens, so the consumer can point it at this region's item. */\n readonly opened = output<void>();\n\n protected readonly t = vdTexts('contextMenu', { label: this.label });\n private readonly el: HTMLElement = inject(ElementRef).nativeElement;\n private readonly doc = inject(DOCUMENT);\n private entry: Shared | null = null;\n private pressTimer: ReturnType<typeof setTimeout> | undefined;\n\n constructor() {\n inject(DestroyRef).onDestroy(() => {\n clearTimeout(this.pressTimer);\n if (this.entry) release(this.vdContextMenu());\n });\n }\n\n protected onContextMenu(event: MouseEvent): void {\n // Shift+right-click keeps the browser's own menu (copy, inspect) available.\n if (event.shiftKey && event.button === 2) return;\n event.preventDefault();\n this.openAt(event.clientX, event.clientY, event.target as HTMLElement);\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n const keyboardMenu = event.key === 'ContextMenu' || (event.shiftKey && event.key === 'F10');\n if (!keyboardMenu) return;\n event.preventDefault();\n const target = (event.target as HTMLElement) ?? this.el;\n const rect = target.getBoundingClientRect();\n const rtl = this.doc.defaultView?.getComputedStyle(target).direction === 'rtl';\n this.openAt(rtl ? rect.right : rect.left, rect.bottom, target);\n }\n\n protected onPointerDown(event: PointerEvent): void {\n if (event.pointerType !== 'touch') return;\n const { clientX: x, clientY: y } = event;\n const target = event.target as HTMLElement;\n const cancel = (e?: PointerEvent) => {\n if (\n e &&\n e.type === 'pointermove' &&\n Math.hypot(e.clientX - x, e.clientY - y) < LONG_PRESS_SLOP\n )\n return;\n clearTimeout(this.pressTimer);\n this.el.removeEventListener('pointermove', cancel);\n this.el.removeEventListener('pointerup', cancel);\n this.el.removeEventListener('pointercancel', cancel);\n };\n this.el.addEventListener('pointermove', cancel);\n this.el.addEventListener('pointerup', cancel);\n this.el.addEventListener('pointercancel', cancel);\n clearTimeout(this.pressTimer);\n this.pressTimer = setTimeout(() => {\n cancel();\n this.openAt(x, y, target);\n }, LONG_PRESS_MS);\n }\n\n private openAt(x: number, y: number, origin: HTMLElement): void {\n const menu = this.vdContextMenu();\n this.entry ??= acquire(menu, this.doc);\n // Android also fires contextmenu after a long press; one opening is enough.\n if (this.entry.controller.isOpen && this.entry.opener === this.focusable(origin)) return;\n this.opened.emit();\n this.entry.opener = this.focusable(origin);\n this.place(this.entry.anchor, x, y);\n menu.el.setAttribute('aria-label', this.t().label);\n menu.labelledBy.set(null);\n this.entry.controller.close(false);\n this.entry.controller.open('first');\n }\n\n /**\n * Puts the zero-size anchor at viewport point (x, y). An ancestor with a transform, filter or\n * container query becomes the fixed containing block, so the first guess is measured and\n * corrected by the difference. Insets stay logical: in RTL inline-start grows leftwards.\n */\n private place(anchor: HTMLElement, x: number, y: number): void {\n const rtl = this.doc.defaultView?.getComputedStyle(anchor).direction === 'rtl';\n let inline = rtl ? this.doc.documentElement.clientWidth - x : x;\n let block = y;\n const set = () => {\n anchor.style.setProperty('--vd-context-x', `${inline}px`);\n anchor.style.setProperty('--vd-context-y', `${block}px`);\n };\n set();\n const rect = anchor.getBoundingClientRect();\n inline += rtl ? rect.left - x : x - rect.left;\n block += y - rect.top;\n set();\n }\n\n /** Focus returns to the nearest focusable element of this region, or the region itself. */\n private focusable(origin: HTMLElement): HTMLElement {\n const candidate = origin.closest<HTMLElement>(\n 'a[href], button, input, select, textarea, [tabindex]',\n );\n return candidate && this.el.contains(candidate) ? candidate : this.el;\n }\n}\n"],"mappings":";;;;;;AAeA,MAAM,OAAO;AAEb,SAAS,WAAW,IAAe;CACjC,OAAO,GAAG,aAAa,eAAe,MAAM,UAAW,GAAyB;AAClF;AAEA,IAAa,mBAAb,MAA6B;CAOR;CACA;CACA;CARF,YAAY,IAAI,YAAW;CACpC,cAAc;CAEd,UAAU;CAElB,YACmB,SACA,MACA,SAAgC;EAFhC,KAAA,UAAA;EACA,KAAA,OAAA;EACA,KAAA,UAAA;EAEjB,QAAQ,iBAAiB,eAAe,KAAK,oBAAoB;EACjE,QAAQ,iBAAiB,SAAS,KAAK,cAAc;EACrD,QAAQ,iBAAiB,WAAW,KAAK,gBAAgB;EACzD,KAAK,iBAAiB,WAAW,KAAK,aAAa;EACnD,KAAK,iBAAiB,SAAS,KAAK,WAAW;EAC/C,KAAK,iBAAiB,eAAe,KAAK,aAAa;EACvD,KAAK,iBAAiB,UAAU,KAAK,QAAQ;CAC/C;CAEA,IAAI,SAAM;EACR,OAAO,KAAK,KAAK,QAAQ,eAAe;CAC1C;CAEA,KAAK,QAA0B,SAAO;EACpC,IAAI,CAAC,KAAK,QAAQ;GAChB,KAAK,KAAK,YAAY,EAAE,QAAQ,KAAK,QAAO,CAAwB;GACpE,KAAK,QAAQ,eAAe,IAAI;EAClC;EACA,MAAM,QAAQ,KAAK,aAAY;EAC/B,CAAC,UAAU,UAAU,MAAM,KAAK,MAAM,MAAM,SAAS,GAAA,EAAK,MAAK;CACjE;CAEA,MAAM,aAAoB;EACxB,KAAK,cAAc;EACnB,IAAI,KAAK,QAAQ,KAAK,KAAK,YAAW;CACxC;CAEA,UAAO;EACL,KAAK,QAAQ,oBAAoB,eAAe,KAAK,oBAAoB;EACzE,KAAK,QAAQ,oBAAoB,SAAS,KAAK,cAAc;EAC7D,KAAK,QAAQ,oBAAoB,WAAW,KAAK,gBAAgB;EACjE,KAAK,KAAK,oBAAoB,WAAW,KAAK,aAAa;EAC3D,KAAK,KAAK,oBAAoB,SAAS,KAAK,WAAW;EACvD,KAAK,KAAK,oBAAoB,eAAe,KAAK,aAAa;EAC/D,KAAK,KAAK,oBAAoB,UAAU,KAAK,QAAQ;CACvD;CAEQ,eAAY;EAClB,OAAO,KAAK,QAAQ,MAAK,CAAE,CAAC,QAAQ,MAAM,CAAC,WAAW,CAAC,CAAC;CAC1D;CAEiB,6BAA4B;EAC3C,KAAK,UAAU,KAAK;CACtB;CAEiB,kBAAkB,UAAqB;EACtD,IAAI,KAAK,WAAW,KAAK,QAAQ;GAC/B,KAAK,UAAU;GACf,KAAK,MAAM,KAAK;GAChB;EACF;EAEA,KAAK,KAAK,OAAO;EACjB,MAAM,eAAc;CACtB;CAEiB,oBAAoB,UAAwB;EAC3D,MAAM,EAAE,QAAQ;EAChB,IAAI,QAAQ,eAAe,QAAQ,WAAW,QAAQ,KAAK;GACzD,MAAM,eAAc;GACpB,KAAK,KAAK,OAAO;EACnB,OAAO,IAAI,QAAQ,WAAW;GAC5B,MAAM,eAAc;GACpB,KAAK,KAAK,MAAM;EAClB;CACF;CAEiB,iBAAiB,UAAwB;EACxD,MAAM,QAAQ,KAAK,QAAQ,MAAK;EAChC,MAAM,UAAU,MAAM,QAAQ,MAAM,MAAqB;EACzD,MAAM,EAAE,QAAQ;EAEhB,IAAI,QAAQ,UAAU;GACpB,MAAM,eAAc;GACpB,KAAK,MAAM,IAAI;GACf;EACF;EACA,IAAI,QAAQ,OAAO;GACjB,KAAK,MAAM,KAAK;GAChB;EACF;EACA,MAAM,SAAS,aAAa,KAAK,SAAS,MAAM,IAAI,UAAU,GAAG;GAAE,MAAM;GAAM,UAAU;EAAE,CAAE;EAC7F,IAAI,WAAW,MAAM;GACnB,MAAM,eAAc;GACpB,MAAM,OAAO,EAAE,MAAK;GACpB;EACF;EACA,IAAI,YAAY,QAAQ,KAAK,GAAG;GAC9B,MAAM,MAAM,KAAK,UAAU,MACzB,KACA,MAAM,KAAK,MAAM,EAAE,aAAa,KAAI,KAAM,EAAE,GAC5C,MAAM,IAAI,UAAU,GACpB,OAAO;GAET,IAAI,QAAQ,MAAM,MAAM,IAAI,EAAE,MAAK;EACrC;CACF;CAEiB,eAAe,UAAqB;EACnD,MAAM,OAAQ,MAAM,OAAmB,QAAqB,IAAI;EAChE,IAAI,CAAC,QAAQ,CAAC,KAAK,KAAK,SAAS,IAAI,GAAG;EACxC,IAAI,WAAW,IAAI,GAAG;GACpB,MAAM,eAAc;GACpB,MAAM,yBAAwB;GAC9B;EACF;EAEA,KAAK,MAAM,IAAI;CACjB;CAGiB,iBAAiB,UAAuB;EACvD,IAAI,MAAM,gBAAgB,SAAS;EACnC,MAAM,OAAQ,MAAM,OAAmB,QAAqB,IAAI;EAChE,IAAI,QAAQ,CAAC,WAAW,IAAI,KAAK,SAAS,KAAK,KAAK,cAAc,eAAe,KAAK,MAAK;CAC7F;CAEiB,YAAY,UAAgB;EAC3C,IAAK,MAAsB,aAAa,UAAU;EAClD,KAAK,UAAU,MAAK;EACpB,KAAK,QAAQ,eAAe,KAAK;EACjC,IAAI,KAAK,aAAa,CAAC,KAAK,QAAQ,gBAAe,KAAM,KAAK,QAAA,CAAS,MAAK;EAC5E,KAAK,cAAc;CACrB;AACD;AClID,IAAa,SAAb,MAAa,OAAM;CACR,KAAK,WAAW,SAAS;CACzB,KAAkB,OAAO,UAAU,CAAC,CAAC;CACrC,aAAa,OAAsB,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAEjD,QAAK;EACH,OAAO,MAAM,KAAK,KAAK,GAAG,iBAA8B,qBAAmB,CAAC;CAC9E;CAPW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAM,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAN,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAM,cAAA;EAAA,UAAA;EAAA,MAAA;GAAA,YAAA;IAAA,QAAA;IAAA,WAAA;IAAA,YAAA;GAAA;GAAA,YAAA;IAAA,MAAA;IAAA,wBAAA;GAAA;GAAA,gBAAA;EAAA;EAAA,UAAA,CAAA,QAAA;EAAA,UAAA;CAAA,CAAA;;AAAN,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAM,YAAA,CAAA;EAZlB,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,UAAU;GACV,MAAM;IACJ,OAAO;IACP,MAAM;IACN,SAAS;IACT,UAAU;IACV,QAAQ;IACR,0BAA0B;GAC3B;EACF,CAAA;;;AAqBD,IAAa,gBAAb,MAAa,cAAa;CACf,gBAAgB,MAAM,SAAkB,GAAA,YAAA,CAAA,EAAA,WAAA,gBAAA,CAAA,+BAAA,CAAA,CAAA;CAC9B,OAAO,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CACtB,KAAwB,OAAO,UAAU,CAAC,CAAC;CAE5D,cAAA;EACE,MAAM,aAAa,OAAO,UAAU;EACpC,sBAAqB;GACnB,MAAM,OAAO,KAAK,cAAa;GAC/B,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,GAAG,KAAK,WAAW,iBAAiB;GAC1D,KAAK,WAAW,IAAI,KAAK,GAAG,EAAE;GAC9B,MAAM,OAAO,KAAK,KAAK;GACvB,KAAK,GAAG,MAAM,YAAY,eAAe,IAAI;GAC7C,KAAK,GAAG,MAAM,YAAY,mBAAmB,IAAI;GACjD,MAAM,aAAa,IAAI,iBAAiB,KAAK,IAAI,KAAK,IAAI;IACxD,aAAa,KAAK,MAAK;IACvB,eAAe,SAAS,KAAK,KAAK,IAAI,IAAI;GAC3C,CAAA;GACD,WAAW,gBAAgB,WAAW,QAAO,CAAE;EACjD,CAAC;CACH;CApBW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAa,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAb,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAa,cAAA;EAAA,UAAA;EAAA,QAAA,EAAA,eAAA;GAAA,mBAAA;GAAA,YAAA;GAAA,UAAA;GAAA,YAAA;GAAA,mBAAA;EAAA,EAAA;EAAA,MAAA;GAAA,YAAA,EAAA,iBAAA,OAAA;GAAA,YAAA;IAAA,sBAAA;IAAA,sBAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,UAAA;CAAA,CAAA;;AAAb,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAa,YAAA,CAAA;EATzB,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,MAAM;IACJ,iBAAiB;IACjB,wBAAwB;IACxB,wBAAwB;IACxB,qBAAqB;GACtB;EACF,CAAA;;;;;;;;;;;;AAqCD,IAAa,aAAb,MAAa,WAAU;CACZ,UAAU,MAAyB,WAAU,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAE7C,WAAW,MAAM,OAAK;EAAA,GAAA,YAAA,EAAA,WAAA,WAAA,+BAAA,CAAA;EAAI,WAAW;CAAgB,CAAA;CAC3C,WAChB,OAAO,UAAU,CAAC,CAAC,cAA8B,YAAY;CALrD,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAU,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAV,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAU,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,UAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,MAAA;GAAA,YAAA;IAAA,QAAA;IAAA,YAAA;GAAA;GAAA,YAAA;IAAA,aAAA;IAAA,qBAAA;IAAA,sBAAA;GAAA;GAAA,gBAAA;EAAA;EAAA,UAAA;CAAA,CAAA;;AAAV,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAU,YAAA,CAAA;EAXtB,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,MAAM;IACJ,OAAO;IACP,MAAM;IACN,UAAU;IACV,eAAe;IACf,uBAAuB;IACvB,wBAAwB;GACzB;EACF,CAAA;;;;;;;;;;;;;;;;;;;;;AAaD,IAAa,kBAAb,MAAa,gBAAe;CAAf,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAe,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAf,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAe,cAAA;EAAA,UAAA;EAAA,MAAA;GAAA,YAAA,EAAA,QAAA,YAAA;GAAA,gBAAA;EAAA;EAAA,UAAA;CAAA,CAAA;;AAAf,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAe,YAAA,CAAA;EAJ3B,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,MAAM;IAAE,OAAO;IAAsB,MAAM;GAAW;EACvD,CAAA;;;AAQD,IAAa,cAAb,MAAa,YAAW;CAAX,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAW,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAX,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAW,cAAA;EAAA,UAAA;EAAA,MAAA;GAAA,YAAA,EAAA,QAAA,eAAA;GAAA,gBAAA;EAAA;EAAA,UAAA;CAAA,CAAA;;AAAX,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAW,YAAA,CAAA;EAJvB,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,MAAM;IAAE,OAAO;IAAkB,MAAM;GAAc;EACtD,CAAA;;;AAGD,MAAa,UAAU;CAAC;CAAQ;CAAe;CAAY;CAAiB;AAAW;AC/FvF,MAAM,gBAAgB;AACtB,MAAM,kBAAkB;AASxB,MAAM,yBAAS,IAAI,QAAO;AAE1B,SAAS,QAAQ,MAAc,KAAa;CAC1C,IAAI,QAAQ,OAAO,IAAI,KAAK,EAAE;CAC9B,IAAI,CAAC,OAAO;EACV,MAAM,SAAS,IAAI,cAAc,MAAM;EACvC,OAAO,YAAY;EACnB,OAAO,aAAa,eAAe,MAAM;EACzC,MAAM,OAAO,KAAK,WAAW,mBAAmB;EAChD,OAAO,MAAM,YAAY,eAAe,IAAI;EAC5C,KAAK,GAAG,MAAM,YAAY,mBAAmB,IAAI;EAEjD,CAAC,KAAK,GAAG,iBAAiB,IAAI,KAAA,CAAM,YAAY,MAAM;EACtD,MAAM,UAAkB;GACtB;GACA,QAAQ;GACR,OAAO;GACP,YAAY,IAAI,iBAAiB,QAAQ,KAAK,IAAI;IAChD,aAAa,KAAK,MAAK;IACvB,qBAAqB,QAAQ;GAC9B,CAAA;EACF;EACD,QAAQ;EACR,OAAO,IAAI,KAAK,IAAI,KAAK;CAC3B;CACA,MAAM;CACN,OAAO;AACT;AAEA,SAAS,QAAQ,MAAY;CAC3B,MAAM,QAAQ,OAAO,IAAI,KAAK,EAAE;CAChC,IAAI,CAAC,SAAS,EAAE,MAAM,QAAQ,GAAG;CACjC,MAAM,WAAW,QAAO;CACxB,MAAM,OAAO,OAAM;CACnB,OAAO,OAAO,KAAK,EAAE;AACvB;AAeA,IAAa,gBAAb,MAAa,cAAa;CACf,gBAAgB,MAAM,SAAkB,GAAA,YAAA,CAAA,EAAA,WAAA,gBAAA,CAAA,+BAAA,CAAA,CAAA;CAExC,QAAQ,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAEvB,SAAS,OAAM;CAEL,IAAI,QAAQ,eAAe,EAAE,OAAO,KAAK,MAAK,CAAE;CAClD,KAAkB,OAAO,UAAU,CAAC,CAAC;CACrC,MAAM,OAAO,QAAQ;CAC9B,QAAuB;CACvB;CAER,cAAA;EACE,OAAO,UAAU,CAAC,CAAC,gBAAe;GAChC,aAAa,KAAK,UAAU;GAC5B,IAAI,KAAK,OAAO,QAAQ,KAAK,cAAa,CAAE;EAC9C,CAAC;CACH;CAEU,cAAc,OAAiB;EAEvC,IAAI,MAAM,YAAY,MAAM,WAAW,GAAG;EAC1C,MAAM,eAAc;EACpB,KAAK,OAAO,MAAM,SAAS,MAAM,SAAS,MAAM,MAAqB;CACvE;CAEU,UAAU,OAAoB;EAEtC,IAAI,EADiB,MAAM,QAAQ,iBAAkB,MAAM,YAAY,MAAM,QAAQ,QAClE;EACnB,MAAM,eAAc;EACpB,MAAM,SAAU,MAAM,UAA0B,KAAK;EACrD,MAAM,OAAO,OAAO,sBAAqB;EACzC,MAAM,MAAM,KAAK,IAAI,aAAa,iBAAiB,MAAM,CAAC,CAAC,cAAc;EACzE,KAAK,OAAO,MAAM,KAAK,QAAQ,KAAK,MAAM,KAAK,QAAQ,MAAM;CAC/D;CAEU,cAAc,OAAmB;EACzC,IAAI,MAAM,gBAAgB,SAAS;EACnC,MAAM,EAAE,SAAS,GAAG,SAAS,MAAM;EACnC,MAAM,SAAS,MAAM;EACrB,MAAM,UAAU,MAAoB;GAClC,IACE,KACA,EAAE,SAAS,iBACX,KAAK,MAAM,EAAE,UAAU,GAAG,EAAE,UAAU,CAAC,IAAI,iBAE3C;GACF,aAAa,KAAK,UAAU;GAC5B,KAAK,GAAG,oBAAoB,eAAe,MAAM;GACjD,KAAK,GAAG,oBAAoB,aAAa,MAAM;GAC/C,KAAK,GAAG,oBAAoB,iBAAiB,MAAM;EACrD;EACA,KAAK,GAAG,iBAAiB,eAAe,MAAM;EAC9C,KAAK,GAAG,iBAAiB,aAAa,MAAM;EAC5C,KAAK,GAAG,iBAAiB,iBAAiB,MAAM;EAChD,aAAa,KAAK,UAAU;EAC5B,KAAK,aAAa,iBAAgB;GAChC,OAAM;GACN,KAAK,OAAO,GAAG,GAAG,MAAM;EAC1B,GAAG,aAAa;CAClB;CAEQ,OAAO,GAAW,GAAW,QAAmB;EACtD,MAAM,OAAO,KAAK,cAAa;EAC/B,KAAK,UAAU,QAAQ,MAAM,KAAK,GAAG;EAErC,IAAI,KAAK,MAAM,WAAW,UAAU,KAAK,MAAM,WAAW,KAAK,UAAU,MAAM,GAAG;EAClF,KAAK,OAAO,KAAI;EAChB,KAAK,MAAM,SAAS,KAAK,UAAU,MAAM;EACzC,KAAK,MAAM,KAAK,MAAM,QAAQ,GAAG,CAAC;EAClC,KAAK,GAAG,aAAa,cAAc,KAAK,EAAC,CAAE,CAAC,KAAK;EACjD,KAAK,WAAW,IAAI,IAAI;EACxB,KAAK,MAAM,WAAW,MAAM,KAAK;EACjC,KAAK,MAAM,WAAW,KAAK,OAAO;CACpC;CAOQ,MAAM,QAAqB,GAAW,GAAS;EACrD,MAAM,MAAM,KAAK,IAAI,aAAa,iBAAiB,MAAM,CAAC,CAAC,cAAc;EACzE,IAAI,SAAS,MAAM,KAAK,IAAI,gBAAgB,cAAc,IAAI;EAC9D,IAAI,QAAQ;EACZ,MAAM,YAAW;GACf,OAAO,MAAM,YAAY,kBAAkB,GAAG,OAAM,GAAI;GACxD,OAAO,MAAM,YAAY,kBAAkB,GAAG,MAAK,GAAI;EACzD;EACA,IAAG;EACH,MAAM,OAAO,OAAO,sBAAqB;EACzC,UAAU,MAAM,KAAK,OAAO,IAAI,IAAI,KAAK;EACzC,SAAS,IAAI,KAAK;EAClB,IAAG;CACL;CAGQ,UAAU,QAAmB;EACnC,MAAM,YAAY,OAAO,QACvB,sDAAsD;EAExD,OAAO,aAAa,KAAK,GAAG,SAAS,SAAS,IAAI,YAAY,KAAK;CACrE;CAvGW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAa,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAb,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAa,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,eAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,SAAA,EAAA,QAAA,SAAA;EAAA,MAAA;GAAA,WAAA;IAAA,eAAA;IAAA,WAAA;IAAA,eAAA;GAAA;GAAA,gBAAA;EAAA;EAAA,UAAA;CAAA,CAAA;;AAAb,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAa,YAAA,CAAA;EATzB,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,MAAM;IACJ,OAAO;IACP,iBAAiB;IACjB,aAAa;IACb,iBAAiB;GAClB;EACF,CAAA"}
|
|
1
|
+
{"version":3,"file":"vadem-ui-menu.mjs","names":[],"sources":["../../../projects/ui/menu/src/core/menu-controller.ts","../../../projects/ui/menu/src/menu.ts","../../../projects/ui/menu/src/context-menu.ts"],"sourcesContent":["/**\n * Framework-agnostic menu button (APG): trigger + `popover=\"auto\"` menu. Focus moves into the\n * menu (roving focus over items), arrows loop, typeahead jumps, activation or Escape closes and\n * returns focus to the trigger, Tab closes and lets focus move on.\n */\nimport { VdTypeahead, vdListTarget } from '@vadem/ui/keyboard';\n\nexport interface VdMenuControllerOptions {\n /** Items in DOM order (role=\"menuitem\", including disabled ones). */\n items(): HTMLElement[];\n onOpenChange?(open: boolean): void;\n /** Where focus returns on close; defaults to the trigger (context menus return to the opener). */\n returnFocusTo?(): HTMLElement | null;\n}\n\nconst ITEM = '[role=\"menuitem\"]';\n\nfunction isDisabled(el: HTMLElement): boolean {\n return el.getAttribute('aria-disabled') === 'true' || (el as HTMLButtonElement).disabled;\n}\n\nexport class VdMenuController {\n private readonly typeahead = new VdTypeahead();\n private returnFocus = false;\n /** Light dismiss closes on pointerdown over the trigger; the click must not reopen. */\n private wasOpen = false;\n\n constructor(\n private readonly trigger: HTMLElement,\n private readonly menu: HTMLElement,\n private readonly options: VdMenuControllerOptions,\n ) {\n trigger.addEventListener('pointerdown', this.onTriggerPointerDown);\n trigger.addEventListener('click', this.onTriggerClick);\n trigger.addEventListener('keydown', this.onTriggerKeydown);\n menu.addEventListener('keydown', this.onMenuKeydown);\n menu.addEventListener('click', this.onMenuClick);\n menu.addEventListener('pointermove', this.onPointerMove);\n menu.addEventListener('toggle', this.onToggle);\n }\n\n get isOpen(): boolean {\n return this.menu.matches(':popover-open');\n }\n\n open(focus: 'first' | 'last' = 'first'): void {\n if (!this.isOpen) {\n this.menu.showPopover({ source: this.trigger } as ShowPopoverOptions);\n this.options.onOpenChange?.(true);\n }\n const items = this.enabledItems();\n (focus === 'first' ? items[0] : items[items.length - 1])?.focus();\n }\n\n close(returnFocus: boolean): void {\n this.returnFocus = returnFocus;\n if (this.isOpen) this.menu.hidePopover();\n }\n\n destroy(): void {\n this.trigger.removeEventListener('pointerdown', this.onTriggerPointerDown);\n this.trigger.removeEventListener('click', this.onTriggerClick);\n this.trigger.removeEventListener('keydown', this.onTriggerKeydown);\n this.menu.removeEventListener('keydown', this.onMenuKeydown);\n this.menu.removeEventListener('click', this.onMenuClick);\n this.menu.removeEventListener('pointermove', this.onPointerMove);\n this.menu.removeEventListener('toggle', this.onToggle);\n }\n\n private enabledItems(): HTMLElement[] {\n return this.options.items().filter((i) => !isDisabled(i));\n }\n\n private readonly onTriggerPointerDown = () => {\n this.wasOpen = this.isOpen;\n };\n\n private readonly onTriggerClick = (event: MouseEvent) => {\n if (this.wasOpen || this.isOpen) {\n this.wasOpen = false;\n this.close(false);\n return;\n }\n // Enter/Space are handled in keydown (and prevented), so this is a pointer click.\n this.open('first');\n event.preventDefault();\n };\n\n private readonly onTriggerKeydown = (event: KeyboardEvent) => {\n const { key } = event;\n if (key === 'ArrowDown' || key === 'Enter' || key === ' ') {\n event.preventDefault();\n this.open('first');\n } else if (key === 'ArrowUp') {\n event.preventDefault();\n this.open('last');\n }\n };\n\n private readonly onMenuKeydown = (event: KeyboardEvent) => {\n const items = this.options.items();\n const current = items.indexOf(event.target as HTMLElement);\n const { key } = event;\n\n if (key === 'Escape') {\n event.preventDefault();\n this.close(true);\n return;\n }\n if (key === 'Tab') {\n this.close(false);\n return;\n }\n const target = vdListTarget(key, current, items.map(isDisabled), { loop: true, pageSize: 10 });\n if (target !== null) {\n event.preventDefault();\n items[target]?.focus();\n return;\n }\n if (VdTypeahead.accepts(event)) {\n const idx = this.typeahead.match(\n key,\n items.map((i) => i.textContent?.trim() ?? ''),\n items.map(isDisabled),\n current,\n );\n if (idx !== null) items[idx]?.focus();\n }\n };\n\n private readonly onMenuClick = (event: MouseEvent) => {\n const item = (event.target as Element).closest<HTMLElement>(ITEM);\n if (!item || !this.menu.contains(item)) return;\n if (isDisabled(item)) {\n event.preventDefault();\n event.stopImmediatePropagation();\n return;\n }\n // Item handlers already ran (bubbling reached the menu): close and restore focus.\n this.close(true);\n };\n\n /** Pointer and keyboard share one \"current\" item: hovering focuses it. */\n private readonly onPointerMove = (event: PointerEvent) => {\n if (event.pointerType === 'touch') return;\n const item = (event.target as Element).closest<HTMLElement>(ITEM);\n if (item && !isDisabled(item) && item !== this.menu.ownerDocument.activeElement) item.focus();\n };\n\n private readonly onToggle = (event: Event) => {\n if ((event as ToggleEvent).newState !== 'closed') return;\n this.typeahead.reset();\n this.options.onOpenChange?.(false);\n if (this.returnFocus) (this.options.returnFocusTo?.() ?? this.trigger).focus();\n this.returnFocus = false;\n };\n}\n","import {\n DestroyRef,\n Directive,\n ElementRef,\n afterNextRender,\n booleanAttribute,\n inject,\n input,\n signal,\n} from '@angular/core';\nimport { vdUniqueId } from '@vadem/ui/field';\nimport { VdMenuController } from './core/menu-controller';\n\n/** Menu panel: a `popover=\"auto\"` with `role=\"menu\"`. Open it with `vdMenuTrigger`. */\n@Directive({\n selector: '[vdMenu]',\n exportAs: 'vdMenu',\n host: {\n class: 'vd-menu',\n role: 'menu',\n popover: 'auto',\n tabindex: '-1',\n '[id]': 'id',\n '[attr.aria-labelledby]': 'labelledBy()',\n },\n})\nexport class VdMenu {\n readonly id = vdUniqueId('vd-menu');\n readonly el: HTMLElement = inject(ElementRef).nativeElement;\n readonly labelledBy = signal<string | null>(null);\n\n items(): HTMLElement[] {\n return Array.from(this.el.querySelectorAll<HTMLElement>('[role=\"menuitem\"]'));\n }\n}\n\n/** Opens a `vdMenu`. Use on a button (works with `vdButton`). Spec: specs/menu.md */\n@Directive({\n selector: 'button[vdMenuTrigger]',\n host: {\n 'aria-haspopup': 'menu',\n '[attr.aria-expanded]': 'open()',\n '[attr.aria-controls]': 'vdMenuTrigger().id',\n '[attr.data-state]': 'open() ? \"open\" : \"closed\"',\n },\n})\nexport class VdMenuTrigger {\n readonly vdMenuTrigger = input.required<VdMenu>();\n protected readonly open = signal(false);\n private readonly el: HTMLButtonElement = inject(ElementRef).nativeElement;\n\n constructor() {\n const destroyRef = inject(DestroyRef);\n afterNextRender(() => {\n const menu = this.vdMenuTrigger();\n if (!this.el.id) this.el.id = vdUniqueId('vd-menu-trigger');\n menu.labelledBy.set(this.el.id);\n const name = `--${menu.id}`;\n this.el.style.setProperty('anchor-name', name);\n menu.el.style.setProperty('position-anchor', name);\n const controller = new VdMenuController(this.el, menu.el, {\n items: () => menu.items(),\n onOpenChange: (open) => this.open.set(open),\n });\n destroyRef.onDestroy(() => controller.destroy());\n });\n }\n}\n\nexport type VdMenuItemVariant = 'default' | 'danger';\n\n@Directive({\n selector: 'button[vdMenuItem], a[vdMenuItem]',\n host: {\n class: 'vd-menu__item',\n role: 'menuitem',\n tabindex: '-1',\n '[attr.type]': 'isButton ? \"button\" : null',\n '[attr.data-variant]': 'variant()',\n '[attr.aria-disabled]': 'disabled() || null',\n },\n})\nexport class VdMenuItem {\n readonly variant = input<VdMenuItemVariant>('default');\n /** Disabled items stay in the menu (discoverable) but are skipped and inert. */\n readonly disabled = input(false, { transform: booleanAttribute });\n protected readonly isButton =\n (inject(ElementRef).nativeElement as HTMLElement).tagName === 'BUTTON';\n}\n\n@Directive({\n selector: '[vdMenuSeparator]',\n host: { class: 'vd-menu__separator', role: 'separator' },\n})\nexport class VdMenuSeparator {}\n\n/** Group heading inside a menu (mono eyebrow). Presentational. */\n@Directive({\n selector: '[vdMenuLabel]',\n host: { class: 'vd-menu__label', role: 'presentation' },\n})\nexport class VdMenuLabel {}\n\nexport const VD_MENU = [VdMenu, VdMenuTrigger, VdMenuItem, VdMenuSeparator, VdMenuLabel] as const;\n","import { DOCUMENT } from '@angular/common';\nimport { DestroyRef, Directive, ElementRef, inject, input, output } from '@angular/core';\nimport { vdUniqueId } from '@vadem/ui/field';\nimport { vdTexts } from '@vadem/ui/locale';\nimport { VdMenuController } from './core/menu-controller';\nimport type { VdMenu } from './menu';\n\n/** Touch hold that opens the menu where `contextmenu` does not fire (iOS Safari). */\nconst LONG_PRESS_MS = 500;\nconst LONG_PRESS_SLOP = 10;\n\n/** One controller and one virtual anchor per menu, shared by every region that opens it. */\ninterface Shared {\n anchor: HTMLElement;\n controller: VdMenuController;\n opener: HTMLElement | null;\n users: number;\n}\nconst shared = new WeakMap<HTMLElement, Shared>();\n\nfunction acquire(menu: VdMenu, doc: Document): Shared {\n let entry = shared.get(menu.el);\n if (!entry) {\n const anchor = doc.createElement('span');\n anchor.className = 'vd-context-menu__anchor';\n anchor.setAttribute('aria-hidden', 'true');\n const name = `--${vdUniqueId('vd-context-anchor')}`;\n anchor.style.setProperty('anchor-name', name);\n menu.el.style.setProperty('position-anchor', name);\n // Next to the menu, so it shares any dialog's top layer and inert state.\n (menu.el.parentElement ?? doc.body).appendChild(anchor);\n const created: Shared = {\n anchor,\n opener: null,\n users: 0,\n controller: new VdMenuController(anchor, menu.el, {\n items: () => menu.items(),\n returnFocusTo: () => created.opener,\n }),\n };\n entry = created;\n shared.set(menu.el, entry);\n }\n entry.users++;\n return entry;\n}\n\nfunction release(menu: VdMenu): void {\n const entry = shared.get(menu.el);\n if (!entry || --entry.users > 0) return;\n entry.controller.destroy();\n entry.anchor.remove();\n shared.delete(menu.el);\n}\n\n/**\n * Opens a `vdMenu` at the pointer on right-click / long-press, or at the focused element on\n * the ContextMenu key and Shift+F10. Spec: specs/menu.md\n */\n@Directive({\n selector: '[vdContextMenu]',\n host: {\n class: 'vd-context-menu-target',\n '(contextmenu)': 'onContextMenu($event)',\n '(keydown)': 'onKeydown($event)',\n '(pointerdown)': 'onPointerDown($event)',\n },\n})\nexport class VdContextMenu {\n readonly vdContextMenu = input.required<VdMenu>();\n /** Accessible name of the menu while this region opened it. */\n readonly label = input<string>();\n /** Fires before the menu opens, so the consumer can point it at this region's item. */\n readonly opened = output<void>();\n\n protected readonly t = vdTexts('contextMenu', { label: this.label });\n private readonly el: HTMLElement = inject(ElementRef).nativeElement;\n private readonly doc = inject(DOCUMENT);\n private entry: Shared | null = null;\n private pendingPointerOpen: ((event: PointerEvent) => void) | null = null;\n private pressTimer: ReturnType<typeof setTimeout> | undefined;\n\n constructor() {\n inject(DestroyRef).onDestroy(() => {\n clearTimeout(this.pressTimer);\n this.cancelPointerOpen();\n if (this.entry) release(this.vdContextMenu());\n });\n }\n\n protected onContextMenu(event: MouseEvent): void {\n // Shift+right-click keeps the browser's own menu (copy, inspect) available.\n if (event.shiftKey && event.button === 2) return;\n event.preventDefault();\n this.cancelPointerOpen();\n const { clientX: x, clientY: y } = event;\n const origin = event.target as HTMLElement;\n // Some engines dispatch contextmenu before right-button release. Opening an\n // auto popover then lets that same pointerup immediately light-dismiss it.\n if (event.buttons & 2) {\n this.pendingPointerOpen = (release) => {\n if (release.button !== 2) return;\n this.cancelPointerOpen();\n if (origin.isConnected) this.openAt(x, y, origin);\n };\n this.doc.addEventListener('pointerup', this.pendingPointerOpen);\n this.doc.addEventListener('pointercancel', this.cancelPointerOpen);\n } else {\n this.openAt(x, y, origin);\n }\n }\n\n private readonly cancelPointerOpen = (): void => {\n if (this.pendingPointerOpen) {\n this.doc.removeEventListener('pointerup', this.pendingPointerOpen);\n this.pendingPointerOpen = null;\n }\n this.doc.removeEventListener('pointercancel', this.cancelPointerOpen);\n };\n\n protected onKeydown(event: KeyboardEvent): void {\n const keyboardMenu = event.key === 'ContextMenu' || (event.shiftKey && event.key === 'F10');\n if (!keyboardMenu) return;\n event.preventDefault();\n const target = (event.target as HTMLElement) ?? this.el;\n const rect = target.getBoundingClientRect();\n const rtl = this.doc.defaultView?.getComputedStyle(target).direction === 'rtl';\n this.openAt(rtl ? rect.right : rect.left, rect.bottom, target);\n }\n\n protected onPointerDown(event: PointerEvent): void {\n if (event.pointerType !== 'touch') return;\n const { clientX: x, clientY: y } = event;\n const target = event.target as HTMLElement;\n const cancel = (e?: PointerEvent) => {\n if (\n e &&\n e.type === 'pointermove' &&\n Math.hypot(e.clientX - x, e.clientY - y) < LONG_PRESS_SLOP\n )\n return;\n clearTimeout(this.pressTimer);\n this.el.removeEventListener('pointermove', cancel);\n this.el.removeEventListener('pointerup', cancel);\n this.el.removeEventListener('pointercancel', cancel);\n };\n this.el.addEventListener('pointermove', cancel);\n this.el.addEventListener('pointerup', cancel);\n this.el.addEventListener('pointercancel', cancel);\n clearTimeout(this.pressTimer);\n this.pressTimer = setTimeout(() => {\n cancel();\n this.openAt(x, y, target);\n }, LONG_PRESS_MS);\n }\n\n private openAt(x: number, y: number, origin: HTMLElement): void {\n const menu = this.vdContextMenu();\n this.entry ??= acquire(menu, this.doc);\n // Android also fires contextmenu after a long press; one opening is enough.\n if (this.entry.controller.isOpen && this.entry.opener === this.focusable(origin)) return;\n this.opened.emit();\n this.entry.opener = this.focusable(origin);\n this.place(this.entry.anchor, x, y);\n menu.el.setAttribute('aria-label', this.t().label);\n menu.labelledBy.set(null);\n this.entry.controller.close(false);\n this.entry.controller.open('first');\n }\n\n /**\n * Puts the zero-size anchor at viewport point (x, y). An ancestor with a transform, filter or\n * container query becomes the fixed containing block, so the first guess is measured and\n * corrected by the difference. Insets stay logical: in RTL inline-start grows leftwards.\n */\n private place(anchor: HTMLElement, x: number, y: number): void {\n const rtl = this.doc.defaultView?.getComputedStyle(anchor).direction === 'rtl';\n let inline = rtl ? this.doc.documentElement.clientWidth - x : x;\n let block = y;\n const set = () => {\n anchor.style.setProperty('--vd-context-x', `${inline}px`);\n anchor.style.setProperty('--vd-context-y', `${block}px`);\n };\n set();\n const rect = anchor.getBoundingClientRect();\n inline += rtl ? rect.left - x : x - rect.left;\n block += y - rect.top;\n set();\n }\n\n /** Focus returns to the nearest focusable element of this region, or the region itself. */\n private focusable(origin: HTMLElement): HTMLElement {\n const candidate = origin.closest<HTMLElement>(\n 'a[href], button, input, select, textarea, [tabindex]',\n );\n return candidate && this.el.contains(candidate) ? candidate : this.el;\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vadem/ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"@angular/common": "^22.2.0",
|
|
6
6
|
"@angular/core": "^22.2.0",
|
|
@@ -303,6 +303,29 @@
|
|
|
303
303
|
"default": "./fesm2022/vadem-ui-upload-list.mjs"
|
|
304
304
|
}
|
|
305
305
|
},
|
|
306
|
+
"description": "Modern Angular UI components with dark and light themes, CSS design tokens, keyboard interactions, and English/Ukrainian localization.",
|
|
307
|
+
"keywords": [
|
|
308
|
+
"angular",
|
|
309
|
+
"ui",
|
|
310
|
+
"components",
|
|
311
|
+
"design-system",
|
|
312
|
+
"signals",
|
|
313
|
+
"theming",
|
|
314
|
+
"accessibility"
|
|
315
|
+
],
|
|
316
|
+
"repository": {
|
|
317
|
+
"type": "git",
|
|
318
|
+
"url": "git+https://github.com/Demchuk12/vadem-ui-angular.git",
|
|
319
|
+
"directory": "projects/ui"
|
|
320
|
+
},
|
|
321
|
+
"homepage": "https://github.com/Demchuk12/vadem-ui-angular#readme",
|
|
322
|
+
"bugs": {
|
|
323
|
+
"url": "https://github.com/Demchuk12/vadem-ui-angular/issues"
|
|
324
|
+
},
|
|
325
|
+
"publishConfig": {
|
|
326
|
+
"access": "public",
|
|
327
|
+
"registry": "https://registry.npmjs.org/"
|
|
328
|
+
},
|
|
306
329
|
"module": "fesm2022/vadem-ui.mjs",
|
|
307
330
|
"typings": "types/vadem-ui.d.ts",
|
|
308
331
|
"type": "module"
|
package/types/vadem-ui-menu.d.ts
CHANGED
|
@@ -99,9 +99,11 @@ export declare class VdContextMenu {
|
|
|
99
99
|
private readonly el;
|
|
100
100
|
private readonly doc;
|
|
101
101
|
private entry;
|
|
102
|
+
private pendingPointerOpen;
|
|
102
103
|
private pressTimer;
|
|
103
104
|
constructor();
|
|
104
105
|
protected onContextMenu(event: MouseEvent): void;
|
|
106
|
+
private readonly cancelPointerOpen;
|
|
105
107
|
protected onKeydown(event: KeyboardEvent): void;
|
|
106
108
|
protected onPointerDown(event: PointerEvent): void;
|
|
107
109
|
private openAt;
|