mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
feat(core): add overlay primitive
This commit is contained in:
@@ -54,6 +54,8 @@ export * from './ui/menu/props';
|
||||
export * from './ui/mute-button/mute-button-core';
|
||||
export * from './ui/mute-button/mute-button-data-attrs';
|
||||
export * from './ui/mute-button/props';
|
||||
export * from './ui/overlay/overlay-core';
|
||||
export * from './ui/overlay/overlay-data-attrs';
|
||||
export * from './ui/pip-button/pip-button-core';
|
||||
export * from './ui/pip-button/pip-button-data-attrs';
|
||||
export * from './ui/pip-button/props';
|
||||
|
||||
@@ -16,6 +16,7 @@ import HotkeyDef from './hotkey/hotkey-component';
|
||||
import LiveButtonDef from './live-button/live-button-component';
|
||||
import MenuDef from './menu/menu-component';
|
||||
import MuteButtonDef from './mute-button/mute-button-component';
|
||||
import OverlayDef from './overlay/overlay-component';
|
||||
import PiPButtonDef from './pip-button/pip-button-component';
|
||||
import PlayButtonDef from './play-button/play-button-component';
|
||||
import PlaybackRateButtonDef from './playback-rate-button/playback-rate-button-component';
|
||||
@@ -50,6 +51,7 @@ export const Hotkey = createComponent(HotkeyDef);
|
||||
export const LiveButton = createComponent(LiveButtonDef);
|
||||
export const Menu = createComponent(MenuDef);
|
||||
export const MuteButton = createComponent(MuteButtonDef);
|
||||
export const Overlay = createComponent(OverlayDef);
|
||||
export const PiPButton = createComponent(PiPButtonDef);
|
||||
export const PlaybackRateButton = createComponent(PlaybackRateButtonDef);
|
||||
export const PlaybackRateRadioGroup = createComponent(PlaybackRateRadioGroupDef);
|
||||
@@ -85,6 +87,7 @@ export const COMPONENTS = {
|
||||
LiveButton: LiveButtonDef,
|
||||
Menu: MenuDef,
|
||||
MuteButton: MuteButtonDef,
|
||||
Overlay: OverlayDef,
|
||||
PiPButton: PiPButtonDef,
|
||||
PlaybackRateButton: PlaybackRateButtonDef,
|
||||
PlaybackRateRadioGroup: PlaybackRateRadioGroupDef,
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { defineComponent } from '../manifest';
|
||||
import { OverlayDataAttrs } from './overlay-data-attrs';
|
||||
|
||||
export default defineComponent()({
|
||||
name: 'Overlay',
|
||||
dataAttrs: OverlayDataAttrs,
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
import type { MediaControlsState, MediaErrorState } from '../../media/state';
|
||||
|
||||
export interface OverlayMediaState {
|
||||
controls?: MediaControlsState | null | undefined;
|
||||
error?: MediaErrorState | null | undefined;
|
||||
}
|
||||
|
||||
export interface OverlayState {
|
||||
visible: boolean;
|
||||
controlsVisible: boolean;
|
||||
errorVisible: boolean;
|
||||
}
|
||||
|
||||
export class OverlayCore {
|
||||
#media: OverlayMediaState = {};
|
||||
|
||||
setMedia(media: OverlayMediaState): void {
|
||||
this.#media = media;
|
||||
}
|
||||
|
||||
getState(): OverlayState {
|
||||
const controlsVisible = this.#media.controls?.controlsVisible ?? false;
|
||||
const errorVisible = Boolean(this.#media.error?.error);
|
||||
|
||||
return {
|
||||
visible: controlsVisible || errorVisible,
|
||||
controlsVisible,
|
||||
errorVisible,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export namespace OverlayCore {
|
||||
export type MediaState = OverlayMediaState;
|
||||
export type State = OverlayState;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import type { StateAttrMap } from '../types';
|
||||
import type { OverlayState } from './overlay-core';
|
||||
|
||||
export const OverlayDataAttrs = {
|
||||
/** Present when the overlay should be visible. */
|
||||
visible: 'data-visible',
|
||||
/** Present when controls visibility is showing the overlay. */
|
||||
controlsVisible: 'data-controls-visible',
|
||||
/** Present when error visibility is showing the overlay. */
|
||||
errorVisible: 'data-error-visible',
|
||||
} as const satisfies StateAttrMap<OverlayState>;
|
||||
@@ -0,0 +1,75 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import type { MediaControlsState, MediaErrorState } from '../../../media/state';
|
||||
import { OverlayCore } from '../overlay-core';
|
||||
|
||||
describe('OverlayCore', () => {
|
||||
describe('getState', () => {
|
||||
it('is visible when controls are visible', () => {
|
||||
const core = new OverlayCore();
|
||||
|
||||
core.setMedia({ controls: createControlsState({ controlsVisible: true }), error: createErrorState() });
|
||||
|
||||
expect(core.getState()).toEqual({
|
||||
visible: true,
|
||||
controlsVisible: true,
|
||||
errorVisible: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('is visible when an error is active', () => {
|
||||
const core = new OverlayCore();
|
||||
|
||||
core.setMedia({
|
||||
controls: createControlsState({ controlsVisible: false }),
|
||||
error: createErrorState({ code: 1, message: 'failed' }),
|
||||
});
|
||||
|
||||
expect(core.getState()).toEqual({
|
||||
visible: true,
|
||||
controlsVisible: false,
|
||||
errorVisible: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('is hidden when neither controls nor error need it', () => {
|
||||
const core = new OverlayCore();
|
||||
|
||||
core.setMedia({ controls: createControlsState({ controlsVisible: false }), error: createErrorState() });
|
||||
|
||||
expect(core.getState()).toEqual({
|
||||
visible: false,
|
||||
controlsVisible: false,
|
||||
errorVisible: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('treats missing feature state as hidden', () => {
|
||||
const core = new OverlayCore();
|
||||
|
||||
core.setMedia({});
|
||||
|
||||
expect(core.getState()).toEqual({
|
||||
visible: false,
|
||||
controlsVisible: false,
|
||||
errorVisible: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function createControlsState(overrides: Partial<MediaControlsState> = {}): MediaControlsState {
|
||||
return {
|
||||
userActive: true,
|
||||
controlsVisible: true,
|
||||
toggleControls: () => true,
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function createErrorState(error: MediaErrorState['error'] = null): MediaErrorState {
|
||||
return {
|
||||
error,
|
||||
dismissError: () => {},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user