haya-select 1.0.0 → 1.0.3
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
package/src/config.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class HayaSelectConfiguration {
|
|
2
|
+
getBodyPortal() {
|
|
3
|
+
if (!this._bodyPortal) throw new Error("bodyPortal wasn't set")
|
|
4
|
+
|
|
5
|
+
return this._bodyPortal
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
setBodyPortal(newBodyPortal) {
|
|
9
|
+
this._bodyPortal = newBodyPortal
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const configuration = new HayaSelectConfiguration()
|
|
14
|
+
|
|
15
|
+
export default configuration
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "./style"
|
|
2
|
-
import BodyPortal from "components/layout/body-portal"
|
|
3
2
|
import classNames from "classnames"
|
|
3
|
+
import config from "../config.js"
|
|
4
4
|
import {digg, digs} from "diggerize"
|
|
5
5
|
import debounce from "debounce"
|
|
6
6
|
import {idForComponent, nameForComponent} from "@kaspernj/api-maker-inputs"
|
|
@@ -33,7 +33,7 @@ const LoadedOption = class LoadedOption extends BaseComponent {
|
|
|
33
33
|
|
|
34
34
|
return (
|
|
35
35
|
<div
|
|
36
|
-
className="
|
|
36
|
+
className="haya-select-option"
|
|
37
37
|
data-selected={selected}
|
|
38
38
|
data-value={digg(loadedOption, "value")}
|
|
39
39
|
onClick={this.onOptionClicked}
|
|
@@ -56,6 +56,7 @@ export default class CustomSelect extends React.PureComponent {
|
|
|
56
56
|
static propTypes = {
|
|
57
57
|
attribute: PropTypes.string,
|
|
58
58
|
className: PropTypes.string,
|
|
59
|
+
defaultValue: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
59
60
|
defaultValues: PropTypes.array,
|
|
60
61
|
defaultValuesFromOptions: PropTypes.array,
|
|
61
62
|
model: PropTypes.object,
|
|
@@ -70,7 +71,7 @@ export default class CustomSelect extends React.PureComponent {
|
|
|
70
71
|
searchTextInputRef = React.createRef()
|
|
71
72
|
|
|
72
73
|
state = {
|
|
73
|
-
currentOptions:
|
|
74
|
+
currentOptions: this.defaultCurrentOptions(),
|
|
74
75
|
loadedOptions: this.defaultLoadedOptions(),
|
|
75
76
|
opened: false,
|
|
76
77
|
optionsLeft: undefined,
|
|
@@ -80,12 +81,28 @@ export default class CustomSelect extends React.PureComponent {
|
|
|
80
81
|
scrollTop: undefined
|
|
81
82
|
}
|
|
82
83
|
|
|
84
|
+
defaultCurrentOptions() {
|
|
85
|
+
const {defaultValue, defaultValues} = this.props
|
|
86
|
+
const {options} = digs(this.props, "options")
|
|
87
|
+
|
|
88
|
+
if (!Array.isArray(options)) return []
|
|
89
|
+
|
|
90
|
+
return options.filter(({value}) =>
|
|
91
|
+
(defaultValue && value == defaultValue) ||
|
|
92
|
+
(defaultValues && defaultValues.includes(value))
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
|
|
83
96
|
defaultLoadedOptions() {
|
|
84
97
|
const {options} = digs(this.props, "options")
|
|
85
98
|
|
|
86
|
-
if (typeof options == "function")
|
|
99
|
+
if (typeof options == "function") {
|
|
100
|
+
return undefined
|
|
101
|
+
} else if (Array.isArray(options)) {
|
|
102
|
+
return options
|
|
103
|
+
}
|
|
87
104
|
|
|
88
|
-
|
|
105
|
+
throw new Error(`Unknown type of options: ${typeof options}`)
|
|
89
106
|
}
|
|
90
107
|
|
|
91
108
|
componentDidMount() {
|
|
@@ -98,12 +115,13 @@ export default class CustomSelect extends React.PureComponent {
|
|
|
98
115
|
|
|
99
116
|
render() {
|
|
100
117
|
const {endOfSelectRef} = digs(this, "endOfSelectRef")
|
|
101
|
-
const {attribute, className, defaultValues, model, multiple, onChange, options, search, ...restProps} = this.props
|
|
118
|
+
const {attribute, className, defaultValue, defaultValues, model, multiple, onChange, options, search, ...restProps} = this.props
|
|
102
119
|
const {currentOptions, opened} = digs(this.state, "currentOptions", "opened")
|
|
120
|
+
const BodyPortal = config.getBodyPortal()
|
|
103
121
|
|
|
104
122
|
return (
|
|
105
123
|
<div
|
|
106
|
-
className={classNames("
|
|
124
|
+
className={classNames("haya-select", className)}
|
|
107
125
|
data-id={idForComponent(this)}
|
|
108
126
|
{...restProps}
|
|
109
127
|
>
|
|
@@ -113,15 +131,15 @@ export default class CustomSelect extends React.PureComponent {
|
|
|
113
131
|
</BodyPortal>
|
|
114
132
|
}
|
|
115
133
|
<div
|
|
116
|
-
className="
|
|
134
|
+
className="haya-select-current-selected"
|
|
117
135
|
data-opened={opened}
|
|
118
136
|
onClick={this.onSelectClicked}
|
|
119
137
|
>
|
|
120
138
|
{opened &&
|
|
121
139
|
<input
|
|
122
|
-
className="
|
|
140
|
+
className="haya-select-search-text-input"
|
|
123
141
|
onChange={digg(this, "onSearchTextInputChangedDebounced")}
|
|
124
|
-
placeholder={I18n.t("
|
|
142
|
+
placeholder={I18n.t("haya_select.search_dot_dot_dot")} type="text"
|
|
125
143
|
ref={digg(this, "searchTextInputRef")}
|
|
126
144
|
/>
|
|
127
145
|
}
|
|
@@ -129,7 +147,7 @@ export default class CustomSelect extends React.PureComponent {
|
|
|
129
147
|
<>
|
|
130
148
|
{currentOptions.length == 0 &&
|
|
131
149
|
<div style={{color: "grey"}}>
|
|
132
|
-
{I18n.t("
|
|
150
|
+
{I18n.t("haya_select.nothing_selected")}
|
|
133
151
|
</div>
|
|
134
152
|
}
|
|
135
153
|
{currentOptions.map((currentOption) =>
|
|
@@ -154,11 +172,15 @@ export default class CustomSelect extends React.PureComponent {
|
|
|
154
172
|
defaultValues () {
|
|
155
173
|
const {attribute, defaultValuesFromOptions, model} = this.props
|
|
156
174
|
|
|
175
|
+
console.log("defaultValues")
|
|
176
|
+
|
|
157
177
|
if (defaultValuesFromOptions) return defaultValuesFromOptions
|
|
158
178
|
|
|
159
179
|
if (attribute && model) {
|
|
160
180
|
if (!(attribute in model)) throw new Error(`No such attribute on ${model.modelClassData().name}: ${attribute}`)
|
|
161
181
|
|
|
182
|
+
console.log(`Default value from ${attribute}: ${model[attribute]()}`)
|
|
183
|
+
|
|
162
184
|
return model[attribute]()
|
|
163
185
|
}
|
|
164
186
|
}
|
|
@@ -180,9 +202,20 @@ export default class CustomSelect extends React.PureComponent {
|
|
|
180
202
|
|
|
181
203
|
loadOptions = async () => {
|
|
182
204
|
const {options} = digs(this.props, "options")
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
205
|
+
const searchValue = digg(this, "searchTextInputRef", "current")?.value
|
|
206
|
+
|
|
207
|
+
if (Array.isArray(options)) {
|
|
208
|
+
return this.loadOptionsFromArray(options, searchValue)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const loadedOptions = await options({searchValue})
|
|
212
|
+
|
|
213
|
+
this.setState({loadedOptions})
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
loadOptionsFromArray(options, searchValue) {
|
|
217
|
+
const lowerSearchValue = searchValue?.toLowerCase()
|
|
218
|
+
const loadedOptions = options.filter(({text}) => !lowerSearchValue || text.toLowerCase().includes(lowerSearchValue))
|
|
186
219
|
|
|
187
220
|
this.setState({loadedOptions})
|
|
188
221
|
}
|
|
@@ -266,7 +299,7 @@ export default class CustomSelect extends React.PureComponent {
|
|
|
266
299
|
|
|
267
300
|
return (
|
|
268
301
|
<div
|
|
269
|
-
className="
|
|
302
|
+
className="haya-select-options-container"
|
|
270
303
|
data-id={idForComponent(this)}
|
|
271
304
|
ref={optionsContainerRef}
|
|
272
305
|
style={{
|
|
@@ -285,8 +318,8 @@ export default class CustomSelect extends React.PureComponent {
|
|
|
285
318
|
/>
|
|
286
319
|
)}
|
|
287
320
|
{loadedOptions?.length === 0 &&
|
|
288
|
-
<div className="
|
|
289
|
-
{I18n.t("
|
|
321
|
+
<div className="haya-select-no-options-container">
|
|
322
|
+
{I18n.t("haya_select.no_options_found")}
|
|
290
323
|
</div>
|
|
291
324
|
}
|
|
292
325
|
</div>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
.
|
|
1
|
+
.haya-select-current-selected {
|
|
2
2
|
background-color: #fff;
|
|
3
3
|
border: 1px solid #999;
|
|
4
4
|
cursor: pointer;
|
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
.
|
|
16
|
+
.haya-select-search-text-input {
|
|
17
17
|
border: 0;
|
|
18
18
|
outline: none;
|
|
19
19
|
padding: 0;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
.
|
|
22
|
+
.haya-select-options-container {
|
|
23
23
|
background-color: #fff;
|
|
24
24
|
border: 1px solid #999;
|
|
25
25
|
max-height: 300px;
|
|
@@ -27,8 +27,9 @@
|
|
|
27
27
|
position: absolute;
|
|
28
28
|
z-index: 99999;
|
|
29
29
|
|
|
30
|
-
.
|
|
30
|
+
.haya-select-option {
|
|
31
31
|
padding: 4px 8px;
|
|
32
|
+
color: #000;
|
|
32
33
|
|
|
33
34
|
&[data-selected="true"] {
|
|
34
35
|
background-color: #80b2ff;
|