@twick/player-react 0.15.7 → 0.15.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -136,7 +136,6 @@ var init_internal = __esm({
136
136
  this.abortController?.abort();
137
137
  this.abortController = new AbortController();
138
138
  this.project = project;
139
- console.log(project);
140
139
  this.defaultSettings = (0, import_core.getFullPreviewSettings)(this.project);
141
140
  const player = new import_core.Player(this.project);
142
141
  player.setVariables(this.variables);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/internal.ts","../src/index.tsx","../src/controls.tsx","../src/icons.tsx","../src/utils.ts"],"sourcesContent":["import type {Project} from '@twick/core';\nimport {Player, Stage, getFullPreviewSettings} from '@twick/core';\n\nimport {Vector2} from '@twick/core';\n\nconst stylesNew = `\n.overlay {\n\tposition: absolute;\n\tleft: 0;\n\tright: 0;\n\ttop: 0;\n\tbottom: 0;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\topacity: 0;\n\ttransition: opacity 0.1s;\n\tz-index: 0;\n }\n .canvas {\n\twidth: 100%;\n\tdisplay: block;\n\topacity: 1;\n\ttransition: opacity 0.1s;\n }\n`;\n\nconst TEMPLATE = `<style>${stylesNew}</style><div class=\"overlay\"></div>`;\nconst ID = 'twick-player';\n\nenum State {\n Initial = 'initial',\n Loading = 'loading',\n Ready = 'ready',\n Error = 'error',\n}\n\nclass TwickPlayer extends HTMLElement {\n public static get observedAttributes() {\n return [\n 'playing',\n 'variables',\n 'looping',\n 'fps',\n 'quality',\n 'width',\n 'height',\n 'volume',\n ];\n }\n\n private get fps() {\n const attr = this.getAttribute('fps');\n return attr ? parseFloat(attr) : (this.defaultSettings?.fps ?? 60);\n }\n\n private get quality() {\n const attr = this.getAttribute('quality');\n return attr\n ? parseFloat(attr)\n : (this.defaultSettings?.resolutionScale ?? 1);\n }\n\n private get width() {\n const attr = this.getAttribute('width');\n return attr ? parseFloat(attr) : (this.defaultSettings?.size.width ?? 0);\n }\n\n private get height() {\n const attr = this.getAttribute('height');\n return attr ? parseFloat(attr) : (this.defaultSettings?.size.height ?? 0);\n }\n\n private get variables() {\n try {\n const attr = this.getAttribute('variables');\n return attr ? JSON.parse(attr) : {};\n } catch {\n this.project?.logger.warn(`Project variables could not be parsed.`);\n return {};\n }\n }\n\n private readonly root: ShadowRoot;\n private readonly canvas: HTMLCanvasElement;\n private readonly overlay: HTMLCanvasElement;\n\n private state = State.Initial;\n private project: Project | null = null;\n private player: Player | null = null;\n private defaultSettings:\n | ReturnType<typeof getFullPreviewSettings>\n | undefined;\n private abortController: AbortController | null = null;\n private playing = false;\n private stage = new Stage();\n\n private time: number = 0;\n private duration: number = 0; // in frames\n private looping = true;\n private volume = 1;\n private volumeChangeRequested = true;\n\n public constructor() {\n super();\n this.root = this.attachShadow({mode: 'open'});\n this.root.innerHTML = TEMPLATE;\n\n this.overlay = this.root.querySelector('.overlay')!;\n this.canvas = this.stage.finalBuffer;\n this.canvas.classList.add('canvas');\n this.root.prepend(this.canvas);\n this.setState(State.Initial);\n }\n\n public setProject(project: Project) {\n this.updateProject(project);\n }\n\n private setState(state: State) {\n this.state = state;\n this.setPlaying(this.playing);\n }\n\n private setPlaying(value: boolean) {\n if (this.state === State.Ready && value) {\n this.player?.togglePlayback(true);\n this.playing = true;\n } else {\n this.player?.togglePlayback(false);\n this.playing = false;\n }\n }\n\n private async updateProject(project: Project) {\n const playing = this.playing;\n this.setState(State.Initial);\n\n this.abortController?.abort();\n this.abortController = new AbortController();\n\n this.project = project;\n console.log(project);\n this.defaultSettings = getFullPreviewSettings(this.project);\n\n const player = new Player(this.project);\n player.setVariables(this.variables);\n player.toggleLoop(this.looping);\n\n this.player?.onRender.unsubscribe(this.render);\n this.player?.onFrameChanged.unsubscribe(this.handleFrameChanged);\n this.player?.togglePlayback(false);\n this.player?.deactivate();\n\n this.player = player;\n this.updateSettings();\n\n this.setState(State.Ready);\n this.dispatchEvent(new CustomEvent('playerready', {detail: this.player}));\n\n // Restore previous state\n this.setPlaying(playing);\n this.player.onRender.subscribe(this.render);\n this.player.onFrameChanged.subscribe(this.handleFrameChanged);\n }\n\n public attributeChangedCallback(name: string, _: any, newValue: any) {\n switch (name) {\n case 'playing':\n this.setPlaying(newValue === 'true');\n break;\n case 'variables':\n this.player?.setVariables(this.variables);\n this.player?.requestSeek(this.player.playback.frame);\n this.player?.playback.reload();\n break;\n case 'looping':\n this.looping = newValue === 'true';\n this.player?.toggleLoop(newValue === 'true');\n break;\n case 'fps':\n case 'quality':\n case 'width':\n case 'height':\n this.updateSettings();\n break;\n case 'volume':\n this.volume = newValue;\n this.volumeChangeRequested = true;\n }\n }\n\n /**\n * Runs when the element is removed from the DOM.\n */\n public disconnectedCallback() {\n this.player?.deactivate();\n this.player?.onRender.unsubscribe(this.render);\n\n this.removeEventListener('seekto', this.handleSeekTo);\n this.removeEventListener('volumechange', this.handleVolumeChange);\n }\n\n /**\n * Runs when the element is added to the DOM.\n */\n public connectedCallback() {\n this.player?.activate();\n this.player?.onRender.subscribe(this.render);\n\n this.addEventListener('seekto', this.handleSeekTo);\n this.addEventListener('volumechange', this.handleVolumeChange);\n }\n\n /**\n * Triggered by the timeline.\n */\n private handleSeekTo = (event: Event) => {\n if (!this.project) {\n return;\n }\n\n const e = event as CustomEvent;\n this.time = e.detail;\n this.player?.requestSeek(e.detail * this.player.playback.fps);\n this.volumeChangeRequested = true;\n };\n\n private handleVolumeChange = (event: Event) => {\n if (!this.project) {\n return;\n }\n\n const e = event as CustomEvent;\n this.volume = e.detail;\n\n this.player?.playback.currentScene.adjustVolume(this.volume);\n };\n\n /**\n * Triggered by the player.\n */\n private handleFrameChanged = (frame: number) => {\n if (!this.project || !this.player) {\n return;\n }\n this.time = frame / this.player.playback.fps;\n\n if (this.volumeChangeRequested || frame === 0) {\n this.player?.playback.currentScene.adjustVolume(this.volume);\n this.volumeChangeRequested = false;\n }\n };\n\n /**\n * Called on every frame.\n */\n private render = async () => {\n if (this.player && this.project) {\n await this.stage.render(\n this.player.playback.currentScene,\n this.player.playback.previousScene,\n );\n\n this.dispatchEvent(new CustomEvent('timeupdate', {detail: this.time}));\n\n const durationInFrames = this.player.playback.duration;\n if (durationInFrames === this.duration) {\n return;\n }\n\n this.duration = durationInFrames;\n\n const durationInSeconds = durationInFrames / this.player.playback.fps;\n this.dispatchEvent(\n new CustomEvent('duration', {detail: durationInSeconds}),\n );\n }\n };\n\n private updateSettings() {\n if (!this.defaultSettings) {\n return;\n }\n\n const settings = {\n ...this.defaultSettings,\n size: new Vector2(this.width, this.height),\n resolutionScale: this.quality,\n fps: this.fps,\n };\n this.stage.configure(settings);\n this.player?.configure(settings);\n }\n}\n\nif (!customElements.get(ID)) {\n customElements.define(ID, TwickPlayer);\n}\n","'use client';\nimport type {Player as CorePlayer, Project} from '@twick/core';\nimport type {ComponentProps} from 'react';\nimport {useCallback, useEffect, useRef, useState} from 'react';\nimport {Controls} from './controls';\nimport './index.css';\nimport {shouldShowControls} from './utils';\n\ninterface TwickPlayerProps {\n playing?: string;\n variables?: string;\n looping?: string;\n width?: number;\n height?: number;\n quality?: number;\n fps?: number;\n volume?: number;\n}\n\ndeclare global {\n namespace JSX {\n interface IntrinsicElements {\n // eslint-disable-next-line\n 'twick-player': TwickPlayerProps & ComponentProps<'div'>;\n }\n }\n}\n\ninterface PlayerProps {\n project: Project;\n controls?: boolean;\n variables?: Record<string, any>;\n playing?: boolean;\n currentTime?: number;\n volume?: number;\n looping?: boolean;\n fps?: number;\n\n width?: number;\n height?: number;\n quality?: number;\n timeDisplayFormat?: 'MM:SS' | 'MM:SS.mm' | 'MM:SS.m';\n\n onDurationChange?: (duration: number) => void;\n onTimeUpdate?: (currentTime: number) => void;\n onPlayerReady?: (player: CorePlayer) => void;\n onPlayerResize?: (rect: DOMRectReadOnly) => void;\n}\n\nexport function Player({\n project,\n controls = true,\n variables = {},\n playing = false,\n currentTime = 0,\n volume = 1,\n looping = true,\n fps = 30,\n\n width = undefined,\n height = undefined,\n quality = undefined,\n timeDisplayFormat = 'MM:SS',\n\n onDurationChange = () => {},\n onTimeUpdate = () => {},\n onPlayerReady = () => {},\n onPlayerResize = () => {},\n}: PlayerProps) {\n const [playingState, setPlaying] = useState(playing);\n const [isMouseOver, setIsMouseOver] = useState(false);\n const [currentTimeState, setCurrentTime] = useState(currentTime);\n const [volumeState, setVolumeState] = useState(volume);\n const [duration, setDuration] = useState(-1);\n\n const focus = useRef(false);\n const playerRef = useRef<HTMLDivElement | null>(null);\n const wrapperRef = useRef<HTMLDivElement | null>(null);\n const lastRect = useRef<DOMRectReadOnly | null>(null);\n\n const onClickHandler = controls ? () => setPlaying(prev => !prev) : undefined;\n\n /**\n * Sync the playing prop with the player's own state when it changes.\n */\n useEffect(() => {\n setPlaying(playing);\n }, [playing]);\n\n /**\n * Sync the current time with the player's own state.\n */\n useEffect(() => {\n const diff = Math.abs(currentTime - currentTimeState);\n if (diff > 0.05) {\n setForcedTime(currentTime);\n }\n }, [currentTime]);\n\n useEffect(() => {\n setForcedVolume(volume);\n }, [volume]);\n\n /**\n * Receives the current time of the video from the player.\n * Use refs to ensure we always call the latest callbacks.\n */\n const onTimeUpdateRef = useRef(onTimeUpdate);\n const onDurationChangeRef = useRef(onDurationChange);\n \n // Update refs when callbacks change\n useEffect(() => {\n onTimeUpdateRef.current = onTimeUpdate;\n }, [onTimeUpdate]);\n \n useEffect(() => {\n onDurationChangeRef.current = onDurationChange;\n }, [onDurationChange]);\n\n const handleTimeUpdate = useCallback((event: Event) => {\n const e = event as CustomEvent;\n setCurrentTime(e.detail);\n onTimeUpdateRef.current(e.detail);\n }, []);\n\n /**\n * Receives the duration of the video from the player.\n */\n const handleDurationUpdate = useCallback((event: Event) => {\n const e = event as CustomEvent;\n setDuration(e.detail);\n onDurationChangeRef.current(e.detail);\n }, []);\n\n /**\n * Play and pause using the space key.\n */\n const handleKeyDown = useCallback((event: KeyboardEvent) => {\n if (event.code === 'Space' && focus.current) {\n event.preventDefault();\n setPlaying(prev => !prev);\n }\n }, []);\n\n const onPlayerReadyRef = useRef(onPlayerReady);\n \n useEffect(() => {\n onPlayerReadyRef.current = onPlayerReady;\n }, [onPlayerReady]);\n\n const handlePlayerReady = useCallback((event: Event) => {\n const player = (event as CustomEvent).detail;\n if (player) {\n onPlayerReadyRef.current(player);\n }\n \n // Ensure event listeners are attached when player becomes ready\n // This is a fallback in case listeners weren't attached earlier\n const playerElement = playerRef.current;\n if (playerElement) {\n // Remove and re-add to ensure they're attached\n playerElement.removeEventListener('timeupdate', handleTimeUpdate);\n playerElement.removeEventListener('duration', handleDurationUpdate);\n playerElement.addEventListener('timeupdate', handleTimeUpdate);\n playerElement.addEventListener('duration', handleDurationUpdate);\n }\n }, [handleTimeUpdate, handleDurationUpdate]);\n\n const handlePlayerResize = useCallback(\n (entries: ResizeObserverEntry[]) => {\n const [firstEntry] = entries;\n if (!firstEntry || !wrapperRef.current) {\n return;\n }\n\n const newRect = wrapperRef.current.getBoundingClientRect();\n if (\n !lastRect.current ||\n newRect.width !== lastRect.current.width ||\n newRect.height !== lastRect.current.height ||\n newRect.x !== lastRect.current.x ||\n newRect.y !== lastRect.current.y\n ) {\n lastRect.current = newRect;\n onPlayerResize(newRect);\n }\n },\n [onPlayerResize],\n );\n\n useEffect(() => {\n if (!wrapperRef.current) return;\n\n const resizeObserver = new ResizeObserver(handlePlayerResize);\n resizeObserver.observe(wrapperRef.current);\n\n return () => {\n resizeObserver.disconnect();\n };\n }, [handlePlayerResize]);\n\n /**\n * Import the player and add all event listeners.\n */\n useEffect(() => {\n let cleanup: (() => void) | null = null;\n\n const setupListeners = () => {\n const player = playerRef.current;\n if (!player) return;\n\n // Remove any existing listeners first to avoid duplicates\n player.removeEventListener('timeupdate', handleTimeUpdate);\n player.removeEventListener('duration', handleDurationUpdate);\n player.removeEventListener('playerready', handlePlayerReady);\n\n // Add event listeners\n player.addEventListener('timeupdate', handleTimeUpdate);\n player.addEventListener('duration', handleDurationUpdate);\n player.addEventListener('playerready', handlePlayerReady);\n document.addEventListener('keydown', handleKeyDown);\n\n cleanup = () => {\n player.removeEventListener('timeupdate', handleTimeUpdate);\n player.removeEventListener('duration', handleDurationUpdate);\n player.removeEventListener('playerready', handlePlayerReady);\n document.removeEventListener('keydown', handleKeyDown);\n };\n };\n\n // Import the custom element definition\n import('./internal').then(() => {\n // Wait for the next tick to ensure the element is in the DOM\n // Use requestAnimationFrame to ensure the custom element is ready\n requestAnimationFrame(() => {\n if (playerRef.current) {\n (playerRef.current as any).setProject(project);\n // Set up listeners after the element is ready\n setupListeners();\n }\n });\n });\n\n // Also set up listeners immediately if element already exists\n // This handles the case where the element was already in the DOM\n if (playerRef.current) {\n setupListeners();\n }\n\n return () => {\n if (cleanup) {\n cleanup();\n }\n };\n }, [project, handleTimeUpdate, handleDurationUpdate, handlePlayerReady, handleKeyDown]);\n\n /**\n * When the forced time changes, seek to that time.\n */\n function setForcedTime(forcedTime: number) {\n if (playerRef.current) {\n playerRef.current.dispatchEvent(\n new CustomEvent('seekto', {detail: forcedTime}),\n );\n }\n }\n\n function setForcedVolume(volume: number) {\n setVolumeState(volume);\n if (playerRef.current) {\n playerRef.current.dispatchEvent(\n new CustomEvent('volumechange', {detail: volume}),\n );\n }\n }\n\n return (\n <div className=\"twick-player-root\" style={{display: 'contents'}}>\n <div\n ref={wrapperRef}\n className=\"relative cursor-default focus:outline-none\"\n onFocus={() => (focus.current = true)}\n onBlur={() => (focus.current = false)}\n tabIndex={0}\n onMouseEnter={() => setIsMouseOver(true)}\n onMouseLeave={() => setIsMouseOver(false)}\n >\n <div className=\"relative\">\n <twick-player\n ref={playerRef}\n playing={String(playingState)}\n onClick={onClickHandler}\n variables={JSON.stringify(variables)}\n looping={looping ? 'true' : 'false'}\n width={width}\n height={height}\n quality={quality}\n fps={fps}\n volume={volumeState}\n />\n <div\n className={`absolute bottom-0 w-full transition-opacity duration-200 ${\n shouldShowControls(playingState, isMouseOver, !controls)\n ? 'opacity-100'\n : 'opacity-0'\n }`}\n >\n <Controls\n duration={duration}\n playing={playingState}\n setPlaying={setPlaying}\n currentTime={currentTimeState}\n setForcedTime={setForcedTime}\n timeDisplayFormat={timeDisplayFormat}\n volume={volumeState}\n setVolume={setForcedVolume}\n />\n </div>\n </div>\n </div>\n </div>\n );\n}\n","import {useState} from 'react';\nimport {MutedSoundIcon, PauseButton, PlayButton, SoundIcon} from './icons';\nimport {getFormattedTime} from './utils';\n\nfunction PlayPause({\n playing,\n setPlaying,\n}: {\n playing: boolean;\n setPlaying: (playing: boolean) => void;\n}) {\n return (\n <button type=\"button\" className=\"p-1\" onClick={() => setPlaying(!playing)}>\n {playing ? <PauseButton /> : <PlayButton />}\n </button>\n );\n}\n\nfunction VolumeSlider({\n volume,\n setVolume,\n}: {\n volume: number;\n setVolume: (volume: number) => void;\n}) {\n const [isHovering, setIsHovering] = useState(false);\n const [isInteracting, setIsInteracting] = useState(false);\n const [previousVolume, setPreviousVolume] = useState(1);\n\n const handleIconClick = () => {\n if (volume > 0) {\n setPreviousVolume(volume);\n setVolume(0);\n } else {\n setVolume(previousVolume);\n }\n };\n\n return (\n <div\n className=\"flex items-center space-x-2 relative\"\n onMouseEnter={() => setIsHovering(true)}\n onMouseLeave={() => {\n if (!isInteracting) {\n setIsHovering(false);\n }\n }}\n >\n <div\n className=\"w-6 h-6 flex items-center justify-center cursor-pointer\"\n onClick={handleIconClick}\n >\n {volume === 0 ? <MutedSoundIcon /> : <SoundIcon />}\n </div>\n {(isHovering || isInteracting) && (\n <div className=\"flex items-center h-1.5 whitespace-nowrap\">\n <div className=\"relative w-20 h-1.5 bg-gray-300 rounded-full\">\n <div\n className=\"absolute top-0 left-0 h-full bg-gray-100 rounded-full\"\n style={{width: `${volume * 100}%`}}\n />\n <input\n type=\"range\"\n min={0}\n max={1}\n step={0.01}\n value={volume}\n onChange={e => {\n const newVolume = Number(e.target.value);\n setVolume(newVolume);\n if (newVolume > 0) {\n setPreviousVolume(newVolume);\n }\n }}\n onMouseDown={() => setIsInteracting(true)}\n onMouseUp={() => setIsInteracting(false)}\n onMouseLeave={() => setIsInteracting(false)}\n className=\"absolute top-0 left-0 w-full h-full opacity-0 cursor-pointer\"\n />\n </div>\n </div>\n )}\n </div>\n );\n}\n\nfunction Timeline({\n currentTime,\n duration,\n setCurrentTime,\n}: {\n currentTime: number;\n duration: number;\n setCurrentTime: (currentTime: number) => void;\n}) {\n const progressPercentage = (currentTime / duration) * 100;\n\n return (\n <div className=\"relative flex-1 w-full h-1.5 bg-gray-300 rounded-full overflow-hidden\">\n <div\n className=\"absolute top-0 left-0 h-full bg-gray-100\"\n style={{width: `${progressPercentage}%`}}\n />\n <input\n type=\"range\"\n value={currentTime}\n min={0}\n max={duration}\n step={0.01}\n className=\"absolute top-0 left-0 w-full h-full opacity-0 cursor-pointer\"\n onChange={event => setCurrentTime(Number(event.target.value))}\n />\n </div>\n );\n}\n\nexport function Controls({\n duration,\n playing,\n setPlaying,\n currentTime,\n setForcedTime,\n timeDisplayFormat,\n volume,\n setVolume,\n}: {\n duration: number;\n playing: boolean;\n setPlaying: (playing: boolean) => void;\n currentTime: number;\n setForcedTime: (currentTime: number) => void;\n timeDisplayFormat: 'MM:SS' | 'MM:SS.m' | 'MM:SS.mm';\n volume: number;\n setVolume: (volume: number) => void;\n}) {\n return (\n <div className=\"text-white p-4 flex-col space-y-2 bg-gradient-to-t from-gray-500 to-transparent\">\n <div className=\"flex items-center space-x-2\">\n <PlayPause playing={playing} setPlaying={setPlaying} />\n <div className=\"flex items-center space-x-2\">\n <VolumeSlider volume={volume} setVolume={setVolume} />\n <div>\n <span>\n {getFormattedTime(currentTime, duration, timeDisplayFormat)}\n </span>\n </div>\n </div>\n <div className=\"flex-grow\" />\n </div>\n <Timeline\n currentTime={currentTime}\n duration={duration}\n setCurrentTime={setForcedTime}\n />\n </div>\n );\n}\n","export function PlayButton() {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n className=\"w-6 h-6\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.5 5.653c0-1.427 1.529-2.33 2.779-1.643l11.54 6.347c1.295.712 1.295 2.573 0 3.286L7.28 19.99c-1.25.687-2.779-.217-2.779-1.643V5.653Z\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function PauseButton() {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n className=\"w-6 h-6\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M6.75 5.25a.75.75 0 0 1 .75-.75H9a.75.75 0 0 1 .75.75v13.5a.75.75 0 0 1-.75.75H7.5a.75.75 0 0 1-.75-.75V5.25Zm7.5 0A.75.75 0 0 1 15 4.5h1.5a.75.75 0 0 1 .75.75v13.5a.75.75 0 0 1-.75.75H15a.75.75 0 0 1-.75-.75V5.25Z\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function SoundIcon() {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n className=\"p-w-6 p-h-6\"\n >\n <path d=\"M18.36,19.36a1,1,0,0,1-.7-.29,1,1,0,0,1,0-1.41,8,8,0,0,0,0-11.32,1,1,0,0,1,1.41-1.41,10,10,0,0,1,0,14.14A1,1,0,0,1,18.36,19.36Z\" />\n <path d=\"M15.54,16.54a1,1,0,0,1-.71-.3,1,1,0,0,1,0-1.41,4,4,0,0,0,0-5.66,1,1,0,0,1,1.41-1.41,6,6,0,0,1,0,8.48A1,1,0,0,1,15.54,16.54Z\" />\n <path d=\"M11.38,4.08a1,1,0,0,0-1.09.21L6.59,8H4a2,2,0,0,0-2,2v4a2,2,0,0,0,2,2H6.59l3.7,3.71A1,1,0,0,0,11,20a.84.84,0,0,0,.38-.08A1,1,0,0,0,12,19V5A1,1,0,0,0,11.38,4.08Z\" />\n </svg>\n );\n}\n\nexport function MutedSoundIcon() {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n className=\"p-w-6 p-h-6\"\n >\n <path d=\"M11.38,4.08a1,1,0,0,0-1.09.21L6.59,8H4a2,2,0,0,0-2,2v4a2,2,0,0,0,2,2H6.59l3.7,3.71A1,1,0,0,0,11,20a.84.84,0,0,0,.38-.08A1,1,0,0,0,12,19V5A1,1,0,0,0,11.38,4.08Z\" />\n <path d=\"M16,15.5a1,1,0,0,1-.71-.29,1,1,0,0,1,0-1.42l5-5a1,1,0,0,1,1.42,1.42l-5,5A1,1,0,0,1,16,15.5Z\" />\n <path d=\"M21,15.5a1,1,0,0,1-.71-.29l-5-5a1,1,0,0,1,1.42-1.42l5,5a1,1,0,0,1,0,1.42A1,1,0,0,1,21,15.5Z\" />\n </svg>\n );\n}\n","export function getFormattedTime(\n timeInSeconds: number,\n absoluteTimeInSeconds: number,\n timeDisplayFormat: 'MM:SS' | 'MM:SS.mm' | 'MM:SS.m',\n) {\n function toFormattedTime(timeInSeconds: number) {\n const minutes = Math.floor(timeInSeconds / 60);\n const seconds = Math.floor(timeInSeconds % 60)\n .toString()\n .padStart(2, '0');\n const milliseconds = Math.floor((timeInSeconds % 1) * 1000)\n .toString()\n .padStart(3, '0');\n\n if (timeDisplayFormat === 'MM:SS') {\n return `${minutes}:${seconds}`;\n }\n\n if (timeDisplayFormat === 'MM:SS.m') {\n return `${minutes}:${seconds}.${milliseconds[0]}`;\n }\n\n if (timeDisplayFormat === 'MM:SS.mm') {\n return `${minutes}:${seconds}.${milliseconds.slice(0, 2)}`;\n }\n }\n\n return `${toFormattedTime(timeInSeconds)} / ${toFormattedTime(absoluteTimeInSeconds)}`;\n}\n\nexport function shouldShowControls(\n playing: boolean,\n isMouseOver: boolean,\n areControlsDisabled: boolean,\n) {\n if (areControlsDisabled) {\n return false;\n }\n\n return !playing || isMouseOver;\n}\n"],"mappings":"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","names":["import_core","Player","import_react","timeInSeconds","import_jsx_runtime","import_jsx_runtime","Player","volume"]}
1
+ {"version":3,"sources":["../src/internal.ts","../src/index.tsx","../src/controls.tsx","../src/icons.tsx","../src/utils.ts"],"sourcesContent":["import type {Project} from '@twick/core';\nimport {Player, Stage, getFullPreviewSettings} from '@twick/core';\n\nimport {Vector2} from '@twick/core';\n\nconst stylesNew = `\n.overlay {\n\tposition: absolute;\n\tleft: 0;\n\tright: 0;\n\ttop: 0;\n\tbottom: 0;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\topacity: 0;\n\ttransition: opacity 0.1s;\n\tz-index: 0;\n }\n .canvas {\n\twidth: 100%;\n\tdisplay: block;\n\topacity: 1;\n\ttransition: opacity 0.1s;\n }\n`;\n\nconst TEMPLATE = `<style>${stylesNew}</style><div class=\"overlay\"></div>`;\nconst ID = 'twick-player';\n\nenum State {\n Initial = 'initial',\n Loading = 'loading',\n Ready = 'ready',\n Error = 'error',\n}\n\nclass TwickPlayer extends HTMLElement {\n public static get observedAttributes() {\n return [\n 'playing',\n 'variables',\n 'looping',\n 'fps',\n 'quality',\n 'width',\n 'height',\n 'volume',\n ];\n }\n\n private get fps() {\n const attr = this.getAttribute('fps');\n return attr ? parseFloat(attr) : (this.defaultSettings?.fps ?? 60);\n }\n\n private get quality() {\n const attr = this.getAttribute('quality');\n return attr\n ? parseFloat(attr)\n : (this.defaultSettings?.resolutionScale ?? 1);\n }\n\n private get width() {\n const attr = this.getAttribute('width');\n return attr ? parseFloat(attr) : (this.defaultSettings?.size.width ?? 0);\n }\n\n private get height() {\n const attr = this.getAttribute('height');\n return attr ? parseFloat(attr) : (this.defaultSettings?.size.height ?? 0);\n }\n\n private get variables() {\n try {\n const attr = this.getAttribute('variables');\n return attr ? JSON.parse(attr) : {};\n } catch {\n this.project?.logger.warn(`Project variables could not be parsed.`);\n return {};\n }\n }\n\n private readonly root: ShadowRoot;\n private readonly canvas: HTMLCanvasElement;\n private readonly overlay: HTMLCanvasElement;\n\n private state = State.Initial;\n private project: Project | null = null;\n private player: Player | null = null;\n private defaultSettings:\n | ReturnType<typeof getFullPreviewSettings>\n | undefined;\n private abortController: AbortController | null = null;\n private playing = false;\n private stage = new Stage();\n\n private time: number = 0;\n private duration: number = 0; // in frames\n private looping = true;\n private volume = 1;\n private volumeChangeRequested = true;\n\n public constructor() {\n super();\n this.root = this.attachShadow({mode: 'open'});\n this.root.innerHTML = TEMPLATE;\n\n this.overlay = this.root.querySelector('.overlay')!;\n this.canvas = this.stage.finalBuffer;\n this.canvas.classList.add('canvas');\n this.root.prepend(this.canvas);\n this.setState(State.Initial);\n }\n\n public setProject(project: Project) {\n this.updateProject(project);\n }\n\n private setState(state: State) {\n this.state = state;\n this.setPlaying(this.playing);\n }\n\n private setPlaying(value: boolean) {\n if (this.state === State.Ready && value) {\n this.player?.togglePlayback(true);\n this.playing = true;\n } else {\n this.player?.togglePlayback(false);\n this.playing = false;\n }\n }\n\n private async updateProject(project: Project) {\n const playing = this.playing;\n this.setState(State.Initial);\n\n this.abortController?.abort();\n this.abortController = new AbortController();\n\n this.project = project;\n this.defaultSettings = getFullPreviewSettings(this.project);\n\n const player = new Player(this.project);\n player.setVariables(this.variables);\n player.toggleLoop(this.looping);\n\n this.player?.onRender.unsubscribe(this.render);\n this.player?.onFrameChanged.unsubscribe(this.handleFrameChanged);\n this.player?.togglePlayback(false);\n this.player?.deactivate();\n\n this.player = player;\n this.updateSettings();\n\n this.setState(State.Ready);\n this.dispatchEvent(new CustomEvent('playerready', {detail: this.player}));\n\n // Restore previous state\n this.setPlaying(playing);\n this.player.onRender.subscribe(this.render);\n this.player.onFrameChanged.subscribe(this.handleFrameChanged);\n }\n\n public attributeChangedCallback(name: string, _: any, newValue: any) {\n switch (name) {\n case 'playing':\n this.setPlaying(newValue === 'true');\n break;\n case 'variables':\n this.player?.setVariables(this.variables);\n this.player?.requestSeek(this.player.playback.frame);\n this.player?.playback.reload();\n break;\n case 'looping':\n this.looping = newValue === 'true';\n this.player?.toggleLoop(newValue === 'true');\n break;\n case 'fps':\n case 'quality':\n case 'width':\n case 'height':\n this.updateSettings();\n break;\n case 'volume':\n this.volume = newValue;\n this.volumeChangeRequested = true;\n }\n }\n\n /**\n * Runs when the element is removed from the DOM.\n */\n public disconnectedCallback() {\n this.player?.deactivate();\n this.player?.onRender.unsubscribe(this.render);\n\n this.removeEventListener('seekto', this.handleSeekTo);\n this.removeEventListener('volumechange', this.handleVolumeChange);\n }\n\n /**\n * Runs when the element is added to the DOM.\n */\n public connectedCallback() {\n this.player?.activate();\n this.player?.onRender.subscribe(this.render);\n\n this.addEventListener('seekto', this.handleSeekTo);\n this.addEventListener('volumechange', this.handleVolumeChange);\n }\n\n /**\n * Triggered by the timeline.\n */\n private handleSeekTo = (event: Event) => {\n if (!this.project) {\n return;\n }\n\n const e = event as CustomEvent;\n this.time = e.detail;\n this.player?.requestSeek(e.detail * this.player.playback.fps);\n this.volumeChangeRequested = true;\n };\n\n private handleVolumeChange = (event: Event) => {\n if (!this.project) {\n return;\n }\n\n const e = event as CustomEvent;\n this.volume = e.detail;\n\n this.player?.playback.currentScene.adjustVolume(this.volume);\n };\n\n /**\n * Triggered by the player.\n */\n private handleFrameChanged = (frame: number) => {\n if (!this.project || !this.player) {\n return;\n }\n this.time = frame / this.player.playback.fps;\n\n if (this.volumeChangeRequested || frame === 0) {\n this.player?.playback.currentScene.adjustVolume(this.volume);\n this.volumeChangeRequested = false;\n }\n };\n\n /**\n * Called on every frame.\n */\n private render = async () => {\n if (this.player && this.project) {\n await this.stage.render(\n this.player.playback.currentScene,\n this.player.playback.previousScene,\n );\n\n this.dispatchEvent(new CustomEvent('timeupdate', {detail: this.time}));\n\n const durationInFrames = this.player.playback.duration;\n if (durationInFrames === this.duration) {\n return;\n }\n\n this.duration = durationInFrames;\n\n const durationInSeconds = durationInFrames / this.player.playback.fps;\n this.dispatchEvent(\n new CustomEvent('duration', {detail: durationInSeconds}),\n );\n }\n };\n\n private updateSettings() {\n if (!this.defaultSettings) {\n return;\n }\n\n const settings = {\n ...this.defaultSettings,\n size: new Vector2(this.width, this.height),\n resolutionScale: this.quality,\n fps: this.fps,\n };\n this.stage.configure(settings);\n this.player?.configure(settings);\n }\n}\n\nif (!customElements.get(ID)) {\n customElements.define(ID, TwickPlayer);\n}\n","'use client';\nimport type {Player as CorePlayer, Project} from '@twick/core';\nimport type {ComponentProps} from 'react';\nimport {useCallback, useEffect, useRef, useState} from 'react';\nimport {Controls} from './controls';\nimport './index.css';\nimport {shouldShowControls} from './utils';\n\ninterface TwickPlayerProps {\n playing?: string;\n variables?: string;\n looping?: string;\n width?: number;\n height?: number;\n quality?: number;\n fps?: number;\n volume?: number;\n}\n\ndeclare global {\n namespace JSX {\n interface IntrinsicElements {\n // eslint-disable-next-line\n 'twick-player': TwickPlayerProps & ComponentProps<'div'>;\n }\n }\n}\n\ninterface PlayerProps {\n project: Project;\n controls?: boolean;\n variables?: Record<string, any>;\n playing?: boolean;\n currentTime?: number;\n volume?: number;\n looping?: boolean;\n fps?: number;\n\n width?: number;\n height?: number;\n quality?: number;\n timeDisplayFormat?: 'MM:SS' | 'MM:SS.mm' | 'MM:SS.m';\n\n onDurationChange?: (duration: number) => void;\n onTimeUpdate?: (currentTime: number) => void;\n onPlayerReady?: (player: CorePlayer) => void;\n onPlayerResize?: (rect: DOMRectReadOnly) => void;\n}\n\nexport function Player({\n project,\n controls = true,\n variables = {},\n playing = false,\n currentTime = 0,\n volume = 1,\n looping = true,\n fps = 30,\n\n width = undefined,\n height = undefined,\n quality = undefined,\n timeDisplayFormat = 'MM:SS',\n\n onDurationChange = () => {},\n onTimeUpdate = () => {},\n onPlayerReady = () => {},\n onPlayerResize = () => {},\n}: PlayerProps) {\n const [playingState, setPlaying] = useState(playing);\n const [isMouseOver, setIsMouseOver] = useState(false);\n const [currentTimeState, setCurrentTime] = useState(currentTime);\n const [volumeState, setVolumeState] = useState(volume);\n const [duration, setDuration] = useState(-1);\n\n const focus = useRef(false);\n const playerRef = useRef<HTMLDivElement | null>(null);\n const wrapperRef = useRef<HTMLDivElement | null>(null);\n const lastRect = useRef<DOMRectReadOnly | null>(null);\n\n const onClickHandler = controls ? () => setPlaying(prev => !prev) : undefined;\n\n /**\n * Sync the playing prop with the player's own state when it changes.\n */\n useEffect(() => {\n setPlaying(playing);\n }, [playing]);\n\n /**\n * Sync the current time with the player's own state.\n */\n useEffect(() => {\n const diff = Math.abs(currentTime - currentTimeState);\n if (diff > 0.05) {\n setForcedTime(currentTime);\n }\n }, [currentTime]);\n\n useEffect(() => {\n setForcedVolume(volume);\n }, [volume]);\n\n /**\n * Receives the current time of the video from the player.\n * Use refs to ensure we always call the latest callbacks.\n */\n const onTimeUpdateRef = useRef(onTimeUpdate);\n const onDurationChangeRef = useRef(onDurationChange);\n \n // Update refs when callbacks change\n useEffect(() => {\n onTimeUpdateRef.current = onTimeUpdate;\n }, [onTimeUpdate]);\n \n useEffect(() => {\n onDurationChangeRef.current = onDurationChange;\n }, [onDurationChange]);\n\n const handleTimeUpdate = useCallback((event: Event) => {\n const e = event as CustomEvent;\n setCurrentTime(e.detail);\n onTimeUpdateRef.current(e.detail);\n }, []);\n\n /**\n * Receives the duration of the video from the player.\n */\n const handleDurationUpdate = useCallback((event: Event) => {\n const e = event as CustomEvent;\n setDuration(e.detail);\n onDurationChangeRef.current(e.detail);\n }, []);\n\n /**\n * Play and pause using the space key.\n */\n const handleKeyDown = useCallback((event: KeyboardEvent) => {\n if (event.code === 'Space' && focus.current) {\n event.preventDefault();\n setPlaying(prev => !prev);\n }\n }, []);\n\n const onPlayerReadyRef = useRef(onPlayerReady);\n \n useEffect(() => {\n onPlayerReadyRef.current = onPlayerReady;\n }, [onPlayerReady]);\n\n const handlePlayerReady = useCallback((event: Event) => {\n const player = (event as CustomEvent).detail;\n if (player) {\n onPlayerReadyRef.current(player);\n }\n \n // Ensure event listeners are attached when player becomes ready\n // This is a fallback in case listeners weren't attached earlier\n const playerElement = playerRef.current;\n if (playerElement) {\n // Remove and re-add to ensure they're attached\n playerElement.removeEventListener('timeupdate', handleTimeUpdate);\n playerElement.removeEventListener('duration', handleDurationUpdate);\n playerElement.addEventListener('timeupdate', handleTimeUpdate);\n playerElement.addEventListener('duration', handleDurationUpdate);\n }\n }, [handleTimeUpdate, handleDurationUpdate]);\n\n const handlePlayerResize = useCallback(\n (entries: ResizeObserverEntry[]) => {\n const [firstEntry] = entries;\n if (!firstEntry || !wrapperRef.current) {\n return;\n }\n\n const newRect = wrapperRef.current.getBoundingClientRect();\n if (\n !lastRect.current ||\n newRect.width !== lastRect.current.width ||\n newRect.height !== lastRect.current.height ||\n newRect.x !== lastRect.current.x ||\n newRect.y !== lastRect.current.y\n ) {\n lastRect.current = newRect;\n onPlayerResize(newRect);\n }\n },\n [onPlayerResize],\n );\n\n useEffect(() => {\n if (!wrapperRef.current) return;\n\n const resizeObserver = new ResizeObserver(handlePlayerResize);\n resizeObserver.observe(wrapperRef.current);\n\n return () => {\n resizeObserver.disconnect();\n };\n }, [handlePlayerResize]);\n\n /**\n * Import the player and add all event listeners.\n */\n useEffect(() => {\n let cleanup: (() => void) | null = null;\n\n const setupListeners = () => {\n const player = playerRef.current;\n if (!player) return;\n\n // Remove any existing listeners first to avoid duplicates\n player.removeEventListener('timeupdate', handleTimeUpdate);\n player.removeEventListener('duration', handleDurationUpdate);\n player.removeEventListener('playerready', handlePlayerReady);\n\n // Add event listeners\n player.addEventListener('timeupdate', handleTimeUpdate);\n player.addEventListener('duration', handleDurationUpdate);\n player.addEventListener('playerready', handlePlayerReady);\n document.addEventListener('keydown', handleKeyDown);\n\n cleanup = () => {\n player.removeEventListener('timeupdate', handleTimeUpdate);\n player.removeEventListener('duration', handleDurationUpdate);\n player.removeEventListener('playerready', handlePlayerReady);\n document.removeEventListener('keydown', handleKeyDown);\n };\n };\n\n // Import the custom element definition\n import('./internal').then(() => {\n // Wait for the next tick to ensure the element is in the DOM\n // Use requestAnimationFrame to ensure the custom element is ready\n requestAnimationFrame(() => {\n if (playerRef.current) {\n (playerRef.current as any).setProject(project);\n // Set up listeners after the element is ready\n setupListeners();\n }\n });\n });\n\n // Also set up listeners immediately if element already exists\n // This handles the case where the element was already in the DOM\n if (playerRef.current) {\n setupListeners();\n }\n\n return () => {\n if (cleanup) {\n cleanup();\n }\n };\n }, [project, handleTimeUpdate, handleDurationUpdate, handlePlayerReady, handleKeyDown]);\n\n /**\n * When the forced time changes, seek to that time.\n */\n function setForcedTime(forcedTime: number) {\n if (playerRef.current) {\n playerRef.current.dispatchEvent(\n new CustomEvent('seekto', {detail: forcedTime}),\n );\n }\n }\n\n function setForcedVolume(volume: number) {\n setVolumeState(volume);\n if (playerRef.current) {\n playerRef.current.dispatchEvent(\n new CustomEvent('volumechange', {detail: volume}),\n );\n }\n }\n\n return (\n <div className=\"twick-player-root\" style={{display: 'contents'}}>\n <div\n ref={wrapperRef}\n className=\"relative cursor-default focus:outline-none\"\n onFocus={() => (focus.current = true)}\n onBlur={() => (focus.current = false)}\n tabIndex={0}\n onMouseEnter={() => setIsMouseOver(true)}\n onMouseLeave={() => setIsMouseOver(false)}\n >\n <div className=\"relative\">\n <twick-player\n ref={playerRef}\n playing={String(playingState)}\n onClick={onClickHandler}\n variables={JSON.stringify(variables)}\n looping={looping ? 'true' : 'false'}\n width={width}\n height={height}\n quality={quality}\n fps={fps}\n volume={volumeState}\n />\n <div\n className={`absolute bottom-0 w-full transition-opacity duration-200 ${\n shouldShowControls(playingState, isMouseOver, !controls)\n ? 'opacity-100'\n : 'opacity-0'\n }`}\n >\n <Controls\n duration={duration}\n playing={playingState}\n setPlaying={setPlaying}\n currentTime={currentTimeState}\n setForcedTime={setForcedTime}\n timeDisplayFormat={timeDisplayFormat}\n volume={volumeState}\n setVolume={setForcedVolume}\n />\n </div>\n </div>\n </div>\n </div>\n );\n}\n","import {useState} from 'react';\nimport {MutedSoundIcon, PauseButton, PlayButton, SoundIcon} from './icons';\nimport {getFormattedTime} from './utils';\n\nfunction PlayPause({\n playing,\n setPlaying,\n}: {\n playing: boolean;\n setPlaying: (playing: boolean) => void;\n}) {\n return (\n <button type=\"button\" className=\"p-1\" onClick={() => setPlaying(!playing)}>\n {playing ? <PauseButton /> : <PlayButton />}\n </button>\n );\n}\n\nfunction VolumeSlider({\n volume,\n setVolume,\n}: {\n volume: number;\n setVolume: (volume: number) => void;\n}) {\n const [isHovering, setIsHovering] = useState(false);\n const [isInteracting, setIsInteracting] = useState(false);\n const [previousVolume, setPreviousVolume] = useState(1);\n\n const handleIconClick = () => {\n if (volume > 0) {\n setPreviousVolume(volume);\n setVolume(0);\n } else {\n setVolume(previousVolume);\n }\n };\n\n return (\n <div\n className=\"flex items-center space-x-2 relative\"\n onMouseEnter={() => setIsHovering(true)}\n onMouseLeave={() => {\n if (!isInteracting) {\n setIsHovering(false);\n }\n }}\n >\n <div\n className=\"w-6 h-6 flex items-center justify-center cursor-pointer\"\n onClick={handleIconClick}\n >\n {volume === 0 ? <MutedSoundIcon /> : <SoundIcon />}\n </div>\n {(isHovering || isInteracting) && (\n <div className=\"flex items-center h-1.5 whitespace-nowrap\">\n <div className=\"relative w-20 h-1.5 bg-gray-300 rounded-full\">\n <div\n className=\"absolute top-0 left-0 h-full bg-gray-100 rounded-full\"\n style={{width: `${volume * 100}%`}}\n />\n <input\n type=\"range\"\n min={0}\n max={1}\n step={0.01}\n value={volume}\n onChange={e => {\n const newVolume = Number(e.target.value);\n setVolume(newVolume);\n if (newVolume > 0) {\n setPreviousVolume(newVolume);\n }\n }}\n onMouseDown={() => setIsInteracting(true)}\n onMouseUp={() => setIsInteracting(false)}\n onMouseLeave={() => setIsInteracting(false)}\n className=\"absolute top-0 left-0 w-full h-full opacity-0 cursor-pointer\"\n />\n </div>\n </div>\n )}\n </div>\n );\n}\n\nfunction Timeline({\n currentTime,\n duration,\n setCurrentTime,\n}: {\n currentTime: number;\n duration: number;\n setCurrentTime: (currentTime: number) => void;\n}) {\n const progressPercentage = (currentTime / duration) * 100;\n\n return (\n <div className=\"relative flex-1 w-full h-1.5 bg-gray-300 rounded-full overflow-hidden\">\n <div\n className=\"absolute top-0 left-0 h-full bg-gray-100\"\n style={{width: `${progressPercentage}%`}}\n />\n <input\n type=\"range\"\n value={currentTime}\n min={0}\n max={duration}\n step={0.01}\n className=\"absolute top-0 left-0 w-full h-full opacity-0 cursor-pointer\"\n onChange={event => setCurrentTime(Number(event.target.value))}\n />\n </div>\n );\n}\n\nexport function Controls({\n duration,\n playing,\n setPlaying,\n currentTime,\n setForcedTime,\n timeDisplayFormat,\n volume,\n setVolume,\n}: {\n duration: number;\n playing: boolean;\n setPlaying: (playing: boolean) => void;\n currentTime: number;\n setForcedTime: (currentTime: number) => void;\n timeDisplayFormat: 'MM:SS' | 'MM:SS.m' | 'MM:SS.mm';\n volume: number;\n setVolume: (volume: number) => void;\n}) {\n return (\n <div className=\"text-white p-4 flex-col space-y-2 bg-gradient-to-t from-gray-500 to-transparent\">\n <div className=\"flex items-center space-x-2\">\n <PlayPause playing={playing} setPlaying={setPlaying} />\n <div className=\"flex items-center space-x-2\">\n <VolumeSlider volume={volume} setVolume={setVolume} />\n <div>\n <span>\n {getFormattedTime(currentTime, duration, timeDisplayFormat)}\n </span>\n </div>\n </div>\n <div className=\"flex-grow\" />\n </div>\n <Timeline\n currentTime={currentTime}\n duration={duration}\n setCurrentTime={setForcedTime}\n />\n </div>\n );\n}\n","export function PlayButton() {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n className=\"w-6 h-6\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.5 5.653c0-1.427 1.529-2.33 2.779-1.643l11.54 6.347c1.295.712 1.295 2.573 0 3.286L7.28 19.99c-1.25.687-2.779-.217-2.779-1.643V5.653Z\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function PauseButton() {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n className=\"w-6 h-6\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M6.75 5.25a.75.75 0 0 1 .75-.75H9a.75.75 0 0 1 .75.75v13.5a.75.75 0 0 1-.75.75H7.5a.75.75 0 0 1-.75-.75V5.25Zm7.5 0A.75.75 0 0 1 15 4.5h1.5a.75.75 0 0 1 .75.75v13.5a.75.75 0 0 1-.75.75H15a.75.75 0 0 1-.75-.75V5.25Z\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function SoundIcon() {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n className=\"p-w-6 p-h-6\"\n >\n <path d=\"M18.36,19.36a1,1,0,0,1-.7-.29,1,1,0,0,1,0-1.41,8,8,0,0,0,0-11.32,1,1,0,0,1,1.41-1.41,10,10,0,0,1,0,14.14A1,1,0,0,1,18.36,19.36Z\" />\n <path d=\"M15.54,16.54a1,1,0,0,1-.71-.3,1,1,0,0,1,0-1.41,4,4,0,0,0,0-5.66,1,1,0,0,1,1.41-1.41,6,6,0,0,1,0,8.48A1,1,0,0,1,15.54,16.54Z\" />\n <path d=\"M11.38,4.08a1,1,0,0,0-1.09.21L6.59,8H4a2,2,0,0,0-2,2v4a2,2,0,0,0,2,2H6.59l3.7,3.71A1,1,0,0,0,11,20a.84.84,0,0,0,.38-.08A1,1,0,0,0,12,19V5A1,1,0,0,0,11.38,4.08Z\" />\n </svg>\n );\n}\n\nexport function MutedSoundIcon() {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n className=\"p-w-6 p-h-6\"\n >\n <path d=\"M11.38,4.08a1,1,0,0,0-1.09.21L6.59,8H4a2,2,0,0,0-2,2v4a2,2,0,0,0,2,2H6.59l3.7,3.71A1,1,0,0,0,11,20a.84.84,0,0,0,.38-.08A1,1,0,0,0,12,19V5A1,1,0,0,0,11.38,4.08Z\" />\n <path d=\"M16,15.5a1,1,0,0,1-.71-.29,1,1,0,0,1,0-1.42l5-5a1,1,0,0,1,1.42,1.42l-5,5A1,1,0,0,1,16,15.5Z\" />\n <path d=\"M21,15.5a1,1,0,0,1-.71-.29l-5-5a1,1,0,0,1,1.42-1.42l5,5a1,1,0,0,1,0,1.42A1,1,0,0,1,21,15.5Z\" />\n </svg>\n );\n}\n","export function getFormattedTime(\n timeInSeconds: number,\n absoluteTimeInSeconds: number,\n timeDisplayFormat: 'MM:SS' | 'MM:SS.mm' | 'MM:SS.m',\n) {\n function toFormattedTime(timeInSeconds: number) {\n const minutes = Math.floor(timeInSeconds / 60);\n const seconds = Math.floor(timeInSeconds % 60)\n .toString()\n .padStart(2, '0');\n const milliseconds = Math.floor((timeInSeconds % 1) * 1000)\n .toString()\n .padStart(3, '0');\n\n if (timeDisplayFormat === 'MM:SS') {\n return `${minutes}:${seconds}`;\n }\n\n if (timeDisplayFormat === 'MM:SS.m') {\n return `${minutes}:${seconds}.${milliseconds[0]}`;\n }\n\n if (timeDisplayFormat === 'MM:SS.mm') {\n return `${minutes}:${seconds}.${milliseconds.slice(0, 2)}`;\n }\n }\n\n return `${toFormattedTime(timeInSeconds)} / ${toFormattedTime(absoluteTimeInSeconds)}`;\n}\n\nexport function shouldShowControls(\n playing: boolean,\n isMouseOver: boolean,\n areControlsDisabled: boolean,\n) {\n if (areControlsDisabled) {\n return false;\n }\n\n return !playing || isMouseOver;\n}\n"],"mappings":"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","names":["import_core","Player","import_react","timeInSeconds","import_jsx_runtime","import_jsx_runtime","Player","volume"]}
package/dist/index.js CHANGED
@@ -366,7 +366,7 @@ function Player({
366
366
  document.removeEventListener("keydown", handleKeyDown);
367
367
  };
368
368
  };
369
- import("./internal-H4HUGGQY.js").then(() => {
369
+ import("./internal-ELSJV37U.js").then(() => {
370
370
  requestAnimationFrame(() => {
371
371
  if (playerRef.current) {
372
372
  playerRef.current.setProject(project);
@@ -110,7 +110,6 @@ var TwickPlayer = class extends HTMLElement {
110
110
  this.abortController?.abort();
111
111
  this.abortController = new AbortController();
112
112
  this.project = project;
113
- console.log(project);
114
113
  this.defaultSettings = getFullPreviewSettings(this.project);
115
114
  const player = new Player(this.project);
116
115
  player.setVariables(this.variables);
@@ -241,4 +240,4 @@ var TwickPlayer = class extends HTMLElement {
241
240
  if (!customElements.get(ID)) {
242
241
  customElements.define(ID, TwickPlayer);
243
242
  }
244
- //# sourceMappingURL=internal-H4HUGGQY.js.map
243
+ //# sourceMappingURL=internal-ELSJV37U.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/internal.ts"],"sourcesContent":["import type {Project} from '@twick/core';\nimport {Player, Stage, getFullPreviewSettings} from '@twick/core';\n\nimport {Vector2} from '@twick/core';\n\nconst stylesNew = `\n.overlay {\n\tposition: absolute;\n\tleft: 0;\n\tright: 0;\n\ttop: 0;\n\tbottom: 0;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\topacity: 0;\n\ttransition: opacity 0.1s;\n\tz-index: 0;\n }\n .canvas {\n\twidth: 100%;\n\tdisplay: block;\n\topacity: 1;\n\ttransition: opacity 0.1s;\n }\n`;\n\nconst TEMPLATE = `<style>${stylesNew}</style><div class=\"overlay\"></div>`;\nconst ID = 'twick-player';\n\nenum State {\n Initial = 'initial',\n Loading = 'loading',\n Ready = 'ready',\n Error = 'error',\n}\n\nclass TwickPlayer extends HTMLElement {\n public static get observedAttributes() {\n return [\n 'playing',\n 'variables',\n 'looping',\n 'fps',\n 'quality',\n 'width',\n 'height',\n 'volume',\n ];\n }\n\n private get fps() {\n const attr = this.getAttribute('fps');\n return attr ? parseFloat(attr) : (this.defaultSettings?.fps ?? 60);\n }\n\n private get quality() {\n const attr = this.getAttribute('quality');\n return attr\n ? parseFloat(attr)\n : (this.defaultSettings?.resolutionScale ?? 1);\n }\n\n private get width() {\n const attr = this.getAttribute('width');\n return attr ? parseFloat(attr) : (this.defaultSettings?.size.width ?? 0);\n }\n\n private get height() {\n const attr = this.getAttribute('height');\n return attr ? parseFloat(attr) : (this.defaultSettings?.size.height ?? 0);\n }\n\n private get variables() {\n try {\n const attr = this.getAttribute('variables');\n return attr ? JSON.parse(attr) : {};\n } catch {\n this.project?.logger.warn(`Project variables could not be parsed.`);\n return {};\n }\n }\n\n private readonly root: ShadowRoot;\n private readonly canvas: HTMLCanvasElement;\n private readonly overlay: HTMLCanvasElement;\n\n private state = State.Initial;\n private project: Project | null = null;\n private player: Player | null = null;\n private defaultSettings:\n | ReturnType<typeof getFullPreviewSettings>\n | undefined;\n private abortController: AbortController | null = null;\n private playing = false;\n private stage = new Stage();\n\n private time: number = 0;\n private duration: number = 0; // in frames\n private looping = true;\n private volume = 1;\n private volumeChangeRequested = true;\n\n public constructor() {\n super();\n this.root = this.attachShadow({mode: 'open'});\n this.root.innerHTML = TEMPLATE;\n\n this.overlay = this.root.querySelector('.overlay')!;\n this.canvas = this.stage.finalBuffer;\n this.canvas.classList.add('canvas');\n this.root.prepend(this.canvas);\n this.setState(State.Initial);\n }\n\n public setProject(project: Project) {\n this.updateProject(project);\n }\n\n private setState(state: State) {\n this.state = state;\n this.setPlaying(this.playing);\n }\n\n private setPlaying(value: boolean) {\n if (this.state === State.Ready && value) {\n this.player?.togglePlayback(true);\n this.playing = true;\n } else {\n this.player?.togglePlayback(false);\n this.playing = false;\n }\n }\n\n private async updateProject(project: Project) {\n const playing = this.playing;\n this.setState(State.Initial);\n\n this.abortController?.abort();\n this.abortController = new AbortController();\n\n this.project = project;\n this.defaultSettings = getFullPreviewSettings(this.project);\n\n const player = new Player(this.project);\n player.setVariables(this.variables);\n player.toggleLoop(this.looping);\n\n this.player?.onRender.unsubscribe(this.render);\n this.player?.onFrameChanged.unsubscribe(this.handleFrameChanged);\n this.player?.togglePlayback(false);\n this.player?.deactivate();\n\n this.player = player;\n this.updateSettings();\n\n this.setState(State.Ready);\n this.dispatchEvent(new CustomEvent('playerready', {detail: this.player}));\n\n // Restore previous state\n this.setPlaying(playing);\n this.player.onRender.subscribe(this.render);\n this.player.onFrameChanged.subscribe(this.handleFrameChanged);\n }\n\n public attributeChangedCallback(name: string, _: any, newValue: any) {\n switch (name) {\n case 'playing':\n this.setPlaying(newValue === 'true');\n break;\n case 'variables':\n this.player?.setVariables(this.variables);\n this.player?.requestSeek(this.player.playback.frame);\n this.player?.playback.reload();\n break;\n case 'looping':\n this.looping = newValue === 'true';\n this.player?.toggleLoop(newValue === 'true');\n break;\n case 'fps':\n case 'quality':\n case 'width':\n case 'height':\n this.updateSettings();\n break;\n case 'volume':\n this.volume = newValue;\n this.volumeChangeRequested = true;\n }\n }\n\n /**\n * Runs when the element is removed from the DOM.\n */\n public disconnectedCallback() {\n this.player?.deactivate();\n this.player?.onRender.unsubscribe(this.render);\n\n this.removeEventListener('seekto', this.handleSeekTo);\n this.removeEventListener('volumechange', this.handleVolumeChange);\n }\n\n /**\n * Runs when the element is added to the DOM.\n */\n public connectedCallback() {\n this.player?.activate();\n this.player?.onRender.subscribe(this.render);\n\n this.addEventListener('seekto', this.handleSeekTo);\n this.addEventListener('volumechange', this.handleVolumeChange);\n }\n\n /**\n * Triggered by the timeline.\n */\n private handleSeekTo = (event: Event) => {\n if (!this.project) {\n return;\n }\n\n const e = event as CustomEvent;\n this.time = e.detail;\n this.player?.requestSeek(e.detail * this.player.playback.fps);\n this.volumeChangeRequested = true;\n };\n\n private handleVolumeChange = (event: Event) => {\n if (!this.project) {\n return;\n }\n\n const e = event as CustomEvent;\n this.volume = e.detail;\n\n this.player?.playback.currentScene.adjustVolume(this.volume);\n };\n\n /**\n * Triggered by the player.\n */\n private handleFrameChanged = (frame: number) => {\n if (!this.project || !this.player) {\n return;\n }\n this.time = frame / this.player.playback.fps;\n\n if (this.volumeChangeRequested || frame === 0) {\n this.player?.playback.currentScene.adjustVolume(this.volume);\n this.volumeChangeRequested = false;\n }\n };\n\n /**\n * Called on every frame.\n */\n private render = async () => {\n if (this.player && this.project) {\n await this.stage.render(\n this.player.playback.currentScene,\n this.player.playback.previousScene,\n );\n\n this.dispatchEvent(new CustomEvent('timeupdate', {detail: this.time}));\n\n const durationInFrames = this.player.playback.duration;\n if (durationInFrames === this.duration) {\n return;\n }\n\n this.duration = durationInFrames;\n\n const durationInSeconds = durationInFrames / this.player.playback.fps;\n this.dispatchEvent(\n new CustomEvent('duration', {detail: durationInSeconds}),\n );\n }\n };\n\n private updateSettings() {\n if (!this.defaultSettings) {\n return;\n }\n\n const settings = {\n ...this.defaultSettings,\n size: new Vector2(this.width, this.height),\n resolutionScale: this.quality,\n fps: this.fps,\n };\n this.stage.configure(settings);\n this.player?.configure(settings);\n }\n}\n\nif (!customElements.get(ID)) {\n customElements.define(ID, TwickPlayer);\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twick/player-react",
3
- "version": "0.15.7",
3
+ "version": "0.15.9",
4
4
  "description": "",
5
5
  "author": "twick",
6
6
  "license": "MIT",
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "keywords": [],
27
27
  "dependencies": {
28
- "@twick/core": "0.15.7",
28
+ "@twick/core": "0.15.9",
29
29
  "react": "^18",
30
30
  "react-dom": "^18",
31
31
  "uuid": "^10.0.0"
@@ -46,5 +46,5 @@
46
46
  "url": "https://github.com/ncounterspecialist/twick-base.git"
47
47
  },
48
48
  "bugs": "https://github.com/ncounterspecialist/twick-base/issues",
49
- "gitHead": "2088b9cc48dce047cf1753453fe80866b17478a3"
49
+ "gitHead": "78e57eea48761f2bd1c9d0c813d8617228fa7ff7"
50
50
  }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/internal.ts"],"sourcesContent":["import type {Project} from '@twick/core';\nimport {Player, Stage, getFullPreviewSettings} from '@twick/core';\n\nimport {Vector2} from '@twick/core';\n\nconst stylesNew = `\n.overlay {\n\tposition: absolute;\n\tleft: 0;\n\tright: 0;\n\ttop: 0;\n\tbottom: 0;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\topacity: 0;\n\ttransition: opacity 0.1s;\n\tz-index: 0;\n }\n .canvas {\n\twidth: 100%;\n\tdisplay: block;\n\topacity: 1;\n\ttransition: opacity 0.1s;\n }\n`;\n\nconst TEMPLATE = `<style>${stylesNew}</style><div class=\"overlay\"></div>`;\nconst ID = 'twick-player';\n\nenum State {\n Initial = 'initial',\n Loading = 'loading',\n Ready = 'ready',\n Error = 'error',\n}\n\nclass TwickPlayer extends HTMLElement {\n public static get observedAttributes() {\n return [\n 'playing',\n 'variables',\n 'looping',\n 'fps',\n 'quality',\n 'width',\n 'height',\n 'volume',\n ];\n }\n\n private get fps() {\n const attr = this.getAttribute('fps');\n return attr ? parseFloat(attr) : (this.defaultSettings?.fps ?? 60);\n }\n\n private get quality() {\n const attr = this.getAttribute('quality');\n return attr\n ? parseFloat(attr)\n : (this.defaultSettings?.resolutionScale ?? 1);\n }\n\n private get width() {\n const attr = this.getAttribute('width');\n return attr ? parseFloat(attr) : (this.defaultSettings?.size.width ?? 0);\n }\n\n private get height() {\n const attr = this.getAttribute('height');\n return attr ? parseFloat(attr) : (this.defaultSettings?.size.height ?? 0);\n }\n\n private get variables() {\n try {\n const attr = this.getAttribute('variables');\n return attr ? JSON.parse(attr) : {};\n } catch {\n this.project?.logger.warn(`Project variables could not be parsed.`);\n return {};\n }\n }\n\n private readonly root: ShadowRoot;\n private readonly canvas: HTMLCanvasElement;\n private readonly overlay: HTMLCanvasElement;\n\n private state = State.Initial;\n private project: Project | null = null;\n private player: Player | null = null;\n private defaultSettings:\n | ReturnType<typeof getFullPreviewSettings>\n | undefined;\n private abortController: AbortController | null = null;\n private playing = false;\n private stage = new Stage();\n\n private time: number = 0;\n private duration: number = 0; // in frames\n private looping = true;\n private volume = 1;\n private volumeChangeRequested = true;\n\n public constructor() {\n super();\n this.root = this.attachShadow({mode: 'open'});\n this.root.innerHTML = TEMPLATE;\n\n this.overlay = this.root.querySelector('.overlay')!;\n this.canvas = this.stage.finalBuffer;\n this.canvas.classList.add('canvas');\n this.root.prepend(this.canvas);\n this.setState(State.Initial);\n }\n\n public setProject(project: Project) {\n this.updateProject(project);\n }\n\n private setState(state: State) {\n this.state = state;\n this.setPlaying(this.playing);\n }\n\n private setPlaying(value: boolean) {\n if (this.state === State.Ready && value) {\n this.player?.togglePlayback(true);\n this.playing = true;\n } else {\n this.player?.togglePlayback(false);\n this.playing = false;\n }\n }\n\n private async updateProject(project: Project) {\n const playing = this.playing;\n this.setState(State.Initial);\n\n this.abortController?.abort();\n this.abortController = new AbortController();\n\n this.project = project;\n console.log(project);\n this.defaultSettings = getFullPreviewSettings(this.project);\n\n const player = new Player(this.project);\n player.setVariables(this.variables);\n player.toggleLoop(this.looping);\n\n this.player?.onRender.unsubscribe(this.render);\n this.player?.onFrameChanged.unsubscribe(this.handleFrameChanged);\n this.player?.togglePlayback(false);\n this.player?.deactivate();\n\n this.player = player;\n this.updateSettings();\n\n this.setState(State.Ready);\n this.dispatchEvent(new CustomEvent('playerready', {detail: this.player}));\n\n // Restore previous state\n this.setPlaying(playing);\n this.player.onRender.subscribe(this.render);\n this.player.onFrameChanged.subscribe(this.handleFrameChanged);\n }\n\n public attributeChangedCallback(name: string, _: any, newValue: any) {\n switch (name) {\n case 'playing':\n this.setPlaying(newValue === 'true');\n break;\n case 'variables':\n this.player?.setVariables(this.variables);\n this.player?.requestSeek(this.player.playback.frame);\n this.player?.playback.reload();\n break;\n case 'looping':\n this.looping = newValue === 'true';\n this.player?.toggleLoop(newValue === 'true');\n break;\n case 'fps':\n case 'quality':\n case 'width':\n case 'height':\n this.updateSettings();\n break;\n case 'volume':\n this.volume = newValue;\n this.volumeChangeRequested = true;\n }\n }\n\n /**\n * Runs when the element is removed from the DOM.\n */\n public disconnectedCallback() {\n this.player?.deactivate();\n this.player?.onRender.unsubscribe(this.render);\n\n this.removeEventListener('seekto', this.handleSeekTo);\n this.removeEventListener('volumechange', this.handleVolumeChange);\n }\n\n /**\n * Runs when the element is added to the DOM.\n */\n public connectedCallback() {\n this.player?.activate();\n this.player?.onRender.subscribe(this.render);\n\n this.addEventListener('seekto', this.handleSeekTo);\n this.addEventListener('volumechange', this.handleVolumeChange);\n }\n\n /**\n * Triggered by the timeline.\n */\n private handleSeekTo = (event: Event) => {\n if (!this.project) {\n return;\n }\n\n const e = event as CustomEvent;\n this.time = e.detail;\n this.player?.requestSeek(e.detail * this.player.playback.fps);\n this.volumeChangeRequested = true;\n };\n\n private handleVolumeChange = (event: Event) => {\n if (!this.project) {\n return;\n }\n\n const e = event as CustomEvent;\n this.volume = e.detail;\n\n this.player?.playback.currentScene.adjustVolume(this.volume);\n };\n\n /**\n * Triggered by the player.\n */\n private handleFrameChanged = (frame: number) => {\n if (!this.project || !this.player) {\n return;\n }\n this.time = frame / this.player.playback.fps;\n\n if (this.volumeChangeRequested || frame === 0) {\n this.player?.playback.currentScene.adjustVolume(this.volume);\n this.volumeChangeRequested = false;\n }\n };\n\n /**\n * Called on every frame.\n */\n private render = async () => {\n if (this.player && this.project) {\n await this.stage.render(\n this.player.playback.currentScene,\n this.player.playback.previousScene,\n );\n\n this.dispatchEvent(new CustomEvent('timeupdate', {detail: this.time}));\n\n const durationInFrames = this.player.playback.duration;\n if (durationInFrames === this.duration) {\n return;\n }\n\n this.duration = durationInFrames;\n\n const durationInSeconds = durationInFrames / this.player.playback.fps;\n this.dispatchEvent(\n new CustomEvent('duration', {detail: durationInSeconds}),\n );\n }\n };\n\n private updateSettings() {\n if (!this.defaultSettings) {\n return;\n }\n\n const settings = {\n ...this.defaultSettings,\n size: new Vector2(this.width, this.height),\n resolutionScale: this.quality,\n fps: this.fps,\n };\n this.stage.configure(settings);\n this.player?.configure(settings);\n }\n}\n\nif (!customElements.get(ID)) {\n customElements.define(ID, TwickPlayer);\n}\n"],"mappings":"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","names":[]}