@cyber-harbour/ui 1.0.67 → 1.0.68
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.js +150 -150
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +170 -170
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/Graph2D/Graph2D.tsx +105 -37
- package/src/Theme/themes/dark.ts +2 -2
package/package.json
CHANGED
package/src/Graph2D/Graph2D.tsx
CHANGED
|
@@ -1181,6 +1181,49 @@ export const Graph2D: any = forwardRef<Graph2DRef, Graph2DProps>(
|
|
|
1181
1181
|
[getNodeAtPosition]
|
|
1182
1182
|
);
|
|
1183
1183
|
|
|
1184
|
+
const getHoveredIndex = useCallback(
|
|
1185
|
+
(x: number, y: number) => {
|
|
1186
|
+
let hoveredIndex = null;
|
|
1187
|
+
if (canvasRef.current && stateRef.current && buttonImages.length > 0) {
|
|
1188
|
+
const buttonRadius = (config.nodeSizeBase * config.nodeAreaFactor) / 2;
|
|
1189
|
+
const rect = canvasRef.current.getBoundingClientRect();
|
|
1190
|
+
|
|
1191
|
+
// Масштабуємо координати відносно розміру відображення полотна
|
|
1192
|
+
const canvasScaleX = canvasRef.current.width / rect.width;
|
|
1193
|
+
const canvasScaleY = canvasRef.current.height / rect.height;
|
|
1194
|
+
|
|
1195
|
+
// Масштабовані координати миші в системі координат полотна
|
|
1196
|
+
const scaledMouseX = x * canvasScaleX;
|
|
1197
|
+
const scaledMouseY = y * canvasScaleY;
|
|
1198
|
+
|
|
1199
|
+
// Застосовуємо поточну трансформацію для отримання світових координат
|
|
1200
|
+
const worldX = (scaledMouseX - stateRef.current.transform.x) / stateRef.current.transform.k;
|
|
1201
|
+
const worldY = (scaledMouseY - stateRef.current.transform.y) / stateRef.current.transform.k;
|
|
1202
|
+
|
|
1203
|
+
// Node position
|
|
1204
|
+
const nodeX = stateRef.current.selectedNode?.x || 0;
|
|
1205
|
+
const nodeY = stateRef.current.selectedNode?.y || 0;
|
|
1206
|
+
|
|
1207
|
+
// Обчислюємо кількість кнопок та їхні сектори
|
|
1208
|
+
const buttonCount = Math.min(buttonImages.length, 8);
|
|
1209
|
+
const sectorAngle = Math.min((Math.PI * 2) / buttonCount, Math.PI);
|
|
1210
|
+
|
|
1211
|
+
// Перевіряємо, чи вказівник миші знаходиться над будь-яким сектором кнопок
|
|
1212
|
+
for (let i = 0; i < buttonCount; i++) {
|
|
1213
|
+
const startAngle = i * sectorAngle;
|
|
1214
|
+
const endAngle = (i + 1) * sectorAngle;
|
|
1215
|
+
|
|
1216
|
+
if (isPointInButtonSector(worldX, worldY, nodeX, nodeY, buttonRadius, startAngle, endAngle)) {
|
|
1217
|
+
hoveredIndex = i;
|
|
1218
|
+
break;
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
return hoveredIndex;
|
|
1223
|
+
},
|
|
1224
|
+
[buttonImages]
|
|
1225
|
+
);
|
|
1226
|
+
|
|
1184
1227
|
// Обробка руху миші для перетягування та наведення
|
|
1185
1228
|
const handleMouseMove = useCallback(
|
|
1186
1229
|
(event: React.MouseEvent<HTMLCanvasElement>) => {
|
|
@@ -1274,40 +1317,7 @@ export const Graph2D: any = forwardRef<Graph2DRef, Graph2DProps>(
|
|
|
1274
1317
|
|
|
1275
1318
|
// Логіка виявлення наведення на кнопки
|
|
1276
1319
|
if (stateRef.current.selectedNode && canvasRef.current && buttonImages.length > 0) {
|
|
1277
|
-
const
|
|
1278
|
-
|
|
1279
|
-
// Масштабуємо координати відносно розміру відображення полотна
|
|
1280
|
-
const canvasScaleX = canvasRef.current.width / rect.width;
|
|
1281
|
-
const canvasScaleY = canvasRef.current.height / rect.height;
|
|
1282
|
-
|
|
1283
|
-
// Масштабовані координати миші в системі координат полотна
|
|
1284
|
-
const scaledMouseX = x * canvasScaleX;
|
|
1285
|
-
const scaledMouseY = y * canvasScaleY;
|
|
1286
|
-
|
|
1287
|
-
// Застосовуємо поточну трансформацію для отримання світових координат
|
|
1288
|
-
const worldX = (scaledMouseX - stateRef.current.transform.x) / stateRef.current.transform.k;
|
|
1289
|
-
const worldY = (scaledMouseY - stateRef.current.transform.y) / stateRef.current.transform.k;
|
|
1290
|
-
|
|
1291
|
-
// Node position
|
|
1292
|
-
const nodeX = stateRef.current.selectedNode.x || 0;
|
|
1293
|
-
const nodeY = stateRef.current.selectedNode.y || 0;
|
|
1294
|
-
|
|
1295
|
-
// Обчислюємо кількість кнопок та їхні сектори
|
|
1296
|
-
const buttonCount = Math.min(buttonImages.length, 8);
|
|
1297
|
-
const sectorAngle = Math.min((Math.PI * 2) / buttonCount, Math.PI);
|
|
1298
|
-
|
|
1299
|
-
let hoveredIndex = null;
|
|
1300
|
-
|
|
1301
|
-
// Перевіряємо, чи вказівник миші знаходиться над будь-яким сектором кнопок
|
|
1302
|
-
for (let i = 0; i < buttonCount; i++) {
|
|
1303
|
-
const startAngle = i * sectorAngle;
|
|
1304
|
-
const endAngle = (i + 1) * sectorAngle;
|
|
1305
|
-
|
|
1306
|
-
if (isPointInButtonSector(worldX, worldY, nodeX, nodeY, buttonRadius, startAngle, endAngle)) {
|
|
1307
|
-
hoveredIndex = i;
|
|
1308
|
-
break;
|
|
1309
|
-
}
|
|
1310
|
-
}
|
|
1320
|
+
const hoveredIndex = getHoveredIndex(x, y);
|
|
1311
1321
|
if (hoveredIndex !== null) hoveredNode = stateRef.current.selectedNode; // Set hoveredNode to selectedNode for further processing
|
|
1312
1322
|
if (hoveredIndex !== stateRef.current.hoveredButtonIndex) {
|
|
1313
1323
|
shouldRender = true; // Only render if hovered button index has changed
|
|
@@ -1371,6 +1381,7 @@ export const Graph2D: any = forwardRef<Graph2DRef, Graph2DProps>(
|
|
|
1371
1381
|
handleLinkHover,
|
|
1372
1382
|
renderCanvas2D,
|
|
1373
1383
|
isPointInButtonSector,
|
|
1384
|
+
getHoveredIndex,
|
|
1374
1385
|
]
|
|
1375
1386
|
);
|
|
1376
1387
|
|
|
@@ -1396,7 +1407,9 @@ export const Graph2D: any = forwardRef<Graph2DRef, Graph2DProps>(
|
|
|
1396
1407
|
if (rect) {
|
|
1397
1408
|
const x = event.clientX - rect.left;
|
|
1398
1409
|
const y = event.clientY - rect.top;
|
|
1399
|
-
|
|
1410
|
+
if (buttonImages.length > 0 && stateRef.current.hoveredButtonIndex === null) {
|
|
1411
|
+
stateRef.current.hoveredButtonIndex = getHoveredIndex(x, y);
|
|
1412
|
+
}
|
|
1400
1413
|
// Спочатку перевіряємо, чи ми клікаємо на кнопку обраного вузла
|
|
1401
1414
|
let isButtonClick = false;
|
|
1402
1415
|
if (
|
|
@@ -1409,6 +1422,7 @@ export const Graph2D: any = forwardRef<Graph2DRef, Graph2DProps>(
|
|
|
1409
1422
|
if (button && button.onClick) {
|
|
1410
1423
|
button.onClick(stateRef.current.selectedNode);
|
|
1411
1424
|
isButtonClick = true;
|
|
1425
|
+
stateRef.current.hoveredButtonIndex = null;
|
|
1412
1426
|
}
|
|
1413
1427
|
}
|
|
1414
1428
|
|
|
@@ -1465,7 +1479,16 @@ export const Graph2D: any = forwardRef<Graph2DRef, Graph2DProps>(
|
|
|
1465
1479
|
|
|
1466
1480
|
renderCanvas2D();
|
|
1467
1481
|
},
|
|
1468
|
-
[
|
|
1482
|
+
[
|
|
1483
|
+
buttons,
|
|
1484
|
+
renderCanvas2D,
|
|
1485
|
+
handleNodeClick,
|
|
1486
|
+
handleBackgroundClick,
|
|
1487
|
+
getLinkAtPosition,
|
|
1488
|
+
handleLinkClick,
|
|
1489
|
+
getHoveredIndex,
|
|
1490
|
+
buttonImages,
|
|
1491
|
+
]
|
|
1469
1492
|
);
|
|
1470
1493
|
|
|
1471
1494
|
// Обробляємо подію колеса миші для масштабування
|
|
@@ -1509,6 +1532,47 @@ export const Graph2D: any = forwardRef<Graph2DRef, Graph2DProps>(
|
|
|
1509
1532
|
[renderCanvas2D]
|
|
1510
1533
|
);
|
|
1511
1534
|
|
|
1535
|
+
//Обробка подій на тачскрін девайсах
|
|
1536
|
+
const convertTouchToMouseEvent = (
|
|
1537
|
+
e: TouchEvent | React.TouchEvent<HTMLCanvasElement>,
|
|
1538
|
+
callback: (event: React.MouseEvent<HTMLCanvasElement>) => void
|
|
1539
|
+
) => {
|
|
1540
|
+
const touch = e.touches[0];
|
|
1541
|
+
if (touch) {
|
|
1542
|
+
// Create a synthetic React.MouseEvent-like object
|
|
1543
|
+
const syntheticEvent = {
|
|
1544
|
+
clientX: touch.clientX,
|
|
1545
|
+
clientY: touch.clientY,
|
|
1546
|
+
} as React.MouseEvent<HTMLCanvasElement>;
|
|
1547
|
+
callback(syntheticEvent);
|
|
1548
|
+
}
|
|
1549
|
+
};
|
|
1550
|
+
const handleTouchStart = useCallback(
|
|
1551
|
+
(e: React.TouchEvent<HTMLCanvasElement>) => {
|
|
1552
|
+
convertTouchToMouseEvent(e, handleMouseDown);
|
|
1553
|
+
},
|
|
1554
|
+
[handleMouseDown]
|
|
1555
|
+
);
|
|
1556
|
+
|
|
1557
|
+
const handleTouchEnd = useCallback(
|
|
1558
|
+
(e: TouchEvent) => {
|
|
1559
|
+
if (stateRef.current.mustBeStoppedPropagation) {
|
|
1560
|
+
e.preventDefault();
|
|
1561
|
+
e.stopPropagation();
|
|
1562
|
+
}
|
|
1563
|
+
stateRef.current.mustBeStoppedPropagation = false;
|
|
1564
|
+
convertTouchToMouseEvent(e, handleMouseUp);
|
|
1565
|
+
},
|
|
1566
|
+
[handleMouseUp]
|
|
1567
|
+
);
|
|
1568
|
+
|
|
1569
|
+
const handleTouchMove = useCallback(
|
|
1570
|
+
(e: React.TouchEvent<HTMLCanvasElement>) => {
|
|
1571
|
+
convertTouchToMouseEvent(e, handleMouseMove);
|
|
1572
|
+
},
|
|
1573
|
+
[handleMouseMove]
|
|
1574
|
+
);
|
|
1575
|
+
|
|
1512
1576
|
useImperativeHandle(
|
|
1513
1577
|
ref,
|
|
1514
1578
|
() => ({
|
|
@@ -1647,12 +1711,14 @@ export const Graph2D: any = forwardRef<Graph2DRef, Graph2DProps>(
|
|
|
1647
1711
|
|
|
1648
1712
|
// Add event listener with passive: false to allow preventDefault
|
|
1649
1713
|
canvas.addEventListener('wheel', handleWheel, { passive: false });
|
|
1714
|
+
canvas.addEventListener('touchend', handleTouchEnd, { passive: false });
|
|
1650
1715
|
|
|
1651
1716
|
// Clean up when component unmounts
|
|
1652
1717
|
return () => {
|
|
1653
1718
|
canvas.removeEventListener('wheel', handleWheel);
|
|
1719
|
+
canvas.removeEventListener('touchend', handleTouchEnd);
|
|
1654
1720
|
};
|
|
1655
|
-
}, [handleWheel]);
|
|
1721
|
+
}, [handleWheel, handleTouchEnd]);
|
|
1656
1722
|
|
|
1657
1723
|
return (
|
|
1658
1724
|
<Wrapper>
|
|
@@ -1665,6 +1731,8 @@ export const Graph2D: any = forwardRef<Graph2DRef, Graph2DProps>(
|
|
|
1665
1731
|
onMouseUp={handleMouseUp}
|
|
1666
1732
|
onMouseLeave={handleMouseUp}
|
|
1667
1733
|
onClick={handleClick}
|
|
1734
|
+
onTouchStart={handleTouchStart}
|
|
1735
|
+
onTouchMove={handleTouchMove}
|
|
1668
1736
|
/>
|
|
1669
1737
|
</Wrapper>
|
|
1670
1738
|
);
|