@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyber-harbour/ui",
3
- "version": "1.0.67",
3
+ "version": "1.0.68",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",
@@ -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 buttonRadius = (config.nodeSizeBase * config.nodeAreaFactor) / 2;
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
- [buttons, renderCanvas2D, handleNodeClick, handleBackgroundClick, getLinkAtPosition, handleLinkClick]
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
  );
@@ -922,8 +922,8 @@ export const darkThemePx: Theme = {
922
922
  },
923
923
  color: {
924
924
  icon: '#FDC700',
925
- text: '#894B00',
926
- background: '#FFFBE0',
925
+ text: '#FFEDD8',
926
+ background: '#68550E',
927
927
  },
928
928
  },
929
929
  label: {