When building a custom side panel feel free to choose any React components you prefer. You can build your own one from scratch as well.
Here's a common use case however: display a grid of media file previews in the side panel (templates, images, assets, etc.). For this purpose you can leverage <ImagesGrid />
component.
How to use <ImagesGrid />
component?
<ImagesGrid />
is a React component that:
Displays an array of any items as images
Supports infinite scrolling API
Supports drag&drop from side panel into canvas
import { ImagesGrid } from 'polotno/side-panel/images-grid';
<ImagesGrid
images={[{ url: 'example.png' }, { url: 'example.png' }]}
getPreview={(item) => item.url}
onSelect={async (image, pos, element, event) => {
const width = 100;
const height = 100;
const x = (pos?.x || store.width / 2) - width / 2;
const y = (pos?.y || store.height / 2) - height / 2;
store.activePage?.addElement({
type: 'image',
src: image.url,
width,
height,
x,
y,
});
}}
isLoading={false}
loadMore={() => {}}
getCredit={(image) => <span>Photo by Anton</span>}
rowsNumber={2}
crossOrigin="anonymous"
itemHeight={'100px'}
error={true}
/>;
How to use useInfiniteAPI
hook?
In scenarios where an API is called to display a list of images within a side panel grid, various React tools are at your disposal. This includes utilizing fetch methods within hooks or leveraging any suitable library for the task. Additionally, Polotno provides the useInfiniteAPI
hook as a convenient option. The useInfiniteAPI
hook serves as a wrapper around the swr library, simplifying the process of fetching data.
import { useInfiniteAPI } from 'polotno/utils/use-api';
export const SidePanel = () => {
const { data, isLoading, loadMore, isReachingEnd, hasMore, reset, error } = useInfiniteAPI({
getAPI: ({ page, query }) => `https://example.com/api?page=${page}&query=${query}`,
defaultQuery: '',
timeout: 500,
getSize: (firstResult) => firstResult.total_pages,
fetchFunc: (url) => fetch(url).then((r) => r.json()),
});
});
How to drop elements from side panel into workspace?
If you prefer not to use <ImagesGrid />
component, you will have to handle drop&drop of DOM elements implementation. However, Polotno
has some tools to listen to drop event on the workspace. You can use this:
import { unstable_registerNextDomDrop } from 'polotno/config';
<img
draggable
src={url}
onDragStart={() => {
registerNextDomDrop((pos, element) => {
if (element && element.type === 'image') {
element.set({ src: url });
return;
}
store.activePage.addElement({
type: 'image',
src: url,
x: pos.x,
y: pos.y,
width: 100,
height: 100,
});
});
}}
onDragEnd={() => {
registerNextDomDrop(null);
}}
/>;