file-upload

Image upload

Image upload

Загрузка превью…

src/file-upload/c-file-upload-7.vue

<!--
  Оригинал реализует drag-and-drop/загрузку без композабла useFileUpload
  (свой useState/handleDrop). Диф снимает только начальное состояние —
  реальных файлов нет, поэтому интерактивная ветка (реальная загрузка,
  прогресс) не воспроизведена: `images`/`isDragging`/`errors` зафиксированы
  пустыми, как в react.tsx (см. комментарий кейса). Иконки — путь lucide
  "x"/"cloud-upload". `https://picsum.photos/...` заменён PIXEL.
-->
<script setup lang="ts">
import { formatBytes } from "@/composables/use-file-upload"
import { Button } from "@/components/ui/button"
import { Card, CardContent } from "@/components/ui/card"

const PIXEL = "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAUwAOw=="
const maxSize = 2 * 1024 * 1024

const visibleDefaultImages = [
  { id: "default-1", src: PIXEL, alt: "Product view 1" },
  { id: "default-2", src: PIXEL, alt: "Product view 2" },
  { id: "default-3", src: PIXEL, alt: "Product view 3" },
  { id: "default-4", src: PIXEL, alt: "Product view 4" },
]
</script>

<template>
  <div class="w-full max-w-4xl">
    <div class="mb-6">
      <div class="grid grid-cols-4 gap-2.5">
        <Card
          v-for="defaultImg in visibleDefaultImages"
          :key="defaultImg.id"
          class="bg-accent/50 group/item rounded-md relative flex shrink-0 items-center justify-center p-0 shadow-none"
        >
          <img :src="defaultImg.src" class="rounded-md h-[120px] w-full object-cover" :alt="defaultImg.alt" />
          <Button
            variant="outline"
            size="icon"
            class="absolute end-1 top-1 size-6 rounded-full opacity-0 shadow-sm group-hover/item:opacity-100 dark:bg-zinc-800 hover:dark:bg-zinc-700"
          >
            <svg
              xmlns="http://www.w3.org/2000/svg"
              width="24"
              height="24"
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
              stroke-linejoin="round"
              class="size-3.5"
            ><path d="M18 6 6 18" /><path d="m6 6 12 12" /></svg>
          </Button>
        </Card>
      </div>
    </div>

    <Card class="rounded-md border-dashed shadow-none transition-colors border-muted-foreground/25 hover:border-muted-foreground/50">
      <CardContent class="text-center">
        <div class="border-border mx-auto mb-3 flex size-[32px] items-center justify-center rounded-full border">
          <svg
            xmlns="http://www.w3.org/2000/svg"
            width="24"
            height="24"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
            stroke-linecap="round"
            stroke-linejoin="round"
            class="size-4"
          ><path d="M12 13v8" /><path d="M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242" /><path d="m8 17 4-4 4 4" /></svg>
        </div>
        <h3 class="text-2sm text-foreground mb-0.5 font-semibold">Choose a file or drag &amp; drop here.</h3>
        <span class="text-secondary-foreground mb-3 block text-xs font-normal">{{ `JPEG, PNG, up to ${formatBytes(maxSize)}.` }}</span>
        <Button size="sm">Browse File</Button>
      </CardContent>
    </Card>
  </div>
</template>

Установка

npx shadcn-vue@latest add https://revueui.rootapi.dev/r/c-file-upload-7.json

Зависимости реестра

Источник: порт из ReUI (Keenthemes, MIT)