filters

Filters with prefetched async options

Filters with prefetched async options

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

src/filters/c-filters-11.vue

<!--
  ПОРТ c-filters-11 ("Filters with prefetched async options").

  Апстрим прогоняет `loadOptions` через реальный `setTimeout` (600ms) на
  первом вызове, чтобы симулировать сетевую задержку prefetch-а. Попапы
  значений не раскрываются на статичном скриншоте (см. docs/PORTING.md,
  раздел про `filters`), поэтому `loadOptions` физически не вызывается при
  монтировании — сам факт задержки не мог бы повлиять на диф. Тем не менее
  правило (никакого таймера, влияющего на первый рендер / детерминированный
  источник данных) соблюдено дословно: `setTimeout` заменён на
  `Promise.resolve()` (сохраняет асинхронность вызова — как и апстримный
  `loadOptions`, возвращающий `Promise`), а кеширование через closure-ref
  перенесено как есть.
-->
<script setup lang="ts">
import { h, ref } from "vue"
import {
  Filters,
  type Filter,
  type FilterFieldConfig,
  type FilterOption,
} from "@/components/reui/filters"

function UsersIcon() {
  return h(
    "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",
    },
    [
      h("path", { d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" }),
      h("path", { d: "M16 3.128a4 4 0 0 1 0 7.744" }),
      h("path", { d: "M22 21v-2a4 4 0 0 0-3-3.87" }),
      h("circle", { cx: "9", cy: "7", r: "4" }),
    ]
  )
}

// Prefetch source: the whole remote list, cached in a closure ref once
// `loadOptions` resolves for the first time (same shape as the React `useRef`
// cache in the upstream pattern).
const TEAMS: FilterOption<string>[] = [
  { value: "eng", label: "Engineering" },
  { value: "design", label: "Design" },
  { value: "product", label: "Product" },
  { value: "marketing", label: "Marketing" },
  { value: "sales", label: "Sales" },
  { value: "support", label: "Customer Support" },
  { value: "finance", label: "Finance" },
  { value: "people", label: "People Ops" },
  { value: "legal", label: "Legal" },
  { value: "it", label: "IT" },
  { value: "data", label: "Data & Analytics" },
  { value: "security", label: "Security" },
]

let cache: FilterOption<string>[] | null = null

const demoFields: FilterFieldConfig<string>[] = [
  {
    key: "team",
    label: "Team",
    icon: UsersIcon,
    type: "multiselect",
    // Prefetch the whole list once, then filter the cached copy by the
    // query so the search box still works without more requests. Real
    // network delay replaced by a plain microtask (ponytail: no fake timer
    // may gate the first render; the async shape of `loadOptions` itself is
    // preserved verbatim).
    loadOptions: async (query: string) => {
      if (!cache) {
        await Promise.resolve()
        cache = TEAMS
      }
      const q = query.trim().toLowerCase()
      return q ? cache.filter((team) => team.label.toLowerCase().includes(q)) : cache
    },
  },
]

const filters = ref<Filter<string>[]>([])

function handleFiltersChange(next: Filter<string>[]) {
  filters.value = next
}
</script>

<template>
  <div class="flex grow content-start items-start self-start">
    <Filters :filters="filters" :fields="demoFields" @change="handleFiltersChange" />
  </div>
</template>

Установка

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

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

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