sortable

Sortable settings priority with frame

Sortable settings priority with frame

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

src/sortable/c-sortable-5.vue

<!--
  Расхождение с апстримом: `IconPlaceholder` заменена инлайновым `<svg>`
  (lucide-react v0.545.0 "grip-vertical") — см. 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"
import { Switch } from "@/components/ui/switch"

interface NotificationChannel {
  id: string
  name: string
  description: string
  enabled: boolean
}

const channels = ref<NotificationChannel[]>([
  { id: "1", name: "Email", description: "Send notifications via email", enabled: true },
  { id: "2", name: "Push Notifications", description: "Browser and mobile push", enabled: true },
  { id: "3", name: "SMS", description: "Text message alerts", enabled: false },
  { id: "4", name: "Slack", description: "Post to Slack channels", enabled: true },
  { id: "5", name: "Webhook", description: "Send to custom endpoint", enabled: false },
])

function getItemValue(item: NotificationChannel) {
  return item.id
}

function toggleChannel(id: string) {
  const channel = channels.value.find((ch) => ch.id === id)
  if (channel) channel.enabled = !channel.enabled
}
</script>

<template>
  <div class="mx-auto w-full max-w-md">
    <Frame spacing="sm">
      <FrameHeader>
        <FrameTitle>Notification Priority</FrameTitle>
        <FrameDescription>
          Drag to reorder by priority. Top channels are tried first.
        </FrameDescription>
      </FrameHeader>
      <Sortable
        v-model:value="channels"
        :get-item-value="getItemValue"
        strategy="vertical"
        class="space-y-1"
      >
        <SortableItem v-for="channel in channels" :key="channel.id" :value="channel.id">
          <FramePanel class="p-0!">
            <div class="flex items-center gap-3 px-3 py-2.5">
              <SortableItemHandle class="text-muted-foreground hover:text-foreground">
                <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-4">
                  <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>
              <div class="min-w-0 flex-1">
                <p class="text-sm font-medium">{{ channel.name }}</p>
                <p class="text-muted-foreground text-xs">{{ channel.description }}</p>
              </div>
              <Switch :default-value="channel.enabled" @update:model-value="() => toggleChannel(channel.id)" />
            </div>
          </FramePanel>
        </SortableItem>
      </Sortable>
    </Frame>
  </div>
</template>

Установка

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

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

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