@wordpress/block-library
Version:
Block library for the WordPress editor.
336 lines (335 loc) • 11.1 kB
JavaScript
/**
* WordPress dependencies
*/
import { __, _x, sprintf } from '@wordpress/i18n';
import { NavigableMenu, MenuItem, FormFileUpload, MenuGroup, ToolbarGroup, ToolbarButton, Dropdown, Button, TextControl, SelectControl, ToggleControl, __experimentalGrid as Grid, __experimentalHStack as HStack, __experimentalVStack as VStack, privateApis as componentsPrivateApis } from '@wordpress/components';
import { MediaUpload, MediaUploadCheck, store as blockEditorStore } from '@wordpress/block-editor';
import { store as noticesStore } from '@wordpress/notices';
import { upload, media } from '@wordpress/icons';
import { useSelect, useDispatch } from '@wordpress/data';
import { useState, useRef, useEffect } from '@wordpress/element';
import { getFilename } from '@wordpress/url';
/**
* Internal dependencies
*/
import { unlock } from '../lock-unlock';
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
const {
Badge
} = unlock(componentsPrivateApis);
const ALLOWED_TYPES = ['text/vtt'];
const DEFAULT_KIND = 'subtitles';
const KIND_OPTIONS = [{
label: __('Subtitles'),
value: 'subtitles'
}, {
label: __('Captions'),
value: 'captions'
}, {
label: __('Descriptions'),
value: 'descriptions'
}, {
label: __('Chapters'),
value: 'chapters'
}, {
label: __('Metadata'),
value: 'metadata'
}];
function TrackList({
tracks,
onEditPress
}) {
const content = tracks.map((track, index) => {
return /*#__PURE__*/_jsxs(HStack, {
className: "block-library-video-tracks-editor__track-list-track",
children: [/*#__PURE__*/_jsx("span", {
children: track.label
}), /*#__PURE__*/_jsxs(HStack, {
justify: "flex-end",
children: [track.default && /*#__PURE__*/_jsx(Badge, {
children: __('Default')
}), /*#__PURE__*/_jsx(Button, {
__next40pxDefaultSize: true,
variant: "tertiary",
onClick: () => onEditPress(index),
"aria-label": sprintf(/* translators: %s: Label of the video text track e.g: "French subtitles". */
_x('Edit %s', 'text tracks'), track.label),
children: __('Edit')
})]
})]
}, track.src);
});
return /*#__PURE__*/_jsx(MenuGroup, {
label: __('Text tracks'),
className: "block-library-video-tracks-editor__track-list",
children: content
});
}
function SingleTrackEditor({
track,
onChange,
onClose,
onRemove,
allowSettingDefault
}) {
const {
src = '',
label = '',
srcLang = '',
kind = DEFAULT_KIND,
default: isDefaultTrack = false
} = track;
const fileName = src.startsWith('blob:') ? '' : getFilename(src) || '';
return /*#__PURE__*/_jsxs(VStack, {
className: "block-library-video-tracks-editor__single-track-editor",
spacing: "4",
children: [/*#__PURE__*/_jsx("span", {
className: "block-library-video-tracks-editor__single-track-editor-edit-track-label",
children: __('Edit track')
}), /*#__PURE__*/_jsxs("span", {
children: [__('File'), ": ", /*#__PURE__*/_jsx("b", {
children: fileName
})]
}), /*#__PURE__*/_jsxs(Grid, {
columns: 2,
gap: 4,
children: [/*#__PURE__*/_jsx(TextControl, {
__next40pxDefaultSize: true,
__nextHasNoMarginBottom: true,
onChange: newLabel => onChange({
...track,
label: newLabel
}),
label: __('Label'),
value: label,
help: __('Title of track')
}), /*#__PURE__*/_jsx(TextControl, {
__next40pxDefaultSize: true,
__nextHasNoMarginBottom: true,
onChange: newSrcLang => onChange({
...track,
srcLang: newSrcLang
}),
label: __('Source language'),
value: srcLang,
help: __('Language tag (en, fr, etc.)')
})]
}), /*#__PURE__*/_jsxs(VStack, {
spacing: "4",
children: [/*#__PURE__*/_jsx(SelectControl, {
__next40pxDefaultSize: true,
__nextHasNoMarginBottom: true,
className: "block-library-video-tracks-editor__single-track-editor-kind-select",
options: KIND_OPTIONS,
value: kind,
label: __('Kind'),
onChange: newKind => {
onChange({
...track,
kind: newKind
});
}
}), /*#__PURE__*/_jsx(ToggleControl, {
__next40pxDefaultSize: true,
__nextHasNoMarginBottom: true,
label: __('Set as default track'),
checked: isDefaultTrack,
disabled: !allowSettingDefault,
onChange: defaultTrack => {
onChange({
...track,
default: defaultTrack
});
}
}), /*#__PURE__*/_jsxs(HStack, {
className: "block-library-video-tracks-editor__single-track-editor-buttons-container",
children: [/*#__PURE__*/_jsx(Button, {
__next40pxDefaultSize: true,
isDestructive: true,
variant: "link",
onClick: onRemove,
children: __('Remove track')
}), /*#__PURE__*/_jsx(Button, {
__next40pxDefaultSize: true,
variant: "primary",
onClick: () => {
const changes = {};
let hasChanges = false;
if (label === '') {
changes.label = __('English');
hasChanges = true;
}
if (srcLang === '') {
changes.srcLang = 'en';
hasChanges = true;
}
if (track.kind === undefined) {
changes.kind = DEFAULT_KIND;
hasChanges = true;
}
if (hasChanges) {
onChange({
...track,
...changes
});
}
onClose();
},
children: __('Apply')
})]
})]
})]
});
}
export default function TracksEditor({
tracks = [],
onChange
}) {
const {
createNotice
} = useDispatch(noticesStore);
const mediaUpload = useSelect(select => {
return select(blockEditorStore).getSettings().mediaUpload;
}, []);
const [trackBeingEdited, setTrackBeingEdited] = useState(null);
const dropdownPopoverRef = useRef();
const handleTrackSelect = ({
title,
url
}) => {
if (tracks.some(track => track.src === url)) {
createNotice('error', __('This track already exists.'), {
isDismissible: true,
type: 'snackbar'
});
return;
}
const trackIndex = tracks.length;
onChange([...tracks, {
label: title || '',
src: url
}]);
setTrackBeingEdited(trackIndex);
};
useEffect(() => {
dropdownPopoverRef.current?.focus();
}, [trackBeingEdited]);
if (!mediaUpload) {
return null;
}
return /*#__PURE__*/_jsx(Dropdown, {
contentClassName: "block-library-video-tracks-editor",
focusOnMount: true,
popoverProps: {
ref: dropdownPopoverRef
},
renderToggle: ({
isOpen,
onToggle
}) => {
const handleOnToggle = () => {
if (!isOpen) {
// When the Popover opens make sure the initial view is
// always the track list rather than the edit track UI.
setTrackBeingEdited(null);
}
onToggle();
};
return /*#__PURE__*/_jsx(ToolbarGroup, {
children: /*#__PURE__*/_jsx(ToolbarButton, {
"aria-expanded": isOpen,
"aria-haspopup": "true",
onClick: handleOnToggle,
children: __('Text tracks')
})
});
},
renderContent: () => {
if (trackBeingEdited !== null) {
return /*#__PURE__*/_jsx(SingleTrackEditor, {
track: tracks[trackBeingEdited],
onChange: newTrack => {
const newTracks = [...tracks];
newTracks[trackBeingEdited] = newTrack;
onChange(newTracks);
},
onClose: () => setTrackBeingEdited(null),
onRemove: () => {
onChange(tracks.filter((_track, index) => index !== trackBeingEdited));
setTrackBeingEdited(null);
},
allowSettingDefault: !tracks.some(track => track.default) || tracks[trackBeingEdited].default
});
}
return /*#__PURE__*/_jsxs(_Fragment, {
children: [tracks.length === 0 && /*#__PURE__*/_jsxs("div", {
className: "block-library-video-tracks-editor__tracks-informative-message",
children: [/*#__PURE__*/_jsx("h2", {
className: "block-library-video-tracks-editor__tracks-informative-message-title",
children: __('Text tracks')
}), /*#__PURE__*/_jsx("p", {
className: "block-library-video-tracks-editor__tracks-informative-message-description",
children: __('Tracks can be subtitles, captions, chapters, or descriptions. They help make your content more accessible to a wider range of users.')
})]
}), /*#__PURE__*/_jsxs(NavigableMenu, {
children: [/*#__PURE__*/_jsx(TrackList, {
tracks: tracks,
onEditPress: setTrackBeingEdited
}), /*#__PURE__*/_jsxs(MenuGroup, {
className: "block-library-video-tracks-editor__add-tracks-container",
label: __('Add tracks'),
children: [/*#__PURE__*/_jsx(MediaUpload, {
onSelect: handleTrackSelect,
allowedTypes: ALLOWED_TYPES,
render: ({
open
}) => /*#__PURE__*/_jsx(MenuItem, {
icon: media,
onClick: open,
children: __('Open Media Library')
})
}), /*#__PURE__*/_jsx(MediaUploadCheck, {
children: /*#__PURE__*/_jsx(FormFileUpload, {
onChange: event => {
const files = event.target.files;
const trackIndex = tracks.length;
mediaUpload({
allowedTypes: ALLOWED_TYPES,
filesList: files,
onFileChange: ([{
url
}]) => {
const newTracks = [...tracks];
if (!newTracks[trackIndex]) {
newTracks[trackIndex] = {};
}
newTracks[trackIndex] = {
...tracks[trackIndex],
src: url
};
onChange(newTracks);
setTrackBeingEdited(trackIndex);
}
});
},
accept: ".vtt,text/vtt",
render: ({
openFileDialog
}) => {
return /*#__PURE__*/_jsx(MenuItem, {
icon: upload,
onClick: () => {
openFileDialog();
},
children: _x('Upload', 'verb')
});
}
})
})]
})]
})]
});
}
});
}
//# sourceMappingURL=tracks-editor.js.map