Documentation/Guides

Fichiers et autres applications

Le glisser-déposer propre au navigateur, sous forme de glissements de la bibliothèque — des fichiers, des liens et du texte venus d'autres applications dans des cibles de dépôt et des listes qui leur font de la place, des items glissés hors de la page, et entre les fenêtres de votre application.

Modifier cette page

Cette page a été traduite par IA et peut contenir des inexactitudes. Lire l'original en anglais

Les glissements de la bibliothèque vivent dans la page. Le navigateur a son propre glisser-déposer, qui franchit les bords de la page : des fichiers depuis le bureau, un lien depuis un autre onglet, du texte depuis une autre application, et vos items glissés vers tous ces endroits. La bibliothèque prend aussi en charge ces glissements, comme des glissements du provider : les cibles s'allument, les listes font de la place, les événements et les textes pour les lecteurs d'écran sont les mêmes que d'habitude.

Live

Chargement de la démo…

<script setup lang="ts">
import { DnDProvider } from '@vue-dnd-kit/core';
import Board from './Board.vue';
</script>

<template>
  <DnDProvider>
    <Board />
  </DnDProvider>
</template>

Depuis l'extérieur de la page

Une cible accepte ces glissements avec external, qui dit ce qu'elle accepte. Les cibles sans cette option les ignorent.

Board.vue
const { items } = makeSortableList(grid, {
  items: cards,
  group: 'moodboard',
  strategy: 'grid',
  external: { files: 'image/*', links: true, text: true },
  createItem: fromOutside,
});
externalAccepte
filesDes fichiers : true n'importe lesquels, des types MIME et des extensions tels que <input accept> les lit ('image/*, .md'), ou une fonction interrogée fichier par fichier. Jamais les dossiers.
multiplefalse : un fichier à la fois. Un glissement de plusieurs fichiers est refusé.
linksDes liens (text/uri-list) : une adresse depuis un autre onglet, un lien d'une page.
textDu texte brut : une sélection depuis une autre application.
typesD'autres types MIME, exactement tels que les autres applications les proposent.

makeDroppable accepte la même option : une zone qui accepte une image d'avatar se trouve dans glisser-déposer.

Ce que transporte le glissement

Le navigateur garde pour lui les données d'un glissement jusqu'au dépôt. Tant que le glissement est tenu, la page apprend seulement quels types de données il transporte. active.external et e.external disent ce qui est connu :

Pendant le glissementAu dépôt
typesLes types MIME qu'il propose : Files, text/uri-list…Les mêmes
fileTypesUn type MIME par fichierLes mêmes
filesVideLes fichiers que la cible accepte, en File
urls, text, htmlVideSes liens, son texte, son HTML
getData(type)''Les données de n'importe quel type qu'il propose
readyfalsetrue

Dans une liste

Une liste lui fait de la place comme à un élément déplaçable simple : avec createItem, qui est appelé deux fois : pendant le glissement, pour l'item qui montre où il va, et au dépôt, avec les données, pour ce qui est inséré. Un tableau d'items est inséré en entier à cet endroit : une carte par image.

cards.ts
export const fromOutside = (active: Active): Card | Card[] | undefined => {
  const { external } = active;
  if (!external) return undefined;
  // While it is held: a tile that says what is coming.
  if (!external.ready) return { id: 'incoming', kind: 'incoming', label: incoming(external) };
  // At the drop: a card each.
  if (external.files.length) {
    return external.files.map((file) => ({ id: uid(), kind: 'image', src: URL.createObjectURL(file), name: file.name }));
  }
  if (external.urls.length) return external.urls.map((url) => ({ id: uid(), kind: 'link', url, title: host(url) }));
  const text = external.text.trim();
  return text ? { id: uid(), kind: 'note', text } : undefined;
};
  • La tuile d'arrivée est une ligne de votre liste comme une autre : la liste la rend, les lignes autour s'écartent de son chemin, onDrop reçoit les vrais items.
  • Les arbres acceptent aussi ces glissements, un nœud à la fois : un nœud dossier avec un enfant par fichier en contient plusieurs.
  • L'événement de dépôt a e.external avec les données, dans le onDrop de la liste comme dans celui des moniteurs.

Hors de la page

Avec native, un glissement d'item à la souris est le glissement propre au navigateur : il peut donc quitter la page, vers le bureau, un éditeur, un chat, un autre onglet.

Tile.vue
makeSortableItem(el, {
  item: () => props.card,
  native: { data: () => toOutside(props.card) },
});
cards.ts
case 'link':
  return { 'text/uri-list': card.url, 'text/plain': card.url };
case 'note':
  return { 'text/plain': card.text };
  • data donne l'item aux autres applications sous forme de types MIME et de texte : text/plain, text/uri-list, text/html. Lu au début du glissement. Sans elle, native: true transporte le label comme texte.
  • Sur la page, le glissement fonctionne comme n'importe quel autre : cibles, listes qui font de la place, dépôt. Le navigateur dessine l'image glissée à la place de l'overlay, et l'élément reste en place (transform reste null avec overlay: false).
  • Les glissements de l'item au toucher et au clavier restent ceux de la bibliothèque : le navigateur n'a pas de glissement à lui pour eux.
  • effect (effectAllowed) dit ce que l'endroit où il est déposé a le droit de faire : 'copyMove' par défaut. Un dépôt ailleurs termine le glissement avec droppedOutside, 'move', 'copy' ou 'link', dans onDragEnd. Un déplacement retire les items de leur liste ; une copie les laisse.

makeDraggable accepte native de la même façon.

Entre fenêtres

Un item avec native se transporte aussi lui-même : les listes de son groupe dans une autre fenêtre de votre application l'acceptent comme s'il venait de l'une de leurs propres listes. Ouvrez le moodboard dans une seconde fenêtre et faites-y glisser une carte.

  • Pendant le glissement, l'autre fenêtre a déjà l'item : sa liste le montre en place.
  • Au dépôt, il y entre, et ici il quitte sa liste (le dépôt était un déplacement). Maintenez Ctrl (Option sur Mac) pour le copier à la place.
  • Une liste avec createItem est aussi interrogée pour ces items, avec active.external.group défini et les items dans active.items[].item : renvoyez-les, ou des copies avec des clés de cette fenêtre. Sans createItem, ils entrent tels quels.
  • Les items voyagent en JSON : les dates deviennent des chaînes, les fonctions sont omises.

Limites

  • Les données n'arrivent qu'avec le dépôt, jamais avant : prévoyez sans elles l'item qui s'affiche pendant qu'un glissement est tenu.
  • Faire glisser des fichiers, c'est pour les utilisateurs de souris et de pavé tactile. Proposez aussi un <input type="file"> à côté de la zone.
  • Un seul provider de la page accepte les glissements venus de l'extérieur : le premier qui a une cible pour eux.
  • Dans Firefox, un item déplacé dans une autre liste pendant le glissement puis déposé dans une autre fenêtre n'est pas informé de ce dépôt : ici, il reste où il était.
  • Un item dont le JSON dépasse 16 Ko va quand même dans une autre fenêtre, mais cette fenêtre ne le montre qu'au dépôt.

L'API est dans makeDroppable et makeDraggable.