diff --git a/src/aria/private/behaviors/event-manager/event-manager.ts b/src/aria/private/behaviors/event-manager/event-manager.ts index f6718617cc8f..212bd3fcde17 100644 --- a/src/aria/private/behaviors/event-manager/event-manager.ts +++ b/src/aria/private/behaviors/event-manager/event-manager.ts @@ -24,6 +24,7 @@ export interface EventWithModifiers extends Event { * This library has not yet had a need for stopPropagationImmediate. */ export interface EventHandlerOptions { + handleRepeat?: boolean; stopPropagation: boolean; preventDefault: boolean; } diff --git a/src/aria/private/behaviors/event-manager/keyboard-event-manager.ts b/src/aria/private/behaviors/event-manager/keyboard-event-manager.ts index a088f744dda3..43cdc62d2a95 100644 --- a/src/aria/private/behaviors/event-manager/keyboard-event-manager.ts +++ b/src/aria/private/behaviors/event-manager/keyboard-event-manager.ts @@ -30,6 +30,7 @@ type KeyCode = string | SignalLike | RegExp; */ export class KeyboardEventManager extends EventManager { options: EventHandlerOptions = { + handleRepeat: false, preventDefault: true, stopPropagation: true, }; @@ -50,7 +51,7 @@ export class KeyboardEventManager extends EventManager< this.configs.push({ handler: handler, - matcher: event => this._isMatch(event, key, modifiers), + matcher: event => this._isMatch(event, key, modifiers, options), ...this.options, ...options, }); @@ -73,11 +74,20 @@ export class KeyboardEventManager extends EventManager< }; } - private _isMatch(event: T, key: KeyCode, modifiers: ModifierInputs) { + private _isMatch( + event: T, + key: KeyCode, + modifiers: ModifierInputs, + options?: Partial, + ): boolean { if (!hasModifiers(event, modifiers)) { return false; } + if (event.repeat && !options?.handleRepeat) { + return false; + } + if (key instanceof RegExp) { return key.test(event.key); } diff --git a/src/aria/private/toolbar/toolbar.ts b/src/aria/private/toolbar/toolbar.ts index 25396ad6fe22..f0b384e6575d 100644 --- a/src/aria/private/toolbar/toolbar.ts +++ b/src/aria/private/toolbar/toolbar.ts @@ -80,10 +80,10 @@ export class ToolbarPattern { const manager = new KeyboardEventManager(); return manager - .on(this._nextKey, () => this.listBehavior.next()) - .on(this._prevKey, () => this.listBehavior.prev()) - .on(this._altNextKey, () => this._groupNext()) - .on(this._altPrevKey, () => this._groupPrev()) + .on(this._nextKey, () => this.listBehavior.next(), {handleRepeat: true}) + .on(this._prevKey, () => this.listBehavior.prev(), {handleRepeat: true}) + .on(this._altNextKey, () => this._groupNext(), {handleRepeat: true}) + .on(this._altPrevKey, () => this._groupPrev(), {handleRepeat: true}) .on(' ', () => this.select()) .on('Enter', () => this.select()) .on('Home', () => this.listBehavior.first()) @@ -179,7 +179,7 @@ export class ToolbarPattern { /** Handles click events for the toolbar. */ onClick(event: MouseEvent) { - if (this.disabled()) return; + if (this.disabled() || (event as PointerEvent).pointerType === '') return; this._goto(event); } diff --git a/src/aria/toolbar/toolbar.spec.ts b/src/aria/toolbar/toolbar.spec.ts index 26c246a9351a..d054d3c2b9e7 100644 --- a/src/aria/toolbar/toolbar.spec.ts +++ b/src/aria/toolbar/toolbar.spec.ts @@ -23,7 +23,9 @@ describe('Toolbar', () => { }; const click = (element: HTMLElement, eventInit?: PointerEventInit) => { - element.dispatchEvent(new PointerEvent('click', {bubbles: true, ...eventInit})); + element.dispatchEvent( + new PointerEvent('click', {bubbles: true, pointerType: 'mouse', ...eventInit}), + ); fixture.detectChanges(); };