Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions goldens/aria/grid/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,21 +60,21 @@ export class GridCell {
export class GridCellWidget {
constructor();
activate(): void;
readonly activated: _angular_core.OutputEmitterRef<FocusEvent | KeyboardEvent | undefined>;
readonly active: Signal<boolean>;
deactivate(): void;
readonly deactivated: _angular_core.OutputEmitterRef<FocusEvent | KeyboardEvent | undefined>;
readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
readonly element: HTMLElement;
readonly focusTarget: _angular_core.InputSignal<ElementRef<any> | HTMLElement | undefined>;
readonly id: _angular_core.InputSignal<string>;
get isActivated(): Signal<boolean>;
readonly onActivate: _angular_core.OutputEmitterRef<FocusEvent | KeyboardEvent | undefined>;
readonly onDeactivate: _angular_core.OutputEmitterRef<FocusEvent | KeyboardEvent | undefined>;
readonly _pattern: GridCellWidgetPattern;
protected readonly _tabIndex: Signal<number>;
readonly tabindex: _angular_core.InputSignal<number | undefined>;
readonly widgetType: _angular_core.InputSignal<"simple" | "complex" | "editable">;
// (undocumented)
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<GridCellWidget, "[ngGridCellWidget]", ["ngGridCellWidget"], { "id": { "alias": "id"; "required": false; "isSignal": true; }; "widgetType": { "alias": "widgetType"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "focusTarget": { "alias": "focusTarget"; "required": false; "isSignal": true; }; "tabindex": { "alias": "tabindex"; "required": false; "isSignal": true; }; }, { "onActivate": "onActivate"; "onDeactivate": "onDeactivate"; }, never, never, true, never>;
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<GridCellWidget, "[ngGridCellWidget]", ["ngGridCellWidget"], { "id": { "alias": "id"; "required": false; "isSignal": true; }; "widgetType": { "alias": "widgetType"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "focusTarget": { "alias": "focusTarget"; "required": false; "isSignal": true; }; "tabindex": { "alias": "tabindex"; "required": false; "isSignal": true; }; }, { "activated": "activated"; "deactivated": "deactivated"; }, never, never, true, never>;
// (undocumented)
static ɵfac: _angular_core.ɵɵFactoryDeclaration<GridCellWidget, never>;
}
Expand Down
8 changes: 4 additions & 4 deletions goldens/aria/menu/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class Menu<V> {
readonly expansionDelay: _angular_core.InputSignal<number>;
readonly id: _angular_core.InputSignal<string>;
readonly _items: Signal<MenuItem<V>[]>;
onSelect: _angular_core.OutputEmitterRef<V>;
readonly itemSelected: _angular_core.OutputEmitterRef<V>;
readonly parent: _angular_core.WritableSignal<MenuTrigger<V> | MenuItem<V> | undefined>;
readonly _pattern: MenuPattern<V>;
readonly tabIndex: Signal<0 | -1>;
Expand All @@ -28,7 +28,7 @@ export class Menu<V> {
readonly visible: Signal<boolean>;
readonly wrap: _angular_core.InputSignalWithTransform<boolean, unknown>;
// (undocumented)
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<Menu<any>, "[ngMenu]", ["ngMenu"], { "id": { "alias": "id"; "required": false; "isSignal": true; }; "wrap": { "alias": "wrap"; "required": false; "isSignal": true; }; "typeaheadDelay": { "alias": "typeaheadDelay"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "expansionDelay": { "alias": "expansionDelay"; "required": false; "isSignal": true; }; }, { "onSelect": "onSelect"; }, ["_allItems"], never, true, [{ directive: typeof DeferredContentAware; inputs: { "preserveContent": "preserveContent"; }; outputs: {}; }]>;
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<Menu<any>, "[ngMenu]", ["ngMenu"], { "id": { "alias": "id"; "required": false; "isSignal": true; }; "wrap": { "alias": "wrap"; "required": false; "isSignal": true; }; "typeaheadDelay": { "alias": "typeaheadDelay"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "expansionDelay": { "alias": "expansionDelay"; "required": false; "isSignal": true; }; }, { "itemSelected": "itemSelected"; }, ["_allItems"], never, true, [{ directive: typeof DeferredContentAware; inputs: { "preserveContent": "preserveContent"; }; outputs: {}; }]>;
// (undocumented)
static ɵfac: _angular_core.ɵɵFactoryDeclaration<Menu<any>, never>;
}
Expand All @@ -42,15 +42,15 @@ export class MenuBar<V> {
readonly element: HTMLElement;
// (undocumented)
readonly _items: SignalLike<MenuItem<V>[]>;
onSelect: _angular_core.OutputEmitterRef<V>;
readonly itemSelected: _angular_core.OutputEmitterRef<V>;
readonly _pattern: MenuBarPattern<V>;
readonly softDisabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
readonly textDirection: _angular_core.WritableSignal<_angular_cdk_bidi.Direction>;
readonly typeaheadDelay: _angular_core.InputSignal<number>;
readonly values: _angular_core.ModelSignal<V[]>;
readonly wrap: _angular_core.InputSignalWithTransform<boolean, unknown>;
// (undocumented)
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<MenuBar<any>, "[ngMenuBar]", ["ngMenuBar"], { "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "softDisabled": { "alias": "softDisabled"; "required": false; "isSignal": true; }; "values": { "alias": "values"; "required": false; "isSignal": true; }; "wrap": { "alias": "wrap"; "required": false; "isSignal": true; }; "typeaheadDelay": { "alias": "typeaheadDelay"; "required": false; "isSignal": true; }; }, { "values": "valuesChange"; "onSelect": "onSelect"; }, ["_allItems"], never, true, never>;
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<MenuBar<any>, "[ngMenuBar]", ["ngMenuBar"], { "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "softDisabled": { "alias": "softDisabled"; "required": false; "isSignal": true; }; "values": { "alias": "values"; "required": false; "isSignal": true; }; "wrap": { "alias": "wrap"; "required": false; "isSignal": true; }; "typeaheadDelay": { "alias": "typeaheadDelay"; "required": false; "isSignal": true; }; }, { "values": "valuesChange"; "itemSelected": "itemSelected"; }, ["_allItems"], never, true, never>;
// (undocumented)
static ɵfac: _angular_core.ɵɵFactoryDeclaration<MenuBar<any>, never>;
}
Expand Down
4 changes: 2 additions & 2 deletions goldens/aria/private/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ export class ListboxPattern<V> {
// @public
export interface MenuBarInputs<V> extends ListInputs<MenuItemPattern<V>, V> {
items: SignalLike<MenuItemPattern<V>[]>;
onSelect?: (value: V) => void;
itemSelected?: (value: V) => void;
textDirection: SignalLike<'ltr' | 'rtl'>;
}

Expand Down Expand Up @@ -533,7 +533,7 @@ export interface MenuInputs<V> extends Omit<ListInputs<MenuItemPattern<V>, V>, '
expansionDelay: SignalLike<number>;
id: SignalLike<string>;
items: SignalLike<MenuItemPattern<V>[]>;
onSelect?: (value: V) => void;
itemSelected?: (value: V) => void;
parent: SignalLike<MenuTriggerPattern<V> | MenuItemPattern<V> | undefined>;
textDirection: SignalLike<'ltr' | 'rtl'>;
}
Expand Down
14 changes: 6 additions & 8 deletions src/aria/grid/grid-cell-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@ export class GridCellWidget {
readonly focusTarget = input<ElementRef | HTMLElement | undefined>();

/** Emits when the widget is activated. */
readonly onActivate = output<KeyboardEvent | FocusEvent | undefined>();
readonly activated = output<KeyboardEvent | FocusEvent | undefined>();

/** Emits when the widget is deactivated. */
readonly onDeactivate = output<KeyboardEvent | FocusEvent | undefined>();
readonly deactivated = output<KeyboardEvent | FocusEvent | undefined>();

/** The tabindex override. */
readonly tabindex = input<number | undefined>();
Expand All @@ -96,10 +96,8 @@ export class GridCellWidget {
element: () => this.element,
cell: () => this._cell._pattern,
focusTarget: computed(() => {
if (this.focusTarget() instanceof ElementRef) {
return (this.focusTarget() as ElementRef).nativeElement;
}
return this.focusTarget();
const target = this.focusTarget();
return target instanceof ElementRef ? target.nativeElement : target;
}),
});

Expand All @@ -112,14 +110,14 @@ export class GridCellWidget {
afterRenderEffect(() => {
const activateEvent = this._pattern.lastActivateEvent();
if (activateEvent) {
this.onActivate.emit(activateEvent);
this.activated.emit(activateEvent);
}
});

afterRenderEffect(() => {
const deactivateEvent = this._pattern.lastDeactivateEvent();
if (deactivateEvent) {
this.onDeactivate.emit(deactivateEvent);
this.deactivated.emit(deactivateEvent);
}
});
}
Expand Down
4 changes: 2 additions & 2 deletions src/aria/menu/menu-bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export class MenuBar<V> {
private readonly _itemPatterns = signal<any[]>([]);

/** A callback function triggered when a menu item is selected. */
onSelect = output<V>();
readonly itemSelected = output<V>();

constructor() {
this._pattern = new MenuBarPattern({
Expand All @@ -118,7 +118,7 @@ export class MenuBar<V> {
focusMode: () => 'roving',
orientation: () => 'horizontal',
selectionMode: () => 'explicit',
onSelect: (value: V) => this.onSelect.emit(value),
itemSelected: (value: V) => this.itemSelected.emit(value),
activeItem: signal(undefined),
element: computed(() => this._elementRef.nativeElement),
});
Expand Down
7 changes: 4 additions & 3 deletions src/aria/menu/menu-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ import type {MenuBar} from './menu-bar';
* or action a user can take. They can also act as triggers for sub-menus.
*
* ```html
* <div ngMenuItem (onSelect)="doAction()">Action Item</div>
*
* <div ngMenuItem [submenu]="anotherMenu">Submenu Trigger</div>
* <div ngMenu (itemSelected)="doAction()">
* <div ngMenuItem >Action Item</div>
* <div ngMenuItem [submenu]="anotherMenu">Submenu Trigger</div>
* </div>
* ```
*
* @developerPreview 21.0
Expand Down
36 changes: 18 additions & 18 deletions src/aria/menu/menu.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,49 +157,49 @@ describe('Standalone Menu Pattern', () => {

it('should select an item on click', () => {
const banana = getItem('Banana');
spyOn(fixture.componentInstance, 'onSelect');
spyOn(fixture.componentInstance, 'itemSelected');

click(banana!);
expect(fixture.componentInstance.onSelect).toHaveBeenCalledWith('Banana');
expect(fixture.componentInstance.itemSelected).toHaveBeenCalledWith('Banana');
});

it('should select an item on enter', () => {
const banana = getItem('Banana');
spyOn(fixture.componentInstance, 'onSelect');
spyOn(fixture.componentInstance, 'itemSelected');

keydown(document.activeElement!, 'ArrowDown'); // Move focus to Banana
expect(document.activeElement).toBe(banana);

keydown(banana!, 'Enter');
expect(fixture.componentInstance.onSelect).toHaveBeenCalledWith('Banana');
expect(fixture.componentInstance.itemSelected).toHaveBeenCalledWith('Banana');
});

it('should select an item on space', () => {
const banana = getItem('Banana');
spyOn(fixture.componentInstance, 'onSelect');
spyOn(fixture.componentInstance, 'itemSelected');

keydown(document.activeElement!, 'ArrowDown'); // Move focus to Banana
expect(document.activeElement).toBe(banana);

keydown(banana!, ' ');
expect(fixture.componentInstance.onSelect).toHaveBeenCalledWith('Banana');
expect(fixture.componentInstance.itemSelected).toHaveBeenCalledWith('Banana');
});

it('should not select a disabled item', () => {
const cherry = getItem('Cherry');
spyOn(fixture.componentInstance, 'onSelect');
spyOn(fixture.componentInstance, 'itemSelected');

click(cherry!);
expect(fixture.componentInstance.onSelect).not.toHaveBeenCalled();
expect(fixture.componentInstance.itemSelected).not.toHaveBeenCalled();

keydown(document.activeElement!, 'End');
expect(document.activeElement).toBe(cherry);

keydown(cherry!, 'Enter');
expect(fixture.componentInstance.onSelect).not.toHaveBeenCalled();
expect(fixture.componentInstance.itemSelected).not.toHaveBeenCalled();

keydown(cherry!, ' ');
expect(fixture.componentInstance.onSelect).not.toHaveBeenCalled();
expect(fixture.componentInstance.itemSelected).not.toHaveBeenCalled();
});
});

Expand Down Expand Up @@ -317,18 +317,18 @@ describe('Standalone Menu Pattern', () => {
});

it('should close on selecting an item on click', () => {
spyOn(fixture.componentInstance, 'onSelect');
spyOn(fixture.componentInstance, 'itemSelected');
click(getItem('Berries')!); // open submenu
expect(isSubmenuExpanded()).toBe(true);

click(getItem('Blueberry')!);

expect(fixture.componentInstance.onSelect).toHaveBeenCalledWith('Blueberry');
expect(fixture.componentInstance.itemSelected).toHaveBeenCalledWith('Blueberry');
expect(isSubmenuExpanded()).toBe(false);
});

it('should close on selecting an item on enter', () => {
spyOn(fixture.componentInstance, 'onSelect');
spyOn(fixture.componentInstance, 'itemSelected');
const apple = getItem('Apple');
const banana = getItem('Banana');
const berries = getItem('Berries');
Expand All @@ -342,12 +342,12 @@ describe('Standalone Menu Pattern', () => {

keydown(blueberry!, 'Enter');

expect(fixture.componentInstance.onSelect).toHaveBeenCalledWith('Blueberry');
expect(fixture.componentInstance.itemSelected).toHaveBeenCalledWith('Blueberry');
expect(isSubmenuExpanded()).toBe(false);
});

it('should close on selecting an item on space', () => {
spyOn(fixture.componentInstance, 'onSelect');
spyOn(fixture.componentInstance, 'itemSelected');
const apple = getItem('Apple');
const banana = getItem('Banana');
const berries = getItem('Berries');
Expand All @@ -361,7 +361,7 @@ describe('Standalone Menu Pattern', () => {

keydown(blueberry!, ' ');

expect(fixture.componentInstance.onSelect).toHaveBeenCalledWith('Blueberry');
expect(fixture.componentInstance.itemSelected).toHaveBeenCalledWith('Blueberry');
expect(isSubmenuExpanded()).toBe(false);
});

Expand Down Expand Up @@ -959,7 +959,7 @@ describe('Menu Bar Pattern', () => {

@Component({
template: `
<div ngMenu [expansionDelay]="0" (onSelect)="onSelect($event)">
<div ngMenu [expansionDelay]="0" (itemSelected)="itemSelected($event)">
<ng-template ngMenuContent>
<div ngMenuItem value='Apple' searchTerm='Apple'>Apple</div>
<div ngMenuItem value='Banana' searchTerm='Banana'>Banana</div>
Expand All @@ -980,7 +980,7 @@ describe('Menu Bar Pattern', () => {
imports: [Menu, MenuItem, MenuContent],
})
class StandaloneMenuExample {
onSelect(value: string) {}
itemSelected(value: string) {}
}

@Component({
Expand Down
4 changes: 2 additions & 2 deletions src/aria/menu/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export class Menu<V> {
readonly tabIndex = computed(() => this._pattern.tabIndex());

/** A callback function triggered when a menu item is selected. */
onSelect = output<V>();
readonly itemSelected = output<V>();

/** The delay in milliseconds before expanding sub-menus on hover. */
readonly expansionDelay = input<number>(100); // Arbitrarily chosen.
Expand All @@ -151,7 +151,7 @@ export class Menu<V> {
selectionMode: () => 'explicit',
activeItem: signal(undefined),
element: computed(() => this._elementRef.nativeElement),
onSelect: (value: V) => this.onSelect.emit(value),
itemSelected: (value: V) => this.itemSelected.emit(value),
});

afterRenderEffect(() => {
Expand Down
20 changes: 10 additions & 10 deletions src/aria/private/menu/menu.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,43 +254,43 @@ describe('Standalone Menu Pattern', () => {
describe('Selection', () => {
it('should select an item on click', () => {
const items = menu.inputs.items();
menu.inputs.onSelect = jasmine.createSpy('onSelect');
menu.inputs.itemSelected = jasmine.createSpy('itemSelected');
menu.onClick(clickMenuItem(items, 1));
expect(menu.inputs.onSelect).toHaveBeenCalledWith('b');
expect(menu.inputs.itemSelected).toHaveBeenCalledWith('b');
});

it('should select an item on enter', () => {
const items = menu.inputs.items();
menu.inputs.activeItem.set(items[1]);
menu.inputs.onSelect = jasmine.createSpy('onSelect');
menu.inputs.itemSelected = jasmine.createSpy('itemSelected');

menu.onKeydown(enter());
expect(menu.inputs.onSelect).toHaveBeenCalledWith('b');
expect(menu.inputs.itemSelected).toHaveBeenCalledWith('b');
});

it('should select an item on space', () => {
const items = menu.inputs.items();
menu.inputs.activeItem.set(items[1]);
menu.inputs.onSelect = jasmine.createSpy('onSelect');
menu.inputs.itemSelected = jasmine.createSpy('itemSelected');

menu.onKeydown(space());
expect(menu.inputs.onSelect).toHaveBeenCalledWith('b');
expect(menu.inputs.itemSelected).toHaveBeenCalledWith('b');
});

it('should not select a disabled item', () => {
const items = menu.inputs.items() as TestMenuItem[];
items[1].inputs.disabled.set(true);
menu.inputs.activeItem.set(items[1]);
menu.inputs.onSelect = jasmine.createSpy('onSelect');
menu.inputs.itemSelected = jasmine.createSpy('itemSelected');

menu.onClick(clickMenuItem(items, 1));
expect(menu.inputs.onSelect).not.toHaveBeenCalled();
expect(menu.inputs.itemSelected).not.toHaveBeenCalled();

menu.onKeydown(enter());
expect(menu.inputs.onSelect).not.toHaveBeenCalled();
expect(menu.inputs.itemSelected).not.toHaveBeenCalled();

menu.onKeydown(space());
expect(menu.inputs.onSelect).not.toHaveBeenCalled();
expect(menu.inputs.itemSelected).not.toHaveBeenCalled();
});
});

Expand Down
8 changes: 4 additions & 4 deletions src/aria/private/menu/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export interface MenuBarInputs<V> extends ListInputs<MenuItemPattern<V>, V> {
items: SignalLike<MenuItemPattern<V>[]>;

/** Callback function triggered when a menu item is selected. */
onSelect?: (value: V) => void;
itemSelected?: (value: V) => void;

/** The text direction of the menu bar. */
textDirection: SignalLike<'ltr' | 'rtl'>;
Expand All @@ -34,7 +34,7 @@ export interface MenuInputs<V> extends Omit<ListInputs<MenuItemPattern<V>, V>, '
parent: SignalLike<MenuTriggerPattern<V> | MenuItemPattern<V> | undefined>;

/** Callback function triggered when a menu item is selected. */
onSelect?: (value: V) => void;
itemSelected?: (value: V) => void;

/** The text direction of the menu bar. */
textDirection: SignalLike<'ltr' | 'rtl'>;
Expand Down Expand Up @@ -370,12 +370,12 @@ export class MenuPattern<V> {

if (!item.submenu() && isMenuBar) {
root.close();
root?.inputs.onSelect?.(item.value());
root?.inputs.itemSelected?.(item.value());
}

if (!item.submenu() && isMenu) {
root.inputs.activeItem()?.close({refocus: true});
root?.inputs.onSelect?.(item.value());
root?.inputs.itemSelected?.(item.value());
}
}
}
Expand Down
Loading
Loading