Documentación/Guías

Archivos y otras apps

El arrastrar y soltar propio del navegador, como arrastres de la biblioteca — archivos, enlaces y texto de otras apps en destinos de drop y listas que les hacen sitio, ítems arrastrados fuera de la página, y entre ventanas de tu app.

Editar esta página

Esta página la ha traducido una IA y puede contener imprecisiones. Leer el original en inglés

Los arrastres de la biblioteca viven dentro de la página. El navegador tiene un arrastrar y soltar propio que cruza los bordes de la página: archivos desde el escritorio, un enlace desde otra pestaña, texto desde otra app, y tus ítems arrastrados hacia todos esos sitios. La biblioteca también gestiona esos arrastres, como arrastres del provider: los destinos se iluminan, las listas hacen sitio, los eventos y los textos para lectores de pantalla son los de siempre.

Live

Cargando la demo…

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

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

Desde fuera de la página

Un destino acepta esos arrastres con external, que dice lo que acepta. Los destinos sin esta opción los ignoran.

Board.vue
const { items } = makeSortableList(grid, {
  items: cards,
  group: 'moodboard',
  strategy: 'grid',
  external: { files: 'image/*', links: true, text: true },
  createItem: fromOutside,
});
externalAcepta
filesArchivos: true cualquiera, tipos MIME y extensiones tal como los lee <input accept> ('image/*, .md'), o una función a la que se pregunta archivo por archivo. Carpetas nunca.
multiplefalse: un archivo cada vez. Un arrastre de varios se rechaza.
linksEnlaces (text/uri-list): una dirección desde otra pestaña, un enlace de una página.
textTexto plano: una selección desde otra app.
typesOtros tipos MIME, exactamente como los ofrecen otras apps.

makeDroppable acepta la misma opción: una zona que acepta una imagen de avatar está en arrastrar y soltar.

Lo que lleva el arrastre

El navegador se guarda los datos de un arrastre hasta que se suelta. Mientras se mantiene, la página solo sabe qué tipos de datos lleva. active.external y e.external dicen lo que se sabe:

Mientras se mantieneAl soltar
typesLos tipos MIME que ofrece: Files, text/uri-list…Los mismos
fileTypesUn tipo MIME por archivoLos mismos
filesVacíoLos archivos que acepta el destino, como File
urls, text, htmlVacíoSus enlaces, su texto, su HTML
getData(type)''Los datos de cualquier tipo que ofrezca
readyfalsetrue

En una lista

Una lista le hace sitio como a un elemento arrastrable simple: con createItem, al que se le pregunta dos veces: mientras se mantiene el arrastre, por el ítem que muestra adónde va, y al soltar, con los datos, por lo que entra. Un array de ítems se inserta entero en ese sitio: una tarjeta por imagen.

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 ficha de lo que llega es una fila de tu lista como cualquier otra: la lista la renderiza, las filas de alrededor se apartan de su camino, onDrop recibe los ítems reales.
  • Los árboles también aceptan estos arrastres, un nodo cada vez: un nodo carpeta con un hijo por archivo admite varios.
  • El evento del drop tiene e.external con los datos, tanto en el onDrop de la lista como en el de los monitores.

Fuera de la página

Con native, un arrastre de un ítem con el ratón es el arrastre propio del navegador, así que puede salir de la página: al escritorio, a un editor, a un chat, a otra pestaña.

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 da a otras apps el ítem como tipos MIME y texto: text/plain, text/uri-list, text/html. Se lee cuando empieza el arrastre. Sin ella, native: true lleva el label como texto.
  • En la página, el arrastre funciona como cualquier otro: destinos, listas que hacen sitio, el drop. El navegador dibuja la imagen arrastrada en lugar del overlay, y el elemento se queda en su sitio (transform sigue siendo null con overlay: false).
  • Los arrastres táctiles y con teclado del ítem siguen siendo de la biblioteca: el navegador no tiene un arrastre propio para ellos.
  • effect (effectAllowed) dice qué puede hacer el sitio donde se suelta: 'copyMove' por defecto. Un drop en otro sitio termina el arrastre con droppedOutside, 'move', 'copy' o 'link', en onDragEnd. Un movimiento saca los ítems de su lista; una copia los deja.

makeDraggable acepta native de la misma forma.

Entre ventanas

Un ítem con native también se lleva a sí mismo: las listas de su grupo en otra ventana de tu app lo aceptan como si viniera de una de sus propias listas. Abre el moodboard en una segunda ventana y arrastra una tarjeta de una a otra.

  • Mientras se mantiene el arrastre, la otra ventana ya tiene el ítem: su lista lo muestra en su sitio.
  • Al soltar, entra allí, y aquí sale de su lista (el drop fue un movimiento). Mantén Ctrl (Option en Mac) para copiarlo en su lugar.
  • A una lista con createItem también se le pregunta por estos ítems, con active.external.group definido y los ítems en active.items[].item: devuélvelos, o copias con claves de esa ventana. Sin createItem, entran tal cual.
  • Los ítems viajan como JSON: las fechas se vuelven cadenas, las funciones se descartan.

Límites

  • Los datos llegan solo con el drop, nunca antes: planifica sin ellos el ítem que se muestra mientras se mantiene un arrastre.
  • Arrastrar archivos es cosa de quien usa ratón o trackpad. Ofrece también un <input type="file"> junto a la zona.
  • Un único provider de la página acepta arrastres de fuera: el primero que tenga un destino para ellos.
  • En Firefox, un ítem movido a otra lista durante el arrastre y luego soltado en otra ventana no se entera de ese drop: aquí se queda donde estaba.
  • Un ítem cuyo JSON pasa de 16 KB sigue yendo a otra ventana, pero esa ventana solo lo muestra al soltar.

La API está en makeDroppable y makeDraggable.