rsuite 4.10.3 → 4.10.7

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.
@@ -36,6 +36,7 @@ function (_React$Component) {
36
36
  _this.triggerRef = void 0;
37
37
  _this.containerRef = void 0;
38
38
  _this.positionRef = void 0;
39
+ _this.menuWrapperRef = void 0;
39
40
  _this.menuContainerRef = void 0;
40
41
  _this.isControlled = void 0;
41
42
 
@@ -291,7 +292,7 @@ function (_React$Component) {
291
292
  items: []
292
293
  };
293
294
  _this.state = _extends({}, initState, {}, getDerivedStateForCascade(props, initState), {
294
- flattenData: flattenTree(props.data)
295
+ flattenData: flattenTree(props.data, props.childrenKey)
295
296
  });
296
297
  _this.isControlled = !_isUndefined(props.value);
297
298
  _this.triggerRef = React.createRef();
@@ -299,6 +300,7 @@ function (_React$Component) {
299
300
  _this.positionRef = React.createRef();
300
301
  _this.toggleRef = React.createRef(); // for test
301
302
 
303
+ _this.menuWrapperRef = React.createRef();
302
304
  _this.menuContainerRef = React.createRef();
303
305
  return _this;
304
306
  }
@@ -307,7 +309,8 @@ function (_React$Component) {
307
309
  var value = nextProps.value,
308
310
  data = nextProps.data,
309
311
  labelKey = nextProps.labelKey,
310
- valueKey = nextProps.valueKey;
312
+ valueKey = nextProps.valueKey,
313
+ childrenKey = nextProps.childrenKey;
311
314
 
312
315
  if (data !== prevState.data) {
313
316
  var _prevState$selectNode;
@@ -325,12 +328,12 @@ function (_React$Component) {
325
328
  return _stringToObject(item, labelKey, valueKey);
326
329
  })), {
327
330
  data: data,
328
- flattenData: flattenTree(data)
331
+ flattenData: flattenTree(data, childrenKey)
329
332
  });
330
333
  }
331
334
 
332
335
  return _extends({}, getDerivedStateForCascade(nextProps, prevState), {
333
- flattenData: flattenTree(data),
336
+ flattenData: flattenTree(data, childrenKey),
334
337
  data: data
335
338
  });
336
339
  }
@@ -441,6 +444,7 @@ function (_React$Component) {
441
444
  var menuProps = _pick(this.props, Object.keys(_omit(dropdownMenuPropTypes, ['classPrefix'])));
442
445
 
443
446
  return React.createElement(MenuWrapper, {
447
+ ref: this.menuWrapperRef,
444
448
  className: classes,
445
449
  style: menuStyle,
446
450
  getToggleInstance: this.getToggleInstance,
@@ -164,6 +164,17 @@ function (_React$Component) {
164
164
  }
165
165
  };
166
166
 
167
+ _proto.componentDidUpdate = function componentDidUpdate(prevProps) {
168
+ var preValue = prevProps.value;
169
+ var currentValue = this.props.value;
170
+
171
+ if (preValue !== currentValue) {
172
+ this.setState({
173
+ value: currentValue
174
+ });
175
+ }
176
+ };
177
+
167
178
  _proto.getValue = function getValue() {
168
179
  var value = this.props.value;
169
180
  return _isUndefined(value) ? this.state.value : value;
@@ -48,6 +48,7 @@ function (_React$Component2) {
48
48
  _this.lastFocus = null;
49
49
  _this.onDocumentKeyupListener = null;
50
50
  _this.onFocusinListener = null;
51
+ _this._isMounted = null;
51
52
 
52
53
  _this.setMountNodeRef = function (ref) {
53
54
  var _ref$getMountNode;
@@ -95,15 +96,30 @@ function (_React$Component2) {
95
96
  _this.enforceFocus = function () {
96
97
  var enforceFocus = _this.props.enforceFocus;
97
98
 
98
- if (!enforceFocus || !_this.isTopModal()) {
99
+ if (!enforceFocus || !_this._isMounted || !_this.isTopModal()) {
99
100
  return;
100
101
  }
101
102
 
102
- var active = activeElement(ownerDocument(_assertThisInitialized(_this)));
103
+ var currentActiveElement = activeElement(ownerDocument(_assertThisInitialized(_this)));
103
104
 
104
105
  var modal = _this.getDialogElement();
105
106
 
106
- if (modal && modal !== active && !contains(modal, active)) {
107
+ if (modal && modal !== currentActiveElement && !contains(modal, currentActiveElement)) {
108
+ modal.focus();
109
+ }
110
+ };
111
+
112
+ _this.handlePortalRendered = function () {
113
+ if (!_this.props.autoFocus) {
114
+ return;
115
+ }
116
+
117
+ var modal = _this.getDialogElement();
118
+
119
+ var currentActiveElement = activeElement(ownerDocument(_assertThisInitialized(_this)));
120
+
121
+ if (modal && modal !== currentActiveElement && !contains(modal, currentActiveElement)) {
122
+ _this.lastFocus = currentActiveElement;
107
123
  modal.focus();
108
124
  }
109
125
  };
@@ -120,6 +136,8 @@ function (_React$Component2) {
120
136
  var _proto2 = BaseModal.prototype;
121
137
 
122
138
  _proto2.componentDidMount = function componentDidMount() {
139
+ this._isMounted = true;
140
+
123
141
  if (this.props.show) {
124
142
  this.onShow();
125
143
  }
@@ -163,6 +181,7 @@ function (_React$Component2) {
163
181
  var _this$props4 = this.props,
164
182
  show = _this$props4.show,
165
183
  transition = _this$props4.transition;
184
+ this._isMounted = false;
166
185
 
167
186
  if (show || transition && !this.state.exited) {
168
187
  this.onHide();
@@ -293,7 +312,8 @@ function (_React$Component2) {
293
312
 
294
313
  return React.createElement(Portal, {
295
314
  ref: this.setMountNodeRef,
296
- container: container
315
+ container: container,
316
+ onRendered: this.handlePortalRendered
297
317
  }, React.createElement("div", {
298
318
  ref: this.modalNodeRef,
299
319
  role: rest.role,
@@ -66,6 +66,7 @@ function (_React$Component) {
66
66
  return React.createElement("div", _extends({}, props, {
67
67
  title: null,
68
68
  role: "dialog",
69
+ tabIndex: -1,
69
70
  ref: mergeRefs(this.bindHtmlRef, dialogRef),
70
71
  className: classNames(classPrefix, className),
71
72
  style: modalStyle
@@ -1,7 +1,9 @@
1
1
  import * as React from 'react';
2
- import { StandardProps } from '../@types/common';
2
+ import { StandardProps, FormControlBaseProps } from '../@types/common';
3
3
 
4
- export interface SliderProps<ValueType = number> extends StandardProps {
4
+ export interface SliderProps<ValueType = number>
5
+ extends StandardProps,
6
+ FormControlBaseProps<ValueType> {
5
7
  /** Minimum value of sliding range */
6
8
  min?: number;
7
9
 
@@ -11,12 +13,6 @@ export interface SliderProps<ValueType = number> extends StandardProps {
11
13
  /** Slide the value of one step */
12
14
  step?: number;
13
15
 
14
- /** Value (Controlled) */
15
- value?: ValueType;
16
-
17
- /** Default value */
18
- defaultValue?: ValueType;
19
-
20
16
  /** A css class to apply to the Handle node. */
21
17
  handleClassName?: string;
22
18
 
@@ -44,9 +40,6 @@ export interface SliderProps<ValueType = number> extends StandardProps {
44
40
  /** Vertical Slide */
45
41
  vertical?: boolean;
46
42
 
47
- /** Callback function that changes data */
48
- onChange?: (value: ValueType, event: React.MouseEvent) => void;
49
-
50
43
  /** Customize labels on the render ruler */
51
44
  renderMark?: (mark: number) => React.ReactNode;
52
45
  }
@@ -268,7 +268,7 @@ function (_React$Component) {
268
268
  fileList: nextFileList
269
269
  };
270
270
 
271
- if (nextFile.progress) {
271
+ if (nextFile.progress || nextFile.status === 'error') {
272
272
  var fileMap = this.state.fileMap;
273
273
  fileMap[nextFile.fileKey] = {
274
274
  progress: nextFile.progress,
@@ -66,6 +66,7 @@ function (_React$Component) {
66
66
  _this.triggerRef = void 0;
67
67
  _this.containerRef = void 0;
68
68
  _this.positionRef = void 0;
69
+ _this.menuWrapperRef = void 0;
69
70
  _this.menuContainerRef = void 0;
70
71
  _this.isControlled = void 0;
71
72
 
@@ -321,7 +322,7 @@ function (_React$Component) {
321
322
  items: []
322
323
  };
323
324
  _this.state = (0, _extends3.default)({}, initState, {}, (0, _utils.getDerivedStateForCascade)(props, initState), {
324
- flattenData: (0, _treeUtils.flattenTree)(props.data)
325
+ flattenData: (0, _treeUtils.flattenTree)(props.data, props.childrenKey)
325
326
  });
326
327
  _this.isControlled = !(0, _isUndefined2.default)(props.value);
327
328
  _this.triggerRef = React.createRef();
@@ -329,6 +330,7 @@ function (_React$Component) {
329
330
  _this.positionRef = React.createRef();
330
331
  _this.toggleRef = React.createRef(); // for test
331
332
 
333
+ _this.menuWrapperRef = React.createRef();
332
334
  _this.menuContainerRef = React.createRef();
333
335
  return _this;
334
336
  }
@@ -337,7 +339,8 @@ function (_React$Component) {
337
339
  var value = nextProps.value,
338
340
  data = nextProps.data,
339
341
  labelKey = nextProps.labelKey,
340
- valueKey = nextProps.valueKey;
342
+ valueKey = nextProps.valueKey,
343
+ childrenKey = nextProps.childrenKey;
341
344
 
342
345
  if (data !== prevState.data) {
343
346
  var _prevState$selectNode;
@@ -355,12 +358,12 @@ function (_React$Component) {
355
358
  return (0, _stringToObject2.default)(item, labelKey, valueKey);
356
359
  })), {
357
360
  data: data,
358
- flattenData: (0, _treeUtils.flattenTree)(data)
361
+ flattenData: (0, _treeUtils.flattenTree)(data, childrenKey)
359
362
  });
360
363
  }
361
364
 
362
365
  return (0, _extends3.default)({}, (0, _utils.getDerivedStateForCascade)(nextProps, prevState), {
363
- flattenData: (0, _treeUtils.flattenTree)(data),
366
+ flattenData: (0, _treeUtils.flattenTree)(data, childrenKey),
364
367
  data: data
365
368
  });
366
369
  }
@@ -469,6 +472,7 @@ function (_React$Component) {
469
472
  var classes = (0, _classnames.default)(this.addPrefix('cascader-menu'), menuClassName, (_classNames2 = {}, _classNames2[this.addPrefix('inline')] = inline, _classNames2));
470
473
  var menuProps = (0, _pick2.default)(this.props, Object.keys((0, _omit2.default)(_DropdownMenu.dropdownMenuPropTypes, ['classPrefix'])));
471
474
  return React.createElement(_Picker.MenuWrapper, {
475
+ ref: this.menuWrapperRef,
472
476
  className: classes,
473
477
  style: menuStyle,
474
478
  getToggleInstance: this.getToggleInstance,
@@ -189,6 +189,17 @@ function (_React$Component) {
189
189
  }
190
190
  };
191
191
 
192
+ _proto.componentDidUpdate = function componentDidUpdate(prevProps) {
193
+ var preValue = prevProps.value;
194
+ var currentValue = this.props.value;
195
+
196
+ if (preValue !== currentValue) {
197
+ this.setState({
198
+ value: currentValue
199
+ });
200
+ }
201
+ };
202
+
192
203
  _proto.getValue = function getValue() {
193
204
  var value = this.props.value;
194
205
  return (0, _isUndefined2.default)(value) ? this.state.value : value;
@@ -69,6 +69,7 @@ function (_React$Component2) {
69
69
  _this.lastFocus = null;
70
70
  _this.onDocumentKeyupListener = null;
71
71
  _this.onFocusinListener = null;
72
+ _this._isMounted = null;
72
73
 
73
74
  _this.setMountNodeRef = function (ref) {
74
75
  var _ref$getMountNode;
@@ -116,15 +117,30 @@ function (_React$Component2) {
116
117
  _this.enforceFocus = function () {
117
118
  var enforceFocus = _this.props.enforceFocus;
118
119
 
119
- if (!enforceFocus || !_this.isTopModal()) {
120
+ if (!enforceFocus || !_this._isMounted || !_this.isTopModal()) {
120
121
  return;
121
122
  }
122
123
 
123
- var active = (0, _domLib.activeElement)((0, _domLib.ownerDocument)((0, _assertThisInitialized2.default)(_this)));
124
+ var currentActiveElement = (0, _domLib.activeElement)((0, _domLib.ownerDocument)((0, _assertThisInitialized2.default)(_this)));
124
125
 
125
126
  var modal = _this.getDialogElement();
126
127
 
127
- if (modal && modal !== active && !(0, _domLib.contains)(modal, active)) {
128
+ if (modal && modal !== currentActiveElement && !(0, _domLib.contains)(modal, currentActiveElement)) {
129
+ modal.focus();
130
+ }
131
+ };
132
+
133
+ _this.handlePortalRendered = function () {
134
+ if (!_this.props.autoFocus) {
135
+ return;
136
+ }
137
+
138
+ var modal = _this.getDialogElement();
139
+
140
+ var currentActiveElement = (0, _domLib.activeElement)((0, _domLib.ownerDocument)((0, _assertThisInitialized2.default)(_this)));
141
+
142
+ if (modal && modal !== currentActiveElement && !(0, _domLib.contains)(modal, currentActiveElement)) {
143
+ _this.lastFocus = currentActiveElement;
128
144
  modal.focus();
129
145
  }
130
146
  };
@@ -141,6 +157,8 @@ function (_React$Component2) {
141
157
  var _proto2 = BaseModal.prototype;
142
158
 
143
159
  _proto2.componentDidMount = function componentDidMount() {
160
+ this._isMounted = true;
161
+
144
162
  if (this.props.show) {
145
163
  this.onShow();
146
164
  }
@@ -184,6 +202,7 @@ function (_React$Component2) {
184
202
  var _this$props4 = this.props,
185
203
  show = _this$props4.show,
186
204
  transition = _this$props4.transition;
205
+ this._isMounted = false;
187
206
 
188
207
  if (show || transition && !this.state.exited) {
189
208
  this.onHide();
@@ -312,7 +331,8 @@ function (_React$Component2) {
312
331
 
313
332
  return React.createElement(_Portal.default, {
314
333
  ref: this.setMountNodeRef,
315
- container: container
334
+ container: container,
335
+ onRendered: this.handlePortalRendered
316
336
  }, React.createElement("div", {
317
337
  ref: this.modalNodeRef,
318
338
  role: rest.role,
@@ -82,6 +82,7 @@ function (_React$Component) {
82
82
  return React.createElement("div", (0, _extends2.default)({}, props, {
83
83
  title: null,
84
84
  role: "dialog",
85
+ tabIndex: -1,
85
86
  ref: (0, _mergeRefs.default)(this.bindHtmlRef, dialogRef),
86
87
  className: (0, _classnames.default)(classPrefix, className),
87
88
  style: modalStyle
@@ -1,7 +1,9 @@
1
1
  import * as React from 'react';
2
- import { StandardProps } from '../@types/common';
2
+ import { StandardProps, FormControlBaseProps } from '../@types/common';
3
3
 
4
- export interface SliderProps<ValueType = number> extends StandardProps {
4
+ export interface SliderProps<ValueType = number>
5
+ extends StandardProps,
6
+ FormControlBaseProps<ValueType> {
5
7
  /** Minimum value of sliding range */
6
8
  min?: number;
7
9
 
@@ -11,12 +13,6 @@ export interface SliderProps<ValueType = number> extends StandardProps {
11
13
  /** Slide the value of one step */
12
14
  step?: number;
13
15
 
14
- /** Value (Controlled) */
15
- value?: ValueType;
16
-
17
- /** Default value */
18
- defaultValue?: ValueType;
19
-
20
16
  /** A css class to apply to the Handle node. */
21
17
  handleClassName?: string;
22
18
 
@@ -44,9 +40,6 @@ export interface SliderProps<ValueType = number> extends StandardProps {
44
40
  /** Vertical Slide */
45
41
  vertical?: boolean;
46
42
 
47
- /** Callback function that changes data */
48
- onChange?: (value: ValueType, event: React.MouseEvent) => void;
49
-
50
43
  /** Customize labels on the render ruler */
51
44
  renderMark?: (mark: number) => React.ReactNode;
52
45
  }
@@ -289,7 +289,7 @@ function (_React$Component) {
289
289
  fileList: nextFileList
290
290
  };
291
291
 
292
- if (nextFile.progress) {
292
+ if (nextFile.progress || nextFile.status === 'error') {
293
293
  var fileMap = this.state.fileMap;
294
294
  fileMap[nextFile.fileKey] = {
295
295
  progress: nextFile.progress,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rsuite",
3
- "version": "4.10.3",
3
+ "version": "4.10.7",
4
4
  "description": "A suite of react components",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
@@ -29,7 +29,8 @@
29
29
  "test:component": "cross-env NODE_ENV=coverage RUN_ENV=test karma start --single-run",
30
30
  "test:styles": "node test/stylesSpec.js",
31
31
  "coveralls": "cat ./coverage/lcov/lcov.info | ./node_modules/.bin/coveralls",
32
- "prepublishOnly": "npm run build"
32
+ "prepublishOnly": "npm run build",
33
+ "version": "npm run changelog && git add -A"
33
34
  },
34
35
  "keywords": [
35
36
  "react",
@@ -62,7 +63,7 @@
62
63
  "prop-types": "^15.7.2",
63
64
  "react-lifecycles-compat": "^3.0.4",
64
65
  "react-virtualized": "^9.21.0",
65
- "rsuite-table": "^3.15.1",
66
+ "rsuite-table": "^3.16.0",
66
67
  "schema-typed": "^1.5.1"
67
68
  },
68
69
  "peerDependencies": {
@@ -111,7 +112,7 @@
111
112
  "css-loader": "^0.28.11",
112
113
  "cssnano": "^4.1.10",
113
114
  "del": "^3.0.0",
114
- "dtslint": "^0.3.0",
115
+ "dtslint": "^4.2.1",
115
116
  "enzyme": "^3.3.0",
116
117
  "enzyme-adapter-react-16": "^1.1.1",
117
118
  "eslint": "^6.7.2",
@@ -73,6 +73,7 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
73
73
  triggerRef: React.RefObject<any>;
74
74
  containerRef: React.RefObject<any>;
75
75
  positionRef: React.RefObject<any>;
76
+ menuWrapperRef: React.RefObject<any>;
76
77
  menuContainerRef: React.RefObject<any>;
77
78
  isControlled: boolean;
78
79
 
@@ -98,7 +99,7 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
98
99
  this.state = {
99
100
  ...initState,
100
101
  ...getDerivedStateForCascade(props, initState),
101
- flattenData: flattenTree(props.data)
102
+ flattenData: flattenTree(props.data, props.childrenKey)
102
103
  };
103
104
 
104
105
  this.isControlled = !_.isUndefined(props.value);
@@ -108,11 +109,12 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
108
109
  this.toggleRef = React.createRef();
109
110
 
110
111
  // for test
112
+ this.menuWrapperRef = React.createRef();
111
113
  this.menuContainerRef = React.createRef();
112
114
  }
113
115
 
114
116
  static getDerivedStateFromProps(nextProps, prevState) {
115
- const { value, data, labelKey, valueKey } = nextProps;
117
+ const { value, data, labelKey, valueKey, childrenKey } = nextProps;
116
118
  if (data !== prevState.data) {
117
119
  // First get the value of the clicked node `selectNodeValue`, and then get the new `newChildren`.
118
120
  const selectNodeValue = prevState?.selectNode?.[valueKey];
@@ -129,13 +131,13 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
129
131
  newChildren.map(item => stringToObject(item, labelKey, valueKey))
130
132
  ),
131
133
  data,
132
- flattenData: flattenTree(data)
134
+ flattenData: flattenTree(data, childrenKey)
133
135
  };
134
136
  }
135
137
 
136
138
  return {
137
139
  ...getDerivedStateForCascade(nextProps, prevState),
138
- flattenData: flattenTree(data),
140
+ flattenData: flattenTree(data, childrenKey),
139
141
  data
140
142
  };
141
143
  }
@@ -450,6 +452,7 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
450
452
 
451
453
  return (
452
454
  <MenuWrapper
455
+ ref={this.menuWrapperRef}
453
456
  className={classes}
454
457
  style={menuStyle}
455
458
  getToggleInstance={this.getToggleInstance}
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import ReactTestUtils from 'react-dom/test-utils';
2
+ import ReactTestUtils, { act } from 'react-dom/test-utils';
3
3
  import Cascader from '../Cascader';
4
4
  import Button from '../../Button';
5
5
  import { getDOMNode, getInstance } from '@test/testUtils';
@@ -214,4 +214,59 @@ describe('Cascader', () => {
214
214
  assert.equal(instance2.querySelector('.rs-picker-toggle-placeholder').innerText, 'Select');
215
215
  assert.equal(instance3.querySelector('.rs-picker-toggle-placeholder').innerText, 'Select');
216
216
  });
217
+
218
+ it('Should show search items with childrenKey', () => {
219
+ const itemsWithChildrenKey = {
220
+ childrenKey: 'sub',
221
+ data: [
222
+ {
223
+ value: 't',
224
+ label: 't'
225
+ },
226
+ {
227
+ value: 'h',
228
+ label: 'h'
229
+ },
230
+ {
231
+ value: 'g',
232
+ label: 'g',
233
+ sub: [
234
+ {
235
+ value: 'g-m',
236
+ label: 'g-m'
237
+ },
238
+ {
239
+ value: 'g-b',
240
+ label: 'g-b'
241
+ }
242
+ ]
243
+ }
244
+ ]
245
+ };
246
+
247
+ const instance = getInstance(
248
+ <Cascader
249
+ defaultOpen
250
+ data={itemsWithChildrenKey.data}
251
+ childrenKey={itemsWithChildrenKey.childrenKey}
252
+ />
253
+ );
254
+
255
+ const overlay = getDOMNode(instance.menuWrapperRef.current);
256
+
257
+ ReactTestUtils.act(() => {
258
+ const input = overlay.querySelector('.rs-picker-search-bar-input');
259
+
260
+ ReactTestUtils.Simulate.focus(input);
261
+
262
+ input.value = 'g';
263
+ ReactTestUtils.Simulate.change(input);
264
+ });
265
+
266
+ ReactTestUtils.act(() => {
267
+ const searchResult = overlay.querySelectorAll('.rs-picker-cascader-row');
268
+
269
+ assert.equal(searchResult.length, 2);
270
+ });
271
+ });
217
272
  });
@@ -115,6 +115,15 @@ class InputNumber extends React.Component<InputNumberProps, InputNumberState> {
115
115
  this.inputWheelListener.off();
116
116
  }
117
117
  }
118
+ componentDidUpdate(prevProps: InputNumberProps) {
119
+ const { value: preValue } = prevProps;
120
+ const { value: currentValue } = this.props;
121
+ if (preValue !== currentValue) {
122
+ this.setState({
123
+ value: currentValue
124
+ });
125
+ }
126
+ }
118
127
 
119
128
  bindInputRef = ref => {
120
129
  this.input = ref;
@@ -149,4 +149,29 @@ describe('InputNumber', () => {
149
149
  const instance = getDOMNode(<InputNumber classPrefix="custom-prefix" />);
150
150
  assert.ok(instance.className.match(/\bcustom-prefix\b/));
151
151
  });
152
+ it('should be change correct value when reset value', () => {
153
+ let refValue = 0;
154
+ const Wrapper = React.forwardRef((props, ref) => {
155
+ const [value, setValue] = React.useState(refValue);
156
+ const reset = () => {
157
+ setValue(null);
158
+ };
159
+ refValue = value;
160
+ return (
161
+ <div ref={ref}>
162
+ <InputNumber value={value} onChange={setValue} />
163
+ <button id="reset" onClick={reset}>
164
+ reset
165
+ </button>
166
+ </div>
167
+ );
168
+ });
169
+ const instance = getDOMNode(<Wrapper />);
170
+ const resetBtn = instance.querySelector('#reset');
171
+ ReactTestUtils.Simulate.change(instance.querySelector('.rs-input'), { target: { value: 1 } });
172
+ ReactTestUtils.Simulate.click(resetBtn);
173
+ ReactTestUtils.Simulate.change(instance.querySelector('.rs-input'), { target: { value: 1 } });
174
+
175
+ assert.equal(refValue, 1);
176
+ });
152
177
  });
@@ -50,6 +50,7 @@ class BaseModal extends React.Component<BaseModalProps, BaseModalState> {
50
50
  lastFocus = null;
51
51
  onDocumentKeyupListener = null;
52
52
  onFocusinListener = null;
53
+ _isMounted = null;
53
54
 
54
55
  constructor(props: BaseModalProps) {
55
56
  super(props);
@@ -59,6 +60,7 @@ class BaseModal extends React.Component<BaseModalProps, BaseModalState> {
59
60
  this.dialogRef = React.createRef();
60
61
  }
61
62
  componentDidMount() {
63
+ this._isMounted = true;
62
64
  if (this.props.show) {
63
65
  this.onShow();
64
66
  }
@@ -95,6 +97,8 @@ class BaseModal extends React.Component<BaseModalProps, BaseModalState> {
95
97
  componentWillUnmount() {
96
98
  const { show, transition } = this.props;
97
99
 
100
+ this._isMounted = false;
101
+
98
102
  if (show || (transition && !this.state.exited)) {
99
103
  this.onHide();
100
104
  }
@@ -173,14 +177,28 @@ class BaseModal extends React.Component<BaseModalProps, BaseModalState> {
173
177
  enforceFocus = () => {
174
178
  const { enforceFocus } = this.props;
175
179
 
176
- if (!enforceFocus || !this.isTopModal()) {
180
+ if (!enforceFocus || !this._isMounted || !this.isTopModal()) {
181
+ return;
182
+ }
183
+
184
+ const currentActiveElement = activeElement(ownerDocument(this));
185
+ const modal = this.getDialogElement();
186
+
187
+ if (modal && modal !== currentActiveElement && !contains(modal, currentActiveElement)) {
188
+ modal.focus();
189
+ }
190
+ };
191
+
192
+ handlePortalRendered = () => {
193
+ if (!this.props.autoFocus) {
177
194
  return;
178
195
  }
179
196
 
180
- const active = activeElement(ownerDocument(this));
181
197
  const modal = this.getDialogElement();
198
+ const currentActiveElement = activeElement(ownerDocument(this));
182
199
 
183
- if (modal && modal !== active && !contains(modal, active)) {
200
+ if (modal && modal !== currentActiveElement && !contains(modal, currentActiveElement)) {
201
+ this.lastFocus = currentActiveElement;
184
202
  modal.focus();
185
203
  }
186
204
  };
@@ -268,7 +286,11 @@ class BaseModal extends React.Component<BaseModalProps, BaseModalState> {
268
286
  }
269
287
 
270
288
  return (
271
- <Portal ref={this.setMountNodeRef} container={container}>
289
+ <Portal
290
+ ref={this.setMountNodeRef}
291
+ container={container}
292
+ onRendered={this.handlePortalRendered}
293
+ >
272
294
  <div ref={this.modalNodeRef} role={rest.role} style={style} className={className}>
273
295
  {backdrop && this.renderBackdrop()}
274
296
  <RefHolder ref={this.dialogRef}>{dialog}</RefHolder>
@@ -53,6 +53,7 @@ class ModalDialog extends React.Component<ModalDialogProps> {
53
53
  {...props}
54
54
  title={null}
55
55
  role="dialog"
56
+ tabIndex={-1}
56
57
  ref={mergeRefs(this.bindHtmlRef, dialogRef)}
57
58
  className={classNames(classPrefix, className)}
58
59
  style={modalStyle}