primitives/@mihcm/ui·v0.21.0·stable
OrgSelector
Form-field-shaped picker for hierarchical org structures (departments, teams, business units, locations). Five variants (popover/inline/columns/drawer/command) and four selection modes (single/multi/cascade/include-descendants) compose freely. Full WAI-ARIA TreeView keyboard model, lazy loading, optional virtualization for large trees.
Props
The full prop API for OrgSelector. Same surface in web and React Native — bundlers pick the right variant via the react-native export condition.
| Prop | Type | Default | Description | Since |
|---|---|---|---|---|
data | OrgNode[] | — | Tree to render. Omit and use `loadChildren` for a fully lazy tree. | 0.20.0 |
loadChildren | (node: OrgNode) => Promise<OrgNode[]> | — | Lazy-load children for nodes flagged with `hasChildren: true`. Called once per node on first expand. | 0.20.0 |
variant | 'popover' | 'inline' | 'columns' | 'drawer' | 'command' | 'breadcrumb-drill' | 'popover' | Visual shell. Mode and triggerDisplay are independent — every combination is supported. | 0.20.0 |
mode | 'single' | 'multi' | 'cascade' | 'include-descendants' | 'single' | Selection semantics. See Usage → Modes for value shapes. | 0.20.0 |
pickable | 'any-level' | 'leaf-only' | 'any-level' | `leaf-only` makes parents expandable but read-only. | 0.20.0 |
triggerDisplay | 'chips' | 'breadcrumb' | 'path' | 'count' | 'chips' | How the closed trigger renders the selection. `breadcrumb` shows `Group › Engineering › Platform`; `path` uses `/` separators; `count` shows `N selected`. | 0.20.0 |
pathSeparator | ReactNode | — | Override the separator between path segments. Defaults to `›` for breadcrumb and `/` for path. | 0.20.0 |
autoVirtualizeThreshold | number | 1000 | Total node count above which the renderer auto-enables virtualization (caps visible rows and prompts to narrow with search). Set `Infinity` to disable. | 0.20.0 |
value | string | string[] | null | — | Controlled value. `string | null` in single mode; `string[]` otherwise. | 0.20.0 |
defaultValue | string | string[] | null | — | Uncontrolled initial value. | 0.20.0 |
onChange | (next: string | string[] | null) => void | — | Fires whenever the selection changes. | 0.20.0 |
label | ReactNode | — | Form-field label. Renders inside `popover`, `inline`, and `drawer` shells. | 0.20.0 |
placeholder | string | — | Placeholder text on the closed popover trigger. | 0.20.0 |
helpText | ReactNode | — | Help text below the field. Wired via `aria-describedby`. | 0.20.0 |
errorText | ReactNode | — | Error text. Toggles `aria-invalid` styling. | 0.20.0 |
required | boolean | — | Marks the field as required (renders asterisk + `aria-required`). | 0.20.0 |
disabled | boolean | — | Disables every interactive affordance. | 0.20.0 |
searchable | boolean | — | Show the typeahead search input. Defaults to `true` for trees with ≥ 7 roots. | 0.20.0 |
matcher | (node: OrgNode, query: string) => boolean | — | Custom matcher. Defaults to case-insensitive substring on `label`. | 0.20.0 |
disabledKeys | readonly string[] | — | Keys that cannot be toggled, even when otherwise selectable. | 0.20.0 |
defaultExpandedKeys | readonly string[] | — | Keys expanded on first render. | 0.20.0 |
expandAll | boolean | — | Force every parent open and disable collapse. | 0.20.0 |
expandOnValue | boolean | true | Auto-expand the ancestry path of the current value(s) when opening. | 0.20.0 |
virtualized | boolean | — | Virtualize the flattened rows (requires `@tanstack/react-virtual`). Use for trees with >1k visible nodes. | 0.20.0 |
maxVisibleChips | number | — | Max visible chip count in the multi-select trigger before "…+N". | 0.20.0 |
drawerSide | 'left' | 'right' | 'bottom' | 'bottom' | Side the drawer slides in from in `drawer` variant. | 0.20.0 |
Import
import { OrgSelector, type OrgNode } from '@mihcm/ui/OrgSelector';