UNPKG

6.77 kBJavaScriptView Raw
1import React from 'react';
2import {render} from 'react-dom';
3import {connect} from 'react-redux';
4import {createStore} from 'redux';
5import actions from './actions';
6import {reducers} from './reducers';
7
8
9const NoItems = () => {
10
11 return (
12 <div
13 key={null}
14 className="item item-no-results"
15 >No results found</div>
16 );
17};
18
19const Presentation = ({...props}) => {
20 let topBar;
21 const visibleItems = Object.keys(props.visibleItems).map((item) => {
22 return (
23 <div
24 onClick={() => {
25 props.submit({
26 selected: item,
27 selectedItemLabel: props.items[item]
28 });
29 focus();
30 }}
31 key={item}
32 className={
33 (item == props.currentlyHighlighted) ? 'item item-selected' : 'item'
34 }
35 >
36 {props.items[item]}
37 </div>
38 )
39
40 });
41 const focus = () => {
42 if (topBar)
43 topBar.focus();
44 };
45 return (
46 <div
47 className="select-react-redux-container"
48 ref={(input) => {
49 if (props.initialRender && input) {
50 props.initialRenderFalse();
51 document.addEventListener('click', function (event) {
52 if (!input.contains(event.target)) {
53 props.refresh();
54 }
55 });
56
57 }
58
59 }}>
60 <a href="#"
61 tabIndex={props.tabIndex}
62 onClick={props.topBarOnClick}
63 onKeyPress={props.linkOnKeyPress}
64 onKeyDown={e => {
65 if (e.key.indexOf('Arrow') == 0) {
66 props.linkOnKeyPress(e)
67 }
68 }}
69 className={props.open ? 'selected selected-open' : 'selected'}
70 ref={function (input) {
71 if (input && props.open) {
72 topBar = input;
73 focus();
74 }
75 }}
76 >
77 <div
78 className={Object.keys(props.items).length == 0 ? 'top-bar top-bar-empty' : 'top-bar'}>
79 { Object.keys(props.items).length == 0 ? 'No options available' :
80 props.selectedItemLabel
81 ? props.selectedItemLabel
82 : 'Please select...'}
83 </div>
84 </a>
85
86 <div className={props.open ? 'results-container open' : 'results-container' }>
87 <div className="input-container">
88 <input
89 type="text"
90 autoCorrect="off"
91 autoCapitalize="off"
92 spellCheck="false"
93 autoComplete="off"
94 ref={(item) => {
95 if (item && props.open) {
96 item.focus()
97 }
98 }}
99 value={props.visibilityFilter}
100 onKeyPress={(e) => {
101 if (e.key === 'Enter' && props.open) {
102 props.submit({
103 selected: props.currentlyHighlighted,
104 selectedItemLabel: props.items[props.currentlyHighlighted]
105 });
106 focus();
107 }
108 }}
109 onChange={props.inputOnChange}
110 onKeyDown={(e) => {
111 props.inputOnKeyDown(e);
112 if (e.key == 'Escape') {
113 focus();
114 }
115 }}
116 />
117 </div>
118 {visibleItems.length > 0 ? visibleItems : <NoItems/>}
119 </div>
120 </div>
121 );
122};
123
124export const Select = ({items, selected = null, tabIndex = null, onChange}) => {
125
126 const store = createStore(reducers);
127
128 store.dispatch({type: '@@redux/INIT'});
129
130 window.store = store;
131
132 store.dispatch({type: actions.SET_ITEMS, payload: items});
133
134 if (selected) {
135 store.dispatch({
136 type: actions.SET_SELECTED, payload: {
137 selected: selected,
138 selectedItemLabel: items[selected]
139 }
140 });
141 }
142
143 if (tabIndex) {
144 store.dispatch({type: actions.SET_TABINDEX, payload: tabIndex})
145 }
146
147 const mapStateToProps = (state = {}) => {
148 return state;
149 };
150
151 const mapDispatchToProps = (dispatch) => {
152 return {
153 submit: (item) => {
154 if (item.selected) {
155 dispatch({type: actions.SET_SELECTED, payload: item});
156 dispatch({type: actions.SET_OPEN, payload: false});
157 dispatch({type: actions.SET_FILTER, payload: ''});
158 onChange(item.selected);
159 }
160 },
161 linkOnKeyPress: (e) => {
162 if (e.key != 'Escape') {
163 dispatch({type: actions.SET_OPEN, payload: true});
164 dispatch({type: actions.SET_FILTER, payload: ''});
165 }
166 },
167
168 inputOnChange: (e) => {
169 dispatch({type: actions.SET_FILTER, payload: e.target.value})
170 },
171 inputOnKeyDown: (e) => {
172 if (e.key === 'ArrowDown') {
173 dispatch({type: actions.SET_NEXT_HIGHLIGHTED, payload: false})
174 }
175
176 if (e.key === 'ArrowUp') {
177 dispatch({type: actions.SET_PREV_HIGHLIGHTED, payload: false})
178 }
179
180 if (e.key === 'Escape') {
181 dispatch({type: actions.SET_OPEN, payload: false});
182 dispatch({type: actions.SET_FILTER, payload: ''});
183 }
184 },
185 topBarOnClick: () => {
186 dispatch({type: actions.TOGGLE_OPEN});
187 },
188
189 initialRenderFalse: () => {
190 dispatch({type: actions.SET_INITIAL_RENDER_FALSE});
191 },
192 refresh: () => {
193 dispatch({type: actions.SET_OPEN, payload: false});
194 dispatch({type: actions.SET_FILTER, payload: ''});
195 }
196 }
197 };
198
199 const SelectWithStore = connect(
200 mapStateToProps,
201 mapDispatchToProps
202 )(Presentation);
203
204 return (
205 <SelectWithStore store={store}/>
206 )
207};