rsuite 4.9.3 → 4.10.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.
- package/CHANGELOG.md +42 -0
- package/dist/rsuite.js +18 -601
- package/dist/rsuite.min.js +2 -2
- package/dist/rsuite.min.js.map +1 -1
- package/dist/styles/rsuite-dark-rtl.css +2 -1
- package/dist/styles/rsuite-dark-rtl.min.css +1 -1
- package/dist/styles/rsuite-dark-rtl.min.css.map +1 -1
- package/dist/styles/rsuite-dark.css +2 -1
- package/dist/styles/rsuite-dark.min.css +1 -1
- package/dist/styles/rsuite-dark.min.css.map +1 -1
- package/dist/styles/rsuite-default-rtl.css +2 -1
- package/dist/styles/rsuite-default-rtl.min.css +1 -1
- package/dist/styles/rsuite-default-rtl.min.css.map +1 -1
- package/dist/styles/rsuite-default.css +2 -1
- package/dist/styles/rsuite-default.min.css +1 -1
- package/dist/styles/rsuite-default.min.css.map +1 -1
- package/es/CheckTreePicker/CheckTreePicker.js +8 -7
- package/es/MultiCascader/DropdownMenu.js +1 -1
- package/es/MultiCascader/MultiCascader.d.ts +8 -0
- package/es/MultiCascader/MultiCascader.js +6 -3
- package/es/Overlay/OverlayTrigger.d.ts +1 -1
- package/es/Overlay/OverlayTrigger.js +12 -1
- package/es/Table/styles/common.less +2 -1
- package/es/utils/treeUtils.js +5 -1
- package/lib/CheckTreePicker/CheckTreePicker.js +8 -7
- package/lib/MultiCascader/DropdownMenu.js +1 -1
- package/lib/MultiCascader/MultiCascader.d.ts +8 -0
- package/lib/MultiCascader/MultiCascader.js +6 -3
- package/lib/Overlay/OverlayTrigger.d.ts +1 -1
- package/lib/Overlay/OverlayTrigger.js +12 -1
- package/lib/Table/styles/common.less +2 -1
- package/lib/utils/treeUtils.js +5 -1
- package/package.json +3 -3
- package/src/CheckTreePicker/CheckTreePicker.tsx +15 -7
- package/src/CheckTreePicker/test/CheckTreePickerSpec.js +184 -1
- package/src/MultiCascader/DropdownMenu.tsx +1 -1
- package/src/MultiCascader/MultiCascader.d.ts +8 -0
- package/src/MultiCascader/MultiCascader.tsx +4 -2
- package/src/MultiCascader/test/DropdownMenuSpec.js +17 -0
- package/src/MultiCascader/test/MultiCascaderSpec.js +14 -1
- package/src/Overlay/OverlayTrigger.d.ts +1 -1
- package/src/Overlay/OverlayTrigger.tsx +22 -1
- package/src/Overlay/test/OverlayTriggerSpec.js +155 -0
- package/src/Table/styles/common.less +2 -1
- package/src/TreePicker/test/TreePickerSpec.js +43 -15
- package/src/utils/treeUtils.ts +4 -1
|
@@ -4,10 +4,23 @@ import Enzyme, { mount } from 'enzyme';
|
|
|
4
4
|
import Adapter from 'enzyme-adapter-react-16';
|
|
5
5
|
import { getDOMNode, getInstance } from '@test/testUtils';
|
|
6
6
|
import CheckTreePicker from '../CheckTreePicker';
|
|
7
|
-
import { findDOMNode } from 'react-dom';
|
|
7
|
+
import ReactDOM, { findDOMNode } from 'react-dom';
|
|
8
|
+
import { assert } from 'chai';
|
|
8
9
|
|
|
9
10
|
Enzyme.configure({ adapter: new Adapter() });
|
|
10
11
|
|
|
12
|
+
let container;
|
|
13
|
+
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
container = document.createElement('div');
|
|
16
|
+
document.body.appendChild(container);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
afterEach(() => {
|
|
20
|
+
document.body.removeChild(container);
|
|
21
|
+
container = null;
|
|
22
|
+
});
|
|
23
|
+
|
|
11
24
|
const data = [
|
|
12
25
|
{
|
|
13
26
|
label: 'Master',
|
|
@@ -298,6 +311,66 @@ describe('CheckTreePicker', () => {
|
|
|
298
311
|
instance.unmount();
|
|
299
312
|
});
|
|
300
313
|
|
|
314
|
+
it('Should return 2 values', done => {
|
|
315
|
+
const customData = [
|
|
316
|
+
{
|
|
317
|
+
value: '1',
|
|
318
|
+
label: '1',
|
|
319
|
+
children: [
|
|
320
|
+
{
|
|
321
|
+
value: '1-1',
|
|
322
|
+
label: '1-1'
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
value: '1-2',
|
|
326
|
+
label: '1-2'
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
value: '1-3',
|
|
330
|
+
label: '1-3'
|
|
331
|
+
}
|
|
332
|
+
]
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
value: '2',
|
|
336
|
+
label: '2',
|
|
337
|
+
children: [
|
|
338
|
+
{
|
|
339
|
+
value: '2-1',
|
|
340
|
+
label: '2-1'
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
value: '2-2',
|
|
344
|
+
label: '2-2'
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
value: '2-3',
|
|
348
|
+
label: '2-3'
|
|
349
|
+
}
|
|
350
|
+
]
|
|
351
|
+
}
|
|
352
|
+
];
|
|
353
|
+
|
|
354
|
+
const doneOp = values => {
|
|
355
|
+
if (values.length === 2) {
|
|
356
|
+
done();
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
const instance = getDOMNode(
|
|
360
|
+
<CheckTreePicker
|
|
361
|
+
data={customData}
|
|
362
|
+
inline
|
|
363
|
+
value={['1-1', '1-2', '1-3']}
|
|
364
|
+
cascade
|
|
365
|
+
defaultExpandAll
|
|
366
|
+
onChange={doneOp}
|
|
367
|
+
/>
|
|
368
|
+
);
|
|
369
|
+
|
|
370
|
+
assert.equal(instance.querySelectorAll('.rs-checkbox-checked').length, 4);
|
|
371
|
+
ReactTestUtils.Simulate.change(instance.querySelectorAll('.rs-check-tree-node input')[5]);
|
|
372
|
+
});
|
|
373
|
+
|
|
301
374
|
it('Should render empty tree when searchKeyword is `name`', () => {
|
|
302
375
|
const instance = mount(<CheckTreePicker data={data} inline searchKeyword="name" />);
|
|
303
376
|
assert.equal(instance.find('.rs-check-tree-node').length, 0);
|
|
@@ -384,4 +457,114 @@ describe('CheckTreePicker', () => {
|
|
|
384
457
|
assert.equal(instance2.querySelector('.rs-picker-toggle-placeholder').innerText, 'Select');
|
|
385
458
|
assert.equal(instance3.querySelector('.rs-picker-toggle-placeholder').innerText, 'Select');
|
|
386
459
|
});
|
|
460
|
+
|
|
461
|
+
it('Should controlled by value', () => {
|
|
462
|
+
const TestApp = React.forwardRef((props, ref) => {
|
|
463
|
+
const [value, setValue] = React.useState();
|
|
464
|
+
const pickerRef = React.useRef();
|
|
465
|
+
React.useImperativeHandle(ref, () => ({
|
|
466
|
+
picker: pickerRef.current,
|
|
467
|
+
setValue
|
|
468
|
+
}));
|
|
469
|
+
|
|
470
|
+
return <CheckTreePicker data={data} ref={pickerRef} value={value} defaultExpandAll open />;
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
TestApp.displayName = 'TestCheckTreePicker';
|
|
474
|
+
|
|
475
|
+
const ref = React.createRef();
|
|
476
|
+
ReactTestUtils.act(() => {
|
|
477
|
+
ReactDOM.render(<TestApp ref={ref} />, container);
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
assert.equal(
|
|
481
|
+
ref.current.picker.treeViewRef.current.querySelectorAll('.rs-checkbox-checked').length,
|
|
482
|
+
0
|
|
483
|
+
);
|
|
484
|
+
|
|
485
|
+
ReactTestUtils.act(() => {
|
|
486
|
+
ref.current.setValue(['Master']);
|
|
487
|
+
});
|
|
488
|
+
assert.equal(
|
|
489
|
+
ref.current.picker.treeViewRef.current.querySelectorAll('.rs-checkbox-checked').length,
|
|
490
|
+
4
|
|
491
|
+
);
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
it('Should controlled by expandItemValues', () => {
|
|
495
|
+
const TestApp = React.forwardRef((props, ref) => {
|
|
496
|
+
const [expandItemValues, setExpandItemValues] = React.useState();
|
|
497
|
+
const pickerRef = React.useRef();
|
|
498
|
+
React.useImperativeHandle(ref, () => ({
|
|
499
|
+
picker: pickerRef.current,
|
|
500
|
+
setExpandItemValues
|
|
501
|
+
}));
|
|
502
|
+
|
|
503
|
+
return (
|
|
504
|
+
<CheckTreePicker data={data} ref={pickerRef} expandItemValues={expandItemValues} open />
|
|
505
|
+
);
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
TestApp.displayName = 'TestCheckTreePicker';
|
|
509
|
+
|
|
510
|
+
const ref = React.createRef();
|
|
511
|
+
ReactTestUtils.act(() => {
|
|
512
|
+
ReactDOM.render(<TestApp ref={ref} />, container);
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
assert.equal(
|
|
516
|
+
ref.current.picker.treeViewRef.current.querySelectorAll('.rs-check-tree-node-expanded')
|
|
517
|
+
.length,
|
|
518
|
+
0
|
|
519
|
+
);
|
|
520
|
+
|
|
521
|
+
ReactTestUtils.act(() => {
|
|
522
|
+
ref.current.setExpandItemValues(['Master']);
|
|
523
|
+
});
|
|
524
|
+
assert.equal(
|
|
525
|
+
ref.current.picker.treeViewRef.current.querySelectorAll('.rs-check-tree-node-expanded')
|
|
526
|
+
.length,
|
|
527
|
+
1
|
|
528
|
+
);
|
|
529
|
+
});
|
|
530
|
+
|
|
531
|
+
it('Should controlled by uncheckableItemValues', () => {
|
|
532
|
+
const TestApp = React.forwardRef((props, ref) => {
|
|
533
|
+
const [uncheckableItemValues, setUncheckableItemValues] = React.useState();
|
|
534
|
+
const pickerRef = React.useRef();
|
|
535
|
+
React.useImperativeHandle(ref, () => ({
|
|
536
|
+
picker: pickerRef.current,
|
|
537
|
+
setUncheckableItemValues
|
|
538
|
+
}));
|
|
539
|
+
|
|
540
|
+
return (
|
|
541
|
+
<CheckTreePicker
|
|
542
|
+
data={data}
|
|
543
|
+
ref={pickerRef}
|
|
544
|
+
uncheckableItemValues={uncheckableItemValues}
|
|
545
|
+
open
|
|
546
|
+
/>
|
|
547
|
+
);
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
TestApp.displayName = 'TestCheckTreePicker';
|
|
551
|
+
|
|
552
|
+
const ref = React.createRef();
|
|
553
|
+
ReactTestUtils.act(() => {
|
|
554
|
+
ReactDOM.render(<TestApp ref={ref} />, container);
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
assert.equal(
|
|
558
|
+
ref.current.picker.treeViewRef.current.querySelectorAll('.rs-checkbox-inner').length,
|
|
559
|
+
5
|
|
560
|
+
);
|
|
561
|
+
|
|
562
|
+
ReactTestUtils.act(() => {
|
|
563
|
+
ref.current.setUncheckableItemValues(['Master']);
|
|
564
|
+
});
|
|
565
|
+
assert.equal(
|
|
566
|
+
ref.current.picker.treeViewRef.current.querySelectorAll('.rs-checkbox-inner').length,
|
|
567
|
+
4
|
|
568
|
+
);
|
|
569
|
+
});
|
|
387
570
|
});
|
|
@@ -166,7 +166,7 @@ class DropdownMenu extends React.Component<DropdownMenuProps> {
|
|
|
166
166
|
className={classes}
|
|
167
167
|
componentClass="li"
|
|
168
168
|
indeterminate={cascade && !active && this.utils.isSomeChildChecked(node, value)}
|
|
169
|
-
onSelectItem={this.handleSelect.bind(this, layer
|
|
169
|
+
onSelectItem={this.handleSelect.bind(this, layer)}
|
|
170
170
|
onCheck={onCheck}
|
|
171
171
|
checkable={!uncheckable}
|
|
172
172
|
>
|
|
@@ -41,6 +41,14 @@ export interface MultiCascaderProps<ValueType = any> extends FormControlPickerPr
|
|
|
41
41
|
event: React.SyntheticEvent<HTMLElement>
|
|
42
42
|
) => void;
|
|
43
43
|
|
|
44
|
+
/** Called after the checkbox state changes */
|
|
45
|
+
onCheck?: (
|
|
46
|
+
value: ValueType,
|
|
47
|
+
item: any,
|
|
48
|
+
checked: boolean,
|
|
49
|
+
event: React.SyntheticEvent<HTMLElement>
|
|
50
|
+
) => void;
|
|
51
|
+
|
|
44
52
|
/** Called when clean */
|
|
45
53
|
onClean?: (event: React.SyntheticEvent<HTMLElement>) => void;
|
|
46
54
|
|
|
@@ -57,7 +57,8 @@ class MultiCascader extends React.Component<MultiCascaderProps, MultiCascaderSta
|
|
|
57
57
|
renderMenuItem: PropTypes.func,
|
|
58
58
|
renderMenu: PropTypes.func,
|
|
59
59
|
onSearch: PropTypes.func,
|
|
60
|
-
onSelect: PropTypes.func
|
|
60
|
+
onSelect: PropTypes.func,
|
|
61
|
+
onCheck: PropTypes.func
|
|
61
62
|
};
|
|
62
63
|
|
|
63
64
|
static defaultProps = {
|
|
@@ -187,7 +188,7 @@ class MultiCascader extends React.Component<MultiCascaderProps, MultiCascaderSta
|
|
|
187
188
|
}
|
|
188
189
|
|
|
189
190
|
handleCheck = (item: any, event: React.SyntheticEvent<any>, checked: boolean) => {
|
|
190
|
-
const { valueKey,
|
|
191
|
+
const { valueKey, cascade, uncheckableItemValues, onChange, onCheck } = this.props;
|
|
191
192
|
const itemValue = item[valueKey];
|
|
192
193
|
let value = [];
|
|
193
194
|
|
|
@@ -208,6 +209,7 @@ class MultiCascader extends React.Component<MultiCascaderProps, MultiCascaderSta
|
|
|
208
209
|
}
|
|
209
210
|
|
|
210
211
|
onChange?.(value, event);
|
|
212
|
+
onCheck?.(value, item, checked, event);
|
|
211
213
|
};
|
|
212
214
|
|
|
213
215
|
handleChangeForSearchItem = (value: any, checked: boolean, event: React.SyntheticEvent<any>) => {
|
|
@@ -112,6 +112,23 @@ describe('MultiCascader - DropdownMenu', () => {
|
|
|
112
112
|
}, 1);
|
|
113
113
|
});
|
|
114
114
|
|
|
115
|
+
it('Should call onSelect callback with 4 params', done => {
|
|
116
|
+
const doneOp = (node, activePaths, createConcat, event) => {
|
|
117
|
+
if (
|
|
118
|
+
typeof node === 'object' &&
|
|
119
|
+
Array.isArray(activePaths) &&
|
|
120
|
+
typeof createConcat === 'function' &&
|
|
121
|
+
event.target
|
|
122
|
+
) {
|
|
123
|
+
done();
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const instance = getInstance(<Dropdown defaultOpen data={items} onSelect={doneOp} />);
|
|
128
|
+
const menuContainer = getDOMNode(instance.menuContainerRef.current);
|
|
129
|
+
ReactTestUtils.Simulate.click(menuContainer.querySelectorAll('.rs-checkbox')[1]);
|
|
130
|
+
});
|
|
131
|
+
|
|
115
132
|
it('Should not call onSelect callback on disabled item', () => {
|
|
116
133
|
const onSelectSpy = sinon.spy();
|
|
117
134
|
const instance = getInstance(
|
|
@@ -7,7 +7,6 @@ import Button from '../../Button';
|
|
|
7
7
|
|
|
8
8
|
const namespace = `${globalKey}-picker`;
|
|
9
9
|
const toggleClassName = `.${namespace}-toggle-placeholder`;
|
|
10
|
-
const activeClassName = '.rs-dropdown-menu-item-active';
|
|
11
10
|
|
|
12
11
|
const items = [
|
|
13
12
|
{
|
|
@@ -209,6 +208,20 @@ describe('MultiCascader', () => {
|
|
|
209
208
|
ReactTestUtils.Simulate.click(menu.querySelector('.rs-checkbox'));
|
|
210
209
|
});
|
|
211
210
|
|
|
211
|
+
it('Should call onCheck callback ', done => {
|
|
212
|
+
let checkbox = null;
|
|
213
|
+
const doneOp = (value, item, checked, event) => {
|
|
214
|
+
if (value[0] === 'abc' && item.value === 'abc' && checked && event.target === checkbox) {
|
|
215
|
+
done();
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
const instance = getInstance(<Dropdown data={items} defaultOpen onCheck={doneOp} />);
|
|
220
|
+
const menu = findDOMNode(instance.menuContainerRef.current);
|
|
221
|
+
checkbox = menu.querySelector('.rs-checkbox-wrapper');
|
|
222
|
+
ReactTestUtils.Simulate.click(checkbox);
|
|
223
|
+
});
|
|
224
|
+
|
|
212
225
|
it('Should call onChange callback ', done => {
|
|
213
226
|
const doneOp = value => {
|
|
214
227
|
if (value[0] === 'abc') {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { AnimationEventProps, StandardProps, TypeAttributes } from '../@types/common';
|
|
3
3
|
|
|
4
|
-
export type OverlayTriggerTrigger = 'click' | 'hover' | 'focus' | 'active' | 'none';
|
|
4
|
+
export type OverlayTriggerTrigger = 'click' | 'contextMenu' | 'hover' | 'focus' | 'active' | 'none';
|
|
5
5
|
|
|
6
6
|
export interface TriggerProps extends AnimationEventProps, StandardProps {
|
|
7
7
|
/** Triggering events */
|
|
@@ -26,6 +26,7 @@ interface TriggerProps {
|
|
|
26
26
|
onMouseOut?: React.MouseEventHandler;
|
|
27
27
|
onBlur?: React.MouseEventHandler;
|
|
28
28
|
onClick?: React.MouseEventHandler;
|
|
29
|
+
onContextMenu?: React.MouseEventHandler;
|
|
29
30
|
onFocus?: React.MouseEventHandler;
|
|
30
31
|
}
|
|
31
32
|
|
|
@@ -81,7 +82,11 @@ class OverlayTrigger extends React.Component<OverlayTriggerProps, OverlayTrigger
|
|
|
81
82
|
handleSpeakerMouseLeave = () => {
|
|
82
83
|
const { trigger } = this.props;
|
|
83
84
|
this.mouseEnteredToSpeaker = false;
|
|
84
|
-
if (
|
|
85
|
+
if (
|
|
86
|
+
!isOneOf('click', trigger) &&
|
|
87
|
+
!isOneOf('active', trigger) &&
|
|
88
|
+
!isOneOf('contextMenu', trigger)
|
|
89
|
+
) {
|
|
85
90
|
this.hideWithCheck();
|
|
86
91
|
}
|
|
87
92
|
};
|
|
@@ -130,6 +135,10 @@ class OverlayTrigger extends React.Component<OverlayTriggerProps, OverlayTrigger
|
|
|
130
135
|
}
|
|
131
136
|
};
|
|
132
137
|
|
|
138
|
+
preventDefault = (event: React.MouseEvent<Element, MouseEvent>) => {
|
|
139
|
+
event.preventDefault();
|
|
140
|
+
};
|
|
141
|
+
|
|
133
142
|
handleDelayedShow = () => {
|
|
134
143
|
const { delayShow, enterable } = this.props;
|
|
135
144
|
const delay = isNil(delayShow) ? this.props.delay : delayShow;
|
|
@@ -197,6 +206,8 @@ class OverlayTrigger extends React.Component<OverlayTriggerProps, OverlayTrigger
|
|
|
197
206
|
|
|
198
207
|
if (isOneOf('click', trigger)) {
|
|
199
208
|
overlayProps.onHide = createChainedFunction(this.hide, onHide);
|
|
209
|
+
} else if (isOneOf('contextMenu', trigger)) {
|
|
210
|
+
overlayProps.onHide = createChainedFunction(this.hide, onHide);
|
|
200
211
|
} else if (isOneOf('active', trigger)) {
|
|
201
212
|
overlayProps.onHide = createChainedFunction(this.hide, onHide);
|
|
202
213
|
}
|
|
@@ -228,6 +239,7 @@ class OverlayTrigger extends React.Component<OverlayTriggerProps, OverlayTrigger
|
|
|
228
239
|
children,
|
|
229
240
|
speaker,
|
|
230
241
|
onClick,
|
|
242
|
+
onContextMenu,
|
|
231
243
|
trigger,
|
|
232
244
|
onMouseOver,
|
|
233
245
|
onMouseOut,
|
|
@@ -254,6 +266,15 @@ class OverlayTrigger extends React.Component<OverlayTriggerProps, OverlayTrigger
|
|
|
254
266
|
props.onClick = createChainedFunction(this.toggleHideAndShow, props.onClick);
|
|
255
267
|
}
|
|
256
268
|
|
|
269
|
+
if (isOneOf('contextMenu', trigger)) {
|
|
270
|
+
props.onContextMenu = createChainedFunction(
|
|
271
|
+
this.preventDefault,
|
|
272
|
+
this.toggleHideAndShow,
|
|
273
|
+
triggerProps.onContextMenu,
|
|
274
|
+
onContextMenu
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
257
278
|
if (isOneOf('active', trigger)) {
|
|
258
279
|
props.onClick = createChainedFunction(this.handleDelayedShow, props.onClick);
|
|
259
280
|
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import ReactTestUtils from 'react-dom/test-utils';
|
|
3
|
+
import { getDOMNode } from '@test/testUtils';
|
|
4
|
+
|
|
5
|
+
import OverlayTrigger from '../OverlayTrigger';
|
|
6
|
+
import Tooltip from '../../Tooltip';
|
|
7
|
+
|
|
8
|
+
describe('OverlayTrigger', () => {
|
|
9
|
+
it('Should create Whisper element', () => {
|
|
10
|
+
const instance = getDOMNode(
|
|
11
|
+
<OverlayTrigger speaker={<Tooltip>tooltip</Tooltip>}>
|
|
12
|
+
<button type="button">button</button>
|
|
13
|
+
</OverlayTrigger>
|
|
14
|
+
);
|
|
15
|
+
assert.equal(instance.nodeName, 'BUTTON');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('Should maintain overlay classname when trigger click', () => {
|
|
19
|
+
const whisper = getDOMNode(
|
|
20
|
+
<OverlayTrigger
|
|
21
|
+
trigger="click"
|
|
22
|
+
speaker={<Tooltip className="test-whisper_click">test</Tooltip>}
|
|
23
|
+
>
|
|
24
|
+
<button>button</button>
|
|
25
|
+
</OverlayTrigger>
|
|
26
|
+
);
|
|
27
|
+
ReactTestUtils.Simulate.click(whisper);
|
|
28
|
+
assert.equal(document.getElementsByClassName('test-whisper_click').length, 1);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('Should maintain overlay classname when trigger contextMenu', () => {
|
|
32
|
+
const whisper = getDOMNode(
|
|
33
|
+
<OverlayTrigger
|
|
34
|
+
trigger="contextMenu"
|
|
35
|
+
speaker={<Tooltip className="test-whisper_context-menu">test</Tooltip>}
|
|
36
|
+
>
|
|
37
|
+
<button>button</button>
|
|
38
|
+
</OverlayTrigger>
|
|
39
|
+
);
|
|
40
|
+
ReactTestUtils.Simulate.contextMenu(whisper);
|
|
41
|
+
assert.equal(document.getElementsByClassName('test-whisper_context-menu').length, 1);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('Should maintain overlay classname when trigger focus', () => {
|
|
45
|
+
const whisper = getDOMNode(
|
|
46
|
+
<OverlayTrigger
|
|
47
|
+
trigger="focus"
|
|
48
|
+
speaker={<Tooltip className="test-whisper_focus">test</Tooltip>}
|
|
49
|
+
>
|
|
50
|
+
<button>button</button>
|
|
51
|
+
</OverlayTrigger>
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
ReactTestUtils.Simulate.focus(whisper);
|
|
55
|
+
assert.equal(document.getElementsByClassName('test-whisper_focus').length, 1);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('Should maintain overlay classname when trigger mouseOver and setting [trigger="hover"]', () => {
|
|
59
|
+
const whisper = getDOMNode(
|
|
60
|
+
<OverlayTrigger
|
|
61
|
+
trigger="hover"
|
|
62
|
+
speaker={<Tooltip className="test-whisper_hover">test</Tooltip>}
|
|
63
|
+
>
|
|
64
|
+
<button>button</button>
|
|
65
|
+
</OverlayTrigger>
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
ReactTestUtils.Simulate.mouseOver(whisper);
|
|
69
|
+
assert.equal(document.getElementsByClassName('test-whisper_hover').length, 1);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('Should maintain overlay classname when trigger click and setting [trigger="active"] ', () => {
|
|
73
|
+
const whisper = getDOMNode(
|
|
74
|
+
<OverlayTrigger
|
|
75
|
+
trigger="active"
|
|
76
|
+
speaker={<Tooltip className="test-whisper_active">test</Tooltip>}
|
|
77
|
+
>
|
|
78
|
+
<button>button</button>
|
|
79
|
+
</OverlayTrigger>
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
ReactTestUtils.Simulate.click(whisper);
|
|
83
|
+
assert.equal(document.getElementsByClassName('test-whisper_active').length, 1);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('Should call onClick callback', done => {
|
|
87
|
+
const doneOp = () => {
|
|
88
|
+
done();
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const whisper = getDOMNode(
|
|
92
|
+
<OverlayTrigger onClick={doneOp} trigger="click" speaker={<Tooltip />}>
|
|
93
|
+
<button>button</button>
|
|
94
|
+
</OverlayTrigger>
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
ReactTestUtils.Simulate.click(whisper);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('Should call onContextMenu callback', done => {
|
|
101
|
+
const doneOp = () => {
|
|
102
|
+
done();
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const whisper = getDOMNode(
|
|
106
|
+
<OverlayTrigger onContextMenu={doneOp} trigger="contextMenu" speaker={<Tooltip />}>
|
|
107
|
+
<button>button</button>
|
|
108
|
+
</OverlayTrigger>
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
ReactTestUtils.Simulate.contextMenu(whisper);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('Should call onFocus callback', done => {
|
|
115
|
+
const doneOp = () => {
|
|
116
|
+
done();
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const whisper = getDOMNode(
|
|
120
|
+
<OverlayTrigger onFocus={doneOp} trigger="focus" speaker={<Tooltip />}>
|
|
121
|
+
<button>button</button>
|
|
122
|
+
</OverlayTrigger>
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
ReactTestUtils.Simulate.focus(whisper);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('Should call onMouseOver callback', done => {
|
|
129
|
+
const doneOp = () => {
|
|
130
|
+
done();
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const whisper = getDOMNode(
|
|
134
|
+
<OverlayTrigger onMouseOver={doneOp} trigger="hover" speaker={<Tooltip />}>
|
|
135
|
+
<button>button</button>
|
|
136
|
+
</OverlayTrigger>
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
ReactTestUtils.Simulate.mouseOver(whisper);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('Should call onMouseOut callback', done => {
|
|
143
|
+
const doneOp = () => {
|
|
144
|
+
done();
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const whisper = getDOMNode(
|
|
148
|
+
<OverlayTrigger onMouseOut={doneOp} trigger="hover" speaker={<Tooltip />}>
|
|
149
|
+
<button>button</button>
|
|
150
|
+
</OverlayTrigger>
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
ReactTestUtils.Simulate.mouseOut(whisper);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
@@ -166,11 +166,12 @@
|
|
|
166
166
|
border-style: solid;
|
|
167
167
|
border-width: 0;
|
|
168
168
|
border-color: @table-border-color;
|
|
169
|
-
display: block;
|
|
170
169
|
overflow: hidden;
|
|
171
170
|
position: absolute;
|
|
172
171
|
white-space: normal;
|
|
173
172
|
background: @table-body-background;
|
|
173
|
+
display: table;
|
|
174
|
+
table-layout: fixed;
|
|
174
175
|
|
|
175
176
|
&.first {
|
|
176
177
|
border-left-width: 0;
|
|
@@ -2,13 +2,22 @@ import React from 'react';
|
|
|
2
2
|
import ReactTestUtils from 'react-dom/test-utils';
|
|
3
3
|
import Enzyme, { mount } from 'enzyme';
|
|
4
4
|
import Adapter from 'enzyme-adapter-react-16';
|
|
5
|
-
import { findDOMNode } from 'react-dom';
|
|
5
|
+
import ReactDOM, { findDOMNode } from 'react-dom';
|
|
6
6
|
import { getDOMNode, getInstance } from '@test/testUtils';
|
|
7
7
|
import TreePicker from '../TreePicker';
|
|
8
8
|
|
|
9
9
|
Enzyme.configure({ adapter: new Adapter() });
|
|
10
|
+
let container;
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
container = document.createElement('div');
|
|
14
|
+
document.body.appendChild(container);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
document.body.removeChild(container);
|
|
19
|
+
container = null;
|
|
20
|
+
});
|
|
12
21
|
|
|
13
22
|
const data = [
|
|
14
23
|
{
|
|
@@ -157,7 +166,7 @@ describe('TreePicker', () => {
|
|
|
157
166
|
});
|
|
158
167
|
|
|
159
168
|
it('Should call `onChange` callback', done => {
|
|
160
|
-
const doneOp =
|
|
169
|
+
const doneOp = () => {
|
|
161
170
|
done();
|
|
162
171
|
};
|
|
163
172
|
const instance = getDOMNode(<TreePicker inline onChange={doneOp} data={data} />);
|
|
@@ -243,7 +252,7 @@ describe('TreePicker', () => {
|
|
|
243
252
|
});
|
|
244
253
|
|
|
245
254
|
it('Should focus item by keyCode=13 ', done => {
|
|
246
|
-
const doneOp =
|
|
255
|
+
const doneOp = () => {
|
|
247
256
|
done();
|
|
248
257
|
};
|
|
249
258
|
const instance = mount(<TreePicker data={data} onChange={doneOp} inline defaultExpandAll />);
|
|
@@ -271,8 +280,6 @@ describe('TreePicker', () => {
|
|
|
271
280
|
});
|
|
272
281
|
|
|
273
282
|
it('Should load data async', () => {
|
|
274
|
-
let activeNode = null;
|
|
275
|
-
let layer = 0;
|
|
276
283
|
const data = [
|
|
277
284
|
{
|
|
278
285
|
label: 'Master',
|
|
@@ -293,8 +300,6 @@ describe('TreePicker', () => {
|
|
|
293
300
|
|
|
294
301
|
let newData = [];
|
|
295
302
|
const mockOnExpand = (node, l, concat) => {
|
|
296
|
-
activeNode = node;
|
|
297
|
-
layer = l;
|
|
298
303
|
newData = concat(data, children);
|
|
299
304
|
};
|
|
300
305
|
|
|
@@ -391,13 +396,36 @@ describe('TreePicker', () => {
|
|
|
391
396
|
assert.ok(list[0].innerText, 'Louisa');
|
|
392
397
|
});
|
|
393
398
|
|
|
394
|
-
it('Should
|
|
395
|
-
const
|
|
396
|
-
|
|
397
|
-
|
|
399
|
+
it('Should controlled by expandItemValues', () => {
|
|
400
|
+
const TestApp = React.forwardRef((props, ref) => {
|
|
401
|
+
const [expandItemValues, setExpandItemValues] = React.useState();
|
|
402
|
+
const pickerRef = React.useRef();
|
|
403
|
+
React.useImperativeHandle(ref, () => ({
|
|
404
|
+
picker: pickerRef.current,
|
|
405
|
+
setExpandItemValues
|
|
406
|
+
}));
|
|
407
|
+
|
|
408
|
+
return <TreePicker data={data} ref={pickerRef} expandItemValues={expandItemValues} open />;
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
TestApp.displayName = 'TestCheckTreePicker';
|
|
412
|
+
|
|
413
|
+
const ref = React.createRef();
|
|
414
|
+
ReactTestUtils.act(() => {
|
|
415
|
+
ReactDOM.render(<TestApp ref={ref} />, container);
|
|
416
|
+
});
|
|
398
417
|
|
|
399
|
-
assert.equal(
|
|
400
|
-
|
|
401
|
-
|
|
418
|
+
assert.equal(
|
|
419
|
+
ref.current.picker.treeViewRef.current.querySelectorAll('.rs-tree-node-expanded').length,
|
|
420
|
+
0
|
|
421
|
+
);
|
|
422
|
+
|
|
423
|
+
ReactTestUtils.act(() => {
|
|
424
|
+
ref.current.setExpandItemValues(['Master']);
|
|
425
|
+
});
|
|
426
|
+
assert.equal(
|
|
427
|
+
ref.current.picker.treeViewRef.current.querySelectorAll('.rs-tree-node-expanded').length,
|
|
428
|
+
1
|
|
429
|
+
);
|
|
402
430
|
});
|
|
403
431
|
});
|
package/src/utils/treeUtils.ts
CHANGED
|
@@ -123,7 +123,10 @@ export function treeDeprecatedWarning(
|
|
|
123
123
|
* @param b
|
|
124
124
|
*/
|
|
125
125
|
export function compareArray(a: any[], b: any[]) {
|
|
126
|
-
|
|
126
|
+
if (!(_.isArray(a) && _.isArray(b))) {
|
|
127
|
+
return a !== b;
|
|
128
|
+
}
|
|
129
|
+
return !shallowEqualArray(a, b);
|
|
127
130
|
}
|
|
128
131
|
|
|
129
132
|
/**
|