@cyber-harbour/ui 1.0.17 → 1.0.18

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.17",
3
+ "version": "1.0.18",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",
@@ -16,6 +16,7 @@
16
16
  "dev": "tsup --config tsup.dev.config.ts",
17
17
  "build": "cross-env NODE_ENV=production tsup",
18
18
  "build:dev": "tsup",
19
+ "type:check": "tsc --noEmit",
19
20
  "test": "echo \"Error: no test specified\" && exit 1",
20
21
  "storybook": "storybook dev -p 6006",
21
22
  "build-storybook": "storybook build",
@@ -1,24 +1,115 @@
1
+ import React from 'react';
1
2
  import styled from 'styled-components';
3
+ import {
4
+ ButtonVariant,
5
+ ButtonSize,
6
+ ButtonColor,
7
+ getButtonStyles,
8
+ getButtonSizeStyles,
9
+ ButtonElementStyle,
10
+ } from '../../Theme';
2
11
 
3
- const StyledButton = styled.button`
4
- padding: 0.5rem 1rem;
5
- background: ${(props) => props.theme.colors.primary.main};
6
- color: ${(props) => props.theme.colors.text.invert};
7
- border: none;
8
- border-radius: 4px;
9
- font-size: 1rem;
10
- transition: background-color 0.2s ease;
11
-
12
- &:hover {
13
- background: ${(props) => props.theme.colors.primary.light};
14
- }
15
- `;
16
-
17
- export interface ButtonProps {
18
- children: any;
19
- color?: string;
12
+ interface BaseButtonProps {
13
+ children?: any;
14
+ variant?: ButtonVariant;
15
+ color?: ButtonColor;
16
+ size?: ButtonSize;
17
+ disabled?: boolean;
18
+ fullWidth?: boolean;
19
+ className?: string;
20
+ icon?: any;
21
+ iconPosition?: 'left' | 'right';
20
22
  }
21
23
 
22
- export const Button = ({ children, color }: ButtonProps) => {
23
- return <StyledButton color={color}>{children}</StyledButton>;
24
+ export type ButtonProps = BaseButtonProps &
25
+ (React.AnchorHTMLAttributes<HTMLAnchorElement> | React.ButtonHTMLAttributes<HTMLButtonElement>);
26
+
27
+ const getCss = (styles: ButtonElementStyle) => `
28
+ background: ${styles.background};
29
+ color: ${styles.text};
30
+ border-color: ${styles.border};
31
+ box-shadow: ${styles.boxShadow};
32
+ `;
33
+
34
+ // Створюємо стилізований компонент, що використовує уніфіковану палітру
35
+ const StyledButton = styled.button<{
36
+ $variant: ButtonVariant;
37
+ $color: ButtonColor;
38
+ $size: ButtonSize;
39
+ $disabled: boolean;
40
+ $fullWidth: boolean;
41
+ $iconPosition: 'left' | 'right';
42
+ }>`
43
+ ${({ $variant, $color, $size, $disabled, $fullWidth, $iconPosition, theme }) => {
44
+ const sizes = getButtonSizeStyles(theme, $size);
45
+ return `
46
+ ${getCss(getButtonStyles(theme, $variant, $color, 'default'))}
47
+ font-size: ${sizes.fontSize};
48
+ gap: ${sizes.gap};
49
+ padding-block: ${sizes.paddingBlock};
50
+ padding-inline: ${sizes.paddingInline};
51
+ border-radius: ${sizes.borderRadius};
52
+ border-width: ${sizes.borderWidth};
53
+ border-style: solid;
54
+ width: ${$fullWidth ? '100%' : 'auto'};
55
+ cursor: ${$disabled ? 'not-allowed' : 'pointer'};
56
+ font-weight: 500;
57
+ display: inline-flex;
58
+ align-items: center;
59
+ justify-content: center;
60
+ text-decoration: none;
61
+ transition: all 0.2s ease;
62
+ outline: none;
63
+
64
+ ${$iconPosition === 'right' ? 'flex-direction: row-reverse;' : ''}
65
+
66
+ &:hover {
67
+ ${getCss(getButtonStyles(theme, $variant, $color, 'hover'))}
68
+ }
69
+
70
+ &:active {
71
+ ${getCss(getButtonStyles(theme, $variant, $color, 'active'))}
72
+ }
73
+
74
+ &:disabled {
75
+ ${getCss(getButtonStyles(theme, $variant, $color, 'disabled'))}
76
+ }
77
+
78
+ svg {
79
+ width: ${sizes.iconSize};
80
+ height: ${sizes.iconSize};
81
+ }
82
+ `;
83
+ }}
84
+ `;
85
+
86
+ export const Button = ({
87
+ children,
88
+ variant = 'fill',
89
+ color = 'primary',
90
+ size = 'medium',
91
+ disabled = false,
92
+ fullWidth = false,
93
+ className,
94
+ icon,
95
+ iconPosition = 'left',
96
+ ...props
97
+ }: ButtonProps) => {
98
+ return (
99
+ <StyledButton
100
+ as={'href' in props ? 'a' : 'button'}
101
+ $variant={variant}
102
+ $color={color}
103
+ $size={size}
104
+ $disabled={disabled}
105
+ $fullWidth={fullWidth}
106
+ $iconPosition={iconPosition}
107
+ disabled={disabled}
108
+ className={className}
109
+ {...props}
110
+ >
111
+ {icon}
112
+ <div>{children}</div>
113
+ </StyledButton>
114
+ );
24
115
  };
@@ -1 +1 @@
1
- export { Button } from './Button';
1
+ export * from './Button';
@@ -5,24 +5,14 @@ interface HeaderProps {
5
5
  }
6
6
 
7
7
  export const Header = ({ children }: HeaderProps) => {
8
- return (
9
- <StyledWrapper>
10
- <StyledContainer>{children}</StyledContainer>
11
- </StyledWrapper>
12
- );
8
+ return <StyledContainer>{children}</StyledContainer>;
13
9
  };
14
10
 
15
- const StyledWrapper = styled.header`
16
- height: 56px;
17
- `;
18
-
19
- const StyledContainer = styled.div(
11
+ const StyledContainer = styled.header(
20
12
  ({ theme }) => `
21
13
  display: flex;
22
- position: fixed;
14
+ position: sticky;
23
15
  top: 0;
24
- left: 0;
25
- right: 0;
26
16
  z-index: 1000;
27
17
  align-items: center;
28
18
  justify-content: space-between;
@@ -31,5 +21,17 @@ const StyledContainer = styled.div(
31
21
  height: 56px;
32
22
  background-color: ${theme.colors.background};
33
23
  border-bottom: 1px solid ${theme.colors.stroke.main};
24
+
25
+ &:before {
26
+ content: '';
27
+ display: block;
28
+ position: absolute;
29
+ top: 0;
30
+ left: 0;
31
+ width: 100%;
32
+ height: 25dvh;
33
+ transform: translateY(-100%);
34
+ background: ${theme.colors.background};
35
+ }
34
36
  `
35
37
  );
@@ -47,16 +47,16 @@ const StyledItem = styled.li<StyledProps>(
47
47
  }
48
48
 
49
49
  ::before {
50
- content: '';
51
- position: absolute;
52
- top: 0;
53
- left: 0;
54
- width: 2px;
55
- height: ${$active ? '100%' : 0};
56
- border-radius: 2px;
57
- transform: translateX(-25%);
58
- background-color: ${$active ? theme.colors.primary.main : 'transparent'};
59
- transition: background-color 0.3s ease-in-out, height 0.3s ease-in-out;
50
+ content: '';
51
+ position: absolute;
52
+ top: 0;
53
+ left: 0;
54
+ width: 2px;
55
+ height: ${$active ? '100%' : 0};
56
+ border-radius: 2px;
57
+ transform: translateX(-25%);
58
+ background-color: ${$active ? theme.colors.primary.main : 'transparent'};
59
+ transition: background-color 0.3s ease-in-out, height 0.3s ease-in-out;
60
60
  }
61
61
  `
62
62
  );
@@ -88,11 +88,7 @@ const StyledLink = styled.a<StyledProps>(
88
88
  transition: background-color 0.3s ease-in-out, color 0.3s ease-in-out;
89
89
 
90
90
  &:hover {
91
- background-color: ${theme.colors.primary.lighter};
92
91
  color: ${theme.colors.primary.main};
93
- span {
94
- background-color: ${theme.colors.primary.lighter};
95
- }
96
92
  }`
97
93
  );
98
94
 
@@ -1,4 +1,4 @@
1
- import { CSSProperties, FC, useCallback, useMemo } from 'react';
1
+ import { FC, useCallback, useMemo } from 'react';
2
2
  import { styled } from 'styled-components';
3
3
  import { ChevronRightIcon } from '../IconComponents';
4
4
  import { ChevronLeftIcon } from '../IconComponents';
@@ -15,61 +15,61 @@ export const Sidebar = ({ defaultCollapsed, children }: SidebarProps) => {
15
15
  const [collapsed, setCollapsed] = React.useState(!!defaultCollapsed);
16
16
 
17
17
  return (
18
- <StyledWrapper $collapsed={collapsed}>
19
- <StyledContainer $collapsed={collapsed}>
20
- <SidebarContext.Provider
21
- value={{
22
- collapsed,
23
- setCollapsed,
24
- }}
25
- >
26
- {children}
27
- </SidebarContext.Provider>
28
- </StyledContainer>
29
- </StyledWrapper>
18
+ <StyledContainer $collapsed={collapsed}>
19
+ <SidebarContext.Provider
20
+ value={{
21
+ collapsed,
22
+ setCollapsed,
23
+ }}
24
+ >
25
+ {children}
26
+ </SidebarContext.Provider>
27
+ </StyledContainer>
30
28
  );
31
29
  };
32
30
 
33
- const StyledWrapper = styled.aside<StyledProps>(
34
- ({ $collapsed }) => `
35
- position: relative;
31
+ const StyledContainer = styled.aside<StyledProps>(
32
+ ({ theme, $collapsed }) => `
33
+ display: flex;
34
+ flex-direction: column;
35
+ justify-content: space-between;
36
+ gap: 20px;
37
+ position: sticky;
38
+ z-index: 1000;
39
+ top: 0;
40
+ width: ${theme.sidebar.width};
41
+ padding: 12px;
36
42
  height: 100%;
37
- width: 220px;
43
+ border-right: 1px solid ${theme.colors.stroke.light};
44
+ background: ${theme.colors.background};
45
+ ${
46
+ $collapsed
47
+ ? `
48
+ width: 65px;
49
+ `
50
+ : ''
51
+ }
38
52
 
53
+ &:before {
54
+ content: '';
55
+ display: block;
56
+ position: absolute;
57
+ top: 0;
58
+ left: 0;
59
+ width: 100%;
60
+ height: 25dvh;
61
+ transform: translateY(-100%);
62
+ background: ${theme.colors.background};
63
+ border-right: 1px solid ${theme.colors.stroke.light};
39
64
 
40
- ${
41
- $collapsed &&
42
- `
43
- & {
65
+ width: ${theme.sidebar.width};
66
+ ${
67
+ $collapsed
68
+ ? `
44
69
  width: 65px;
45
- height: 100%;
46
- min-heigth: 0px;
70
+ `
71
+ : ''
47
72
  }
48
- `
49
73
  }
50
74
  `
51
75
  );
52
-
53
- const StyledContainer = styled.div<StyledProps>(
54
- ({ theme, $collapsed }) => `
55
- display: flex;
56
- flex-direction: column;
57
- justify-content: space-between;
58
- gap: 1px;
59
- position: fixed;
60
- z-index: 1000;
61
- top: 56px;
62
- left: 0;
63
- width: 220px;
64
- padding: 12px;
65
- height: calc(100% - 56px);
66
- border-right: 1px solid ${theme.colors.stroke.light};
67
- background: ${theme.colors.background};
68
- ${
69
- $collapsed &&
70
- `
71
- width: 65px;
72
- `
73
- }
74
- `
75
- );
@@ -112,15 +112,15 @@ const StyledItem = styled.a<StyledProps>(
112
112
  top: 0;
113
113
  height: 100%;
114
114
  width: 0px;
115
- border-top-right-radius: 2px;
116
- border-bottom-right-radius: 2px;
115
+ border-top-right-radius: 5px;
116
+ border-bottom-right-radius: 5px;
117
117
  background: rgaba(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
122
  background: ${theme.colors.primary.main};
123
- width: 3px;
123
+ width: 5px;
124
124
  `
125
125
  : ''
126
126
  }
@@ -1,6 +1,6 @@
1
1
  import styled from 'styled-components';
2
2
  import { CSSProperties, ElementType, ReactNode } from 'react';
3
- import { ColorVariant, TypographyVariant } from '../../Theme/theme';
3
+ import { ColorVariant, TypographyVariant } from '../../Theme';
4
4
  import { resolveThemeColor } from '../../Theme/utils';
5
5
 
6
6
  export interface TypographyProps {
@@ -23,7 +23,7 @@ const StyledTypography = styled.div<{
23
23
  // Resolve color from theme if it's a theme color path, or use the direct color value
24
24
 
25
25
  return `
26
- font-size: ${theme.typography[$variant]};
26
+ font-size: ${theme.typography.variants[$variant].fontSize};
27
27
  font-weight: ${$weight};
28
28
  font-style: ${$style};
29
29
  color: ${resolveThemeColor(theme, $color) || theme.colors.text.main};
@@ -26,12 +26,13 @@ export const StyledContainer = styled.div<StyledContainerProps>(
26
26
  ({ $withHeader, $withSidebar }) => `
27
27
  display: grid;
28
28
  min-height: 100dvh;
29
+ position: relative;
29
30
  grid-template-columns: ${$withSidebar ? 'auto 1fr' : '1fr'};
30
31
  grid-template-rows: ${$withHeader ? 'auto 1fr' : '1fr'};
31
32
  grid-template-areas: ${
32
33
  $withHeader
33
34
  ? $withSidebar
34
- ? `'header header' 'sidebar content'`
35
+ ? `'sidebar header' 'sidebar content'`
35
36
  : `'header' 'content'`
36
37
  : $withSidebar
37
38
  ? `'sidebar content'`
@@ -1,4 +1,3 @@
1
- import { ReactElement, ReactNode } from 'react';
2
1
  import { ThemeProvider as ThemeProviderStyled } from 'styled-components';
3
2
  import { lightTheme } from './theme';
4
3
  import { GlobalStyle } from './GlobalStyle';
@@ -1,4 +1,5 @@
1
- export * from './theme';
2
1
  export * from './GlobalStyle';
3
2
  export * from './ThemeProvider';
4
3
  export * from './utils';
4
+ export * from './types';
5
+ export * from './theme';
@@ -0,0 +1,7 @@
1
+ import 'styled-components';
2
+ import { Palette } from './palette';
3
+ import { Theme } from './types';
4
+
5
+ declare module 'styled-components' {
6
+ export interface DefaultTheme extends Theme {}
7
+ }