haya-select 1.0.5 → 1.0.8

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.
@@ -0,0 +1,9 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: npm
4
+ directory: "/"
5
+ schedule:
6
+ interval: weekly
7
+ time: "01:00"
8
+ timezone: Europe/Copenhagen
9
+ open-pull-requests-limit: 99
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "haya-select",
3
- "version": "1.0.5",
3
+ "version": "1.0.8",
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
  }
@@ -14,39 +14,6 @@ const nameForComponentWithMultiple = (component) => {
14
14
  return name
15
15
  }
16
16
 
17
- const presentOption = (currentValue) => {
18
- if (currentValue.text) return currentValue.text
19
-
20
- if (currentValue.html) {
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
17
  export default class CustomSelect extends React.PureComponent {
51
18
  static defaultProps = {
52
19
  multiple: false,
@@ -63,7 +30,12 @@ export default class CustomSelect extends React.PureComponent {
63
30
  multiple: PropTypes.bool.isRequired,
64
31
  onChange: PropTypes.func,
65
32
  options: PropTypes.oneOfType([PropTypes.array, PropTypes.func]).isRequired,
66
- search: PropTypes.bool.isRequired
33
+ search: PropTypes.bool.isRequired,
34
+ toggleOptions: PropTypes.arrayOf(PropTypes.shape({
35
+ icon: PropTypes.string.isRequired,
36
+ label: PropTypes.string.isRequired,
37
+ value: PropTypes.string.isRequired
38
+ }))
67
39
  }
68
40
 
69
41
  endOfSelectRef = React.createRef()
@@ -78,7 +50,8 @@ export default class CustomSelect extends React.PureComponent {
78
50
  optionsTop: undefined,
79
51
  optionsWidth: undefined,
80
52
  scrollLeft: undefined,
81
- scrollTop: undefined
53
+ scrollTop: undefined,
54
+ toggled: {}
82
55
  }
83
56
 
84
57
  defaultCurrentOptions() {
@@ -106,16 +79,16 @@ export default class CustomSelect extends React.PureComponent {
106
79
  }
107
80
 
108
81
  componentDidMount() {
109
- const {attribute, defaultValuesFromOptions, model, options} = this.props
82
+ const {attribute, defaultValue, defaultValuesFromOptions, model, options} = this.props
110
83
 
111
- if ((defaultValuesFromOptions || (attribute && model)) && typeof options == "function") {
84
+ if (((defaultValue || defaultValuesFromOptions) || (attribute && model)) && typeof options == "function") {
112
85
  this.loadDefaultValuesFromOptionsCallback()
113
86
  }
114
87
  }
115
88
 
116
89
  render() {
117
90
  const {endOfSelectRef} = digs(this, "endOfSelectRef")
118
- const {attribute, className, defaultValue, defaultValues, model, multiple, onChange, options, search, ...restProps} = this.props
91
+ const {attribute, className, defaultValue, defaultValues, model, multiple, onChange, options, search, toggleOptions, ...restProps} = this.props
119
92
  const {currentOptions, opened} = digs(this.state, "currentOptions", "opened")
120
93
  const BodyPortal = config.getBodyPortal()
121
94
 
@@ -158,7 +131,7 @@ export default class CustomSelect extends React.PureComponent {
158
131
  type="hidden"
159
132
  value={digg(currentOption, "value")}
160
133
  />
161
- {presentOption(currentOption)}
134
+ {this.presentOption(currentOption)}
162
135
  </div>
163
136
  )}
164
137
  </>
@@ -170,9 +143,10 @@ export default class CustomSelect extends React.PureComponent {
170
143
  }
171
144
 
172
145
  defaultValues () {
173
- const {attribute, defaultValuesFromOptions, model} = this.props
146
+ const {attribute, defaultValue, defaultValuesFromOptions, model} = this.props
174
147
 
175
148
  if (defaultValuesFromOptions) return defaultValuesFromOptions
149
+ if (defaultValue) return defaultValue
176
150
 
177
151
  if (attribute && model) {
178
152
  if (!(attribute in model)) throw new Error(`No such attribute on ${model.modelClassData().name}: ${attribute}`)
@@ -209,6 +183,24 @@ export default class CustomSelect extends React.PureComponent {
209
183
  this.setState({loadedOptions})
210
184
  }
211
185
 
186
+ hayaSelectOption({key, loadedOption}) {
187
+ const {currentOptions} = digs(this.state, "currentOptions")
188
+ const selected = Boolean(currentOptions.find((currentOption) => currentOption.value == loadedOption.value))
189
+
190
+ return (
191
+ <div
192
+ className="haya-select-option"
193
+ data-selected={selected}
194
+ data-value={digg(loadedOption, "value")}
195
+ key={key}
196
+ onClick={(e) => this.onOptionClicked(e, loadedOption)}
197
+ style={{cursor: "pointer"}}
198
+ >
199
+ {this.presentOption(loadedOption)}
200
+ </div>
201
+ )
202
+ }
203
+
212
204
  loadOptionsFromArray(options, searchValue) {
213
205
  const lowerSearchValue = searchValue?.toLowerCase()
214
206
  const loadedOptions = options.filter(({text}) => !lowerSearchValue || text.toLowerCase().includes(lowerSearchValue))
@@ -273,7 +265,6 @@ export default class CustomSelect extends React.PureComponent {
273
265
  optionsContainer() {
274
266
  const {optionsContainerRef} = digs(this, "endOfSelectRef", "optionsContainerRef")
275
267
  const {
276
- currentOptions,
277
268
  loadedOptions,
278
269
  optionsLeft,
279
270
  optionsTop,
@@ -282,7 +273,6 @@ export default class CustomSelect extends React.PureComponent {
282
273
  scrollTop
283
274
  } = digs(
284
275
  this.state,
285
- "currentOptions",
286
276
  "loadedOptions",
287
277
  "currentOptions",
288
278
  "opened",
@@ -306,12 +296,10 @@ export default class CustomSelect extends React.PureComponent {
306
296
  >
307
297
  <EventListener event="click" onCalled={this.onWindowClicked} target={window} />
308
298
  {loadedOptions?.map((loadedOption) =>
309
- <LoadedOption
310
- currentOptions={currentOptions}
311
- key={`loaded-option-${digg(loadedOption.value)}`}
312
- loadedOption={loadedOption}
313
- onClick={this.onOptionClicked}
314
- />
299
+ this.hayaSelectOption({
300
+ key: `loaded-option-${digg(loadedOption.value)}`,
301
+ loadedOption
302
+ })
315
303
  )}
316
304
  {loadedOptions?.length === 0 &&
317
305
  <div className="haya-select-no-options-container">
@@ -326,26 +314,87 @@ export default class CustomSelect extends React.PureComponent {
326
314
  e.preventDefault()
327
315
  e.stopPropagation()
328
316
 
329
- const {onChange} = this.props
317
+ const {onChange, toggleOptions} = this.props
330
318
  const {multiple} = digs(this.props, "multiple")
331
319
 
332
- this.setState((prevState) => {
333
- const existingOption = prevState.currentOptions.find((currentOption) => currentOption.value == loadedOption.value)
320
+ this.setState(
321
+ (prevState) => {
322
+ const existingOption = prevState.currentOptions.find((currentOption) => currentOption.value == loadedOption.value)
323
+ const newState = {}
324
+ const {toggled} = digs(prevState, "toggled")
325
+ const newToggled = {...toggled}
326
+
327
+ if (existingOption) {
328
+ if (toggleOptions) {
329
+ const currentIndex = digg(toggled, loadedOption.value)
330
+
331
+ if (currentIndex >= (toggleOptions.length - 1)) {
332
+ delete newToggled[loadedOption.value]
333
+
334
+ newState.currentOptions = prevState.currentOptions.filter((currentOption) => currentOption.value != loadedOption.value)
335
+ } else {
336
+ newToggled[loadedOption.value] = toggled[loadedOption.value] + 1
337
+ }
338
+
339
+ newState.toggled = newToggled
340
+ } else {
341
+ newState.currentOptions = prevState.currentOptions.filter((currentOption) => currentOption.value != loadedOption.value)
342
+ }
343
+ } else {
344
+ if (toggleOptions) {
345
+ newToggled[loadedOption.value] = 0
346
+ newState.toggled = newToggled
347
+ }
334
348
 
335
- if (existingOption) {
336
- return {
337
- currentOptions: prevState.currentOptions.filter((currentOption) => currentOption.value != loadedOption.value)
349
+ if (multiple || toggleOptions) {
350
+ newState.currentOptions = prevState.currentOptions.concat([loadedOption])
351
+ } else {
352
+ newState.currentOptions = [loadedOption]
353
+ }
338
354
  }
339
- } else {
340
- if (multiple) {
341
- return {currentOptions: prevState.currentOptions.concat([loadedOption])}
342
- } else {
343
- return {currentOptions: [loadedOption]}
355
+
356
+ return newState
357
+ },
358
+ () => {
359
+ if (onChange) {
360
+ const toggles = {}
361
+
362
+ for(const toggleKey in this.state.toggled) {
363
+ const toggleValue = digg(this, "state", "toggled", toggleKey)
364
+ const toggleOption = digg(this, "props", "toggleOptions", toggleValue)
365
+
366
+ toggles[toggleKey] = toggleOption
367
+ }
368
+
369
+ onChange({
370
+ options: this.state.currentOptions,
371
+ toggles
372
+ })
344
373
  }
345
374
  }
346
- })
375
+ )
347
376
 
348
377
  if (!multiple) this.closeOptions()
349
- if (onChange) onChange(loadedOption)
378
+
379
+ }
380
+
381
+ presentOption = (currentValue) => {
382
+ const {toggleOptions} = this.props
383
+ const {toggled} = digs(this.state, "toggled")
384
+
385
+ return (
386
+ <div>
387
+ {toggleOptions && !(currentValue.value in toggled) &&
388
+ <i className="fa fa-fw" />
389
+ }
390
+ {toggleOptions && (currentValue.value in toggled) &&
391
+ <i className={`fa fa-fw fa-${toggleOptions[toggled[currentValue.value]].icon}`} />
392
+ }
393
+ {currentValue.text}
394
+ {("html" in currentValue) &&
395
+ <div dangerouslySetInnerHTML={{__html: digg(currentValue, "html")}} />
396
+ }
397
+ </div>
398
+ )
350
399
  }
351
400
  }