hpo-react-visualizer 0.0.1

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.
Files changed (45) hide show
  1. package/README.md +59 -0
  2. package/dist/index.cjs +1483 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.cts +244 -0
  5. package/dist/index.d.ts +244 -0
  6. package/dist/index.js +1473 -0
  7. package/dist/index.js.map +1 -0
  8. package/package.json +60 -0
  9. package/src/HpoVisualizer.tsx +210 -0
  10. package/src/OrganSvg.tsx +141 -0
  11. package/src/__tests__/colorScheme.test.tsx +146 -0
  12. package/src/__tests__/createStrictColorPalette.test.ts +135 -0
  13. package/src/__tests__/renderOrder.test.tsx +146 -0
  14. package/src/__tests__/setup.ts +1 -0
  15. package/src/constants.ts +158 -0
  16. package/src/index.ts +34 -0
  17. package/src/lib/createStrictColorPalette.ts +57 -0
  18. package/src/lib/index.ts +1 -0
  19. package/src/svg/Blood.tsx +23 -0
  20. package/src/svg/Body.tsx +24 -0
  21. package/src/svg/Breast.tsx +42 -0
  22. package/src/svg/Cell.tsx +79 -0
  23. package/src/svg/Constitutional.tsx +29 -0
  24. package/src/svg/Digestive.tsx +28 -0
  25. package/src/svg/Ear.tsx +23 -0
  26. package/src/svg/Endocrine.tsx +32 -0
  27. package/src/svg/Eye.tsx +23 -0
  28. package/src/svg/Growth.tsx +23 -0
  29. package/src/svg/Head.tsx +51 -0
  30. package/src/svg/Heart.tsx +23 -0
  31. package/src/svg/Immune.tsx +32 -0
  32. package/src/svg/Integument.tsx +58 -0
  33. package/src/svg/Kidney.tsx +41 -0
  34. package/src/svg/Limbs.tsx +46 -0
  35. package/src/svg/Lung.tsx +23 -0
  36. package/src/svg/Metabolism.tsx +41 -0
  37. package/src/svg/Muscle.tsx +225 -0
  38. package/src/svg/Neoplasm.tsx +23 -0
  39. package/src/svg/Nervous.tsx +49 -0
  40. package/src/svg/Prenatal.tsx +23 -0
  41. package/src/svg/ThoracicCavity.tsx +28 -0
  42. package/src/svg/Voice.tsx +23 -0
  43. package/src/svg/index.ts +54 -0
  44. package/src/types.ts +162 -0
  45. package/src/useOrganInteraction.ts +130 -0
@@ -0,0 +1,244 @@
1
+ import { CSSProperties, ComponentType } from 'react';
2
+ import * as react_jsx_runtime from 'react/jsx-runtime';
3
+
4
+ /**
5
+ * Supported organ identifiers
6
+ */
7
+ type OrganId = "head" | "eye" | "ear" | "heart" | "lung" | "digestive" | "kidney" | "integument" | "constitutional" | "limbs" | "nervous" | "breast" | "thoracicCavity" | "voice" | "metabolism" | "cell" | "endocrine" | "neoplasm" | "immune" | "muscle" | "growth" | "prenatal" | "blood";
8
+ /**
9
+ * Color scheme for each organ.
10
+ */
11
+ type ColorName = "blue" | "yellow" | "gray";
12
+ /**
13
+ * Color step
14
+ */
15
+ type ColorStep = 100 | 200 | 300;
16
+ /**
17
+ * Solid color scale (required colors)
18
+ */
19
+ type SolidColorScale = Record<ColorStep, string>;
20
+ /**
21
+ * Color scale for a color palette.
22
+ * Solid colors (100, 200, 300) are required.
23
+ * Alpha colors are all-or-nothing optional via the 'alpha' property.
24
+ */
25
+ type ColorScale = SolidColorScale & {
26
+ alpha?: SolidColorScale;
27
+ };
28
+ type ColorPalette = Record<ColorName, ColorScale>;
29
+ type StrictColorPalette = Record<ColorName, Required<ColorScale>>;
30
+ /**
31
+ * Style properties for organ SVG elements
32
+ */
33
+ interface OrganStyle {
34
+ /** Fill color of the organ */
35
+ fill?: string;
36
+ /** Stroke (border) color */
37
+ stroke?: string;
38
+ /** Stroke width in pixels */
39
+ strokeWidth?: number;
40
+ /** Opacity (0-1) */
41
+ opacity?: number;
42
+ /** Whether the organ is visible */
43
+ visible?: boolean;
44
+ /** Blur effect in pixels (CSS filter blur) */
45
+ blur?: number;
46
+ }
47
+ /**
48
+ * Configuration for individual organ
49
+ */
50
+ interface OrganConfig {
51
+ /** Organ identifier */
52
+ id: OrganId;
53
+ /** Associated HPO IDs for this organ (optional) */
54
+ hpoIds?: string[];
55
+ /** Default style */
56
+ style?: OrganStyle;
57
+ /** Style when hovered */
58
+ hoverStyle?: OrganStyle;
59
+ /** Style when selected/active */
60
+ activeStyle?: OrganStyle;
61
+ /** Color scheme to use for this organ */
62
+ colorName?: ColorName;
63
+ /** Show red outline around this organ */
64
+ showOutline?: boolean;
65
+ }
66
+ /**
67
+ * Props for individual organ SVG components
68
+ */
69
+ interface OrganSvgProps {
70
+ /** Current style to apply */
71
+ style?: OrganStyle;
72
+ /** CSS transition string for smooth style changes */
73
+ transition?: string;
74
+ /** Color scale to use for this organ (with guaranteed alpha values) */
75
+ colorScale: Required<ColorScale>;
76
+ /** Whether the organ is in active state (hovered or selected) */
77
+ isActive?: boolean;
78
+ /** Additional CSS class name */
79
+ className?: string;
80
+ }
81
+ /**
82
+ * Internal state for organ interaction
83
+ */
84
+ interface OrganInteractionState {
85
+ /** Currently hovered organ ID */
86
+ hoveredOrgan: OrganId | null;
87
+ /** Currently selected/clicked organ ID */
88
+ selectedOrgan: OrganId | null;
89
+ }
90
+ /**
91
+ * Handlers returned by useOrganInteraction hook
92
+ */
93
+ interface OrganInteractionHandlers {
94
+ /** Handle mouse enter on organ */
95
+ handleMouseEnter: (organId: OrganId) => void;
96
+ /** Handle mouse leave on organ */
97
+ handleMouseLeave: () => void;
98
+ /** Handle click on organ */
99
+ handleClick: (organId: OrganId) => void;
100
+ }
101
+ /**
102
+ * Props for the main HpoVisualizer component
103
+ */
104
+ interface HpoVisualizerProps {
105
+ /** Detailed organ configurations */
106
+ organs?: OrganConfig[];
107
+ /**
108
+ * List of organ IDs to display.
109
+ * - undefined: all organs are visible
110
+ * - OrganId[]: only the specified organs are visible
111
+ * - []: no organs are visible
112
+ */
113
+ visibleOrgans?: OrganId[];
114
+ /** Controlled: currently hovered organ */
115
+ hoveredOrgan?: OrganId | null;
116
+ /** Controlled: currently selected organ */
117
+ selectedOrgan?: OrganId | null;
118
+ /** Callback when hover state changes */
119
+ onHover?: (organId: OrganId | null) => void;
120
+ /** Callback when selection state changes */
121
+ onSelect?: (organId: OrganId | null) => void;
122
+ /** Color palette to use for organs */
123
+ colorPalette?: Partial<ColorPalette>;
124
+ /** Width of the visualizer */
125
+ width?: number | string;
126
+ /** Height of the visualizer */
127
+ height?: number | string;
128
+ /** Additional CSS class name */
129
+ className?: string;
130
+ /** Additional inline styles */
131
+ style?: CSSProperties;
132
+ }
133
+
134
+ /**
135
+ * All supported organ IDs
136
+ */
137
+ declare const ORGAN_IDS: readonly OrganId[];
138
+ /**
139
+ * Display names for organs (English)
140
+ */
141
+ declare const ORGAN_NAMES_EN: Record<OrganId, string>;
142
+ /**
143
+ * Display names for organs (Korean)
144
+ */
145
+ declare const ORGAN_NAMES_KO: Record<OrganId, string>;
146
+ /**
147
+ * Color palettes for each color scheme.
148
+ * Based on Tailwind CSS color palette.
149
+ */
150
+ declare const DEFAULT_COLOR_PALETTE: StrictColorPalette;
151
+ /**
152
+ * Animation duration in milliseconds
153
+ */
154
+ declare const ANIMATION_DURATION_MS = 150;
155
+
156
+ /**
157
+ * HPO Visualizer - Interactive human organ visualization component
158
+ *
159
+ * Features:
160
+ * - Displays organs as interactive SVG graphics
161
+ * - Hover effect with visual highlighting
162
+ * - Click to select/deselect organs
163
+ * - Hover effects work independently even when an organ is selected
164
+ * - Exposes hover and selection state via callbacks
165
+ */
166
+ declare function HpoVisualizer({ organs, visibleOrgans, hoveredOrgan: controlledHovered, selectedOrgan: controlledSelected, onHover, onSelect, colorPalette: inputColorPalette, width, height, className, style, }: HpoVisualizerProps): react_jsx_runtime.JSX.Element;
167
+
168
+ interface OrganSvgWrapperProps {
169
+ /** Organ identifier */
170
+ organId: OrganId;
171
+ /** Organ configuration */
172
+ config?: OrganConfig;
173
+ /** Color palette to use for this organ (with guaranteed alpha values) */
174
+ colorPalette: StrictColorPalette;
175
+ /** Whether the organ is currently hovered */
176
+ isHovered: boolean;
177
+ /** Whether the organ is currently selected */
178
+ isSelected: boolean;
179
+ /** Mouse enter handler */
180
+ onMouseEnter: () => void;
181
+ /** Mouse leave handler */
182
+ onMouseLeave: () => void;
183
+ /** Click handler */
184
+ onClick: () => void;
185
+ /** X position in parent coordinate system */
186
+ x: number;
187
+ /** Y position in parent coordinate system */
188
+ y: number;
189
+ /** Width of the organ SVG viewport */
190
+ width: number;
191
+ /** Height of the organ SVG viewport */
192
+ height: number;
193
+ /** ViewBox for the organ SVG (local coordinate system) */
194
+ viewBox: string;
195
+ /** Show red outline around this organ */
196
+ showOutline?: boolean;
197
+ /** Whether the organ is visible (controls opacity for animation) */
198
+ isVisible?: boolean;
199
+ }
200
+ /**
201
+ * Wrapper component for organ SVG with interaction handling
202
+ */
203
+ declare function OrganSvg({ organId, config, colorPalette, isHovered, isSelected, onMouseEnter, onMouseLeave, onClick, x, y, width, height, viewBox, showOutline, isVisible, }: OrganSvgWrapperProps): react_jsx_runtime.JSX.Element;
204
+
205
+ /**
206
+ * Map of organ IDs to their SVG components
207
+ */
208
+ declare const ORGAN_COMPONENTS: Record<OrganId, ComponentType<OrganSvgProps>>;
209
+
210
+ interface UseOrganInteractionOptions {
211
+ /** Controlled hover state from parent */
212
+ hoveredOrgan?: OrganId | null;
213
+ /** Controlled selected state from parent */
214
+ selectedOrgan?: OrganId | null;
215
+ /** Callback when hover state changes */
216
+ onHover?: (organId: OrganId | null) => void;
217
+ /** Callback when selected state changes */
218
+ onSelect?: (organId: OrganId | null) => void;
219
+ }
220
+ interface UseOrganInteractionResult {
221
+ /** Current interaction state */
222
+ state: OrganInteractionState;
223
+ /** Event handlers for organs */
224
+ handlers: OrganInteractionHandlers;
225
+ /** Check if an organ is currently highlighted (hovered or selected) */
226
+ isHighlighted: (organId: OrganId) => boolean;
227
+ /** Check if an organ is currently selected */
228
+ isSelected: (organId: OrganId) => boolean;
229
+ /** Check if an organ is currently hovered */
230
+ isHovered: (organId: OrganId) => boolean;
231
+ }
232
+ /**
233
+ * Hook to manage organ hover and click interactions
234
+ *
235
+ * Behavior:
236
+ * - Mouse enter on organ updates hoveredOrgan and calls onHover
237
+ * - Click on organ sets selectedOrgan and calls onSelect
238
+ * - Click on already selected organ deselects it
239
+ * - Click on different organ changes selection
240
+ * - Hover effects work independently even when an organ is selected
241
+ */
242
+ declare function useOrganInteraction(options?: UseOrganInteractionOptions): UseOrganInteractionResult;
243
+
244
+ export { ANIMATION_DURATION_MS, type ColorScale as ColorPalette, type ColorName as ColorScheme, DEFAULT_COLOR_PALETTE, HpoVisualizer, type HpoVisualizerProps, ORGAN_COMPONENTS, ORGAN_IDS, ORGAN_NAMES_EN, ORGAN_NAMES_KO, type OrganConfig, type OrganId, type OrganInteractionHandlers, type OrganInteractionState, type OrganStyle, OrganSvg, type OrganSvgProps, type OrganSvgWrapperProps, type UseOrganInteractionOptions, type UseOrganInteractionResult, useOrganInteraction };
@@ -0,0 +1,244 @@
1
+ import { CSSProperties, ComponentType } from 'react';
2
+ import * as react_jsx_runtime from 'react/jsx-runtime';
3
+
4
+ /**
5
+ * Supported organ identifiers
6
+ */
7
+ type OrganId = "head" | "eye" | "ear" | "heart" | "lung" | "digestive" | "kidney" | "integument" | "constitutional" | "limbs" | "nervous" | "breast" | "thoracicCavity" | "voice" | "metabolism" | "cell" | "endocrine" | "neoplasm" | "immune" | "muscle" | "growth" | "prenatal" | "blood";
8
+ /**
9
+ * Color scheme for each organ.
10
+ */
11
+ type ColorName = "blue" | "yellow" | "gray";
12
+ /**
13
+ * Color step
14
+ */
15
+ type ColorStep = 100 | 200 | 300;
16
+ /**
17
+ * Solid color scale (required colors)
18
+ */
19
+ type SolidColorScale = Record<ColorStep, string>;
20
+ /**
21
+ * Color scale for a color palette.
22
+ * Solid colors (100, 200, 300) are required.
23
+ * Alpha colors are all-or-nothing optional via the 'alpha' property.
24
+ */
25
+ type ColorScale = SolidColorScale & {
26
+ alpha?: SolidColorScale;
27
+ };
28
+ type ColorPalette = Record<ColorName, ColorScale>;
29
+ type StrictColorPalette = Record<ColorName, Required<ColorScale>>;
30
+ /**
31
+ * Style properties for organ SVG elements
32
+ */
33
+ interface OrganStyle {
34
+ /** Fill color of the organ */
35
+ fill?: string;
36
+ /** Stroke (border) color */
37
+ stroke?: string;
38
+ /** Stroke width in pixels */
39
+ strokeWidth?: number;
40
+ /** Opacity (0-1) */
41
+ opacity?: number;
42
+ /** Whether the organ is visible */
43
+ visible?: boolean;
44
+ /** Blur effect in pixels (CSS filter blur) */
45
+ blur?: number;
46
+ }
47
+ /**
48
+ * Configuration for individual organ
49
+ */
50
+ interface OrganConfig {
51
+ /** Organ identifier */
52
+ id: OrganId;
53
+ /** Associated HPO IDs for this organ (optional) */
54
+ hpoIds?: string[];
55
+ /** Default style */
56
+ style?: OrganStyle;
57
+ /** Style when hovered */
58
+ hoverStyle?: OrganStyle;
59
+ /** Style when selected/active */
60
+ activeStyle?: OrganStyle;
61
+ /** Color scheme to use for this organ */
62
+ colorName?: ColorName;
63
+ /** Show red outline around this organ */
64
+ showOutline?: boolean;
65
+ }
66
+ /**
67
+ * Props for individual organ SVG components
68
+ */
69
+ interface OrganSvgProps {
70
+ /** Current style to apply */
71
+ style?: OrganStyle;
72
+ /** CSS transition string for smooth style changes */
73
+ transition?: string;
74
+ /** Color scale to use for this organ (with guaranteed alpha values) */
75
+ colorScale: Required<ColorScale>;
76
+ /** Whether the organ is in active state (hovered or selected) */
77
+ isActive?: boolean;
78
+ /** Additional CSS class name */
79
+ className?: string;
80
+ }
81
+ /**
82
+ * Internal state for organ interaction
83
+ */
84
+ interface OrganInteractionState {
85
+ /** Currently hovered organ ID */
86
+ hoveredOrgan: OrganId | null;
87
+ /** Currently selected/clicked organ ID */
88
+ selectedOrgan: OrganId | null;
89
+ }
90
+ /**
91
+ * Handlers returned by useOrganInteraction hook
92
+ */
93
+ interface OrganInteractionHandlers {
94
+ /** Handle mouse enter on organ */
95
+ handleMouseEnter: (organId: OrganId) => void;
96
+ /** Handle mouse leave on organ */
97
+ handleMouseLeave: () => void;
98
+ /** Handle click on organ */
99
+ handleClick: (organId: OrganId) => void;
100
+ }
101
+ /**
102
+ * Props for the main HpoVisualizer component
103
+ */
104
+ interface HpoVisualizerProps {
105
+ /** Detailed organ configurations */
106
+ organs?: OrganConfig[];
107
+ /**
108
+ * List of organ IDs to display.
109
+ * - undefined: all organs are visible
110
+ * - OrganId[]: only the specified organs are visible
111
+ * - []: no organs are visible
112
+ */
113
+ visibleOrgans?: OrganId[];
114
+ /** Controlled: currently hovered organ */
115
+ hoveredOrgan?: OrganId | null;
116
+ /** Controlled: currently selected organ */
117
+ selectedOrgan?: OrganId | null;
118
+ /** Callback when hover state changes */
119
+ onHover?: (organId: OrganId | null) => void;
120
+ /** Callback when selection state changes */
121
+ onSelect?: (organId: OrganId | null) => void;
122
+ /** Color palette to use for organs */
123
+ colorPalette?: Partial<ColorPalette>;
124
+ /** Width of the visualizer */
125
+ width?: number | string;
126
+ /** Height of the visualizer */
127
+ height?: number | string;
128
+ /** Additional CSS class name */
129
+ className?: string;
130
+ /** Additional inline styles */
131
+ style?: CSSProperties;
132
+ }
133
+
134
+ /**
135
+ * All supported organ IDs
136
+ */
137
+ declare const ORGAN_IDS: readonly OrganId[];
138
+ /**
139
+ * Display names for organs (English)
140
+ */
141
+ declare const ORGAN_NAMES_EN: Record<OrganId, string>;
142
+ /**
143
+ * Display names for organs (Korean)
144
+ */
145
+ declare const ORGAN_NAMES_KO: Record<OrganId, string>;
146
+ /**
147
+ * Color palettes for each color scheme.
148
+ * Based on Tailwind CSS color palette.
149
+ */
150
+ declare const DEFAULT_COLOR_PALETTE: StrictColorPalette;
151
+ /**
152
+ * Animation duration in milliseconds
153
+ */
154
+ declare const ANIMATION_DURATION_MS = 150;
155
+
156
+ /**
157
+ * HPO Visualizer - Interactive human organ visualization component
158
+ *
159
+ * Features:
160
+ * - Displays organs as interactive SVG graphics
161
+ * - Hover effect with visual highlighting
162
+ * - Click to select/deselect organs
163
+ * - Hover effects work independently even when an organ is selected
164
+ * - Exposes hover and selection state via callbacks
165
+ */
166
+ declare function HpoVisualizer({ organs, visibleOrgans, hoveredOrgan: controlledHovered, selectedOrgan: controlledSelected, onHover, onSelect, colorPalette: inputColorPalette, width, height, className, style, }: HpoVisualizerProps): react_jsx_runtime.JSX.Element;
167
+
168
+ interface OrganSvgWrapperProps {
169
+ /** Organ identifier */
170
+ organId: OrganId;
171
+ /** Organ configuration */
172
+ config?: OrganConfig;
173
+ /** Color palette to use for this organ (with guaranteed alpha values) */
174
+ colorPalette: StrictColorPalette;
175
+ /** Whether the organ is currently hovered */
176
+ isHovered: boolean;
177
+ /** Whether the organ is currently selected */
178
+ isSelected: boolean;
179
+ /** Mouse enter handler */
180
+ onMouseEnter: () => void;
181
+ /** Mouse leave handler */
182
+ onMouseLeave: () => void;
183
+ /** Click handler */
184
+ onClick: () => void;
185
+ /** X position in parent coordinate system */
186
+ x: number;
187
+ /** Y position in parent coordinate system */
188
+ y: number;
189
+ /** Width of the organ SVG viewport */
190
+ width: number;
191
+ /** Height of the organ SVG viewport */
192
+ height: number;
193
+ /** ViewBox for the organ SVG (local coordinate system) */
194
+ viewBox: string;
195
+ /** Show red outline around this organ */
196
+ showOutline?: boolean;
197
+ /** Whether the organ is visible (controls opacity for animation) */
198
+ isVisible?: boolean;
199
+ }
200
+ /**
201
+ * Wrapper component for organ SVG with interaction handling
202
+ */
203
+ declare function OrganSvg({ organId, config, colorPalette, isHovered, isSelected, onMouseEnter, onMouseLeave, onClick, x, y, width, height, viewBox, showOutline, isVisible, }: OrganSvgWrapperProps): react_jsx_runtime.JSX.Element;
204
+
205
+ /**
206
+ * Map of organ IDs to their SVG components
207
+ */
208
+ declare const ORGAN_COMPONENTS: Record<OrganId, ComponentType<OrganSvgProps>>;
209
+
210
+ interface UseOrganInteractionOptions {
211
+ /** Controlled hover state from parent */
212
+ hoveredOrgan?: OrganId | null;
213
+ /** Controlled selected state from parent */
214
+ selectedOrgan?: OrganId | null;
215
+ /** Callback when hover state changes */
216
+ onHover?: (organId: OrganId | null) => void;
217
+ /** Callback when selected state changes */
218
+ onSelect?: (organId: OrganId | null) => void;
219
+ }
220
+ interface UseOrganInteractionResult {
221
+ /** Current interaction state */
222
+ state: OrganInteractionState;
223
+ /** Event handlers for organs */
224
+ handlers: OrganInteractionHandlers;
225
+ /** Check if an organ is currently highlighted (hovered or selected) */
226
+ isHighlighted: (organId: OrganId) => boolean;
227
+ /** Check if an organ is currently selected */
228
+ isSelected: (organId: OrganId) => boolean;
229
+ /** Check if an organ is currently hovered */
230
+ isHovered: (organId: OrganId) => boolean;
231
+ }
232
+ /**
233
+ * Hook to manage organ hover and click interactions
234
+ *
235
+ * Behavior:
236
+ * - Mouse enter on organ updates hoveredOrgan and calls onHover
237
+ * - Click on organ sets selectedOrgan and calls onSelect
238
+ * - Click on already selected organ deselects it
239
+ * - Click on different organ changes selection
240
+ * - Hover effects work independently even when an organ is selected
241
+ */
242
+ declare function useOrganInteraction(options?: UseOrganInteractionOptions): UseOrganInteractionResult;
243
+
244
+ export { ANIMATION_DURATION_MS, type ColorScale as ColorPalette, type ColorName as ColorScheme, DEFAULT_COLOR_PALETTE, HpoVisualizer, type HpoVisualizerProps, ORGAN_COMPONENTS, ORGAN_IDS, ORGAN_NAMES_EN, ORGAN_NAMES_KO, type OrganConfig, type OrganId, type OrganInteractionHandlers, type OrganInteractionState, type OrganStyle, OrganSvg, type OrganSvgProps, type OrganSvgWrapperProps, type UseOrganInteractionOptions, type UseOrganInteractionResult, useOrganInteraction };