@angular/youtube-player
Version:
Angular YouTube Player
1 lines • 52.3 kB
Source Map (JSON)
{"version":3,"file":"youtube-player.mjs","sources":["../../../../../darwin_arm64-fastbuild-ST-fdfa778d11ba/bin/src/youtube-player/youtube-player-placeholder.ts","../../../../../darwin_arm64-fastbuild-ST-fdfa778d11ba/bin/src/youtube-player/youtube-player.ts","../../../../../darwin_arm64-fastbuild-ST-fdfa778d11ba/bin/src/youtube-player/youtube-module.ts"],"sourcesContent":["/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\nimport {ChangeDetectionStrategy, Component, Input, ViewEncapsulation} from '@angular/core';\n\n/** Quality of the placeholder image. */\nexport type PlaceholderImageQuality = 'high' | 'standard' | 'low';\n\n@Component({\n selector: 'youtube-player-placeholder',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n template: `\n <button type=\"button\" class=\"youtube-player-placeholder-button\" [attr.aria-label]=\"buttonLabel\">\n <svg\n height=\"100%\"\n version=\"1.1\"\n viewBox=\"0 0 68 48\"\n focusable=\"false\"\n aria-hidden=\"true\">\n <path d=\"M66.52,7.74c-0.78-2.93-2.49-5.41-5.42-6.19C55.79,.13,34,0,34,0S12.21,.13,6.9,1.55 C3.97,2.33,2.27,4.81,1.48,7.74C0.06,13.05,0,24,0,24s0.06,10.95,1.48,16.26c0.78,2.93,2.49,5.41,5.42,6.19 C12.21,47.87,34,48,34,48s21.79-0.13,27.1-1.55c2.93-0.78,4.64-3.26,5.42-6.19C67.94,34.95,68,24,68,24S67.94,13.05,66.52,7.74z\" fill=\"#f00\"></path>\n <path d=\"M 45,24 27,14 27,34\" fill=\"#fff\"></path>\n </svg>\n </button>\n `,\n styleUrl: 'youtube-player-placeholder.css',\n host: {\n 'class': 'youtube-player-placeholder',\n '[class.youtube-player-placeholder-loading]': 'isLoading',\n '[style.background-image]': '_getBackgroundImage()',\n '[style.width.px]': 'width',\n '[style.height.px]': 'height',\n },\n})\nexport class YouTubePlayerPlaceholder {\n /** ID of the video for which to show the placeholder. */\n @Input() videoId: string;\n\n /** Width of the video for which to show the placeholder. */\n @Input() width: number;\n\n /** Height of the video for which to show the placeholder. */\n @Input() height: number;\n\n /** Whether the video is currently being loaded. */\n @Input() isLoading: boolean;\n\n /** Accessible label for the play button. */\n @Input() buttonLabel: string;\n\n /** Quality of the placeholder image. */\n @Input() quality: PlaceholderImageQuality;\n\n /** Gets the background image showing the placeholder. */\n protected _getBackgroundImage(): string | undefined {\n let url: string;\n\n if (this.quality === 'low') {\n url = `https://i.ytimg.com/vi/${this.videoId}/hqdefault.jpg`;\n } else if (this.quality === 'high') {\n url = `https://i.ytimg.com/vi/${this.videoId}/maxresdefault.jpg`;\n } else {\n url = `https://i.ytimg.com/vi_webp/${this.videoId}/sddefault.webp`;\n }\n\n return `url(${url})`;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\n// Workaround for: https://github.com/bazelbuild/rules_nodejs/issues/1265\n/// <reference types=\"youtube\" preserve=\"true\" />\n\nimport {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n Input,\n NgZone,\n OnDestroy,\n Output,\n ViewChild,\n ViewEncapsulation,\n PLATFORM_ID,\n OnChanges,\n SimpleChanges,\n booleanAttribute,\n numberAttribute,\n InjectionToken,\n inject,\n CSP_NONCE,\n ChangeDetectorRef,\n AfterViewInit,\n EventEmitter,\n} from '@angular/core';\nimport {isPlatformBrowser} from '@angular/common';\nimport {trustedResourceUrl} from 'safevalues';\nimport {setScriptSrc} from 'safevalues/dom';\nimport {Observable, of as observableOf, Subject, BehaviorSubject, fromEventPattern} from 'rxjs';\nimport {takeUntil, switchMap} from 'rxjs/operators';\nimport {PlaceholderImageQuality, YouTubePlayerPlaceholder} from './youtube-player-placeholder';\n\ndeclare global {\n interface Window {\n YT: typeof YT | undefined;\n onYouTubeIframeAPIReady: (() => void) | undefined;\n }\n}\n\n/** Injection token used to configure the `YouTubePlayer`. */\nexport const YOUTUBE_PLAYER_CONFIG = new InjectionToken<YouTubePlayerConfig>(\n 'YOUTUBE_PLAYER_CONFIG',\n);\n\n/** Object that can be used to configure the `YouTubePlayer`. */\nexport interface YouTubePlayerConfig {\n /** Whether to load the YouTube iframe API automatically. Defaults to `true`. */\n loadApi?: boolean;\n\n /**\n * By default the player shows a placeholder image instead of loading the YouTube API which\n * improves the initial page load performance. Use this option to disable the placeholder loading\n * behavior globally. Defaults to `false`.\n */\n disablePlaceholder?: boolean;\n\n /** Accessible label for the play button inside of the placeholder. */\n placeholderButtonLabel?: string;\n\n /**\n * Quality of the displayed placeholder image. Defaults to `standard`,\n * because not all video have a high-quality placeholder.\n */\n placeholderImageQuality?: PlaceholderImageQuality;\n}\n\nexport const DEFAULT_PLAYER_WIDTH = 640;\nexport const DEFAULT_PLAYER_HEIGHT = 390;\n\n/**\n * Object used to store the state of the player if the\n * user tries to interact with the API before it has been loaded.\n */\ninterface PendingPlayerState {\n playbackState?: PlayerState.PLAYING | PlayerState.PAUSED | PlayerState.CUED;\n playbackRate?: number;\n volume?: number;\n muted?: boolean;\n seek?: {seconds: number; allowSeekAhead: boolean};\n}\n\n/** Coercion function for time values. */\nfunction coerceTime(value: number | undefined): number | undefined {\n return value == null ? value : numberAttribute(value, 0);\n}\n\n/**\n * Equivalent of `YT.PlayerState` which we can't use, because it's meant to\n * be read off the `window` which we can't do before the API has been loaded.\n */\nenum PlayerState {\n UNSTARTED = -1,\n ENDED = 0,\n PLAYING = 1,\n PAUSED = 2,\n BUFFERING = 3,\n CUED = 5,\n}\n\n/**\n * Angular component that renders a YouTube player via the YouTube player\n * iframe API.\n * @see https://developers.google.com/youtube/iframe_api_reference\n */\n@Component({\n selector: 'youtube-player',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [YouTubePlayerPlaceholder],\n styleUrl: 'youtube-player.css',\n template: `\n @if (_shouldShowPlaceholder()) {\n <youtube-player-placeholder\n [videoId]=\"videoId!\"\n [width]=\"width\"\n [height]=\"height\"\n [isLoading]=\"_isLoading\"\n [buttonLabel]=\"placeholderButtonLabel\"\n [quality]=\"placeholderImageQuality\"\n (click)=\"_load(true)\"/>\n }\n <div [style.display]=\"_shouldShowPlaceholder() ? 'none' : ''\">\n <div #youtubeContainer></div>\n </div>\n `,\n})\nexport class YouTubePlayer implements AfterViewInit, OnChanges, OnDestroy {\n private _ngZone = inject(NgZone);\n private readonly _nonce = inject(CSP_NONCE, {optional: true});\n private readonly _changeDetectorRef = inject(ChangeDetectorRef);\n private readonly _elementRef = inject<ElementRef<HTMLElement>>(ElementRef);\n private _player: YT.Player | undefined;\n private _pendingPlayer: YT.Player | undefined;\n private _existingApiReadyCallback: (() => void) | undefined;\n private _pendingPlayerState: PendingPlayerState | undefined;\n private readonly _destroyed = new Subject<void>();\n private readonly _playerChanges = new BehaviorSubject<YT.Player | undefined>(undefined);\n protected _isLoading = false;\n protected _hasPlaceholder = true;\n\n /** Whether we're currently rendering inside a browser. */\n private readonly _isBrowser: boolean;\n\n /** YouTube Video ID to view */\n @Input()\n videoId: string | undefined;\n\n /** Height of video player */\n @Input({transform: numberAttribute})\n get height(): number {\n return this._height;\n }\n set height(height: number | undefined) {\n this._height = height == null || isNaN(height) ? DEFAULT_PLAYER_HEIGHT : height;\n }\n private _height = DEFAULT_PLAYER_HEIGHT;\n\n /** Width of video player */\n @Input({transform: numberAttribute})\n get width(): number {\n return this._width;\n }\n set width(width: number | undefined) {\n this._width = width == null || isNaN(width) ? DEFAULT_PLAYER_WIDTH : width;\n }\n private _width = DEFAULT_PLAYER_WIDTH;\n\n /** The moment when the player is supposed to start playing */\n @Input({transform: coerceTime})\n startSeconds: number | undefined;\n\n /** The moment when the player is supposed to stop playing */\n @Input({transform: coerceTime})\n endSeconds: number | undefined;\n\n /** The suggested quality of the player */\n @Input()\n suggestedQuality: YT.SuggestedVideoQuality | undefined;\n\n /**\n * Extra parameters used to configure the player. See:\n * https://developers.google.com/youtube/player_parameters.html?playerVersion=HTML5#Parameters\n */\n @Input()\n playerVars: YT.PlayerVars | undefined;\n\n /** Whether cookies inside the player have been disabled. */\n @Input({transform: booleanAttribute})\n disableCookies: boolean = false;\n\n /** Whether to automatically load the YouTube iframe API. Defaults to `true`. */\n @Input({transform: booleanAttribute})\n loadApi: boolean;\n\n /**\n * By default the player shows a placeholder image instead of loading the YouTube API which\n * improves the initial page load performance. This input allows for the behavior to be disabled.\n */\n @Input({transform: booleanAttribute})\n disablePlaceholder: boolean = false;\n\n /**\n * Whether the iframe will attempt to load regardless of the status of the api on the\n * page. Set this to true if you don't want the `onYouTubeIframeAPIReady` field to be\n * set on the global window.\n */\n @Input({transform: booleanAttribute}) showBeforeIframeApiLoads: boolean = false;\n\n /** Accessible label for the play button inside of the placeholder. */\n @Input() placeholderButtonLabel: string;\n\n /**\n * Quality of the displayed placeholder image. Defaults to `standard`,\n * because not all video have a high-quality placeholder.\n */\n @Input() placeholderImageQuality: PlaceholderImageQuality;\n\n // Note: ready event can't go through the lazy emitter, because it\n // happens before the `_playerChanges` stream emits the new player.\n\n /** Emits when the player is initialized. */\n @Output() readonly ready: Observable<YT.PlayerEvent> = new EventEmitter<YT.PlayerEvent>();\n\n /** Emits when the state of the player has changed. */\n @Output() readonly stateChange: Observable<YT.OnStateChangeEvent> =\n this._getLazyEmitter<YT.OnStateChangeEvent>('onStateChange');\n\n /** Emits when there's an error while initializing the player. */\n @Output() readonly error: Observable<YT.OnErrorEvent> =\n this._getLazyEmitter<YT.OnErrorEvent>('onError');\n\n /** Emits when the underlying API of the player has changed. */\n @Output() readonly apiChange: Observable<YT.PlayerEvent> =\n this._getLazyEmitter<YT.PlayerEvent>('onApiChange');\n\n /** Emits when the playback quality has changed. */\n @Output() readonly playbackQualityChange: Observable<YT.OnPlaybackQualityChangeEvent> =\n this._getLazyEmitter<YT.OnPlaybackQualityChangeEvent>('onPlaybackQualityChange');\n\n /** Emits when the playback rate has changed. */\n @Output() readonly playbackRateChange: Observable<YT.OnPlaybackRateChangeEvent> =\n this._getLazyEmitter<YT.OnPlaybackRateChangeEvent>('onPlaybackRateChange');\n\n /** The element that will be replaced by the iframe. */\n @ViewChild('youtubeContainer', {static: true})\n youtubeContainer: ElementRef<HTMLElement>;\n\n constructor(...args: unknown[]);\n\n constructor() {\n const platformId = inject<Object>(PLATFORM_ID);\n const config = inject(YOUTUBE_PLAYER_CONFIG, {optional: true});\n this.loadApi = config?.loadApi ?? true;\n this.disablePlaceholder = !!config?.disablePlaceholder;\n this.placeholderButtonLabel = config?.placeholderButtonLabel || 'Play video';\n this.placeholderImageQuality = config?.placeholderImageQuality || 'standard';\n this._isBrowser = isPlatformBrowser(platformId);\n }\n\n ngAfterViewInit() {\n this._conditionallyLoad();\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (this._shouldRecreatePlayer(changes)) {\n this._conditionallyLoad();\n } else if (this._player) {\n if (changes['width'] || changes['height']) {\n this._setSize();\n }\n\n if (changes['suggestedQuality']) {\n this._setQuality();\n }\n\n if (changes['startSeconds'] || changes['endSeconds'] || changes['suggestedQuality']) {\n this._cuePlayer();\n }\n }\n }\n\n ngOnDestroy() {\n this._pendingPlayer?.destroy();\n\n if (this._player) {\n this._player.destroy();\n window.onYouTubeIframeAPIReady = this._existingApiReadyCallback;\n }\n\n this._playerChanges.complete();\n this._destroyed.next();\n this._destroyed.complete();\n }\n\n /** See https://developers.google.com/youtube/iframe_api_reference#playVideo */\n playVideo() {\n if (this._player) {\n this._player.playVideo();\n } else {\n this._getPendingState().playbackState = PlayerState.PLAYING;\n this._load(true);\n }\n }\n\n /** See https://developers.google.com/youtube/iframe_api_reference#pauseVideo */\n pauseVideo() {\n if (this._player) {\n this._player.pauseVideo();\n } else {\n this._getPendingState().playbackState = PlayerState.PAUSED;\n }\n }\n\n /** See https://developers.google.com/youtube/iframe_api_reference#stopVideo */\n stopVideo() {\n if (this._player) {\n this._player.stopVideo();\n } else {\n // It seems like YouTube sets the player to CUED when it's stopped.\n this._getPendingState().playbackState = PlayerState.CUED;\n }\n }\n\n /** See https://developers.google.com/youtube/iframe_api_reference#seekTo */\n seekTo(seconds: number, allowSeekAhead: boolean) {\n if (this._player) {\n this._player.seekTo(seconds, allowSeekAhead);\n } else {\n this._getPendingState().seek = {seconds, allowSeekAhead};\n }\n }\n\n /** See https://developers.google.com/youtube/iframe_api_reference#mute */\n mute() {\n if (this._player) {\n this._player.mute();\n } else {\n this._getPendingState().muted = true;\n }\n }\n\n /** See https://developers.google.com/youtube/iframe_api_reference#unMute */\n unMute() {\n if (this._player) {\n this._player.unMute();\n } else {\n this._getPendingState().muted = false;\n }\n }\n\n /** See https://developers.google.com/youtube/iframe_api_reference#isMuted */\n isMuted(): boolean {\n if (this._player) {\n return this._player.isMuted();\n }\n\n if (this._pendingPlayerState) {\n return !!this._pendingPlayerState.muted;\n }\n\n return false;\n }\n\n /** See https://developers.google.com/youtube/iframe_api_reference#setVolume */\n setVolume(volume: number) {\n if (this._player) {\n this._player.setVolume(volume);\n } else {\n this._getPendingState().volume = volume;\n }\n }\n\n /** See https://developers.google.com/youtube/iframe_api_reference#getVolume */\n getVolume(): number {\n if (this._player) {\n return this._player.getVolume();\n }\n\n if (this._pendingPlayerState && this._pendingPlayerState.volume != null) {\n return this._pendingPlayerState.volume;\n }\n\n return 0;\n }\n\n /** See https://developers.google.com/youtube/iframe_api_reference#setPlaybackRate */\n setPlaybackRate(playbackRate: number) {\n if (this._player) {\n return this._player.setPlaybackRate(playbackRate);\n } else {\n this._getPendingState().playbackRate = playbackRate;\n }\n }\n\n /** See https://developers.google.com/youtube/iframe_api_reference#getPlaybackRate */\n getPlaybackRate(): number {\n if (this._player) {\n return this._player.getPlaybackRate();\n }\n\n if (this._pendingPlayerState && this._pendingPlayerState.playbackRate != null) {\n return this._pendingPlayerState.playbackRate;\n }\n\n return 0;\n }\n\n /** See https://developers.google.com/youtube/iframe_api_reference#getAvailablePlaybackRates */\n getAvailablePlaybackRates(): number[] {\n return this._player ? this._player.getAvailablePlaybackRates() : [];\n }\n\n /** See https://developers.google.com/youtube/iframe_api_reference#getVideoLoadedFraction */\n getVideoLoadedFraction(): number {\n return this._player ? this._player.getVideoLoadedFraction() : 0;\n }\n\n /** See https://developers.google.com/youtube/iframe_api_reference#getPlayerState */\n getPlayerState(): YT.PlayerState | undefined {\n if (!this._isBrowser || !window.YT) {\n return undefined;\n }\n\n if (this._player) {\n return this._player.getPlayerState();\n }\n\n if (this._pendingPlayerState && this._pendingPlayerState.playbackState != null) {\n return this._pendingPlayerState.playbackState;\n }\n\n return PlayerState.UNSTARTED;\n }\n\n /** See https://developers.google.com/youtube/iframe_api_reference#getCurrentTime */\n getCurrentTime(): number {\n if (this._player) {\n return this._player.getCurrentTime();\n }\n\n if (this._pendingPlayerState && this._pendingPlayerState.seek) {\n return this._pendingPlayerState.seek.seconds;\n }\n\n return 0;\n }\n\n /** See https://developers.google.com/youtube/iframe_api_reference#getPlaybackQuality */\n getPlaybackQuality(): YT.SuggestedVideoQuality {\n return this._player ? this._player.getPlaybackQuality() : 'default';\n }\n\n /** See https://developers.google.com/youtube/iframe_api_reference#getAvailableQualityLevels */\n getAvailableQualityLevels(): YT.SuggestedVideoQuality[] {\n return this._player ? this._player.getAvailableQualityLevels() : [];\n }\n\n /** See https://developers.google.com/youtube/iframe_api_reference#getDuration */\n getDuration(): number {\n return this._player ? this._player.getDuration() : 0;\n }\n\n /** See https://developers.google.com/youtube/iframe_api_reference#getVideoUrl */\n getVideoUrl(): string {\n return this._player ? this._player.getVideoUrl() : '';\n }\n\n /** See https://developers.google.com/youtube/iframe_api_reference#getVideoEmbedCode */\n getVideoEmbedCode(): string {\n return this._player ? this._player.getVideoEmbedCode() : '';\n }\n\n /**\n * Attempts to put the player into fullscreen mode, depending on browser support.\n * @param options Options controlling how the element behaves in fullscreen mode.\n */\n async requestFullscreen(options?: FullscreenOptions): Promise<void> {\n // Note that we do this on the host, rather than the iframe, because it allows us to handle the\n // placeholder in fullscreen mode. Null check the method since it's not supported everywhere.\n const element = this._elementRef.nativeElement;\n return element.requestFullscreen\n ? element.requestFullscreen(options)\n : Promise.reject(new Error('Fullscreen API not supported by browser.'));\n }\n\n /**\n * Loads the YouTube API and sets up the player.\n * @param playVideo Whether to automatically play the video once the player is loaded.\n */\n protected _load(playVideo: boolean) {\n // Don't do anything if we're not in a browser environment.\n if (!this._isBrowser) {\n return;\n }\n\n if (!window.YT || !window.YT.Player) {\n if (this.loadApi) {\n this._isLoading = true;\n loadApi(this._nonce);\n } else if (this.showBeforeIframeApiLoads && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throw new Error(\n 'Namespace YT not found, cannot construct embedded youtube player. ' +\n 'Please install the YouTube Player API Reference for iframe Embeds: ' +\n 'https://developers.google.com/youtube/iframe_api_reference',\n );\n }\n\n this._existingApiReadyCallback = window.onYouTubeIframeAPIReady;\n\n window.onYouTubeIframeAPIReady = () => {\n this._existingApiReadyCallback?.();\n this._ngZone.run(() => this._createPlayer(playVideo));\n };\n } else {\n this._createPlayer(playVideo);\n }\n }\n\n /** Loads the player depending on the internal state of the component. */\n private _conditionallyLoad() {\n // If the placeholder isn't shown anymore, we have to trigger a load.\n if (!this._shouldShowPlaceholder()) {\n this._load(false);\n } else if (this.playerVars?.autoplay === 1) {\n // If it's an autoplaying video, we have to hide the placeholder and start playing.\n this._load(true);\n }\n }\n\n /** Whether to show the placeholder element. */\n protected _shouldShowPlaceholder(): boolean {\n if (this.disablePlaceholder) {\n return false;\n }\n\n // Since we don't load the API on the server, we show the placeholder permanently.\n if (!this._isBrowser) {\n return true;\n }\n\n return this._hasPlaceholder && !!this.videoId && !this._player;\n }\n\n /** Gets an object that should be used to store the temporary API state. */\n private _getPendingState(): PendingPlayerState {\n if (!this._pendingPlayerState) {\n this._pendingPlayerState = {};\n }\n\n return this._pendingPlayerState;\n }\n\n /**\n * Determines whether a change in the component state\n * requires the YouTube player to be recreated.\n */\n private _shouldRecreatePlayer(changes: SimpleChanges): boolean {\n const change =\n changes['videoId'] ||\n changes['playerVars'] ||\n changes['disableCookies'] ||\n changes['disablePlaceholder'];\n return !!change && !change.isFirstChange();\n }\n\n /**\n * Creates a new YouTube player and destroys the existing one.\n * @param playVideo Whether to play the video once it loads.\n */\n private _createPlayer(playVideo: boolean) {\n this._player?.destroy();\n this._pendingPlayer?.destroy();\n\n // A player can't be created if the API isn't loaded,\n // or there isn't a video or playlist to be played.\n if (typeof YT === 'undefined' || (!this.videoId && !this.playerVars?.list)) {\n return;\n }\n\n // Important! We need to create the Player object outside of the `NgZone`, because it kicks\n // off a 250ms setInterval which will continually trigger change detection if we don't.\n const params: YT.PlayerOptions = {\n host: this.disableCookies ? 'https://www.youtube-nocookie.com' : undefined,\n width: this.width,\n height: this.height,\n // Calling `playVideo` on load doesn't appear to actually play\n // the video so we need to trigger it through `playerVars` instead.\n playerVars: playVideo ? {...(this.playerVars || {}), autoplay: 1} : this.playerVars,\n };\n // We only want to injecct a videoId if one is provided, otherwise loading a playlist via\n // playerVars.list, the missing videoId will create a null value in the youtube iframe url\n // and that can trigger a JS error `Invalid video id` in widget api.\n if (this.videoId) {\n params.videoId = this.videoId;\n }\n const player = this._ngZone.runOutsideAngular(\n () => new YT.Player(this.youtubeContainer.nativeElement, params),\n );\n\n const whenReady = (event: YT.PlayerEvent) => {\n // Only assign the player once it's ready, otherwise YouTube doesn't expose some APIs.\n this._ngZone.run(() => {\n this._isLoading = false;\n this._hasPlaceholder = false;\n this._player = player;\n this._pendingPlayer = undefined;\n player.removeEventListener('onReady', whenReady);\n this._playerChanges.next(player);\n (this.ready as EventEmitter<YT.PlayerEvent>).emit(event);\n this._setSize();\n this._setQuality();\n\n if (this._pendingPlayerState) {\n this._applyPendingPlayerState(player, this._pendingPlayerState);\n this._pendingPlayerState = undefined;\n }\n\n // Only cue the player when it either hasn't started yet or it's cued,\n // otherwise cuing it can interrupt a player with autoplay enabled.\n const state = player.getPlayerState();\n if (state === PlayerState.UNSTARTED || state === PlayerState.CUED || state == null) {\n this._cuePlayer();\n } else if (\n (playVideo || this.playerVars?.autoplay === 1) &&\n this.startSeconds &&\n this.startSeconds > 0\n ) {\n // We have to use `seekTo` when `startSeconds` are specified with a playing video\n // (either from user interaction or autoplay). The \"proper\" way to do it would be to\n // either go through `cueVideoById` or `playerVars.start`, but at the time of writing\n // both end up resetting the video to the state as if the user hasn't interacted with it.\n player.seekTo(this.startSeconds, true);\n }\n\n this._changeDetectorRef.markForCheck();\n });\n };\n\n this._pendingPlayer = player;\n player.addEventListener('onReady', whenReady);\n }\n\n /** Applies any state that changed before the player was initialized. */\n private _applyPendingPlayerState(player: YT.Player, pendingState: PendingPlayerState): void {\n const {playbackState, playbackRate, volume, muted, seek} = pendingState;\n\n switch (playbackState) {\n case PlayerState.PLAYING:\n player.playVideo();\n break;\n case PlayerState.PAUSED:\n player.pauseVideo();\n break;\n case PlayerState.CUED:\n player.stopVideo();\n break;\n }\n\n if (playbackRate != null) {\n player.setPlaybackRate(playbackRate);\n }\n\n if (volume != null) {\n player.setVolume(volume);\n }\n\n if (muted != null) {\n muted ? player.mute() : player.unMute();\n }\n\n if (seek != null) {\n player.seekTo(seek.seconds, seek.allowSeekAhead);\n }\n }\n\n /** Cues the player based on the current component state. */\n private _cuePlayer() {\n if (this._player && this.videoId) {\n this._player.cueVideoById({\n videoId: this.videoId,\n startSeconds: this.startSeconds,\n endSeconds: this.endSeconds,\n suggestedQuality: this.suggestedQuality,\n });\n }\n }\n\n /** Sets the player's size based on the current input values. */\n private _setSize() {\n this._player?.setSize(this.width, this.height);\n }\n\n /** Sets the player's quality based on the current input values. */\n private _setQuality() {\n if (this._player && this.suggestedQuality) {\n this._player.setPlaybackQuality(this.suggestedQuality);\n }\n }\n\n /** Gets an observable that adds an event listener to the player when a user subscribes to it. */\n private _getLazyEmitter<T extends YT.PlayerEvent>(name: keyof YT.Events): Observable<T> {\n // Start with the stream of players. This way the events will be transferred\n // over to the new player if it gets swapped out under-the-hood.\n return this._playerChanges.pipe(\n // Switch to the bound event. `switchMap` ensures that the old event is removed when the\n // player is changed. If there's no player, return an observable that never emits.\n switchMap(player => {\n return player\n ? fromEventPattern<T>(\n listener => {\n player.addEventListener(name, listener);\n },\n listener => {\n // The API seems to throw when we try to unbind from a destroyed player and it\n // doesn'texpose whether the player has been destroyed so we have to wrap it in a\n // try/catch to prevent the entire stream from erroring out.\n try {\n player?.removeEventListener?.(name, listener);\n } catch {}\n },\n )\n : observableOf<T>();\n }),\n // By default we run all the API interactions outside the zone\n // so we have to bring the events back in manually when they emit.\n source =>\n new Observable<T>(observer =>\n source.subscribe({\n next: value => this._ngZone.run(() => observer.next(value)),\n error: error => observer.error(error),\n complete: () => observer.complete(),\n }),\n ),\n // Ensures that everything is cleared out on destroy.\n takeUntil(this._destroyed),\n );\n }\n}\n\nlet apiLoaded = false;\n\n/** Loads the YouTube API from a specified URL only once. */\nfunction loadApi(nonce: string | null): void {\n if (apiLoaded) {\n return;\n }\n\n // We can use `document` directly here, because this logic doesn't run outside the browser.\n const url = trustedResourceUrl`https://www.youtube.com/iframe_api`;\n const script = document.createElement('script');\n const callback = (event: Event) => {\n script.removeEventListener('load', callback);\n script.removeEventListener('error', callback);\n\n if (event.type === 'error') {\n apiLoaded = false;\n\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n console.error(`Failed to load YouTube API from ${url}`);\n }\n }\n };\n script.addEventListener('load', callback);\n script.addEventListener('error', callback);\n setScriptSrc(script, url);\n script.async = true;\n\n if (nonce) {\n script.setAttribute('nonce', nonce);\n }\n\n // Set this immediately to true so we don't start loading another script\n // while this one is pending. If loading fails, we'll flip it back to false.\n apiLoaded = true;\n document.body.appendChild(script);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\nimport {NgModule} from '@angular/core';\nimport {YouTubePlayer} from './youtube-player';\n\n@NgModule({\n imports: [YouTubePlayer],\n exports: [YouTubePlayer],\n})\nexport class YouTubePlayerModule {}\n"],"names":["YouTubePlayerPlaceholder","videoId","width","height","isLoading","buttonLabel","quality","_getBackgroundImage","url","deps","target","i0","ɵɵFactoryTarget","Component","ɵcmp","ɵɵngDeclareComponent","minVersion","version","type","isStandalone","selector","inputs","host","properties","classAttribute","ngImport","template","isInline","styles","changeDetection","ChangeDetectionStrategy","OnPush","encapsulation","ViewEncapsulation","None","decorators","Input","YOUTUBE_PLAYER_CONFIG","InjectionToken","DEFAULT_PLAYER_WIDTH","DEFAULT_PLAYER_HEIGHT","coerceTime","value","numberAttribute","PlayerState","YouTubePlayer","_ngZone","inject","NgZone","_nonce","CSP_NONCE","optional","_changeDetectorRef","ChangeDetectorRef","_elementRef","ElementRef","_player","_pendingPlayer","_existingApiReadyCallback","_pendingPlayerState","_destroyed","Subject","_playerChanges","BehaviorSubject","undefined","_isLoading","_hasPlaceholder","_isBrowser","_height","isNaN","_width","startSeconds","endSeconds","suggestedQuality","playerVars","disableCookies","loadApi","disablePlaceholder","showBeforeIframeApiLoads","placeholderButtonLabel","placeholderImageQuality","ready","EventEmitter","stateChange","_getLazyEmitter","error","apiChange","playbackQualityChange","playbackRateChange","youtubeContainer","constructor","platformId","PLATFORM_ID","config","isPlatformBrowser","ngAfterViewInit","_conditionallyLoad","ngOnChanges","changes","_shouldRecreatePlayer","_setSize","_setQuality","_cuePlayer","ngOnDestroy","destroy","window","onYouTubeIframeAPIReady","complete","next","playVideo","_getPendingState","playbackState","PLAYING","_load","pauseVideo","PAUSED","stopVideo","CUED","seekTo","seconds","allowSeekAhead","seek","mute","muted","unMute","isMuted","setVolume","volume","getVolume","setPlaybackRate","playbackRate","getPlaybackRate","getAvailablePlaybackRates","getVideoLoadedFraction","getPlayerState","YT","UNSTARTED","getCurrentTime","getPlaybackQuality","getAvailableQualityLevels","getDuration","getVideoUrl","getVideoEmbedCode","requestFullscreen","options","element","nativeElement","Promise","reject","Error","Player","ngDevMode","run","_createPlayer","_shouldShowPlaceholder","autoplay","change","isFirstChange","list","params","player","runOutsideAngular","whenReady","event","removeEventListener","emit","_applyPendingPlayerState","state","markForCheck","addEventListener","pendingState","cueVideoById","setSize","setPlaybackQuality","name","pipe","switchMap","fromEventPattern","listener","observableOf","source","Observable","observer","subscribe","takeUntil","booleanAttribute","outputs","viewQueries","propertyName","first","predicate","descendants","static","usesOnChanges","dependencies","kind","args","imports","transform","Output","ViewChild","apiLoaded","nonce","trustedResourceUrl","script","document","createElement","callback","console","setScriptSrc","async","setAttribute","body","appendChild","YouTubePlayerModule","NgModule","exports"],"mappings":"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