Documentação/Guias

Arquivos e outros apps

O arrastar e soltar do próprio navegador, como arrastes da biblioteca — arquivos, links e texto de outros apps para alvos de drop e listas que abrem espaço para eles, itens arrastados para fora da página, e entre janelas do seu app.

Editar esta página

Esta página foi traduzida por IA e pode conter imprecisões. Ler o original em inglês

Os arrastes da biblioteca vivem dentro da página. O navegador tem um arrastar e soltar próprio que atravessa as bordas da página: arquivos da área de trabalho, um link de outra aba, texto de outro app, e itens seus arrastados para todos esses lugares. A biblioteca também roda esses arrastes, como arrastes do provider: os alvos se acendem, as listas abrem espaço, os eventos e os textos do leitor de tela são os de sempre.

Live

Carregando a demo…

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

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

De fora da página

Um alvo aceita esses arrastes com external, dizendo o que aceita. Alvos sem ele os ignoram.

Board.vue
const { items } = makeSortableList(grid, {
  items: cards,
  group: 'moodboard',
  strategy: 'grid',
  external: { files: 'image/*', links: true, text: true },
  createItem: fromOutside,
});
externalAceita
filesArquivos: true qualquer um, tipos MIME e extensões como <input accept> os lê ('image/*, .md'), ou uma função consultada arquivo por arquivo. Pastas, nunca.
multiplefalse: um arquivo por vez. Um arraste de vários é recusado.
linksLinks (text/uri-list): um endereço de outra aba, um link de uma página.
textTexto simples: uma seleção de outro app.
typesOutros tipos MIME, exatamente como outros apps os oferecem.

makeDroppable aceita a mesma opção: uma zona que aceita uma imagem de avatar está em arrastar e soltar.

O que o arraste carrega

O navegador guarda os dados de um arraste para si até o drop. Enquanto o arraste continua, a página só fica sabendo que tipos de dados ele carrega. active.external e e.external dizem o que se sabe:

Durante o arrasteNo drop
typesOs tipos MIME que ele oferece: Files, text/uri-list…Os mesmos
fileTypesUm tipo MIME por arquivoOs mesmos
filesVazioOs arquivos que o alvo aceita, como objetos File
urls, text, htmlVazioOs seus links, o seu texto, o seu HTML
getData(type)''Os dados de qualquer tipo que ele oferece
readyfalsetrue

Em uma lista

Uma lista abre espaço para ele como para um draggable simples: com createItem, que é consultado duas vezes: durante o arraste, pelo item que mostra para onde ele vai, e no drop, com os dados, pelo que entra. Um array de itens insere todos naquele lugar: um card por imagem.

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;
};
  • O bloco que está chegando é uma linha da sua lista como qualquer outra: a lista o renderiza, as linhas em volta deslizam para sair do caminho dele, e onDrop recebe os itens reais.
  • Árvores também aceitam esses arrastes, um nó por vez: um nó de pasta com um filho por arquivo guarda vários.
  • O evento de drop tem e.external com os dados, no onDrop da lista como no dos monitores.

Para fora da página

Com native, um arraste de um item com o mouse é o arraste do próprio navegador, então ele pode sair da página: para a área de trabalho, para um editor, um chat, outra aba.

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 entrega o item a outros apps como tipos MIME e texto: text/plain, text/uri-list, text/html. É lido quando o arraste começa. Sem ele, native: true carrega o label como texto.
  • Na página, o arraste funciona como qualquer outro: alvos, listas que abrem espaço, o drop. O navegador desenha a imagem arrastada em vez do overlay, e o elemento fica no lugar (transform continua null com overlay: false).
  • Arrastes do item por toque e por teclado continuam sendo da biblioteca: o navegador não tem um arraste próprio para eles.
  • effect (effectAllowed) diz o que o lugar onde ele é solto pode fazer: 'copyMove' por padrão. Um drop em outro lugar termina o arraste com droppedOutside, 'move', 'copy' ou 'link', em onDragEnd. Uma movimentação tira os itens da lista deles; uma cópia os mantém.

makeDraggable aceita native da mesma forma.

Entre janelas

Um item com native também carrega a si mesmo: as listas do grupo dele em outra janela do seu app o aceitam como se viesse de uma das próprias listas delas. Abra o moodboard em uma segunda janela e arraste um card de uma para a outra.

  • Enquanto o arraste continua, a outra janela já tem o item: a lista dela o mostra na posição.
  • No drop, ele entra, e aqui ele sai da sua lista (o drop foi uma movimentação). Segure Ctrl (Option no Mac) para copiá-lo em vez disso.
  • Uma lista com createItem também é consultada para esses itens, com active.external.group definido e os itens em active.items[].item: retorne-os, ou cópias com keys daquela janela. Sem createItem, eles entram como estão.
  • Os itens viajam como JSON: datas viram strings, funções ficam de fora.

Limites

  • Os dados chegam só com o drop, nunca antes: planeje o item que aparece durante o arraste sem eles.
  • Arrastar arquivos é para quem usa mouse e trackpad. Ofereça também um <input type="file"> ao lado da zona.
  • Um único provider da página aceita arrastes de fora: o primeiro que tiver um alvo para eles.
  • No Firefox, um item movido para outra lista durante o arraste e depois solto em outra janela não fica sabendo desse drop: aqui ele continua onde estava.
  • Um item cujo JSON passa de 16 KB ainda vai para outra janela, mas essa janela só o mostra no drop.

A API está em makeDroppable e makeDraggable.