By default, to add new assets to the Media Area through the interface, you can upload files from your computer. But plugins can define custom asset sources to allow contributors to upload assets from external providers.
For example, the Unsplash plugin in our Marketplace allows to upload royalty-free high-resolution images:
Within a plugin you can define the assetSources
hook to expose new asset sources. Every source must specify an internal ID, and a name and a representative icon that will be shown in the interface.
import { connect } from 'datocms-plugin-sdk';connect({assetSources() {return [{id: 'unsplash',name: 'Unsplash',icon: {type: 'svg',viewBox: '0 0 448 512',content:'<path fill="currentColor" d="M448,230.17V480H0V230.17H141.13V355.09H306.87V230.17ZM306.87,32H141.13V156.91H306.87Z" class=""></path>',},modal: {width: 'm',},},];},});
When the user selects the custom source, a modal will be opened with the size you specified, and the renderAssetSource
hook will be called. Inside of this hook we initialize React and render a custom component called AssetBrowser
, passing down as a prop the second ctx
argument, which provides a series of information and methods for interacting with the main application:
import { connect } from 'datocms-plugin-sdk';connect({assetSources() {return [{...}];},renderAssetSource(sourceId: string, ctx: RenderAssetSourceCtx) {render(<AssetBrowser ctx={ctx} />);},});
As we just saw, a plugin might offer different asset sources, so we can use the sourceId
argument to know which one we are requested to render, and write a specific React component for each of them.
import { Canvas, RenderAssetSourceCtx } from 'datocms-react-ui';type PropTypes = {ctx: RenderAssetSourceCtx;};function AssetBrowser({ ctx }: PropTypes) {return (<Canvas ctx={ctx}>Hello from the sidebar!</Canvas>);}
It is important to wrap the content inside the Canvas
component, so that the iframe will continuously auto-adjust its size based on the content we're rendering, and to give our app the look and feel of the DatoCMS web app.
We can use this component to render whatever we want. The important thing is to call the ctx.select
method to communicate to the main DatoCMS app the selected asset URL:
import { ButtonLink } from 'datocms-react-ui';function AssetBrowser({ ctx }: PropTypes) {const handleSelect = () => {ctx.select({resource: {url: 'https://unsplash.com/photos/yf8qPXQFDJE',filename: `sky.jpg`,},});}return (<Canvas ctx={ctx}><Button onClick={handleSelect}>Select</Button></Canvas>);}
If you're generating your asset on the fly (ie. by rendering on a canvas), instead of a regular URL you can also pass a base64-encoded data URI:
ctx.select({resource: {base64: 'data:image/png;base64,PD94bWwgd..',filename: `generated-image.png`,},});
You can also optionally specify some metadata to associate with the newly created upload:
ctx.select({resource: {url:'https://images.unsplash.com/photo-1416339306562-f3d12fefd36f',filename: 'man-drinking-coffee.jpg',},copyright: 'Royalty free (Unsplash)',author: 'Jeff Sheldon',notes: 'A man drinking a coffee',tags: ['man', 'coffee'],});