// Rôle : fournit l'outil images avec import fichier/texte, collage, libellés et annotation rapide. import { useState } from "react"; import { Icon } from "../../../components/Icon.jsx"; import { moveItem, useGroupedReorder } from "../../../hooks/useGroupedReorder.js"; import { TextExchangeActions } from "./TextExchangeActions.jsx"; export function ImagesModule({ toolboxId, moduleId, context, editing, textExchangeOpen }) { const data = context.getModuleData(toolboxId, moduleId, { images: [] }); const textContent = context.moduleText?.images || {}; const [dragOver, setDragOver] = useState(false); const pastePlaceholder = textContent.pastePlaceholder || "Coller une image ici"; const { itemReorder, getItemProps, isItemDragging, isItemDropTarget, getDropPlacement } = useGroupedReorder({ namespace: "images", items: data.images, getItemId: (image) => image.id, getParentId: () => moduleId, orientation: "horizontal", onItemMove: (operation) => { context.setModuleData(toolboxId, moduleId, { images: moveItem(data.images, operation.sourceId, operation.targetId, operation.placement) }); }, hierarchy: { enabled: true, stickyParents: true } }); async function addFiles(files) { if (await context.addImageFiles(toolboxId, moduleId, files)) { setDragOver(false); } } function updateImage(imageId, patch) { context.setModuleData(toolboxId, moduleId, { images: data.images.map((image) => image.id === imageId ? { ...image, ...patch } : image) }); } return ( <> {editing && (
{ if (event.currentTarget.textContent.trim() === pastePlaceholder) event.currentTarget.textContent = ""; }} onBlur={(event) => { if (!event.currentTarget.textContent.trim()) event.currentTarget.textContent = pastePlaceholder; }} onPaste={(event) => { const files = [...(event.clipboardData?.items || [])] .filter((item) => item.type.startsWith("image/")) .map((item) => item.getAsFile()) .filter(Boolean); if (!files.length) return; event.preventDefault(); event.currentTarget.textContent = pastePlaceholder; addFiles(files); }} > {pastePlaceholder}
)} {textExchangeOpen && (
context.setModuleData(toolboxId, moduleId, nextData, "images")} />
)}
{data.images.map((image) => { const className = [ isItemDragging(image.id) ? "is-dragging" : "", isItemDropTarget(image.id) ? "is-drop-target" : "", getDropPlacement("item", image.id) === "after" ? "drop-after" : "" ].filter(Boolean).join(" "); return (
{editing ? ( updateImage(image.id, { label: event.target.value })} aria-label={textContent.labelAriaLabel || "Libellé de l'image"} /> ) : image.label ? (
{image.label}
) : null}
); })}
); }