UNPKG

bitmovin-player-ui

Version:
171 lines (149 loc) 4.39 kB
import { ComponentConfig, Component } from '../Component'; import { DOM } from '../../DOM'; import { EventDispatcher, NoArgs, Event } from '../../EventDispatcher'; import { LocalizableText, i18n } from '../../localization/i18n'; import { Icon } from '../Icon'; /** * Configures the style of a {@link Button} component. */ export enum ButtonStyle { /** * Only display the button as an icon. */ Icon = 'icon', /** * Only display the button as text. */ Text = 'text', /** * Display the button with an icon and text. * The Icon is displayed before the text. */ TextWithLeadingIcon = 'text-icon-leading', /** * Display the button with an icon and text. * The Icon is displayed after the text. */ TextWithTrailingIcon = 'text-icon-trailing', } /** * Configuration interface for a {@link Button} component. * * @category Configs */ export interface ButtonConfig extends ComponentConfig { /** * The text as string or localize callback on the button. */ text?: LocalizableText; /** * WCAG20 standard for defining info about the component (usually the name) */ ariaLabel?: LocalizableText; /** * Specifies whether the first touch event received by the {@link UIContainer} should be prevented or not. * * Default: false */ acceptsTouchWithUiHidden?: boolean; /** * The style of the button. * Default: {@link ButtonStyle.Icon} */ buttonStyle?: ButtonStyle; } /** * A simple clickable button. * * @category Components */ export class Button<Config extends ButtonConfig> extends Component<Config> { private static readonly CLASS_TOUCHED = 'touched'; private buttonEvents = { onClick: new EventDispatcher<Button<Config>, NoArgs>(), }; constructor(config: Config) { super(config); this.config = this.mergeConfig( config, { cssClass: 'ui-button', role: 'button', tabIndex: 0, acceptsTouchWithUiHidden: false, buttonStyle: ButtonStyle.Icon, } as Config, this.config, ); } protected toDomElement(): DOM { const buttonElementAttributes: { [name: string]: string } = { id: this.config.id, 'aria-label': i18n.performLocalization(this.config.ariaLabel || this.config.text), class: this.getCssClasses(), type: 'button', tabindex: this.config.tabIndex.toString(), }; if (this.config.role != null) { buttonElementAttributes['role'] = this.config.role; } // Create the button element with the text label const buttonElement = new DOM('button', buttonElementAttributes, this); const addIconElement = () => { const icon = new Icon(); buttonElement.append(icon.getDomElement()); }; const addLabelElement = () => { buttonElement.append( new DOM('span', { class: this.prefixCss('label') }).html(i18n.performLocalization(this.config.text)), ); }; switch (this.config.buttonStyle) { case ButtonStyle.Icon: addIconElement(); break; case ButtonStyle.Text: addLabelElement(); break; case ButtonStyle.TextWithLeadingIcon: addIconElement(); addLabelElement(); break; case ButtonStyle.TextWithTrailingIcon: addLabelElement(); addIconElement(); break; } // Listen for the click event on the button element and trigger the corresponding event on the button component buttonElement.on('click', e => { e.preventDefault(); this.onClickEvent(); }); buttonElement.on('touchstart', e => { this.getDomElement().addClass(Button.CLASS_TOUCHED); }); buttonElement.on('touchend', e => { this.getDomElement().removeClass(Button.CLASS_TOUCHED); }); return buttonElement; } /** * Sets text on the label of the button. * @param text the text to put into the label of the button */ setText(text: LocalizableText): void { this.getDomElement() .find('.' + this.prefixCss('label')) .html(i18n.performLocalization(text)); } protected onClickEvent() { this.buttonEvents.onClick.dispatch(this); } /** * Gets the event that is fired when the button is clicked. * @returns {Event<Button<Config>, NoArgs>} */ get onClick(): Event<Button<Config>, NoArgs> { return this.buttonEvents.onClick.getEvent(); } }