@spothero/ui 15.1.0 → 15.1.2

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.
Files changed (91) hide show
  1. package/CHANGELOG.md +0 -18
  2. package/package.json +2 -3
  3. package/styles/v2/components/Modal/styles/dialogContainer.js +0 -1
  4. package/styles/v2/components/Radio/Radio.jsx +1 -1
  5. package/styles/v2/components/Radio/RadioGroup.jsx +1 -1
  6. package/v2/index.js +1 -1
  7. package/v2/index.js.map +1 -1
  8. package/styles/Alert/Alert.jsx +0 -45
  9. package/styles/Alert/Alert.spec.js +0 -85
  10. package/styles/AutoSuggestInput/AutoSuggestInput.jsx +0 -429
  11. package/styles/AutoSuggestInput/AutoSuggestInput.spec.js +0 -132
  12. package/styles/AutoSuggestInput/AutoSuggestItem.jsx +0 -61
  13. package/styles/AutoSuggestInput/AutoSuggestList.jsx +0 -85
  14. package/styles/Badge/Badge.jsx +0 -24
  15. package/styles/Badge/Badge.spec.js +0 -43
  16. package/styles/Chart/Chart.jsx +0 -185
  17. package/styles/Chart/Chart.spec.js +0 -369
  18. package/styles/Checkbox/Checkbox.jsx +0 -159
  19. package/styles/Checkbox/Checkbox.spec.js +0 -142
  20. package/styles/DateTime/DatePicker.jsx +0 -281
  21. package/styles/DateTime/DatePicker.spec.js +0 -186
  22. package/styles/DateTime/DatePickerCalendar.jsx +0 -170
  23. package/styles/DateTime/DatePickerCalendarNavigation.jsx +0 -44
  24. package/styles/DateTime/DatePickerCalendarWithRange.jsx +0 -218
  25. package/styles/DateTime/DateTimePicker.jsx +0 -266
  26. package/styles/DateTime/DateTimePicker.spec.js +0 -60
  27. package/styles/DateTime/DateTimeRangePicker.jsx +0 -629
  28. package/styles/DateTime/DateTimeRangePicker.spec.js +0 -425
  29. package/styles/DateTime/TimePicker.jsx +0 -158
  30. package/styles/DateTime/TimePicker.spec.js +0 -148
  31. package/styles/DateTime/date-time-assertions.js +0 -89
  32. package/styles/DateTime/index.js +0 -6
  33. package/styles/ErrorBoundary/ErrorBoundary.jsx +0 -76
  34. package/styles/ErrorBoundary/ErrorBoundary.spec.js +0 -72
  35. package/styles/Flyout/Flyout.jsx +0 -147
  36. package/styles/Flyout/Flyout.spec.js +0 -117
  37. package/styles/Form/Form.jsx +0 -151
  38. package/styles/Form/Form.spec.js +0 -148
  39. package/styles/Form/FormElementError.jsx +0 -18
  40. package/styles/Form/FormGroup.jsx +0 -32
  41. package/styles/Form/FormGroupError.jsx +0 -24
  42. package/styles/Form/index.js +0 -4
  43. package/styles/GooglePlacesSearchInput/GooglePlacesSearchInput.jsx +0 -215
  44. package/styles/GooglePlacesSearchInput/GooglePlacesSearchInput.spec.js +0 -213
  45. package/styles/GooglePlacesSearchInput/PoweredByGoogle.jsx +0 -43
  46. package/styles/GooglePlacesSearchInput/index.js +0 -2
  47. package/styles/HorizontalRule/HorizontalRule.jsx +0 -36
  48. package/styles/HorizontalRule/HorizontalRule.spec.js +0 -94
  49. package/styles/Label/Label.jsx +0 -22
  50. package/styles/Label/Label.spec.js +0 -11
  51. package/styles/Notification/Notification.jsx +0 -117
  52. package/styles/Notification/Notification.spec.js +0 -154
  53. package/styles/Notification/NotificationContainer.jsx +0 -90
  54. package/styles/Notification/NotificationPropTypes.js +0 -20
  55. package/styles/Notification/index.js +0 -2
  56. package/styles/PasswordControl/PasswordControl.jsx +0 -197
  57. package/styles/PasswordControl/PasswordControl.spec.js +0 -236
  58. package/styles/Portal/Portal.jsx +0 -65
  59. package/styles/Portal/Portal.spec.js +0 -45
  60. package/styles/PulseLoader/PulseLoader.jsx +0 -71
  61. package/styles/PulseLoader/PulseLoader.spec.js +0 -63
  62. package/styles/Radio/Radio.jsx +0 -114
  63. package/styles/Radio/Radio.spec.js +0 -128
  64. package/styles/Radio/RadioGroup.jsx +0 -105
  65. package/styles/Radio/index.js +0 -2
  66. package/styles/RenderInBody/RenderInBody.jsx +0 -56
  67. package/styles/RenderInBody/RenderInBody.spec.js +0 -24
  68. package/styles/Select/Select.jsx +0 -251
  69. package/styles/Select/Select.spec.js +0 -254
  70. package/styles/Select/SelectItemPropTypes.js +0 -19
  71. package/styles/Select/index.js +0 -2
  72. package/styles/SelectControlled/SelectControlled.jsx +0 -250
  73. package/styles/SelectControlled/SelectControlled.spec.js +0 -290
  74. package/styles/SelectControlled/index.js +0 -1
  75. package/styles/Sprite/Sprite.jsx +0 -16
  76. package/styles/Sprite/Sprite.spec.js +0 -11
  77. package/styles/Tabs/Tab.jsx +0 -38
  78. package/styles/Tabs/TabContent.jsx +0 -46
  79. package/styles/Tabs/TabNavigation.jsx +0 -64
  80. package/styles/Tabs/TabPanel.jsx +0 -30
  81. package/styles/Tabs/Tabs.jsx +0 -87
  82. package/styles/Tabs/Tabs.spec.js +0 -201
  83. package/styles/Tabs/index.js +0 -5
  84. package/styles/TextArea/TextArea.jsx +0 -137
  85. package/styles/TextArea/TextArea.spec.js +0 -111
  86. package/styles/TextInput/TextInput.jsx +0 -159
  87. package/styles/TextInput/TextInput.spec.js +0 -263
  88. package/styles/TextInput/TextInputPropTypes.js +0 -88
  89. package/styles/TextInput/index.js +0 -2
  90. package/styles/Tooltip/Tooltip.jsx +0 -230
  91. package/styles/Tooltip/Tooltip.spec.js +0 -170
@@ -1,263 +0,0 @@
1
- describe('<TextInput />', () => {
2
- context('Display', () => {
3
- context('Default', () => {
4
- it('Should have placeholder, default value, label, help text, and custom class names', () => {
5
- cy.visitStory('v1/TextInput/Display', 'Default')
6
- .get('.TextInput')
7
- .should('exist')
8
- .and('have.class', 'custom-class1')
9
- .and('have.class', 'custom-class2')
10
- .find('input')
11
- .should('have.attr', 'name', 'license-plate')
12
- .and('have.attr', 'placeholder', 'License Plate')
13
- .and('have.value', 'ECTO-1')
14
- .get('.TextInput')
15
- .find('.Label')
16
- .contains('Add new license plate')
17
- .get('.TextInput')
18
- .find('.FormElement-help-text')
19
- .contains('Additional help node text');
20
- });
21
- });
22
-
23
- context('Disabled', () => {
24
- it('Is disabled', () => {
25
- cy.visitStory('v1/TextInput/Display', 'Disabled')
26
- .get('.TextInput')
27
- .find('input')
28
- .should('be.disabled');
29
- });
30
- });
31
-
32
- context('Read Only', () => {
33
- it('Is read only', () => {
34
- cy.visitStory('v1/TextInput/Display', 'ReadOnly')
35
- .get('.TextInput')
36
- .find('input')
37
- .should('have.attr', 'readonly');
38
- });
39
- });
40
-
41
- context('Icon', () => {
42
- it('Should render with an icon', () => {
43
- cy.visitStory('v1/TextInput/Display', 'Icon')
44
- .get('.TextInput')
45
- .should('have.class', 'FormElement-with-icon-right')
46
- .find('.Icon')
47
- .should('exist');
48
- });
49
- });
50
-
51
- context('Loading', () => {
52
- it('Should render with a loading spinner', () => {
53
- cy.visitStory('v1/TextInput/Display', 'Loading')
54
- .get('.TextInput')
55
- .find('.Loader')
56
- .should('exist');
57
- });
58
- });
59
-
60
- context('Inline', () => {
61
- it('Should render with inline styling', () => {
62
- cy.visitStory('v1/TextInput/Display', 'Inline')
63
- .get('.TextInput')
64
- .should('have.class', 'FormElement-inline');
65
- });
66
- });
67
-
68
- context('Auto Focus', () => {
69
- it('Receives focus after rendered', () => {
70
- cy.visitStory('v1/TextInput/Display', 'AutoFocus')
71
- .focused()
72
- .should('have.attr', 'name', 'license-plate');
73
- });
74
- });
75
- });
76
-
77
- context('Formatting', () => {
78
- describe('Mask', () => {
79
- it('Applies a mask over the input text', () => {
80
- cy.visitStory('v1/TextInput/Formatting', 'Mask')
81
- .get('.TextInput')
82
- .find('input')
83
- .click()
84
- .should('have.value', '+X-XXX-XXX-XXXX')
85
- .type('12345678899', {delay: 0})
86
- .blur()
87
- .should('have.value', '+1-234-567-8899');
88
- });
89
- });
90
-
91
- describe('Pattern', () => {
92
- it('Has pattern attribute and ensures the input text follows the specified regex pattern', () => {
93
- cy.visitStory('v1/TextInput/Formatting', 'Pattern')
94
- .get('.TextInput')
95
- .find('input')
96
- .should('have.attr', 'pattern', '[A-Za-z0-9]+')
97
- // should show error since value does not follow pattern
98
- .type('OÜTAT!M&', {delay: 0})
99
- .get('button[type=submit]')
100
- .click()
101
- .get('.TextInput')
102
- .find('.FormElementError')
103
- .should('exist')
104
- // should not show error since value follows pattern
105
- .get('.TextInput')
106
- .find('input')
107
- .clear()
108
- .type('oUtAT1M3', {delay: 0})
109
- .get('button[type=submit]')
110
- .click()
111
- .get('.TextInput')
112
- .find('.FormElementError')
113
- .should('not.exist');
114
- });
115
- });
116
-
117
- context('Max Length', () => {
118
- it('Has maxlength attribute and does not allow more characters', () => {
119
- // longstring is 53 characters long
120
- const longstring =
121
- 'myusernamemyusernamemyusernamemyusernamemyusernameabc';
122
-
123
- cy.visitStory('v1/TextInput/Formatting', 'MaxLength')
124
- .get('.TextInput')
125
- .find('input')
126
- .should('have.attr', 'maxlength', '50')
127
- .type(longstring, {delay: 0})
128
- .should('have.value', longstring.substring(0, 50));
129
- });
130
- });
131
-
132
- context('Min Max', () => {
133
- it('Has min and max attributes and does not consider input outside that range valid', () => {
134
- cy.visitStory('v1/TextInput/Formatting', 'MinMax')
135
- .get('.TextInput')
136
- .find('input')
137
- .should('have.attr', 'min', '1')
138
- .should('have.attr', 'max', '100')
139
- // should show error since value is below min
140
- .type('0', {delay: 0})
141
- .get('button[type=submit]')
142
- .click()
143
- .get('.TextInput')
144
- .find('.FormElementError')
145
- .should('exist')
146
- // should not show error since value is in range
147
- .get('.TextInput')
148
- .find('input')
149
- .clear()
150
- .type('42', {delay: 0})
151
- .get('button[type=submit]')
152
- .click()
153
- .get('.TextInput')
154
- .find('.FormElementError')
155
- .should('not.exist')
156
- // should show error since value is above max
157
- .get('.TextInput')
158
- .find('input')
159
- .clear()
160
- .type('4200', {delay: 0})
161
- .get('button[type=submit]')
162
- .click()
163
- .get('.TextInput')
164
- .find('.FormElementError')
165
- .should('exist');
166
- });
167
- });
168
- });
169
-
170
- context('Methods', () => {
171
- describe('On Change', () => {
172
- it('Executes the method when a change is detected', () => {
173
- cy.visitStory('v1/TextInput/Methods', 'OnChange', {
174
- onBeforeLoad: contentWindow => {
175
- contentWindow.onTextInputChange = evt => {
176
- console.log(`onTextInputChange`); // eslint-disable-line no-console
177
- };
178
-
179
- cy.stub(contentWindow, 'onTextInputChange').as(
180
- 'onTextInputChange'
181
- );
182
- },
183
- })
184
- .get('.TextInput')
185
- .find('input')
186
- .type('OUTATIME', {delay: 0})
187
- .get('@onTextInputChange')
188
- .should('be.called');
189
- });
190
- });
191
-
192
- describe('On Focus', () => {
193
- it('Executes the method when input is focused on', () => {
194
- cy.visitStory('v1/TextInput/Methods', 'OnFocus', {
195
- onBeforeLoad: contentWindow => {
196
- contentWindow.onTextInputFocus = evt => {
197
- console.log(`onTextInputFocus`); // eslint-disable-line no-console
198
- };
199
-
200
- cy.stub(contentWindow, 'onTextInputFocus').as(
201
- 'onTextInputFocus'
202
- );
203
- },
204
- })
205
- .get('.TextInput')
206
- .find('input')
207
- .focus()
208
- .get('@onTextInputFocus')
209
- .should('be.called');
210
- });
211
- });
212
-
213
- describe('On Blur', () => {
214
- it('Executes the method when input loses focus', () => {
215
- cy.visitStory('v1/TextInput/Methods', 'OnBlur', {
216
- onBeforeLoad: contentWindow => {
217
- contentWindow.onTextInputBlur = evt => {
218
- console.log(`onTextInputBlur`); // eslint-disable-line no-console
219
- };
220
-
221
- cy.stub(contentWindow, 'onTextInputBlur').as(
222
- 'onTextInputBlur'
223
- );
224
- },
225
- })
226
- .get('.TextInput')
227
- .find('input')
228
- .focus()
229
- .get('@onTextInputBlur')
230
- .should('not.be.called')
231
- .get('.TextInput')
232
- .find('input')
233
- .blur()
234
- .get('@onTextInputBlur')
235
- .should('be.called');
236
- });
237
- });
238
-
239
- describe('On Invalid', () => {
240
- it('Displays an error if the input is invalid', () => {
241
- cy.visitStory('v1/TextInput/Methods', 'OnInvalid')
242
- .get('.TextInput')
243
- .find('input')
244
- // Show error on empty field since this is required
245
- .should('have.value', '')
246
- .get('button[type=submit]')
247
- .click()
248
- .get('.TextInput')
249
- .find('.FormElementError')
250
- .should('exist')
251
- // Don't show error on field with content
252
- .get('.TextInput')
253
- .find('input')
254
- .type('MY PRSHE', {delay: 0})
255
- .get('button[type=submit]')
256
- .click()
257
- .get('.TextInput')
258
- .find('.FormElementError')
259
- .should('not.exist');
260
- });
261
- });
262
- });
263
- });
@@ -1,88 +0,0 @@
1
- import PropTypes from 'prop-types';
2
-
3
- const TextInputPropTypes = {
4
- /** Additional class(es) to add to the component. */
5
- className: PropTypes.string,
6
- /** A unique name which is used to identify this element. If belonging to a form this is used as the key for serialization and is required. */
7
- name: PropTypes.string,
8
- /** What HTML input type the underlying input should be set to. */
9
- type: PropTypes.oneOf([
10
- 'text',
11
- 'password',
12
- 'date',
13
- 'email',
14
- 'time',
15
- 'tel',
16
- 'search',
17
- 'number',
18
- 'hidden',
19
- ]),
20
- /** Text to display in the field before a user starts to type in the input. */
21
- placeholder: PropTypes.string,
22
- /** A custom label (typically a Label component) to display above the input. */
23
- label: PropTypes.element,
24
- /** A regular expression that the input value is checked against for validation. */
25
- pattern: PropTypes.string,
26
- /** Whether this field is required during validation. */
27
- required: PropTypes.bool,
28
- /** Disallows user interaction. */
29
- disabled: PropTypes.bool,
30
- /** Whether to show a loading animation inside of the component. */
31
- loading: PropTypes.bool,
32
- /** Whether the field should be auto focused when mounted. */
33
- autoFocus: PropTypes.bool,
34
- /** Whether the field should be focused when the component receives new props. */
35
- focus: PropTypes.bool,
36
- /** A custom validation error (typically a FormElementError component) to display when this component is part of a form and is invalid. */
37
- error: PropTypes.element,
38
- /** The default value to display in the input when mounted. */
39
- defaultValue: PropTypes.string,
40
- /** A custom icon (typically an Icon component) to show in the input field. */
41
- icon: PropTypes.element,
42
- /** If an icon is provided, whether it should appear on the left or right side of the input field. */
43
- iconPosition: PropTypes.oneOf(['left', 'right']),
44
- /** A custom help element to place below the input. */
45
- helpNode: PropTypes.node,
46
- /** Applies proper styling to display this field inline in a form. */
47
- inline: PropTypes.bool,
48
- /** Specifies that the input field is read-only. */
49
- readOnly: PropTypes.bool,
50
- /** Specifies the maximum number of characters allowed. */
51
- maxLength: PropTypes.number,
52
- /** Specifies the minimum value when type is `date` or `number`. */
53
- min: PropTypes.number,
54
- /** Specifies the maximum value when type is `date` or `number`. */
55
- max: PropTypes.number,
56
- /** A string to use as a mask. See <a href="https://github.com/sanniassin/react-input-mask#mask--string" target="_blank">react-input-mask</a>. */
57
- mask: PropTypes.string,
58
- /** Character to cover unfilled editable parts of mask. See <a href="https://github.com/sanniassin/react-input-mask#maskchar--string" target="_blank">react-input-mask</a>. */
59
- maskChar: PropTypes.string,
60
- /** Additional props to pass to the input element */
61
- additionalInputProps: PropTypes.object,
62
- /**
63
- * Function to execute when the input changes.
64
- *
65
- * @param {SyntheticEvent} evt - The React `SyntheticEvent`.
66
- */
67
- onChange: PropTypes.func,
68
- /**
69
- * Function to execute when the input is focused.
70
- *
71
- * @param {SyntheticEvent} evt - The React `SyntheticEvent`.
72
- */
73
- onFocus: PropTypes.func,
74
- /**
75
- * Function to execute when the input loses focused.
76
- *
77
- * @param {SyntheticEvent} evt - The React `SyntheticEvent`.
78
- */
79
- onBlur: PropTypes.func,
80
- /**
81
- * Function to execute when the element is marked as invalid by a validation check.
82
- *
83
- * @param {ValidityState} validationState - ValidityState object for more fine grained control over error handling in a parent component if desired.
84
- */
85
- onInvalid: PropTypes.func,
86
- };
87
-
88
- export default TextInputPropTypes;
@@ -1,2 +0,0 @@
1
- export {default as TextInput} from './TextInput';
2
- export {default as TextInputPropTypes} from './TextInputPropTypes';
@@ -1,230 +0,0 @@
1
- import bind from 'lodash/bind';
2
- import React, {Component} from 'react';
3
- import PropTypes from 'prop-types';
4
- import classNames from 'classnames';
5
- import IconTimes from '@spothero/icons/times';
6
- import DOMUtils from '@spothero/utils/dom';
7
- import Button from 'v1/components/Button/Button';
8
- import Portal from '../Portal/Portal';
9
-
10
- export default class Tooltip extends Component {
11
- static propTypes = {
12
- /** Additional class(es) to add to the component. */
13
- className: PropTypes.string,
14
- /** Additional class(es) to add to the containing Portal component. */
15
- containerClassName: PropTypes.string,
16
- /** The markup node to insert into the tooltip. */
17
- children: PropTypes.node.isRequired,
18
- /** Where to position the tooltip in relation to the triggering element. */
19
- position: PropTypes.oneOf(['top', 'right', 'bottom', 'left']),
20
- /** Whether to show the close button or not. */
21
- showClose: PropTypes.bool,
22
- /** The selector (.foo, #foo, etc...) for the element to attach the tooltip to. */
23
- triggerSelector: PropTypes.string.isRequired,
24
- /** Whether to reposition the tooltip when it moves, be it via window resize or scrolling or whatever moves it. */
25
- updateOnMove: PropTypes.bool,
26
- /** The offset of the tooltip from the triggering element. This is based on what the position is set to (`top` offsets up, etc). */
27
- tipOffset: PropTypes.number,
28
- /** Whether to automatically adjust the tooltip if its off the left or right side of the screen. */
29
- adjustArrow: PropTypes.bool,
30
- /** Whether to close the tooltip if the body outside of it is clicked. */
31
- closeOnBodyClick: PropTypes.bool,
32
- /** A function to execute after the tooltip has been hidden. Use this to manage state in a parent component to remove the tooltip from the DOM (see examples). */
33
- onHidden: PropTypes.func.isRequired,
34
- };
35
- static defaultProps = {
36
- position: 'top',
37
- showClose: true,
38
- tipOffset: 0,
39
- adjustArrow: true,
40
- };
41
-
42
- constructor(props) {
43
- super(props);
44
-
45
- this._isArrowAdjusted = false;
46
- }
47
-
48
- componentDidMount() {
49
- const {triggerSelector, updateOnMove, closeOnBodyClick} = this.props;
50
-
51
- this._trigger = DOMUtils.el(triggerSelector);
52
- this._positionTooltip();
53
-
54
- DOMUtils.addClass(this._container, 'Tooltip-showing');
55
-
56
- if (updateOnMove) {
57
- this._container.style.position = 'fixed';
58
-
59
- this._scrollInterval = setInterval(
60
- bind(this._positionTooltip, this),
61
- 100
62
- );
63
- }
64
-
65
- if (closeOnBodyClick) {
66
- document.addEventListener('click', this._onCloseClick, {
67
- capture: true,
68
- });
69
- }
70
- }
71
-
72
- componentWillUnmount() {
73
- const {updateOnMove, closeOnBodyClick} = this.props;
74
-
75
- if (updateOnMove) {
76
- clearInterval(this._scrollInterval);
77
- }
78
-
79
- if (closeOnBodyClick) {
80
- document.removeEventListener('click', this._onCloseClick);
81
- }
82
- }
83
-
84
- _onCloseClick = evt => {
85
- this.hide();
86
- };
87
-
88
- _positionTooltip() {
89
- if (!this._trigger) {
90
- return;
91
- }
92
-
93
- const {position, tipOffset, updateOnMove, adjustArrow} = this.props;
94
- const {
95
- top: clientTop,
96
- left: clientLeft,
97
- right: clientRight,
98
- bottom: clientBottom,
99
- width,
100
- height,
101
- } = this._trigger.getBoundingClientRect();
102
- const tooltipWidth = this._container.offsetWidth;
103
- const tooltipHeight = this._container.offsetHeight;
104
- const {
105
- top: documentTop,
106
- left: documentLeft,
107
- } = DOMUtils.getDocumentOffset(this._trigger);
108
- const top = updateOnMove ? clientTop : documentTop;
109
- const right = updateOnMove ? clientRight : documentLeft + width;
110
- const bottom = updateOnMove ? clientBottom : documentTop + height;
111
- const left = updateOnMove ? clientLeft : documentLeft;
112
- const containerMid =
113
- position === 'top' || position === 'bottom'
114
- ? tooltipWidth / 2
115
- : tooltipHeight / 2;
116
- const bodyWidth = document.body.clientWidth;
117
- const adjuster = 5;
118
- let newTop = 0;
119
- let newLeft = 0;
120
-
121
- switch (position) {
122
- case 'top':
123
- newTop = top - tooltipHeight - tipOffset;
124
- newLeft = left + width / 2 - containerMid;
125
- break;
126
-
127
- case 'right':
128
- newTop = top + height / 2 - containerMid;
129
- newLeft = right + tipOffset;
130
- break;
131
-
132
- case 'bottom':
133
- newTop = bottom + tipOffset;
134
- newLeft = left + width / 2 - containerMid;
135
- break;
136
-
137
- case 'left':
138
- newTop = top + height / 2 - containerMid;
139
- newLeft = left - tooltipWidth - tipOffset;
140
- break;
141
- }
142
-
143
- // adjust tooltip position if off the left side of the screen
144
- let adjustedLeft = newLeft < 0 ? adjuster : newLeft;
145
-
146
- // adjust tooltip position if off the right side of the screen
147
- if (tooltipWidth > bodyWidth - adjustedLeft) {
148
- adjustedLeft = bodyWidth - tooltipWidth - adjuster;
149
- }
150
-
151
- this._container.style.top = `${newTop}px`;
152
- this._container.style.left = `${adjustedLeft}px`;
153
-
154
- if (
155
- adjustArrow &&
156
- !this._isArrowAdjusted &&
157
- adjustedLeft !== newLeft &&
158
- (position === 'top' || position === 'bottom')
159
- ) {
160
- this._arrow.style.left = `${
161
- this._arrow.getBoundingClientRect().left +
162
- (newLeft - adjustedLeft)
163
- }px`;
164
-
165
- this._isArrowAdjusted = true;
166
- }
167
- }
168
-
169
- /**
170
- * Hides the Tooltip programmatically and fires the `onHidden` callback when done.
171
- *
172
- * @public
173
- * @returns {void}
174
- */
175
- hide() {
176
- if (DOMUtils.hasClass(this._container, 'Tooltip-showing')) {
177
- DOMUtils.removeClass(this._container, 'Tooltip-showing');
178
-
179
- setTimeout(() => {
180
- this.props.onHidden();
181
- }, 250);
182
- }
183
- }
184
-
185
- render() {
186
- const {
187
- className,
188
- containerClassName,
189
- position,
190
- showClose,
191
- children,
192
- } = this.props;
193
- const classes = classNames(
194
- 'Tooltip',
195
- `Tooltip-${position}`,
196
- {'Tooltip-no-close': !showClose},
197
- className
198
- );
199
-
200
- return (
201
- <Portal className={containerClassName}>
202
- <div
203
- ref={node => {
204
- this._container = node;
205
- }}
206
- className={classes}
207
- role="tooltip"
208
- >
209
- <div
210
- ref={node => {
211
- this._arrow = node;
212
- }}
213
- className="Tooltip-arrow"
214
- />
215
- <div className="Tooltip-content">
216
- {children}
217
- {showClose && (
218
- <Button
219
- className="Tooltip-close"
220
- onClick={this._onCloseClick}
221
- >
222
- <IconTimes />
223
- </Button>
224
- )}
225
- </div>
226
- </div>
227
- </Portal>
228
- );
229
- }
230
- }