haya-select 1.0.27 → 1.0.29

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "haya-select",
3
- "version": "1.0.27",
3
+ "version": "1.0.29",
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.27"
16
+ "set-state-compare": "^1.0.42"
17
17
  },
18
18
  "peerDependencies": {
19
19
  "prop-types": ">= 15.7.2",
@@ -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 React from "react"
13
- import {anythingDifferent, Shape} from "set-state-compare"
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 React.PureComponent {
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.shape)
55
- t = fetchingObject(this)
56
-
57
- endOfSelectRef = React.createRef()
58
- optionsContainerRef = React.createRef()
59
- currentSelectedRef = React.createRef()
60
- searchTextInputRef = React.createRef()
61
-
62
- shape = new Shape(this, {
63
- currentOptions: this.defaultCurrentOptions(),
64
- loadedOptions: this.defaultLoadedOptions(),
65
- opened: false,
66
- optionsLeft: undefined,
67
- optionsPlacement: undefined,
68
- optionsTop: undefined,
69
- optionsVisibility: undefined,
70
- optionsWidth: undefined,
71
- scrollLeft: undefined,
72
- scrollTop: undefined,
73
- toggled: this.defaultToggled()
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.t.onAnythingResizedDebounced, true)
113
- window.addEventListener("scroll", this.t.onAnythingScrolledDebounced, true)
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.shape.currentOptions, newCurrentOptions)) {
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.shape.toggled, newToggled)) {
136
+ if (anythingDifferent(this.state.toggled, newToggled)) {
131
137
  newState.toggled = newToggled
132
138
  }
133
139
  }
134
140
 
135
- this.shape.set(newState)
141
+ this.setState(newState)
136
142
  }
137
143
 
138
144
  componentWillUnmount() {
139
- window.removeEventListener("resize", this.t.onAnythingResizedDebounced)
140
- window.removeEventListener("scroll", this.t.onAnythingScrolledDebounced)
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.t
150
+ const {currentSelectedRef, endOfSelectRef, onSelectClicked, onSearchTextInputChangedDebounced} = this.tt
145
151
  const {
146
152
  attribute,
147
153
  className,
@@ -151,6 +157,7 @@ export default class HayaSelect extends React.PureComponent {
151
157
  id,
152
158
  model,
153
159
  multiple,
160
+ name,
154
161
  onChange,
155
162
  onOptionsClosed,
156
163
  options,
@@ -185,18 +192,26 @@ export default class HayaSelect extends React.PureComponent {
185
192
  <input
186
193
  className="haya-select-search-text-input"
187
194
  onChange={onSearchTextInputChangedDebounced}
188
- placeholder={I18n.t("haya_select.search_dot_dot_dot")}
195
+ placeholder={this.t(".search_dot_dot_dot")}
189
196
  type="text"
190
- ref={this.t.searchTextInputRef}
197
+ ref={this.tt.searchTextInputRef}
191
198
  />
192
199
  }
193
200
  {!opened &&
194
201
  <>
195
202
  {currentOptions.length == 0 &&
196
203
  <div style={{color: "grey"}}>
197
- {placeholder || I18n.t("haya_select.nothing_selected")}
204
+ {placeholder || this.t(".nothing_selected")}
198
205
  </div>
199
206
  }
207
+ {currentOptions.length == 0 &&
208
+ <input
209
+ id={idForComponent(this)}
210
+ name={nameForComponentWithMultiple(this)}
211
+ type="hidden"
212
+ value=""
213
+ />
214
+ }
200
215
  {currentOptions.map((currentOption) =>
201
216
  <div className="current-option" key={currentOption.key || `current-value-${currentOption.value}`}>
202
217
  {currentOption.type == "group" &&
@@ -246,7 +261,7 @@ export default class HayaSelect extends React.PureComponent {
246
261
  }
247
262
 
248
263
  isActive() {
249
- if (this.t.endOfSelectRef.current) {
264
+ if (this.tt.endOfSelectRef.current) {
250
265
  return true
251
266
  }
252
267
 
@@ -259,16 +274,16 @@ export default class HayaSelect extends React.PureComponent {
259
274
  if (!defaultValues) return
260
275
 
261
276
  const result = await this.props.options({
262
- searchValue: digg(this.t.searchTextInputRef, "current")?.value,
277
+ searchValue: digg(this.tt.searchTextInputRef, "current")?.value,
263
278
  values: defaultValues
264
279
  })
265
280
 
266
- this.shape.set({currentOptions: this.shape.currentOptions.concat(result)})
281
+ this.setState({currentOptions: this.state.currentOptions.concat(result)})
267
282
  }
268
283
 
269
284
  loadOptions = async () => {
270
285
  const {options} = this.p
271
- const searchValue = digg(this.t.searchTextInputRef, "current")?.value
286
+ const searchValue = digg(this.tt.searchTextInputRef, "current")?.value
272
287
 
273
288
  if (Array.isArray(options)) {
274
289
  return this.loadOptionsFromArray(options, searchValue)
@@ -276,7 +291,7 @@ export default class HayaSelect extends React.PureComponent {
276
291
 
277
292
  const loadedOptions = await options({searchValue})
278
293
 
279
- this.shape.set({loadedOptions})
294
+ this.setState({loadedOptions})
280
295
  }
281
296
 
282
297
  hayaSelectOption({key, loadedOption}) {
@@ -285,7 +300,7 @@ export default class HayaSelect extends React.PureComponent {
285
300
  }
286
301
 
287
302
  return <Option
288
- currentOptions={this.shape.currentOptions}
303
+ currentOptions={this.state.currentOptions}
289
304
  icon={this.iconForOption(loadedOption)}
290
305
  key={key}
291
306
  option={loadedOption}
@@ -298,7 +313,7 @@ export default class HayaSelect extends React.PureComponent {
298
313
  const lowerSearchValue = searchValue?.toLowerCase()
299
314
  const loadedOptions = options.filter(({text}) => !lowerSearchValue || text.toLowerCase().includes(lowerSearchValue))
300
315
 
301
- this.shape.set({loadedOptions})
316
+ this.setState({loadedOptions})
302
317
  }
303
318
 
304
319
  onSelectClicked = (e) => {
@@ -314,23 +329,23 @@ export default class HayaSelect extends React.PureComponent {
314
329
  }
315
330
  }
316
331
 
317
- onSearchTextInputChangedDebounced = debounce(this.t.loadOptions, 200)
332
+ onSearchTextInputChangedDebounced = debounce(this.tt.loadOptions, 200)
318
333
 
319
334
  closeOptions() {
320
- this.shape.set({
335
+ this.setState({
321
336
  loadedOptions: undefined,
322
337
  opened: false
323
338
  })
324
339
 
325
340
  if (this.props.onOptionsClosed) {
326
- this.props.onOptionsClosed({options: this.shape.currentOptions})
341
+ this.props.onOptionsClosed({options: this.state.currentOptions})
327
342
  }
328
343
  }
329
344
 
330
345
  openOptions() {
331
346
  this.setOptionsPositionBelow()
332
347
  this.loadOptions()
333
- this.shape.set(
348
+ this.setState(
334
349
  {opened: true},
335
350
  () => {
336
351
  this.focusTextInput()
@@ -339,7 +354,7 @@ export default class HayaSelect extends React.PureComponent {
339
354
  )
340
355
  }
341
356
 
342
- focusTextInput = () => digg(this.t.searchTextInputRef, "current").focus()
357
+ focusTextInput = () => digg(this.tt.searchTextInputRef, "current").focus()
343
358
 
344
359
  setOptionsPosition() {
345
360
  if (!this.isActive()) return // Debounce after un-mount handeling.
@@ -349,7 +364,7 @@ export default class HayaSelect extends React.PureComponent {
349
364
  }
350
365
 
351
366
  setOptionsPositionAboveIfOutsideScreen() {
352
- const {optionsContainerRef} = this.t
367
+ const {optionsContainerRef} = this.tt
353
368
  const {optionsTop} = this.s
354
369
  const optionsHeight = digg(optionsContainerRef, "current", "offsetHeight")
355
370
  const scrollTop = document.documentElement.scrollTop
@@ -358,18 +373,18 @@ export default class HayaSelect extends React.PureComponent {
358
373
  if (window.innerHeight < optionsTotalHeight) {
359
374
  this.setOptionsPositionAbove()
360
375
  } else {
361
- this.shape.set({optionsVisibility: "visible"})
376
+ this.setState({optionsVisibility: "visible"})
362
377
  }
363
378
  }
364
379
 
365
380
  setOptionsPositionAbove() {
366
- const {optionsContainerRef, currentSelectedRef, searchTextInputRef} = this.t
381
+ const {optionsContainerRef, currentSelectedRef, searchTextInputRef} = this.tt
367
382
  const optionsHeight = digg(optionsContainerRef, "current", "offsetHeight")
368
383
  const position = currentSelectedRef.current.getBoundingClientRect()
369
384
  const {left, top, width} = digs(position, "left", "top", "width")
370
385
  const optionsTop = top - optionsHeight + 2
371
386
 
372
- this.shape.set(
387
+ this.setState(
373
388
  {
374
389
  opened: true,
375
390
  optionsLeft: left,
@@ -385,11 +400,11 @@ export default class HayaSelect extends React.PureComponent {
385
400
  }
386
401
 
387
402
  setOptionsPositionBelow() {
388
- const {endOfSelectRef, searchTextInputRef} = this.t
403
+ const {endOfSelectRef, searchTextInputRef} = this.tt
389
404
  const position = endOfSelectRef.current.getBoundingClientRect()
390
405
  const {left, top, width} = digs(position, "left", "top", "width")
391
406
 
392
- this.shape.set(
407
+ this.setState(
393
408
  {
394
409
  opened: true,
395
410
  optionsLeft: left,
@@ -410,7 +425,7 @@ export default class HayaSelect extends React.PureComponent {
410
425
  }
411
426
  }
412
427
 
413
- onAnythingResizedDebounced = debounce(this.t.onAnythingResized, 25)
428
+ onAnythingResizedDebounced = debounce(this.tt.onAnythingResized, 25)
414
429
 
415
430
  onAnythingScrolled = (e) => {
416
431
  if (this.s.opened) {
@@ -418,10 +433,10 @@ export default class HayaSelect extends React.PureComponent {
418
433
  }
419
434
  }
420
435
 
421
- onAnythingScrolledDebounced = debounce(this.t.onAnythingScrolled, 25)
436
+ onAnythingScrolledDebounced = debounce(this.tt.onAnythingScrolled, 25)
422
437
 
423
438
  onWindowClicked = (e) => {
424
- const {optionsContainerRef} = this.t
439
+ const {optionsContainerRef} = this.tt
425
440
  const {opened} = this.s
426
441
 
427
442
  // If options are open and a click is made outside of the options container
@@ -431,7 +446,7 @@ export default class HayaSelect extends React.PureComponent {
431
446
  }
432
447
 
433
448
  optionsContainer() {
434
- const {optionsContainerRef} = this.t
449
+ const {optionsContainerRef} = this.tt
435
450
  const {loadedOptions, optionsLeft, optionsTop, optionsVisibility, optionsWidth, scrollLeft, scrollTop} = this.s
436
451
 
437
452
  return (
@@ -455,7 +470,7 @@ export default class HayaSelect extends React.PureComponent {
455
470
  )}
456
471
  {loadedOptions?.length === 0 &&
457
472
  <div className="haya-select-no-options-container">
458
- {I18n.t("haya_select.no_options_found")}
473
+ {this.t(".no_options_found")}
459
474
  </div>
460
475
  }
461
476
  </div>
@@ -468,7 +483,7 @@ export default class HayaSelect extends React.PureComponent {
468
483
 
469
484
  const {onChange, toggleOptions} = this.props
470
485
  const {multiple} = this.p
471
- const {currentOptions, toggled} = this.shape
486
+ const {currentOptions, toggled} = this.state
472
487
  const newState = {}
473
488
  const existingOption = currentOptions.find((currentOption) => currentOption.value == loadedOption.value)
474
489
  const newToggled = {...toggled}
@@ -505,12 +520,12 @@ export default class HayaSelect extends React.PureComponent {
505
520
  }
506
521
  }
507
522
 
508
- this.shape.set(newState)
523
+ this.setState(newState)
509
524
 
510
525
  if (onChange) {
511
526
  const toggles = {}
512
527
 
513
- for(const toggleKey in this.shape.toggled) {
528
+ for(const toggleKey in this.state.toggled) {
514
529
  const toggleValue = digg(this.s.toggled, toggleKey)
515
530
  const toggleOption = digg(this.p.toggleOptions, toggleValue)
516
531
 
@@ -519,7 +534,7 @@ export default class HayaSelect extends React.PureComponent {
519
534
 
520
535
  onChange({
521
536
  event,
522
- options: this.shape.currentOptions,
537
+ options: this.state.currentOptions,
523
538
  toggles
524
539
  })
525
540
  }
@@ -564,4 +579,4 @@ export default class HayaSelect extends React.PureComponent {
564
579
  </div>
565
580
  )
566
581
  }
567
- }
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
- const OptionGroup = ({option}) => {
5
- return (
6
- <div className="haya-select--option-group">
7
- {option.text}
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
- OptionGroup.propTypes = {
13
- option: PropTypes.object.isRequired
14
- }
15
-
16
- export default memo(OptionGroup)
10
+ render() {
11
+ return (
12
+ <div className="haya-select--option-group">
13
+ {option.text}
14
+ </div>
15
+ )
16
+ }
17
+ }))
@@ -1,32 +1,32 @@
1
1
  import PropTypes from "prop-types"
2
- import {memo, useMemo} from "react"
3
- import useShape from "set-state-compare/src/use-shape.js"
2
+ import {memo} from "react"
3
+ import {shapeComponent, ShapeComponent} from "set-state-compare/src/shape-component.js"
4
4
 
5
- const Option = (props) => {
6
- const s = useShape(props)
7
- const onClick = useCallback((e) => s.p.onOptionClicked(e, s.p.option), [])
8
- const selected = Boolean(s.p.currentOptions.find((currentOption) => currentOption.value == s.p.option.value))
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
- return (
11
- <div
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
- Option.propTypes = {
24
- currentOptions: PropTypes.array.isRequired,
25
- disabled: PropTypes.bool,
26
- icon: PropTypes.string,
27
- onOptionClicked: PropTypes.func.isRequired,
28
- option: PropTypes.object.isRequired,
29
- presentOption: PropTypes.func.isRequired
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
+ {props.presentOption(this.props.option)}
27
+ </div>
28
+ )
29
+ }
31
30
 
32
- export default memo(Option)
31
+ onClick = (e) => this.props.onOptionClicked(e, this.props.option)
32
+ }))