+
+
+ {canAdd && (
+ } onClick={() => setPickerOpen(true)}>
+ {kind === "image" ? t`Add Images` : t`Add Files`}
+
+ )}
+
+
+ {items.length === 0 ? (
+
+ ) : (
+
+ item._key)}
+ strategy={verticalListSortingStrategy}
+ >
+
+ {items.map((item, index) => (
+ handleRemove(item._key) : undefined}
+ />
+ ))}
+
+
+
+ )}
+
+
{}}
+ onSelectMany={handleAdd}
+ mimeTypeFilters={
+ allowedMimeTypes && allowedMimeTypes.length > 0
+ ? allowedMimeTypes
+ : kind === "image"
+ ? ["image/"]
+ : []
+ }
+ fieldId={fieldId}
+ hideUrlInput={kind === "file"}
+ mediaKind={kind}
+ title={t`Select ${label}`}
+ />
+ {required && items.length === 0 && (
+ {t`This field is required`}
+ )}
+
+ );
+}
+
+interface SortableMediaRowProps {
+ item: MultiMediaValue;
+ kind: "image" | "file";
+ sortKey: string;
+ index: number;
+ onRemove?: () => void;
+}
+
+function SortableMediaRow({ item, kind, sortKey, index, onRemove }: SortableMediaRowProps) {
+ const { t } = useLingui();
+ const [imageBroken, setImageBroken] = React.useState(false);
+ const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
+ id: sortKey,
+ });
+
+ const style = {
+ transform: CSS.Transform.toString(transform),
+ transition,
+ };
+
+ const isLocal = !item.provider || item.provider === "local";
+ const storageKey = typeof item.meta?.storageKey === "string" ? item.meta.storageKey : undefined;
+ const displayUrl =
+ item.previewUrl ||
+ item.src ||
+ (isLocal ? `/_emdash/api/media/file/${encodeURIComponent(storageKey ?? item.id)}` : undefined);
+ const name = item.filename || item.alt || item.id || t`Untitled`;
+
+ return (
+