Arjen Scherff-de Water
Creative Developer
Arjen is located at Netherlands
Get thumbnail and video by pasting vimeo/youtube url
import { PatchEvent, set, unset } from "part:@sanity/form-builder/patch-event";
import React, { useState } from "react";
import getVideoId from "get-video-id";
import { withDocument } from "part:@sanity/form-builder";
import { nanoid } from "nanoid";
import { TextInput, Stack, Button } from "@sanity/ui";
import { AddIcon } from "@sanity/icons";
const VideoIdFieldComponent = (props, ref) => {
const { onChange, value } = props;
const [newDoc, setNewDoc] = useState<{
id: string;
service: string;
thumbnail: string;
url: string;
}>(value || null);
const createPatchFrom = (value: any) =>
PatchEvent.from(value === "" ? unset() : set(value));
async function getThumbnail({ id, service }) {
if (service === "youtube") {
return `https://img.youtube.com/vi/${id}/mqdefault.jpg`;
}
if (service === "vimeo") {
const response = await fetch(
`https://vimeo.com/api/oembed.json?url=https://player.vimeo.com/video/${id}`
);
const json = await response.json();
return json.thumbnail_url.split("_")[0] + "_320x180";
}
return null;
}
async function onUrlChange(e) {
const url = e.target.value;
if (url.trim().length) {
const { id, service } = getVideoId(url);
const thumbnail = await getThumbnail({ id, service });
setNewDoc({ url, id, service, thumbnail });
} else {
setNewDoc(null);
}
}
function save() {
onChange(
createPatchFrom({
_key: nanoid(),
_type: "videoId",
...newDoc,
})
);
}
return (
<Stack space={3}>
<TextInput
type="text"
onChange={onUrlChange}
ref={ref}
value={newDoc?.url}
/>
{newDoc?.thumbnail && <img src={newDoc.thumbnail} />}
<Button
text={`Create`}
fontSize={2}
icon={AddIcon}
padding={3}
tone="positive"
onClick={save}
/>
</Stack>
);
};
export const VideoIdField = withDocument(
React.forwardRef(VideoIdFieldComponent)
);
import { VideoIdField } from "../inputs/VideoIdField";
import React from "react";
export default {
type: "object",
name: "videoId",
title: "Video ID",
inputComponent: VideoIdField,
fields: [
{
type: "string",
name: "url",
title: "Video URL",
description: "A URL to a vimeo or youtube video",
},
{
type: "string",
name: "id",
title: "Video ID",
description: "Auto generated",
readOnly: true,
},
{
type: "string",
name: "service",
title: "Service",
description: "Auto generated",
readOnly: true,
},
{
type: "string",
name: "thumbnail",
title: "Thumbnail",
description: "Auto generated",
readOnly: true,
},
],
preview: {
select: {
id: "id",
service: "service",
thumbnail: "thumbnail",
},
prepare({ service = "", thumbnail }) {
return {
title: `video ${service}`,
media: () => (thumbnail ? <img src={thumbnail} /> : null),
};
},
},
};
Youtube/Vimeo only for now, can be extended to be used with other services. Needs nanoid and get-video-id from npm.
Creative Developer
Recent studio styling has borders around icons in the desk structure. Here's a snippet to remove those.
Go to Remove studio desk icon bordersAdd a title between fields for some visual grouping
Go to Heading custom componentChoose a file from a searchable select
Go to File Searchable Select