haya-select 1.0.6 → 1.0.9
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/.github/dependabot.yml +9 -0
- package/package.json +5 -1
- package/src/select/index.jsx +143 -69
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "haya-select",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -12,5 +12,9 @@
|
|
|
12
12
|
"classnames": "^2.3.1",
|
|
13
13
|
"debounce": "^1.2.1",
|
|
14
14
|
"diggerize": "^1.0.4"
|
|
15
|
+
},
|
|
16
|
+
"peerDependencies": {
|
|
17
|
+
"prop-types": ">= 15.7.2",
|
|
18
|
+
"react": ">= 16.0.0"
|
|
15
19
|
}
|
|
16
20
|
}
|
package/src/select/index.jsx
CHANGED
|
@@ -14,41 +14,9 @@ const nameForComponentWithMultiple = (component) => {
|
|
|
14
14
|
return name
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
if ("text" in currentValue) return currentValue.text
|
|
19
|
-
|
|
20
|
-
if ("html" in currentValue) {
|
|
21
|
-
return (
|
|
22
|
-
<div dangerouslySetInnerHTML={{__html: digg(currentValue, "html")}} />
|
|
23
|
-
)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
throw new Error(`Couldn't figure out how to present option from the given keys: ${Object.keys(currentValue, ", ")}`)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const LoadedOption = class LoadedOption extends BaseComponent {
|
|
30
|
-
render() {
|
|
31
|
-
const {currentOptions, loadedOption} = digs(this.props, "currentOptions", "loadedOption")
|
|
32
|
-
const selected = Boolean(currentOptions.find((currentOption) => currentOption.value == loadedOption.value))
|
|
33
|
-
|
|
34
|
-
return (
|
|
35
|
-
<div
|
|
36
|
-
className="haya-select-option"
|
|
37
|
-
data-selected={selected}
|
|
38
|
-
data-value={digg(loadedOption, "value")}
|
|
39
|
-
onClick={this.onOptionClicked}
|
|
40
|
-
style={{cursor: "pointer"}}
|
|
41
|
-
>
|
|
42
|
-
{presentOption(loadedOption)}
|
|
43
|
-
</div>
|
|
44
|
-
)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
onOptionClicked = (e) => this.props.onClick(e, this.props.loadedOption)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export default class CustomSelect extends React.PureComponent {
|
|
17
|
+
export default class HayaSelect extends React.PureComponent {
|
|
51
18
|
static defaultProps = {
|
|
19
|
+
defaultToggled: {},
|
|
52
20
|
multiple: false,
|
|
53
21
|
search: false
|
|
54
22
|
}
|
|
@@ -56,14 +24,22 @@ export default class CustomSelect extends React.PureComponent {
|
|
|
56
24
|
static propTypes = {
|
|
57
25
|
attribute: PropTypes.string,
|
|
58
26
|
className: PropTypes.string,
|
|
27
|
+
defaultToggled: PropTypes.object,
|
|
59
28
|
defaultValue: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
60
29
|
defaultValues: PropTypes.array,
|
|
61
30
|
defaultValuesFromOptions: PropTypes.array,
|
|
31
|
+
id: PropTypes.node,
|
|
62
32
|
model: PropTypes.object,
|
|
63
33
|
multiple: PropTypes.bool.isRequired,
|
|
64
34
|
onChange: PropTypes.func,
|
|
65
35
|
options: PropTypes.oneOfType([PropTypes.array, PropTypes.func]).isRequired,
|
|
66
|
-
|
|
36
|
+
placeholder: PropTypes.node,
|
|
37
|
+
search: PropTypes.bool.isRequired,
|
|
38
|
+
toggleOptions: PropTypes.arrayOf(PropTypes.shape({
|
|
39
|
+
icon: PropTypes.string.isRequired,
|
|
40
|
+
label: PropTypes.string.isRequired,
|
|
41
|
+
value: PropTypes.string.isRequired
|
|
42
|
+
}))
|
|
67
43
|
}
|
|
68
44
|
|
|
69
45
|
endOfSelectRef = React.createRef()
|
|
@@ -78,7 +54,8 @@ export default class CustomSelect extends React.PureComponent {
|
|
|
78
54
|
optionsTop: undefined,
|
|
79
55
|
optionsWidth: undefined,
|
|
80
56
|
scrollLeft: undefined,
|
|
81
|
-
scrollTop: undefined
|
|
57
|
+
scrollTop: undefined,
|
|
58
|
+
toggled: digg(this, "props", "defaultToggled")
|
|
82
59
|
}
|
|
83
60
|
|
|
84
61
|
defaultCurrentOptions() {
|
|
@@ -106,16 +83,31 @@ export default class CustomSelect extends React.PureComponent {
|
|
|
106
83
|
}
|
|
107
84
|
|
|
108
85
|
componentDidMount() {
|
|
109
|
-
const {attribute, defaultValuesFromOptions, model, options} = this.props
|
|
86
|
+
const {attribute, defaultValue, defaultValuesFromOptions, model, options} = this.props
|
|
110
87
|
|
|
111
|
-
if ((defaultValuesFromOptions || (attribute && model)) && typeof options == "function") {
|
|
88
|
+
if (((defaultValue || defaultValuesFromOptions) || (attribute && model)) && typeof options == "function") {
|
|
112
89
|
this.loadDefaultValuesFromOptionsCallback()
|
|
113
90
|
}
|
|
114
91
|
}
|
|
115
92
|
|
|
116
93
|
render() {
|
|
117
94
|
const {endOfSelectRef} = digs(this, "endOfSelectRef")
|
|
118
|
-
const {
|
|
95
|
+
const {
|
|
96
|
+
attribute,
|
|
97
|
+
className,
|
|
98
|
+
defaultToggled,
|
|
99
|
+
defaultValue,
|
|
100
|
+
defaultValues,
|
|
101
|
+
id,
|
|
102
|
+
model,
|
|
103
|
+
multiple,
|
|
104
|
+
onChange,
|
|
105
|
+
options,
|
|
106
|
+
placeholder,
|
|
107
|
+
search,
|
|
108
|
+
toggleOptions,
|
|
109
|
+
...restProps
|
|
110
|
+
} = this.props
|
|
119
111
|
const {currentOptions, opened} = digs(this.state, "currentOptions", "opened")
|
|
120
112
|
const BodyPortal = config.getBodyPortal()
|
|
121
113
|
|
|
@@ -147,18 +139,20 @@ export default class CustomSelect extends React.PureComponent {
|
|
|
147
139
|
<>
|
|
148
140
|
{currentOptions.length == 0 &&
|
|
149
141
|
<div style={{color: "grey"}}>
|
|
150
|
-
{I18n.t("haya_select.nothing_selected")}
|
|
142
|
+
{placeholder || I18n.t("haya_select.nothing_selected")}
|
|
151
143
|
</div>
|
|
152
144
|
}
|
|
153
145
|
{currentOptions.map((currentOption) =>
|
|
154
146
|
<div className="current-option" key={`current-value-${digg(currentOption, "value")}`}>
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
147
|
+
{nameForComponentWithMultiple(this) &&
|
|
148
|
+
<input
|
|
149
|
+
id={idForComponent(this)}
|
|
150
|
+
name={nameForComponentWithMultiple(this)}
|
|
151
|
+
type="hidden"
|
|
152
|
+
value={digg(currentOption, "value")}
|
|
153
|
+
/>
|
|
154
|
+
}
|
|
155
|
+
{this.presentOption(currentOption)}
|
|
162
156
|
</div>
|
|
163
157
|
)}
|
|
164
158
|
</>
|
|
@@ -170,9 +164,10 @@ export default class CustomSelect extends React.PureComponent {
|
|
|
170
164
|
}
|
|
171
165
|
|
|
172
166
|
defaultValues () {
|
|
173
|
-
const {attribute, defaultValuesFromOptions, model} = this.props
|
|
167
|
+
const {attribute, defaultValue, defaultValuesFromOptions, model} = this.props
|
|
174
168
|
|
|
175
169
|
if (defaultValuesFromOptions) return defaultValuesFromOptions
|
|
170
|
+
if (defaultValue) return defaultValue
|
|
176
171
|
|
|
177
172
|
if (attribute && model) {
|
|
178
173
|
if (!(attribute in model)) throw new Error(`No such attribute on ${model.modelClassData().name}: ${attribute}`)
|
|
@@ -209,6 +204,24 @@ export default class CustomSelect extends React.PureComponent {
|
|
|
209
204
|
this.setState({loadedOptions})
|
|
210
205
|
}
|
|
211
206
|
|
|
207
|
+
hayaSelectOption({key, loadedOption}) {
|
|
208
|
+
const {currentOptions} = digs(this.state, "currentOptions")
|
|
209
|
+
const selected = Boolean(currentOptions.find((currentOption) => currentOption.value == loadedOption.value))
|
|
210
|
+
|
|
211
|
+
return (
|
|
212
|
+
<div
|
|
213
|
+
className="haya-select-option"
|
|
214
|
+
data-selected={selected}
|
|
215
|
+
data-value={digg(loadedOption, "value")}
|
|
216
|
+
key={key}
|
|
217
|
+
onClick={(e) => this.onOptionClicked(e, loadedOption)}
|
|
218
|
+
style={{cursor: "pointer"}}
|
|
219
|
+
>
|
|
220
|
+
{this.presentOption(loadedOption)}
|
|
221
|
+
</div>
|
|
222
|
+
)
|
|
223
|
+
}
|
|
224
|
+
|
|
212
225
|
loadOptionsFromArray(options, searchValue) {
|
|
213
226
|
const lowerSearchValue = searchValue?.toLowerCase()
|
|
214
227
|
const loadedOptions = options.filter(({text}) => !lowerSearchValue || text.toLowerCase().includes(lowerSearchValue))
|
|
@@ -273,7 +286,6 @@ export default class CustomSelect extends React.PureComponent {
|
|
|
273
286
|
optionsContainer() {
|
|
274
287
|
const {optionsContainerRef} = digs(this, "endOfSelectRef", "optionsContainerRef")
|
|
275
288
|
const {
|
|
276
|
-
currentOptions,
|
|
277
289
|
loadedOptions,
|
|
278
290
|
optionsLeft,
|
|
279
291
|
optionsTop,
|
|
@@ -282,7 +294,6 @@ export default class CustomSelect extends React.PureComponent {
|
|
|
282
294
|
scrollTop
|
|
283
295
|
} = digs(
|
|
284
296
|
this.state,
|
|
285
|
-
"currentOptions",
|
|
286
297
|
"loadedOptions",
|
|
287
298
|
"currentOptions",
|
|
288
299
|
"opened",
|
|
@@ -306,12 +317,10 @@ export default class CustomSelect extends React.PureComponent {
|
|
|
306
317
|
>
|
|
307
318
|
<EventListener event="click" onCalled={this.onWindowClicked} target={window} />
|
|
308
319
|
{loadedOptions?.map((loadedOption) =>
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
onClick={this.onOptionClicked}
|
|
314
|
-
/>
|
|
320
|
+
this.hayaSelectOption({
|
|
321
|
+
key: `loaded-option-${digg(loadedOption.value)}`,
|
|
322
|
+
loadedOption
|
|
323
|
+
})
|
|
315
324
|
)}
|
|
316
325
|
{loadedOptions?.length === 0 &&
|
|
317
326
|
<div className="haya-select-no-options-container">
|
|
@@ -326,26 +335,91 @@ export default class CustomSelect extends React.PureComponent {
|
|
|
326
335
|
e.preventDefault()
|
|
327
336
|
e.stopPropagation()
|
|
328
337
|
|
|
329
|
-
const {onChange} = this.props
|
|
338
|
+
const {onChange, toggleOptions} = this.props
|
|
330
339
|
const {multiple} = digs(this.props, "multiple")
|
|
331
340
|
|
|
332
|
-
this.setState(
|
|
333
|
-
|
|
341
|
+
this.setState(
|
|
342
|
+
(prevState) => {
|
|
343
|
+
const existingOption = prevState.currentOptions.find((currentOption) => currentOption.value == loadedOption.value)
|
|
344
|
+
const newState = {}
|
|
345
|
+
const {toggled} = digs(prevState, "toggled")
|
|
346
|
+
const newToggled = {...toggled}
|
|
347
|
+
|
|
348
|
+
if (existingOption) {
|
|
349
|
+
if (toggleOptions) {
|
|
350
|
+
const currentIndex = digg(toggled, loadedOption.value)
|
|
351
|
+
|
|
352
|
+
if (currentIndex >= (toggleOptions.length - 1)) {
|
|
353
|
+
delete newToggled[loadedOption.value]
|
|
354
|
+
|
|
355
|
+
newState.currentOptions = prevState.currentOptions.filter((currentOption) => currentOption.value != loadedOption.value)
|
|
356
|
+
} else {
|
|
357
|
+
newToggled[loadedOption.value] = toggled[loadedOption.value] + 1
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
newState.toggled = newToggled
|
|
361
|
+
} else {
|
|
362
|
+
newState.currentOptions = prevState.currentOptions.filter((currentOption) => currentOption.value != loadedOption.value)
|
|
363
|
+
}
|
|
364
|
+
} else {
|
|
365
|
+
if (toggleOptions) {
|
|
366
|
+
newToggled[loadedOption.value] = 0
|
|
367
|
+
newState.toggled = newToggled
|
|
368
|
+
}
|
|
334
369
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
370
|
+
if (multiple || toggleOptions) {
|
|
371
|
+
newState.currentOptions = prevState.currentOptions.concat([loadedOption])
|
|
372
|
+
} else {
|
|
373
|
+
newState.currentOptions = [loadedOption]
|
|
374
|
+
}
|
|
338
375
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
376
|
+
|
|
377
|
+
return newState
|
|
378
|
+
},
|
|
379
|
+
() => {
|
|
380
|
+
if (onChange) {
|
|
381
|
+
const toggles = {}
|
|
382
|
+
|
|
383
|
+
for(const toggleKey in this.state.toggled) {
|
|
384
|
+
const toggleValue = digg(this, "state", "toggled", toggleKey)
|
|
385
|
+
const toggleOption = digg(this, "props", "toggleOptions", toggleValue)
|
|
386
|
+
|
|
387
|
+
toggles[toggleKey] = toggleOption
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
onChange({
|
|
391
|
+
options: this.state.currentOptions,
|
|
392
|
+
toggles
|
|
393
|
+
})
|
|
344
394
|
}
|
|
345
395
|
}
|
|
346
|
-
|
|
396
|
+
)
|
|
347
397
|
|
|
348
398
|
if (!multiple) this.closeOptions()
|
|
349
|
-
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
presentOption = (currentValue) => {
|
|
402
|
+
const {toggleOptions} = this.props
|
|
403
|
+
const {toggled} = digs(this.state, "toggled")
|
|
404
|
+
|
|
405
|
+
return (
|
|
406
|
+
<div
|
|
407
|
+
className="haya-select-option-presentation"
|
|
408
|
+
data-toggle-icon={toggleOptions[toggled[currentValue.value]]?.icon}
|
|
409
|
+
data-toggle-value={toggleOptions[toggled[currentValue.value]]?.value}
|
|
410
|
+
data-value={currentValue.value}
|
|
411
|
+
>
|
|
412
|
+
{toggleOptions && !(currentValue.value in toggled) &&
|
|
413
|
+
<i className="fa fa-fw" />
|
|
414
|
+
}
|
|
415
|
+
{toggleOptions && (currentValue.value in toggled) &&
|
|
416
|
+
<i className={`fa fa-fw fa-${toggleOptions[toggled[currentValue.value]].icon}`} />
|
|
417
|
+
}
|
|
418
|
+
{currentValue.text}
|
|
419
|
+
{("html" in currentValue) &&
|
|
420
|
+
<div dangerouslySetInnerHTML={{__html: digg(currentValue, "html")}} />
|
|
421
|
+
}
|
|
422
|
+
</div>
|
|
423
|
+
)
|
|
350
424
|
}
|
|
351
425
|
}
|