haya-select 1.0.28 → 1.0.30
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 +2 -2
- package/src/select/index.jsx +69 -63
- package/src/select/option-group.jsx +13 -12
- package/src/select/option.jsx +27 -27
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "haya-select",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.30",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"debounce": "^1.2.1",
|
|
14
14
|
"diggerize": "^1.0.4",
|
|
15
15
|
"fetching-object": "^1.0.1",
|
|
16
|
-
"set-state-compare": "^1.0.
|
|
16
|
+
"set-state-compare": "^1.0.42"
|
|
17
17
|
},
|
|
18
18
|
"peerDependencies": {
|
|
19
19
|
"prop-types": ">= 15.7.2",
|
package/src/select/index.jsx
CHANGED
|
@@ -9,8 +9,8 @@ import nameForComponent from "@kaspernj/api-maker/src/inputs/name-for-component.
|
|
|
9
9
|
import Option from "./option"
|
|
10
10
|
import OptionGroup from "./option-group"
|
|
11
11
|
import PropTypes from "prop-types"
|
|
12
|
-
import
|
|
13
|
-
import {
|
|
12
|
+
import {memo, useRef} from "react"
|
|
13
|
+
import {shapeComponent, ShapeComponent} from "set-state-compare/src/shape-component.js"
|
|
14
14
|
|
|
15
15
|
const nameForComponentWithMultiple = (component) => {
|
|
16
16
|
let name = nameForComponent(component)
|
|
@@ -20,7 +20,7 @@ const nameForComponentWithMultiple = (component) => {
|
|
|
20
20
|
return name
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
export default class HayaSelect extends
|
|
23
|
+
export default memo(shapeComponent(class HayaSelect extends ShapeComponent {
|
|
24
24
|
static defaultProps = {
|
|
25
25
|
multiple: false,
|
|
26
26
|
search: false
|
|
@@ -51,27 +51,33 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
p = fetchingObject(() => this.props)
|
|
54
|
-
s = fetchingObject(() => this.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
54
|
+
s = fetchingObject(() => this.state)
|
|
55
|
+
tt = fetchingObject(this)
|
|
56
|
+
|
|
57
|
+
setup() {
|
|
58
|
+
const {t} = useI18n({namespace: "haya_select"})
|
|
59
|
+
|
|
60
|
+
this.setInstance({
|
|
61
|
+
endOfSelectRef: useRef(),
|
|
62
|
+
optionsContainerRef: useRef(),
|
|
63
|
+
currentSelectedRef: useRef(),
|
|
64
|
+
searchTextInputRef: useRef(),
|
|
65
|
+
t
|
|
66
|
+
})
|
|
67
|
+
this.useStates({
|
|
68
|
+
currentOptions: () => this.defaultCurrentOptions(),
|
|
69
|
+
loadedOptions: () => this.defaultLoadedOptions(),
|
|
70
|
+
opened: false,
|
|
71
|
+
optionsLeft: undefined,
|
|
72
|
+
optionsPlacement: undefined,
|
|
73
|
+
optionsTop: undefined,
|
|
74
|
+
optionsVisibility: undefined,
|
|
75
|
+
optionsWidth: undefined,
|
|
76
|
+
scrollLeft: undefined,
|
|
77
|
+
scrollTop: undefined,
|
|
78
|
+
toggled: () => this.defaultToggled()
|
|
79
|
+
})
|
|
80
|
+
}
|
|
75
81
|
|
|
76
82
|
defaultCurrentOptions() {
|
|
77
83
|
const {defaultValue, defaultValues, values} = this.props
|
|
@@ -109,8 +115,8 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
109
115
|
this.loadDefaultValuesFromOptionsCallback()
|
|
110
116
|
}
|
|
111
117
|
|
|
112
|
-
window.addEventListener("resize", this.
|
|
113
|
-
window.addEventListener("scroll", this.
|
|
118
|
+
window.addEventListener("resize", this.tt.onAnythingResizedDebounced, true)
|
|
119
|
+
window.addEventListener("scroll", this.tt.onAnythingScrolledDebounced, true)
|
|
114
120
|
}
|
|
115
121
|
|
|
116
122
|
componentDidUpdate() {
|
|
@@ -119,7 +125,7 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
119
125
|
if ("values" in this.props) {
|
|
120
126
|
const newCurrentOptions = this.defaultCurrentOptions()
|
|
121
127
|
|
|
122
|
-
if (anythingDifferent(this.
|
|
128
|
+
if (anythingDifferent(this.state.currentOptions, newCurrentOptions)) {
|
|
123
129
|
newState.currentOptions = newCurrentOptions
|
|
124
130
|
}
|
|
125
131
|
}
|
|
@@ -127,21 +133,21 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
127
133
|
if ("toggled" in this.props) {
|
|
128
134
|
const newToggled = this.p.toggled
|
|
129
135
|
|
|
130
|
-
if (anythingDifferent(this.
|
|
136
|
+
if (anythingDifferent(this.state.toggled, newToggled)) {
|
|
131
137
|
newState.toggled = newToggled
|
|
132
138
|
}
|
|
133
139
|
}
|
|
134
140
|
|
|
135
|
-
this.
|
|
141
|
+
this.setState(newState)
|
|
136
142
|
}
|
|
137
143
|
|
|
138
144
|
componentWillUnmount() {
|
|
139
|
-
window.removeEventListener("resize", this.
|
|
140
|
-
window.removeEventListener("scroll", this.
|
|
145
|
+
window.removeEventListener("resize", this.tt.onAnythingResizedDebounced)
|
|
146
|
+
window.removeEventListener("scroll", this.tt.onAnythingScrolledDebounced)
|
|
141
147
|
}
|
|
142
148
|
|
|
143
149
|
render() {
|
|
144
|
-
const {currentSelectedRef, endOfSelectRef, onSelectClicked, onSearchTextInputChangedDebounced} = this.
|
|
150
|
+
const {currentSelectedRef, endOfSelectRef, onSelectClicked, onSearchTextInputChangedDebounced} = this.tt
|
|
145
151
|
const {
|
|
146
152
|
attribute,
|
|
147
153
|
className,
|
|
@@ -186,16 +192,16 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
186
192
|
<input
|
|
187
193
|
className="haya-select-search-text-input"
|
|
188
194
|
onChange={onSearchTextInputChangedDebounced}
|
|
189
|
-
placeholder={
|
|
195
|
+
placeholder={this.t(".search_dot_dot_dot")}
|
|
190
196
|
type="text"
|
|
191
|
-
ref={this.
|
|
197
|
+
ref={this.tt.searchTextInputRef}
|
|
192
198
|
/>
|
|
193
199
|
}
|
|
194
200
|
{!opened &&
|
|
195
201
|
<>
|
|
196
202
|
{currentOptions.length == 0 &&
|
|
197
203
|
<div style={{color: "grey"}}>
|
|
198
|
-
{placeholder ||
|
|
204
|
+
{placeholder || this.t(".nothing_selected")}
|
|
199
205
|
</div>
|
|
200
206
|
}
|
|
201
207
|
{currentOptions.length == 0 &&
|
|
@@ -255,7 +261,7 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
255
261
|
}
|
|
256
262
|
|
|
257
263
|
isActive() {
|
|
258
|
-
if (this.
|
|
264
|
+
if (this.tt.endOfSelectRef.current) {
|
|
259
265
|
return true
|
|
260
266
|
}
|
|
261
267
|
|
|
@@ -268,16 +274,16 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
268
274
|
if (!defaultValues) return
|
|
269
275
|
|
|
270
276
|
const result = await this.props.options({
|
|
271
|
-
searchValue: digg(this.
|
|
277
|
+
searchValue: digg(this.tt.searchTextInputRef, "current")?.value,
|
|
272
278
|
values: defaultValues
|
|
273
279
|
})
|
|
274
280
|
|
|
275
|
-
this.
|
|
281
|
+
this.setState({currentOptions: this.state.currentOptions.concat(result)})
|
|
276
282
|
}
|
|
277
283
|
|
|
278
284
|
loadOptions = async () => {
|
|
279
285
|
const {options} = this.p
|
|
280
|
-
const searchValue = digg(this.
|
|
286
|
+
const searchValue = digg(this.tt.searchTextInputRef, "current")?.value
|
|
281
287
|
|
|
282
288
|
if (Array.isArray(options)) {
|
|
283
289
|
return this.loadOptionsFromArray(options, searchValue)
|
|
@@ -285,7 +291,7 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
285
291
|
|
|
286
292
|
const loadedOptions = await options({searchValue})
|
|
287
293
|
|
|
288
|
-
this.
|
|
294
|
+
this.setState({loadedOptions})
|
|
289
295
|
}
|
|
290
296
|
|
|
291
297
|
hayaSelectOption({key, loadedOption}) {
|
|
@@ -294,7 +300,7 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
294
300
|
}
|
|
295
301
|
|
|
296
302
|
return <Option
|
|
297
|
-
currentOptions={this.
|
|
303
|
+
currentOptions={this.state.currentOptions}
|
|
298
304
|
icon={this.iconForOption(loadedOption)}
|
|
299
305
|
key={key}
|
|
300
306
|
option={loadedOption}
|
|
@@ -307,7 +313,7 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
307
313
|
const lowerSearchValue = searchValue?.toLowerCase()
|
|
308
314
|
const loadedOptions = options.filter(({text}) => !lowerSearchValue || text.toLowerCase().includes(lowerSearchValue))
|
|
309
315
|
|
|
310
|
-
this.
|
|
316
|
+
this.setState({loadedOptions})
|
|
311
317
|
}
|
|
312
318
|
|
|
313
319
|
onSelectClicked = (e) => {
|
|
@@ -323,23 +329,23 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
323
329
|
}
|
|
324
330
|
}
|
|
325
331
|
|
|
326
|
-
onSearchTextInputChangedDebounced = debounce(this.
|
|
332
|
+
onSearchTextInputChangedDebounced = debounce(this.tt.loadOptions, 200)
|
|
327
333
|
|
|
328
334
|
closeOptions() {
|
|
329
|
-
this.
|
|
335
|
+
this.setState({
|
|
330
336
|
loadedOptions: undefined,
|
|
331
337
|
opened: false
|
|
332
338
|
})
|
|
333
339
|
|
|
334
340
|
if (this.props.onOptionsClosed) {
|
|
335
|
-
this.props.onOptionsClosed({options: this.
|
|
341
|
+
this.props.onOptionsClosed({options: this.state.currentOptions})
|
|
336
342
|
}
|
|
337
343
|
}
|
|
338
344
|
|
|
339
345
|
openOptions() {
|
|
340
346
|
this.setOptionsPositionBelow()
|
|
341
347
|
this.loadOptions()
|
|
342
|
-
this.
|
|
348
|
+
this.setState(
|
|
343
349
|
{opened: true},
|
|
344
350
|
() => {
|
|
345
351
|
this.focusTextInput()
|
|
@@ -348,7 +354,7 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
348
354
|
)
|
|
349
355
|
}
|
|
350
356
|
|
|
351
|
-
focusTextInput = () => digg(this.
|
|
357
|
+
focusTextInput = () => digg(this.tt.searchTextInputRef, "current").focus()
|
|
352
358
|
|
|
353
359
|
setOptionsPosition() {
|
|
354
360
|
if (!this.isActive()) return // Debounce after un-mount handeling.
|
|
@@ -358,7 +364,7 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
358
364
|
}
|
|
359
365
|
|
|
360
366
|
setOptionsPositionAboveIfOutsideScreen() {
|
|
361
|
-
const {optionsContainerRef} = this.
|
|
367
|
+
const {optionsContainerRef} = this.tt
|
|
362
368
|
const {optionsTop} = this.s
|
|
363
369
|
const optionsHeight = digg(optionsContainerRef, "current", "offsetHeight")
|
|
364
370
|
const scrollTop = document.documentElement.scrollTop
|
|
@@ -367,18 +373,18 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
367
373
|
if (window.innerHeight < optionsTotalHeight) {
|
|
368
374
|
this.setOptionsPositionAbove()
|
|
369
375
|
} else {
|
|
370
|
-
this.
|
|
376
|
+
this.setState({optionsVisibility: "visible"})
|
|
371
377
|
}
|
|
372
378
|
}
|
|
373
379
|
|
|
374
380
|
setOptionsPositionAbove() {
|
|
375
|
-
const {optionsContainerRef, currentSelectedRef, searchTextInputRef} = this.
|
|
381
|
+
const {optionsContainerRef, currentSelectedRef, searchTextInputRef} = this.tt
|
|
376
382
|
const optionsHeight = digg(optionsContainerRef, "current", "offsetHeight")
|
|
377
383
|
const position = currentSelectedRef.current.getBoundingClientRect()
|
|
378
384
|
const {left, top, width} = digs(position, "left", "top", "width")
|
|
379
385
|
const optionsTop = top - optionsHeight + 2
|
|
380
386
|
|
|
381
|
-
this.
|
|
387
|
+
this.setState(
|
|
382
388
|
{
|
|
383
389
|
opened: true,
|
|
384
390
|
optionsLeft: left,
|
|
@@ -394,11 +400,11 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
394
400
|
}
|
|
395
401
|
|
|
396
402
|
setOptionsPositionBelow() {
|
|
397
|
-
const {endOfSelectRef, searchTextInputRef} = this.
|
|
403
|
+
const {endOfSelectRef, searchTextInputRef} = this.tt
|
|
398
404
|
const position = endOfSelectRef.current.getBoundingClientRect()
|
|
399
405
|
const {left, top, width} = digs(position, "left", "top", "width")
|
|
400
406
|
|
|
401
|
-
this.
|
|
407
|
+
this.setState(
|
|
402
408
|
{
|
|
403
409
|
opened: true,
|
|
404
410
|
optionsLeft: left,
|
|
@@ -419,7 +425,7 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
419
425
|
}
|
|
420
426
|
}
|
|
421
427
|
|
|
422
|
-
onAnythingResizedDebounced = debounce(this.
|
|
428
|
+
onAnythingResizedDebounced = debounce(this.tt.onAnythingResized, 25)
|
|
423
429
|
|
|
424
430
|
onAnythingScrolled = (e) => {
|
|
425
431
|
if (this.s.opened) {
|
|
@@ -427,10 +433,10 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
427
433
|
}
|
|
428
434
|
}
|
|
429
435
|
|
|
430
|
-
onAnythingScrolledDebounced = debounce(this.
|
|
436
|
+
onAnythingScrolledDebounced = debounce(this.tt.onAnythingScrolled, 25)
|
|
431
437
|
|
|
432
438
|
onWindowClicked = (e) => {
|
|
433
|
-
const {optionsContainerRef} = this.
|
|
439
|
+
const {optionsContainerRef} = this.tt
|
|
434
440
|
const {opened} = this.s
|
|
435
441
|
|
|
436
442
|
// If options are open and a click is made outside of the options container
|
|
@@ -440,7 +446,7 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
440
446
|
}
|
|
441
447
|
|
|
442
448
|
optionsContainer() {
|
|
443
|
-
const {optionsContainerRef} = this.
|
|
449
|
+
const {optionsContainerRef} = this.tt
|
|
444
450
|
const {loadedOptions, optionsLeft, optionsTop, optionsVisibility, optionsWidth, scrollLeft, scrollTop} = this.s
|
|
445
451
|
|
|
446
452
|
return (
|
|
@@ -464,7 +470,7 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
464
470
|
)}
|
|
465
471
|
{loadedOptions?.length === 0 &&
|
|
466
472
|
<div className="haya-select-no-options-container">
|
|
467
|
-
{
|
|
473
|
+
{this.t(".no_options_found")}
|
|
468
474
|
</div>
|
|
469
475
|
}
|
|
470
476
|
</div>
|
|
@@ -477,7 +483,7 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
477
483
|
|
|
478
484
|
const {onChange, toggleOptions} = this.props
|
|
479
485
|
const {multiple} = this.p
|
|
480
|
-
const {currentOptions, toggled} = this.
|
|
486
|
+
const {currentOptions, toggled} = this.state
|
|
481
487
|
const newState = {}
|
|
482
488
|
const existingOption = currentOptions.find((currentOption) => currentOption.value == loadedOption.value)
|
|
483
489
|
const newToggled = {...toggled}
|
|
@@ -514,12 +520,12 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
514
520
|
}
|
|
515
521
|
}
|
|
516
522
|
|
|
517
|
-
this.
|
|
523
|
+
this.setState(newState)
|
|
518
524
|
|
|
519
525
|
if (onChange) {
|
|
520
526
|
const toggles = {}
|
|
521
527
|
|
|
522
|
-
for(const toggleKey in this.
|
|
528
|
+
for(const toggleKey in this.state.toggled) {
|
|
523
529
|
const toggleValue = digg(this.s.toggled, toggleKey)
|
|
524
530
|
const toggleOption = digg(this.p.toggleOptions, toggleValue)
|
|
525
531
|
|
|
@@ -528,7 +534,7 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
528
534
|
|
|
529
535
|
onChange({
|
|
530
536
|
event,
|
|
531
|
-
options: this.
|
|
537
|
+
options: this.state.currentOptions,
|
|
532
538
|
toggles
|
|
533
539
|
})
|
|
534
540
|
}
|
|
@@ -573,4 +579,4 @@ export default class HayaSelect extends React.PureComponent {
|
|
|
573
579
|
</div>
|
|
574
580
|
)
|
|
575
581
|
}
|
|
576
|
-
}
|
|
582
|
+
}))
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import PropTypes from "prop-types"
|
|
2
2
|
import {memo} from "react"
|
|
3
|
+
import {shapeComponent, ShapeComponent} from "set-state-compare/src/shape-component.js"
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
</div>
|
|
9
|
-
)
|
|
10
|
-
}
|
|
5
|
+
export default memo(shapeComponent(class OptionGroup extends ShapeComponent {
|
|
6
|
+
static propTypes = {
|
|
7
|
+
option: PropTypes.object.isRequired
|
|
8
|
+
}
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
render() {
|
|
11
|
+
return (
|
|
12
|
+
<div className="haya-select--option-group">
|
|
13
|
+
{option.text}
|
|
14
|
+
</div>
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
}))
|
package/src/select/option.jsx
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
import PropTypes from "prop-types"
|
|
2
|
-
import {memo
|
|
3
|
-
import
|
|
2
|
+
import {memo} from "react"
|
|
3
|
+
import {shapeComponent, ShapeComponent} from "set-state-compare/src/shape-component.js"
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
export default memo(shapeComponent(class Option extends ShapeComponent {
|
|
6
|
+
static propTypes = {
|
|
7
|
+
currentOptions: PropTypes.array.isRequired,
|
|
8
|
+
disabled: PropTypes.bool,
|
|
9
|
+
icon: PropTypes.string,
|
|
10
|
+
onOptionClicked: PropTypes.func.isRequired,
|
|
11
|
+
option: PropTypes.object.isRequired,
|
|
12
|
+
presentOption: PropTypes.func.isRequired
|
|
13
|
+
}
|
|
9
14
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
className="haya-select-option"
|
|
13
|
-
data-disabled={Boolean(s.p.option.disabled)}
|
|
14
|
-
data-selected={selected}
|
|
15
|
-
data-value={s.p.option.value}
|
|
16
|
-
onClick={onClick}
|
|
17
|
-
>
|
|
18
|
-
{props.presentOption(s.p.option)}
|
|
19
|
-
</div>
|
|
20
|
-
)
|
|
21
|
-
}
|
|
15
|
+
render() {
|
|
16
|
+
const selected = Boolean(this.props.currentOptions.find((currentOption) => currentOption.value == this.props.option.value))
|
|
22
17
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
18
|
+
return (
|
|
19
|
+
<div
|
|
20
|
+
className="haya-select-option"
|
|
21
|
+
data-disabled={Boolean(this.props.option.disabled)}
|
|
22
|
+
data-selected={selected}
|
|
23
|
+
data-value={this.props.option.value}
|
|
24
|
+
onClick={this.onClick}
|
|
25
|
+
>
|
|
26
|
+
{this.props.presentOption(this.props.option)}
|
|
27
|
+
</div>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
31
30
|
|
|
32
|
-
|
|
31
|
+
onClick = (e) => this.props.onOptionClicked(e, this.props.option)
|
|
32
|
+
}))
|