Tree
Плотное дерево строк, каким его показывает файловый навигатор редактора: уровни с отступами,
треугольник у ветки, значок, подпись, метка справа. Отдельного примитива shadcn для этого нет —
Tree собран из Item / ItemGroup / ScrollArea кита, по дереву ресурсов ReFormer Builder,
где он и был доведён до рабочего состояния.
Источник узлов задаётся одним из двух способов. nodes — дерево известно целиком: узел это
{ id, label, kind?, children?, badge?, disabled? }, где id — адрес, уникальный в пределах
всего дерева (для файлов удобно брать полный путь), а kind объявляется, а не выводится из
children, иначе пустой каталог был бы неотличим от файла. loadChildren — уровни читаются
лениво, по одному, при первом раскрытии ветки; корневой уровень дерево запрашивает само, передав
в загрузчик null. Прочитанный уровень запоминается: свернуть и раскрыть обратно повторного
обращения не стоит, а перечитать его после переименования или удаления файла можно через
TreeHandle.refresh(). Пока уровень читается, на месте треугольника крутится спиннер; отказ
красит подпись ветки в тревожный цвет и уходит в onLoadError. Оба способа сочетаются: nodes
задают верхний уровень, loadChildren дочитывает всё остальное.
Виртуальный скролл включён по умолчанию, и это не оптимизация «на будущее»: раскрытый каталог
реального проекта — тысячи строк, у каждой свои обработчики, а поверх строки у потребителя может
висеть контекстное меню, то есть ещё один узел с подписками. Отрисовывается только окно видимых
строк — для этого дереву нужна определённая высота: её задаёт либо maxRows (высота по
содержимому — то, что нужно списку в поповере), либо className вызывающего (h-full в панели).
Выключают виртуализацию (virtualized={false}) там, где дерево заведомо короткое, а разметка
нужна целиком — например на этой самой странице: Docusaurus отрисовывает её на сервере.
Дерево — навигация, а не поле формы: у него нет ни value, ни onChange, ни статики
reformerAdapter, и в component поля его не кладут. Причина не в недоделке: поле обязано отдавать одно значение, а у дерева
значений столько же, сколько строк, и вопросов оно решает два разных — «где я сейчас»
(selectedId, ровно одна строка, туда же уходит фокус) и «что я выбрал» (checkedIds, сколько
угодно строк). Если форме нужно выбрать файл, это делает вариант комбобокса — ComboboxTree
(значение string | null) или ComboboxTreeMulti (string[] | null): в поповере у них живёт
ровно это же дерево, а наружу они отдают контракт поля. Само Tree остаётся там, где выбор не
единственная цель, — в панелях, навигаторах, деревьях ресурсов.
Variants — готовые конфигурации компонента: один и тот же компонент с разными преднастроенными пропсами. Витрина состояний (напр. обычный Select и Select с расширенной информацией — два варианта).
Examples — приёмы в коде: как решить задачу. Напр. как разные Data Provider’ы работают с компонентом (рецепты использования).