@alexbrand09/famtreejs 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +259 -0
- package/dist/components/FamilyTree.d.ts +7 -0
- package/dist/components/FamilyTree.d.ts.map +1 -0
- package/dist/components/FamilyTreeWithProvider.d.ts +5 -0
- package/dist/components/FamilyTreeWithProvider.d.ts.map +1 -0
- package/dist/components/defaults/BasicPersonCard.d.ts +7 -0
- package/dist/components/defaults/BasicPersonCard.d.ts.map +1 -0
- package/dist/components/defaults/DetailedPersonCard.d.ts +10 -0
- package/dist/components/defaults/DetailedPersonCard.d.ts.map +1 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5634 -0
- package/dist/layout/engine.d.ts +62 -0
- package/dist/layout/engine.d.ts.map +1 -0
- package/dist/store/FamilyTreeContext.d.ts +48 -0
- package/dist/store/FamilyTreeContext.d.ts.map +1 -0
- package/dist/store/treeStore.d.ts +35 -0
- package/dist/store/treeStore.d.ts.map +1 -0
- package/dist/types/index.d.ts +169 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/utils/validation.d.ts +13 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/package.json +88 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { FamilyTreeData, SpacingConfig, Orientation } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* A positioned node in the layout
|
|
4
|
+
*/
|
|
5
|
+
export interface LayoutNode {
|
|
6
|
+
id: string;
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Connection between two partners
|
|
12
|
+
*/
|
|
13
|
+
export interface PartnershipConnection {
|
|
14
|
+
partnershipId: string;
|
|
15
|
+
partner1Id: string;
|
|
16
|
+
partner2Id: string | null;
|
|
17
|
+
/** Midpoint of the partnership line (where drop line starts) */
|
|
18
|
+
midpoint: {
|
|
19
|
+
x: number;
|
|
20
|
+
y: number;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Connection from partnership to child
|
|
25
|
+
*/
|
|
26
|
+
export interface ChildConnection {
|
|
27
|
+
partnershipId: string;
|
|
28
|
+
childId: string;
|
|
29
|
+
/** Where the vertical drop line starts */
|
|
30
|
+
dropPoint: {
|
|
31
|
+
x: number;
|
|
32
|
+
y: number;
|
|
33
|
+
};
|
|
34
|
+
/** Where the line connects to the child */
|
|
35
|
+
childPoint: {
|
|
36
|
+
x: number;
|
|
37
|
+
y: number;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Complete layout result
|
|
42
|
+
*/
|
|
43
|
+
export interface LayoutResult {
|
|
44
|
+
nodes: LayoutNode[];
|
|
45
|
+
partnershipConnections: PartnershipConnection[];
|
|
46
|
+
childConnections: ChildConnection[];
|
|
47
|
+
/** The orientation used for this layout */
|
|
48
|
+
orientation: Orientation;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Options for layout calculation
|
|
52
|
+
*/
|
|
53
|
+
export interface LayoutOptions {
|
|
54
|
+
spacing: SpacingConfig;
|
|
55
|
+
orientation?: Orientation;
|
|
56
|
+
rootPersonId?: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Calculate the layout for a family tree
|
|
60
|
+
*/
|
|
61
|
+
export declare function calculateLayout<T>(data: FamilyTreeData<T>, options: LayoutOptions): LayoutResult;
|
|
62
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/layout/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE3E;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,gEAAgE;IAChE,QAAQ,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,SAAS,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,2CAA2C;IAC3C,UAAU,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,sBAAsB,EAAE,qBAAqB,EAAE,CAAC;IAChD,gBAAgB,EAAE,eAAe,EAAE,CAAC;IACpC,2CAA2C;IAC3C,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,aAAa,CAAC;IACvB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AA8DD;;GAEG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAC/B,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,EACvB,OAAO,EAAE,aAAa,GACrB,YAAY,CAgDd"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
declare const FamilyTreeContext: import("react").Context<import("zustand").UseBoundStore<import("zustand").StoreApi<import("./treeStore").TreeStore>> | null>;
|
|
3
|
+
export interface FamilyTreeProviderProps {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
minZoom?: number;
|
|
6
|
+
maxZoom?: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Provider component that creates and provides a tree store instance
|
|
10
|
+
*/
|
|
11
|
+
export declare function FamilyTreeProvider({ children, minZoom, maxZoom, }: FamilyTreeProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
/**
|
|
13
|
+
* Hook to access tree state reactively
|
|
14
|
+
*/
|
|
15
|
+
export declare function useFamilyTreeState(): {
|
|
16
|
+
zoomLevel: number;
|
|
17
|
+
rootPersonId: string | null;
|
|
18
|
+
selectedPersonId: string | null;
|
|
19
|
+
visibleNodeIds: string[];
|
|
20
|
+
expandedNodeIds: string[];
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Hook to access tree actions
|
|
24
|
+
*/
|
|
25
|
+
export declare function useFamilyTreeActions(): {
|
|
26
|
+
zoomTo: (level: number) => void;
|
|
27
|
+
zoomIn: () => void;
|
|
28
|
+
zoomOut: () => void;
|
|
29
|
+
centerOnPerson: (personId: string) => void;
|
|
30
|
+
fitToView: () => void;
|
|
31
|
+
expandAll: () => void;
|
|
32
|
+
collapseAll: () => void;
|
|
33
|
+
toggleBranch: (personId: string) => void;
|
|
34
|
+
setRoot: (personId: string) => void;
|
|
35
|
+
getZoom: () => number;
|
|
36
|
+
getRoot: () => string | null;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Internal hook to get full store access (for FamilyTree component)
|
|
40
|
+
*/
|
|
41
|
+
export declare function useTreeStoreInternal(): import("./treeStore").TreeStore;
|
|
42
|
+
/**
|
|
43
|
+
* Internal hook to get the raw store reference (for callback registration)
|
|
44
|
+
* This avoids subscribing to state changes, preventing infinite loops
|
|
45
|
+
*/
|
|
46
|
+
export declare function useTreeStoreRaw(): import("zustand").UseBoundStore<import("zustand").StoreApi<import("./treeStore").TreeStore>>;
|
|
47
|
+
export { FamilyTreeContext };
|
|
48
|
+
//# sourceMappingURL=FamilyTreeContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FamilyTreeContext.d.ts","sourceRoot":"","sources":["../../src/store/FamilyTreeContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAuC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAK5E,QAAA,MAAM,iBAAiB,8HAAiE,CAAC;AAEzF,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,SAAS,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,OAAa,EACb,OAAW,GACZ,EAAE,uBAAuB,2CASzB;AAcD;;GAEG;AACH,wBAAgB,kBAAkB;eAInB,MAAM;kBACH,MAAM,GAAG,IAAI;sBACT,MAAM,GAAG,IAAI;oBACf,MAAM,EAAE;qBACP,MAAM,EAAE;EAQ5B;AAED;;GAEG;AACH,wBAAgB,oBAAoB;YAIxB,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI;YACvB,MAAM,IAAI;aACT,MAAM,IAAI;oBACH,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI;eAC/B,MAAM,IAAI;eACV,MAAM,IAAI;iBACR,MAAM,IAAI;kBACT,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI;aAC/B,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI;aAC1B,MAAM,MAAM;aACZ,MAAM,MAAM,GAAG,IAAI;EAmC/B;AAED;;GAEG;AACH,wBAAgB,oBAAoB,oCAGnC;AAED;;;GAGG;AACH,wBAAgB,eAAe,iGAE9B;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface TreeState {
|
|
2
|
+
zoom: number;
|
|
3
|
+
panX: number;
|
|
4
|
+
panY: number;
|
|
5
|
+
selectedPersonId: string | null;
|
|
6
|
+
hoveredPersonId: string | null;
|
|
7
|
+
expandedIds: Set<string>;
|
|
8
|
+
rootPersonId: string | null;
|
|
9
|
+
visibleNodeIds: string[];
|
|
10
|
+
}
|
|
11
|
+
export interface TreeActions {
|
|
12
|
+
setZoom: (zoom: number) => void;
|
|
13
|
+
zoomIn: (step?: number) => void;
|
|
14
|
+
zoomOut: (step?: number) => void;
|
|
15
|
+
setPan: (x: number, y: number) => void;
|
|
16
|
+
panBy: (dx: number, dy: number) => void;
|
|
17
|
+
setSelectedPersonId: (id: string | null) => void;
|
|
18
|
+
setHoveredPersonId: (id: string | null) => void;
|
|
19
|
+
toggleBranch: (personId: string) => void;
|
|
20
|
+
expandAll: (allIds: string[]) => void;
|
|
21
|
+
collapseAll: () => void;
|
|
22
|
+
setExpandedIds: (ids: Set<string>) => void;
|
|
23
|
+
setRootPersonId: (id: string | null) => void;
|
|
24
|
+
setVisibleNodeIds: (ids: string[]) => void;
|
|
25
|
+
_centerOnPersonCallback: ((personId: string) => void) | null;
|
|
26
|
+
_fitToViewCallback: (() => void) | null;
|
|
27
|
+
_expandAllCallback: (() => void) | null;
|
|
28
|
+
_registerCallbacks: (centerOnPerson: (personId: string) => void, fitToView: () => void, expandAll: () => void) => void;
|
|
29
|
+
_unregisterCallbacks: () => void;
|
|
30
|
+
reset: () => void;
|
|
31
|
+
}
|
|
32
|
+
export type TreeStore = TreeState & TreeActions;
|
|
33
|
+
export declare const createTreeStore: (minZoom?: number, maxZoom?: number) => import("zustand").UseBoundStore<import("zustand").StoreApi<TreeStore>>;
|
|
34
|
+
export declare const useTreeStore: import("zustand").UseBoundStore<import("zustand").StoreApi<TreeStore>>;
|
|
35
|
+
//# sourceMappingURL=treeStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"treeStore.d.ts","sourceRoot":"","sources":["../../src/store/treeStore.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,SAAS;IAExB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IAGb,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAG/B,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAGzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAG5B,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAE1B,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAGjC,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAGxC,mBAAmB,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACjD,kBAAkB,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAGhD,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACtC,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,cAAc,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IAG3C,eAAe,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAG7C,iBAAiB,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAG3C,uBAAuB,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IAC7D,kBAAkB,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC;IACxC,kBAAkB,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC;IACxC,kBAAkB,EAAE,CAClB,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,EAC1C,SAAS,EAAE,MAAM,IAAI,EACrB,SAAS,EAAE,MAAM,IAAI,KAClB,IAAI,CAAC;IACV,oBAAoB,EAAE,MAAM,IAAI,CAAC;IAGjC,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;AAehD,eAAO,MAAM,eAAe,GAAI,gBAAa,EAAE,gBAAW,2EA8DrD,CAAC;AAGN,eAAO,MAAM,YAAY,wEAAoB,CAAC"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import type { ComponentType, CSSProperties } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* A person node in the family tree
|
|
4
|
+
*/
|
|
5
|
+
export interface PersonNode<T = unknown> {
|
|
6
|
+
/** Unique identifier */
|
|
7
|
+
id: string;
|
|
8
|
+
/** User's data object, passed to NodeComponent */
|
|
9
|
+
data: T;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A partnership (marriage, civil union, or informal relationship)
|
|
13
|
+
*/
|
|
14
|
+
export interface Partnership {
|
|
15
|
+
/** Unique identifier */
|
|
16
|
+
id: string;
|
|
17
|
+
/** IDs of the two partners. Use [id, null] for single-parent situations */
|
|
18
|
+
partnerIds: [string, string | null];
|
|
19
|
+
/** IDs of children from this partnership */
|
|
20
|
+
childIds: string[];
|
|
21
|
+
/** Optional metadata */
|
|
22
|
+
type?: 'marriage' | 'civil-union' | 'partnership' | 'other';
|
|
23
|
+
startDate?: string;
|
|
24
|
+
endDate?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Complete family tree data structure
|
|
28
|
+
*/
|
|
29
|
+
export interface FamilyTreeData<T = unknown> {
|
|
30
|
+
/** All people in the tree */
|
|
31
|
+
people: PersonNode<T>[];
|
|
32
|
+
/** All partnerships */
|
|
33
|
+
partnerships: Partnership[];
|
|
34
|
+
/** Optional starting point for rendering */
|
|
35
|
+
rootPersonId?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Props passed to user's custom node component
|
|
39
|
+
*/
|
|
40
|
+
export interface NodeComponentProps<T = unknown> {
|
|
41
|
+
/** The person's ID */
|
|
42
|
+
id: string;
|
|
43
|
+
/** The user's data object */
|
|
44
|
+
data: T;
|
|
45
|
+
/** Whether this node is currently selected */
|
|
46
|
+
isSelected: boolean;
|
|
47
|
+
/** Whether this node is currently hovered */
|
|
48
|
+
isHovered: boolean;
|
|
49
|
+
/** Whether this node's branch is expanded */
|
|
50
|
+
isExpanded: boolean;
|
|
51
|
+
/** Toggle branch expansion */
|
|
52
|
+
onToggleExpand: () => void;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Tree orientation options
|
|
56
|
+
*/
|
|
57
|
+
export type Orientation = 'top-down' | 'bottom-up' | 'left-right' | 'right-left';
|
|
58
|
+
/**
|
|
59
|
+
* Spacing configuration
|
|
60
|
+
*/
|
|
61
|
+
export interface SpacingConfig {
|
|
62
|
+
/** Vertical space between generations (px) */
|
|
63
|
+
generation?: number;
|
|
64
|
+
/** Horizontal space between siblings (px) */
|
|
65
|
+
siblings?: number;
|
|
66
|
+
/** Space between partners (px) */
|
|
67
|
+
partners?: number;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Line styling configuration
|
|
71
|
+
*/
|
|
72
|
+
export interface LineStyle {
|
|
73
|
+
stroke?: string;
|
|
74
|
+
strokeWidth?: number;
|
|
75
|
+
strokeDasharray?: string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Theme options
|
|
79
|
+
*/
|
|
80
|
+
export type Theme = 'light' | 'dark';
|
|
81
|
+
/**
|
|
82
|
+
* Main FamilyTree component props
|
|
83
|
+
*/
|
|
84
|
+
export interface FamilyTreeProps<T = unknown> {
|
|
85
|
+
/** Tree data */
|
|
86
|
+
data: FamilyTreeData<T>;
|
|
87
|
+
/** Custom component to render each person node */
|
|
88
|
+
nodeComponent: ComponentType<NodeComponentProps<T>>;
|
|
89
|
+
/** Tree orientation */
|
|
90
|
+
orientation?: Orientation;
|
|
91
|
+
/** Spacing configuration */
|
|
92
|
+
spacing?: SpacingConfig;
|
|
93
|
+
/** Person ID to center the tree on */
|
|
94
|
+
rootPersonId?: string;
|
|
95
|
+
/** Number of ancestor generations to show (undefined = all) */
|
|
96
|
+
ancestorDepth?: number;
|
|
97
|
+
/** Number of descendant generations to show (undefined = all) */
|
|
98
|
+
descendantDepth?: number;
|
|
99
|
+
/** Built-in theme */
|
|
100
|
+
theme?: Theme;
|
|
101
|
+
/** Line/connection styling */
|
|
102
|
+
lineStyle?: LineStyle;
|
|
103
|
+
/** Additional CSS class for the container */
|
|
104
|
+
className?: string;
|
|
105
|
+
/** Inline styles for the container */
|
|
106
|
+
style?: CSSProperties;
|
|
107
|
+
/** Disable all animations */
|
|
108
|
+
disableAnimations?: boolean;
|
|
109
|
+
/** Animation duration in ms (default: 300) */
|
|
110
|
+
animationDuration?: number;
|
|
111
|
+
/** Initial zoom level (default: 1) */
|
|
112
|
+
initialZoom?: number;
|
|
113
|
+
/** Zoom range */
|
|
114
|
+
minZoom?: number;
|
|
115
|
+
maxZoom?: number;
|
|
116
|
+
/** Called when a person node is clicked */
|
|
117
|
+
onPersonClick?: (personId: string, data: T) => void;
|
|
118
|
+
/** Called when a person node is hovered */
|
|
119
|
+
onPersonHover?: (personId: string | null, data: T | null) => void;
|
|
120
|
+
/** Called when a partnership is clicked */
|
|
121
|
+
onPartnershipClick?: (partnershipId: string) => void;
|
|
122
|
+
/** Called when zoom level changes */
|
|
123
|
+
onZoomChange?: (zoom: number) => void;
|
|
124
|
+
/** Called when the centered person changes */
|
|
125
|
+
onRootChange?: (personId: string) => void;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Imperative handle for FamilyTree component
|
|
129
|
+
*/
|
|
130
|
+
export interface FamilyTreeHandle {
|
|
131
|
+
/** Set zoom level */
|
|
132
|
+
zoomTo(level: number): void;
|
|
133
|
+
/** Zoom in by a step */
|
|
134
|
+
zoomIn(): void;
|
|
135
|
+
/** Zoom out by a step */
|
|
136
|
+
zoomOut(): void;
|
|
137
|
+
/** Center the view on a specific person */
|
|
138
|
+
centerOnPerson(personId: string): void;
|
|
139
|
+
/** Fit the entire tree (or visible portion) in view */
|
|
140
|
+
fitToView(): void;
|
|
141
|
+
/** Expand all collapsed branches */
|
|
142
|
+
expandAll(): void;
|
|
143
|
+
/** Collapse all branches */
|
|
144
|
+
collapseAll(): void;
|
|
145
|
+
/** Expand/collapse a specific person's branch */
|
|
146
|
+
toggleBranch(personId: string): void;
|
|
147
|
+
/** Re-root the tree on a different person */
|
|
148
|
+
setRoot(personId: string): void;
|
|
149
|
+
/** Get current zoom level */
|
|
150
|
+
getZoom(): number;
|
|
151
|
+
/** Get current root person ID */
|
|
152
|
+
getRoot(): string | null;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* State returned by useFamilyTreeState hook
|
|
156
|
+
*/
|
|
157
|
+
export interface FamilyTreeState {
|
|
158
|
+
/** Current zoom level */
|
|
159
|
+
zoomLevel: number;
|
|
160
|
+
/** Currently centered person ID */
|
|
161
|
+
rootPersonId: string | null;
|
|
162
|
+
/** Currently selected person ID */
|
|
163
|
+
selectedPersonId: string | null;
|
|
164
|
+
/** IDs of currently visible nodes */
|
|
165
|
+
visibleNodeIds: string[];
|
|
166
|
+
/** IDs of expanded branches */
|
|
167
|
+
expandedNodeIds: string[];
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC,GAAG,OAAO;IACrC,wBAAwB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,kDAAkD;IAClD,IAAI,EAAE,CAAC,CAAC;CACT;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,wBAAwB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,2EAA2E;IAC3E,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IACpC,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,wBAAwB;IACxB,IAAI,CAAC,EAAE,UAAU,GAAG,aAAa,GAAG,aAAa,GAAG,OAAO,CAAC;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc,CAAC,CAAC,GAAG,OAAO;IACzC,6BAA6B;IAC7B,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;IACxB,uBAAuB;IACvB,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,4CAA4C;IAC5C,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,OAAO;IAC7C,sBAAsB;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,6BAA6B;IAC7B,IAAI,EAAE,CAAC,CAAC;IACR,8CAA8C;IAC9C,UAAU,EAAE,OAAO,CAAC;IACpB,6CAA6C;IAC7C,SAAS,EAAE,OAAO,CAAC;IACnB,6CAA6C;IAC7C,UAAU,EAAE,OAAO,CAAC;IACpB,8BAA8B;IAC9B,cAAc,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,WAAW,GAAG,YAAY,GAAG,YAAY,CAAC;AAEjF;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,MAAM,KAAK,GAAG,OAAO,GAAG,MAAM,CAAC;AAErC;;GAEG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IAC1C,gBAAgB;IAChB,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;IAExB,kDAAkD;IAClD,aAAa,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC;IAIpD,uBAAuB;IACvB,WAAW,CAAC,EAAE,WAAW,CAAC;IAE1B,4BAA4B;IAC5B,OAAO,CAAC,EAAE,aAAa,CAAC;IAIxB,sCAAsC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,iEAAiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAC;IAIzB,qBAAqB;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;IAEd,8BAA8B;IAC9B,SAAS,CAAC,EAAE,SAAS,CAAC;IAEtB,6CAA6C;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,sCAAsC;IACtC,KAAK,CAAC,EAAE,aAAa,CAAC;IAItB,6BAA6B;IAC7B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B,8CAA8C;IAC9C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,iBAAiB;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IAIjB,2CAA2C;IAC3C,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IAEpD,2CAA2C;IAC3C,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC;IAElE,2CAA2C;IAC3C,kBAAkB,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IAErD,qCAAqC;IACrC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAEtC,8CAA8C;IAC9C,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,qBAAqB;IACrB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAE5B,wBAAwB;IACxB,MAAM,IAAI,IAAI,CAAC;IAEf,yBAAyB;IACzB,OAAO,IAAI,IAAI,CAAC;IAEhB,2CAA2C;IAC3C,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAEvC,uDAAuD;IACvD,SAAS,IAAI,IAAI,CAAC;IAElB,oCAAoC;IACpC,SAAS,IAAI,IAAI,CAAC;IAElB,4BAA4B;IAC5B,WAAW,IAAI,IAAI,CAAC;IAEpB,iDAAiD;IACjD,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAErC,6CAA6C;IAC7C,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAEhC,6BAA6B;IAC7B,OAAO,IAAI,MAAM,CAAC;IAElB,iCAAiC;IACjC,OAAO,IAAI,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mCAAmC;IACnC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,qCAAqC;IACrC,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,+BAA+B;IAC/B,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FamilyTreeData } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Validation error thrown when family tree data is invalid
|
|
4
|
+
*/
|
|
5
|
+
export declare class ValidationError extends Error {
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Validates family tree data and throws on any issues
|
|
10
|
+
* @throws ValidationError if data is invalid
|
|
11
|
+
*/
|
|
12
|
+
export declare function validateFamilyTreeData<T>(data: FamilyTreeData<T>): void;
|
|
13
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C;;GAEG;AACH,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,IAAI,CA8DvE"}
|
package/package.json
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@alexbrand09/famtreejs",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "React library for rendering interactive family trees with partnership-centric data model",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
},
|
|
14
|
+
"./styles.css": "./dist/index.css"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"dev": "vite",
|
|
21
|
+
"build": "vite build && tsc --emitDeclarationOnly --outDir dist",
|
|
22
|
+
"preview": "vite preview",
|
|
23
|
+
"test": "vitest",
|
|
24
|
+
"test:run": "vitest run",
|
|
25
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
26
|
+
"format": "prettier --write \"src/**/*.{ts,tsx}\"",
|
|
27
|
+
"storybook": "storybook dev -p 6006",
|
|
28
|
+
"build-storybook": "storybook build",
|
|
29
|
+
"release": "standard-version",
|
|
30
|
+
"release:first": "standard-version --first-release"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"react": "^18.0.0",
|
|
34
|
+
"react-dom": "^18.0.0"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"react",
|
|
38
|
+
"family-tree",
|
|
39
|
+
"genealogy",
|
|
40
|
+
"visualization",
|
|
41
|
+
"d3"
|
|
42
|
+
],
|
|
43
|
+
"author": "Alexander Brand",
|
|
44
|
+
"license": "MIT",
|
|
45
|
+
"repository": {
|
|
46
|
+
"type": "git",
|
|
47
|
+
"url": "https://github.com/alexbrand/famtreejs"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@chromatic-com/storybook": "^4.1.3",
|
|
51
|
+
"@eslint/js": "^9.39.2",
|
|
52
|
+
"@storybook/addon-a11y": "^10.1.11",
|
|
53
|
+
"@storybook/addon-docs": "^10.1.11",
|
|
54
|
+
"@storybook/addon-onboarding": "^10.1.11",
|
|
55
|
+
"@storybook/addon-vitest": "^10.1.11",
|
|
56
|
+
"@storybook/react-vite": "^10.1.11",
|
|
57
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
58
|
+
"@testing-library/react": "^16.3.1",
|
|
59
|
+
"@types/d3": "^7.4.3",
|
|
60
|
+
"@types/react": "^19.2.7",
|
|
61
|
+
"@types/react-dom": "^19.2.3",
|
|
62
|
+
"@typescript-eslint/eslint-plugin": "^8.51.0",
|
|
63
|
+
"@typescript-eslint/parser": "^8.51.0",
|
|
64
|
+
"@vitejs/plugin-react": "^5.1.2",
|
|
65
|
+
"@vitest/browser-playwright": "^4.0.16",
|
|
66
|
+
"@vitest/coverage-v8": "^4.0.16",
|
|
67
|
+
"eslint": "^9.39.2",
|
|
68
|
+
"eslint-plugin-react": "^7.37.5",
|
|
69
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
70
|
+
"eslint-plugin-storybook": "^10.1.11",
|
|
71
|
+
"globals": "^17.0.0",
|
|
72
|
+
"jsdom": "^27.4.0",
|
|
73
|
+
"playwright": "^1.57.0",
|
|
74
|
+
"prettier": "^3.7.4",
|
|
75
|
+
"react": "^19.2.3",
|
|
76
|
+
"react-dom": "^19.2.3",
|
|
77
|
+
"standard-version": "^9.5.0",
|
|
78
|
+
"storybook": "^10.1.11",
|
|
79
|
+
"typescript": "^5.9.3",
|
|
80
|
+
"vite": "^7.3.0",
|
|
81
|
+
"vitest": "^4.0.16"
|
|
82
|
+
},
|
|
83
|
+
"dependencies": {
|
|
84
|
+
"d3": "^7.9.0",
|
|
85
|
+
"framer-motion": "^12.23.26",
|
|
86
|
+
"zustand": "^5.0.9"
|
|
87
|
+
}
|
|
88
|
+
}
|