diff --git a/packages/html/html/src/components/media-current-time-display.ts b/packages/html/html/src/components/media-current-time-display.ts index 99269ae5..afdead26 100644 --- a/packages/html/html/src/components/media-current-time-display.ts +++ b/packages/html/html/src/components/media-current-time-display.ts @@ -3,7 +3,10 @@ import { StateHook, PropsHook, } from '../utils/component-factory'; -import { currentTimeDisplayStateDefinition, formatDisplayTime } from '@vjs-10/media-store'; +import { + currentTimeDisplayStateDefinition, + formatDisplayTime, +} from '@vjs-10/media-store'; import { namedNodeMapToObject } from '../utils/element-utils.js'; export function getTemplateHTML( @@ -21,6 +24,7 @@ export class CurrentTimeDisplayBase extends HTMLElement { mode: 'open' as ShadowRootMode, }; static getTemplateHTML = getTemplateHTML; + static observedAttributes = ['show-remaining']; _state: | { @@ -56,13 +60,39 @@ export class CurrentTimeDisplayBase extends HTMLElement { return this._state?.duration; } + get showRemaining() { + return this.hasAttribute('show-remaining'); + } + + attributeChangedCallback( + name: string, + _oldValue: string | null, + _newValue: string | null, + ) { + if (name === 'show-remaining' && this._state) { + // Re-render with current state when show-remaining attribute changes + this._update({}, this._state); + } + } + _update(_props: any, state: any) { this._state = state; - - // Update the span content with formatted current time + + // Update the span content with formatted time const spanElement = this.shadowRoot?.querySelector('span') as HTMLElement; if (spanElement) { - spanElement.textContent = formatDisplayTime(state.currentTime); + if ( + this.showRemaining && + state.duration != null && + state.currentTime != null + ) { + // Show remaining time: duration - currentTime + const remainingTime = state.duration - state.currentTime; + spanElement.textContent = `-${formatDisplayTime(remainingTime)}`; + } else { + // Show current time (default behavior) + spanElement.textContent = formatDisplayTime(state.currentTime); + } } } } @@ -108,7 +138,10 @@ export const CurrentTimeDisplay = toConnectedHTMLComponent( // Register the custom element if (!globalThis.customElements.get('media-current-time-display')) { // @ts-ignore - Custom element constructor compatibility - globalThis.customElements.define('media-current-time-display', CurrentTimeDisplay); + globalThis.customElements.define( + 'media-current-time-display', + CurrentTimeDisplay, + ); } -export default CurrentTimeDisplay; \ No newline at end of file +export default CurrentTimeDisplay; diff --git a/packages/html/html/src/skins/media-skin-default.ts b/packages/html/html/src/skins/media-skin-default.ts index 829392f4..02198c7a 100644 --- a/packages/html/html/src/skins/media-skin-default.ts +++ b/packages/html/html/src/skins/media-skin-default.ts @@ -114,6 +114,7 @@ export function getTemplateHTML() { + diff --git a/packages/react/react/src/components/CurrentTimeDisplay.tsx b/packages/react/react/src/components/CurrentTimeDisplay.tsx index 43331527..16455a38 100644 --- a/packages/react/react/src/components/CurrentTimeDisplay.tsx +++ b/packages/react/react/src/components/CurrentTimeDisplay.tsx @@ -5,7 +5,10 @@ import { } from '@vjs-10/react-media-store'; import * as React from 'react'; import { toConnectedComponent } from '../utils/component-factory'; -import { currentTimeDisplayStateDefinition, formatDisplayTime } from '@vjs-10/media-store'; +import { + currentTimeDisplayStateDefinition, + formatDisplayTime, +} from '@vjs-10/media-store'; export const useCurrentTimeDisplayState = (_props: any) => { const mediaStore = useMediaStore(); @@ -26,7 +29,7 @@ export type useCurrentTimeDisplayState = typeof useCurrentTimeDisplayState; export type CurrentTimeDisplayState = ReturnType; export const useCurrentTimeDisplayProps = ( - props: React.PropsWithChildren<{ [k: string]: any }>, + props: React.PropsWithChildren<{ showRemaining?: boolean; [k: string]: any }>, state: ReturnType, ) => { const baseProps: Record = { @@ -44,11 +47,19 @@ export const renderCurrentTimeDisplay = ( props: CurrentTimeDisplayProps, state: CurrentTimeDisplayState, ) => { - return ( - - {formatDisplayTime(state.currentTime)} - - ); + const { showRemaining, ...restProps } = props; + + let timeToDisplay: number | undefined; + + if (showRemaining && state.duration != null && state.currentTime != null) { + // Show remaining time: duration - currentTime + timeToDisplay = state.duration - state.currentTime; + } else { + // Show current time (default behavior) + timeToDisplay = state.currentTime; + } + + return -{formatDisplayTime(timeToDisplay)}; }; export type renderCurrentTimeDisplay = typeof renderCurrentTimeDisplay; @@ -59,4 +70,4 @@ export const CurrentTimeDisplay = toConnectedComponent( renderCurrentTimeDisplay, 'CurrentTimeDisplay', ); -export default CurrentTimeDisplay; \ No newline at end of file +export default CurrentTimeDisplay; diff --git a/packages/react/react/src/skins/MediaSkinDefault.tsx b/packages/react/react/src/skins/MediaSkinDefault.tsx index 3ccf2e01..fedc45ef 100644 --- a/packages/react/react/src/skins/MediaSkinDefault.tsx +++ b/packages/react/react/src/skins/MediaSkinDefault.tsx @@ -31,7 +31,11 @@ export const MediaSkinDefault: React.FC<{ children: React.ReactNode }> = ({ - + {/* @ts-ignore */} @@ -48,7 +52,9 @@ export const MediaSkinDefault: React.FC<{ children: React.ReactNode }> = ({ {/* @ts-ignore */} - +