@capillarytech/blaze-ui 0.1.6-alpha.41 → 0.1.6-alpha.43

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.
@@ -0,0 +1,183 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import classnames from 'classnames';
4
+ import styled from 'styled-components';
5
+ import * as AntdIcons from '@ant-design/icons';
6
+ import { IconWrapper, BackgroundWrapper, iconStyles } from './styles';
7
+ import withStyles from '../utils/withStyles';
8
+
9
+ const StyledIcon = styled.span`
10
+ ${iconStyles}
11
+ `;
12
+
13
+ const getSvgIcon = (type, svgProps = {}) => {
14
+ const icons = {
15
+ // Add your SVG icons here if needed
16
+ };
17
+
18
+ const IconComponent = icons[type];
19
+ return IconComponent ? <IconComponent {...svgProps} /> : null;
20
+ };
21
+
22
+ const getAntIcon = (type) => {
23
+ // Convert kebab-case to PascalCase for Ant Design icon naming
24
+ const pascalCase = type
25
+ .split('-')
26
+ .map(part => part.charAt(0).toUpperCase() + part.slice(1))
27
+ .join('');
28
+
29
+ // Try different naming conventions
30
+ const iconName = `${pascalCase}Outlined`;
31
+ const iconNameFilled = `${pascalCase}Filled`;
32
+ const iconNameTwoTone = `${pascalCase}TwoTone`;
33
+
34
+ return AntdIcons[iconName] || AntdIcons[iconNameFilled] || AntdIcons[iconNameTwoTone];
35
+ };
36
+
37
+ const CapIcon = ({
38
+ type,
39
+ size = 'm',
40
+ style = {},
41
+ className = '',
42
+ disabled = false,
43
+ spin = false,
44
+ rotate,
45
+ withBackground = false,
46
+ backgroundProps = {},
47
+ onClick,
48
+ textLabel,
49
+ component,
50
+ svgProps = {},
51
+ allowSvg = true,
52
+ ...rest
53
+ }) => {
54
+ const handleClick = (e) => {
55
+ if (!disabled && onClick) {
56
+ onClick(e);
57
+ }
58
+ };
59
+
60
+ // Render custom component if provided
61
+ if (component) {
62
+ return (
63
+ <IconWrapper
64
+ className={classnames('cap-icon', size, { 'with-text-label': textLabel }, className)}
65
+ style={style}
66
+ disabled={disabled}
67
+ onClick={handleClick}
68
+ {...rest}
69
+ >
70
+ {component}
71
+ {textLabel}
72
+ </IconWrapper>
73
+ );
74
+ }
75
+
76
+ // Try to get SVG icon if allowSvg is true
77
+ const svgIcon = allowSvg && type ? getSvgIcon(type, svgProps) : null;
78
+
79
+ // If SVG icon exists and allowSvg is true, use it
80
+ if (svgIcon) {
81
+ const iconComponent = (
82
+ <IconWrapper
83
+ className={classnames('cap-icon', size, { spin }, { 'with-text-label': textLabel }, className)}
84
+ style={{
85
+ ...style,
86
+ transform: rotate ? `rotate(${rotate}deg)` : undefined
87
+ }}
88
+ disabled={disabled}
89
+ onClick={handleClick}
90
+ {...rest}
91
+ >
92
+ {svgIcon}
93
+ {textLabel}
94
+ </IconWrapper>
95
+ );
96
+
97
+ return withBackground ? (
98
+ <BackgroundWrapper size={size} {...backgroundProps}>
99
+ {iconComponent}
100
+ </BackgroundWrapper>
101
+ ) : iconComponent;
102
+ }
103
+
104
+ // Try to get Ant Design icon
105
+ const AntIcon = type ? getAntIcon(type) : null;
106
+
107
+ if (AntIcon) {
108
+ const iconComponent = (
109
+ <IconWrapper
110
+ className={classnames('cap-icon', size, { 'with-text-label': textLabel }, className)}
111
+ style={style}
112
+ disabled={disabled}
113
+ onClick={handleClick}
114
+ {...rest}
115
+ >
116
+ <AntIcon
117
+ spin={spin}
118
+ rotate={rotate}
119
+ />
120
+ {textLabel}
121
+ </IconWrapper>
122
+ );
123
+
124
+ return withBackground ? (
125
+ <BackgroundWrapper size={size} {...backgroundProps}>
126
+ {iconComponent}
127
+ </BackgroundWrapper>
128
+ ) : iconComponent;
129
+ }
130
+
131
+ // Fallback: render an empty icon container
132
+ return (
133
+ <IconWrapper
134
+ className={classnames('cap-icon', size, { 'with-text-label': textLabel }, className)}
135
+ style={style}
136
+ disabled={disabled}
137
+ onClick={handleClick}
138
+ {...rest}
139
+ >
140
+ {textLabel}
141
+ </IconWrapper>
142
+ );
143
+ };
144
+
145
+ CapIcon.propTypes = {
146
+ type: PropTypes.string,
147
+ size: PropTypes.oneOf(['xs', 's', 'm', 'l']),
148
+ style: PropTypes.object,
149
+ className: PropTypes.string,
150
+ disabled: PropTypes.bool,
151
+ spin: PropTypes.bool,
152
+ rotate: PropTypes.number,
153
+ withBackground: PropTypes.bool,
154
+ backgroundProps: PropTypes.object,
155
+ onClick: PropTypes.func,
156
+ textLabel: PropTypes.node,
157
+ component: PropTypes.node,
158
+ svgProps: PropTypes.object,
159
+ allowSvg: PropTypes.bool,
160
+ };
161
+
162
+ CapIcon.defaultProps = {
163
+ size: 'm',
164
+ style: {},
165
+ className: '',
166
+ disabled: false,
167
+ spin: false,
168
+ withBackground: false,
169
+ backgroundProps: {},
170
+ svgProps: {},
171
+ allowSvg: true,
172
+ };
173
+
174
+ // Create AntIcon subcomponent for backward compatibility
175
+ const AntIcon = styled.i`
176
+ display: inline-flex;
177
+ align-items: center;
178
+ justify-content: center;
179
+ `;
180
+
181
+ CapIcon.AntIcon = AntIcon;
182
+
183
+ export default withStyles(CapIcon, iconStyles);
@@ -0,0 +1,3 @@
1
+ import CapIcon from './CapIcon';
2
+
3
+ export default CapIcon;
@@ -0,0 +1,76 @@
1
+ import styled, { css } from 'styled-components';
2
+ import * as styledVars from '../styled/variables';
3
+
4
+ export const IconWrapper = styled.span`
5
+ display: inline-flex;
6
+ align-items: center;
7
+ justify-content: center;
8
+ cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
9
+ opacity: ${({ disabled }) => (disabled ? 0.5 : 1)};
10
+
11
+ &.xs {
12
+ font-size: 12px;
13
+ width: 12px;
14
+ height: 12px;
15
+ }
16
+
17
+ &.s {
18
+ font-size: 16px;
19
+ width: 16px;
20
+ height: 16px;
21
+ }
22
+
23
+ &.m {
24
+ font-size: 24px;
25
+ width: 24px;
26
+ height: 24px;
27
+ }
28
+
29
+ &.l {
30
+ font-size: 32px;
31
+ width: 32px;
32
+ height: 32px;
33
+ }
34
+
35
+ &.with-text-label {
36
+ display: inline-flex;
37
+ align-items: center;
38
+ gap: 8px;
39
+ }
40
+ `;
41
+
42
+ export const BackgroundWrapper = styled.span`
43
+ display: inline-flex;
44
+ align-items: center;
45
+ justify-content: center;
46
+ border-radius: 50%;
47
+ background-color: ${({ bgColor }) => bgColor || styledVars.CAP_G09};
48
+ width: ${({ size }) => (size === 'xs' ? '20px' : size === 's' ? '24px' : size === 'l' ? '48px' : '36px')};
49
+ height: ${({ size }) => (size === 'xs' ? '20px' : size === 's' ? '24px' : size === 'l' ? '48px' : '36px')};
50
+ `;
51
+
52
+ export const iconStyles = css`
53
+ &.cap-icon {
54
+ display: inline-flex;
55
+ align-items: center;
56
+
57
+ .anticon {
58
+ display: flex;
59
+ align-items: center;
60
+ justify-content: center;
61
+ }
62
+
63
+ &.spin {
64
+ animation: rotate 2s linear infinite;
65
+ }
66
+ }
67
+
68
+ @keyframes rotate {
69
+ from {
70
+ transform: rotate(0deg);
71
+ }
72
+ to {
73
+ transform: rotate(360deg);
74
+ }
75
+ }
76
+ `;
@@ -0,0 +1,126 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import classnames from 'classnames';
4
+ import styled from 'styled-components';
5
+ import { StyledLabelDiv, StyledLabelSpan, labelStyles } from './styles';
6
+ import withStyles from '../utils/withStyles';
7
+
8
+ const getLabelTypeStyles = (type) => {
9
+ const types = {
10
+ label1: { fontSize: '12px', color: '#5e6c84', fontWeight: 'normal', lineHeight: 'normal' },
11
+ label2: { fontSize: '12px', color: '#091e42', fontWeight: 'normal', lineHeight: 'normal' },
12
+ label3: { fontSize: '12px', color: '#97a0af', fontWeight: 'normal', lineHeight: 'normal' },
13
+ label4: { fontSize: '12px', color: '#091e42', fontWeight: '500', lineHeight: 'normal' },
14
+ label5: { fontSize: '10px', color: '#091e42', fontWeight: 'normal', lineHeight: 'normal' },
15
+ label6: { fontSize: '12px', color: '#b3bac5', fontWeight: 'normal', lineHeight: 'normal' },
16
+ label7: { fontSize: '14px', color: '#5e6c84', fontWeight: '500', lineHeight: 'normal' },
17
+ label8: { fontSize: '12px', color: '#091e42', fontWeight: '500', lineHeight: 'normal' },
18
+ label9: { fontSize: '12px', color: '#091e42', lineHeight: '16px', fontWeight: 'normal' },
19
+ label10: { fontSize: '12px', color: '#ffffff', lineHeight: '16px', fontWeight: 'normal' },
20
+ label11: { fontSize: '10px', color: '#5e6c84', fontWeight: 'normal', lineHeight: 'normal' },
21
+ label12: { fontSize: '12px', color: '#ffffff', fontWeight: 'normal', lineHeight: 'normal' },
22
+ label13: { fontSize: '10px', color: '#97a0af', fontWeight: 'normal', lineHeight: 'normal' },
23
+ label14: { fontSize: '14px', color: '#676e7c', fontWeight: 'normal', lineHeight: 'normal' },
24
+ label15: { fontSize: '14px', color: '#091e42', fontWeight: 'normal', lineHeight: 'normal' },
25
+ label16: { fontSize: '14px', color: '#091e42', fontWeight: '500', lineHeight: 'normal' },
26
+ label17: { fontSize: '16px', color: '#091e42', fontWeight: '500', lineHeight: 'normal' },
27
+ label18: { fontSize: '14px', color: '#5e6c84', fontWeight: 'normal', lineHeight: 'normal' },
28
+ label19: { fontSize: '12px', lineHeight: '16px', fontWeight: 'normal', color: 'rgba(0, 0, 0, 0.87)' },
29
+ label20: { fontSize: '14px', color: '#2466ea', fontWeight: '500', lineHeight: 'normal' },
30
+ label21: { fontSize: '12px', color: '#2466ea', fontWeight: 'normal', lineHeight: 'normal' },
31
+ label22: { fontSize: '24px', color: '#5f6d85', lineHeight: '28px', fontWeight: 'normal' },
32
+ label23: { fontSize: '14px', color: '#ffffff', fontWeight: 'normal', lineHeight: 'normal' },
33
+ label24: { fontSize: '14px', color: '#5e6c84', fontWeight: '400', lineHeight: '20px' },
34
+ label25: { fontSize: '14px', color: '#5e6c84', fontWeight: '500', lineHeight: '20px' },
35
+ label26: { fontSize: '10px', color: '#091E42', fontWeight: '400', lineHeight: '12px' },
36
+ label27: { fontSize: '12px', color: '#2466EA', fontWeight: '500', lineHeight: '16px' },
37
+ label28: { color: '#FFF', fontSize: '12px', fontWeight: '500', lineHeight: '16px' },
38
+ label29: { color: '#FFF', fontSize: '10px', fontWeight: '400', lineHeight: '12px' },
39
+ label30: { color: '#FFF', fontSize: '10px', fontWeight: '400', lineHeight: '12px' },
40
+ label31: { fontSize: '12px', color: '#091E42', fontWeight: '400', lineHeight: '16px' },
41
+ label32: { lineHeight: '20px', fontSize: '14px', color: '#ffffff', fontWeight: '500' },
42
+ label33: { fontSize: '14px', color: '#2466EA', fontWeight: '500', lineHeight: '20px' },
43
+ };
44
+
45
+ return types[type] || types.label1;
46
+ };
47
+
48
+ const CapLabel = ({
49
+ children,
50
+ type = 'label1',
51
+ className = '',
52
+ style = {},
53
+ fontWeight,
54
+ lineHeight,
55
+ ...rest
56
+ }) => {
57
+ const typeStyles = getLabelTypeStyles(type);
58
+
59
+ return (
60
+ <StyledLabelDiv
61
+ className={classnames('cap-label', type, className)}
62
+ style={style}
63
+ typeStyles={typeStyles}
64
+ fontWeight={fontWeight}
65
+ lineHeight={lineHeight}
66
+ {...rest}
67
+ >
68
+ {children}
69
+ </StyledLabelDiv>
70
+ );
71
+ };
72
+
73
+ CapLabel.propTypes = {
74
+ children: PropTypes.node,
75
+ type: PropTypes.string,
76
+ className: PropTypes.string,
77
+ style: PropTypes.object,
78
+ fontWeight: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
79
+ lineHeight: PropTypes.string,
80
+ };
81
+
82
+ CapLabel.defaultProps = {
83
+ type: 'label1',
84
+ className: '',
85
+ style: {},
86
+ };
87
+
88
+ // Static method for inline label
89
+ const CapLabelInline = styled(({ children, type = 'label1', className = '', style = {}, fontWeight, lineHeight, ...rest }) => {
90
+ const typeStyles = getLabelTypeStyles(type);
91
+
92
+ return (
93
+ <StyledLabelSpan
94
+ className={classnames('cap-label', type, className)}
95
+ style={style}
96
+ typeStyles={typeStyles}
97
+ fontWeight={fontWeight}
98
+ lineHeight={lineHeight}
99
+ {...rest}
100
+ >
101
+ {children}
102
+ </StyledLabelSpan>
103
+ );
104
+ })`
105
+ ${labelStyles}
106
+ `;
107
+
108
+ CapLabelInline.propTypes = {
109
+ children: PropTypes.node,
110
+ type: PropTypes.string,
111
+ className: PropTypes.string,
112
+ style: PropTypes.object,
113
+ fontWeight: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
114
+ lineHeight: PropTypes.string,
115
+ };
116
+
117
+ CapLabelInline.defaultProps = {
118
+ type: 'label1',
119
+ className: '',
120
+ style: {},
121
+ };
122
+
123
+ // Attach the static method
124
+ CapLabel.CapLabelInline = CapLabelInline;
125
+
126
+ export default withStyles(CapLabel, labelStyles);
@@ -0,0 +1,3 @@
1
+ import CapLabel from './CapLabel';
2
+
3
+ export default CapLabel;
@@ -0,0 +1,259 @@
1
+ import styled, { css } from 'styled-components';
2
+ import * as styledVars from '../styled/variables';
3
+
4
+ export const StyledLabelDiv = styled.div`
5
+ font-family: ${styledVars.FONT_FAMILY};
6
+ font-size: ${({ typeStyles }) => typeStyles?.fontSize || '12px'};
7
+ font-weight: ${({ typeStyles, fontWeight }) => fontWeight || typeStyles?.fontWeight || 'normal'};
8
+ color: ${({ typeStyles }) => typeStyles?.color || styledVars.CAP_G04};
9
+ line-height: ${({ typeStyles, lineHeight }) => lineHeight || typeStyles?.lineHeight || 'normal'};
10
+ margin: 0;
11
+ padding: 0;
12
+ `;
13
+
14
+ export const StyledLabelSpan = styled.span`
15
+ font-family: ${styledVars.FONT_FAMILY};
16
+ font-size: ${({ typeStyles }) => typeStyles?.fontSize || '12px'};
17
+ font-weight: ${({ typeStyles, fontWeight }) => fontWeight || typeStyles?.fontWeight || 'normal'};
18
+ color: ${({ typeStyles }) => typeStyles?.color || styledVars.CAP_G04};
19
+ line-height: ${({ typeStyles, lineHeight }) => lineHeight || typeStyles?.lineHeight || 'normal'};
20
+ margin: 0;
21
+ padding: 0;
22
+ `;
23
+
24
+ export const labelStyles = css`
25
+ &.cap-label {
26
+ font-family: ${styledVars.FONT_FAMILY};
27
+
28
+ &.label1 {
29
+ font-size: 12px;
30
+ color: ${styledVars.CAP_G04};
31
+ font-weight: normal;
32
+ line-height: normal;
33
+ }
34
+
35
+ &.label2 {
36
+ font-size: 12px;
37
+ color: ${styledVars.CAP_G01};
38
+ font-weight: normal;
39
+ line-height: normal;
40
+ }
41
+
42
+ &.label3 {
43
+ font-size: 12px;
44
+ color: ${styledVars.CAP_G05};
45
+ font-weight: normal;
46
+ line-height: normal;
47
+ }
48
+
49
+ &.label4 {
50
+ font-size: 12px;
51
+ color: ${styledVars.CAP_G01};
52
+ font-weight: 500;
53
+ line-height: normal;
54
+ }
55
+
56
+ &.label5 {
57
+ font-size: 10px;
58
+ color: ${styledVars.CAP_G01};
59
+ font-weight: normal;
60
+ line-height: normal;
61
+ }
62
+
63
+ &.label6 {
64
+ font-size: 12px;
65
+ color: ${styledVars.CAP_G06};
66
+ font-weight: normal;
67
+ line-height: normal;
68
+ }
69
+
70
+ &.label7 {
71
+ font-size: 14px;
72
+ color: ${styledVars.CAP_G04};
73
+ font-weight: 500;
74
+ line-height: normal;
75
+ }
76
+
77
+ &.label8 {
78
+ font-size: 12px;
79
+ color: ${styledVars.CAP_G01};
80
+ font-weight: 500;
81
+ line-height: normal;
82
+ }
83
+
84
+ &.label9 {
85
+ font-size: 12px;
86
+ color: ${styledVars.CAP_G01};
87
+ line-height: 16px;
88
+ font-weight: normal;
89
+ }
90
+
91
+ &.label10 {
92
+ font-size: 12px;
93
+ color: ${styledVars.CAP_WHITE};
94
+ line-height: 16px;
95
+ font-weight: normal;
96
+ }
97
+
98
+ &.label11 {
99
+ font-size: 10px;
100
+ color: ${styledVars.CAP_G04};
101
+ font-weight: normal;
102
+ line-height: normal;
103
+ }
104
+
105
+ &.label12 {
106
+ font-size: 12px;
107
+ color: ${styledVars.CAP_WHITE};
108
+ font-weight: normal;
109
+ line-height: normal;
110
+ }
111
+
112
+ &.label13 {
113
+ font-size: 10px;
114
+ color: ${styledVars.CAP_G05};
115
+ font-weight: normal;
116
+ line-height: normal;
117
+ }
118
+
119
+ &.label14 {
120
+ font-size: 14px;
121
+ color: #676e7c;
122
+ font-weight: normal;
123
+ line-height: normal;
124
+ }
125
+
126
+ &.label15 {
127
+ font-size: 14px;
128
+ color: ${styledVars.CAP_G01};
129
+ font-weight: normal;
130
+ line-height: normal;
131
+ }
132
+
133
+ &.label16 {
134
+ font-size: 14px;
135
+ color: ${styledVars.CAP_G01};
136
+ font-weight: 500;
137
+ line-height: normal;
138
+ }
139
+
140
+ &.label17 {
141
+ font-size: 16px;
142
+ color: ${styledVars.CAP_G01};
143
+ font-weight: 500;
144
+ line-height: normal;
145
+ }
146
+
147
+ &.label18 {
148
+ font-size: 14px;
149
+ color: ${styledVars.CAP_G04};
150
+ font-weight: normal;
151
+ line-height: normal;
152
+ }
153
+
154
+ &.label19 {
155
+ font-size: 12px;
156
+ line-height: 16px;
157
+ font-weight: normal;
158
+ color: rgba(0, 0, 0, 0.87);
159
+ }
160
+
161
+ &.label20 {
162
+ font-size: 14px;
163
+ color: ${styledVars.CAP_BLUE01};
164
+ font-weight: 500;
165
+ line-height: normal;
166
+ }
167
+
168
+ &.label21 {
169
+ font-size: 12px;
170
+ color: ${styledVars.CAP_BLUE01};
171
+ font-weight: normal;
172
+ line-height: normal;
173
+ }
174
+
175
+ &.label22 {
176
+ font-size: 24px;
177
+ color: ${styledVars.CAP_G04};
178
+ line-height: 28px;
179
+ font-weight: normal;
180
+ }
181
+
182
+ &.label23 {
183
+ font-size: 14px;
184
+ color: ${styledVars.CAP_WHITE};
185
+ font-weight: normal;
186
+ line-height: normal;
187
+ }
188
+
189
+ &.label24 {
190
+ font-size: 14px;
191
+ color: ${styledVars.CAP_G04};
192
+ font-weight: 400;
193
+ line-height: 20px;
194
+ }
195
+
196
+ &.label25 {
197
+ font-size: 14px;
198
+ color: ${styledVars.CAP_G04};
199
+ font-weight: 500;
200
+ line-height: 20px;
201
+ }
202
+
203
+ &.label26 {
204
+ font-size: 10px;
205
+ color: ${styledVars.CAP_G01};
206
+ font-weight: 400;
207
+ line-height: 12px;
208
+ }
209
+
210
+ &.label27 {
211
+ font-size: 12px;
212
+ color: ${styledVars.CAP_BLUE01};
213
+ font-weight: 500;
214
+ line-height: 16px;
215
+ }
216
+
217
+ &.label28 {
218
+ color: ${styledVars.CAP_WHITE};
219
+ font-size: 12px;
220
+ font-weight: 500;
221
+ line-height: 16px;
222
+ }
223
+
224
+ &.label29 {
225
+ color: ${styledVars.CAP_WHITE};
226
+ font-size: 10px;
227
+ font-weight: 400;
228
+ line-height: 12px;
229
+ }
230
+
231
+ &.label30 {
232
+ color: ${styledVars.CAP_WHITE};
233
+ font-size: 10px;
234
+ font-weight: 400;
235
+ line-height: 12px;
236
+ }
237
+
238
+ &.label31 {
239
+ font-size: 12px;
240
+ color: ${styledVars.CAP_G01};
241
+ font-weight: 400;
242
+ line-height: 16px;
243
+ }
244
+
245
+ &.label32 {
246
+ line-height: 20px;
247
+ font-size: 14px;
248
+ color: ${styledVars.CAP_WHITE};
249
+ font-weight: 500;
250
+ }
251
+
252
+ &.label33 {
253
+ font-size: 14px;
254
+ color: ${styledVars.CAP_BLUE01};
255
+ font-weight: 500;
256
+ line-height: 20px;
257
+ }
258
+ }
259
+ `;
@@ -0,0 +1,123 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import classnames from 'classnames';
4
+ import styled from 'styled-components';
5
+ import { StyledRow, rowStyles } from './styles';
6
+ import withStyles from '../utils/withStyles';
7
+
8
+ const CapRow = ({
9
+ children,
10
+ className = '',
11
+ style = {},
12
+ justify = 'start',
13
+ align = 'top',
14
+ gutter = 0,
15
+ wrap = true,
16
+ type,
17
+ width,
18
+ height,
19
+ margin,
20
+ padding,
21
+ prefixCls = 'ant-row',
22
+ fullWidth = false,
23
+ fullHeight = false,
24
+ fillSpace = false,
25
+ responsive = true,
26
+ vertical = false,
27
+ noWrap = false,
28
+ gap = null,
29
+ ...rest
30
+ }) => {
31
+ // Use either the gap property or gutter for spacing
32
+ const gutterValue = gap !== null ? null : gutter;
33
+ const wrapValue = noWrap ? false : wrap;
34
+
35
+ return (
36
+ <StyledRow
37
+ className={classnames(
38
+ 'cap-row-v2',
39
+ {
40
+ 'with-custom-width': width,
41
+ 'with-custom-height': height,
42
+ 'fill-space': fillSpace,
43
+ 'full-width': fullWidth,
44
+ 'full-height': fullHeight,
45
+ 'ant-row-no-wrap': noWrap,
46
+ 'with-gap': gap !== null,
47
+ },
48
+ className
49
+ )}
50
+ style={{
51
+ ...(gap !== null ? { gap: typeof gap === 'number' ? `${gap}px` : gap } : {}),
52
+ ...style,
53
+ }}
54
+ justify={justify}
55
+ align={align}
56
+ gutter={gutterValue}
57
+ wrap={wrapValue}
58
+ type={type}
59
+ width={width}
60
+ height={height}
61
+ margin={margin}
62
+ padding={padding}
63
+ prefixCls={prefixCls}
64
+ fullWidth={fullWidth}
65
+ fullHeight={fullHeight}
66
+ fillSpace={fillSpace}
67
+ responsive={responsive}
68
+ vertical={vertical}
69
+ {...rest}
70
+ >
71
+ {children}
72
+ </StyledRow>
73
+ );
74
+ };
75
+
76
+ CapRow.propTypes = {
77
+ children: PropTypes.node,
78
+ className: PropTypes.string,
79
+ style: PropTypes.object,
80
+ justify: PropTypes.oneOf(['start', 'end', 'center', 'space-around', 'space-between', 'space-evenly']),
81
+ align: PropTypes.oneOf(['top', 'middle', 'bottom', 'stretch']),
82
+ gutter: PropTypes.oneOfType([
83
+ PropTypes.number,
84
+ PropTypes.object,
85
+ PropTypes.arrayOf(PropTypes.number),
86
+ ]),
87
+ wrap: PropTypes.bool,
88
+ type: PropTypes.string,
89
+ width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
90
+ height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
91
+ margin: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
92
+ padding: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
93
+ prefixCls: PropTypes.string,
94
+ fullWidth: PropTypes.bool,
95
+ fullHeight: PropTypes.bool,
96
+ fillSpace: PropTypes.bool,
97
+ responsive: PropTypes.bool,
98
+ vertical: PropTypes.bool,
99
+ noWrap: PropTypes.bool,
100
+ gap: PropTypes.oneOfType([
101
+ PropTypes.number,
102
+ PropTypes.arrayOf(PropTypes.number),
103
+ PropTypes.string,
104
+ ]),
105
+ };
106
+
107
+ CapRow.defaultProps = {
108
+ className: '',
109
+ style: {},
110
+ justify: 'start',
111
+ align: 'top',
112
+ gutter: 0,
113
+ wrap: true,
114
+ prefixCls: 'ant-row',
115
+ fullWidth: false,
116
+ fullHeight: false,
117
+ fillSpace: false,
118
+ responsive: true,
119
+ vertical: false,
120
+ noWrap: false,
121
+ };
122
+
123
+ export default withStyles(CapRow, rowStyles);
@@ -0,0 +1,3 @@
1
+ import CapRow from './CapRow';
2
+
3
+ export default CapRow;
@@ -0,0 +1,50 @@
1
+ import styled, { css } from 'styled-components';
2
+ import { Row } from 'antd-v5';
3
+ import * as styledVars from '../styled/variables';
4
+
5
+ export const StyledRow = styled(Row)`
6
+ width: ${({ width, fullWidth }) => (fullWidth ? '100%' : width || 'auto')};
7
+ height: ${({ height, fullHeight }) => (fullHeight ? '100%' : height || 'auto')};
8
+ margin: ${({ margin }) => margin || 'inherit'};
9
+ padding: ${({ padding }) => padding || 'inherit'};
10
+ ${({ responsive }) => !responsive && css`
11
+ display: flex;
12
+ flex-wrap: wrap;
13
+ `};
14
+ ${({ fillSpace }) => fillSpace && css`
15
+ flex: 1;
16
+ `};
17
+ `;
18
+
19
+ export const rowStyles = css`
20
+ &.cap-row-v2 {
21
+ &.with-custom-width {
22
+ width: auto;
23
+ }
24
+
25
+ &.with-custom-height {
26
+ height: auto;
27
+ }
28
+
29
+ &.fill-space {
30
+ flex: 1;
31
+ }
32
+
33
+ &.full-width {
34
+ width: 100%;
35
+ }
36
+
37
+ &.full-height {
38
+ height: 100%;
39
+ }
40
+
41
+ &.ant-row-no-wrap {
42
+ flex-wrap: nowrap;
43
+ }
44
+
45
+ &.with-gap {
46
+ display: grid;
47
+ grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
48
+ }
49
+ }
50
+ `;
@@ -0,0 +1,98 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Tooltip } from 'antd-v5';
4
+ import classnames from 'classnames';
5
+ import styled from 'styled-components';
6
+ import { tooltipStyles } from './styles';
7
+ import withStyles from '../utils/withStyles';
8
+
9
+ const StyledTooltip = styled(Tooltip)`
10
+ ${tooltipStyles}
11
+ `;
12
+
13
+ const CapTooltip = ({
14
+ title,
15
+ children,
16
+ placement = 'top',
17
+ visible,
18
+ defaultVisible = false,
19
+ trigger = 'hover',
20
+ destroyTooltipOnHide = false,
21
+ mouseEnterDelay = 0.1,
22
+ mouseLeaveDelay = 0.1,
23
+ overlayClassName = '',
24
+ overlayStyle,
25
+ onVisibleChange,
26
+ align,
27
+ arrowPointAtCenter = false,
28
+ autoAdjustOverflow = true,
29
+ getPopupContainer,
30
+ className = '',
31
+ ...rest
32
+ }) => {
33
+ return (
34
+ <StyledTooltip
35
+ title={title}
36
+ placement={placement}
37
+ open={visible}
38
+ defaultOpen={defaultVisible}
39
+ trigger={trigger}
40
+ destroyTooltipOnHide={destroyTooltipOnHide}
41
+ mouseEnterDelay={mouseEnterDelay}
42
+ mouseLeaveDelay={mouseLeaveDelay}
43
+ overlayClassName={classnames('cap-tooltip-overlay-v2', overlayClassName)}
44
+ overlayStyle={overlayStyle}
45
+ onOpenChange={onVisibleChange}
46
+ align={align}
47
+ arrow={{ pointAtCenter: arrowPointAtCenter }}
48
+ autoAdjustOverflow={autoAdjustOverflow}
49
+ getPopupContainer={getPopupContainer}
50
+ className={classnames('cap-tooltip-v2', className)}
51
+ {...rest}
52
+ >
53
+ {children}
54
+ </StyledTooltip>
55
+ );
56
+ };
57
+
58
+ CapTooltip.propTypes = {
59
+ title: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
60
+ children: PropTypes.node,
61
+ placement: PropTypes.oneOf([
62
+ 'top', 'left', 'right', 'bottom',
63
+ 'topLeft', 'topRight', 'bottomLeft', 'bottomRight',
64
+ 'leftTop', 'leftBottom', 'rightTop', 'rightBottom',
65
+ ]),
66
+ visible: PropTypes.bool,
67
+ defaultVisible: PropTypes.bool,
68
+ trigger: PropTypes.oneOfType([
69
+ PropTypes.string,
70
+ PropTypes.arrayOf(PropTypes.string),
71
+ ]),
72
+ destroyTooltipOnHide: PropTypes.bool,
73
+ mouseEnterDelay: PropTypes.number,
74
+ mouseLeaveDelay: PropTypes.number,
75
+ overlayClassName: PropTypes.string,
76
+ overlayStyle: PropTypes.object,
77
+ onVisibleChange: PropTypes.func,
78
+ align: PropTypes.object,
79
+ arrowPointAtCenter: PropTypes.bool,
80
+ autoAdjustOverflow: PropTypes.bool,
81
+ getPopupContainer: PropTypes.func,
82
+ className: PropTypes.string,
83
+ };
84
+
85
+ CapTooltip.defaultProps = {
86
+ placement: 'top',
87
+ defaultVisible: false,
88
+ trigger: 'hover',
89
+ destroyTooltipOnHide: false,
90
+ mouseEnterDelay: 0.1,
91
+ mouseLeaveDelay: 0.1,
92
+ overlayClassName: '',
93
+ arrowPointAtCenter: false,
94
+ autoAdjustOverflow: true,
95
+ className: '',
96
+ };
97
+
98
+ export default withStyles(CapTooltip, tooltipStyles);
@@ -0,0 +1,3 @@
1
+ import CapTooltip from './CapTooltip';
2
+
3
+ export default CapTooltip;
@@ -0,0 +1,34 @@
1
+ import styled, { css } from 'styled-components';
2
+ import * as styledVars from '../styled/variables';
3
+
4
+ export const tooltipStyles = css`
5
+ &.cap-tooltip-overlay-v2 {
6
+ .ant-tooltip-inner {
7
+ background-color: ${styledVars.CAP_G01};
8
+ color: ${styledVars.CAP_WHITE};
9
+ padding: 8px 12px;
10
+ font-size: 14px;
11
+ line-height: 20px;
12
+ border-radius: ${styledVars.RADIUS_04};
13
+ max-width: 300px;
14
+ word-wrap: break-word;
15
+ }
16
+
17
+ .ant-tooltip-arrow::before {
18
+ background-color: ${styledVars.CAP_G01};
19
+ }
20
+ }
21
+
22
+ .button-disabled-tooltip-wrapper {
23
+ display: inline-block;
24
+ cursor: not-allowed;
25
+
26
+ .ant-btn[disabled] {
27
+ pointer-events: none;
28
+ }
29
+ }
30
+ `;
31
+
32
+ export const StyledTooltipWrapper = styled.div`
33
+ display: inline-block;
34
+ `;
@@ -0,0 +1,82 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import classnames from 'classnames';
4
+ import { CapTooltip, CapIcon } from '../';
5
+ import withStyles from '../utils/withStyles';
6
+ import { tooltipWithInfoStyles } from './styles';
7
+
8
+ /**
9
+ * CapTooltipWithInfo - A component that combines an info icon with a tooltip
10
+ * for displaying additional information on hover or other trigger events.
11
+ */
12
+ const CapTooltipWithInfo = ({
13
+ title,
14
+ iconSize = 's',
15
+ iconType = 'info-circle',
16
+ placement = 'top',
17
+ trigger = 'hover',
18
+ className = '',
19
+ tooltipProps = {},
20
+ iconProps = {},
21
+ ...rest
22
+ }) => {
23
+ return (
24
+ <span
25
+ className={classnames('cap-tooltip-with-info', className)}
26
+ {...rest}
27
+ >
28
+ <CapTooltip
29
+ title={title}
30
+ placement={placement}
31
+ trigger={trigger}
32
+ {...tooltipProps}
33
+ >
34
+ <span className="cap-tooltip-with-info-icon">
35
+ <CapIcon
36
+ type={iconType}
37
+ size={iconSize}
38
+ {...iconProps}
39
+ />
40
+ </span>
41
+ </CapTooltip>
42
+ </span>
43
+ );
44
+ };
45
+
46
+ CapTooltipWithInfo.propTypes = {
47
+ /** Content to display in the tooltip */
48
+ title: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired,
49
+ /** Size of the info icon */
50
+ iconSize: PropTypes.oneOf(['xs', 's', 'm', 'l']),
51
+ /** Type of icon to display */
52
+ iconType: PropTypes.string,
53
+ /** Placement of the tooltip relative to the icon */
54
+ placement: PropTypes.oneOf([
55
+ 'top', 'left', 'right', 'bottom',
56
+ 'topLeft', 'topRight', 'bottomLeft', 'bottomRight',
57
+ 'leftTop', 'leftBottom', 'rightTop', 'rightBottom',
58
+ ]),
59
+ /** How the tooltip is triggered */
60
+ trigger: PropTypes.oneOfType([
61
+ PropTypes.string,
62
+ PropTypes.arrayOf(PropTypes.string),
63
+ ]),
64
+ /** Additional class name */
65
+ className: PropTypes.string,
66
+ /** Additional props passed to the CapTooltip component */
67
+ tooltipProps: PropTypes.object,
68
+ /** Additional props passed to the CapIcon component */
69
+ iconProps: PropTypes.object,
70
+ };
71
+
72
+ CapTooltipWithInfo.defaultProps = {
73
+ iconSize: 's',
74
+ iconType: 'info-circle',
75
+ placement: 'top',
76
+ trigger: 'hover',
77
+ className: '',
78
+ tooltipProps: {},
79
+ iconProps: {},
80
+ };
81
+
82
+ export default withStyles(CapTooltipWithInfo, tooltipWithInfoStyles);
@@ -0,0 +1,3 @@
1
+ import CapTooltipWithInfo from './CapTooltipWithInfo';
2
+
3
+ export default CapTooltipWithInfo;
@@ -0,0 +1,22 @@
1
+ import { css } from 'styled-components';
2
+ import * as styledVars from '../styled/variables';
3
+
4
+ export const tooltipWithInfoStyles = css`
5
+ &.cap-tooltip-with-info {
6
+ display: inline-flex;
7
+ align-items: center;
8
+ cursor: default;
9
+
10
+ .cap-tooltip-with-info-icon {
11
+ color: ${styledVars.CAP_G06};
12
+ margin-left: 4px;
13
+ cursor: help;
14
+
15
+ &:hover {
16
+ color: ${styledVars.CAP_G07};
17
+ }
18
+ }
19
+ }
20
+ `;
21
+
22
+ export default tooltipWithInfoStyles;
@@ -2,13 +2,10 @@
2
2
  import React, { useState, useEffect, useMemo, useCallback, memo } from 'react';
3
3
  import PropTypes from 'prop-types';
4
4
  import classnames from 'classnames';
5
- import { TreeSelect, Tooltip, Input, Button } from 'antd-v5';
5
+ import { TreeSelect, Input, Button } from 'antd-v5';
6
6
  import styled from 'styled-components';
7
7
  import * as styledVars from '../styled/variables';
8
- import uploadIcon from '../assets/upload.svg';
9
-
10
- import { InfoCircleOutlined, SearchOutlined, WarningFilled, DownOutlined } from '@ant-design/icons';
11
-
8
+ import { CapLabel, CapTooltipWithInfo, CapRow, CapIcon } from '../';
12
9
  import withStyles from '../utils/withStyles';
13
10
  import { SelectWrapper, HeaderWrapper, selectStyles } from './styles';
14
11
 
@@ -57,10 +54,14 @@ const CapUnifiedSelect = ({
57
54
  };
58
55
 
59
56
  const NoResult = memo(({ noResultText, className }) => (
60
- <div className={classnames(className, "cap-unified-select-no-result")}>
61
- <WarningFilled className="cap-unified-select-no-result-icon" />
62
- <div className="cap-unified-select-no-result-text">{noResultText}</div>
63
- </div>
57
+ <CapRow
58
+ className={classnames(className, "cap-unified-select-no-result")}
59
+ align="middle"
60
+ gap={8}
61
+ >
62
+ <CapIcon type="warning" size="s" />
63
+ <CapLabel className="cap-unified-select-no-result-text">{noResultText}</CapLabel>
64
+ </CapRow>
64
65
  ));
65
66
 
66
67
  const getFilteredTreeData = useCallback((data, search) => {
@@ -137,10 +138,10 @@ const CapUnifiedSelect = ({
137
138
  const suffix = useMemo(() => {
138
139
  return isMulti && Array.isArray(value) && value?.length > 1 ? (
139
140
  <>
140
- <span>+{value.length - 1} more <DownOutlined /></span>
141
+ <span>+{value.length - 1} more <CapIcon type="down" size="s" /></span>
141
142
  </>
142
143
  ) : (
143
- <DownOutlined />
144
+ <CapIcon type="down" size="s" />
144
145
  );
145
146
  }, [isMulti, value]);
146
147
 
@@ -157,15 +158,17 @@ const CapUnifiedSelect = ({
157
158
  return (
158
159
  <>
159
160
  <HeaderWrapper className={classnames(disabled ? 'disabled' : '', 'cap-unified-select-header')}>
160
- {headerLabel && <label type="label16" className={classnames(disabled ? 'disabled' : '', 'cap-unified-select-header-label')}>{headerLabel}</label>}
161
+ {headerLabel && <CapLabel type="label16" className={classnames(disabled ? 'disabled' : '', 'cap-unified-select-header-label')}>{headerLabel}</CapLabel>}
161
162
  {tooltip && (
162
- <Tooltip title={tooltip} rootClassName="cap-unified-tooltip" className={classnames(disabled ? 'disabled' : '', 'cap-unified-select-header-tooltip')}>
163
- <InfoCircleOutlined />
164
- </Tooltip>
163
+ <CapTooltipWithInfo
164
+ title={tooltip}
165
+ className={classnames(disabled ? 'disabled' : '', 'cap-unified-select-header-tooltip')}
166
+ iconProps={{ disabled }}
167
+ />
165
168
  )}
166
169
  </HeaderWrapper>
167
170
  <div className="cap-unified-select-header-byline-text">
168
- {bylineText && <label className={classnames(disabled ? 'disabled' : '', 'cap-unified-select-header-byline-text')}>{bylineText}</label>}
171
+ {bylineText && <CapLabel className={classnames(disabled ? 'disabled' : '', 'cap-unified-select-header-byline-text')}>{bylineText}</CapLabel>}
169
172
  </div>
170
173
  </>
171
174
  );
@@ -185,46 +188,55 @@ const CapUnifiedSelect = ({
185
188
  return (
186
189
  <div className={classnames(popupClassName, `${type}-popup-container`)}>
187
190
  {showSearch && (
188
- <div className={classnames("cap-unified-select-search-container")}>
191
+ <CapRow className={classnames("cap-unified-select-search-container")} align="middle">
189
192
  <Input
190
- prefix={<SearchOutlined style={{ color: styledVars.CAP_G06 }} />}
193
+ prefix={<CapIcon type="search" size="s" style={{ color: styledVars.CAP_G06 }} />}
191
194
  placeholder="Search"
192
195
  variant="borderless"
193
196
  value={searchText}
194
197
  onChange={e => setSearchText(e.target.value)}
195
198
  onKeyDown={e => e.stopPropagation()}
196
199
  />
197
- </div>
200
+ </CapRow>
198
201
  )}
199
202
  {isMulti && showUpload && (
200
- <div className={classnames("cap-unified-select-upload-container")}>
203
+ <CapRow className={classnames("cap-unified-select-upload-container")} align="middle">
201
204
  <Button
202
205
  type="link"
203
- icon={<img src={uploadIcon} alt="upload" />}
206
+ icon={<CapIcon type="upload" size="s" />}
204
207
  onClick={() => {}}
205
208
  className={classnames("cap-unified-select-upload-button")}
206
209
  >
207
210
  Upload
208
211
  </Button>
209
- </div>
212
+ </CapRow>
210
213
  )}
211
214
  {isMulti && currentItems.length > 0 && (
212
- <div className={classnames("cap-unified-select-select-all-container")} onClick={e => { e.stopPropagation(); handleSelectAll(); }}>
213
- <input type="checkbox" checked={allSelected} className={classnames("cap-unified-select-select-all-checkbox")} onClick={e => e.stopPropagation()} />
214
- <label className={classnames("cap-unified-select-select-all-label")}>Select all</label>
215
- </div>
215
+ <CapRow
216
+ className={classnames("cap-unified-select-select-all-container")}
217
+ onClick={e => { e.stopPropagation(); handleSelectAll(); }}
218
+ align="middle"
219
+ gap={8}
220
+ >
221
+ <input type="checkbox" checked={allSelected} className={classnames("cap-unified-select-select-all-checkbox")} onClick={e => e.stopPropagation()} />
222
+ <CapLabel className={classnames("cap-unified-select-select-all-label")}>Select all</CapLabel>
223
+ </CapRow>
216
224
  )}
217
225
 
218
226
  {currentItems.length === 0 ? <NoResult noResultText={noResultText} className={classnames(className, "cap-unified-select-no-result")}/> : menu}
219
227
 
220
228
  {currentItems.length > 0 && isMulti && (
221
- <div className={classnames("cap-unified-select-confirm-container")}>
222
- <div>
229
+ <CapRow
230
+ className={classnames("cap-unified-select-confirm-container")}
231
+ justify="space-between"
232
+ align="middle"
233
+ >
234
+ <CapRow gap={8}>
223
235
  <Button type="primary" size="small" className={classnames("cap-unified-select-confirm-button")} onClick={e => { e.stopPropagation(); handleConfirm(); }}>Confirm</Button>
224
236
  <Button type="text" size="small" onClick={e => { e.stopPropagation(); handleCancel(); }}>Cancel</Button>
225
- </div>
226
- {selectedCount > 0 && <span className={classnames("cap-unified-select-selected-count")}>{selectedCount} selected</span>}
227
- </div>
237
+ </CapRow>
238
+ {selectedCount > 0 && <CapLabel className={classnames("cap-unified-select-selected-count")}>{selectedCount} selected</CapLabel>}
239
+ </CapRow>
228
240
  )}
229
241
  </div>
230
242
  );
@@ -257,7 +269,7 @@ const CapUnifiedSelect = ({
257
269
  {...treeSelectVirtualizationProps}
258
270
  popupRender={renderCustomDropdown}
259
271
  />
260
- {isError && <div className={classnames("cap-unified-select-status")}>{errorMessage}</div>}
272
+ {isError && <CapLabel className={classnames("cap-unified-select-status")} style={{ color: 'red' }}>{errorMessage}</CapLabel>}
261
273
  </>
262
274
  );
263
275
  };
package/index.js CHANGED
@@ -1,8 +1,13 @@
1
1
  // Import and export all components
2
+ export { default as CapIcon } from './CapIcon';
2
3
  export { default as CapInput } from './CapInput';
4
+ export { default as CapLabel } from './CapLabel';
5
+ export { default as CapRow } from './CapRow';
3
6
  export { default as CapSkeleton } from './CapSkeleton';
4
7
  export { default as CapSpin } from './CapSpin';
5
8
  export { default as CapTable } from './CapTable';
9
+ export { default as CapTooltip } from './CapTooltip';
10
+ export { default as CapTooltipWithInfo } from './CapTooltipWithInfo';
6
11
  export { default as CapUnifiedSelect } from './CapUnifiedSelect';
7
12
 
8
13
  // Export utilities
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/blaze-ui",
3
3
  "author": "Capillary Technologies",
4
- "version": "0.1.6-alpha.41",
4
+ "version": "0.1.6-alpha.43",
5
5
  "description": "Capillary UI component library with Ant Design v5",
6
6
  "main": "./index.js",
7
7
  "sideEffects": [