Arjen Scherff-de Water
Creative Developer
Arjen is located at Netherlands
Choose a file from a searchable select
import { FileSearchableSelect } from "../inputs/FileSearchableSelect";
export default {
name: "fileAsset",
type: "object",
title: "File",
inputComponent: FileSearchableSelect,
fields: [
{
name: "name",
type: "string",
title: "Filename",
},
{
name: "url",
type: "string",
title: "URL",
},
],
};
import { PatchEvent, set, unset } from "part:@sanity/form-builder/patch-event";
import client from "part:@sanity/base/client";
import FormField from "part:@sanity/components/formfields/default";
import React, { useState, useEffect } from "react";
import SearchableSelect from "part:@sanity/components/selects/searchable";
export const FileSearchableSelect = React.forwardRef(
(
{ onFocus, onBlur, onChange, type, value, level, markers, readOnly },
ref
) => {
const [inputValue, setInputValue] = useState(null);
const [isFetching, setIsFetching] = useState(false);
const [hits, setHits] = useState([]);
const [files, setFiles] = useState([]);
useEffect(() => {
setIsFetching(true);
client
.fetch(
"*[_type == 'sanity.fileAsset'] { originalFilename, url, size } | order(originalFilename)"
)
.then((results) => {
setIsFetching(false);
setFiles(results);
});
}, []);
function handleChange({ props }) {
const { originalFilename, url } = props;
onChange(PatchEvent.from(set({ name: originalFilename, url })));
setInputValue(null);
}
function handleOpen() {
search("");
}
function handleBlur() {
onBlur();
}
function handleFocus() {
onFocus();
}
function handleSearch(query) {
search(query);
}
function handleClear() {
onChange(PatchEvent.from(unset()));
}
function formatSize(size) {
var kb = Math.round(size / 1000);
var mb = kb > 1000 ? size / 1000000 : null;
var roundedMb = mb ? Math.round(mb * 100) / 100 : null;
return roundedMb ? roundedMb + " mb" : kb + " kb";
}
function search(query) {
setInputValue(query);
setHits(
files
.filter(
({ originalFilename }) =>
originalFilename.toLowerCase().indexOf(query.toLowerCase()) > -1
)
.map(({ size, originalFilename, url }) => (
<div
style={{ display: "flex" }}
url={url}
originalFilename={originalFilename}
>
<div>{originalFilename}</div>
<div
style={{
fontSize: 11,
opacity: 0.75,
marginLeft: "auto",
flexShrink: 0,
whiteSpace: "nowrap",
}}
>
{formatSize(size)}
</div>
</div>
))
);
}
function renderItem(originalFilename) {
return originalFilename;
}
return (
<FormField
markers={markers}
label={type.title}
level={level}
description={type.description}
>
<SearchableSelect
placeholder="Type to search…"
title={inputValue}
onOpen={handleOpen}
onFocus={handleFocus}
onBlur={handleBlur}
onSearch={handleSearch}
onChange={handleChange}
onClear={handleClear}
value={value}
inputValue={inputValue === null ? value?.name : inputValue}
renderItem={renderItem}
isLoading={isFetching}
items={hits}
ref={ref}
readOnly={readOnly}
/>
{value?.url && (
<a
target="_blank"
href={value.url}
style={{
display: "block",
background: "whitesmoke",
padding: 6,
margin: "6px 0 0 0",
fontSize: ".75em",
border: "1px solid rgba(0,0,0,.1)",
color: "inherit",
}}
>
{value.url.replace("https://cdn.sanity.io", "")}
</a>
)}
</FormField>
);
}
);
This adds a searchable select with all files from the media library. This makes it easy to link to a previously uploaded file. Only uses files, doesn't include images.
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 bordersGet thumbnail and video by pasting vimeo/youtube url
Go to Vimeo/Youtube video id and thumbnail custom componentAdd a title between fields for some visual grouping
Go to Heading custom componentContent operations
Content backend


The only platform powering content operations
By Industry


Tecovas strengthens their customer connections
Build and Share

Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag store