@cyber-harbour/ui 1.0.70 → 1.0.71

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.70",
3
+ "version": "1.0.71",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",
@@ -95,6 +95,11 @@ export const Graph2D: any = forwardRef<Graph2DRef, Graph2DProps>(
95
95
  isDragging: false,
96
96
  width: width * RATIO,
97
97
  height: height * RATIO,
98
+ animation: {
99
+ id: null,
100
+ buttonIndex: null,
101
+ },
102
+ spinnerAngle: 0,
98
103
  });
99
104
 
100
105
  const { nodes, links } = useMemo(() => cloneDeep(graphData), [graphData]);
@@ -451,38 +456,65 @@ export const Graph2D: any = forwardRef<Graph2DRef, Graph2DProps>(
451
456
  const buttonImage = buttonImages[i];
452
457
  // Якщо кнопка в лоадінгу — малюємо спінер
453
458
  if (buttonImage.loading) {
454
- const spinnerRadius = iconSize / 3;
455
- const spinnerLineLength = iconSize / 3;
456
- const spinnerLineWidth = 1;
459
+ const spinnerRadius = iconSize / 2;
460
+ const dotRadius = iconSize / 12;
457
461
 
458
462
  ctx.save();
459
463
  ctx.translate(iconX, iconY);
464
+ ctx.rotate(stateRef.current.spinnerAngle);
460
465
 
461
466
  // Малюємо кілька променів (ліній) по колу
462
467
  for (let j = 0; j < 12; j++) {
468
+ const angle = (Math.PI * 2 * j) / 12;
463
469
  const alpha = j / 12;
470
+
471
+ const dotX = Math.cos(angle) * spinnerRadius;
472
+ const dotY = Math.sin(angle) * spinnerRadius;
473
+
464
474
  ctx.beginPath();
465
- ctx.strokeStyle = hexToRgba(theme.colors.primary.main, alpha);
466
- ctx.lineWidth = spinnerLineWidth;
467
- ctx.moveTo(0, -spinnerRadius);
468
- ctx.lineTo(0, -spinnerRadius - spinnerLineLength);
469
- ctx.stroke();
470
- ctx.rotate((Math.PI * 2) / 12);
475
+ ctx.fillStyle = hexToRgba(theme.graph2D?.button?.spinnerColor, alpha);
476
+ ctx.arc(dotX, dotY, dotRadius, 0, Math.PI * 2);
477
+ ctx.fill();
471
478
  }
472
-
473
479
  ctx.restore();
480
+
481
+ stateRef.current.spinnerAngle += 0.1;
482
+ if (stateRef.current.spinnerAngle > Math.PI * 2) {
483
+ stateRef.current.spinnerAngle -= Math.PI * 2;
484
+ }
485
+ if (stateRef.current.animation.id !== null) {
486
+ cancelAnimationFrame(stateRef.current.animation.id);
487
+ stateRef.current.animation.id = null;
488
+ stateRef.current.animation.buttonIndex = null;
489
+ }
490
+
491
+ stateRef.current.animation.id = requestAnimationFrame(renderCanvas2D);
492
+ stateRef.current.animation.buttonIndex = i;
474
493
  } else {
494
+ if (stateRef.current.animation.id && stateRef.current.animation.buttonIndex === i) {
495
+ cancelAnimationFrame(stateRef.current.animation.id);
496
+ stateRef.current.animation.id = null;
497
+ stateRef.current.animation.buttonIndex = null;
498
+ }
475
499
  const icon = isHovered ? buttonImage.hoverImg : buttonImage.normalImg;
476
500
  //каунтер може не існувати
477
- const counter = buttonImage.count ? buttonImage.count(node) : null;
501
+ const counter = buttonImage.getCount ? buttonImage.getCount(node) : null;
478
502
  // Малюємо іконку
479
503
  if (icon.complete) {
480
- drawIconWithOptionalCounter(ctx, icon, iconX, iconY, iconSize, counter, theme.colors?.text?.lighter);
504
+ drawIconWithOptionalCounter(ctx, icon, iconX, iconY, iconSize, counter, theme.graph2D?.button?.textColor);
481
505
  } else {
482
506
  // Встановлюємо обробник onload, якщо зображення ще не завантажено
483
507
  icon.onload = () => {
484
508
  if (ctx2dRef.current) {
485
- drawIconWithOptionalCounter(ctx, icon, iconX, iconY, iconSize, counter, theme.colors?.text?.lighter);
509
+ drawIconWithOptionalCounter(
510
+ ctx,
511
+ icon,
512
+ iconX,
513
+ iconY,
514
+ iconSize,
515
+ counter,
516
+ theme.graph2D?.button?.textColor
517
+ );
486
518
  }
487
519
  };
488
520
  }
@@ -491,7 +523,7 @@ export const Graph2D: any = forwardRef<Graph2DRef, Graph2DProps>(
491
523
 
492
524
  ctx.restore();
493
525
  },
494
- [buttonImages, theme.graph2D?.button, theme.colors?.text?.lighter]
526
+ [buttonImages, theme.graph2D?.button]
495
527
  );
496
528
 
497
529
  const renderNodes = useCallback(
@@ -63,6 +63,13 @@ export interface GraphState {
63
63
  isDragging: boolean;
64
64
  width: number;
65
65
  height: number;
66
+ /** Поточна анімація */
67
+ animation: {
68
+ id: number | null;
69
+ buttonIndex: number | null;
70
+ };
71
+ /** Кут оберту спінера */
72
+ spinnerAngle: number;
66
73
  }
67
74
 
68
75
  export interface Graph2DProps {
@@ -88,7 +95,7 @@ export interface NodeButton {
88
95
  img: string;
89
96
  hoverImg: string;
90
97
  loading?: boolean;
91
- count?: (node: NodeObject) => number;
98
+ getCount?: (node: NodeObject) => number;
92
99
  onClick: (node: NodeObject) => void;
93
100
  }
94
101
 
@@ -857,6 +857,8 @@ export const darkThemePx: Theme = {
857
857
  stroke: '#1A1A1A',
858
858
  normalFill: 'rgba(0, 0, 0, 0.8)',
859
859
  hoverFill: 'rgba(25, 25, 25, 0.9)',
860
+ textColor: '#99989C',
861
+ spinnerColor: '#80A0F5',
860
862
  },
861
863
  grid: {
862
864
  dotColor: 'rgba(255, 255, 255, 0.5)',
@@ -856,6 +856,8 @@ export const lightThemePx: Theme = {
856
856
  stroke: '#e5e5e5',
857
857
  normalFill: 'rgba(255, 255, 255, 0.8)',
858
858
  hoverFill: 'rgba(230, 230, 230, 0.9)',
859
+ textColor: '#99989C',
860
+ spinnerColor: '#80A0F5',
859
861
  },
860
862
  grid: {
861
863
  dotColor: 'rgba(0, 0, 0, 0.5)',
@@ -253,6 +253,8 @@ export type Theme = {
253
253
  stroke: string;
254
254
  normalFill: string;
255
255
  hoverFill: string;
256
+ textColor: string;
257
+ spinnerColor: string;
256
258
  };
257
259
  grid: {
258
260
  dotColor: string;