1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
/**
* @prettier
*/
import React from "react"
import Im from "immutable"
import PropTypes from "prop-types"
import ImPropTypes from "react-immutable-proptypes"
export default class ExamplesSelect extends React.PureComponent {
static propTypes = {
examples: ImPropTypes.map.isRequired,
onSelect: PropTypes.func,
currentExampleKey: PropTypes.string,
isModifiedValueAvailable: PropTypes.bool,
isValueModified: PropTypes.bool,
showLabels: PropTypes.bool,
}
static defaultProps = {
examples: Im.Map({}),
onSelect: (...args) =>
console.log( // eslint-disable-line no-console
// FIXME: remove before merging to master...
`DEBUG: ExamplesSelect was not given an onSelect callback`,
...args
),
currentExampleKey: null,
showLabels: true,
}
_onSelect = (key, { isSyntheticChange = false } = {}) => {
if (typeof this.props.onSelect === "function") {
this.props.onSelect(key, {
isSyntheticChange,
})
}
}
_onDomSelect = e => {
if (typeof this.props.onSelect === "function") {
const element = e.target.selectedOptions[0]
const key = element.getAttribute("value")
this._onSelect(key, {
isSyntheticChange: false,
})
}
}
getCurrentExample = () => {
const { examples, currentExampleKey } = this.props
const currentExamplePerProps = examples.get(currentExampleKey)
const firstExamplesKey = examples.keySeq().first()
const firstExample = examples.get(firstExamplesKey)
return currentExamplePerProps || firstExample || Map({})
}
componentDidMount() {
// this is the not-so-great part of ExamplesSelect... here we're
// artificially kicking off an onSelect event in order to set a default
// value in state. the consumer has the option to avoid this by checking
// `isSyntheticEvent`, but we should really be doing this in a selector.
// TODO: clean this up
// FIXME: should this only trigger if `currentExamplesKey` is nullish?
const { onSelect, examples } = this.props
if (typeof onSelect === "function") {
const firstExample = examples.first()
const firstExampleKey = examples.keyOf(firstExample)
this._onSelect(firstExampleKey, {
isSyntheticChange: true,
})
}
}
UNSAFE_componentWillReceiveProps(nextProps) {
const { currentExampleKey, examples } = nextProps
if (examples !== this.props.examples && !examples.has(currentExampleKey)) {
// examples have changed from under us, and the currentExampleKey is no longer
// valid.
const firstExample = examples.first()
const firstExampleKey = examples.keyOf(firstExample)
this._onSelect(firstExampleKey, {
isSyntheticChange: true,
})
}
}
render() {
const {
examples,
currentExampleKey,
isValueModified,
isModifiedValueAvailable,
showLabels,
} = this.props
return (
<div className="examples-select">
{
showLabels ? (
<span className="examples-select__section-label">Examples: </span>
) : null
}
<select
className="examples-select-element"
onChange={this._onDomSelect}
value={
isModifiedValueAvailable && isValueModified
? "__MODIFIED__VALUE__"
: (currentExampleKey || "")
}
>
{isModifiedValueAvailable ? (
<option value="__MODIFIED__VALUE__">[Modified value]</option>
) : null}
{examples
.map((example, exampleName) => {
return (
<option
key={exampleName} // for React
value={exampleName} // for matching to select's `value`
>
{example.get("summary") || exampleName}
</option>
)
})
.valueSeq()}
</select>
</div>
)
}
}
|