@capillarytech/blaze-ui 0.1.6-alpha.42 → 0.1.6-alpha.44

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,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;
@@ -5,9 +5,9 @@ import classnames from 'classnames';
5
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 { CapLabel, CapTooltip, CapRow, CapIcon } from '../';
8
+ import { CapLabel, CapTooltipWithInfo, CapRow, CapIcon } from '../';
9
9
  import withStyles from '../utils/withStyles';
10
- import { SelectWrapper, selectStyles } from './styles';
10
+ import { SelectWrapper, HeaderWrapper, selectStyles } from './styles';
11
11
 
12
12
  const StyledTreeSelect = styled(TreeSelect)`
13
13
  ${selectStyles}
@@ -26,6 +26,7 @@ const CapUnifiedSelect = ({
26
26
  popupClassName,
27
27
  allowClear = false,
28
28
  headerLabel,
29
+ onUpload,
29
30
  tooltip,
30
31
  bylineText,
31
32
  disabled = false,
@@ -42,6 +43,7 @@ const CapUnifiedSelect = ({
42
43
  const [searchText, setSearchText] = useState('');
43
44
  const [tempValue, setTempValue] = useState(value);
44
45
  const [allSelected, setAllSelected] = useState(false);
46
+ const [dropdownOpen, setDropdownOpen] = useState(false);
45
47
 
46
48
 
47
49
  useEffect(() => {
@@ -59,7 +61,7 @@ const CapUnifiedSelect = ({
59
61
  align="middle"
60
62
  gap={8}
61
63
  >
62
- <CapIcon type="warning" size="s" />
64
+ <CapIcon type="warning" size="m" />
63
65
  <CapLabel className="cap-unified-select-no-result-text">{noResultText}</CapLabel>
64
66
  </CapRow>
65
67
  ));
@@ -125,50 +127,66 @@ const CapUnifiedSelect = ({
125
127
 
126
128
  const handleConfirm = useCallback(() => {
127
129
  if (onChange) onChange(tempValue);
130
+ setDropdownOpen(false);
128
131
  }, [onChange, tempValue]);
129
132
 
130
133
  const handleCancel = useCallback(() => {
131
134
  setTempValue(value);
135
+ setDropdownOpen(false);
132
136
  }, [value]);
133
137
 
134
138
  const handleTempChange = useCallback(newValue => {
135
139
  setTempValue(newValue);
136
140
  }, []);
137
141
 
142
+ const handleDropdownVisibilityChange = open => {
143
+ if (!open) {
144
+ setTempValue(value);
145
+ }
146
+ setDropdownOpen(open);
147
+ };
148
+
138
149
  const suffix = useMemo(() => {
139
- return isMulti && Array.isArray(value) && value?.length > 1 ? (
150
+ const displayValue = dropdownOpen ? tempValue : value;
151
+ return isMulti && Array.isArray(displayValue) && displayValue?.length > 1 ? (
140
152
  <>
141
- <span>+{value.length - 1} more <CapIcon type="down" size="s" /></span>
153
+ <span>+{displayValue.length - 1} more <CapIcon type="down" size="s" /></span>
142
154
  </>
143
155
  ) : (
144
156
  <CapIcon type="down" size="s" />
145
157
  );
146
- }, [isMulti, value]);
158
+ }, [isMulti, value, tempValue, dropdownOpen]);
147
159
 
148
160
  const prefix = useMemo(() => {
149
- if (isMulti && Array.isArray(value) && value?.length > 0) {
150
- const selectedLabels = options.filter(opt => value.includes(opt.value)).map(opt => opt.label);
151
- return selectedLabels[0];
161
+ if (isMulti) {
162
+ if (Array.isArray(tempValue) && tempValue?.length > 0) {
163
+ const firstSelectedValue = tempValue[0];
164
+ const firstSelectedOption = options.find(opt => opt.value === firstSelectedValue);
165
+ return firstSelectedOption?.label || null;
166
+ }
167
+ else if (Array.isArray(value) && value?.length > 0) {
168
+ const firstSelectedValue = value[0];
169
+ const firstSelectedOption = options.find(opt => opt.value === firstSelectedValue);
170
+ return firstSelectedOption?.label || null;
171
+ }
152
172
  }
153
173
  return null;
154
- }, [isMulti, value, options]);
174
+ }, [isMulti, value, tempValue, options]);
155
175
 
156
176
  const renderHeader = useCallback(() => {
157
177
  if (!headerLabel && !tooltip) return null;
158
178
  return (
159
179
  <>
160
- <CapRow
161
- className={classnames(disabled ? 'disabled' : '', 'cap-unified-select-header')}
162
- align="middle"
163
- gap={8}
164
- >
180
+ <HeaderWrapper className={classnames(disabled ? 'disabled' : '', 'cap-unified-select-header')}>
165
181
  {headerLabel && <CapLabel type="label16" className={classnames(disabled ? 'disabled' : '', 'cap-unified-select-header-label')}>{headerLabel}</CapLabel>}
166
182
  {tooltip && (
167
- <CapTooltip title={tooltip} className={classnames(disabled ? 'disabled' : '', 'cap-unified-select-header-tooltip')}>
168
- <CapIcon type="info-circle" size="s" />
169
- </CapTooltip>
183
+ <CapTooltipWithInfo
184
+ title={tooltip}
185
+ className={classnames(disabled ? 'disabled' : '', 'cap-unified-select-header-tooltip')}
186
+ iconProps={{ disabled }}
187
+ />
170
188
  )}
171
- </CapRow>
189
+ </HeaderWrapper>
172
190
  <div className="cap-unified-select-header-byline-text">
173
191
  {bylineText && <CapLabel className={classnames(disabled ? 'disabled' : '', 'cap-unified-select-header-byline-text')}>{bylineText}</CapLabel>}
174
192
  </div>
@@ -197,48 +215,54 @@ const CapUnifiedSelect = ({
197
215
  variant="borderless"
198
216
  value={searchText}
199
217
  onChange={e => setSearchText(e.target.value)}
200
- onKeyDown={e => e.stopPropagation()}
201
218
  />
202
219
  </CapRow>
203
220
  )}
204
221
  {isMulti && showUpload && (
205
- <CapRow className={classnames("cap-unified-select-upload-container")} align="middle">
206
- <Button
207
- type="link"
208
- icon={<CapIcon type="upload" size="s" />}
209
- onClick={() => {}}
210
- className={classnames("cap-unified-select-upload-button")}
211
- >
212
- Upload
213
- </Button>
222
+ <CapRow className={classnames("cap-unified-select-upload-container")} align="middle" onClick={onUpload}>
223
+ <CapIcon type="upload" size="s" style={{ color: styledVars.CAP_SECONDARY.base }}/>
224
+ <CapLabel type="label14" className={classnames("cap-unified-select-upload-label")}>Upload</CapLabel>
214
225
  </CapRow>
215
226
  )}
216
227
  {isMulti && currentItems.length > 0 && (
217
228
  <CapRow
218
229
  className={classnames("cap-unified-select-select-all-container")}
219
- onClick={e => { e.stopPropagation(); handleSelectAll(); }}
230
+ onClick={handleSelectAll}
220
231
  align="middle"
221
- gap={8}
232
+ gap={7}
222
233
  >
223
- <input type="checkbox" checked={allSelected} className={classnames("cap-unified-select-select-all-checkbox")} onClick={e => e.stopPropagation()} />
224
- <CapLabel className={classnames("cap-unified-select-select-all-label")}>Select all</CapLabel>
234
+ <input readOnly type="checkbox" checked={allSelected} className={classnames("cap-unified-select-select-all-checkbox")} onClick={handleSelectAll} />
235
+ <CapLabel type="label14" className={classnames("cap-unified-select-select-all-label")}>Select all</CapLabel>
225
236
  </CapRow>
226
237
  )}
227
238
 
228
239
  {currentItems.length === 0 ? <NoResult noResultText={noResultText} className={classnames(className, "cap-unified-select-no-result")}/> : menu}
229
240
 
230
241
  {currentItems.length > 0 && isMulti && (
231
- <CapRow
232
- className={classnames("cap-unified-select-confirm-container")}
233
- justify="space-between"
234
- align="middle"
235
- >
236
- <CapRow gap={8}>
237
- <Button type="primary" size="small" className={classnames("cap-unified-select-confirm-button")} onClick={e => { e.stopPropagation(); handleConfirm(); }}>Confirm</Button>
238
- <Button type="text" size="small" onClick={e => { e.stopPropagation(); handleCancel(); }}>Cancel</Button>
239
- </CapRow>
240
- {selectedCount > 0 && <CapLabel className={classnames("cap-unified-select-selected-count")}>{selectedCount} selected</CapLabel>}
241
- </CapRow>
242
+ <div className="cap-unified-select-confirm-container">
243
+ <div className="cap-unified-select-confirm-button-group">
244
+ <Button
245
+ type="primary"
246
+ size="small"
247
+ className="cap-unified-select-confirm-button"
248
+ onClick={handleConfirm}
249
+ >
250
+ Confirm
251
+ </Button>
252
+ <Button
253
+ type="text"
254
+ className="cap-unified-select-cancel-button"
255
+ size="small"
256
+ onClick={handleCancel}
257
+ >
258
+ Cancel
259
+ </Button>
260
+ <CapLabel className="cap-unified-select-selected-count">
261
+ {selectedCount} selected
262
+ </CapLabel>
263
+ </div>
264
+ </div>
265
+
242
266
  )}
243
267
  </div>
244
268
  );
@@ -256,7 +280,7 @@ const CapUnifiedSelect = ({
256
280
  showSearch={false}
257
281
  maxTagCount={0}
258
282
  maxTagPlaceholder={() => null}
259
- prefix={isMulti && value.length > 0 && prefix}
283
+ prefix={tempValue?.length > 0 ? prefix : undefined}
260
284
  suffixIcon={suffix}
261
285
  className={classnames(`cap-unified-tree-select ${className || ''}`)}
262
286
  style={style}
@@ -264,6 +288,9 @@ const CapUnifiedSelect = ({
264
288
  allowClear={allowClear}
265
289
  multiple={isMulti}
266
290
  treeCheckable={isMulti}
291
+ open={dropdownOpen}
292
+ treeDefaultExpandAll={true}
293
+ onOpenChange={handleDropdownVisibilityChange}
267
294
  showCheckedStrategy={TreeSelect.SHOW_PARENT}
268
295
  virtual
269
296
  disabled={disabled}
@@ -305,6 +332,7 @@ CapUnifiedSelect.propTypes = {
305
332
  errorMessage: PropTypes.string,
306
333
  popupClassName: PropTypes.string,
307
334
  showUpload: PropTypes.bool,
335
+ onUpload: PropTypes.func,
308
336
  };
309
337
 
310
338
  CapUnifiedSelect.defaultProps = {
@@ -320,7 +348,8 @@ CapUnifiedSelect.defaultProps = {
320
348
  disabled: false,
321
349
  showUpload: false,
322
350
  isError: false,
323
- noResultText: 'No results found'
351
+ noResultText: 'No results found',
352
+ onUpload: () => {}
324
353
  };
325
354
 
326
355
  export default withStyles(CapUnifiedSelect, selectStyles);
@@ -95,6 +95,10 @@ export const StyledInfoIcon = styled.span`
95
95
 
96
96
  export const selectStyles = css`
97
97
  &.cap-unified-select-container {
98
+ text-align: justify;
99
+ .ant-btn-variant-solid:not(:disabled):not(.ant-btn-disabled):hover{
100
+ background-color: #42b040 !important;
101
+ }
98
102
  .ant-tree-select-dropdown{
99
103
  padding: 0px !important;
100
104
  }
@@ -108,9 +112,15 @@ export const selectStyles = css`
108
112
  align-items: center !important;
109
113
  border-bottom: 1px solid #f0f0f0 !important;
110
114
  height: 40px !important;
115
+ padding-left: 15px !important;
116
+
117
+ .cap-unified-select-upload-label{
118
+ margin-left: 12px !important;
119
+ color: #2466EA !important;
120
+ }
111
121
  }
112
122
  .cap-unified-select-select-all-container{
113
- padding: 8px 12px !important;
123
+ padding: 9px 9px !important;
114
124
  cursor: pointer !important;
115
125
  display: flex !important;
116
126
  align-items: center !important;
@@ -135,11 +145,6 @@ export const selectStyles = css`
135
145
  line-height: 20px !important;
136
146
  letter-spacing: 0px !important;
137
147
  }
138
- .cap-unified-select-header-tooltip{
139
- width: 16px !important;
140
- height: 16px !important;
141
- color: ${styledVars.CAP_G06} !important;
142
- }
143
148
  .cap-unified-select-header-byline-text{
144
149
  font-family: ${styledVars.FONT_FAMILY} !important;
145
150
  font-weight: 400 !important;
@@ -148,25 +153,65 @@ export const selectStyles = css`
148
153
  letter-spacing: 0px !important;
149
154
  color: #97A0AF !important;
150
155
  }
156
+ .ant-input-affix-wrapper .ant-input-prefix{
157
+ left: 13px !important;
158
+ }
159
+ .ant-select-tree {
160
+ .ant-select-tree-node-content-wrapper{
161
+ background-color: transparent !important;
162
+ }
163
+ .ant-select-tree-node-content-wrapper:hover {
164
+ background-color: transparent !important;
165
+ }
166
+ }
167
+ .ant-select-tree .ant-select-tree-switcher:not(.ant-select-tree-switcher-noop):hover:before{
168
+ background-color: transparent !important;
169
+ }
170
+ .ant-select-selection-item{
171
+ background: transparent !important;
172
+ }
151
173
  .cap-unified-tree-select .ant-select-selector:hover{
152
174
  border: 1px solid #7A869A !important;
153
175
  }
176
+ .cap-unified-tree-select .ant-select-selector:focus{
177
+ border: 1px solid #7A869A !important;
178
+ }
179
+ .cap-unified-tree-select .cap-unified-select-select-all-checkbox{
180
+ height: 18px !important;
181
+ width: 18px !important;
182
+ border-color: #B3BAC5 !important;
183
+ border-radius: 2px !important;
184
+ }
154
185
  .cap-unified-tree-select .select-popup-container .ant-select-tree-switcher-noop,
155
186
  .cap-unified-tree-select .multiSelect-popup-container .ant-select-tree-switcher-noop {
156
187
  display: none !important;
157
188
  }
158
- .ant-tree-select-dropdown .treeSelect-popup-container .ant-select-tree .ant-select-tree-treenode{
159
- margin: 0px !important;
189
+ .cap-unified-tree-select .multiSelect-popup-container .ant-select-tree-treenode{
190
+ padding-left: 15px !important;
160
191
  }
161
192
  .ant-tree-select-dropdown .ant-select-tree .ant-select-tree-treenode{
162
193
  line-height: 40px !important;
163
194
  margin-bottom: 0px !important;
195
+ .ant-select-tree-checkbox .ant-select-tree-checkbox-inner{
196
+ height: 18px !important;
197
+ width: 18px !important;
198
+ border: 2px solid #B3BAC5 !important;
199
+ }
200
+ &:hover{
201
+ background-color: #FFFBE6 !important;
202
+ border-radius: 4px !important;
203
+ }
204
+ &:not(.ant-select-tree-treenode-disabled) .ant-select-tree-node-content-wrapper:hover{
205
+ background-color: none !important;
206
+ }
164
207
  }
165
- .cap-unified-tree-select .multiSelect-popup-container .ant-tree-select-dropdown .ant-select-tree .ant-select-tree-treenode{
166
- margin-left: 10px !important;
208
+ .ant-tree-select-dropdown .ant-select-tree .ant-select-tree-node-content-wrapper{
209
+ border-radius: 0px !important;
210
+ padding-left: 12px !important;
167
211
  }
168
- .multiSelect-popup-container .ant-select-tree-treenode{
169
- margin-left: 10px !important;
212
+ .ant-select-tree-treenode.ant-select-tree-treenode-selected{
213
+ background-color: #E9F0FE !important;
214
+ color: #2466EA !important;
170
215
  }
171
216
  .cap-unified-select-no-result{
172
217
  display: flex;
@@ -192,36 +237,78 @@ export const selectStyles = css`
192
237
  .ant-tree-select-open .ant-select-selector {
193
238
  border-color: #7A869A !important;
194
239
  box-shadow: none !important;
195
- outline: none !important; /* remove blue outline */
240
+ outline: none !important;
196
241
  }
197
242
  .cap-unified-select-search-container{
198
243
  border-bottom: 1px solid #EBECF0 !important;
199
244
  line-height: 40px !important;
245
+ .ant-input-affix-wrapper{
246
+ padding-left: 8px !important;
247
+ }
200
248
  }
201
249
  .cap-unified-select-upload-button{
202
- color: ${styledVars.CAP_BLUE01} !important;
203
- display: flex !important;
204
- align-items: center !important;
205
- font-size: 14px !important;
206
- font-weight: 400 !important;
207
- line-height: 20px !important;
250
+ border: none !important;
251
+ padding-left: 15px !important;
208
252
  }
209
- .cap-unified-select-confirm-container{
210
- display: flex !important;
211
- justify-content: space-between !important;
212
- align-items: center !important;
213
- padding: 8px 12px !important;
214
- border-top: 1px solid #f0f0f0 !important;
253
+ .cap-unified-select-confirm-container {
254
+ display: flex;
255
+ align-items: center;
256
+ height: 48px;
257
+ padding: 7px;
258
+ border-top: 1px solid #EBECF0;
215
259
  }
216
- .cap-unified-select-confirm-button{
217
- margin-right: 8px !important;
260
+ .cap-unified-select-confirm-button-group {
261
+ display: flex;
262
+ padding-left: 8px;
263
+ align-items: center;
264
+ width: 100%; /* so it can push the label */
265
+ button{
266
+ height: 32px;
267
+ width: 94px;
268
+ }
269
+ .cap-unified-select-confirm-button{
270
+ background-color: #6ebd6e !important;
271
+ }
272
+ .cap-unified-select-cancel-button{
273
+ border: transparent !important;
274
+ box-shadow: none !important;
275
+ }
218
276
  }
219
- .cap-unified-select-selected-count{
220
- color: ${styledVars.CAP_G05} !important;
221
- font-size: 14px !important;
277
+ .cap-unified-select-selected-count {
278
+ display: flex;
279
+ margin-left: auto !important; /* pushes to far right */
280
+ font-size: 12px !important;
281
+ font-weight: 400 !important;
282
+ line-height: 16px !important;
283
+ color: #5E6C84 !important;
222
284
  }
223
285
  .cap-unified-select-status{
224
286
  color: #E83135 !important;
225
287
  }
288
+ .cap-unified-select-search-container {
289
+ .ant-input-affix-wrapper {
290
+ border: none !important;
291
+ box-shadow: none !important;
292
+ border-radius: 0 !important;
293
+ }
294
+
295
+ .ant-input-affix-wrapper:hover {
296
+ border: none !important;
297
+ box-shadow: none !important;
298
+ border-bottom: 1px solid #EBECF0 !important;
299
+ }
300
+
301
+ .ant-input-affix-wrapper:focus-within {
302
+ border: none !important;
303
+ box-shadow: none !important;
304
+ border-bottom: 1px solid #091E42 !important;
305
+ outline: none !important;
306
+ }
307
+
308
+ .ant-input {
309
+ border: none !important;
310
+ box-shadow: none !important;
311
+ }
312
+ }
226
313
  }
227
314
  `;
package/index.js CHANGED
@@ -7,6 +7,7 @@ export { default as CapSkeleton } from './CapSkeleton';
7
7
  export { default as CapSpin } from './CapSpin';
8
8
  export { default as CapTable } from './CapTable';
9
9
  export { default as CapTooltip } from './CapTooltip';
10
+ export { default as CapTooltipWithInfo } from './CapTooltipWithInfo';
10
11
  export { default as CapUnifiedSelect } from './CapUnifiedSelect';
11
12
 
12
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.42",
4
+ "version": "0.1.6-alpha.44",
5
5
  "description": "Capillary UI component library with Ant Design v5",
6
6
  "main": "./index.js",
7
7
  "sideEffects": [