@jack-pairce/react-org-chart-editor
v0.9.6
Published
Interactive, editable organization chart component for React. Build, visualize, and edit hierarchical role structures with drag-and-drop, connectors, and an unassigned users list.
Readme
@jack-pairce/react-org-chart-editor
Interactive, editable organization chart component for React. Build, visualize, and edit hierarchical role structures with drag-and-drop, connectors, and an unassigned users list.
- Written in TypeScript
- Ships ESM/CJS typings from dist
- UI built with antd and tailwind (peer styles not required to consume the component)
Install
- npm: npm i @jack-pairce/react-org-chart-editor antd
- pnpm: pnpm add @jack-pairce/react-org-chart-editor antd
- yarn: yarn add @jack-pairce/react-org-chart-editor antd
React 18+ is required.
What you get
The package exports a single component:
- HierarchyPage — a fully featured org chart editor wrapped in internal context state.
Import path:
- ESM: import { HierarchyPage } from '@jack-pairce/react-org-chart-editor'
The build exposes types in dist/index.d.ts.
Quick start
import { useState } from 'react';
import { HierarchyPage } from '@jack-pairce/react-org-chart-editor';
import type { Role, User } from '@jack-pairce/react-org-chart-editor/dist/types';
const initialRoles: Role[] = [
{ id: 1, name: 'CEO', color: '#4F46E5', parent_id: null, is_responsable: true, can_sudo: true, users_limit: 1, users: [], level: 0, children: [] },
];
const initialUsers: User[] = [
{ id: 100, name: 'Alice', role_id: null },
{ id: 101, name: 'Bob', role_id: 1 },
];
export default function Demo() {
const [roles, setRoles] = useState(initialRoles);
const [users, setUsers] = useState(initialUsers);
return (
<HierarchyPage
headerTitle="Company Structure"
roles={roles}
users={users}
isLoading={false}
initialEditMode="none"
onChange={({ roles: nextRoles, users: nextUsers }) => {
setRoles(nextRoles);
setUsers(nextUsers);
}}
onSave={async ({ added, updated, deleted, usersChanged }) => {
// Persist to your backend
console.log({ added, updated, deleted, usersChanged });
}}
/>
);
}Props
HierarchyPage props are defined by HierarchyProps:
- headerTitle: string — Title displayed in the header toolbar.
- roles: Role[] — Flat list of roles. The component builds a tree internally (via parent_id).
- users: User[] — All users. Users with role_id === null appear in the Unassigned list.
- isLoading: boolean — Show a loading state.
- initialEditMode?: 'none' | 'reorder' | 'content' — Optional starting mode.
- onChange?: (next: { roles: Role[]; users: User[] }) => void — Fires whenever local state changes.
- onSave?: (payload: { added: Role[]; updated: Role[]; deleted: Role[]; usersChanged: User[] }) => Promise | void — Called by UI save actions.
Types are available from the package types export, see below.
Types
Minimal, framework-independent types are included:
- User (alias of DefaultUser)
- id: number
- name: string
- family?: string
- role_id: number | null
- Role
- id: number
- name: string
- color: string
- parent_id: number | null
- is_responsable: boolean
- can_sudo: boolean
- users_limit: number
- users: { id: number; name: string; icon?: string | ReactNode | (() => ReactNode) }[]
- level: number
- children: Role[]
- Optional layout/runtime: x, y, isDragging, _new, _placeholder, _overlayed
- EditMode: 'none' | 'reorder' | 'content'
Note: The component computes layout coordinates (x,y) and connector paths internally. Provide roles as a flat array; the tree is built from parent_id relationships.
Behavior overview
- Tree building and layout: roles are converted to a tree, levels are measured, and SVG connectors are rendered between parents and children.
- Drag-and-drop: move roles, reorder, and adjust levels. Height per level is computed dynamically.
- Unassigned users: fixed list for users with role_id = null; drag onto roles.
- Modes: editMode toggles behavior (reorder/content) while 'none' disables editing.
- onChange/onSave: wire these to persist changes.
Styling
- The component includes minimal internal styles (src/components/style.css) and uses antd components. Consumers can override styles via global CSS. Tailwind is used in development but not required in your app.
Development
- Dev preview: pnpm dev
- Build library: pnpm build (emits dist with types and JS)
- Bundle single entry via tsup: pnpm bundle
Importing types
You can import types from the package root when using TypeScript:
import type { Role, User, EditMode } from '@jack-pairce/react-org-chart-editor/dist/types';Alternatively, rely on inference by passing plain objects that match these shapes.
License
MIT © JackPairce
