Server IP : 80.87.202.40 / Your IP : 216.73.216.169 Web Server : Apache System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64 User : bitrix ( 600) PHP Version : 8.2.27 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /home/bitrix/ext_www/rospirotorg.ru/bitrix/js/ui/promo-video-popup/src/ |
Upload File : |
import { Loc, Tag, Type } from 'main.core'; import { EventEmitter } from 'main.core.events'; import { Popup } from 'main.popup'; import { Icon, Main as MainIconSet, Set } from 'ui.icon-set.api.core'; import { Button, ButtonColor, ButtonSize } from 'ui.buttons'; import 'ui.icon-set.main'; import './promo-video-popup.css'; export const AnglePosition = Object.freeze({ TOP: 'top', LEFT: 'left', BOTTOM: 'bottom', RIGHT: 'right', }); export const PromoVideoPopupEvents = Object.freeze({ ACCEPT: 'accept', HIDE: 'hide', }); export type PromoVideoPopupOptions = { videoSrc: string; videoContainerMinHeight: number; width?: number; title?: string; text?: string; icon?: string; colors?: PromoVideoPopupOptionsColors; targetOptions: PromoVideoPopupTargetOptions; angleOptions?: PromoVideoPopupAngleOptions; offset?: PromoVideoPopupOffset; button?: PromoVideoPopupButtonOptions; useOverlay?: boolean; } export const PromoVideoPopupButtonPosition = Object.freeze({ LEFT: 'left', RIGHT: 'right', CENTER: 'center', }); export type PromoVideoPopupButtonOptions = { color?: ButtonColor; text?: string; size?: ButtonSize; position: PromoVideoPopupButtonPosition.LEFT | PromoVideoPopupButtonPosition.RIGHT | PromoVideoPopupButtonPosition.CENTER; } type PromoVideoPopupOffset = { top: number; left: number; } type PromoVideoPopupTargetOptions = HTMLElement | { top: number, left: number }; type PromoVideoPopupAngleOptions = { position: AnglePosition.TOP | AnglePosition.BOTTOM | AnglePosition.LEFT | AnglePosition.RIGHT; offset?: number; } type PromoVideoPopupOptionsColors = { iconBackground: string; title: string; /** * @deprecated Use button option from PromoVideoPopupOptions instead */ button: ButtonColor, } export class PromoVideoPopup extends EventEmitter { #videoSrc: string; #title: string; #width: number; #text: string; #icon: string; #colors: PromoVideoPopupOptionsColors; #targetOptions: ?PromoVideoPopupTargetOptions; #angleOptions: PromoVideoPopupAngleOptions; #offset: ?PromoVideoPopupOffset; #videoContainerMinHeight: number = 255; #buttonOptions: PromoVideoPopupButtonOptions = null; #useOverlay: boolean; #popup: ?Popup; constructor(options: PromoVideoPopupOptions) { super(options); this.setEventNamespace('UI.PromoVideoPopup'); this.#validateOptions(options); this.#videoSrc = options.videoSrc; this.#title = options.title; this.#width = options.width ?? PromoVideoPopup.getWidth(); this.#text = options.text; this.#icon = this.#isIconExist(options.icon) ? options.icon : MainIconSet.B_24; this.#colors = options.colors; this.#targetOptions = options.targetOptions ?? null; this.#angleOptions = options.angleOptions || false; this.#offset = options.offset; this.#videoContainerMinHeight = options.videoContainerMinHeight; this.#buttonOptions = options.button ?? null; this.#useOverlay = options.useOverlay === true; } /** * @deprecated */ static getWidth(): number { return 498; } show(): void { if (!this.#popup) { this.#iniPopup(); } if (this.#popup.isShown()) { return; } this.#popup.show(); } hide(): void { this.#popup?.close(); } isShown(): boolean { return Boolean(this.#popup?.isShown()); } adjustPosition(): void { this.#popup?.adjustPosition({ forceBindPosition: true, }); } getWidth(): number { return this.#width; } setTargetOptions(targetOptions: PromoVideoPopupTargetOptions): this { this.#targetOptions = targetOptions; if (this.#popup) { this.#popup.setBindElement(targetOptions); } return this; } #iniPopup(): void { const styles = getComputedStyle(document.body); const backgroundPrimary = styles.getPropertyValue('--ui-color-background-primary'); const backgroundPrimaryRgb = styles.getPropertyValue('--ui-color-background-primary-rgb'); this.#popup = new Popup({ bindElement: this.#targetOptions, cacheable: false, width: this.#width, borderRadius: '16px', angle: this.#angleOptions, content: this.#renderPopupContent(), closeByEsc: true, autoHide: true, closeIcon: true, background: `rgba(${backgroundPrimaryRgb}, 0.5)`, contentBackground: backgroundPrimary, contentPadding: 12, contentBorderRadius: '8px', overlay: this.#getPopupOverlay(), className: this.#getPopupClassname(), events: { onPopupClose: () => { setTimeout(() => { this.emit(PromoVideoPopupEvents.HIDE); this.#popup.destroy(); this.#popup = null; }, 300); }, }, animation: { showClassName: '--show', closeClassName: this.#getAnimationCloseClassName(), closeAnimationType: 'animation', }, }); this.#popup.setOffset({ offsetTop: this.#offset?.top, offsetLeft: this.#offset?.left, }); } #getPopupClassname(): string { let classNames = ['ui__promo-video-popup']; if (this.#angleOptions?.position === AnglePosition.RIGHT) { classNames = [...classNames, '--from-right']; } if (this.#angleOptions?.position === AnglePosition.TOP) { classNames = [...classNames, '--from-top']; } return classNames.join(' '); } #getAnimationCloseClassName(): string { switch (this.#angleOptions?.position) { case AnglePosition.RIGHT: { return '--close-left'; } case AnglePosition.TOP: { return '--close-bottom'; } default: { return '--close'; } } } #renderPopupContent(): HTMLElement { return Tag.render` <div class="ui__promo-video-popup-content" style="${this.#getPopupContentVariablesStyles()}" > <div class="ui__promo-video-popup-content_header"> <div class="ui__promo-video-popup-content_header-icon"> ${this.#renderIcon()} </div> <div class="ui__promo-video-popup-content_header-title"> ${this.#title} </div> </div> <div class="ui__promo-video-popup-content_promo-text"> ${this.#text} </div> <div class="ui__promo-video-popup-content_promo-video-wrapper" style="min-height: ${`${this.#videoContainerMinHeight}px`}" > ${this.#renderVideo()} </div> <div class="${this.#getPopupFooterElementClassname()}"> ${this.#renderAcceptButton()} </div> </div> `; } #renderVideo(): HTMLElement { const videoElement = Tag.render` <video src="${this.#videoSrc}" autoplay preload loop class="ui__promo-video-popup-content_promo-video" ></video> `; // eslint-disable-next-line @bitrix24/bitrix24-rules/no-native-events-binding videoElement.addEventListener('canplay', () => { videoElement.muted = true; videoElement.play(); }); return videoElement; } #renderAcceptButton(): HTMLElement { const buttonOptions = this.#getButtonOptions(); const btn = new Button({ color: buttonOptions.color, text: buttonOptions.text, size: buttonOptions.size, round: true, onclick: () => { this.emit(PromoVideoPopupEvents.ACCEPT); }, }); return btn.render(); } #renderIcon(): HTMLElement { const color = getComputedStyle(document.body).getPropertyValue('--ui-color-on-primary'); const icon = new Icon({ color, size: 18, icon: this.#icon, }); return icon.render(); } #getPopupContentVariablesStyles(): string { const cssVariables = {}; if (this.#getOptionsTitleColor()) { cssVariables['--ui__promo-video-popup_title-color'] = this.#getOptionsTitleColor(); } if (this.#getOptionsIconColor()) { cssVariables['--ui__promo-video-popup_icon-color'] = this.#getOptionsIconColor(); } return Object.entries(cssVariables).map(([variable, value]) => { return `${variable}: ${value}`; }).join(';'); } #getOptionsTitleColor(): string { return this.#colors?.title; } #getOptionsIconColor(): string { return this.#colors?.iconBackground; } #getOptionsButtonColor(): ?string { return this.#colors?.button; } // eslint-disable-next-line sonarjs/cognitive-complexity #validateOptions(options: PromoVideoPopupOptions): void { const title = options?.title; const text = options?.text; const video = options?.videoSrc; const iconColor = options?.colors?.iconBackground; const titleColor = options?.colors?.title; const buttonColor = options?.colors?.button; const targetOptions = options?.targetOptions; const offset = options?.offset; const videoContainerMinHeight = options?.videoContainerMinHeight; if (!options) { throw new TypeError('UI.PromoVideoPopup: options are required for constructor'); } if (!targetOptions) { throw new Error('UI.PromoVideoPopup: targetOptions is required option'); } if (title && Type.isString(title) === false) { throw new TypeError('UI.PromoVideoPopup: title option must be string'); } if (iconColor && Type.isStringFilled(iconColor) === false) { throw new TypeError('UI.PromoVideoPopup: colors.icon option must be string'); } if (titleColor && Type.isStringFilled(titleColor) === false) { throw new TypeError('UI.PromoVideoPopup: colors.title option must be string'); } if (buttonColor && Object.values(ButtonColor).includes(buttonColor) === false) { throw new TypeError('UI.PromoVideoPopup: colors.button option must be from ButtonColor from ui.buttons'); } if (text && Type.isString(text) === false) { throw new TypeError('UI.PromoVideoPopup: description option must be string'); } if (!video) { throw new Error('UI.PromoVideoPopup: videoSrc is required option'); } if (video && Type.isStringFilled(video) === false) { throw new Error('UI.PromoVideoPopup: videoSrc must be string'); } if (offset && Type.isPlainObject(offset) === false) { throw new Error('UI.PromoVideoPopup: offset options must be plain object with top and left properties'); } if (offset?.top && Type.isNumber(offset?.top) === false) { throw new TypeError('UI.PromoVideoPopup: offset.top option must be number'); } if (offset?.left && Type.isNumber(offset?.left) === false) { throw new TypeError('UI.PromoVideoPopup: offset.left option must be number'); } if (videoContainerMinHeight && Type.isNumber(videoContainerMinHeight) === false) { throw new TypeError('UI.PromoVideoPopup: videoContainerMinHeight option must be number'); } } #isIconExist(icon: string): boolean { return Object.values(Set).includes(icon); } #getButtonOptions(): PromoVideoPopupButtonOptions { const defaultOptions = this.#getDefaultButtonOptions(); return { text: this.#buttonOptions?.text ?? defaultOptions.text, color: this.#buttonOptions?.color ?? defaultOptions.color, size: this.#buttonOptions?.size ?? defaultOptions.size, position: this.#buttonOptions?.position ?? defaultOptions.position, }; } #getDefaultButtonOptions(): PromoVideoPopupButtonOptions { return { text: Loc.getMessage('PROMO_VIDEO_POPUP_ACCEPT'), size: ButtonSize.SMALL, color: this.#getOptionsButtonColor() || ButtonColor.PRIMARY, position: PromoVideoPopupButtonPosition.LEFT, }; } #getPopupOverlay(): { backgroundColor: string } | false { return this.#useOverlay ? { backgroundColor: 'rgba(0, 0, 0, 0.4)' } : false; } #getPopupFooterElementClassname(): string { let buttonAlignModifier = ''; if (this.#getButtonOptions().position === PromoVideoPopupButtonPosition.CENTER) { buttonAlignModifier = '--align-center'; } if (this.#getButtonOptions().position === PromoVideoPopupButtonPosition.RIGHT) { buttonAlignModifier = '--align-right'; } return `ui__promo-video-popup-content_footer ${buttonAlignModifier}`; } }