fix: выбранные позиции справочника отображаются горизонтально рядом с полем

This commit is contained in:
2026-07-24 14:14:56 +03:00
parent b4bded2ffb
commit 031d477630

View File

@@ -142,102 +142,100 @@ export default function TableFieldMultiSelect({
} }
return ( return (
<Popover open={isOpen} onOpenChange={setIsOpen} modal={false}> <div className="flex flex-wrap items-center gap-1 w-full">
<PopoverAnchor asChild> <Popover open={isOpen} onOpenChange={setIsOpen} modal={false}>
<div className="relative w-full"> <PopoverAnchor asChild>
<Input <div className="relative flex-1 min-w-[120px]">
ref={inputRef} <Input
className="h-8" ref={inputRef}
placeholder={placeholder || 'Выберите значения...'} className="h-8"
value={isOpen ? searchTerm : (selectedLabels.length > 0 ? `${selectedLabels.length} выбрано` : placeholder || 'Выберите значения...')} placeholder={placeholder || 'Выберите значения...'}
onChange={(e) => { value={isOpen ? searchTerm : (selectedLabels.length > 0 ? `${selectedLabels.length} выбрано` : placeholder || 'Выберите значения...')}
setSearchTerm(e.target.value); onChange={(e) => {
setIsOpen(true); setSearchTerm(e.target.value);
}} setIsOpen(true);
onFocus={() => { }}
setSearchTerm(''); onFocus={() => {
setIsOpen(true); setSearchTerm('');
}} setIsOpen(true);
data-testid={`select-table-multi-${fieldCode}`} }}
/> data-testid={`select-table-multi-${fieldCode}`}
</div> />
</PopoverAnchor> </div>
<PopoverContent </PopoverAnchor>
className="p-0" <PopoverContent
style={{ width: 'var(--radix-popper-anchor-width)' }} className="p-0"
onOpenAutoFocus={(e) => e.preventDefault()} style={{ width: 'var(--radix-popper-anchor-width)' }}
onInteractOutside={(e) => { onOpenAutoFocus={(e) => e.preventDefault()}
if (inputRef.current && inputRef.current.contains(e.target as Node)) { onInteractOutside={(e) => {
e.preventDefault(); if (inputRef.current && inputRef.current.contains(e.target as Node)) {
} e.preventDefault();
}} }
>
<div
className="max-h-60 overflow-auto"
onWheel={(e) => {
const el = e.currentTarget;
const isUp = e.deltaY < 0;
const isDown = e.deltaY > 0;
const atTop = el.scrollTop <= 0;
const atBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - 1;
if ((isUp && atTop) || (isDown && atBottom)) return;
e.preventDefault();
el.scrollTop += e.deltaY;
}} }}
> >
{hasTree ? ( <div
<DirectoryTreeMultiSelect className="max-h-60 overflow-auto"
nodes={nodes} onWheel={(e) => {
selected={selectedSet} const el = e.currentTarget;
onToggle={toggle} const isUp = e.deltaY < 0;
searchTerm={searchTerm} const isDown = e.deltaY > 0;
/> const atTop = el.scrollTop <= 0;
) : ( const atBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - 1;
<ul className="py-1"> if ((isUp && atTop) || (isDown && atBottom)) return;
{filtered.map((row) => { e.preventDefault();
const rowId = row.id.toString(); el.scrollTop += e.deltaY;
const label = row.values[displayColumnIndex!] || row.values[0] || rowId; }}
return ( >
<li {hasTree ? (
key={row.id} <DirectoryTreeMultiSelect
className="flex items-center gap-2 px-3 py-2 hover:bg-accent cursor-pointer text-sm" nodes={nodes}
title={label} selected={selectedSet}
onMouseDown={(e) => { e.preventDefault(); toggle(rowId); }} onToggle={toggle}
> searchTerm={searchTerm}
<Checkbox checked={selectedSet.has(rowId)} /> />
<Table className="w-3 h-3 text-muted-foreground flex-shrink-0" /> ) : (
<span className="flex-1">{label}</span> <ul className="py-1">
</li> {filtered.map((row) => {
); const rowId = row.id.toString();
})} const label = row.values[displayColumnIndex!] || row.values[0] || rowId;
{filtered.length === 0 && ( return (
<li className="px-3 py-2 text-sm text-muted-foreground">Нет совпадений</li> <li
)} key={row.id}
</ul> className="flex items-center gap-2 px-3 py-2 hover:bg-accent cursor-pointer text-sm"
)} title={label}
</div> onMouseDown={(e) => { e.preventDefault(); toggle(rowId); }}
</PopoverContent> >
{selectedLabels.length > 0 && ( <Checkbox checked={selectedSet.has(rowId)} />
<div className="flex flex-wrap gap-1 mt-1.5"> <Table className="w-3 h-3 text-muted-foreground flex-shrink-0" />
{selectedLabels.map((label, idx) => { <span className="flex-1">{label}</span>
const rowId = selectedValues[idx]; </li>
return ( );
<div key={rowId} className="inline-flex items-center gap-1 px-1.5 py-0.5 rounded bg-muted text-xs"> })}
<span className="truncate max-w-[150px]">{label}</span> {filtered.length === 0 && (
<Button <li className="px-3 py-2 text-sm text-muted-foreground">Нет совпадений</li>
type="button" )}
variant="ghost" </ul>
size="icon" )}
className="h-4 w-4" </div>
onClick={() => toggle(rowId)} </PopoverContent>
> </Popover>
<X className="w-3 h-3" /> {selectedLabels.map((label, idx) => {
</Button> const rowId = selectedValues[idx];
</div> return (
); <div key={rowId} className="inline-flex items-center gap-1 px-1.5 py-0.5 rounded bg-muted text-xs shrink-0">
})} <span className="truncate max-w-[150px]">{label}</span>
</div> <Button
)} type="button"
</Popover> variant="ghost"
size="icon"
className="h-4 w-4"
onClick={() => toggle(rowId)}
>
<X className="w-3 h-3" />
</Button>
</div>
);
})}
</div>
); );
} }