Entity Picker
ilinxa/entity-pickerFreeBlock
Searchable picker for typed entities — single or multi select, kind badges, chip cluster with removal, and custom render slots.
Install it
npx shadcn@latest add https://ui.ilinxa.com/r/entity-picker.jsonSource
1"use client";23import {4 useCallback,5 useId,6 useImperativeHandle,7 useLayoutEffect,8 useRef,9 useState,10 type KeyboardEvent,11 type Ref,12} from "react";13import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";14import {15 Command,16 CommandEmpty,17 CommandInput,18 CommandList,19} from "@/components/ui/command";20import type {21 EntityLike,22 EntityPickerHandle,23 EntityPickerProps,24 KindMeta,25 MultiPickerProps,26 PickerMode,27 SinglePickerProps,28} from "./types";29import { defaultMatch } from "./lib/default-match";30import {31 multiSelectionEqual,32 singleSelectionEqual,33} from "./lib/selection-equality";34import { useItemsById } from "./hooks/use-items-by-id";35import { useOpenState } from "./hooks/use-open-state";36import { TriggerButton } from "./parts/trigger-button";37import { ResultRow } from "./parts/result-row";38import { DefaultEmptyState } from "./parts/default-empty-state";3940function EntityPickerImpl<T extends EntityLike>(props: EntityPickerProps<T>) {41 const {42 items,43 match,44 placeholder = "Search…",45 open: controlledOpen,46 onOpenChange,47 kinds,48 showKindBadges: showKindBadgesProp,49 renderItem,50 renderTrigger,51 renderEmpty,52 disabled = false,53 triggerLabel,54 id,55 className,56 ref,57 } = props;5859 const mode: PickerMode = props.mode === "multi" ? "multi" : "single";60 const value = props.value as T | T[] | null;6162 const reactId = useId();63 const listboxId = `${reactId}-listbox`;6465 const { open, setOpen: rawSetOpen } = useOpenState({66 controlled: controlledOpen,67 onOpenChange,68 });6970 const [query, setQuery] = useState("");7172 const setOpen = useCallback(73 (next: boolean) => {74 if (!next) setQuery("");75 rawSetOpen(next);76 },77 [rawSetOpen],78 );7980 const itemsById = useItemsById(items);8182 const showKindBadges =83 showKindBadgesProp !== undefined84 ? showKindBadgesProp85 : items.some((i) => !!i.kind);8687 // Track the trigger element via state (not a ref) so the setter is React's88 // own setState — passes the React Compiler-aware lint rule that flags89 // ref-accessor functions passed to user-rendered functions during render.90 // The ref-fn is stable across renders (React guarantees setState identity).91 const [triggerNode, setTriggerNode] = useState<HTMLElement | null>(null);9293 // F-cross-13 consumer-trigger path: when a press lands while the popover is94 // open, Radix/Base UI's outside-press dismiss closes it BEFORE the click95// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from ilinxa
All 184 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Account Switcheraccount-switcher | ilinxa | Blocks | Free | 1 dep · 10 files | |
| Account Switcher (deprecated alias)account-switcher-01 | ilinxa | Blocks | Free | no deps | |
| Account Switcher — fixturesaccount-switcher-fixtures | ilinxa | Blocks | Free | no deps | |
| App Sidebarapp-sidebar | ilinxa | Blocks | Free | 1 dep · 37 files | |
| App Sidebar — fixturesapp-sidebar-fixtures | ilinxa | Blocks | Free | no deps | |
| Rich Text Editor (deprecated alias)article-body-01 | ilinxa | Blocks | Free | no deps | |
| Article Metaarticle-meta | ilinxa | Blocks | Free | 1 dep · 4 files | |
| Article Meta (deprecated alias)article-meta-01 | ilinxa | Blocks | Free | no deps |
