import * as _floating_ui_dom from '@floating-ui/dom'; import * as forty_cdk_core_overlay from 'forty-cdk/core-overlay'; import { MenuActivationModality, MenuOverlayHost, ForMenuContext, FloatingFallbackAxisSideDirection, AnchoredPositioningOverride, MenuOpenerPositioning, AnchoredPositioningSeedDefaults, FloatingSide, FloatingAlign } from 'forty-cdk/core-overlay'; import * as _angular_core from '@angular/core'; import { InjectionToken, Signal, Provider } from '@angular/core'; import * as forty_cdk_context_menu from 'forty-cdk/context-menu'; import { WritingDirection, VetoableNativeEvent, VetoableEvent } from 'forty-cdk/core'; /** * Coordination contract `[forContextMenuTrigger]` resolves from its enclosing * `[forContextMenu]` root. It exposes exactly the slice of the root the * trigger consumes: open / disabled state, trigger registration (for * return-focus on close), the pointer / keyboard virtual-anchor setters, and * the open entry point. * * `ForContextMenu` provides it via `useExisting`, so a subclassed root (the * standard design-system wrapping pattern) only has to re-provide tokens — * `FOR_MENU_CONTEXT` for items / content and `FOR_CONTEXT_MENU_CONTEXT` for * the trigger — never a concrete-class alias. */ interface ForContextMenuContext { /** * Whether the menu is currently shown. Read-only at the contract level — * the root backs it with its own `model` and writes through its * `openMenu` / `closeMenu` plumbing; the trigger only ever reads. */ readonly open: Signal; /** * When `true`, trigger activations are no-ops and the `contextmenu` event * falls through to the native browser menu. */ readonly disabled: Signal; /** * Id mirrored to the trigger's host `[id]`, adopting a consumer-set static * `id` when present. It is **not** used as the menu's * `aria-labelledby` target — the trigger is the whole right-click region, so * naming the menu after it would announce the region's entire text; name the * menu with `ariaLabel` instead. The id stays exposed as a stable hook for * the consumer's own references and test selectors. */ readonly triggerId: Signal; /** Registers the trigger element so it receives return-focus on close. */ registerTrigger(el: HTMLElement): void; /** Unregisters a previously registered trigger element. */ unregisterTrigger(el: HTMLElement): void; /** Updates the virtual anchor to a 0×0 rect at (`x`, `y`) in viewport coordinates. */ setVirtualAnchor(x: number, y: number): void; /** * Updates the virtual anchor to a by-value snapshot of `rect`. Used by the * keyboard activators (`Shift+F10`, the `ContextMenu` key) so the menu * floats off the focused element instead of the pointer position. */ setVirtualAnchorFromRect(rect: DOMRect): void; /** * Opens the menu and sends focus to its first or last enabled item * (default `'first'`). Honours `disabled`. `modality` (default * `'keyboard'`) records how the open was activated: a `'pointer'` open * (right-click / long-press) keeps the programmatic initial focus from * reflecting `data-highlighted`, while a `'keyboard'` open (`Shift+F10`, * the `ContextMenu` key) highlights the focused item. */ openMenu(initialFocus?: 'first' | 'last', modality?: MenuActivationModality): void; } /** * Token under which `[forContextMenu]` exposes the {@link ForContextMenuContext} * surface to its `[forContextMenuTrigger]`. Subclassed roots re-provide it with * `{ provide: FOR_CONTEXT_MENU_CONTEXT, useExisting: MySubclass }`. */ declare const FOR_CONTEXT_MENU_CONTEXT: InjectionToken; /** * Headless implementation of a right-click / `Shift+F10` menu (variant of * the [WAI-ARIA Menu pattern](https://www.w3.org/WAI/ARIA/apg/patterns/menubar/)). * Apply on a wrapper that contains a `[forContextMenuTrigger]` and an * `@if`-mounted `[forMenuContent]`. * * The menu is positioned at the pointer location at the time of the * `contextmenu` event — implemented via floating-ui's virtual element so * placement / flip / shift middleware still apply normally. Selecting an * item, Escape, or any outside interaction closes. * * ```html *
*
Right-click here
* @if (open()) { *
* } *
* ``` * * Most of the directive's body (id generation, item collection, typeahead, * navigate / focus helpers, escape / outside-click veto plumbing) is owned * by the shared `_internal/menu-overlay` helper. The directive contributes * the inputs / outputs / model that make up the public surface, the * pointer-driven `VirtualElement` anchor (`setVirtualAnchor` / * `setVirtualAnchorFromRect`), and the contextmenu-specific dismissible * semantics (no exemption — a left-click on the right-click region while * the menu is open should close it). */ declare class ForContextMenu extends MenuOverlayHost implements ForMenuContext, ForContextMenuContext { protected readonly positioningDefaults: forty_cdk_context_menu.ForContextMenuDefaults; /** * Two-way bindable. Whether the menu is currently shown. The `model()` change emitter fires only * when the primitive itself opens or closes the menu, never on consumer writes through * `[(open)]`. */ readonly open: _angular_core.ModelSignal; /** * Direction `flip` falls back to on the perpendicular axis when both sides of * the preferred axis overflow. `'none'` (default) keeps only the opposite * same-axis placement; `'start'` / `'end'` let the menu drop to a * perpendicular side on a narrow viewport. Only consulted when * `avoidCollisions` is on. The default is read from * `provideForContextMenuDefaults` for the surrounding scope, since dropping to * a perpendicular side is a design-system-wide viewport-degradation policy * rather than a per-menu one. */ readonly fallbackAxisSideDirection: _angular_core.InputSignal; /** * When `true` (default), arrow-key navigation wraps from the last enabled * item back to the first (and vice versa). When `false`, navigation stops * at the ends. */ readonly loop: _angular_core.InputSignalWithTransform; /** * Writing direction. Drives ArrowLeft / ArrowRight semantics on submenu * triggers and items underneath this menu (in RTL, ArrowLeft opens a submenu * and ArrowRight closes it back). When unset (default `null`), the inherited * ambient direction is resolved from the nearest ancestor carrying a `dir` * attribute (or ``), defaulting to `'ltr'`. An explicit `[dir]` * always wins, the resolved value is reflected to the host `dir` attribute, * and it is inherited by descendant submenus. */ readonly _dirInput: _angular_core.InputSignal; readonly dir: _angular_core.Signal; /** * When true, the contextmenu event is allowed to fall through to the * native browser menu. Useful for letting the OS-provided context menu * appear on certain regions while keeping the directive mounted. */ readonly disabled: _angular_core.InputSignalWithTransform; /** When true (default), Escape, pointer-down outside, and focus outside close the menu. */ readonly dismissible: _angular_core.InputSignalWithTransform; /** When true (default), focus returns to the right-click target on close. */ readonly returnFocus: _angular_core.InputSignalWithTransform; /** * Accessible name reflected as `aria-label` on `[forMenuContent]`. This is * the only name hook the root exposes for a context menu: the right-click * region is never used as an `aria-labelledby` target, so with no * `ariaLabel` (and no consumer-set static `aria-labelledby` on the content) * the surface exposes no accessible name at all. */ readonly ariaLabel: _angular_core.InputSignal; /** * Fires when Escape is pressed while the menu is open, just before it * closes. Call `preventDefault()` on the emitted veto to keep the menu * open and suppress the Escape-driven close. */ readonly escapeKeyDown: _angular_core.OutputEmitterRef>; /** * Fires on a pointer-down outside the menu, just before it closes. Call * `preventDefault()` on the veto to keep the menu open. */ readonly pointerDownOutside: _angular_core.OutputEmitterRef>; /** * Fires when focus moves outside the menu, just before it closes. Call * `preventDefault()` on the veto to keep the menu open. */ readonly focusOutside: _angular_core.OutputEmitterRef>; /** * Composite outside-interaction channel: fires for either a * pointer-down-outside or a focus-outside, just before the menu closes. * Call `preventDefault()` on the veto to keep the menu open regardless of * which interaction triggered it. */ readonly interactOutside: _angular_core.OutputEmitterRef>; /** * Fires just before the menu sends focus to its first / last enabled * item on mount. Call `preventDefault()` on the emitted veto to skip * the imperative focus move. */ readonly autoFocusOnOpen: _angular_core.OutputEmitterRef; /** * Fires just before focus returns to the trigger on unmount. Call * `preventDefault()` on the veto to suppress the return-focus. */ readonly autoFocusOnClose: _angular_core.OutputEmitterRef; protected readonly _overlay: forty_cdk_core_overlay.MenuOverlay; /** * Virtual-anchor only: a context menu with no recorded pointer / rect position * stays unanchored rather than falling back to its whole right-click region. */ readonly anchor: _angular_core.Signal<_floating_ui_dom.ReferenceElement | null>; /** * The region's own `[menuPositioning]` override, resolved by the base ahead * of this root's `[side]` / `[align]` / `[sideOffset]` / `[alignOffset]`. It * runs through the opener registry so a trigger carries the same override * here as it does under a shared `[forMenu]` root; with no override the four * values are this root's inputs verbatim. */ protected positioningOverride(): AnchoredPositioningOverride | null; /** * ContextMenu exempts nothing — a left-click on the right-click region * while the menu is open should close it like any other outside click. The * right-click region registers without asking for an exemption, so the shared * opener registry resolves this to an empty list rather than a second source. */ readonly dismissibleExemptions: _angular_core.Signal; /** * The right-click region is not a labelling element, so `[forMenuContent]` * emits no `aria-labelledby` fallback for this flavor — pointing the menu's * name at the region would announce its entire text. Name the menu with * `[ariaLabel]` instead. * * Constant: this root's only opener flavour is the region, so unlike * `[forMenu]` it has nothing to resolve per opener. */ readonly triggerLabelsMenu: _angular_core.Signal; /** Top-level: no parent menu. */ readonly parentMenu: null; /** * Updates the virtual anchor to a 0×0 rect at (`x`, `y`) in viewport * coordinates. Widens the shared base's protected pass-through to the public * `ForContextMenuContext` member `[forContextMenuTrigger]` calls. */ setVirtualAnchor(x: number, y: number): void; /** * Updates the virtual anchor to a snapshot of `rect`. Used by the keyboard * activators (`Shift+F10`, `ContextMenu` key) so the menu floats off the * focused element instead of the pointer position. The rect is captured * by value, so subsequent layout changes don't shift the anchor. */ setVirtualAnchorFromRect(rect: DOMRect): void; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵdir: _angular_core.ɵɵDirectiveDeclaration; } /** * Region that opens its parent `[forContextMenu]` on the `contextmenu` event * (right-click / long-press on touch) and on the keyboard equivalents * `Shift+F10` and the dedicated `ContextMenu` key. Pointer activations are * anchored at the cursor; keyboard activations are anchored at the bounding * rect of the focused element, so screen-reader / keyboard-only users get * the menu next to whatever they're working on. The native context menu is * suppressed via `event.preventDefault()`. * * A pointer activation skips `data-highlighted` on the initially focused item; * a keyboard activation highlights it. * * On touch the directive runs its own long-press timer: a `touch` `pointerdown` * held for ~500ms — without lifting or moving past a small tolerance — opens * the menu at the touch point, anchored like a right-click. Where the browser * synthesizes `contextmenu` for a long-press the two paths are mutually * exclusive, so the menu opens exactly once. Suppress the native iOS callout * and text selection on the trigger with CSS * (`-webkit-touch-callout: none; user-select: none;`) — otherwise the OS * gesture fires `pointercancel` and cancels the press. * * Apply on any element. A default `tabindex="-1"` is host-bound so the trigger * can receive programmatic focus and return-focus works on close; set your own * `tabindex` (e.g. `tabindex="0"` to put it in the Tab order) and it wins. The * keyboard activators need the trigger — or something inside it — focusable. * * The root is normally resolved via DI from the enclosing `[forContextMenu]`. * When the trigger is declared inside an `ng-template` stamped into the root * (e.g. via `ngTemplateOutlet`), DI resolves at the template's declaration * site and misses the root — pass it explicitly through the selector input, * `routerLink`-style: `[forContextMenuTrigger]="root"` with * `#root="forContextMenu"`. * * The host carries a generated `id`, adopting a consumer-set static one. No * ARIA wiring consumes it — the menu is named with `ariaLabel`, not * `aria-labelledby` — so it serves as a stable consumer and test hook. * * Disabling merges the trigger's own `disabled` input with the root's. When * disabled, only `data-disabled` is reflected: the trigger is a generic region * with no interactive ARIA role, so it emits neither the native `disabled` * attribute nor `aria-disabled`, and the native browser menu shows through. */ declare class ForContextMenuTrigger { #private; /** * The region's own aria-wiring id, adopting a consumer-set static `id`. It is * per-opener rather than per-root so a menu shared by several openers * (`[forMenu]`) never emits the same `id` twice. The region is not a labelling * control, so the trigger registers as one that must not name the surface — a * menu it opened emits no `aria-labelledby` even when a sibling button opener * would have. */ readonly id: _angular_core.Signal; /** * Optional explicit reference to the `[forContextMenu]` root, named after * the selector `routerLink`-style. The bare valueless attribute keeps * resolving the enclosing root via DI; pass the root explicitly * (`[forContextMenuTrigger]="root"`, with `#root="forContextMenu"`) when * the trigger is declared in an `ng-template` stamped inside the root — * DI resolves at the template's declaration site, so the enclosing root * is invisible there. The empty string (what the valueless attribute * yields) is treated as unset. */ readonly forContextMenuTrigger: _angular_core.InputSignal<"" | ForContextMenuContext>; protected readonly ctx: _angular_core.Signal; /** Disables this trigger only, in addition to the root's `disabled`. */ readonly disabled: _angular_core.InputSignalWithTransform; /** * Placement override for the opens this region drives, falling back to the * root's inputs for every key it leaves out. Only the four placement values * are overridable (`side`, `align`, `sideOffset`, `alignOffset`); the rest of * the positioning surface is collision policy the root owns. * * It exists for a menu shared by heterogeneous openers, where one root cannot * pick offsets that suit them all — a pointer-anchored region wants to sit * flush at the cursor, where a sibling button opener wants a few pixels of * clearance: * * ```html * … * ``` * * It resolves identically under a `[forContextMenu]` root, where it is simply * a per-trigger spelling of the root's own inputs. */ readonly menuPositioning: _angular_core.InputSignal; /** Whether the trigger is disabled — its own `disabled` input OR the root's. */ readonly effectiveDisabled: _angular_core.Signal; constructor(); protected onPointerDown(event: PointerEvent): void; protected onPointerMove(event: PointerEvent): void; protected onPointerRelease(): void; protected onContextMenu(event: MouseEvent): void; protected onKeyDown(event: KeyboardEvent): void; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵdir: _angular_core.ɵɵDirectiveDeclaration; } /** * Defaults inherited by descendant context menus in the surrounding * injector scope. Configure with `provideForContextMenuDefaults` either * at the application root or in any component's `providers` array; partial * overrides merge with the parent scope. */ interface ForContextMenuDefaults extends AnchoredPositioningSeedDefaults { /** * Side the menu is anchored to, relative to the virtual anchor at the * pointer, for context menus that don't override `side` locally. Library * fallback `'bottom'`. */ side: FloatingSide; /** * Alignment along the chosen `side` for context menus that don't override * `align` locally. Library fallback `'start'`. */ align: FloatingAlign; /** * Distance (px) between the virtual anchor (pointer position) and the * floating content along the resolved `side` axis. Defaults to `0` * since context menus open at the cursor. */ sideOffset: number; /** * Padding (px) added to the viewport edges for collision-aware * positioning. Higher values keep the floating content further from * the edge when `flip` / `shift` runs. */ collisionPadding: number; /** * Direction `flip` falls back to on the perpendicular axis when both sides * of the preferred axis overflow. `'none'` (default) keeps only the opposite * same-axis placement; `'start'` / `'end'` let a menu clipped on a narrow * viewport drop to a perpendicular side. Only consulted when * `avoidCollisions` is on. */ fallbackAxisSideDirection: FloatingFallbackAxisSideDirection; } /** Token holding the resolved context-menu defaults for the current scope. */ declare const FOR_CONTEXT_MENU_DEFAULTS: _angular_core.InjectionToken; /** * Configures forty-cdk context-menu defaults for this injector scope. * Partial overrides inherit unspecified keys from the parent scope (or * library defaults at the root). */ declare function provideForContextMenuDefaults(defaults?: Partial): Provider[]; export { FOR_CONTEXT_MENU_CONTEXT, FOR_CONTEXT_MENU_DEFAULTS, ForContextMenu, ForContextMenuTrigger, provideForContextMenuDefaults }; export type { ForContextMenuContext, ForContextMenuDefaults };