@cyber-harbour/ui 1.0.35 → 1.0.37
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 +39 -3
- package/dist/index.d.ts +39 -3
- package/dist/index.js +170 -165
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +170 -165
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/Core/Header/Header.tsx +1 -1
- package/src/Core/Sidebar/Sidebar.tsx +4 -4
- package/src/Core/Sidebar/SidebarDelimeter.tsx +1 -1
- package/src/Core/Sidebar/SidebarItem.tsx +8 -8
- package/src/Graph2D/Graph2D.tsx +20 -14
- package/src/Graph2D/GraphLoader.tsx +9 -21
- package/src/Layouts/PageLayout/PageLayout.tsx +6 -3
- package/src/Theme/GlobalStyle.tsx +9 -3
- package/src/Theme/ThemeProvider.tsx +9 -3
- package/src/Theme/index.ts +1 -1
- package/src/Theme/themes/config.ts +41 -0
- package/src/Theme/themes/dark.ts +707 -0
- package/src/Theme/themes/index.ts +2 -0
- package/src/Theme/{theme.ts → themes/light.ts} +45 -52
- package/src/Theme/types.ts +28 -0
package/package.json
CHANGED
|
@@ -20,7 +20,7 @@ const StyledContainer = styled.header(
|
|
|
20
20
|
padding-right: 20px;
|
|
21
21
|
height: 56px;
|
|
22
22
|
background-color: ${theme.colors.background};
|
|
23
|
-
border-bottom: 1px solid ${theme.colors.stroke.
|
|
23
|
+
border-bottom: 1px solid ${theme.colors.stroke.light};
|
|
24
24
|
|
|
25
25
|
&:before {
|
|
26
26
|
content: '';
|
|
@@ -40,8 +40,8 @@ const StyledContainer = styled.aside<StyledProps>(
|
|
|
40
40
|
width: ${theme.sidebar.width};
|
|
41
41
|
padding: 12px;
|
|
42
42
|
height: 100%;
|
|
43
|
-
border-right: 1px solid ${theme.
|
|
44
|
-
background: ${theme.
|
|
43
|
+
border-right: 1px solid ${theme.sidebar.border};
|
|
44
|
+
background: ${theme.sidebar.background};
|
|
45
45
|
${
|
|
46
46
|
$collapsed
|
|
47
47
|
? `
|
|
@@ -59,8 +59,8 @@ const StyledContainer = styled.aside<StyledProps>(
|
|
|
59
59
|
width: 100%;
|
|
60
60
|
height: 25dvh;
|
|
61
61
|
transform: translateY(-100%);
|
|
62
|
-
background: ${theme.
|
|
63
|
-
border-right: 1px solid ${theme.
|
|
62
|
+
background: ${theme.sidebar.background};
|
|
63
|
+
border-right: 1px solid ${theme.sidebar.border};
|
|
64
64
|
|
|
65
65
|
width: ${theme.sidebar.width};
|
|
66
66
|
${
|
|
@@ -84,15 +84,15 @@ const StyledItem = styled.a<StyledProps>(
|
|
|
84
84
|
cursor: pointer;
|
|
85
85
|
text-decoration: none;
|
|
86
86
|
border-radius: 8px;
|
|
87
|
-
color: ${theme.
|
|
88
|
-
background: ${theme.
|
|
87
|
+
color: ${theme.sidebar.text.default};
|
|
88
|
+
background: ${theme.sidebar.item.default.background};
|
|
89
89
|
transition: background 0.3s ease-in-out, color 0.3s ease-in-out;
|
|
90
90
|
position: relative;
|
|
91
91
|
${
|
|
92
92
|
$active
|
|
93
93
|
? `
|
|
94
|
-
background: ${theme.
|
|
95
|
-
color: ${theme.
|
|
94
|
+
background: ${theme.sidebar.item.active.background};
|
|
95
|
+
color: ${theme.sidebar.text.active};
|
|
96
96
|
`
|
|
97
97
|
: ''
|
|
98
98
|
}
|
|
@@ -101,8 +101,8 @@ const StyledItem = styled.a<StyledProps>(
|
|
|
101
101
|
|
|
102
102
|
|
|
103
103
|
&:hover {
|
|
104
|
-
background: ${theme.
|
|
105
|
-
color: ${theme.
|
|
104
|
+
background: ${theme.sidebar.item.hover.background};
|
|
105
|
+
color: ${theme.sidebar.text.hover};
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
&:before {
|
|
@@ -114,12 +114,12 @@ const StyledItem = styled.a<StyledProps>(
|
|
|
114
114
|
width: 0px;
|
|
115
115
|
border-top-right-radius: 5px;
|
|
116
116
|
border-bottom-right-radius: 5px;
|
|
117
|
-
background:
|
|
117
|
+
background: rgba(0, 0, 0, 0);
|
|
118
118
|
transition: background 0.4s ease-in-out, width 0.3s ease-in-out;
|
|
119
119
|
${
|
|
120
120
|
$active
|
|
121
121
|
? `
|
|
122
|
-
background: ${theme.
|
|
122
|
+
background: ${theme.sidebar.text.active};
|
|
123
123
|
width: 5px;
|
|
124
124
|
`
|
|
125
125
|
: ''
|
package/src/Graph2D/Graph2D.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import ForceGraph2D, { ForceGraphMethods, LinkObject, NodeObject } from 'react-f
|
|
|
2
2
|
import { Graph2DProps } from './types';
|
|
3
3
|
import { useEffect, useRef, useState, useCallback, useLayoutEffect } from 'react';
|
|
4
4
|
import { forceCollide } from 'd3-force';
|
|
5
|
-
import { styled } from 'styled-components';
|
|
5
|
+
import { styled, useTheme } from 'styled-components';
|
|
6
6
|
import eyeLightIcon from './eye_light.png';
|
|
7
7
|
import eyeLightHoverIcon from './eye_light_hover.png';
|
|
8
8
|
import groupLightIcon from './group_light.png';
|
|
@@ -44,6 +44,8 @@ export const Graph2D = ({
|
|
|
44
44
|
onLinkClick,
|
|
45
45
|
onBackgroundClick,
|
|
46
46
|
}: Graph2DProps) => {
|
|
47
|
+
const theme = useTheme();
|
|
48
|
+
|
|
47
49
|
// Стан для підсвічування вузлів і зв'язків
|
|
48
50
|
const [highlightNodes, setHighlightNodes] = useState(new Set());
|
|
49
51
|
const [highlightLinks, setHighlightLinks] = useState(new Set());
|
|
@@ -227,7 +229,7 @@ export const Graph2D = ({
|
|
|
227
229
|
// Малюємо кільце навколо вузла
|
|
228
230
|
ctx.beginPath();
|
|
229
231
|
ctx.arc(node.x, node.y, radius, 0, 2 * Math.PI, false);
|
|
230
|
-
ctx.fillStyle =
|
|
232
|
+
ctx.fillStyle = theme.graph2D.ring.highlightFill;
|
|
231
233
|
ctx.fill();
|
|
232
234
|
},
|
|
233
235
|
[config]
|
|
@@ -246,9 +248,9 @@ export const Graph2D = ({
|
|
|
246
248
|
ctx.beginPath();
|
|
247
249
|
ctx.arc(x, y, buttonRadius, Math.PI, Math.PI * 2, false);
|
|
248
250
|
ctx.lineWidth = 1;
|
|
249
|
-
ctx.strokeStyle =
|
|
251
|
+
ctx.strokeStyle = theme.graph2D.button.stroke;
|
|
250
252
|
ctx.stroke();
|
|
251
|
-
ctx.fillStyle = hoverTopButton ?
|
|
253
|
+
ctx.fillStyle = hoverTopButton ? theme.graph2D.button.hoverFill : theme.graph2D.button.normalFill;
|
|
252
254
|
ctx.fill();
|
|
253
255
|
|
|
254
256
|
// Лінія розділення між кнопками
|
|
@@ -256,16 +258,16 @@ export const Graph2D = ({
|
|
|
256
258
|
ctx.moveTo(x - buttonRadius, y);
|
|
257
259
|
ctx.lineTo(x + buttonRadius, y);
|
|
258
260
|
ctx.lineWidth = 1;
|
|
259
|
-
ctx.strokeStyle =
|
|
261
|
+
ctx.strokeStyle = theme.graph2D.button.stroke;
|
|
260
262
|
ctx.stroke();
|
|
261
263
|
|
|
262
264
|
// Кнопка "згорнути" (нижня частина кільця)
|
|
263
265
|
ctx.beginPath();
|
|
264
266
|
ctx.arc(x, y, buttonRadius, Math.PI * 2, Math.PI, false);
|
|
265
267
|
ctx.lineWidth = 1;
|
|
266
|
-
ctx.strokeStyle =
|
|
268
|
+
ctx.strokeStyle = theme.graph2D.button.stroke;
|
|
267
269
|
ctx.stroke();
|
|
268
|
-
ctx.fillStyle = hoverBottomButton ?
|
|
270
|
+
ctx.fillStyle = hoverBottomButton ? theme.graph2D.button.hoverFill : theme.graph2D.button.normalFill;
|
|
269
271
|
ctx.fill();
|
|
270
272
|
|
|
271
273
|
// Додаємо іконку хрестика для кнопки "сховати вузол"
|
|
@@ -571,7 +573,7 @@ export const Graph2D = ({
|
|
|
571
573
|
const gridSpacing = config.gridSpacing;
|
|
572
574
|
const dotSize = config.dotSize;
|
|
573
575
|
|
|
574
|
-
ctx.fillStyle =
|
|
576
|
+
ctx.fillStyle = theme.graph2D.grid.dotColor;
|
|
575
577
|
|
|
576
578
|
for (let x = 0; x < width; x += gridSpacing) {
|
|
577
579
|
for (let y = 0; y < height; y += gridSpacing) {
|
|
@@ -690,7 +692,7 @@ export const Graph2D = ({
|
|
|
690
692
|
};
|
|
691
693
|
|
|
692
694
|
// Малюємо лінію зв'язку з урахуванням місця для тексту, якщо він є
|
|
693
|
-
const lineColor = highlightLinks.has(link) ?
|
|
695
|
+
const lineColor = highlightLinks.has(link) ? theme.graph2D.link.highlighted : theme.graph2D.link.normal;
|
|
694
696
|
const lineWidth = highlightLinks.has(link) ? 1.5 : 0.5;
|
|
695
697
|
|
|
696
698
|
if (label) {
|
|
@@ -763,7 +765,7 @@ export const Graph2D = ({
|
|
|
763
765
|
ctx.lineTo(-arrowHeadLength, -arrowHeadWidth);
|
|
764
766
|
ctx.closePath();
|
|
765
767
|
|
|
766
|
-
ctx.fillStyle = highlightLinks.has(link) ?
|
|
768
|
+
ctx.fillStyle = highlightLinks.has(link) ? theme.graph2D.link.highlighted : theme.graph2D.link.normal;
|
|
767
769
|
ctx.fill();
|
|
768
770
|
ctx.restore();
|
|
769
771
|
|
|
@@ -777,7 +779,7 @@ export const Graph2D = ({
|
|
|
777
779
|
// Використовуємо реверсивне масштабування для тексту
|
|
778
780
|
const scaledFontSize = calculateFontSize(globalScale);
|
|
779
781
|
ctx.font = `${scaledFontSize}px Sans-Serif`;
|
|
780
|
-
ctx.fillStyle =
|
|
782
|
+
ctx.fillStyle = theme.graph2D.link.textColor; // Колір тексту
|
|
781
783
|
ctx.textAlign = 'center';
|
|
782
784
|
ctx.textBaseline = 'middle';
|
|
783
785
|
|
|
@@ -797,7 +799,9 @@ export const Graph2D = ({
|
|
|
797
799
|
// Рисуємо фон для тексту для кращої читаємості
|
|
798
800
|
const textWidth = ctx.measureText(label).width;
|
|
799
801
|
const padding = 2;
|
|
800
|
-
ctx.fillStyle = highlightLinks.has(link)
|
|
802
|
+
ctx.fillStyle = highlightLinks.has(link)
|
|
803
|
+
? theme.graph2D.link.highlightedTextBgColor
|
|
804
|
+
: theme.graph2D.link.textBgColor;
|
|
801
805
|
ctx.fillRect(
|
|
802
806
|
-textWidth / 2 - padding,
|
|
803
807
|
-scaledFontSize / 2 - padding,
|
|
@@ -806,7 +810,7 @@ export const Graph2D = ({
|
|
|
806
810
|
);
|
|
807
811
|
|
|
808
812
|
// Малюємо текст
|
|
809
|
-
ctx.fillStyle = highlightLinks.has(link) ?
|
|
813
|
+
ctx.fillStyle = highlightLinks.has(link) ? theme.graph2D.link.highlightedTextColor : theme.graph2D.link.textColor;
|
|
810
814
|
ctx.fillText(label, 0, 0);
|
|
811
815
|
|
|
812
816
|
// Відновлення стану контексту
|
|
@@ -945,7 +949,9 @@ export const Graph2D = ({
|
|
|
945
949
|
d3AlphaDecay={0.038}
|
|
946
950
|
// Виділення зв'язків при наведенні
|
|
947
951
|
linkWidth={(link: any) => (highlightLinks.has(link) ? 3 : 1)}
|
|
948
|
-
linkColor={(link: any) =>
|
|
952
|
+
linkColor={(link: any) =>
|
|
953
|
+
highlightLinks.has(link) ? theme.graph2D.link.highlighted : theme.graph2D.link.normal
|
|
954
|
+
}
|
|
949
955
|
onRenderFramePre={renderGrid}
|
|
950
956
|
nodePointerAreaPaint={renderNodePointerAreaPaint}
|
|
951
957
|
nodeCanvasObject={renderNodeCanvasObject}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import ContentLoader from 'react-content-loader';
|
|
3
|
-
import styled from 'styled-components';
|
|
3
|
+
import styled, { useTheme } from 'styled-components';
|
|
4
4
|
|
|
5
5
|
const LoaderWrapper = styled.div`
|
|
6
6
|
position: absolute;
|
|
@@ -21,29 +21,17 @@ interface GraphLoaderProps {
|
|
|
21
21
|
|
|
22
22
|
const GraphLoader: React.FC<GraphLoaderProps> = ({ width = 280, height = 280 }) => {
|
|
23
23
|
// Helper function to create a rect from line coordinates
|
|
24
|
-
const
|
|
25
|
-
// Calculate length and angle of the line
|
|
26
|
-
const length = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
|
|
27
|
-
const angle = (Math.atan2(y2 - y1, x2 - x1) * 180) / Math.PI;
|
|
28
|
-
|
|
29
|
-
// Calculate center point of the line
|
|
30
|
-
const centerX = (x1 + x2) / 2;
|
|
31
|
-
const centerY = (y1 + y2) / 2;
|
|
32
|
-
|
|
33
|
-
return (
|
|
34
|
-
<rect
|
|
35
|
-
x={centerX - length / 2}
|
|
36
|
-
y={centerY - thickness / 2}
|
|
37
|
-
width={length}
|
|
38
|
-
height={thickness}
|
|
39
|
-
transform={`rotate(${angle}, ${centerX}, ${centerY})`}
|
|
40
|
-
/>
|
|
41
|
-
);
|
|
42
|
-
};
|
|
24
|
+
const theme = useTheme();
|
|
43
25
|
|
|
44
26
|
return (
|
|
45
27
|
<LoaderWrapper>
|
|
46
|
-
<ContentLoader
|
|
28
|
+
<ContentLoader
|
|
29
|
+
foregroundColor={theme.contentLoader.foreground}
|
|
30
|
+
backgroundColor={theme.contentLoader.background}
|
|
31
|
+
width={width}
|
|
32
|
+
height={height}
|
|
33
|
+
viewBox="0 0 280 280"
|
|
34
|
+
>
|
|
47
35
|
<path d="m55 38-0.97266 0.22852 7.0801 30.092-18.355-20.979-0.75195 0.6582 19.596 22.395 0.43164 1.834 0.97266-0.22852 0.75195-0.6582-0.37695-0.42969 9.625-27.912-0.94531-0.32617-9.4375 27.371-0.10547-0.12109zm8 34-0.78516 0.61914 0.0957 0.12305-12.311 13.258 0.73242 0.67969 12.205-13.145 14.277 18.084 0.78516-0.61914-14.373-18.207 0.10547-0.11328zm15 19-0.48438 0.875 46.992 25.996 8e-3 4e-3 20.506 11.592-28.182 4.5449 0.15998 0.98819 29.418-4.7441 0.25 0.14062-12.555 24.143 0.88672 0.46094 13-25 15 25 26 30v18l-11 18 0.85352 0.52148 9.8008-16.039-4.6543 33.518 0.99023 0.13867 4.7793-34.408 7.2305 16.27 0.91406-0.40625-7.9141-17.807v-17.104l18 12.316 0.56445-0.82617-18.896-12.928-25.855-29.836-14.633-24.387 0.01562-0.02344h23.805v-1h-23.152l13.848-21.234 55.201-28.791-0.45898-0.88476 0.77734 0.62305 11.402-14.25 16.668-11.842-0.58008-0.81641-16.785 11.928-11.486 14.355-55.434 28.912-14.277 21.893-7.7617-27.166-0.96094 0.27344 7.7227 27.031-1.1191 0.17969-21.604-12.211zm140.43-12.912-6.957-17.338-0.92773 0.37305 6.957 17.338zm-6.957-17.338 0.72266 0.69336 16.232-16.896-0.7207-0.69336zm-3.4766 137.25 5 15 0.94922-0.31641-5-15zm-91-63-0.48047-0.87695-31 17 0.48047 0.87695zm-31 17 5 18 0.96289-0.26758-5-18zm0 0-0.70703-0.70703-12.898 12.898-17.881 9.9336 0.48633 0.875 18-10zm5 18-0.64062-0.76758-18 15 0.64062 0.76758z" />
|
|
48
36
|
<circle cx="229.92" cy="63.7318" r="5" transform="rotate(173.661 229.92 63.7318)" />
|
|
49
37
|
<circle cx="227.711" cy="43.8541" r="5" transform="rotate(173.661 227.711 43.8541)" />
|
|
@@ -54,6 +54,9 @@ export const StyledContainer = styled.div<StyledContainerProps>(
|
|
|
54
54
|
`
|
|
55
55
|
);
|
|
56
56
|
|
|
57
|
-
const StyledMain = styled.main
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
const StyledMain = styled.main(
|
|
58
|
+
({ theme }) => `
|
|
59
|
+
min-width: 0;
|
|
60
|
+
background: ${theme.colors.backgroundBase};
|
|
61
|
+
`
|
|
62
|
+
);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createGlobalStyle } from 'styled-components';
|
|
2
2
|
|
|
3
|
-
export const GlobalStyle = createGlobalStyle
|
|
3
|
+
export const GlobalStyle = createGlobalStyle(
|
|
4
|
+
({ theme }) => `
|
|
4
5
|
*, *::before, *::after {
|
|
5
6
|
box-sizing: border-box;
|
|
6
7
|
margin: 0;
|
|
@@ -8,5 +9,10 @@ export const GlobalStyle = createGlobalStyle`
|
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
body, html {
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
background: ${theme.colors.backgroundBase};
|
|
13
|
+
color: ${theme.colors.text.main};
|
|
14
|
+
font-family: ${theme.typography.fontFamily};
|
|
15
|
+
font-size: ${theme.baseSize}px;
|
|
16
|
+
}
|
|
17
|
+
`
|
|
18
|
+
);
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { StyleSheetManager, ThemeProvider as ThemeProviderStyled, WebTarget } from 'styled-components';
|
|
2
|
-
import { lightTheme } from './
|
|
2
|
+
import { lightTheme, darkTheme } from './themes';
|
|
3
3
|
import { GlobalStyle } from './GlobalStyle';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
interface ThemeProviderProps {
|
|
6
|
+
children: any;
|
|
7
|
+
mode?: 'light' | 'LIGHT' | 'dark' | 'DARK';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type ThemeMode = 'light' | 'LIGHT' | 'dark' | 'DARK';
|
|
11
|
+
export const ThemeProvider = ({ children, mode }: ThemeProviderProps) => {
|
|
6
12
|
return (
|
|
7
13
|
<StyleSheetManager shouldForwardProp={shouldForwardProp}>
|
|
8
|
-
<ThemeProviderStyled theme={lightTheme}>
|
|
14
|
+
<ThemeProviderStyled theme={mode == 'light' || mode === 'LIGHT' ? lightTheme : darkTheme}>
|
|
9
15
|
<GlobalStyle />
|
|
10
16
|
{children}
|
|
11
17
|
</ThemeProviderStyled>
|
package/src/Theme/index.ts
CHANGED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Індексні шари (z-index) для різних компонентів
|
|
2
|
+
export const zIndex = {
|
|
3
|
+
dropdown: 1000,
|
|
4
|
+
sticky: 1020,
|
|
5
|
+
fixed: 1030,
|
|
6
|
+
backdrop: 1040,
|
|
7
|
+
modal: 1050,
|
|
8
|
+
popover: 1060,
|
|
9
|
+
tooltip: 1070,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// Розміри брейкпоінтів
|
|
13
|
+
export const breakpoints = {
|
|
14
|
+
xs: 320,
|
|
15
|
+
s: 576,
|
|
16
|
+
m: 768,
|
|
17
|
+
l: 992,
|
|
18
|
+
xl: 1200,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// Типографія
|
|
22
|
+
export const typography = {
|
|
23
|
+
fontFamily:
|
|
24
|
+
'Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;',
|
|
25
|
+
lineHeight: 1.49,
|
|
26
|
+
// Розміри текстових елементів
|
|
27
|
+
variants: {
|
|
28
|
+
h1: {
|
|
29
|
+
fontSize: 22,
|
|
30
|
+
},
|
|
31
|
+
h2: {
|
|
32
|
+
fontSize: 16,
|
|
33
|
+
},
|
|
34
|
+
h3: {
|
|
35
|
+
fontSize: 14,
|
|
36
|
+
},
|
|
37
|
+
body: {
|
|
38
|
+
fontSize: 12,
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
};
|