mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
feat(compiler): add skin project compilation
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
import { compileProject } from '@videojs/compiler';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import config from '../../../skins.compiler.config';
|
||||
|
||||
const compact = (value: string): string => value.replace(/\s+/g, '');
|
||||
|
||||
describe('skins compiler config', () => {
|
||||
it('lowers the default video source skin to a React Tailwind slice', async () => {
|
||||
const result = await compileProject(config);
|
||||
const output = result.files.find(
|
||||
(file) => file.type === 'chunk' && file.fileName.endsWith('default-video.generated.tailwind.tsx')
|
||||
);
|
||||
|
||||
expect(result.diagnostics).toEqual([]);
|
||||
expect(output).toBeDefined();
|
||||
const code = output!.source;
|
||||
|
||||
expect(code).not.toContain('@videojs/core/components');
|
||||
expect(code).not.toContain('@videojs/icons/components');
|
||||
expect(code).not.toContain('./tailwind/video.tailwind');
|
||||
expect(code).toContain('from "@videojs/skins/default/tailwind/video.tailwind"');
|
||||
expect(code).toContain('from "@videojs/utils/style"');
|
||||
expect(code).toContain('from "@/player/context"');
|
||||
expect(code).toContain('from "@/ui/airplay-button"');
|
||||
expect(code).toContain('from "@/ui/pip-button"');
|
||||
expect(code).toContain('from "@/ui/play-button"');
|
||||
expect(code).toContain('from "@/icons"');
|
||||
expect(code).toContain('import type { ReactNode } from "react"');
|
||||
|
||||
const compactCode = compact(code);
|
||||
expect(compactCode).toContain(compact('children?: ReactNode | undefined;'));
|
||||
expect(compactCode).toContain(compact('<Container className={cn(container, className)}>'));
|
||||
expect(compactCode).toContain(compact('<Controls.Root className={controls} data-controls="">'));
|
||||
expect(compactCode).toContain(compact('<Tooltip.Trigger render={<PlayButton'));
|
||||
expect(compactCode).not.toContain('className={[');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,218 @@
|
||||
// Generated by @videojs/compiler. Do not edit.
|
||||
|
||||
import {
|
||||
airplayIcon,
|
||||
button,
|
||||
buttonGroupEnd,
|
||||
buttonGroupStart,
|
||||
castIcon,
|
||||
container,
|
||||
controls,
|
||||
fullscreenIcon,
|
||||
icon,
|
||||
iconContainer,
|
||||
iconFlipped,
|
||||
pipIcon,
|
||||
playIcon,
|
||||
popup,
|
||||
slider,
|
||||
time,
|
||||
} from '@videojs/skins/default/tailwind/video.tailwind';
|
||||
import { cn } from '@videojs/utils/style';
|
||||
import type { ReactNode } from 'react';
|
||||
import {
|
||||
AirPlayEnterIcon,
|
||||
AirPlayExitIcon,
|
||||
CastEnterIcon,
|
||||
CastExitIcon,
|
||||
FullscreenEnterIcon,
|
||||
FullscreenExitIcon,
|
||||
PauseIcon,
|
||||
PipEnterIcon,
|
||||
PipExitIcon,
|
||||
PlayIcon,
|
||||
RestartIcon,
|
||||
SeekIcon,
|
||||
} from '@/icons';
|
||||
import { Container } from '@/player/context';
|
||||
import { AirPlayButton } from '@/ui/airplay-button';
|
||||
import { CastButton } from '@/ui/cast-button';
|
||||
import { Controls } from '@/ui/controls';
|
||||
import { FullscreenButton } from '@/ui/fullscreen-button';
|
||||
import { Gesture } from '@/ui/gesture';
|
||||
import { Hotkey } from '@/ui/hotkey';
|
||||
import { PiPButton } from '@/ui/pip-button';
|
||||
import { PlayButton } from '@/ui/play-button';
|
||||
import { SeekButton } from '@/ui/seek-button';
|
||||
import { StatusAnnouncer } from '@/ui/status-announcer';
|
||||
import { Time } from '@/ui/time';
|
||||
import { TimeSlider } from '@/ui/time-slider';
|
||||
import { Tooltip } from '@/ui/tooltip';
|
||||
|
||||
const SEEK_TIME = 10;
|
||||
|
||||
export interface DefaultVideoSkinProps {
|
||||
className?: string | undefined;
|
||||
children?: ReactNode | undefined;
|
||||
}
|
||||
|
||||
export function DefaultVideoSkin({ className, children }: DefaultVideoSkinProps) {
|
||||
return (
|
||||
<Container className={cn(container, className)}>
|
||||
{children}
|
||||
|
||||
<Controls.Root className={controls} data-controls="">
|
||||
<Tooltip.Provider>
|
||||
<Controls.Group className={buttonGroupStart}>
|
||||
<Tooltip.Root side="top">
|
||||
<Tooltip.Trigger
|
||||
render={
|
||||
<PlayButton className={cn(button.base, button.subtle, button.icon, playIcon.button)}>
|
||||
<RestartIcon className={cn(icon, playIcon.restart)} />
|
||||
<PlayIcon className={cn(icon, playIcon.play)} />
|
||||
<PauseIcon className={cn(icon, playIcon.pause)} />
|
||||
</PlayButton>
|
||||
}
|
||||
/>
|
||||
<Tooltip.Popup className={popup.tooltip}>
|
||||
<Tooltip.Label />
|
||||
<Tooltip.Shortcut className={popup.tooltipShortcut} />
|
||||
</Tooltip.Popup>
|
||||
</Tooltip.Root>
|
||||
|
||||
<Tooltip.Root side="top">
|
||||
<Tooltip.Trigger
|
||||
render={
|
||||
<SeekButton seconds={-SEEK_TIME} className={cn(button.base, button.subtle, button.icon)}>
|
||||
<SeekIcon className={cn(icon, iconContainer, iconFlipped)} />
|
||||
</SeekButton>
|
||||
}
|
||||
/>
|
||||
<Tooltip.Popup className={popup.tooltip}>
|
||||
<Tooltip.Label />
|
||||
<Tooltip.Shortcut className={popup.tooltipShortcut} />
|
||||
</Tooltip.Popup>
|
||||
</Tooltip.Root>
|
||||
|
||||
<Tooltip.Root side="top">
|
||||
<Tooltip.Trigger
|
||||
render={
|
||||
<SeekButton seconds={SEEK_TIME} className={cn(button.base, button.subtle, button.icon)}>
|
||||
<SeekIcon className={cn(icon, iconContainer)} />
|
||||
</SeekButton>
|
||||
}
|
||||
/>
|
||||
<Tooltip.Popup className={popup.tooltip}>
|
||||
<Tooltip.Label />
|
||||
<Tooltip.Shortcut className={popup.tooltipShortcut} />
|
||||
</Tooltip.Popup>
|
||||
</Tooltip.Root>
|
||||
</Controls.Group>
|
||||
|
||||
<Time.Group className={time.group}>
|
||||
<Time.Value type="current" className={time.current} />
|
||||
<TimeSlider.Root className={slider.root}>
|
||||
<TimeSlider.Track className={slider.track}>
|
||||
<TimeSlider.Fill className={cn(slider.fill.base, slider.fill.fill)} />
|
||||
<TimeSlider.Buffer className={cn(slider.fill.base, slider.fill.buffer)} />
|
||||
</TimeSlider.Track>
|
||||
<TimeSlider.Thumb className={cn(slider.thumb.base, slider.thumb.interactive)} />
|
||||
<TimeSlider.Preview className={slider.preview}>
|
||||
<TimeSlider.Value type="pointer" className={slider.value} />
|
||||
</TimeSlider.Preview>
|
||||
</TimeSlider.Root>
|
||||
<Time.Value type="duration" className={time.duration} />
|
||||
</Time.Group>
|
||||
|
||||
<Controls.Group className={buttonGroupEnd}>
|
||||
<Tooltip.Root side="top">
|
||||
<Tooltip.Trigger
|
||||
render={
|
||||
<CastButton className={cn(button.base, button.subtle, button.icon, castIcon.button)}>
|
||||
<CastEnterIcon className={cn(icon, castIcon.enter)} />
|
||||
<CastExitIcon className={cn(icon, castIcon.exit)} />
|
||||
</CastButton>
|
||||
}
|
||||
/>
|
||||
<Tooltip.Popup className={popup.tooltip}>
|
||||
<Tooltip.Label />
|
||||
<Tooltip.Shortcut className={popup.tooltipShortcut} />
|
||||
</Tooltip.Popup>
|
||||
</Tooltip.Root>
|
||||
|
||||
<Tooltip.Root side="top">
|
||||
<Tooltip.Trigger
|
||||
render={
|
||||
<AirPlayButton className={cn(button.base, button.subtle, button.icon, airplayIcon.button)}>
|
||||
<AirPlayEnterIcon className={cn(icon, airplayIcon.enter)} />
|
||||
<AirPlayExitIcon className={cn(icon, airplayIcon.exit)} />
|
||||
</AirPlayButton>
|
||||
}
|
||||
/>
|
||||
<Tooltip.Popup className={popup.tooltip}>
|
||||
<Tooltip.Label />
|
||||
<Tooltip.Shortcut className={popup.tooltipShortcut} />
|
||||
</Tooltip.Popup>
|
||||
</Tooltip.Root>
|
||||
|
||||
<Tooltip.Root side="top">
|
||||
<Tooltip.Trigger
|
||||
render={
|
||||
<PiPButton className={cn(button.base, button.subtle, button.icon, pipIcon.button)}>
|
||||
<PipEnterIcon className={cn(icon, pipIcon.off)} />
|
||||
<PipExitIcon className={cn(icon, pipIcon.on)} />
|
||||
</PiPButton>
|
||||
}
|
||||
/>
|
||||
<Tooltip.Popup className={popup.tooltip}>
|
||||
<Tooltip.Label />
|
||||
<Tooltip.Shortcut className={popup.tooltipShortcut} />
|
||||
</Tooltip.Popup>
|
||||
</Tooltip.Root>
|
||||
|
||||
<Tooltip.Root side="top">
|
||||
<Tooltip.Trigger
|
||||
render={
|
||||
<FullscreenButton className={cn(button.base, button.subtle, button.icon, fullscreenIcon.button)}>
|
||||
<FullscreenEnterIcon className={cn(icon, fullscreenIcon.enter)} />
|
||||
<FullscreenExitIcon className={cn(icon, fullscreenIcon.exit)} />
|
||||
</FullscreenButton>
|
||||
}
|
||||
/>
|
||||
<Tooltip.Popup className={popup.tooltip}>
|
||||
<Tooltip.Label />
|
||||
<Tooltip.Shortcut className={popup.tooltipShortcut} />
|
||||
</Tooltip.Popup>
|
||||
</Tooltip.Root>
|
||||
</Controls.Group>
|
||||
</Tooltip.Provider>
|
||||
</Controls.Root>
|
||||
|
||||
<Hotkey keys="Space" action="togglePaused" />
|
||||
<Hotkey keys="k" action="togglePaused" />
|
||||
<Hotkey keys="m" action="toggleMuted" />
|
||||
<Hotkey keys="f" action="toggleFullscreen" />
|
||||
<Hotkey keys="c" action="toggleSubtitles" />
|
||||
<Hotkey keys="i" action="togglePictureInPicture" />
|
||||
<Hotkey keys="ArrowRight" action="seekStep" value={SEEK_TIME / 2} />
|
||||
<Hotkey keys="ArrowLeft" action="seekStep" value={-(SEEK_TIME / 2)} />
|
||||
<Hotkey keys="l" action="seekStep" value={SEEK_TIME} />
|
||||
<Hotkey keys="j" action="seekStep" value={-SEEK_TIME} />
|
||||
<Hotkey keys="ArrowUp" action="volumeStep" value={0.05} />
|
||||
<Hotkey keys="ArrowDown" action="volumeStep" value={-0.05} />
|
||||
<Hotkey keys="0-9" action="seekToPercent" />
|
||||
<Hotkey keys="Home" action="seekToPercent" value={0} />
|
||||
<Hotkey keys="End" action="seekToPercent" value={100} />
|
||||
<Hotkey keys=">" action="speedUp" />
|
||||
<Hotkey keys="<" action="speedDown" />
|
||||
|
||||
<Gesture type="tap" action="togglePaused" pointer="mouse" region="center" />
|
||||
<Gesture type="tap" action="toggleControls" pointer="touch" />
|
||||
<Gesture type="doubletap" action="seekStep" value={-SEEK_TIME} region="left" />
|
||||
<Gesture type="doubletap" action="toggleFullscreen" region="center" />
|
||||
<Gesture type="doubletap" action="seekStep" value={SEEK_TIME} region="right" />
|
||||
|
||||
<StatusAnnouncer />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user