(feat) Option to insert multiple images
In my projects I always use the sanity-plugin-media, so thanks for creating it! In many of these projects I also run into that I want to insert multiple images at once in an image array (ie for a carousel or gallery). Searching around, I found that more people have this issue, see the Github issues below or the Sanity Slack:
- https://github.com/sanity-io/sanity/issues/4483
- https://github.com/sanity-io/sanity/issues/1804
- https://github.com/sanity-io/sanity-plugin-media/issues/85
In this pull request, I add the option to insert multiple images at once. By adding the selectionType 'multiple' option, you can determine that the asset source should pass multiple assets. This is not officially supported, but I figured that is where Sanity wishes to go with the selectionType property, since it currently only supports "single".
In this PR I support "multiple", without breaking- or changing any of the current functionality. If you do not pass the selectionType="multiple" it will work the same.
To make this work in a project, you have to create a custom component that creates a AssetSourceComponent with the property selectionType set to multiple. I will pass mine as an example so you can see how this works:
'use client';
import { AssetFromSource, StringInputProps, set, useFormBuilder } from 'sanity';
import { Button, Stack, Text } from '@sanity/ui';
import { FaRegImages } from 'react-icons/fa';
import React, { Fragment, MouseEventHandler, useCallback, useMemo, useState } from 'react';
export const MultipleImagesInputComponent = (properties: StringInputProps) => {
const { onChange, value, renderDefault } = properties;
const formBuilder = useFormBuilder();
const [showAssetSource, setShowAssetSource] = useState(false);
// I would love for this not to use internal but it is currently the only way I think.
const AssetSourceComponent = useMemo(
() => formBuilder?.__internal?.image?.assetSources[0]?.component,
[formBuilder?.__internal?.image?.assetSources]
);
const handleAssetSourceClosed = useCallback(() => {
setShowAssetSource(false);
}, []);
const handleSelectAssetFromSource = useCallback(
(assetsFromSource: AssetFromSource[]) => {
try {
const assetReferences = assetsFromSource.map((asset) => ({
_key: randomKey(),
_type: 'image',
asset: {
_ref: asset.value,
_type: 'reference',
},
}));
const newValue = [...(value || []), ...assetReferences];
onChange(set(newValue));
} catch (error) {
console.error(error);
} finally {
setShowAssetSource(false);
}
},
[onChange, value]
);
const onMultipleImagesClick: MouseEventHandler<HTMLButtonElement> = useCallback(() => {
setShowAssetSource(true);
}, []);
return (
<Fragment>
<Stack space={4}>
{renderDefault(properties)}
<Text size={2} muted align="center">
๐ก To upload multiple images, simply drag them on the list above.
</Text>
<Button
onClick={onMultipleImagesClick}
mode="ghost"
icon={FaRegImages}
text="Add multiple images from media"
/>
</Stack>
{showAssetSource && !!AssetSourceComponent ? (
<AssetSourceComponent
accept="image/*"
assetType="image"
onClose={handleAssetSourceClosed}
onSelect={handleSelectAssetFromSource}
selectedAssets={[]}
selectionType="multiple" // This is where the magic happens
/>
) : undefined}
</Fragment>
);
};
function randomKey() {
return Math.random().toString(36).slice(2);
}
I hope you will find this functionality useful. If there is a better way to achieve what I'm trying to do I love to hear that as well. Searching around, I found many people with this wish, but no solution, therefore I created this PR.
@robinpyon I'm not sure if you are the right person to tag, if not, could you point me in the right direction? I haven't had a response from any of the maintainers on this PR in 2 weeks and would love to hear your thoughts.
@kmelve I haven't heard anything on this PR for a month now... Do you know who I have to connect to this?
Hi @dennispassway โย thanks for your work and contribution here! We're definitively interested in looking at merging this; hopefully we'll find time to get to it over the next couple of weeks ๐
It would be so awesome to have this! ๐๐ผ It's something I get asked about on every project I build.
Wondering what is blocking this for the last 6 months? It seems there is a lot of interest for such a feature.
Hi @kmelve ! This has been stale for a while now. I understand you guys have lots to do, but wondering if you could tell if I can do anything to help get this merged?
Would love to see this feature integrated, please!
@kmelve this is not happening anymore is it? ๐คฃ
For those who really want this, i published my fork on npm and am using that in my projects until this or something similar to this is merged: https://www.npmjs.com/package/@dennispassway/sanity-plugin-media
Thanks @dennispassway , I really need this! Would really appreciate it if @kmelve would take a look and merge ๐๐ผ