@spothero/ui 15.1.0 → 15.1.1
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 -3
- package/styles/Alert/Alert.jsx +0 -45
- package/styles/Alert/Alert.spec.js +0 -85
- package/styles/AutoSuggestInput/AutoSuggestInput.jsx +0 -429
- package/styles/AutoSuggestInput/AutoSuggestInput.spec.js +0 -132
- package/styles/AutoSuggestInput/AutoSuggestItem.jsx +0 -61
- package/styles/AutoSuggestInput/AutoSuggestList.jsx +0 -85
- package/styles/Badge/Badge.jsx +0 -24
- package/styles/Badge/Badge.spec.js +0 -43
- package/styles/Chart/Chart.jsx +0 -185
- package/styles/Chart/Chart.spec.js +0 -369
- package/styles/Checkbox/Checkbox.jsx +0 -159
- package/styles/Checkbox/Checkbox.spec.js +0 -142
- package/styles/DateTime/DatePicker.jsx +0 -281
- package/styles/DateTime/DatePicker.spec.js +0 -186
- package/styles/DateTime/DatePickerCalendar.jsx +0 -170
- package/styles/DateTime/DatePickerCalendarNavigation.jsx +0 -44
- package/styles/DateTime/DatePickerCalendarWithRange.jsx +0 -218
- package/styles/DateTime/DateTimePicker.jsx +0 -266
- package/styles/DateTime/DateTimePicker.spec.js +0 -60
- package/styles/DateTime/DateTimeRangePicker.jsx +0 -629
- package/styles/DateTime/DateTimeRangePicker.spec.js +0 -425
- package/styles/DateTime/TimePicker.jsx +0 -158
- package/styles/DateTime/TimePicker.spec.js +0 -148
- package/styles/DateTime/date-time-assertions.js +0 -89
- package/styles/DateTime/index.js +0 -6
- package/styles/ErrorBoundary/ErrorBoundary.jsx +0 -76
- package/styles/ErrorBoundary/ErrorBoundary.spec.js +0 -72
- package/styles/Flyout/Flyout.jsx +0 -147
- package/styles/Flyout/Flyout.spec.js +0 -117
- package/styles/Form/Form.jsx +0 -151
- package/styles/Form/Form.spec.js +0 -148
- package/styles/Form/FormElementError.jsx +0 -18
- package/styles/Form/FormGroup.jsx +0 -32
- package/styles/Form/FormGroupError.jsx +0 -24
- package/styles/Form/index.js +0 -4
- package/styles/GooglePlacesSearchInput/GooglePlacesSearchInput.jsx +0 -215
- package/styles/GooglePlacesSearchInput/GooglePlacesSearchInput.spec.js +0 -213
- package/styles/GooglePlacesSearchInput/PoweredByGoogle.jsx +0 -43
- package/styles/GooglePlacesSearchInput/index.js +0 -2
- package/styles/HorizontalRule/HorizontalRule.jsx +0 -36
- package/styles/HorizontalRule/HorizontalRule.spec.js +0 -94
- package/styles/Label/Label.jsx +0 -22
- package/styles/Label/Label.spec.js +0 -11
- package/styles/Notification/Notification.jsx +0 -117
- package/styles/Notification/Notification.spec.js +0 -154
- package/styles/Notification/NotificationContainer.jsx +0 -90
- package/styles/Notification/NotificationPropTypes.js +0 -20
- package/styles/Notification/index.js +0 -2
- package/styles/PasswordControl/PasswordControl.jsx +0 -197
- package/styles/PasswordControl/PasswordControl.spec.js +0 -236
- package/styles/Portal/Portal.jsx +0 -65
- package/styles/Portal/Portal.spec.js +0 -45
- package/styles/PulseLoader/PulseLoader.jsx +0 -71
- package/styles/PulseLoader/PulseLoader.spec.js +0 -63
- package/styles/Radio/Radio.jsx +0 -114
- package/styles/Radio/Radio.spec.js +0 -128
- package/styles/Radio/RadioGroup.jsx +0 -105
- package/styles/Radio/index.js +0 -2
- package/styles/RenderInBody/RenderInBody.jsx +0 -56
- package/styles/RenderInBody/RenderInBody.spec.js +0 -24
- package/styles/Select/Select.jsx +0 -251
- package/styles/Select/Select.spec.js +0 -254
- package/styles/Select/SelectItemPropTypes.js +0 -19
- package/styles/Select/index.js +0 -2
- package/styles/SelectControlled/SelectControlled.jsx +0 -250
- package/styles/SelectControlled/SelectControlled.spec.js +0 -290
- package/styles/SelectControlled/index.js +0 -1
- package/styles/Sprite/Sprite.jsx +0 -16
- package/styles/Sprite/Sprite.spec.js +0 -11
- package/styles/Tabs/Tab.jsx +0 -38
- package/styles/Tabs/TabContent.jsx +0 -46
- package/styles/Tabs/TabNavigation.jsx +0 -64
- package/styles/Tabs/TabPanel.jsx +0 -30
- package/styles/Tabs/Tabs.jsx +0 -87
- package/styles/Tabs/Tabs.spec.js +0 -201
- package/styles/Tabs/index.js +0 -5
- package/styles/TextArea/TextArea.jsx +0 -137
- package/styles/TextArea/TextArea.spec.js +0 -111
- package/styles/TextInput/TextInput.jsx +0 -159
- package/styles/TextInput/TextInput.spec.js +0 -263
- package/styles/TextInput/TextInputPropTypes.js +0 -88
- package/styles/TextInput/index.js +0 -2
- package/styles/Tooltip/Tooltip.jsx +0 -230
- package/styles/Tooltip/Tooltip.spec.js +0 -170
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spothero/ui",
|
|
3
|
-
"version": "15.1.
|
|
3
|
+
"version": "15.1.1",
|
|
4
4
|
"description": "SpotHero's React component UI library.",
|
|
5
5
|
"main": "v2/index.js",
|
|
6
6
|
"repository": "https://github.com/spothero/fe-monorepo",
|
|
@@ -66,9 +66,8 @@
|
|
|
66
66
|
"build:backlog": "NODE_ENV=production babel src -d backlog --ignore \"**/*.spec.js\",\"**/stories/**\",\"**/v2/**\"",
|
|
67
67
|
"build": "npm run clean && npm run clone:styles && npm run build:backlog && npm run build:v1 && npm run build:v2",
|
|
68
68
|
"build:storybook": "build-storybook -o ./docs",
|
|
69
|
-
"prepublishOnly": "npm run build",
|
|
70
69
|
"release": "npm-release",
|
|
71
|
-
"
|
|
70
|
+
"publish-storybook": "npm run build:storybook && push-dir --dir=docs --branch=gh-pages --allow-unclean"
|
|
72
71
|
},
|
|
73
72
|
"engines": {
|
|
74
73
|
"node": ">=16.14.2",
|
package/styles/Alert/Alert.jsx
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
|
-
import classNames from 'classnames';
|
|
4
|
-
|
|
5
|
-
const Alert = ({className, children, type, size, inline}) => {
|
|
6
|
-
const classes = classNames(
|
|
7
|
-
'Alert',
|
|
8
|
-
{[`Alert-${type}`]: type},
|
|
9
|
-
{[`Alert-${size}`]: size},
|
|
10
|
-
{'Alert-inline': inline},
|
|
11
|
-
className
|
|
12
|
-
);
|
|
13
|
-
|
|
14
|
-
return (
|
|
15
|
-
<div className={classes}>
|
|
16
|
-
<span className="Alert-content">{children}</span>
|
|
17
|
-
</div>
|
|
18
|
-
);
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
Alert.propTypes = {
|
|
22
|
-
/** Additional class(es) to add to the component. */
|
|
23
|
-
className: PropTypes.string,
|
|
24
|
-
/** The content to render inside of the alert. */
|
|
25
|
-
children: PropTypes.node.isRequired,
|
|
26
|
-
/** Whether to show the alert inline instead of block. */
|
|
27
|
-
inline: PropTypes.bool,
|
|
28
|
-
/** The type of alert to show. */
|
|
29
|
-
type: PropTypes.oneOf([
|
|
30
|
-
'danger',
|
|
31
|
-
'highlight',
|
|
32
|
-
'success',
|
|
33
|
-
'neutral',
|
|
34
|
-
'muted',
|
|
35
|
-
]),
|
|
36
|
-
/** The size of the alert. */
|
|
37
|
-
size: PropTypes.oneOf(['sm', 'md', 'lg']),
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
Alert.defaultProps = {
|
|
41
|
-
type: 'neutral',
|
|
42
|
-
size: 'md',
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export default Alert;
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
describe('<Alert />', () => {
|
|
2
|
-
context('Colors', () => {
|
|
3
|
-
context('Neutral', () => {
|
|
4
|
-
beforeEach(() => {
|
|
5
|
-
cy.visitStory('v1/Alert/Colors', 'Neutral');
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
it('Has neutral styles', () => {
|
|
9
|
-
cy.get('.Alert').should('have.class', 'Alert-neutral');
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it('Renders the correct children', () => {
|
|
13
|
-
cy.get('.Alert').contains('This is an alert.');
|
|
14
|
-
});
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
context('Highlight', () => {
|
|
18
|
-
it('Has highlight styles', () => {
|
|
19
|
-
cy.visitStory('v1/Alert/Colors', 'Highlight')
|
|
20
|
-
.get('.Alert')
|
|
21
|
-
.should('have.class', 'Alert-highlight');
|
|
22
|
-
});
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
context('Danger', () => {
|
|
26
|
-
it('Has danger styles', () => {
|
|
27
|
-
cy.visitStory('v1/Alert/Colors', 'Danger')
|
|
28
|
-
.get('.Alert')
|
|
29
|
-
.should('have.class', 'Alert-danger');
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
context('Success', () => {
|
|
34
|
-
it('Has success styles', () => {
|
|
35
|
-
cy.visitStory('v1/Alert/Colors', 'Success')
|
|
36
|
-
.get('.Alert')
|
|
37
|
-
.should('have.class', 'Alert-success');
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
context('Muted', () => {
|
|
42
|
-
it('Has muted styles', () => {
|
|
43
|
-
cy.visitStory('v1/Alert/Colors', 'Muted')
|
|
44
|
-
.get('.Alert')
|
|
45
|
-
.should('have.class', 'Alert-muted');
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
context('Display', () => {
|
|
51
|
-
context('Inline', () => {
|
|
52
|
-
it('Has inline styles', () => {
|
|
53
|
-
cy.visitStory('v1/Alert/Display', 'Inline')
|
|
54
|
-
.get('.Alert')
|
|
55
|
-
.should('have.class', 'Alert-inline');
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
context('Sizes', () => {
|
|
61
|
-
context('Small', () => {
|
|
62
|
-
it('Has small styles', () => {
|
|
63
|
-
cy.visitStory('v1/Alert/Sizes', 'Small')
|
|
64
|
-
.get('.Alert')
|
|
65
|
-
.should('have.class', 'Alert-sm');
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
context('Medium', () => {
|
|
70
|
-
it('Has medium styles', () => {
|
|
71
|
-
cy.visitStory('v1/Alert/Sizes', 'Medium')
|
|
72
|
-
.get('.Alert')
|
|
73
|
-
.should('have.class', 'Alert-md');
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
context('Large', () => {
|
|
78
|
-
it('Has large styles', () => {
|
|
79
|
-
cy.visitStory('v1/Alert/Sizes', 'Large')
|
|
80
|
-
.get('.Alert')
|
|
81
|
-
.should('have.class', 'Alert-lg');
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
});
|
|
@@ -1,429 +0,0 @@
|
|
|
1
|
-
import isEqual from 'lodash/isEqual';
|
|
2
|
-
import React, {Component} from 'react';
|
|
3
|
-
import PropTypes from 'prop-types';
|
|
4
|
-
import classnames from 'classnames';
|
|
5
|
-
import uuidV4 from 'uuid/v4';
|
|
6
|
-
import IconTimesCircle from '@spothero/icons/times-circle';
|
|
7
|
-
import TextInput from '../TextInput/TextInput';
|
|
8
|
-
import TextInputPropTypes from '../TextInput/TextInputPropTypes';
|
|
9
|
-
import AutoSuggestList from './AutoSuggestList';
|
|
10
|
-
import Button from 'v1/components/Button/Button';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Calculates the difference between current scroll position and position of element, if outside visible window
|
|
14
|
-
*
|
|
15
|
-
* @param {object} elementAttributes
|
|
16
|
-
* @param {number} elementAttributes.parentScrollTop Value of parent element `scrollTop` attribute
|
|
17
|
-
* @param {number} elementAttributes.parentHeight Value of parent element `clientHeight` attribute
|
|
18
|
-
* @param {number} elementAttributes.elementOffsetTop Value of element `offsetTop` attribute
|
|
19
|
-
* @param {number} elementAttributes.elementHeight Value of element `clientHeight` attribute
|
|
20
|
-
*
|
|
21
|
-
* @returns {number} Pixel value of how far to scroll to view element
|
|
22
|
-
*/
|
|
23
|
-
const getScrollDifferential = ({
|
|
24
|
-
parentScrollTop,
|
|
25
|
-
parentHeight,
|
|
26
|
-
elementOffsetTop,
|
|
27
|
-
elementHeight,
|
|
28
|
-
}) => {
|
|
29
|
-
if (elementOffsetTop < parentScrollTop) {
|
|
30
|
-
return elementOffsetTop - parentScrollTop;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const parentLowerBound = parentScrollTop + parentHeight;
|
|
34
|
-
const elementLowerBound = elementOffsetTop + elementHeight;
|
|
35
|
-
|
|
36
|
-
if (elementLowerBound > parentLowerBound) {
|
|
37
|
-
return elementLowerBound - parentLowerBound;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return 0;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
export default class AutoSuggestInput extends Component {
|
|
44
|
-
static propTypes = {
|
|
45
|
-
...TextInputPropTypes,
|
|
46
|
-
/** Whether or not to highlight the first suggestion in the list when suggestions are presented. */
|
|
47
|
-
autoActivateFirstSuggest: PropTypes.bool,
|
|
48
|
-
/** The available suggestions. */
|
|
49
|
-
suggestions: PropTypes.arrayOf(
|
|
50
|
-
PropTypes.shape({
|
|
51
|
-
label: PropTypes.oneOfType([
|
|
52
|
-
PropTypes.string,
|
|
53
|
-
PropTypes.element,
|
|
54
|
-
]).isRequired,
|
|
55
|
-
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
56
|
-
})
|
|
57
|
-
),
|
|
58
|
-
/** A custom element to display at the bottom of the suggestion list */
|
|
59
|
-
suggestionBoxFooter: PropTypes.element,
|
|
60
|
-
/** Optional function to execute when a suggestion is selected. */
|
|
61
|
-
onSuggestionSelect: PropTypes.func,
|
|
62
|
-
/** Optional function to execute when input field is cleared. */
|
|
63
|
-
onClear: PropTypes.func,
|
|
64
|
-
};
|
|
65
|
-
static defaultProps = {
|
|
66
|
-
iconPosition: 'left',
|
|
67
|
-
name: 'search',
|
|
68
|
-
placeholder: 'Search',
|
|
69
|
-
suggestions: [],
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
constructor(props) {
|
|
73
|
-
super(props);
|
|
74
|
-
|
|
75
|
-
const {defaultValue} = props;
|
|
76
|
-
|
|
77
|
-
this.state = {
|
|
78
|
-
suggestionsHidden: true,
|
|
79
|
-
ignoreBlur: false,
|
|
80
|
-
value: defaultValue || '',
|
|
81
|
-
activeSuggestion: null,
|
|
82
|
-
inputKey: uuidV4(),
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
componentDidMount() {
|
|
87
|
-
const {suggestions} = this.props;
|
|
88
|
-
|
|
89
|
-
this._input?.node?.addEventListener('invalid', this._onInvalid);
|
|
90
|
-
|
|
91
|
-
if (suggestions.length) {
|
|
92
|
-
this._showSuggests();
|
|
93
|
-
} else {
|
|
94
|
-
this._hideSuggests();
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
componentDidUpdate(prevProps, prevState) {
|
|
99
|
-
const {suggestions, autoActivateFirstSuggest} = this.props;
|
|
100
|
-
const {value} = this.state;
|
|
101
|
-
const {suggestions: prevSuggestions} = prevProps;
|
|
102
|
-
|
|
103
|
-
if (prevState.value !== value) {
|
|
104
|
-
if (!value) {
|
|
105
|
-
this._input?.node?.focus();
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
if (!isEqual(prevSuggestions, suggestions)) {
|
|
110
|
-
if (suggestions && suggestions.length) {
|
|
111
|
-
this._showSuggests();
|
|
112
|
-
|
|
113
|
-
if (autoActivateFirstSuggest) {
|
|
114
|
-
this._activateSuggest({direction: 'next'});
|
|
115
|
-
}
|
|
116
|
-
} else {
|
|
117
|
-
this._hideSuggests();
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
componentWillUnmount() {
|
|
123
|
-
this._input?.node?.removeEventListener('invalid', this._onInvalid);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
_onInvalid = evt => {
|
|
127
|
-
evt.preventDefault();
|
|
128
|
-
|
|
129
|
-
const {onInvalid} = this.props;
|
|
130
|
-
|
|
131
|
-
if (onInvalid) {
|
|
132
|
-
onInvalid(evt.currentTarget.validity);
|
|
133
|
-
}
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
_onInputChange = evt => {
|
|
137
|
-
this.setState({
|
|
138
|
-
value: evt.target.value,
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
const {onChange} = this.props;
|
|
142
|
-
|
|
143
|
-
if (onChange) {
|
|
144
|
-
onChange(evt);
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
_onInputKeyDown = evt => {
|
|
149
|
-
switch (evt.which) {
|
|
150
|
-
case 40:
|
|
151
|
-
this._nextSuggest(evt);
|
|
152
|
-
break;
|
|
153
|
-
|
|
154
|
-
case 38:
|
|
155
|
-
this._previousSuggest(evt);
|
|
156
|
-
break;
|
|
157
|
-
|
|
158
|
-
case 13:
|
|
159
|
-
this._selectSuggest(evt);
|
|
160
|
-
break;
|
|
161
|
-
|
|
162
|
-
case 27:
|
|
163
|
-
this._hideSuggests(evt);
|
|
164
|
-
break;
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
_onInputFocus = () => {
|
|
169
|
-
const {onFocus} = this.props;
|
|
170
|
-
|
|
171
|
-
if (onFocus) {
|
|
172
|
-
onFocus();
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
this.setState({
|
|
176
|
-
suggestionsHidden: false,
|
|
177
|
-
});
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
_onInputBlur = () => {
|
|
181
|
-
if (!this.state.ignoreBlur) {
|
|
182
|
-
this._hideSuggests();
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
_onSuggestionMouseDown = () => {
|
|
187
|
-
this.setState({
|
|
188
|
-
ignoreBlur: true,
|
|
189
|
-
});
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
_onSuggestionMouseOut = () => {
|
|
193
|
-
this.setState({
|
|
194
|
-
ignoreBlur: false,
|
|
195
|
-
});
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
_onSelectSuggestion = ({suggestion = false}) => {
|
|
199
|
-
const {onSuggestionSelect} = this.props;
|
|
200
|
-
let selectedSuggestion = suggestion;
|
|
201
|
-
|
|
202
|
-
if (!selectedSuggestion) {
|
|
203
|
-
selectedSuggestion = {};
|
|
204
|
-
selectedSuggestion.label = this.state.value;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
this.setState({
|
|
208
|
-
suggestionsHidden: true,
|
|
209
|
-
value: selectedSuggestion.label,
|
|
210
|
-
inputKey: uuidV4(),
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
onSuggestionSelect?.(selectedSuggestion);
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
_onClear = () => {
|
|
217
|
-
const {onClear} = this.props;
|
|
218
|
-
|
|
219
|
-
this.setState({
|
|
220
|
-
value: '',
|
|
221
|
-
inputKey: uuidV4(),
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
if (onClear) {
|
|
225
|
-
onClear();
|
|
226
|
-
}
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
_nextSuggest() {
|
|
230
|
-
this._activateSuggest({
|
|
231
|
-
direction: 'next',
|
|
232
|
-
isArrowPress: true,
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
_previousSuggest() {
|
|
237
|
-
this._activateSuggest({
|
|
238
|
-
direction: 'prev',
|
|
239
|
-
isArrowPress: true,
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
_selectSuggest = evt => {
|
|
244
|
-
evt.preventDefault();
|
|
245
|
-
|
|
246
|
-
this._onSelectSuggestion({
|
|
247
|
-
suggestion: this.state.activeSuggestion,
|
|
248
|
-
});
|
|
249
|
-
};
|
|
250
|
-
|
|
251
|
-
_showSuggests() {
|
|
252
|
-
if (this.state.suggestionsHidden) {
|
|
253
|
-
this.setState({
|
|
254
|
-
suggestionsHidden: false,
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
_hideSuggests() {
|
|
260
|
-
const {onBlur} = this.props;
|
|
261
|
-
|
|
262
|
-
if (onBlur) {
|
|
263
|
-
onBlur();
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
if (!this.state.suggestionsHidden) {
|
|
267
|
-
this.setState({
|
|
268
|
-
suggestionsHidden: true,
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
_activateSuggest({direction, isArrowPress = false}) {
|
|
274
|
-
const {suggestions} = this.props;
|
|
275
|
-
const {activeSuggestion} = this.state;
|
|
276
|
-
const suggestionsCount = suggestions.length - 1;
|
|
277
|
-
const next = direction === 'next';
|
|
278
|
-
const newState = {};
|
|
279
|
-
let newActiveSuggestion = null;
|
|
280
|
-
let newIndex = 0;
|
|
281
|
-
let i = 0;
|
|
282
|
-
|
|
283
|
-
for (i; i <= suggestionsCount; i++) {
|
|
284
|
-
if (suggestions[i] === activeSuggestion) {
|
|
285
|
-
newIndex = next ? i + 1 : i - 1;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
if (!activeSuggestion) {
|
|
290
|
-
newIndex = next ? 0 : suggestionsCount;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
if (newIndex < 0) {
|
|
294
|
-
newIndex = suggestionsCount;
|
|
295
|
-
} else if (newIndex > suggestionsCount) {
|
|
296
|
-
newIndex = 0;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
if (newIndex >= 0 && newIndex <= suggestionsCount) {
|
|
300
|
-
newActiveSuggestion = suggestions[newIndex];
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
newState.activeSuggestion = newActiveSuggestion;
|
|
304
|
-
|
|
305
|
-
if (isArrowPress) {
|
|
306
|
-
newState.value = newActiveSuggestion
|
|
307
|
-
? newActiveSuggestion.label
|
|
308
|
-
: '';
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
if (this._list) {
|
|
312
|
-
const activeChild = this._list.querySelector(
|
|
313
|
-
'.AutoSuggestInput-item-active'
|
|
314
|
-
);
|
|
315
|
-
|
|
316
|
-
let nextActiveChild = next
|
|
317
|
-
? activeChild?.nextSibling
|
|
318
|
-
: activeChild?.previousSibling;
|
|
319
|
-
|
|
320
|
-
nextActiveChild = nextActiveChild
|
|
321
|
-
? nextActiveChild
|
|
322
|
-
: next
|
|
323
|
-
? this._list.firstElementChild
|
|
324
|
-
: this._list.lastElementChild;
|
|
325
|
-
|
|
326
|
-
if (nextActiveChild) {
|
|
327
|
-
const scrollDiff = getScrollDifferential({
|
|
328
|
-
parentScrollTop: this._list.scrollTop,
|
|
329
|
-
parentHeight: this._list.clientHeight,
|
|
330
|
-
elementOffsetTop: nextActiveChild.offsetTop,
|
|
331
|
-
elementHeight: nextActiveChild.clientHeight,
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
if (scrollDiff) {
|
|
335
|
-
this._list.scrollTo(
|
|
336
|
-
nextActiveChild.offsetLeft,
|
|
337
|
-
this._list.scrollTop + scrollDiff
|
|
338
|
-
);
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
this.setState(newState);
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
/**
|
|
347
|
-
* Getter for the input DOM element.
|
|
348
|
-
*
|
|
349
|
-
* @public
|
|
350
|
-
* @returns {Element} - The input element.
|
|
351
|
-
*/
|
|
352
|
-
get node() {
|
|
353
|
-
return this._input?.node;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
render() {
|
|
357
|
-
const {
|
|
358
|
-
className,
|
|
359
|
-
suggestions,
|
|
360
|
-
suggestionBoxFooter,
|
|
361
|
-
additionalInputProps,
|
|
362
|
-
...textInputProps
|
|
363
|
-
} = this.props;
|
|
364
|
-
const {
|
|
365
|
-
value,
|
|
366
|
-
inputKey,
|
|
367
|
-
activeSuggestion,
|
|
368
|
-
suggestionsHidden,
|
|
369
|
-
} = this.state;
|
|
370
|
-
const classes = classnames(
|
|
371
|
-
'AutoSuggestInput',
|
|
372
|
-
{'AutoSuggestInput-suggestions-active': !suggestionsHidden},
|
|
373
|
-
{
|
|
374
|
-
'AutoSuggestInput-no-suggestions':
|
|
375
|
-
!suggestions || !suggestions.length,
|
|
376
|
-
},
|
|
377
|
-
className
|
|
378
|
-
);
|
|
379
|
-
const newAdditionalInputProps = {
|
|
380
|
-
...additionalInputProps,
|
|
381
|
-
onKeyDown: this._onInputKeyDown,
|
|
382
|
-
autoComplete: 'off',
|
|
383
|
-
};
|
|
384
|
-
|
|
385
|
-
return (
|
|
386
|
-
<div
|
|
387
|
-
ref={node => {
|
|
388
|
-
this._container = node;
|
|
389
|
-
}}
|
|
390
|
-
className={classes}
|
|
391
|
-
>
|
|
392
|
-
<div className="FormElement-control">
|
|
393
|
-
<TextInput
|
|
394
|
-
key={inputKey}
|
|
395
|
-
ref={node => {
|
|
396
|
-
this._input = node;
|
|
397
|
-
}}
|
|
398
|
-
{...textInputProps}
|
|
399
|
-
additionalInputProps={newAdditionalInputProps}
|
|
400
|
-
defaultValue={value}
|
|
401
|
-
onChange={this._onInputChange}
|
|
402
|
-
onFocus={this._onInputFocus}
|
|
403
|
-
onBlur={this._onInputBlur}
|
|
404
|
-
/>
|
|
405
|
-
<AutoSuggestList
|
|
406
|
-
ref={node => {
|
|
407
|
-
this._list = node;
|
|
408
|
-
}}
|
|
409
|
-
hidden={suggestionsHidden}
|
|
410
|
-
suggestions={suggestions || []}
|
|
411
|
-
activeSuggestion={activeSuggestion}
|
|
412
|
-
suggestionBoxFooter={suggestionBoxFooter}
|
|
413
|
-
onSuggestionSelect={this._onSelectSuggestion}
|
|
414
|
-
onSuggestionMouseDown={this._onSuggestionMouseDown}
|
|
415
|
-
onSuggestionMouseOut={this._onSuggestionMouseOut}
|
|
416
|
-
/>
|
|
417
|
-
{value && (
|
|
418
|
-
<Button
|
|
419
|
-
className="AutoSuggestInput-clear"
|
|
420
|
-
onClick={this._onClear}
|
|
421
|
-
>
|
|
422
|
-
<IconTimesCircle />
|
|
423
|
-
</Button>
|
|
424
|
-
)}
|
|
425
|
-
</div>
|
|
426
|
-
</div>
|
|
427
|
-
);
|
|
428
|
-
}
|
|
429
|
-
}
|