@cyber-harbour/ui 1.0.26 → 1.0.28
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 +56 -5
- package/dist/index.d.ts +56 -5
- package/dist/index.js +131 -104
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +130 -103
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/Core/Box/Box.tsx +12 -0
- package/src/Core/Box/index.ts +1 -0
- package/src/Core/Button/Button.tsx +5 -2
- package/src/Core/Flex/FlexContainer.tsx +81 -0
- package/src/Core/Flex/FlexItem.tsx +64 -0
- package/src/Core/Flex/index.ts +4 -0
- package/src/Core/Typography/Typography.tsx +6 -3
- package/src/Core/index.ts +2 -0
- package/src/Graph2D/Graph2D.tsx +19 -2
- package/src/Theme/theme.ts +10 -0
- package/src/Theme/types.ts +11 -0
package/package.json
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { styled } from 'styled-components';
|
|
2
|
+
|
|
3
|
+
export const Box = styled.div(
|
|
4
|
+
({ theme }) => `
|
|
5
|
+
padding: ${theme.box.padding};
|
|
6
|
+
border-radius: ${theme.box.border.radius};
|
|
7
|
+
background-color: ${theme.box.background};
|
|
8
|
+
border-width: ${theme.box.border.width};
|
|
9
|
+
border-style: ${theme.box.border.style};
|
|
10
|
+
border-color: ${theme.box.border.color};
|
|
11
|
+
`
|
|
12
|
+
);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Box';
|
|
@@ -21,8 +21,11 @@ interface BaseButtonProps {
|
|
|
21
21
|
iconPosition?: 'left' | 'right';
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export type ButtonProps =
|
|
25
|
-
|
|
24
|
+
export type ButtonProps = (
|
|
25
|
+
| Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'children'>
|
|
26
|
+
| Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children'>
|
|
27
|
+
) &
|
|
28
|
+
BaseButtonProps;
|
|
26
29
|
|
|
27
30
|
const getCss = (styles: ButtonElementStyle) => `
|
|
28
31
|
background: ${styles.background};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { CSSProperties, ReactNode } from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
|
|
4
|
+
export type FlexDirection = 'row' | 'column' | 'row-reverse' | 'column-reverse';
|
|
5
|
+
export type FlexWrap = 'nowrap' | 'wrap' | 'wrap-reverse';
|
|
6
|
+
export type FlexJustify = 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly';
|
|
7
|
+
export type FlexAlign = 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline';
|
|
8
|
+
export type FlexGap = string | number;
|
|
9
|
+
|
|
10
|
+
export interface FlexContainerProps {
|
|
11
|
+
children: any;
|
|
12
|
+
direction?: FlexDirection;
|
|
13
|
+
wrap?: FlexWrap;
|
|
14
|
+
justify?: FlexJustify;
|
|
15
|
+
align?: FlexAlign;
|
|
16
|
+
alignContent?: FlexAlign;
|
|
17
|
+
gap?: FlexGap;
|
|
18
|
+
rowGap?: FlexGap;
|
|
19
|
+
columnGap?: FlexGap;
|
|
20
|
+
className?: string;
|
|
21
|
+
style?: CSSProperties;
|
|
22
|
+
as?: any; // TODO: fix type to styled component or intrinsic element
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const FlexContainer = ({
|
|
26
|
+
children,
|
|
27
|
+
direction = 'row',
|
|
28
|
+
wrap = 'nowrap',
|
|
29
|
+
justify = 'flex-start',
|
|
30
|
+
align = 'stretch',
|
|
31
|
+
alignContent,
|
|
32
|
+
gap,
|
|
33
|
+
rowGap,
|
|
34
|
+
columnGap,
|
|
35
|
+
className,
|
|
36
|
+
style,
|
|
37
|
+
as = 'div',
|
|
38
|
+
}: FlexContainerProps) => {
|
|
39
|
+
return (
|
|
40
|
+
<StyledFlexContainer
|
|
41
|
+
as={as}
|
|
42
|
+
$direction={direction}
|
|
43
|
+
$wrap={wrap}
|
|
44
|
+
$justify={justify}
|
|
45
|
+
$align={align}
|
|
46
|
+
$alignContent={alignContent}
|
|
47
|
+
$gap={gap}
|
|
48
|
+
$rowGap={rowGap}
|
|
49
|
+
$columnGap={columnGap}
|
|
50
|
+
className={className}
|
|
51
|
+
style={style}
|
|
52
|
+
>
|
|
53
|
+
{children}
|
|
54
|
+
</StyledFlexContainer>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
interface StyledFlexContainerProps {
|
|
59
|
+
$direction: FlexDirection;
|
|
60
|
+
$wrap: FlexWrap;
|
|
61
|
+
$justify: FlexJustify;
|
|
62
|
+
$align: FlexAlign;
|
|
63
|
+
$alignContent?: FlexAlign;
|
|
64
|
+
$gap?: FlexGap;
|
|
65
|
+
$rowGap?: FlexGap;
|
|
66
|
+
$columnGap?: FlexGap;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const StyledFlexContainer = styled.div<StyledFlexContainerProps>`
|
|
70
|
+
${({ $direction, $wrap, $justify, $align, $alignContent, $gap, $rowGap, $columnGap }) => `
|
|
71
|
+
display: flex;
|
|
72
|
+
flex-direction: ${$direction};
|
|
73
|
+
flex-wrap: ${$wrap};
|
|
74
|
+
justify-content: ${$justify};
|
|
75
|
+
align-items: ${$align};
|
|
76
|
+
${$alignContent ? `align-content: ${$alignContent};` : ''}
|
|
77
|
+
${$gap !== undefined ? `gap: ${typeof $gap === 'number' ? `${$gap}px` : $gap};` : ''}
|
|
78
|
+
${$rowGap !== undefined ? `row-gap: ${typeof $rowGap === 'number' ? `${$rowGap}px` : $rowGap};` : ''}
|
|
79
|
+
${$columnGap !== undefined ? `column-gap: ${typeof $columnGap === 'number' ? `${$columnGap}px` : $columnGap};` : ''}
|
|
80
|
+
`}
|
|
81
|
+
`;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { CSSProperties, ReactNode } from 'react';
|
|
2
|
+
import { styled } from 'styled-components';
|
|
3
|
+
|
|
4
|
+
export type FlexItemGrow = number;
|
|
5
|
+
export type FlexItemShrink = number;
|
|
6
|
+
export type FlexItemBasis = string | number;
|
|
7
|
+
export type FlexItemAlign = 'auto' | 'flex-start' | 'flex-end' | 'center' | 'baseline' | 'stretch';
|
|
8
|
+
|
|
9
|
+
export interface FlexItemProps {
|
|
10
|
+
children?: any;
|
|
11
|
+
grow?: FlexItemGrow;
|
|
12
|
+
shrink?: FlexItemShrink;
|
|
13
|
+
basis?: FlexItemBasis;
|
|
14
|
+
align?: FlexItemAlign;
|
|
15
|
+
order?: number;
|
|
16
|
+
className?: string;
|
|
17
|
+
style?: CSSProperties;
|
|
18
|
+
as?: any; //TODO: fix type to styled component or intrinsic element
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const FlexItem = ({
|
|
22
|
+
children,
|
|
23
|
+
grow,
|
|
24
|
+
shrink,
|
|
25
|
+
basis,
|
|
26
|
+
align,
|
|
27
|
+
order,
|
|
28
|
+
className,
|
|
29
|
+
style,
|
|
30
|
+
as = 'div',
|
|
31
|
+
}: FlexItemProps) => {
|
|
32
|
+
return (
|
|
33
|
+
<StyledFlexItem
|
|
34
|
+
as={as}
|
|
35
|
+
$grow={grow}
|
|
36
|
+
$shrink={shrink}
|
|
37
|
+
$basis={basis}
|
|
38
|
+
$align={align}
|
|
39
|
+
$order={order}
|
|
40
|
+
className={className}
|
|
41
|
+
style={style}
|
|
42
|
+
>
|
|
43
|
+
{children}
|
|
44
|
+
</StyledFlexItem>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
interface StyledFlexItemProps {
|
|
49
|
+
$grow?: FlexItemGrow;
|
|
50
|
+
$shrink?: FlexItemShrink;
|
|
51
|
+
$basis?: FlexItemBasis;
|
|
52
|
+
$align?: FlexItemAlign;
|
|
53
|
+
$order?: number;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const StyledFlexItem = styled.div<StyledFlexItemProps>`
|
|
57
|
+
${({ $grow, $shrink, $basis, $align, $order }) => `
|
|
58
|
+
${$grow !== undefined ? `flex-grow: ${$grow};` : ''}
|
|
59
|
+
${$shrink !== undefined ? `flex-shrink: ${$shrink};` : ''}
|
|
60
|
+
${$basis !== undefined ? `flex-basis: ${typeof $basis === 'number' ? `${$basis}px` : $basis};` : ''}
|
|
61
|
+
${$align ? `align-self: ${$align};` : ''}
|
|
62
|
+
${$order !== undefined ? `order: ${$order};` : ''}
|
|
63
|
+
`}
|
|
64
|
+
`;
|
|
@@ -4,11 +4,12 @@ import { ColorVariant, TypographyVariant } from '../../Theme';
|
|
|
4
4
|
import { resolveThemeColor } from '../../Theme/utils';
|
|
5
5
|
|
|
6
6
|
export interface TypographyProps {
|
|
7
|
+
style?: CSSProperties;
|
|
7
8
|
variant?: TypographyVariant;
|
|
8
9
|
element?: ElementType;
|
|
9
10
|
children: any;
|
|
10
11
|
weight?: CSSProperties['fontWeight'];
|
|
11
|
-
|
|
12
|
+
fontStyle?: CSSProperties['fontStyle'];
|
|
12
13
|
color?: ColorVariant | string;
|
|
13
14
|
className?: string;
|
|
14
15
|
}
|
|
@@ -35,9 +36,10 @@ export const Typography = ({
|
|
|
35
36
|
element,
|
|
36
37
|
children,
|
|
37
38
|
weight,
|
|
38
|
-
|
|
39
|
+
fontStyle,
|
|
39
40
|
color,
|
|
40
41
|
className,
|
|
42
|
+
style,
|
|
41
43
|
}: TypographyProps) => {
|
|
42
44
|
// Determine which HTML element to render based on the variant if not explicitly specified
|
|
43
45
|
const Element = element || (variant.startsWith('h') ? variant : 'p');
|
|
@@ -47,9 +49,10 @@ export const Typography = ({
|
|
|
47
49
|
as={Element}
|
|
48
50
|
$variant={variant}
|
|
49
51
|
$weight={weight}
|
|
50
|
-
$style={
|
|
52
|
+
$style={fontStyle}
|
|
51
53
|
$color={color}
|
|
52
54
|
className={className}
|
|
55
|
+
style={style}
|
|
53
56
|
>
|
|
54
57
|
{children}
|
|
55
58
|
</StyledTypography>
|
package/src/Core/index.ts
CHANGED
package/src/Graph2D/Graph2D.tsx
CHANGED
|
@@ -241,7 +241,11 @@ export const Graph2D = ({
|
|
|
241
241
|
// Вибір іконки в залежності від стану наведення для верхньої кнопки (сховати)
|
|
242
242
|
const crossIcon = hoverTopButton ? imgCrossLightHoverIcon : imgCrossLightIcon;
|
|
243
243
|
const renderCrossIcon = () => {
|
|
244
|
-
|
|
244
|
+
try {
|
|
245
|
+
ctx.drawImage(crossIcon, x - iconSize / 2, y - (buttonRadius * 2) / 4 - iconSize - 1, iconSize, iconSize);
|
|
246
|
+
} catch (error) {
|
|
247
|
+
console.log('Error rendering cross icon:', error);
|
|
248
|
+
}
|
|
245
249
|
};
|
|
246
250
|
// Використовуємо безпосередньо зображення, якщо воно вже завантажене
|
|
247
251
|
if (crossIcon.complete) {
|
|
@@ -252,22 +256,35 @@ export const Graph2D = ({
|
|
|
252
256
|
crossIcon.onload = () => {
|
|
253
257
|
renderCrossIcon();
|
|
254
258
|
};
|
|
259
|
+
|
|
260
|
+
crossIcon.onerror = () => {
|
|
261
|
+
console.log('Error loading cross icon image');
|
|
262
|
+
};
|
|
255
263
|
}
|
|
256
264
|
|
|
257
265
|
// Додаємо іконку ока для кнопки "згорнути дочірні вузли"
|
|
258
266
|
const eyeIcon = hoverBottomButton ? imgEyeLightHoverIcon : imgEyeLightIcon;
|
|
259
267
|
const renderEyeIcon = () => {
|
|
260
|
-
|
|
268
|
+
try {
|
|
269
|
+
ctx.drawImage(eyeIcon, x - iconSize / 2, y + (buttonRadius * 2) / 4 + 1, iconSize, iconSize);
|
|
270
|
+
} catch (error) {
|
|
271
|
+
console.log('Error rendering eye icon:', error);
|
|
272
|
+
}
|
|
261
273
|
};
|
|
262
274
|
// Використовуємо безпосередньо зображення, якщо воно вже завантажене
|
|
263
275
|
if (eyeIcon.complete) {
|
|
264
276
|
// Розміщуємо іконку в центрі нижньої половини кнопки
|
|
277
|
+
|
|
265
278
|
renderEyeIcon();
|
|
266
279
|
} else {
|
|
267
280
|
// Якщо зображення ще не завантажене, додаємо обробник завершення завантаження
|
|
268
281
|
eyeIcon.onload = () => {
|
|
269
282
|
renderEyeIcon();
|
|
270
283
|
};
|
|
284
|
+
|
|
285
|
+
eyeIcon.onerror = () => {
|
|
286
|
+
console.log('Error loading eye icon image');
|
|
287
|
+
};
|
|
271
288
|
}
|
|
272
289
|
|
|
273
290
|
ctx.restore();
|
package/src/Theme/theme.ts
CHANGED
|
@@ -633,6 +633,16 @@ export const lightThemePx: Theme = {
|
|
|
633
633
|
},
|
|
634
634
|
},
|
|
635
635
|
},
|
|
636
|
+
box: {
|
|
637
|
+
padding: 20,
|
|
638
|
+
border: {
|
|
639
|
+
radius: 8,
|
|
640
|
+
width: 1,
|
|
641
|
+
style: 'solid',
|
|
642
|
+
color: '#EBEBEB',
|
|
643
|
+
},
|
|
644
|
+
background: '#FFFFFF',
|
|
645
|
+
},
|
|
636
646
|
};
|
|
637
647
|
|
|
638
648
|
// Конвертуємо всі розміри з px в rem
|
package/src/Theme/types.ts
CHANGED
|
@@ -184,6 +184,17 @@ export type Theme = {
|
|
|
184
184
|
sizes: Record<InputSize, InputSizeStyle>;
|
|
185
185
|
outlined: Record<InputState, InputElementStyle>;
|
|
186
186
|
};
|
|
187
|
+
//Box
|
|
188
|
+
box: {
|
|
189
|
+
padding: number | string;
|
|
190
|
+
background: string;
|
|
191
|
+
border: {
|
|
192
|
+
radius: number | string;
|
|
193
|
+
width: number | string;
|
|
194
|
+
style: string;
|
|
195
|
+
color: string;
|
|
196
|
+
};
|
|
197
|
+
};
|
|
187
198
|
};
|
|
188
199
|
|
|
189
200
|
//TODO check and refactoring
|