Skip to content

Commit

Permalink
feat(component): add Video player component
Browse files Browse the repository at this point in the history
fix #480
  • Loading branch information
morewings committed Oct 16, 2024
1 parent bd931e7 commit 4845f07
Show file tree
Hide file tree
Showing 27 changed files with 1,714 additions and 417 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

# Koval components library

[![NPM library Create React App template logo](./design/logo-repo.png)](#)
[![NPM library Create React App template logo](./design/logo-repo-social.png)](#)

Koval UI is a React component library built for modern browsers. Each component tries to utilize built-in browser APIs to full extent.

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@
"lint-staged": "15.2.10",
"npm-run-all2": "6.2.3",
"postcss": "8.4.47",
"postcss-preset-env": "10.0.6",
"postcss-preset-env": "9.6.0",
"prettier": "3.3.3",
"react": "18.3.1",
"react-dom": "18.3.1",
Expand Down
862 changes: 450 additions & 412 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions src/internal/Icons/IconDownloadVideo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type {FC, SVGProps} from 'react';
import Icon from '@phosphor-icons/core/assets/fill/box-arrow-down-fill.svg?react';
import classNames from 'classnames';

import classes from './Icon.module.css';

type Props = SVGProps<SVGSVGElement> & {
className?: string;
};

export const IconDownloadVideo: FC<Props> = ({className, ...restProps}) => {
return <Icon className={classNames(classes.icon, className)} {...restProps} />;
};
13 changes: 13 additions & 0 deletions src/internal/Icons/IconFullscreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type {FC, SVGProps} from 'react';
import Icon from '@phosphor-icons/core/assets/fill/frame-corners-fill.svg?react';
import classNames from 'classnames';

import classes from './Icon.module.css';

type Props = SVGProps<SVGSVGElement> & {
className?: string;
};

export const IconFullscreen: FC<Props> = ({className, ...restProps}) => {
return <Icon className={classNames(classes.icon, className)} {...restProps} />;
};
13 changes: 13 additions & 0 deletions src/internal/Icons/IconPause.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type {FC, SVGProps} from 'react';
import Icon from '@phosphor-icons/core/assets/fill/pause-fill.svg?react';
import classNames from 'classnames';

import classes from './Icon.module.css';

type Props = SVGProps<SVGSVGElement> & {
className?: string;
};

export const IconPause: FC<Props> = ({className, ...restProps}) => {
return <Icon className={classNames(classes.icon, className)} {...restProps} />;
};
13 changes: 13 additions & 0 deletions src/internal/Icons/IconPictureInPicture.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type {FC, SVGProps} from 'react';
import Icon from '@phosphor-icons/core/assets/fill/picture-in-picture-fill.svg?react';
import classNames from 'classnames';

import classes from './Icon.module.css';

type Props = SVGProps<SVGSVGElement> & {
className?: string;
};

export const IconPictureInPicture: FC<Props> = ({className, ...restProps}) => {
return <Icon className={classNames(classes.icon, className)} {...restProps} />;
};
13 changes: 13 additions & 0 deletions src/internal/Icons/IconPlay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type {FC, SVGProps} from 'react';
import Icon from '@phosphor-icons/core/assets/fill/play-fill.svg?react';
import classNames from 'classnames';

import classes from './Icon.module.css';

type Props = SVGProps<SVGSVGElement> & {
className?: string;
};

export const IconPlay: FC<Props> = ({className, ...restProps}) => {
return <Icon className={classNames(classes.icon, className)} {...restProps} />;
};
13 changes: 13 additions & 0 deletions src/internal/Icons/IconSpeed.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type {FC, SVGProps} from 'react';
import Icon from '@phosphor-icons/core/assets/fill/gauge-fill.svg?react';
import classNames from 'classnames';

import classes from './Icon.module.css';

type Props = SVGProps<SVGSVGElement> & {
className?: string;
};

export const IconSpeed: FC<Props> = ({className, ...restProps}) => {
return <Icon className={classNames(classes.icon, className)} {...restProps} />;
};
13 changes: 13 additions & 0 deletions src/internal/Icons/IconVideo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type {FC, SVGProps} from 'react';
import Icon from '@phosphor-icons/core/assets/fill/film-slate-fill.svg?react';
import classNames from 'classnames';

import classes from './Icon.module.css';

type Props = SVGProps<SVGSVGElement> & {
className?: string;
};

export const IconVideo: FC<Props> = ({className, ...restProps}) => {
return <Icon className={classNames(classes.icon, className)} {...restProps} />;
};
13 changes: 13 additions & 0 deletions src/internal/Icons/IconVolume.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type {FC, SVGProps} from 'react';
import Icon from '@phosphor-icons/core/assets/fill/speaker-high-fill.svg?react';
import classNames from 'classnames';

import classes from './Icon.module.css';

type Props = SVGProps<SVGSVGElement> & {
className?: string;
};

export const IconVolume: FC<Props> = ({className, ...restProps}) => {
return <Icon className={classNames(classes.icon, className)} {...restProps} />;
};
13 changes: 13 additions & 0 deletions src/internal/Icons/IconVolumeOff.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type {FC, SVGProps} from 'react';
import Icon from '@phosphor-icons/core/assets/fill/speaker-slash-fill.svg?react';
import classNames from 'classnames';

import classes from './Icon.module.css';

type Props = SVGProps<SVGSVGElement> & {
className?: string;
};

export const IconVolumeOff: FC<Props> = ({className, ...restProps}) => {
return <Icon className={classNames(classes.icon, className)} {...restProps} />;
};
9 changes: 9 additions & 0 deletions src/internal/Icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,12 @@ export {IconErrorOutline} from './IconErrorOutline.tsx';
export {IconSortOff} from './IconSortOff.tsx';
export {IconColumns} from './IconColumns.tsx';
export {IconNumeric} from './IconNumeric.tsx';
export {IconPlay} from './IconPlay.tsx';
export {IconPause} from './IconPause.tsx';
export {IconVolume} from './IconVolume.tsx';
export {IconVolumeOff} from './IconVolumeOff.tsx';
export {IconFullscreen} from './IconFullscreen.tsx';
export {IconPictureInPicture} from './IconPictureInPicture.tsx';
export {IconDownloadVideo} from './IconDownloadVideo.tsx';
export {IconVideo} from './IconVideo.tsx';
export {IconSpeed} from './IconSpeed.tsx';
2 changes: 2 additions & 0 deletions src/lib/InputRange/InputRange.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@
background-color: var(--thumb-color);
border: none;
cursor: grab;
height: var(--slider-height);
transition: background-color var(--kg-time-sm) ease-in-out;
width: var(--slider-width);
}

&:--hoverSelector {
Expand Down
1 change: 1 addition & 0 deletions src/lib/InputRange/InputRange.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const meta = {
step: 1,
scaleUnit: 'F',
disabled: false,
displayScale: true,
},
argTypes: {
value: {control: 'text'},
Expand Down
13 changes: 10 additions & 3 deletions src/lib/InputRange/InputRange.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ export type Props = DataAttributes &
prefix?: FC<{className?: string} & SVGProps<SVGSVGElement> & unknown>;
bars?: number;
scaleUnit?: string;
/**
* Enable to display scale below input
*/
displayScale?: boolean;
};

const createOptions = ({
Expand Down Expand Up @@ -72,6 +76,7 @@ export const InputRange = forwardRef<HTMLInputElement, Props>(
revalidateOnFormChange,
validation,
errorMessage,
displayScale,
...nativeProps
},
ref
Expand Down Expand Up @@ -143,9 +148,11 @@ export const InputRange = forwardRef<HTMLInputElement, Props>(
min={min}
max={max}
/>
<datalist id={scaleId} className={classes.scale}>
{createOptions({min: Number(min), max: Number(max), bars, scaleUnit})}
</datalist>
{displayScale && (
<datalist id={scaleId} className={classes.scale}>
{createOptions({min: Number(min), max: Number(max), bars, scaleUnit})}
</datalist>
)}
</div>
{/* TODO: add htmlFor when CSS vars hook supports it */}
<LocalRoot as="output" theme={theme} className={classes.output}>
Expand Down
24 changes: 24 additions & 0 deletions src/lib/Video/Video.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Meta, ArgTypes, Story, Canvas, Source, Markdown, Primary } from "@storybook/blocks";
import {Video} from './Video.tsx';
import * as VideoStories from "./Video.stories.tsx";

<Meta title="Components/Video" of={VideoStories} />

# Video

## Description

`Video` component plays provided video file using Video Embed element.

## Imports

<Markdown>{`
\`\`\`ts
import {Video} from 'koval-ui';
\`\`\`
`}</Markdown>

<Primary />

<ArgTypes of={Video}/>

Loading

0 comments on commit 4845f07

Please sign in to comment.