Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New component: Video #225

Draft
wants to merge 4 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions components/video/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { Video } from './video';
export { VideoControl } from './video-control';
51 changes: 51 additions & 0 deletions components/video/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Video

The Video component allows you to easily add videos to your custom blocks without needing to manually worry about loading states etc. It renders a `<MediaPlaceholder />` component in place of the video if the id is not set and shows a spinner when the video is still loading.

## Usage

```js
import { Video } from '@10up/block-components';

function BlockEdit(props) {
const { attributes, setAttributes } = props;
const { videoId, focalPoint } = attributes;

function handlevideoSelect( video ) {
setAttributes({videoId: video.id});
}

return (
<Video
id={videoId}
className="my-video"
size="full"
onSelect={handlevideoSelect}
labels={{
title: 'Select Poster video',
instructions: 'Upload a media file or pick one from your media library.'
}}
/>
)
}
```

If you'd like to make an Inspector control for this video, use `VideoControl` instead:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add demonstration here.




##

> **Note**
> In order to get the same result as the GIF you also need to use the [`MediaToolbar`](https://github.com/10up/block-components/tree/develop/components/media-toolbar) component. It adds the Replace flow to the Blocks Toolbar.

## Props

| Name | Type | Default | Description |
| ---------- | ----------------- | -------- | -------------------------------------------------------------- |
| `id` | `number` | `null` | video ID |
| `onSelect` | `Function` | `null` | Callback that gets called with the new video when one is selected |
| `size` | `string` | `large` | Name of the video size to be displayed |
| `labels` | `object` | `{}` | Pass in an object of labels to be used by the `MediaPlaceholder` component under the hook. Allows the sub properties `title` and `instructions` |
| `canEditVideo` | `boolean` | `true` | whether or not the video can be edited by in the context its getting viewed. Controls whether a placeholder or upload controls should be shown when no video is present |
| `...rest` | `*` | `null` | any additional attributes you want to pass to the underlying `img` tag |
102 changes: 102 additions & 0 deletions components/video/video-control.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/**
* wraps the Video component with controls to allow use for uploads in the sidebar
*/

import { Video } from './video';
import { MediaPlaceholder, MediaUploadCheck, MediaUpload } from '@wordpress/block-editor';
import { Spinner, Placeholder, BaseControl, useBaseControlProps, Button } from '@wordpress/components';
import { __ } from '@wordpress/i18n';

const VideoControl = ( props ) => {
const {
id,
onSelect,
labels: {
title = __('Video upload'),
instructions = __('Choose a video')
},
canEditVideo = true
} = props;
const hasVideo = !!id;

const allowedTypes = [ 'video/webm', 'video/mp4' ];

const { baseControlProps, controlProps } = useBaseControlProps( props );

if ( !hasVideo && !canEditVideo ) {
return <Placeholder className="block-editor-media-placeholder" withIllustration />;
}

if ( !hasVideo && canEditVideo ) {
return (
<BaseControl
label={title}
help={instructions}
{ ...baseControlProps }
>
<MediaUploadCheck>
<MediaUpload
value={props.video}
onSelect={onSelect}
allowedTypes={allowedTypes}
mode="upload"
multiple={false}
title={title}
help={instructions}
render={ ({open}) => (
<Button variant="primary" onClick={open}>{__('Upload video (webm, mp4)')}</Button>
)}
{ ...controlProps }
/>
</MediaUploadCheck>
</BaseControl>
);
}

if ( hasVideo ) {
return (
<BaseControl
title={title}
{ ...baseControlProps }
>
<Video
id={id}
onSelect={onSelect}
labels={{ title: title, instructions: instructions }}
/>
<MediaUploadCheck>
<MediaUpload
value={id}
onSelect={onSelect}
allowedTypes={allowedTypes}
mode="upload"
multiple={false}
render={ ({open}) => (
<Button variant="secondary" onClick={open}>{__("Change video (webm, mp4)")}</Button>
)}
/>
</MediaUploadCheck>
</BaseControl>
);
}
}

VideoControl.defaultProps = {
labels: {
title: __('Video upload'),
instructions: __('Choose a video')
},
canEditVideo: true
}

VideoControl.propTypes = {
id: PropTypes.number.isRequired,
onSelect: PropTypes.func.isRequired,
labels: PropTypes.shape({
title: PropTypes.string,
instructions: PropTypes.string,
}),
canEditVideo: PropTypes.bool,
}

export { VideoControl };
57 changes: 57 additions & 0 deletions components/video/video.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { MediaPlaceholder } from '@wordpress/block-editor';
import { Spinner, Placeholder } from '@wordpress/components';

import { useMedia, PropTypes } from '@10up/block-components';

const Video = (props) => {
const {
id,
size = 'full',
onSelect,
labels = {},
canEditVideo = true,
className = '',
} = props;
const hasVideo = !!id;
const { media, isResolvingMedia } = useMedia(id);

if (!hasVideo && !canEditVideo) {
return <Placeholder className="block-editor-media-placeholder" withIllustration />;
}

if (!hasVideo && canEditVideo) {
return (
<MediaPlaceholder labels={labels} onSelect={onSelect} accept="video" multiple={false} />
);
}

if (isResolvingMedia) {
return <Spinner />;
}

const sourceUrl = media?.media_details?.sizes[size]?.source_url ?? media?.source_url;
const altText = media?.alt_text;

return <video controls src={sourceUrl} alt={altText} className={className} />;
};

Video.defaultProps = {
labels: {},
canEditVideo: true,
size: 'full',
className: '',
};

Video.propTypes = {
id: PropTypes.number.isRequired,
size: PropTypes.string,
className: PropTypes.string,
onSelect: PropTypes.func.isRequired,
labels: PropTypes.shape({
title: PropTypes.string,
instructions: PropTypes.string,
}),
canEditVideo: PropTypes.bool,
};

export { Video };
Loading