hpo-react-visualizer 0.0.1 → 0.0.2
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/dist/index.cjs +376 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -2
- package/dist/index.d.ts +23 -2
- package/dist/index.js +376 -30
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/HpoVisualizer.tsx +88 -22
- package/src/ZoomControls.tsx +125 -0
- package/src/__tests__/hpoLabel.test.ts +71 -0
- package/src/__tests__/useZoom.test.ts +110 -0
- package/src/__tests__/zoomControls.test.tsx +106 -0
- package/src/constants.ts +90 -1
- package/src/index.ts +4 -0
- package/src/types.ts +32 -0
- package/src/useZoom.ts +196 -0
package/dist/index.cjs
CHANGED
|
@@ -80,6 +80,82 @@ var ORGAN_NAMES_KO = {
|
|
|
80
80
|
prenatal: "\uD0DC\uC544",
|
|
81
81
|
blood: "\uD608\uC561"
|
|
82
82
|
};
|
|
83
|
+
var HPO_LABELS = [
|
|
84
|
+
"others",
|
|
85
|
+
"Growth abnormality",
|
|
86
|
+
"Abnormality of the genitourinary system",
|
|
87
|
+
"Abnormality of the immune system",
|
|
88
|
+
"Abnormality of the digestive system",
|
|
89
|
+
"Abnormality of metabolism/homeostasis",
|
|
90
|
+
"Abnormality of head or neck",
|
|
91
|
+
"Abnormality of the musculoskeletal system",
|
|
92
|
+
"Abnormality of the nervous system",
|
|
93
|
+
"Abnormality of the respiratory system",
|
|
94
|
+
"Abnormality of the eye",
|
|
95
|
+
"Abnormality of the cardiovascular system",
|
|
96
|
+
"Abnormality of the ear",
|
|
97
|
+
"Abnormality of prenatal development or birth",
|
|
98
|
+
"Abnormality of the integument",
|
|
99
|
+
"Abnormality of the breast",
|
|
100
|
+
"Abnormality of the endocrine system",
|
|
101
|
+
"Abnormality of blood and blood-forming tissues",
|
|
102
|
+
"Abnormality of limbs",
|
|
103
|
+
"Abnormality of the voice",
|
|
104
|
+
"Constitutional symptom",
|
|
105
|
+
"Neoplasm",
|
|
106
|
+
"Abnormal cellular phenotype",
|
|
107
|
+
"Abnormality of the thoracic cavity"
|
|
108
|
+
];
|
|
109
|
+
var HPO_LABEL_TO_ORGAN = {
|
|
110
|
+
"Growth abnormality": "growth",
|
|
111
|
+
"Abnormality of the genitourinary system": "kidney",
|
|
112
|
+
"Abnormality of the immune system": "immune",
|
|
113
|
+
"Abnormality of the digestive system": "digestive",
|
|
114
|
+
"Abnormality of metabolism/homeostasis": "metabolism",
|
|
115
|
+
"Abnormality of head or neck": "head",
|
|
116
|
+
"Abnormality of the musculoskeletal system": "muscle",
|
|
117
|
+
"Abnormality of the nervous system": "nervous",
|
|
118
|
+
"Abnormality of the respiratory system": "lung",
|
|
119
|
+
"Abnormality of the eye": "eye",
|
|
120
|
+
"Abnormality of the cardiovascular system": "heart",
|
|
121
|
+
"Abnormality of the ear": "ear",
|
|
122
|
+
"Abnormality of prenatal development or birth": "prenatal",
|
|
123
|
+
"Abnormality of the integument": "integument",
|
|
124
|
+
"Abnormality of the breast": "breast",
|
|
125
|
+
"Abnormality of the endocrine system": "endocrine",
|
|
126
|
+
"Abnormality of blood and blood-forming tissues": "blood",
|
|
127
|
+
"Abnormality of limbs": "limbs",
|
|
128
|
+
"Abnormality of the voice": "voice",
|
|
129
|
+
"Constitutional symptom": "constitutional",
|
|
130
|
+
Neoplasm: "neoplasm",
|
|
131
|
+
"Abnormal cellular phenotype": "cell",
|
|
132
|
+
"Abnormality of the thoracic cavity": "thoracicCavity"
|
|
133
|
+
};
|
|
134
|
+
var ORGAN_TO_HPO_LABEL = {
|
|
135
|
+
growth: "Growth abnormality",
|
|
136
|
+
kidney: "Abnormality of the genitourinary system",
|
|
137
|
+
immune: "Abnormality of the immune system",
|
|
138
|
+
digestive: "Abnormality of the digestive system",
|
|
139
|
+
metabolism: "Abnormality of metabolism/homeostasis",
|
|
140
|
+
head: "Abnormality of head or neck",
|
|
141
|
+
muscle: "Abnormality of the musculoskeletal system",
|
|
142
|
+
nervous: "Abnormality of the nervous system",
|
|
143
|
+
lung: "Abnormality of the respiratory system",
|
|
144
|
+
eye: "Abnormality of the eye",
|
|
145
|
+
heart: "Abnormality of the cardiovascular system",
|
|
146
|
+
ear: "Abnormality of the ear",
|
|
147
|
+
prenatal: "Abnormality of prenatal development or birth",
|
|
148
|
+
integument: "Abnormality of the integument",
|
|
149
|
+
breast: "Abnormality of the breast",
|
|
150
|
+
endocrine: "Abnormality of the endocrine system",
|
|
151
|
+
blood: "Abnormality of blood and blood-forming tissues",
|
|
152
|
+
limbs: "Abnormality of limbs",
|
|
153
|
+
voice: "Abnormality of the voice",
|
|
154
|
+
constitutional: "Constitutional symptom",
|
|
155
|
+
neoplasm: "Neoplasm",
|
|
156
|
+
cell: "Abnormal cellular phenotype",
|
|
157
|
+
thoracicCavity: "Abnormality of the thoracic cavity"
|
|
158
|
+
};
|
|
83
159
|
var DEFAULT_COLOR_PALETTE = {
|
|
84
160
|
blue: {
|
|
85
161
|
100: "#DBEAFE",
|
|
@@ -1303,6 +1379,211 @@ function useOrganInteraction(options = {}) {
|
|
|
1303
1379
|
isHovered
|
|
1304
1380
|
};
|
|
1305
1381
|
}
|
|
1382
|
+
function useZoom(options = {}) {
|
|
1383
|
+
const { minZoom = 1, maxZoom = 5, zoomStep = 0.5 } = options;
|
|
1384
|
+
const [zoom, setZoom] = react.useState(1);
|
|
1385
|
+
const [pan, setPan] = react.useState({ x: 0, y: 0 });
|
|
1386
|
+
const [isDragging, setIsDragging] = react.useState(false);
|
|
1387
|
+
const dragStartRef = react.useRef({ x: 0, y: 0 });
|
|
1388
|
+
const panStartRef = react.useRef({ x: 0, y: 0 });
|
|
1389
|
+
const containerRef = react.useRef(null);
|
|
1390
|
+
const clampZoom = react.useCallback(
|
|
1391
|
+
(value) => Math.max(minZoom, Math.min(maxZoom, value)),
|
|
1392
|
+
[minZoom, maxZoom]
|
|
1393
|
+
);
|
|
1394
|
+
const zoomIn = react.useCallback(() => {
|
|
1395
|
+
setZoom((prev) => clampZoom(prev + zoomStep));
|
|
1396
|
+
}, [clampZoom, zoomStep]);
|
|
1397
|
+
const zoomOut = react.useCallback(() => {
|
|
1398
|
+
setZoom((prev) => clampZoom(prev - zoomStep));
|
|
1399
|
+
}, [clampZoom, zoomStep]);
|
|
1400
|
+
const resetZoom = react.useCallback(() => {
|
|
1401
|
+
setZoom(1);
|
|
1402
|
+
setPan({ x: 0, y: 0 });
|
|
1403
|
+
}, []);
|
|
1404
|
+
react.useEffect(() => {
|
|
1405
|
+
const container = containerRef.current;
|
|
1406
|
+
if (!container) return;
|
|
1407
|
+
const wheelZoomStep = 0.1;
|
|
1408
|
+
const handleWheel = (e) => {
|
|
1409
|
+
e.preventDefault();
|
|
1410
|
+
const rect = container.getBoundingClientRect();
|
|
1411
|
+
const mouseX = e.clientX - rect.left - rect.width / 2;
|
|
1412
|
+
const mouseY = e.clientY - rect.top - rect.height / 2;
|
|
1413
|
+
const delta = e.deltaY > 0 ? -wheelZoomStep : wheelZoomStep;
|
|
1414
|
+
setZoom((prevZoom) => {
|
|
1415
|
+
const newZoom = clampZoom(prevZoom + delta);
|
|
1416
|
+
if (newZoom === prevZoom) return prevZoom;
|
|
1417
|
+
setPan((prevPan) => {
|
|
1418
|
+
const contentX = (mouseX - prevPan.x) / prevZoom;
|
|
1419
|
+
const contentY = (mouseY - prevPan.y) / prevZoom;
|
|
1420
|
+
const newPanX = mouseX - contentX * newZoom;
|
|
1421
|
+
const newPanY = mouseY - contentY * newZoom;
|
|
1422
|
+
if (newZoom <= 1) {
|
|
1423
|
+
return { x: 0, y: 0 };
|
|
1424
|
+
}
|
|
1425
|
+
const maxPanX = rect.width * (newZoom - 1) / 2;
|
|
1426
|
+
const maxPanY = rect.height * (newZoom - 1) / 2;
|
|
1427
|
+
return {
|
|
1428
|
+
x: Math.max(-maxPanX, Math.min(maxPanX, newPanX)),
|
|
1429
|
+
y: Math.max(-maxPanY, Math.min(maxPanY, newPanY))
|
|
1430
|
+
};
|
|
1431
|
+
});
|
|
1432
|
+
return newZoom;
|
|
1433
|
+
});
|
|
1434
|
+
};
|
|
1435
|
+
container.addEventListener("wheel", handleWheel, { passive: false });
|
|
1436
|
+
return () => {
|
|
1437
|
+
container.removeEventListener("wheel", handleWheel);
|
|
1438
|
+
};
|
|
1439
|
+
}, [clampZoom]);
|
|
1440
|
+
const clampPan = react.useCallback((newPan, currentZoom) => {
|
|
1441
|
+
const container = containerRef.current;
|
|
1442
|
+
if (!container || currentZoom <= 1) {
|
|
1443
|
+
return { x: 0, y: 0 };
|
|
1444
|
+
}
|
|
1445
|
+
const containerWidth = container.clientWidth;
|
|
1446
|
+
const containerHeight = container.clientHeight;
|
|
1447
|
+
const maxPanX = containerWidth * (currentZoom - 1) / 2;
|
|
1448
|
+
const maxPanY = containerHeight * (currentZoom - 1) / 2;
|
|
1449
|
+
return {
|
|
1450
|
+
x: Math.max(-maxPanX, Math.min(maxPanX, newPan.x)),
|
|
1451
|
+
y: Math.max(-maxPanY, Math.min(maxPanY, newPan.y))
|
|
1452
|
+
};
|
|
1453
|
+
}, []);
|
|
1454
|
+
react.useEffect(() => {
|
|
1455
|
+
setPan((currentPan) => clampPan(currentPan, zoom));
|
|
1456
|
+
}, [zoom, clampPan]);
|
|
1457
|
+
const handleMouseDown = react.useCallback(
|
|
1458
|
+
(e) => {
|
|
1459
|
+
if (e.button !== 0 || zoom <= 1) return;
|
|
1460
|
+
setIsDragging(true);
|
|
1461
|
+
dragStartRef.current = { x: e.clientX, y: e.clientY };
|
|
1462
|
+
panStartRef.current = { ...pan };
|
|
1463
|
+
e.preventDefault();
|
|
1464
|
+
},
|
|
1465
|
+
[pan, zoom]
|
|
1466
|
+
);
|
|
1467
|
+
const handleMouseMove = react.useCallback(
|
|
1468
|
+
(e) => {
|
|
1469
|
+
if (!isDragging || zoom <= 1) return;
|
|
1470
|
+
const dx = e.clientX - dragStartRef.current.x;
|
|
1471
|
+
const dy = e.clientY - dragStartRef.current.y;
|
|
1472
|
+
const newPan = {
|
|
1473
|
+
x: panStartRef.current.x + dx,
|
|
1474
|
+
y: panStartRef.current.y + dy
|
|
1475
|
+
};
|
|
1476
|
+
setPan(clampPan(newPan, zoom));
|
|
1477
|
+
},
|
|
1478
|
+
[isDragging, zoom, clampPan]
|
|
1479
|
+
);
|
|
1480
|
+
const handleMouseUp = react.useCallback(() => {
|
|
1481
|
+
setIsDragging(false);
|
|
1482
|
+
}, []);
|
|
1483
|
+
const isDefaultZoom = zoom === 1 && pan.x === 0 && pan.y === 0;
|
|
1484
|
+
return {
|
|
1485
|
+
zoom,
|
|
1486
|
+
pan,
|
|
1487
|
+
zoomIn,
|
|
1488
|
+
zoomOut,
|
|
1489
|
+
resetZoom,
|
|
1490
|
+
handleMouseDown,
|
|
1491
|
+
handleMouseMove,
|
|
1492
|
+
handleMouseUp,
|
|
1493
|
+
isDragging,
|
|
1494
|
+
isDefaultZoom,
|
|
1495
|
+
containerRef
|
|
1496
|
+
};
|
|
1497
|
+
}
|
|
1498
|
+
var buttonBaseStyle = {
|
|
1499
|
+
width: 32,
|
|
1500
|
+
height: 32,
|
|
1501
|
+
display: "flex",
|
|
1502
|
+
alignItems: "center",
|
|
1503
|
+
justifyContent: "center",
|
|
1504
|
+
backgroundColor: "rgba(255, 255, 255, 0.9)",
|
|
1505
|
+
border: "1px solid #d1d5db",
|
|
1506
|
+
borderRadius: 6,
|
|
1507
|
+
cursor: "pointer",
|
|
1508
|
+
fontSize: 18,
|
|
1509
|
+
fontWeight: "bold",
|
|
1510
|
+
color: "#374151",
|
|
1511
|
+
transition: "background-color 0.15s ease",
|
|
1512
|
+
userSelect: "none"
|
|
1513
|
+
};
|
|
1514
|
+
var buttonDisabledStyle = {
|
|
1515
|
+
...buttonBaseStyle,
|
|
1516
|
+
opacity: 0.4,
|
|
1517
|
+
cursor: "not-allowed"
|
|
1518
|
+
};
|
|
1519
|
+
var getContainerStyle = (isVisible) => ({
|
|
1520
|
+
position: "absolute",
|
|
1521
|
+
bottom: 12,
|
|
1522
|
+
right: 12,
|
|
1523
|
+
display: "flex",
|
|
1524
|
+
flexDirection: "column",
|
|
1525
|
+
gap: 4,
|
|
1526
|
+
zIndex: 10,
|
|
1527
|
+
opacity: isVisible ? 1 : 0,
|
|
1528
|
+
transition: "opacity 0.2s ease-in-out",
|
|
1529
|
+
pointerEvents: isVisible ? "auto" : "none"
|
|
1530
|
+
});
|
|
1531
|
+
var getResetContainerStyle = (isVisible) => ({
|
|
1532
|
+
position: "absolute",
|
|
1533
|
+
bottom: 12,
|
|
1534
|
+
left: 12,
|
|
1535
|
+
zIndex: 10,
|
|
1536
|
+
opacity: isVisible ? 1 : 0,
|
|
1537
|
+
transition: "opacity 0.2s ease-in-out",
|
|
1538
|
+
pointerEvents: isVisible ? "auto" : "none"
|
|
1539
|
+
});
|
|
1540
|
+
var resetButtonStyle = {
|
|
1541
|
+
...buttonBaseStyle,
|
|
1542
|
+
width: "auto",
|
|
1543
|
+
padding: "6px 12px",
|
|
1544
|
+
fontSize: 12,
|
|
1545
|
+
fontWeight: 500
|
|
1546
|
+
};
|
|
1547
|
+
function ZoomControls({
|
|
1548
|
+
onZoomIn,
|
|
1549
|
+
onZoomOut,
|
|
1550
|
+
onReset,
|
|
1551
|
+
showResetButton,
|
|
1552
|
+
zoom,
|
|
1553
|
+
minZoom,
|
|
1554
|
+
maxZoom,
|
|
1555
|
+
isVisible
|
|
1556
|
+
}) {
|
|
1557
|
+
const isMinZoom = zoom <= minZoom;
|
|
1558
|
+
const isMaxZoom = zoom >= maxZoom;
|
|
1559
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1560
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: getContainerStyle(isVisible), children: [
|
|
1561
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1562
|
+
"button",
|
|
1563
|
+
{
|
|
1564
|
+
type: "button",
|
|
1565
|
+
onClick: onZoomIn,
|
|
1566
|
+
disabled: isMaxZoom,
|
|
1567
|
+
style: isMaxZoom ? buttonDisabledStyle : buttonBaseStyle,
|
|
1568
|
+
"aria-label": "Zoom in",
|
|
1569
|
+
children: "+"
|
|
1570
|
+
}
|
|
1571
|
+
),
|
|
1572
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1573
|
+
"button",
|
|
1574
|
+
{
|
|
1575
|
+
type: "button",
|
|
1576
|
+
onClick: onZoomOut,
|
|
1577
|
+
disabled: isMinZoom,
|
|
1578
|
+
style: isMinZoom ? buttonDisabledStyle : buttonBaseStyle,
|
|
1579
|
+
"aria-label": "Zoom out",
|
|
1580
|
+
children: "\u2212"
|
|
1581
|
+
}
|
|
1582
|
+
)
|
|
1583
|
+
] }),
|
|
1584
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: getResetContainerStyle(isVisible && showResetButton), children: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onReset, style: resetButtonStyle, "aria-label": "Reset zoom", children: "\u21BA" }) })
|
|
1585
|
+
] });
|
|
1586
|
+
}
|
|
1306
1587
|
var ORGAN_POSITIONS = {
|
|
1307
1588
|
growth: { x: 104, y: 1, width: 12, height: 349, viewBox: "0 0 12 349" },
|
|
1308
1589
|
constitutional: { x: 0, y: 0, width: 122, height: 358, viewBox: "0 0 122 358" },
|
|
@@ -1353,6 +1634,7 @@ var FOREGROUND_ORGANS = [
|
|
|
1353
1634
|
"prenatal",
|
|
1354
1635
|
"blood"
|
|
1355
1636
|
];
|
|
1637
|
+
var MIN_ZOOM = 1;
|
|
1356
1638
|
function HpoVisualizer({
|
|
1357
1639
|
organs,
|
|
1358
1640
|
visibleOrgans,
|
|
@@ -1364,9 +1646,24 @@ function HpoVisualizer({
|
|
|
1364
1646
|
width = BODY_VIEWBOX.width,
|
|
1365
1647
|
height = BODY_VIEWBOX.height,
|
|
1366
1648
|
className,
|
|
1367
|
-
style
|
|
1649
|
+
style,
|
|
1650
|
+
maxZoom = 5
|
|
1368
1651
|
}) {
|
|
1369
1652
|
const visualizerID = react.useId();
|
|
1653
|
+
const [isHovering, setIsHovering] = react.useState(false);
|
|
1654
|
+
const {
|
|
1655
|
+
zoom,
|
|
1656
|
+
pan,
|
|
1657
|
+
zoomIn,
|
|
1658
|
+
zoomOut,
|
|
1659
|
+
resetZoom,
|
|
1660
|
+
handleMouseDown,
|
|
1661
|
+
handleMouseMove,
|
|
1662
|
+
handleMouseUp,
|
|
1663
|
+
isDragging,
|
|
1664
|
+
isDefaultZoom,
|
|
1665
|
+
containerRef
|
|
1666
|
+
} = useZoom({ minZoom: MIN_ZOOM, maxZoom });
|
|
1370
1667
|
const colorPalette = react.useMemo(
|
|
1371
1668
|
() => createStrictColorPalette(inputColorPalette),
|
|
1372
1669
|
[inputColorPalette]
|
|
@@ -1403,7 +1700,19 @@ function HpoVisualizer({
|
|
|
1403
1700
|
position: "relative",
|
|
1404
1701
|
width,
|
|
1405
1702
|
height,
|
|
1406
|
-
...style
|
|
1703
|
+
...style,
|
|
1704
|
+
// Apply overflow after style spread to ensure it takes precedence
|
|
1705
|
+
// Use 'clip' instead of 'hidden' to respect padding
|
|
1706
|
+
overflow: "clip"
|
|
1707
|
+
};
|
|
1708
|
+
const contentStyle = {
|
|
1709
|
+
position: "relative",
|
|
1710
|
+
width: "100%",
|
|
1711
|
+
height: "100%",
|
|
1712
|
+
transform: `scale(${zoom}) translate(${pan.x / zoom}px, ${pan.y / zoom}px)`,
|
|
1713
|
+
transformOrigin: "center center",
|
|
1714
|
+
cursor: isDragging ? "grabbing" : zoom > 1 ? "grab" : "default",
|
|
1715
|
+
transition: isDragging ? "none" : "transform 0.1s ease-out"
|
|
1407
1716
|
};
|
|
1408
1717
|
const viewBox = `0 0 ${BODY_VIEWBOX.width} ${BODY_VIEWBOX.height}`;
|
|
1409
1718
|
const scale = Math.min(Number(width) / BODY_VIEWBOX.width, Number(height) / BODY_VIEWBOX.height);
|
|
@@ -1440,43 +1749,83 @@ function HpoVisualizer({
|
|
|
1440
1749
|
`${visualizerID}-${organId}`
|
|
1441
1750
|
);
|
|
1442
1751
|
};
|
|
1443
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1752
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1753
|
+
"div",
|
|
1754
|
+
{
|
|
1755
|
+
ref: containerRef,
|
|
1756
|
+
className,
|
|
1757
|
+
style: containerStyle,
|
|
1758
|
+
onMouseEnter: () => setIsHovering(true),
|
|
1759
|
+
onMouseLeave: () => {
|
|
1760
|
+
setIsHovering(false);
|
|
1761
|
+
handleMouseUp();
|
|
1762
|
+
},
|
|
1763
|
+
onMouseDown: handleMouseDown,
|
|
1764
|
+
onMouseMove: handleMouseMove,
|
|
1765
|
+
onMouseUp: handleMouseUp,
|
|
1766
|
+
role: "application",
|
|
1767
|
+
tabIndex: 0,
|
|
1768
|
+
children: [
|
|
1769
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle, children: [
|
|
1770
|
+
BACKGROUND_ORGANS.map(
|
|
1771
|
+
(organId) => renderOrgan(organId, visibleOrganIds.includes(organId))
|
|
1772
|
+
),
|
|
1773
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1774
|
+
"svg",
|
|
1459
1775
|
{
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1776
|
+
x: translateX,
|
|
1777
|
+
y: "0",
|
|
1778
|
+
width,
|
|
1779
|
+
height,
|
|
1780
|
+
viewBox,
|
|
1781
|
+
style: { position: "absolute", top: "0", left: "0" },
|
|
1782
|
+
pointerEvents: "none",
|
|
1783
|
+
children: [
|
|
1784
|
+
/* @__PURE__ */ jsxRuntime.jsx("title", { children: "Human body" }),
|
|
1785
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1786
|
+
Body,
|
|
1787
|
+
{
|
|
1788
|
+
colorScale: colorPalette[DEFAULT_COLOR_NAME],
|
|
1789
|
+
style: {
|
|
1790
|
+
fill: "#fff"
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
)
|
|
1794
|
+
]
|
|
1464
1795
|
}
|
|
1796
|
+
),
|
|
1797
|
+
FOREGROUND_ORGANS.map(
|
|
1798
|
+
(organId) => renderOrgan(organId, visibleOrganIds.includes(organId))
|
|
1465
1799
|
)
|
|
1466
|
-
]
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1800
|
+
] }),
|
|
1801
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1802
|
+
ZoomControls,
|
|
1803
|
+
{
|
|
1804
|
+
onZoomIn: zoomIn,
|
|
1805
|
+
onZoomOut: zoomOut,
|
|
1806
|
+
onReset: resetZoom,
|
|
1807
|
+
showResetButton: !isDefaultZoom,
|
|
1808
|
+
zoom,
|
|
1809
|
+
minZoom: MIN_ZOOM,
|
|
1810
|
+
maxZoom,
|
|
1811
|
+
isVisible: isHovering
|
|
1812
|
+
}
|
|
1813
|
+
)
|
|
1814
|
+
]
|
|
1815
|
+
}
|
|
1816
|
+
);
|
|
1471
1817
|
}
|
|
1472
1818
|
|
|
1473
1819
|
exports.ANIMATION_DURATION_MS = ANIMATION_DURATION_MS;
|
|
1474
1820
|
exports.DEFAULT_COLOR_PALETTE = DEFAULT_COLOR_PALETTE;
|
|
1821
|
+
exports.HPO_LABELS = HPO_LABELS;
|
|
1822
|
+
exports.HPO_LABEL_TO_ORGAN = HPO_LABEL_TO_ORGAN;
|
|
1475
1823
|
exports.HpoVisualizer = HpoVisualizer;
|
|
1476
1824
|
exports.ORGAN_COMPONENTS = ORGAN_COMPONENTS;
|
|
1477
1825
|
exports.ORGAN_IDS = ORGAN_IDS;
|
|
1478
1826
|
exports.ORGAN_NAMES_EN = ORGAN_NAMES_EN;
|
|
1479
1827
|
exports.ORGAN_NAMES_KO = ORGAN_NAMES_KO;
|
|
1828
|
+
exports.ORGAN_TO_HPO_LABEL = ORGAN_TO_HPO_LABEL;
|
|
1480
1829
|
exports.OrganSvg = OrganSvg;
|
|
1481
1830
|
exports.useOrganInteraction = useOrganInteraction;
|
|
1482
1831
|
//# sourceMappingURL=index.cjs.map
|