@platformatic/ui-components 0.1.110 → 0.1.112
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -3,10 +3,10 @@ import React, { useState, useEffect, useRef } from 'react'
|
|
|
3
3
|
import PropTypes from 'prop-types'
|
|
4
4
|
import styles from './Select.module.css'
|
|
5
5
|
import commonStyles from '../Common.module.css'
|
|
6
|
-
import { MAIN_DARK_BLUE, MAIN_GREEN } from '../constants'
|
|
6
|
+
import { MAIN_DARK_BLUE, MAIN_GREEN, SMALL } from '../constants'
|
|
7
7
|
import PlatformaticIcon from '../PlatformaticIcon'
|
|
8
8
|
|
|
9
|
-
function Select ({ placeholder, name, value, options, borderColor, errorMessage, onChange, onSelect, disabled }) {
|
|
9
|
+
function Select ({ placeholder, name, value, options, borderColor, errorMessage, onChange, onSelect, onClear, disabled, optionsIconColor }) {
|
|
10
10
|
const inputRef = useRef()
|
|
11
11
|
const [showOptions, setShowOptions] = useState(false)
|
|
12
12
|
const [isSelected, setIsSelected] = useState(false)
|
|
@@ -16,6 +16,11 @@ function Select ({ placeholder, name, value, options, borderColor, errorMessage,
|
|
|
16
16
|
if (showError) inputClassName += ' ' + commonStyles['bordered--error-red']
|
|
17
17
|
if (disabled) inputClassName += ' ' + commonStyles['apply-opacity-30']
|
|
18
18
|
|
|
19
|
+
function handleNotSelectable (callback = () => {}) {
|
|
20
|
+
setIsSelected(true)
|
|
21
|
+
setShowOptions(false)
|
|
22
|
+
callback()
|
|
23
|
+
}
|
|
19
24
|
function setSelected ({ label, value }) {
|
|
20
25
|
setIsSelected(true)
|
|
21
26
|
setShowOptions(false)
|
|
@@ -38,14 +43,34 @@ function Select ({ placeholder, name, value, options, borderColor, errorMessage,
|
|
|
38
43
|
}
|
|
39
44
|
}, [value])
|
|
40
45
|
|
|
46
|
+
function renderLi (option, index) {
|
|
47
|
+
return (
|
|
48
|
+
<li
|
|
49
|
+
key={index} className={styles.option} onClick={() => {
|
|
50
|
+
if (option.notSelectable) {
|
|
51
|
+
return handleNotSelectable(option.onClick && option.onClick())
|
|
52
|
+
}
|
|
53
|
+
return setSelected(option)
|
|
54
|
+
}}
|
|
55
|
+
>
|
|
56
|
+
{option.iconName && <PlatformaticIcon iconName={option.iconName} color={optionsIconColor} size={SMALL} onClick={null} />}
|
|
57
|
+
<span>{option.label}</span>
|
|
58
|
+
</li>
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
41
62
|
function renderOptions () {
|
|
42
63
|
if (value.length === 0) {
|
|
43
|
-
return
|
|
64
|
+
return (
|
|
65
|
+
<ul className={styles.options}>
|
|
66
|
+
{options.length > 0 ? options.map((option, index) => renderLi(option, index)) : <li className={styles.option}>No data found</li>}
|
|
67
|
+
</ul>
|
|
68
|
+
)
|
|
44
69
|
}
|
|
45
70
|
const filteredOptions = options.filter(option => option.label.toLowerCase().includes(value.toLowerCase()))
|
|
46
71
|
return (
|
|
47
72
|
<ul className={styles.options}>
|
|
48
|
-
{filteredOptions.length > 0 ? filteredOptions.map((option, index) =>
|
|
73
|
+
{filteredOptions.length > 0 ? filteredOptions.map((option, index) => renderLi(option, index)) : <li className={styles.option}>No data found</li>}
|
|
49
74
|
</ul>
|
|
50
75
|
)
|
|
51
76
|
}
|
|
@@ -57,6 +82,7 @@ function Select ({ placeholder, name, value, options, borderColor, errorMessage,
|
|
|
57
82
|
const ev2 = new Event('input', { bubbles: true })
|
|
58
83
|
ev2.simulated = true
|
|
59
84
|
inputRef.current.dispatchEvent(ev2)
|
|
85
|
+
onClear()
|
|
60
86
|
}
|
|
61
87
|
|
|
62
88
|
return (
|
|
@@ -65,7 +91,7 @@ function Select ({ placeholder, name, value, options, borderColor, errorMessage,
|
|
|
65
91
|
<input type='text' name={name} value={value} className={inputClassName} ref={inputRef} onChange={onChange} disabled={disabled} placeholder={placeholder} />
|
|
66
92
|
<div className={styles.icons}>
|
|
67
93
|
{value?.length > 0 && <PlatformaticIcon iconName='CloseIcon' color={borderColor} onClick={() => clearValue()} />}
|
|
68
|
-
<PlatformaticIcon iconName={showOptions ? 'ArrowUpIcon' : 'ArrowDownIcon'} color={borderColor} onClick={() => setShowOptions(!showOptions)} />
|
|
94
|
+
<PlatformaticIcon iconName={showOptions ? 'ArrowUpIcon' : 'ArrowDownIcon'} color={borderColor} onClick={() => disabled ? null : setShowOptions(!showOptions)} />
|
|
69
95
|
</div>
|
|
70
96
|
</div>
|
|
71
97
|
{showOptions && !showError && renderOptions()}
|
|
@@ -82,7 +108,10 @@ Select.propTypes = {
|
|
|
82
108
|
/**
|
|
83
109
|
* name
|
|
84
110
|
*/
|
|
85
|
-
name: PropTypes.
|
|
111
|
+
name: PropTypes.oneOfType([
|
|
112
|
+
PropTypes.string,
|
|
113
|
+
PropTypes.number
|
|
114
|
+
]),
|
|
86
115
|
/**
|
|
87
116
|
* value
|
|
88
117
|
*/
|
|
@@ -91,8 +120,14 @@ Select.propTypes = {
|
|
|
91
120
|
* options
|
|
92
121
|
*/
|
|
93
122
|
options: PropTypes.arrayOf(PropTypes.shape({
|
|
94
|
-
|
|
95
|
-
|
|
123
|
+
label: PropTypes.string,
|
|
124
|
+
value: PropTypes.oneOfType([
|
|
125
|
+
PropTypes.string,
|
|
126
|
+
PropTypes.number
|
|
127
|
+
]),
|
|
128
|
+
icon: PropTypes.string,
|
|
129
|
+
notSelectable: PropTypes.bool,
|
|
130
|
+
onClick: PropTypes.func
|
|
96
131
|
})),
|
|
97
132
|
/**
|
|
98
133
|
* color of border
|
|
@@ -106,10 +141,18 @@ Select.propTypes = {
|
|
|
106
141
|
* onSelect
|
|
107
142
|
*/
|
|
108
143
|
onSelect: PropTypes.func,
|
|
144
|
+
/**
|
|
145
|
+
* onClear
|
|
146
|
+
*/
|
|
147
|
+
onClear: PropTypes.func,
|
|
109
148
|
/**
|
|
110
149
|
* Disabled
|
|
111
150
|
*/
|
|
112
|
-
disabled: PropTypes.bool
|
|
151
|
+
disabled: PropTypes.bool,
|
|
152
|
+
/**
|
|
153
|
+
* optionsIconColor
|
|
154
|
+
*/
|
|
155
|
+
optionsIconColor: PropTypes.string
|
|
113
156
|
}
|
|
114
157
|
|
|
115
158
|
Select.defaultProps = {
|
|
@@ -122,7 +165,9 @@ Select.defaultProps = {
|
|
|
122
165
|
errorMessage: '',
|
|
123
166
|
onChange: () => {},
|
|
124
167
|
onSelect: () => {},
|
|
125
|
-
|
|
168
|
+
onClear: () => {},
|
|
169
|
+
disabled: false,
|
|
170
|
+
optionsIconColor: MAIN_DARK_BLUE
|
|
126
171
|
}
|
|
127
172
|
|
|
128
173
|
export default Select
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
.container {
|
|
2
|
-
@apply flex flex-col w-full relative
|
|
2
|
+
@apply flex flex-col w-full relative;
|
|
3
3
|
}
|
|
4
4
|
.selectContainer {
|
|
5
|
-
@apply w-full flex items-center h-10 relative;
|
|
6
|
-
}
|
|
5
|
+
@apply w-full flex items-center h-10 relative z-10;
|
|
6
|
+
}
|
|
7
7
|
.select {
|
|
8
8
|
@apply px-2 h-full border border-solid box-border rounded-md ;
|
|
9
9
|
}
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
@apply shadow-main-dark-blue outline-none;
|
|
13
13
|
}
|
|
14
14
|
.options {
|
|
15
|
-
@apply absolute left-0 top-[42px] bg-white w-full max-h-[216px] overflow-y-scroll;
|
|
15
|
+
@apply absolute left-0 top-[42px] bg-white w-full max-h-[216px] overflow-y-scroll z-20;
|
|
16
16
|
box-shadow: 0px 0px 10px rgb(0 40 61 / 25%);
|
|
17
17
|
}
|
|
18
18
|
.option {
|
|
19
|
-
@apply w-full px-4 py-2 border-b border-main-dark-blue/[.15] font-light cursor-pointer hover:bg-main-dark-blue hover:bg-opacity-10
|
|
19
|
+
@apply w-full px-4 py-2 border-b border-main-dark-blue/[.15] font-light cursor-pointer hover:bg-main-dark-blue hover:bg-opacity-10 inline-flex items-center gap-x-1
|
|
20
20
|
}
|
|
21
21
|
.icons {
|
|
22
22
|
@apply absolute top-[50%] right-[0.5rem] translate-y-[-50%] flex gap-x-2;
|
|
@@ -51,12 +51,36 @@ const TemplateBorderMainDarkBlue = (args) => {
|
|
|
51
51
|
)
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
const TemplateBorderMainDarkBlue2 = (args) => {
|
|
55
|
+
const [value, setValue] = useState('')
|
|
56
|
+
|
|
57
|
+
function handleChange (event) {
|
|
58
|
+
setValue(event.target.value)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function handleSelect (event) {
|
|
62
|
+
setValue(event.detail.label)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<>
|
|
67
|
+
<div style={{ backgroundColor: 'white', padding: '20px 10px' }}>
|
|
68
|
+
<p>Value of the input {value}</p>
|
|
69
|
+
<Select {...args} value={value} onChange={handleChange} onSelect={handleSelect} />
|
|
70
|
+
<br />
|
|
71
|
+
<Select placeholder='Disabled' disabled />
|
|
72
|
+
|
|
73
|
+
</div>
|
|
74
|
+
</>
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
54
78
|
export const BorderMainDarkBlue = TemplateBorderMainDarkBlue.bind({})
|
|
55
79
|
|
|
56
80
|
BorderMainDarkBlue.args = {
|
|
57
81
|
name: 'test',
|
|
58
82
|
placeholder: 'Defaul option',
|
|
59
|
-
options: [...Array(20).keys()].map(ele => ({ label: `Option ${ele}`, value: `Value${ele}
|
|
83
|
+
options: [...Array(20).keys()].map(ele => ({ label: `Option ${ele}`, value: `Value${ele}`, iconName: 'SocialGitHubIcon' })),
|
|
60
84
|
borderColor: MAIN_DARK_BLUE
|
|
61
85
|
}
|
|
62
86
|
|
|
@@ -69,3 +93,27 @@ DefaultInvalid.args = {
|
|
|
69
93
|
borderColor: MAIN_GREEN,
|
|
70
94
|
errorMessage: 'This is an error message'
|
|
71
95
|
}
|
|
96
|
+
|
|
97
|
+
export const withDifferentOptions = TemplateBorderMainDarkBlue2.bind({})
|
|
98
|
+
|
|
99
|
+
withDifferentOptions.args = {
|
|
100
|
+
name: 'test',
|
|
101
|
+
placeholder: 'Platformatic',
|
|
102
|
+
options: [...Array(20).keys()].map(ele => ({
|
|
103
|
+
label: `Option ${ele}`,
|
|
104
|
+
value: `Value${ele}`,
|
|
105
|
+
iconName: 'SocialGitHubIcon'
|
|
106
|
+
})).concat({
|
|
107
|
+
label: 'Last but not least',
|
|
108
|
+
iconName: 'AddIcon',
|
|
109
|
+
value: 123123,
|
|
110
|
+
notSelectable: true,
|
|
111
|
+
onClick: () => alert('you clicked last but not least')
|
|
112
|
+
}).concat({
|
|
113
|
+
label: 'Play',
|
|
114
|
+
iconName: 'PlayIcon',
|
|
115
|
+
value: 123123,
|
|
116
|
+
notSelectable: true
|
|
117
|
+
}),
|
|
118
|
+
borderColor: MAIN_DARK_BLUE
|
|
119
|
+
}
|