npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@kintales/tree-view

v1.0.0

Published

A React Native family tree visualization library built on react-native-svg

Readme

@kintales/tree-view

npm version license

Interactive family tree visualization for React Native. Pan, zoom, pinch gestures. Supports multiple marriages, step-children, half-siblings. Built on react-native-svg.

Works on iOS, Android, and Web (via react-native-web).

Installation

npm install @kintales/tree-view

Peer dependencies

npm install react-native-svg react-native-gesture-handler react-native-reanimated

Follow the installation guides for each peer dependency:

Quick start

import { FamilyTree } from '@kintales/tree-view';

const people = [
  { id: '1', name: 'Grandpa Ivan', birthYear: 1940, deathYear: 2020 },
  { id: '2', name: 'Grandma Maria', birthYear: 1943 },
  { id: '3', name: 'Father Petar', birthYear: 1965 },
  { id: '4', name: 'Mother Elena', birthYear: 1968 },
  { id: '5', name: 'Me', birthYear: 1992 },
];

const relationships = [
  { from: '1', to: '2', type: 'spouse' },
  { from: '1', to: '3', type: 'parent' },
  { from: '2', to: '3', type: 'parent' },
  { from: '3', to: '4', type: 'spouse' },
  { from: '3', to: '5', type: 'parent' },
  { from: '4', to: '5', type: 'parent' },
];

<FamilyTree
  people={people}
  relationships={relationships}
  rootId="1"
  onPersonTap={(person) => console.log('Tapped:', person.name)}
/>

Features

  • Automatic layout: parents above, children below, spouses side by side
  • Multiple marriages with per-spouse child grouping
  • Step-children, half-siblings, adopted children (all rendered identically)
  • Pan, pinch-to-zoom, double-tap to reset
  • Tap and long-press callbacks on nodes
  • Circular photos with initials fallback
  • Birth/death year labels
  • Built-in themes: warm (earth tones) and neutral (clean/modern)
  • Custom themes and custom node/edge renderers
  • Viewport culling for large trees (50+ nodes)
  • TypeScript support with full type declarations

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | people | Person[] | required | Array of people to display | | relationships | Relationship[] | required | Array of relationships between people | | rootId | string | first person | Center the tree on this person | | onPersonTap | (person: Person) => void | — | Callback when a node is tapped | | onPersonLongPress | (person: Person) => void | — | Callback on long press | | nodeWidth | number | 120 | Width of each node in pixels | | nodeHeight | number | 160 | Height of each node in pixels | | horizontalSpacing | number | 40 | Horizontal gap between nodes | | verticalSpacing | number | 80 | Vertical gap between generations | | theme | 'warm' \| 'neutral' \| 'custom' | 'warm' | Built-in theme or custom | | customTheme | TreeTheme | — | Custom theme object (requires theme='custom') | | showPhotos | boolean | true | Show photo/initials circle | | showDates | boolean | true | Show birth/death year labels | | photoShape | 'circle' \| 'rounded' | 'circle' | Shape of photo area | | deceasedStyle | 'dim' \| 'sepia' \| 'none' | 'none' | Visual style for deceased people | | enablePan | boolean | true | Enable drag to pan | | enableZoom | boolean | true | Enable pinch to zoom | | minZoom | number | 0.3 | Minimum zoom level | | maxZoom | number | 3.0 | Maximum zoom level | | initialZoom | number | 1.0 | Starting zoom level | | renderNode | (person, position) => ReactNode | — | Custom node renderer | | renderEdge | (from, to, type) => ReactNode | — | Custom edge renderer |

Types

interface Person {
  id: string;
  name: string;
  gender?: 'male' | 'female' | 'other';
  photo?: string;
  birthYear?: number;
  deathYear?: number;
  [key: string]: unknown;
}

interface Relationship {
  from: string;
  to: string;
  type: 'parent' | 'spouse' | 'sibling' | 'step_parent' | 'step_child'
       | 'step_sibling' | 'adopted' | 'guardian' | string;
  marriageYear?: number;
  divorceYear?: number;
}

interface TreeTheme {
  backgroundColor: string;
  nodeBackgroundColor: string;
  nodeBorderColor: string;
  nodeTextColor: string;
  edgeColor: string;
  edgeWidth: number;
  fontFamily: string;
  fontSize: number;
  photoPlaceholderColor: string;
}

Advanced: headless layout

Use the layout algorithm without rendering:

import { computeLayout } from '@kintales/tree-view';

const layout = computeLayout(people, relationships, 'root-id');
// layout.nodes: { id, person, x, y, generation }[]
// layout.edges: { fromId, toId, type, points }[]
// layout.width, layout.height

Custom node renderer

import { Circle, Text } from 'react-native-svg';

<FamilyTree
  people={people}
  relationships={relationships}
  renderNode={(person, pos) => (
    <Circle
      cx={pos.x + pos.width / 2}
      cy={pos.y + pos.height / 2}
      r={40}
      fill={person.gender === 'female' ? '#E8A0BF' : '#7286D3'}
    />
  )}
/>

Performance

  • Trees with 50+ nodes automatically enable viewport culling
  • Only visible nodes and their connecting edges are rendered
  • React.memo on all SVG components prevents unnecessary re-renders
  • useMemo on layout computation and node/edge lists
  • Tested with 200+ node trees

Design principles

  1. All relationship types have identical visual style (no different colors/dashes for step-parent vs biological)
  2. No built-in gendered coloring (use renderNode for customization)
  3. Deceased people have no special treatment by default (deceasedStyle: 'none')
  4. No assumptions about family structure (0-N spouses, 0-N parents)
  5. Zero opinion on data source

Examples

See the examples/ directory:

  • BasicTree.tsx — Minimal 3-generation tree
  • ComplexTree.tsx — Multiple marriages, half-siblings, 4 generations
  • LargeTree.tsx — 100+ nodes performance demo
  • CustomTheme.tsx — Dark theme example
  • CustomNodes.tsx — Custom circular node renderer

License

MIT