@cyber-harbour/ui 1.0.66 → 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.d.mts +50 -1
- package/dist/index.d.ts +50 -1
- package/dist/index.js +199 -171
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +238 -210
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/Core/IconComponents/RotateLeftIcon.tsx +24 -0
- package/src/Core/IconComponents/RotateRightIcon.tsx +24 -0
- package/src/Core/IconComponents/index.ts +2 -0
- package/src/Core/Overlay/Overlay.tsx +92 -0
- package/src/Core/Overlay/index.ts +1 -0
- package/src/Core/index.ts +1 -0
- package/src/Graph2D/Graph2D.tsx +105 -37
- package/src/Theme/themes/dark.ts +7 -2
- package/src/Theme/themes/light.ts +5 -0
- package/src/Theme/types.ts +5 -0
package/package.json
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { SVGProps } from 'react';
|
|
2
|
+
|
|
3
|
+
interface RotateLeftIconProps extends SVGProps<SVGSVGElement> {
|
|
4
|
+
fill?: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const RotateLeftIcon = ({ fill = 'currentColor', ...props }: RotateLeftIconProps) => {
|
|
8
|
+
return (
|
|
9
|
+
<svg viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
|
|
10
|
+
<path
|
|
11
|
+
d="M8.37229 15.6666C4.90562 15.6666 2.09229 12.8466 2.09229 9.38659C2.09229 8.13993 2.45895 6.93326 3.15229 5.89326C3.30562 5.66659 3.61895 5.59993 3.84562 5.75326C4.07229 5.9066 4.13895 6.21993 3.98562 6.44659C3.40562 7.31326 3.09895 8.33326 3.09895 9.37993C3.09895 12.2933 5.46562 14.6599 8.37895 14.6599C11.2923 14.6599 13.659 12.2933 13.659 9.37993C13.659 6.46659 11.2856 4.09993 8.37229 4.09993C7.75895 4.09993 7.15895 4.18659 6.59229 4.35993C6.32562 4.43993 6.04562 4.29326 5.96562 4.02659C5.88562 3.75993 6.03229 3.47993 6.29895 3.39993C6.96562 3.19993 7.65895 3.09326 8.37229 3.09326C11.839 3.09326 14.6523 5.91326 14.6523 9.37326C14.6523 12.8333 11.839 15.6666 8.37229 15.6666Z"
|
|
12
|
+
fill={fill}
|
|
13
|
+
/>
|
|
14
|
+
<path
|
|
15
|
+
d="M5.61881 4.54658C5.50548 4.54658 5.38548 4.50658 5.29215 4.42658C5.07881 4.23992 5.05881 3.92658 5.23881 3.71992L7.16548 1.50658C7.34548 1.29992 7.66548 1.27325 7.87215 1.45992C8.07881 1.63992 8.09881 1.95992 7.91881 2.16658L5.99215 4.37325C5.89215 4.48658 5.75215 4.54658 5.61881 4.54658Z"
|
|
16
|
+
fill={fill}
|
|
17
|
+
/>
|
|
18
|
+
<path
|
|
19
|
+
d="M7.86545 6.18659C7.76545 6.18659 7.65879 6.15325 7.57212 6.09325L5.31879 4.44659C5.09879 4.28659 5.05212 3.97325 5.21212 3.75325C5.37212 3.52659 5.68545 3.47992 5.91212 3.63992L8.15879 5.27992C8.37879 5.43992 8.43212 5.75325 8.26545 5.97992C8.17212 6.11992 8.01879 6.18659 7.86545 6.18659Z"
|
|
20
|
+
fill={fill}
|
|
21
|
+
/>
|
|
22
|
+
</svg>
|
|
23
|
+
);
|
|
24
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { SVGProps } from 'react';
|
|
2
|
+
|
|
3
|
+
interface RotateRightIconProps extends SVGProps<SVGSVGElement> {
|
|
4
|
+
fill?: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const RotateRightIcon = ({ fill = 'currentColor', ...props }: RotateRightIconProps) => {
|
|
8
|
+
return (
|
|
9
|
+
<svg viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
|
|
10
|
+
<path
|
|
11
|
+
d="M8.37228 15.6668C4.90562 15.6668 2.09229 12.8468 2.09229 9.38676C2.09229 5.92676 4.90562 3.1001 8.37228 3.1001C9.08562 3.1001 9.77895 3.2001 10.4456 3.40676C10.7123 3.48676 10.859 3.76676 10.779 4.03343C10.699 4.3001 10.419 4.44676 10.1523 4.36676C9.58562 4.19343 8.98562 4.1001 8.37228 4.1001C5.45895 4.1001 3.09229 6.46676 3.09229 9.3801C3.09229 12.2934 5.45895 14.6601 8.37228 14.6601C11.2856 14.6601 13.6523 12.2934 13.6523 9.3801C13.6523 8.32676 13.3456 7.31343 12.7656 6.44676C12.6123 6.2201 12.6723 5.90676 12.9056 5.75343C13.1323 5.6001 13.4456 5.6601 13.599 5.89343C14.2923 6.92676 14.659 8.13343 14.659 9.38676C14.6523 12.8468 11.839 15.6668 8.37228 15.6668Z"
|
|
12
|
+
fill={fill}
|
|
13
|
+
/>
|
|
14
|
+
<path
|
|
15
|
+
d="M11.1252 4.54664C10.9852 4.54664 10.8452 4.48664 10.7452 4.37331L8.81854 2.15998C8.63854 1.95331 8.65854 1.63331 8.86521 1.45331C9.07188 1.27331 9.39188 1.29331 9.57188 1.49998L11.4985 3.71331C11.6785 3.91998 11.6585 4.23998 11.4519 4.41998C11.3652 4.50664 11.2452 4.54664 11.1252 4.54664Z"
|
|
16
|
+
fill={fill}
|
|
17
|
+
/>
|
|
18
|
+
<path
|
|
19
|
+
d="M8.87904 6.18696C8.72571 6.18696 8.57237 6.11363 8.47237 5.9803C8.31237 5.7603 8.35904 5.44696 8.57904 5.2803L10.8257 3.6403C11.0457 3.47363 11.359 3.52696 11.5257 3.74696C11.6924 3.96696 11.639 4.2803 11.419 4.44696L9.17237 6.09363C9.08571 6.1603 8.98571 6.18696 8.87904 6.18696Z"
|
|
20
|
+
fill={fill}
|
|
21
|
+
/>
|
|
22
|
+
</svg>
|
|
23
|
+
);
|
|
24
|
+
};
|
|
@@ -62,3 +62,5 @@ export { PencilIcon } from './PencilIcon';
|
|
|
62
62
|
export { UserInCircleIcon } from './UserInCircle';
|
|
63
63
|
export { FlashIcon } from './FlashIcon';
|
|
64
64
|
export { FolderInfoIcon } from './FolderInfoIcon';
|
|
65
|
+
export { RotateLeftIcon } from './RotateLeftIcon';
|
|
66
|
+
export { RotateRightIcon } from './RotateRightIcon';
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { createPortal } from 'react-dom';
|
|
2
|
+
import { styled } from 'styled-components';
|
|
3
|
+
import { useBodyScrollLock } from '../../utils';
|
|
4
|
+
import { createComponent, createStyledComponent, generatePropertySpaceStyle, StyledFabricComponent } from '../../Theme';
|
|
5
|
+
|
|
6
|
+
type Position = 'start' | 'center' | 'end';
|
|
7
|
+
|
|
8
|
+
export type OverlayProps = {
|
|
9
|
+
children: any;
|
|
10
|
+
onOutsideClick?: () => void;
|
|
11
|
+
append?: any;
|
|
12
|
+
appendPosition?: Position;
|
|
13
|
+
prepend?: any;
|
|
14
|
+
prependPosition?: Position;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const Overlay = createComponent<OverlayProps>(
|
|
18
|
+
({ children, onOutsideClick, prepend, append, prependPosition, appendPosition, ...props }) => {
|
|
19
|
+
useBodyScrollLock(true);
|
|
20
|
+
return createPortal(
|
|
21
|
+
<Container
|
|
22
|
+
{...props}
|
|
23
|
+
onClick={(e) => {
|
|
24
|
+
if (e.target === e.currentTarget && onOutsideClick) {
|
|
25
|
+
onOutsideClick();
|
|
26
|
+
}
|
|
27
|
+
}}
|
|
28
|
+
>
|
|
29
|
+
{!!prepend && <PrependWrapper $position={prependPosition}>{prepend}</PrependWrapper>}
|
|
30
|
+
<StyledWrapper>{children}</StyledWrapper>
|
|
31
|
+
{!!append && <AppendWrapper $position={appendPosition}>{append}</AppendWrapper>}
|
|
32
|
+
</Container>,
|
|
33
|
+
document.body
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const PrependWrapper = styled.div<{ $position?: Position }>(
|
|
39
|
+
({ theme, $position = 'end' }) => `
|
|
40
|
+
position: absolute;
|
|
41
|
+
top: ${theme.overlay.gap};
|
|
42
|
+
z-index: ${theme.zIndex.backdrop};
|
|
43
|
+
${
|
|
44
|
+
$position === 'end'
|
|
45
|
+
? `right: ${theme.overlay.gap};`
|
|
46
|
+
: $position === 'start'
|
|
47
|
+
? `left: ${theme.overlay.gap};`
|
|
48
|
+
: 'left: 50%; transform: translateX(-50%);'
|
|
49
|
+
}
|
|
50
|
+
`
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const AppendWrapper = styled.div<{ $position?: Position }>(
|
|
54
|
+
({ theme, $position = 'center' }) => `
|
|
55
|
+
position: absolute;
|
|
56
|
+
bottom: ${theme.overlay.gap};
|
|
57
|
+
z-index: ${theme.zIndex.backdrop};
|
|
58
|
+
${
|
|
59
|
+
$position === 'end'
|
|
60
|
+
? `right: ${theme.overlay.gap};`
|
|
61
|
+
: $position === 'start'
|
|
62
|
+
? `left: ${theme.overlay.gap};`
|
|
63
|
+
: 'left: 50%; transform: translateX(-50%);'
|
|
64
|
+
}
|
|
65
|
+
`
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
const StyledWrapper = styled.div`
|
|
69
|
+
max-width: 100%;
|
|
70
|
+
max-height: 100%;
|
|
71
|
+
overflow: hidden;
|
|
72
|
+
`;
|
|
73
|
+
|
|
74
|
+
const Container = createStyledComponent(
|
|
75
|
+
styled.div<StyledFabricComponent>(
|
|
76
|
+
({ theme, py = theme.overlay.paddingBlock }) => `
|
|
77
|
+
position: fixed;
|
|
78
|
+
${generatePropertySpaceStyle(theme, 'padding-block', py)};
|
|
79
|
+
top: 0;
|
|
80
|
+
bottom: 0;
|
|
81
|
+
left: 0;
|
|
82
|
+
right: 0;
|
|
83
|
+
min-width: 0;
|
|
84
|
+
display: flex;
|
|
85
|
+
align-items: center;
|
|
86
|
+
justify-content: center;
|
|
87
|
+
background: ${theme.overlay.background};
|
|
88
|
+
z-index: ${theme.zIndex.backdrop};
|
|
89
|
+
|
|
90
|
+
`
|
|
91
|
+
)
|
|
92
|
+
);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Overlay';
|
package/src/Core/index.ts
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
|
);
|
package/src/Theme/themes/dark.ts
CHANGED
|
@@ -922,8 +922,8 @@ export const darkThemePx: Theme = {
|
|
|
922
922
|
},
|
|
923
923
|
color: {
|
|
924
924
|
icon: '#FDC700',
|
|
925
|
-
text: '#
|
|
926
|
-
background: '#
|
|
925
|
+
text: '#FFEDD8',
|
|
926
|
+
background: '#68550E',
|
|
927
927
|
},
|
|
928
928
|
},
|
|
929
929
|
label: {
|
|
@@ -985,6 +985,11 @@ export const darkThemePx: Theme = {
|
|
|
985
985
|
height: 26,
|
|
986
986
|
iconSize: 8,
|
|
987
987
|
},
|
|
988
|
+
overlay: {
|
|
989
|
+
paddingBlock: 40,
|
|
990
|
+
gap: 6,
|
|
991
|
+
background: 'rgba(0, 0, 0, 0.5)',
|
|
992
|
+
},
|
|
988
993
|
};
|
|
989
994
|
|
|
990
995
|
export const darkTheme = convertPaletteToRem(darkThemePx, darkThemePx.baseSize) as DefaultTheme;
|
|
@@ -984,6 +984,11 @@ export const lightThemePx: Theme = {
|
|
|
984
984
|
height: 26,
|
|
985
985
|
iconSize: 8,
|
|
986
986
|
},
|
|
987
|
+
overlay: {
|
|
988
|
+
paddingBlock: 40,
|
|
989
|
+
gap: 6,
|
|
990
|
+
background: 'rgba(16, 16, 16, 0.1)',
|
|
991
|
+
},
|
|
987
992
|
};
|
|
988
993
|
|
|
989
994
|
export const lightTheme = convertPaletteToRem(lightThemePx, lightThemePx.baseSize) as DefaultTheme;
|
package/src/Theme/types.ts
CHANGED