Skip to content

Commit

Permalink
feat: allow adding custom data to menu bar item types
Browse files Browse the repository at this point in the history
  • Loading branch information
sissbruecker committed Feb 19, 2025
1 parent b98f1e9 commit 87c2b95
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 24 deletions.
28 changes: 18 additions & 10 deletions packages/menu-bar/src/vaadin-menu-bar-mixin.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type { KeyboardMixinClass } from '@vaadin/a11y-base/src/keyboard-mixin.js
import type { ControllerMixinClass } from '@vaadin/component-base/src/controller-mixin.js';
import type { ResizeMixinClass } from '@vaadin/component-base/src/resize-mixin.js';

export interface MenuBarItem {
export type MenuBarItem<TItemData extends object = object> = {
/**
* Text to be set as the menu button component's textContent.
*/
Expand All @@ -37,40 +37,40 @@ export interface MenuBarItem {
/**
* Array of submenu items.
*/
children?: SubMenuItem[];
children?: Array<SubMenuItem<TItemData>>;

/**
* Class/classes to be set to the class attribute of the button.
*/
className?: string;
}
} & TItemData;

export interface SubMenuItem {
export type SubMenuItem<TItemData extends object = object> = {
text?: string;
component?: HTMLElement | string;
disabled?: boolean;
theme?: string[] | string;
checked?: boolean;
className?: string;
children?: SubMenuItem[];
}
children?: Array<SubMenuItem<TItemData>>;
} & TItemData;

export interface MenuBarI18n {
moreOptions: string;
}

export declare function MenuBarMixin<T extends Constructor<HTMLElement>>(
export declare function MenuBarMixin<T extends Constructor<HTMLElement>, TItem extends MenuBarItem = MenuBarItem>(
base: T,
): Constructor<ControllerMixinClass> &
Constructor<DisabledMixinClass> &
Constructor<FocusMixinClass> &
Constructor<KeyboardDirectionMixinClass> &
Constructor<KeyboardMixinClass> &
Constructor<MenuBarMixinClass> &
Constructor<MenuBarMixinClass<TItem>> &
Constructor<ResizeMixinClass> &
T;

export declare class MenuBarMixinClass {
export declare class MenuBarMixinClass<TItem extends MenuBarItem = MenuBarItem> {
/**
* Defines a hierarchical structure, where root level items represent menu bar buttons,
* and `children` property configures a submenu with items to be opened below
Expand Down Expand Up @@ -118,7 +118,7 @@ export declare class MenuBarMixinClass {
* window.Vaadin.featureFlags.accessibleDisabledButtons = true;
* ```
*/
items: MenuBarItem[];
items: TItem[];

/**
* The object used to localize this component.
Expand Down Expand Up @@ -183,3 +183,11 @@ export declare class MenuBarMixinClass {

protected _hasOverflow: boolean;
}

export declare interface MenuBarMixinClass
extends ControllerMixinClass,
DisabledMixinClass,
FocusMixinClass,
KeyboardDirectionMixinClass,
KeyboardMixinClass,
ResizeMixinClass {}
34 changes: 21 additions & 13 deletions packages/menu-bar/src/vaadin-menu-bar.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,25 @@
* Copyright (c) 2019 - 2025 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
import { DisabledMixin } from '@vaadin/a11y-base/src/disabled-mixin.js';
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
import { type MenuBarItem, MenuBarMixin } from './vaadin-menu-bar-mixin.js';
import type { DisabledMixinClass } from '@vaadin/a11y-base/src/disabled-mixin.js';
import type { ElementMixinClass } from '@vaadin/component-base/src/element-mixin.js';
import type { ThemableMixinClass } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
import type { MenuBarItem, MenuBarMixinClass } from './vaadin-menu-bar-mixin.js';

export { MenuBarItem, MenuBarI18n, SubMenuItem } from './vaadin-menu-bar-mixin.js';

/**
* Fired when a submenu item or menu bar button without children is clicked.
*/
export type MenuBarItemSelectedEvent = CustomEvent<{ value: MenuBarItem }>;
export type MenuBarItemSelectedEvent<TItem extends MenuBarItem = MenuBarItem> = CustomEvent<{ value: TItem }>;

export interface MenuBarCustomEventMap {
'item-selected': MenuBarItemSelectedEvent;
export interface MenuBarCustomEventMap<TItem extends MenuBarItem = MenuBarItem> {
'item-selected': MenuBarItemSelectedEvent<TItem>;
}

export interface MenuBarEventMap extends HTMLElementEventMap, MenuBarCustomEventMap {}
export interface MenuBarEventMap<TItem extends MenuBarItem = MenuBarItem>
extends HTMLElementEventMap,
MenuBarCustomEventMap<TItem> {}

/**
* `<vaadin-menu-bar>` is a Web Component providing a set of horizontally stacked buttons offering
Expand Down Expand Up @@ -77,20 +79,26 @@ export interface MenuBarEventMap extends HTMLElementEventMap, MenuBarCustomEvent
*
* @fires {CustomEvent} item-selected - Fired when a submenu item or menu bar button without children is clicked.
*/
declare class MenuBar extends MenuBarMixin(DisabledMixin(ElementMixin(ThemableMixin(HTMLElement)))) {
addEventListener<K extends keyof MenuBarEventMap>(
declare class MenuBar<TItem extends MenuBarItem = MenuBarItem> extends HTMLElement {
addEventListener<K extends keyof MenuBarEventMap<TItem>>(
type: K,
listener: (this: MenuBar, ev: MenuBarEventMap[K]) => void,
listener: (this: MenuBar, ev: MenuBarEventMap<TItem>[K]) => void,
options?: AddEventListenerOptions | boolean,
): void;

removeEventListener<K extends keyof MenuBarEventMap>(
removeEventListener<K extends keyof MenuBarEventMap<TItem>>(
type: K,
listener: (this: MenuBar, ev: MenuBarEventMap[K]) => void,
listener: (this: MenuBar, ev: MenuBarEventMap<TItem>[K]) => void,
options?: EventListenerOptions | boolean,
): void;
}

interface MenuBar<TItem extends MenuBarItem = MenuBarItem>
extends MenuBarMixinClass<TItem>,
DisabledMixinClass,
ElementMixinClass,
ThemableMixinClass {}

declare global {
interface HTMLElementTagNameMap {
'vaadin-menu-bar': MenuBar;
Expand Down
18 changes: 17 additions & 1 deletion packages/menu-bar/test/typings/menu-bar.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type { ThemableMixinClass } from '@vaadin/vaadin-themable-mixin/vaadin-th
import type { MenuBarItem } from '../../src/vaadin-menu-bar-item.js';
import type { MenuBarListBox } from '../../src/vaadin-menu-bar-list-box.js';
import type { MenuBarMixinClass } from '../../src/vaadin-menu-bar-mixin.js';
import type { MenuBarItem as MenuItem, MenuBarItemSelectedEvent } from '../../vaadin-menu-bar.js';
import type { MenuBar, MenuBarItem as MenuItem, MenuBarItemSelectedEvent } from '../../vaadin-menu-bar.js';

const menu = document.createElement('vaadin-menu-bar');

Expand Down Expand Up @@ -39,6 +39,22 @@ assertType<string[] | string | undefined>(menuItem.theme);
assertType<MenuItem[] | undefined>(menuItem.children);
assertType<HTMLElement | string | undefined>(menuItem.component);

// Custom item data
interface ItemData {
type: 'copy' | 'cut' | 'paste';
value: string;
}

const narrowedMenu = menu as MenuBar<MenuItem<ItemData>>;

assertType<ItemData>(narrowedMenu.items[0]);
assertType<ItemData>(narrowedMenu.items[0].children![0]);
assertType<ItemData>(narrowedMenu.items[0].children![0].children![0]);

narrowedMenu.addEventListener('item-selected', (event) => {
assertType<ItemData>(event.detail.value);
});

// Item
const item = document.createElement('vaadin-menu-bar-item');

Expand Down

0 comments on commit 87c2b95

Please # to comment.