@platformatic/ui-components 0.2.16 → 0.2.19
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/assets/{index-C7qZkR7V.js → index-DBEXX1ja.js} +1 -1
- package/dist/index.html +1 -1
- package/package.json +1 -1
- package/src/components/LoginButton.jsx +1 -1
- package/src/components/TooltipV2.jsx +0 -1
- package/src/components/forms/Select.jsx +7 -58
- package/src/components/forms/Select.module.css +5 -2
- package/src/components/forms/SelectWithInput.jsx +327 -0
- package/src/components/forms/SelectWithInput.module.css +40 -0
- package/src/components/forms/index.js +2 -0
- package/src/components/icons/ServiceIcon.jsx +13 -14
- package/src/stories/forms/Select.stories.jsx +3 -16
- package/src/stories/forms/SelectWithInput.stories.jsx +176 -0
package/dist/index.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>Platformatic UI Components</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-DBEXX1ja.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="/assets/index-C-rgNKxt.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
package/package.json
CHANGED
|
@@ -3,6 +3,6 @@ import Button from './Button'
|
|
|
3
3
|
|
|
4
4
|
export default function LoginButton ({ iconName, label, onClick, ...props }) {
|
|
5
5
|
return (
|
|
6
|
-
<Button backgroundColor='main-green' alt={label} label={label} platformaticIcon={{ iconName, size: 'medium', color: 'main-dark-blue' }} data-testid='login-button' size='extra-large' onClick={onClick} {...props}
|
|
6
|
+
<Button backgroundColor='main-green' alt={label} label={label} platformaticIcon={{ iconName, size: 'medium', color: 'main-dark-blue' }} data-testid='login-button' size='extra-large' onClick={onClick} {...props} />
|
|
7
7
|
)
|
|
8
8
|
}
|
|
@@ -13,7 +13,6 @@ function TooltipV2 ({ tooltipClassName, text, visible, alignment, elementClassNa
|
|
|
13
13
|
if (visible) {
|
|
14
14
|
setClassName(visibleClassName())
|
|
15
15
|
if (ref.current) {
|
|
16
|
-
console.log('elementClassName', elementClassName)
|
|
17
16
|
const referenceBoundingClientRect = document.getElementsByClassName(elementClassName)[0]?.getBoundingClientRect()
|
|
18
17
|
if (referenceBoundingClientRect) {
|
|
19
18
|
const topPosition = referenceBoundingClientRect.y - (referenceBoundingClientRect.height)
|
|
@@ -17,12 +17,9 @@ function Select ({
|
|
|
17
17
|
borderColor,
|
|
18
18
|
borderListColor,
|
|
19
19
|
errorMessage,
|
|
20
|
-
onChange,
|
|
21
20
|
onSelect,
|
|
22
|
-
onClear,
|
|
23
21
|
disabled,
|
|
24
22
|
mainColor,
|
|
25
|
-
optionSelected,
|
|
26
23
|
dataAttrName,
|
|
27
24
|
dataAttrValue,
|
|
28
25
|
backgroundColor,
|
|
@@ -30,6 +27,7 @@ function Select ({
|
|
|
30
27
|
}) {
|
|
31
28
|
const inputRef = useRef()
|
|
32
29
|
const [showOptions, setShowOptions] = useState(false)
|
|
30
|
+
// eslint-disable-next-line no-unused-vars
|
|
33
31
|
const [isSelected, setIsSelected] = useState(false)
|
|
34
32
|
const [isOnFocus, setIsOnFocus] = useState(false)
|
|
35
33
|
|
|
@@ -41,6 +39,7 @@ function Select ({
|
|
|
41
39
|
let optionsClassName = `${styles.options} ${defaultOptionsClassName} `
|
|
42
40
|
inputClassName += ' ' + commonStyles[`background-color-${backgroundColor}`]
|
|
43
41
|
optionsClassName += commonStyles[`background-color-${backgroundColor}`]
|
|
42
|
+
const optionSelectedClassName = styles.optionSelected
|
|
44
43
|
|
|
45
44
|
if (borderListColor) {
|
|
46
45
|
optionsClassName += ' ' + styles['bordered-options']
|
|
@@ -94,20 +93,11 @@ function Select ({
|
|
|
94
93
|
}
|
|
95
94
|
|
|
96
95
|
useEffect(() => {
|
|
97
|
-
if (value.length > 0 && !showOptions && !isSelected) {
|
|
98
|
-
setShowOptions(true)
|
|
99
|
-
}
|
|
100
96
|
if (value.length === 0) {
|
|
101
97
|
setIsSelected(false)
|
|
102
98
|
}
|
|
103
99
|
}, [value])
|
|
104
100
|
|
|
105
|
-
useEffect(() => {
|
|
106
|
-
if (optionSelected) {
|
|
107
|
-
setSelected(optionSelected)
|
|
108
|
-
}
|
|
109
|
-
}, [optionSelected])
|
|
110
|
-
|
|
111
101
|
useEffect(() => {
|
|
112
102
|
if (disabled) {
|
|
113
103
|
const className = normalClassName() + ' ' + commonStyles['apply-opacity-30']
|
|
@@ -117,10 +107,10 @@ function Select ({
|
|
|
117
107
|
}
|
|
118
108
|
}, [disabled])
|
|
119
109
|
|
|
120
|
-
function renderLi (option, index) {
|
|
110
|
+
function renderLi (option, index, isOptionSelected) {
|
|
121
111
|
return (
|
|
122
112
|
<li
|
|
123
|
-
key={index} className={singleOptionClassName} onClick={() => {
|
|
113
|
+
key={index} className={`${isOptionSelected ? optionSelectedClassName : singleOptionClassName}`} onClick={() => {
|
|
124
114
|
if (option.notSelectable) {
|
|
125
115
|
return handleNotSelectable(option.onClick && option.onClick())
|
|
126
116
|
}
|
|
@@ -137,34 +127,15 @@ function Select ({
|
|
|
137
127
|
}
|
|
138
128
|
|
|
139
129
|
function renderOptions () {
|
|
140
|
-
if (value.length === 0) {
|
|
141
|
-
return (
|
|
142
|
-
<ul className={optionsClassName}>
|
|
143
|
-
{options.length > 0 ? options.map((option, index) => renderLi(option, index)) : <li className={singleOptionClassName}><div className={styles.liContent}><span className={commonStyles[`text--${mainColor}`]}>No data found</span></div></li>}
|
|
144
|
-
</ul>
|
|
145
|
-
)
|
|
146
|
-
}
|
|
147
130
|
const notFilterableOptions = options.filter(option => option.notFilterable)
|
|
148
|
-
const filteredOptions = options.filter(option => !option.notFilterable).filter(option => option.label.toLowerCase().includes(value.toLowerCase()))
|
|
149
|
-
|
|
150
131
|
return (
|
|
151
132
|
<ul className={optionsClassName}>
|
|
152
|
-
{filteredOptions.length > 0 ? filteredOptions.map((option, index) => renderLi(option, index)) : <li className={singleOptionClassName}><div className={styles.liContent}><span className={commonStyles[`text--${mainColor}`]}>No data found</span></div></li>}
|
|
153
133
|
{notFilterableOptions.length > 0 && notFilterableOptions.map((option, index) => renderLi(option, index))}
|
|
134
|
+
{options.length > 0 ? options.map((option, index) => renderLi(option, index, option.label === value)) : <li className={singleOptionClassName}><div className={styles.liContent}><span className={commonStyles[`text--${mainColor}`]}>No data found</span></div></li>}
|
|
154
135
|
</ul>
|
|
155
136
|
)
|
|
156
137
|
}
|
|
157
138
|
|
|
158
|
-
// https://stackoverflow.com/questions/23892547/what-is-the-best-way-to-trigger-change-or-input-event-in-react-js
|
|
159
|
-
function clearValue () {
|
|
160
|
-
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set
|
|
161
|
-
nativeInputValueSetter.call(inputRef.current, '')
|
|
162
|
-
const ev2 = new Event('input', { bubbles: true })
|
|
163
|
-
ev2.simulated = true
|
|
164
|
-
inputRef.current.dispatchEvent(ev2)
|
|
165
|
-
onClear()
|
|
166
|
-
}
|
|
167
|
-
|
|
168
139
|
function handleFocus () {
|
|
169
140
|
if (!isOnFocus) {
|
|
170
141
|
setIsOnFocus(true)
|
|
@@ -177,7 +148,7 @@ function Select ({
|
|
|
177
148
|
event.preventDefault()
|
|
178
149
|
setTimeout(() => {
|
|
179
150
|
if (showOptions) {
|
|
180
|
-
setShowOptions(false)
|
|
151
|
+
// setShowOptions(false)
|
|
181
152
|
setIsOnFocus(false)
|
|
182
153
|
setWrapperClassName(normalClassName())
|
|
183
154
|
}
|
|
@@ -187,9 +158,8 @@ function Select ({
|
|
|
187
158
|
return (
|
|
188
159
|
<div className={containerClassName} {...dataProps}>
|
|
189
160
|
<div className={styles.selectContainer}>
|
|
190
|
-
<input type='text' name={name} value={value} className={wrapperClassName} ref={inputRef}
|
|
161
|
+
<input type='text' name={name} value={value} className={wrapperClassName} ref={inputRef} disabled={disabled} placeholder={placeholder} onFocus={() => handleFocus()} onBlur={(e) => handleBlur(e)} readOnly />
|
|
191
162
|
<div className={styles.icons}>
|
|
192
|
-
{value?.length > 0 && !disabled && <PlatformaticIcon iconName='CircleCloseIcon' color={borderColor} onClick={() => clearValue()} size={SMALL} />}
|
|
193
163
|
<PlatformaticIcon iconName={showOptions ? 'ArrowUpIcon' : 'ArrowDownIcon'} color={borderColor} disabled={disabled} onClick={() => setShowOptions(!showOptions)} size={SMALL} />
|
|
194
164
|
</div>
|
|
195
165
|
</div>
|
|
@@ -252,18 +222,10 @@ Select.propTypes = {
|
|
|
252
222
|
* color of border UL
|
|
253
223
|
*/
|
|
254
224
|
borderListColor: PropTypes.oneOf([MAIN_GREEN, MAIN_DARK_BLUE, WHITE]),
|
|
255
|
-
/**
|
|
256
|
-
* onChange
|
|
257
|
-
*/
|
|
258
|
-
onChange: PropTypes.func,
|
|
259
225
|
/**
|
|
260
226
|
* onSelect
|
|
261
227
|
*/
|
|
262
228
|
onSelect: PropTypes.func,
|
|
263
|
-
/**
|
|
264
|
-
* onClear
|
|
265
|
-
*/
|
|
266
|
-
onClear: PropTypes.func,
|
|
267
229
|
/**
|
|
268
230
|
* Disabled
|
|
269
231
|
*/
|
|
@@ -272,16 +234,6 @@ Select.propTypes = {
|
|
|
272
234
|
* mainColor
|
|
273
235
|
*/
|
|
274
236
|
mainColor: PropTypes.oneOf([MAIN_DARK_BLUE, WHITE]),
|
|
275
|
-
/**
|
|
276
|
-
* optionSelected
|
|
277
|
-
*/
|
|
278
|
-
optionSelected: PropTypes.shape({
|
|
279
|
-
label: PropTypes.string,
|
|
280
|
-
value: PropTypes.oneOfType([
|
|
281
|
-
PropTypes.string,
|
|
282
|
-
PropTypes.number
|
|
283
|
-
])
|
|
284
|
-
}),
|
|
285
237
|
/**
|
|
286
238
|
* dataAttrName
|
|
287
239
|
*/
|
|
@@ -312,12 +264,9 @@ Select.defaultProps = {
|
|
|
312
264
|
borderColor: MAIN_GREEN,
|
|
313
265
|
borderListColor: '',
|
|
314
266
|
errorMessage: '',
|
|
315
|
-
onChange: () => {},
|
|
316
267
|
onSelect: () => {},
|
|
317
|
-
onClear: () => {},
|
|
318
268
|
disabled: false,
|
|
319
269
|
mainColor: MAIN_DARK_BLUE,
|
|
320
|
-
optionSelected: null,
|
|
321
270
|
dataAttrName: '',
|
|
322
271
|
dataAttrValue: '',
|
|
323
272
|
backgroundColor: WHITE,
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
@apply outline-none;
|
|
18
18
|
}
|
|
19
19
|
.options {
|
|
20
|
-
@apply absolute left-0 top-[42px] w-
|
|
20
|
+
@apply absolute left-0 top-[42px] w-[calc(100%-1rem)] max-h-[216px] overflow-y-auto z-20 p-2;
|
|
21
21
|
}
|
|
22
22
|
.bordered-options {
|
|
23
23
|
@apply border border-solid rounded
|
|
@@ -25,6 +25,9 @@
|
|
|
25
25
|
.option {
|
|
26
26
|
@apply font-light cursor-pointer z-10 flex flex-row justify-between items-center px-4;
|
|
27
27
|
}
|
|
28
|
+
.optionSelected {
|
|
29
|
+
@apply font-light cursor-pointer z-10 flex flex-row justify-between items-center px-4 bg-white/15;
|
|
30
|
+
}
|
|
28
31
|
.bordered-bottom {
|
|
29
32
|
@apply border-b
|
|
30
33
|
}
|
|
@@ -33,7 +36,7 @@
|
|
|
33
36
|
transform: translateY(-50%);
|
|
34
37
|
}
|
|
35
38
|
.liContent {
|
|
36
|
-
@apply py-2 flex items-center gap-x-1 relative z-[-1] w-
|
|
39
|
+
@apply py-2 flex items-center gap-x-1 relative z-[-1] w-full;
|
|
37
40
|
}
|
|
38
41
|
.descriptionValue {
|
|
39
42
|
@apply opacity-70
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
import React, { useState, useEffect, useRef } from 'react'
|
|
3
|
+
import PropTypes from 'prop-types'
|
|
4
|
+
import styles from './SelectWithInput.module.css'
|
|
5
|
+
import commonStyles from '../Common.module.css'
|
|
6
|
+
import { MAIN_DARK_BLUE, MAIN_GREEN, RICH_BLACK, SMALL, WHITE } from '../constants'
|
|
7
|
+
import PlatformaticIcon from '../PlatformaticIcon'
|
|
8
|
+
|
|
9
|
+
function SelectWithInput ({
|
|
10
|
+
defaultContainerClassName,
|
|
11
|
+
placeholder,
|
|
12
|
+
name,
|
|
13
|
+
value,
|
|
14
|
+
options,
|
|
15
|
+
defaultOptionsClassName,
|
|
16
|
+
optionsBorderedBottom,
|
|
17
|
+
borderColor,
|
|
18
|
+
borderListColor,
|
|
19
|
+
errorMessage,
|
|
20
|
+
onChange,
|
|
21
|
+
onSelect,
|
|
22
|
+
onClear,
|
|
23
|
+
disabled,
|
|
24
|
+
mainColor,
|
|
25
|
+
optionSelected,
|
|
26
|
+
dataAttrName,
|
|
27
|
+
dataAttrValue,
|
|
28
|
+
backgroundColor,
|
|
29
|
+
inputTextClassName
|
|
30
|
+
}) {
|
|
31
|
+
const inputRef = useRef()
|
|
32
|
+
const [showOptions, setShowOptions] = useState(false)
|
|
33
|
+
const [isSelected, setIsSelected] = useState(false)
|
|
34
|
+
const [isOnFocus, setIsOnFocus] = useState(false)
|
|
35
|
+
|
|
36
|
+
const showError = errorMessage.length > 0
|
|
37
|
+
const containerClassName = `${styles.container} ${defaultContainerClassName} `
|
|
38
|
+
let inputClassName = `${commonStyles.fullWidth} ${styles.select} ${inputTextClassName}`
|
|
39
|
+
inputClassName += ' ' + styles[`select-${mainColor}`]
|
|
40
|
+
inputClassName += ' ' + commonStyles[`text--${borderColor}`]
|
|
41
|
+
let optionsClassName = `${styles.options} ${defaultOptionsClassName} `
|
|
42
|
+
inputClassName += ' ' + commonStyles[`background-color-${backgroundColor}`]
|
|
43
|
+
optionsClassName += commonStyles[`background-color-${backgroundColor}`]
|
|
44
|
+
|
|
45
|
+
if (borderListColor) {
|
|
46
|
+
optionsClassName += ' ' + styles['bordered-options']
|
|
47
|
+
optionsClassName += ' ' + commonStyles[`bordered--${borderListColor}-30`]
|
|
48
|
+
}
|
|
49
|
+
let singleOptionClassName = `${styles.option} ` + commonStyles[`bordered--${mainColor}-70`] + ' ' + commonStyles[`hover-background-color-opaque-${mainColor}`]
|
|
50
|
+
if (optionsBorderedBottom) {
|
|
51
|
+
singleOptionClassName += ` ${styles['bordered-bottom']}`
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const optionSpanClassName = commonStyles[`text--${mainColor}`]
|
|
55
|
+
|
|
56
|
+
const [wrapperClassName, setWrapperClassName] = useState(normalClassName())
|
|
57
|
+
|
|
58
|
+
function onFocusClassName () {
|
|
59
|
+
return inputClassName + ' ' + commonStyles[`bordered--${borderColor}-100`]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function normalClassName () {
|
|
63
|
+
const baseClassName = inputClassName
|
|
64
|
+
if (showError) {
|
|
65
|
+
inputClassName += ' ' + commonStyles['bordered--error-red']
|
|
66
|
+
} else {
|
|
67
|
+
inputClassName += ' ' + commonStyles[`bordered--${borderColor}-70`]
|
|
68
|
+
}
|
|
69
|
+
if (disabled) inputClassName += ' ' + commonStyles['apply-opacity-30']
|
|
70
|
+
return baseClassName
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const dataProps = {}
|
|
74
|
+
if (dataAttrName && dataAttrValue) {
|
|
75
|
+
dataProps[`data-${dataAttrName}`] = dataAttrValue
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function handleNotSelectable (callback = () => {}) {
|
|
79
|
+
setIsSelected(true)
|
|
80
|
+
setShowOptions(false)
|
|
81
|
+
callback()
|
|
82
|
+
}
|
|
83
|
+
function setSelected ({ label, value }) {
|
|
84
|
+
setIsSelected(true)
|
|
85
|
+
setShowOptions(false)
|
|
86
|
+
/* eslint-disable-next-line no-undef */
|
|
87
|
+
onSelect(new CustomEvent('valueSelected', {
|
|
88
|
+
detail: {
|
|
89
|
+
name,
|
|
90
|
+
label,
|
|
91
|
+
value
|
|
92
|
+
}
|
|
93
|
+
}))
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
if (value.length > 0 && !showOptions && !isSelected) {
|
|
98
|
+
setShowOptions(true)
|
|
99
|
+
}
|
|
100
|
+
if (value.length === 0) {
|
|
101
|
+
setIsSelected(false)
|
|
102
|
+
}
|
|
103
|
+
}, [value])
|
|
104
|
+
|
|
105
|
+
useEffect(() => {
|
|
106
|
+
if (optionSelected) {
|
|
107
|
+
setSelected(optionSelected)
|
|
108
|
+
}
|
|
109
|
+
}, [optionSelected])
|
|
110
|
+
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
if (disabled) {
|
|
113
|
+
const className = normalClassName() + ' ' + commonStyles['apply-opacity-30']
|
|
114
|
+
setWrapperClassName(className)
|
|
115
|
+
} else {
|
|
116
|
+
setWrapperClassName(normalClassName())
|
|
117
|
+
}
|
|
118
|
+
}, [disabled])
|
|
119
|
+
|
|
120
|
+
function renderLi (option, index) {
|
|
121
|
+
return (
|
|
122
|
+
<li
|
|
123
|
+
key={index} className={singleOptionClassName} onClick={() => {
|
|
124
|
+
if (option.notSelectable) {
|
|
125
|
+
return handleNotSelectable(option.onClick && option.onClick())
|
|
126
|
+
}
|
|
127
|
+
return setSelected(option)
|
|
128
|
+
}}
|
|
129
|
+
>
|
|
130
|
+
<div className={styles.liContent}>
|
|
131
|
+
{option.iconName && <PlatformaticIcon iconName={option.iconName} color={option.iconColor || mainColor} size={option.iconSize ?? SMALL} onClick={null} />}
|
|
132
|
+
<span className={optionSpanClassName}>{option.label}</span>
|
|
133
|
+
</div>
|
|
134
|
+
{option.descriptionValue && <span className={`${optionSpanClassName} ${styles.descriptionValue}`}>{option.descriptionValue}</span>}
|
|
135
|
+
</li>
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function renderOptions () {
|
|
140
|
+
if (value.length === 0) {
|
|
141
|
+
return (
|
|
142
|
+
<ul className={optionsClassName}>
|
|
143
|
+
{options.length > 0 ? options.map((option, index) => renderLi(option, index)) : <li className={singleOptionClassName}><div className={styles.liContent}><span className={commonStyles[`text--${mainColor}`]}>No data found</span></div></li>}
|
|
144
|
+
</ul>
|
|
145
|
+
)
|
|
146
|
+
}
|
|
147
|
+
const notFilterableOptions = options.filter(option => option.notFilterable)
|
|
148
|
+
const filteredOptions = options.filter(option => !option.notFilterable).filter(option => option.label.toLowerCase().includes(value.toLowerCase()))
|
|
149
|
+
|
|
150
|
+
return (
|
|
151
|
+
<ul className={optionsClassName}>
|
|
152
|
+
{filteredOptions.length > 0 ? filteredOptions.map((option, index) => renderLi(option, index)) : <li className={singleOptionClassName}><div className={styles.liContent}><span className={commonStyles[`text--${mainColor}`]}>No data found</span></div></li>}
|
|
153
|
+
{notFilterableOptions.length > 0 && notFilterableOptions.map((option, index) => renderLi(option, index))}
|
|
154
|
+
</ul>
|
|
155
|
+
)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// https://stackoverflow.com/questions/23892547/what-is-the-best-way-to-trigger-change-or-input-event-in-react-js
|
|
159
|
+
function clearValue () {
|
|
160
|
+
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set
|
|
161
|
+
nativeInputValueSetter.call(inputRef.current, '')
|
|
162
|
+
const ev2 = new Event('input', { bubbles: true })
|
|
163
|
+
ev2.simulated = true
|
|
164
|
+
inputRef.current.dispatchEvent(ev2)
|
|
165
|
+
onClear()
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function handleFocus () {
|
|
169
|
+
if (!isOnFocus) {
|
|
170
|
+
setIsOnFocus(true)
|
|
171
|
+
setWrapperClassName(onFocusClassName())
|
|
172
|
+
}
|
|
173
|
+
setShowOptions(true)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function handleBlur (event) {
|
|
177
|
+
event.preventDefault()
|
|
178
|
+
setTimeout(() => {
|
|
179
|
+
if (showOptions) {
|
|
180
|
+
setShowOptions(false)
|
|
181
|
+
setIsOnFocus(false)
|
|
182
|
+
setWrapperClassName(normalClassName())
|
|
183
|
+
}
|
|
184
|
+
}, 250)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return (
|
|
188
|
+
<div className={containerClassName} {...dataProps}>
|
|
189
|
+
<div className={styles.selectContainer}>
|
|
190
|
+
<input type='text' name={name} value={value} className={wrapperClassName} ref={inputRef} onChange={onChange} disabled={disabled} placeholder={placeholder} onFocus={() => handleFocus()} onBlur={(e) => handleBlur(e)} />
|
|
191
|
+
<div className={styles.icons}>
|
|
192
|
+
{value?.length > 0 && !disabled && <PlatformaticIcon iconName='CircleCloseIcon' color={borderColor} onClick={() => clearValue()} size={SMALL} />}
|
|
193
|
+
<PlatformaticIcon iconName={showOptions ? 'ArrowUpIcon' : 'ArrowDownIcon'} color={borderColor} disabled={disabled} onClick={() => setShowOptions(!showOptions)} size={SMALL} />
|
|
194
|
+
</div>
|
|
195
|
+
</div>
|
|
196
|
+
{showOptions && !showError && renderOptions()}
|
|
197
|
+
{showError && <span className={commonStyles['error-message']}>{errorMessage}</span>}
|
|
198
|
+
</div>
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
SelectWithInput.propTypes = {
|
|
203
|
+
/**
|
|
204
|
+
* defaultContainerClassName
|
|
205
|
+
*/
|
|
206
|
+
defaultContainerClassName: PropTypes.string,
|
|
207
|
+
/**
|
|
208
|
+
* placeholder
|
|
209
|
+
*/
|
|
210
|
+
placeholder: PropTypes.string,
|
|
211
|
+
/**
|
|
212
|
+
* name
|
|
213
|
+
*/
|
|
214
|
+
name: PropTypes.oneOfType([
|
|
215
|
+
PropTypes.string,
|
|
216
|
+
PropTypes.number
|
|
217
|
+
]),
|
|
218
|
+
/**
|
|
219
|
+
* value
|
|
220
|
+
*/
|
|
221
|
+
value: PropTypes.string,
|
|
222
|
+
/**
|
|
223
|
+
* options
|
|
224
|
+
*/
|
|
225
|
+
options: PropTypes.arrayOf(PropTypes.shape({
|
|
226
|
+
label: PropTypes.string,
|
|
227
|
+
value: PropTypes.oneOfType([
|
|
228
|
+
PropTypes.string,
|
|
229
|
+
PropTypes.number
|
|
230
|
+
]),
|
|
231
|
+
iconName: PropTypes.string,
|
|
232
|
+
iconSize: PropTypes.string,
|
|
233
|
+
iconColor: PropTypes.string,
|
|
234
|
+
notSelectable: PropTypes.bool,
|
|
235
|
+
notFilterable: PropTypes.bool,
|
|
236
|
+
onClick: PropTypes.func,
|
|
237
|
+
descriptionValue: PropTypes.string
|
|
238
|
+
})),
|
|
239
|
+
/**
|
|
240
|
+
* defaultOptionsClassName
|
|
241
|
+
*/
|
|
242
|
+
defaultOptionsClassName: PropTypes.string,
|
|
243
|
+
/**
|
|
244
|
+
* optionsBorderedBottom
|
|
245
|
+
*/
|
|
246
|
+
optionsBorderedBottom: PropTypes.bool,
|
|
247
|
+
/**
|
|
248
|
+
* color of border
|
|
249
|
+
*/
|
|
250
|
+
borderColor: PropTypes.oneOf([MAIN_GREEN, MAIN_DARK_BLUE, WHITE]),
|
|
251
|
+
/**
|
|
252
|
+
* color of border UL
|
|
253
|
+
*/
|
|
254
|
+
borderListColor: PropTypes.oneOf([MAIN_GREEN, MAIN_DARK_BLUE, WHITE]),
|
|
255
|
+
/**
|
|
256
|
+
* onChange
|
|
257
|
+
*/
|
|
258
|
+
onChange: PropTypes.func,
|
|
259
|
+
/**
|
|
260
|
+
* onSelect
|
|
261
|
+
*/
|
|
262
|
+
onSelect: PropTypes.func,
|
|
263
|
+
/**
|
|
264
|
+
* onClear
|
|
265
|
+
*/
|
|
266
|
+
onClear: PropTypes.func,
|
|
267
|
+
/**
|
|
268
|
+
* Disabled
|
|
269
|
+
*/
|
|
270
|
+
disabled: PropTypes.bool,
|
|
271
|
+
/**
|
|
272
|
+
* mainColor
|
|
273
|
+
*/
|
|
274
|
+
mainColor: PropTypes.oneOf([MAIN_DARK_BLUE, WHITE]),
|
|
275
|
+
/**
|
|
276
|
+
* optionSelected
|
|
277
|
+
*/
|
|
278
|
+
optionSelected: PropTypes.shape({
|
|
279
|
+
label: PropTypes.string,
|
|
280
|
+
value: PropTypes.oneOfType([
|
|
281
|
+
PropTypes.string,
|
|
282
|
+
PropTypes.number
|
|
283
|
+
])
|
|
284
|
+
}),
|
|
285
|
+
/**
|
|
286
|
+
* dataAttrName
|
|
287
|
+
*/
|
|
288
|
+
dataAttrName: PropTypes.string,
|
|
289
|
+
/**
|
|
290
|
+
* dataAttrValue
|
|
291
|
+
*/
|
|
292
|
+
dataAttrValue: PropTypes.string,
|
|
293
|
+
/**
|
|
294
|
+
* backgroundColor
|
|
295
|
+
*/
|
|
296
|
+
backgroundColor: PropTypes.oneOf([MAIN_DARK_BLUE, WHITE, RICH_BLACK]),
|
|
297
|
+
/**
|
|
298
|
+
* inputTextClassName
|
|
299
|
+
*/
|
|
300
|
+
inputTextClassName: PropTypes.string
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
SelectWithInput.defaultProps = {
|
|
304
|
+
defaultContainerClassName: '',
|
|
305
|
+
placeholder: 'this is the default',
|
|
306
|
+
name: '',
|
|
307
|
+
value: '',
|
|
308
|
+
id: '',
|
|
309
|
+
options: [],
|
|
310
|
+
defaultOptionsClassName: '',
|
|
311
|
+
optionsBorderedBottom: true,
|
|
312
|
+
borderColor: MAIN_GREEN,
|
|
313
|
+
borderListColor: '',
|
|
314
|
+
errorMessage: '',
|
|
315
|
+
onChange: () => {},
|
|
316
|
+
onSelect: () => {},
|
|
317
|
+
onClear: () => {},
|
|
318
|
+
disabled: false,
|
|
319
|
+
mainColor: MAIN_DARK_BLUE,
|
|
320
|
+
optionSelected: null,
|
|
321
|
+
dataAttrName: '',
|
|
322
|
+
dataAttrValue: '',
|
|
323
|
+
backgroundColor: WHITE,
|
|
324
|
+
inputTextClassName: ''
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export default SelectWithInput
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
.container {
|
|
2
|
+
@apply flex flex-col w-full relative
|
|
3
|
+
}
|
|
4
|
+
.selectContainer {
|
|
5
|
+
@apply w-full flex items-center relative z-10;
|
|
6
|
+
}
|
|
7
|
+
.select {
|
|
8
|
+
@apply py-1.5 px-2 md:px-3 md:py-[10.5px] h-full border border-solid box-border rounded;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.select-main-dark-blue.active,
|
|
12
|
+
.select-main-dark-blue:focus {
|
|
13
|
+
@apply shadow-main-dark-blue outline-none;
|
|
14
|
+
}
|
|
15
|
+
.select-white.active,
|
|
16
|
+
.select-white:focus {
|
|
17
|
+
@apply outline-none;
|
|
18
|
+
}
|
|
19
|
+
.options {
|
|
20
|
+
@apply absolute left-0 top-[42px] w-full max-h-[216px] overflow-y-scroll z-20;
|
|
21
|
+
}
|
|
22
|
+
.bordered-options {
|
|
23
|
+
@apply border border-solid rounded
|
|
24
|
+
}
|
|
25
|
+
.option {
|
|
26
|
+
@apply font-light cursor-pointer z-10 flex flex-row justify-between items-center px-4;
|
|
27
|
+
}
|
|
28
|
+
.bordered-bottom {
|
|
29
|
+
@apply border-b
|
|
30
|
+
}
|
|
31
|
+
.icons {
|
|
32
|
+
@apply absolute top-[50%] right-[0.5rem] flex gap-x-2;
|
|
33
|
+
transform: translateY(-50%);
|
|
34
|
+
}
|
|
35
|
+
.liContent {
|
|
36
|
+
@apply py-2 flex items-center gap-x-1 relative z-[-1] w-auto basis-2/3;
|
|
37
|
+
}
|
|
38
|
+
.descriptionValue {
|
|
39
|
+
@apply opacity-70
|
|
40
|
+
}
|
|
@@ -5,6 +5,7 @@ import Password from './Password'
|
|
|
5
5
|
import Preview from './Preview'
|
|
6
6
|
import RadioGroup from './RadioGroup'
|
|
7
7
|
import Select from './Select'
|
|
8
|
+
import SelectWithInput from './SelectWithInput'
|
|
8
9
|
import TextArea from './TextArea'
|
|
9
10
|
import ToggleSwitch from './ToggleSwitch'
|
|
10
11
|
|
|
@@ -16,6 +17,7 @@ export default {
|
|
|
16
17
|
Preview,
|
|
17
18
|
RadioGroup,
|
|
18
19
|
Select,
|
|
20
|
+
SelectWithInput,
|
|
19
21
|
TextArea,
|
|
20
22
|
ToggleSwitch
|
|
21
23
|
}
|
|
@@ -24,12 +24,11 @@ const ServiceIcon = ({ color, size, disabled, inactive }) => {
|
|
|
24
24
|
xmlns='http://www.w3.org/2000/svg'
|
|
25
25
|
className={className}
|
|
26
26
|
>
|
|
27
|
-
<path d='M10.0006 7.37331C10.8371 7.37331 11.5152 6.72811 11.5152 5.93221C11.5152 5.13631 10.8371 4.49111 10.0006 4.49111C9.16416 4.49111 8.48608 5.13631 8.48608 5.93221C8.48608 6.72811 9.16416 7.37331 10.0006 7.37331Z' stroke='none' strokeLinecap='round' strokeLinejoin='round' />
|
|
28
27
|
<path d='M10.813 2.22453V2.71361C10.813 2.80669 10.874 2.89079 10.9658 2.92345L11.6214 3.15941C11.7106 3.19126 11.8119 3.16921 11.8771 3.10226L12.192 2.78056C12.2847 2.68585 12.4426 2.68503 12.5361 2.77975L13.2964 3.54561C13.3813 3.63134 13.3822 3.76443 13.2989 3.85098L12.8939 4.27392C12.8296 4.34087 12.8141 4.43803 12.8544 4.51968L13.129 5.08306C13.1676 5.16226 13.2517 5.2137 13.3436 5.2137H13.764C13.8945 5.2137 14 5.31412 14 5.43823V6.38372C14 6.50783 13.8945 6.60826 13.764 6.60826H13.3221C13.22 6.60826 13.129 6.67113 13.0973 6.76339L12.8742 7.41413C12.8476 7.49088 12.8665 7.57498 12.924 7.63458L13.2869 8.01588C13.3753 8.10896 13.3667 8.25348 13.2672 8.33594L12.4305 9.03241C12.3344 9.11242 12.1886 9.10508 12.1019 9.01608L11.8101 8.71724C11.7466 8.65193 11.648 8.62825 11.5596 8.65764L10.9503 8.86013C10.8551 8.89197 10.7916 8.97689 10.7916 9.07242V9.5174C10.7916 9.64151 10.686 9.74194 10.5556 9.74194H9.44353C9.3131 9.74194 9.20755 9.64151 9.20755 9.5174V9.07242C9.20755 8.97689 9.14405 8.89197 9.0488 8.86013L8.43956 8.65764C8.35117 8.62825 8.25249 8.65111 8.18899 8.71724L7.89724 9.01608C7.81058 9.10508 7.6647 9.11242 7.56859 9.03241L6.73195 8.33594C6.63241 8.25348 6.62383 8.10896 6.71222 8.01588L7.07519 7.63458C7.13182 7.57498 7.1507 7.49088 7.12496 7.41413L6.90186 6.76339C6.87011 6.67113 6.77915 6.60826 6.67704 6.60826H6.23598C6.10555 6.60826 6 6.50783 6 6.38372V5.43823C6 5.31412 6.10555 5.2137 6.23598 5.2137H6.65644C6.74826 5.2137 6.83235 5.16307 6.87096 5.08306L7.14555 4.51968C7.18588 4.43722 7.16958 4.34087 7.10608 4.27392L6.70106 3.85098C6.61783 3.76443 6.61868 3.63053 6.70364 3.54561L7.46391 2.77975C7.55744 2.68585 7.71533 2.68585 7.808 2.78056L8.12292 3.10226C8.18814 3.16921 8.28939 3.19126 8.37863 3.15941L9.03422 2.92345C9.12603 2.89079 9.18696 2.80669 9.18696 2.71361V2.22453C9.18696 2.10043 9.2925 2 9.42293 2H10.5771C10.7075 2 10.813 2.10043 10.813 2.22453Z' stroke='none' strokeLinecap='round' strokeLinejoin='round' />
|
|
29
|
-
<path d='
|
|
30
|
-
<
|
|
31
|
-
<
|
|
32
|
-
|
|
28
|
+
<path d='M11.5 7H8.5L10 4L11.5 7Z' stroke='none' strokeLinecap='round' strokeLinejoin='round' />
|
|
29
|
+
<path d='M4 5.09668H2V11.2902H11.6V11.1289' stroke='none' strokeLinecap='round' strokeLinejoin='round' />
|
|
30
|
+
<rect x='5.2002' y='11.2903' width='3.2' height='1.54839' stroke='none' />
|
|
31
|
+
<path d='M3.6001 12.8386H10.0001V13.9999H3.6001V12.8386Z' stroke='none' strokeLinejoin='round' />
|
|
33
32
|
</svg>
|
|
34
33
|
)
|
|
35
34
|
break
|
|
@@ -43,12 +42,11 @@ const ServiceIcon = ({ color, size, disabled, inactive }) => {
|
|
|
43
42
|
xmlns='http://www.w3.org/2000/svg'
|
|
44
43
|
className={className}
|
|
45
44
|
>
|
|
46
|
-
<path d='M15.0008 11.06C16.2555 11.06 17.2726 10.0922 17.2726 8.89832C17.2726 7.70448 16.2555 6.73667 15.0008 6.73667C13.7461 6.73667 12.729 7.70448 12.729 8.89832C12.729 10.0922 13.7461 11.06 15.0008 11.06Z' stroke='none' strokeWidth={1.5} strokeLinecap='round' strokeLinejoin='round' />
|
|
47
45
|
<path d='M16.2196 3.3368V4.07042C16.2196 4.21003 16.311 4.33618 16.4487 4.38517L17.4321 4.73912C17.5659 4.78688 17.7178 4.75382 17.8156 4.65339L18.288 4.17084C18.427 4.02877 18.6638 4.02755 18.8041 4.16962L19.9445 5.31842C20.072 5.44701 20.0733 5.64664 19.9484 5.77647L19.3409 6.41088C19.2443 6.51131 19.2212 6.65705 19.2817 6.77952L19.6936 7.62459C19.7515 7.74338 19.8776 7.82054 20.0153 7.82054H20.646C20.8417 7.82054 21 7.97118 21 8.15734V9.57558C21 9.76174 20.8417 9.91238 20.646 9.91238H19.9832C19.83 9.91238 19.6936 10.0067 19.6459 10.1451L19.3113 11.1212C19.2714 11.2363 19.2997 11.3625 19.3859 11.4519L19.9304 12.0238C20.063 12.1634 20.0501 12.3802 19.9008 12.5039L18.6458 13.5486C18.5017 13.6686 18.2828 13.6576 18.1528 13.5241L17.7152 13.0759C17.62 12.9779 17.472 12.9424 17.3394 12.9865L16.4255 13.2902C16.2826 13.338 16.1874 13.4653 16.1874 13.6086V14.2761C16.1874 14.4623 16.0291 14.6129 15.8334 14.6129H14.1653C13.9696 14.6129 13.8113 14.4623 13.8113 14.2761V13.6086C13.8113 13.4653 13.7161 13.338 13.5732 13.2902L12.6593 12.9865C12.5268 12.9424 12.3787 12.9767 12.2835 13.0759L11.8459 13.5241C11.7159 13.6576 11.4971 13.6686 11.3529 13.5486L10.0979 12.5039C9.94862 12.3802 9.93575 12.1634 10.0683 12.0238L10.6128 11.4519C10.6977 11.3625 10.7261 11.2363 10.6874 11.1212L10.3528 10.1451C10.3052 10.0067 10.1687 9.91238 10.0156 9.91238H9.35396C9.15832 9.91238 9 9.76174 9 9.57558V8.15734C9 7.97118 9.15832 7.82054 9.35396 7.82054H9.98466C10.1224 7.82054 10.2485 7.74461 10.3064 7.62459L10.7183 6.77952C10.7788 6.65582 10.7544 6.51131 10.6591 6.41088L10.0516 5.77647C9.92674 5.64664 9.92803 5.44579 10.0555 5.31842L11.1959 4.16962C11.3362 4.02877 11.573 4.02877 11.712 4.17084L12.1844 4.65339C12.2822 4.75382 12.4341 4.78688 12.568 4.73912L13.5513 4.38517C13.689 4.33618 13.7804 4.21003 13.7804 4.07042V3.3368C13.7804 3.15064 13.9388 3 14.1344 3H15.8656C16.0612 3 16.2196 3.15064 16.2196 3.3368Z' stroke='none' strokeWidth={1.5} strokeLinecap='round' strokeLinejoin='round' />
|
|
48
|
-
<path d='
|
|
49
|
-
<
|
|
50
|
-
<
|
|
51
|
-
|
|
46
|
+
<path d='M17.25 10.5H12.75L15 6L17.25 10.5Z' stroke='none' strokeWidth={1.5} strokeLinecap='round' strokeLinejoin='round' />
|
|
47
|
+
<path d='M6 7.64502H3V16.9353H17.4V16.6934' stroke='none' strokeWidth={1.5} strokeLinecap='round' strokeLinejoin='round' />
|
|
48
|
+
<rect x='7.7998' y='16.9353' width='4.8' height='2.32258' stroke='none' strokeWidth={1.5} />
|
|
49
|
+
<path d='M5.3999 19.2578H14.9999V20.9997H5.3999V19.2578Z' stroke='none' strokeWidth={1.5} strokeLinejoin='round' />
|
|
52
50
|
</svg>
|
|
53
51
|
)
|
|
54
52
|
break
|
|
@@ -62,11 +60,12 @@ const ServiceIcon = ({ color, size, disabled, inactive }) => {
|
|
|
62
60
|
xmlns='http://www.w3.org/2000/svg'
|
|
63
61
|
className={className}
|
|
64
62
|
>
|
|
65
|
-
<path d='M25.0014 18.4333C27.0926 18.4333 28.7878 16.8203 28.7878 14.8305C28.7878 12.8408 27.0926 11.2278 25.0014 11.2278C22.9103 11.2278 21.2151 12.8408 21.2151 14.8305C21.2151 16.8203 22.9103 18.4333 25.0014 18.4333Z' stroke='none' strokeWidth={2} strokeLinecap='round' strokeLinejoin='round' />
|
|
66
63
|
<path d='M27.0326 5.56134V6.78403C27.0326 7.01672 27.1849 7.22697 27.4145 7.30862L29.0534 7.89853C29.2765 7.97814 29.5297 7.92303 29.6927 7.75565L30.48 6.95141C30.7117 6.71462 31.1064 6.71258 31.3402 6.94936L33.2409 8.86403C33.4533 9.07836 33.4554 9.41107 33.2473 9.62744L32.2348 10.6848C32.0739 10.8522 32.0353 11.0951 32.1361 11.2992L32.8226 12.7076C32.9191 12.9056 33.1294 13.0342 33.3589 13.0342H34.4101C34.7361 13.0342 35 13.2853 35 13.5956V15.9593C35 16.2696 34.7361 16.5206 34.4101 16.5206H33.3053C33.05 16.5206 32.8226 16.6778 32.7432 16.9085L32.1855 18.5353C32.119 18.7272 32.1661 18.9374 32.3099 19.0865L33.2173 20.0397C33.4383 20.2724 33.4168 20.6337 33.168 20.8399L31.0764 22.581C30.8361 22.7811 30.4714 22.7627 30.2547 22.5402L29.5254 21.7931C29.3666 21.6298 29.1199 21.5706 28.899 21.6441L27.3758 22.1503C27.1377 22.2299 26.979 22.4422 26.979 22.681V23.7935C26.979 24.1038 26.7151 24.3548 26.389 24.3548H23.6088C23.2827 24.3548 23.0189 24.1038 23.0189 23.7935V22.681C23.0189 22.4422 22.8601 22.2299 22.622 22.1503L21.0989 21.6441C20.8779 21.5706 20.6312 21.6278 20.4725 21.7931L19.7431 22.5402C19.5264 22.7627 19.1618 22.7811 18.9215 22.581L16.8299 20.8399C16.581 20.6337 16.5596 20.2724 16.7805 20.0397L17.688 19.0865C17.8296 18.9374 17.8768 18.7272 17.8124 18.5353L17.2546 16.9085C17.1753 16.6778 16.9479 16.5206 16.6926 16.5206H15.5899C15.2639 16.5206 15 16.2696 15 15.9593V13.5956C15 13.2853 15.2639 13.0342 15.5899 13.0342H16.6411C16.8706 13.0342 17.0809 12.9077 17.1774 12.7076L17.8639 11.2992C17.9647 11.093 17.924 10.8522 17.7652 10.6848L16.7527 9.62744C16.5446 9.41107 16.5467 9.07631 16.7591 8.86403L18.6598 6.94936C18.8936 6.71462 19.2883 6.71462 19.52 6.95141L20.3073 7.75565C20.4703 7.92303 20.7235 7.97814 20.9466 7.89853L22.5855 7.30862C22.8151 7.22697 22.9674 7.01672 22.9674 6.78403V5.56134C22.9674 5.25107 23.2313 5 23.5573 5H26.4427C26.7687 5 27.0326 5.25107 27.0326 5.56134Z' stroke='none' strokeWidth={2} strokeLinecap='round' strokeLinejoin='round' />
|
|
67
|
-
<path d='
|
|
68
|
-
<
|
|
69
|
-
<
|
|
64
|
+
<path d='M28.75 17.5H21.25L25 10L28.75 17.5Z' stroke='none' strokeWidth={2} strokeLinecap='round' strokeLinejoin='round' />
|
|
65
|
+
<path d='M10 12.7417H5V28.2256H29V27.8223' stroke='none' strokeWidth={2} strokeLinecap='round' strokeLinejoin='round' />
|
|
66
|
+
<rect x='13' y='28.2256' width='8' height='3.87097' stroke='none' strokeWidth={2} />
|
|
67
|
+
<path d='M9 32.0964H25V34.9997H9V32.0964Z' stroke='none' strokeWidth={2} strokeLinejoin='round' />
|
|
68
|
+
|
|
70
69
|
</svg>
|
|
71
70
|
)
|
|
72
71
|
break
|