sortable

Sortable image gallery grid with frame

Sortable image gallery grid with frame

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

src/sortable/c-sortable-7.vue

<!--
  Расхождение с апстримом: `IconPlaceholder` заменена инлайновым `<svg>`
  (lucide-react v0.545.0 "grip-vertical"/"image") — см. docs/PORTING.md §5.
-->
<script setup lang="ts">
import { ref } from "vue"
import { Frame, FrameDescription, FrameHeader, FramePanel, FrameTitle } from "@/components/reui/frame"
import { Sortable, SortableItem, SortableItemHandle } from "@/components/reui/sortable"

interface GalleryImage {
  id: string
  name: string
  dimensions: string
  size: string
}

const images = ref<GalleryImage[]>([
  { id: "1", name: "hero-banner.jpg", dimensions: "1920×1080", size: "2.4 MB" },
  { id: "2", name: "product-shot.png", dimensions: "800×600", size: "1.8 MB" },
  { id: "3", name: "team-photo.jpg", dimensions: "1200×800", size: "3.2 MB" },
  { id: "4", name: "logo-dark.svg", dimensions: "240×60", size: "12 KB" },
  { id: "5", name: "og-image.png", dimensions: "1200×630", size: "890 KB" },
  { id: "6", name: "favicon.ico", dimensions: "32×32", size: "4 KB" },
])

function getItemValue(item: GalleryImage) {
  return item.id
}
</script>

<template>
  <div class="mx-auto w-full max-w-md">
    <Frame spacing="xs">
      <FrameHeader>
        <FrameTitle>Media Library</FrameTitle>
        <FrameDescription>Drag to reorder display priority</FrameDescription>
      </FrameHeader>
      <FramePanel class="p-2!">
        <Sortable
          v-model:value="images"
          :get-item-value="getItemValue"
          strategy="grid"
          class="grid grid-cols-3 gap-2"
        >
          <SortableItem v-for="image in images" :key="image.id" :value="image.id">
            <div class="bg-muted group rounded-lg relative flex flex-col items-center justify-center gap-2 border p-4">
              <SortableItemHandle class="text-muted-foreground hover:text-foreground absolute top-1.5 right-1.5 opacity-0 transition-opacity group-hover:opacity-100">
                <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="lucide lucide-grip-vertical size-3.5">
                  <circle cx="9" cy="12" r="1" />
                  <circle cx="9" cy="5" r="1" />
                  <circle cx="9" cy="19" r="1" />
                  <circle cx="15" cy="12" r="1" />
                  <circle cx="15" cy="5" r="1" />
                  <circle cx="15" cy="19" r="1" />
                </svg>
              </SortableItemHandle>
              <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="lucide lucide-image text-muted-foreground size-5">
                <rect width="18" height="18" x="3" y="3" rx="2" ry="2" />
                <circle cx="9" cy="9" r="2" />
                <path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" />
              </svg>
              <div class="w-full text-center">
                <p class="truncate text-xs font-medium">{{ image.name }}</p>
                <p class="text-muted-foreground text-[10px]">{{ image.dimensions }} &middot; {{ image.size }}</p>
              </div>
            </div>
          </SortableItem>
        </Sortable>
      </FramePanel>
    </Frame>
  </div>
</template>

Установка

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

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

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