@douyinfe/semi-ui 2.6.0 → 2.7.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/_base/_story/index.stories.js +2 -6
- package/_portal/_story/portal.stories.js +1 -5
- package/_utils/hooks/usePrevFocus.ts +1 -0
- package/button/__test__/button.test.js +7 -0
- package/button/buttonGroup.tsx +5 -2
- package/cascader/__test__/cascader.test.js +159 -81
- package/cascader/_story/cascader.stories.js +36 -23
- package/cascader/index.tsx +26 -5
- package/datePicker/_story/v2/InsetInput.jsx +104 -0
- package/datePicker/_story/v2/InsetInputE2E.jsx +69 -0
- package/datePicker/_story/v2/index.js +2 -0
- package/datePicker/dateInput.tsx +95 -9
- package/datePicker/datePicker.tsx +89 -15
- package/datePicker/index.tsx +15 -0
- package/datePicker/insetInput.tsx +76 -0
- package/datePicker/monthsGrid.tsx +14 -7
- package/dist/css/semi.css +109 -7
- package/dist/css/semi.min.css +1 -1
- package/dist/umd/semi-ui.js +925 -152
- package/dist/umd/semi-ui.js.map +1 -1
- package/dist/umd/semi-ui.min.js +1 -1
- package/dist/umd/semi-ui.min.js.map +1 -1
- package/form/hooks/useFormApi.tsx +3 -2
- package/input/_story/input.stories.js +23 -1
- package/lib/cjs/_utils/hooks/usePrevFocus.js +1 -0
- package/lib/cjs/button/buttonGroup.d.ts +1 -0
- package/lib/cjs/button/buttonGroup.js +6 -2
- package/lib/cjs/cascader/index.d.ts +1 -0
- package/lib/cjs/cascader/index.js +38 -9
- package/lib/cjs/datePicker/dateInput.d.ts +9 -2
- package/lib/cjs/datePicker/dateInput.js +92 -9
- package/lib/cjs/datePicker/datePicker.d.ts +7 -2
- package/lib/cjs/datePicker/datePicker.js +123 -18
- package/lib/cjs/datePicker/index.js +24 -2
- package/lib/cjs/datePicker/insetInput.d.ts +21 -0
- package/lib/cjs/datePicker/insetInput.js +80 -0
- package/lib/cjs/datePicker/monthsGrid.js +19 -7
- package/lib/cjs/form/hooks/useFormApi.d.ts +2 -1
- package/lib/cjs/modal/useModal/HookModal.js +2 -0
- package/lib/cjs/radio/radioGroup.js +6 -0
- package/lib/cjs/select/index.js +5 -2
- package/lib/cjs/tag/group.d.ts +2 -0
- package/lib/cjs/tag/group.js +4 -2
- package/lib/cjs/tooltip/index.js +1 -1
- package/lib/cjs/tree/index.js +5 -3
- package/lib/cjs/tree/interface.d.ts +1 -0
- package/lib/cjs/tree/nodeList.js +3 -1
- package/lib/cjs/treeSelect/index.js +11 -3
- package/lib/es/_utils/hooks/usePrevFocus.js +2 -0
- package/lib/es/button/buttonGroup.d.ts +1 -0
- package/lib/es/button/buttonGroup.js +5 -2
- package/lib/es/cascader/index.d.ts +1 -0
- package/lib/es/cascader/index.js +35 -6
- package/lib/es/datePicker/dateInput.d.ts +9 -2
- package/lib/es/datePicker/dateInput.js +91 -9
- package/lib/es/datePicker/datePicker.d.ts +7 -2
- package/lib/es/datePicker/datePicker.js +124 -18
- package/lib/es/datePicker/index.js +20 -0
- package/lib/es/datePicker/insetInput.d.ts +21 -0
- package/lib/es/datePicker/insetInput.js +65 -0
- package/lib/es/datePicker/monthsGrid.js +19 -7
- package/lib/es/form/hooks/useFormApi.d.ts +2 -1
- package/lib/es/modal/useModal/HookModal.js +2 -0
- package/lib/es/radio/radioGroup.js +6 -0
- package/lib/es/select/index.js +5 -2
- package/lib/es/tag/group.d.ts +2 -0
- package/lib/es/tag/group.js +4 -2
- package/lib/es/tooltip/index.js +1 -1
- package/lib/es/tree/index.js +5 -3
- package/lib/es/tree/interface.d.ts +1 -0
- package/lib/es/tree/nodeList.js +3 -1
- package/lib/es/treeSelect/index.js +11 -3
- package/modal/_story/modal.stories.js +93 -1
- package/modal/useModal/HookModal.tsx +1 -0
- package/notification/_story/useNotification/index.jsx +21 -7
- package/package.json +9 -9
- package/radio/__test__/radioGroup.test.jsx +9 -1
- package/radio/_story/radio.stories.js +22 -1
- package/radio/radioGroup.tsx +9 -0
- package/select/_story/select.stories.js +73 -2
- package/select/index.tsx +5 -3
- package/table/_story/v2/FixedMemoryLeak/index.jsx +33 -0
- package/table/_story/v2/index.js +2 -1
- package/tag/group.tsx +5 -3
- package/toast/_story/toast.stories.js +41 -0
- package/tooltip/index.tsx +1 -1
- package/tree/__test__/tree.test.js +87 -2
- package/tree/_story/tree.stories.js +65 -5
- package/tree/index.tsx +4 -2
- package/tree/interface.ts +1 -0
- package/tree/nodeList.tsx +3 -2
- package/treeSelect/__test__/treeSelect.test.js +28 -0
- package/treeSelect/_story/treeSelect.stories.js +55 -2
- package/treeSelect/index.tsx +14 -3
|
@@ -346,37 +346,50 @@ export const Searchable = () => {
|
|
|
346
346
|
filterLeafOnly={false}
|
|
347
347
|
onChange={e => console.log(e)}
|
|
348
348
|
/>
|
|
349
|
+
<br />
|
|
350
|
+
<br />
|
|
351
|
+
<div>fix-1449,当 label 为 ReactNode 时,搜索显示结果[object object]</div>
|
|
352
|
+
<Cascader
|
|
353
|
+
style={{ width: 300 }}
|
|
354
|
+
treeData={treedataWithNodeLabel}
|
|
355
|
+
placeholder="宁波为 ReactNode"
|
|
356
|
+
filterTreeNode
|
|
357
|
+
/>
|
|
358
|
+
<br />
|
|
359
|
+
<br />
|
|
349
360
|
<div>
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
361
|
+
filterTreeNode=false,且 label 为 ReactNode
|
|
362
|
+
时,配合displayRender使用,使得回显到input的内容符合预期
|
|
363
|
+
</div>
|
|
364
|
+
<Cascader
|
|
365
|
+
style={{ width: 300 }}
|
|
366
|
+
treeData={treedataWithNodeLabel}
|
|
367
|
+
placeholder="自定义回填时显示数据的格式"
|
|
368
|
+
displayRender={list =>
|
|
369
|
+
list.map((v, i) => {
|
|
370
|
+
return list.length - 1 === i ? (
|
|
371
|
+
<React.Fragment key={i}>{v}</React.Fragment>
|
|
372
|
+
) : (
|
|
373
|
+
<React.Fragment key={i}>{v} / </React.Fragment>
|
|
374
|
+
);
|
|
375
|
+
})
|
|
376
|
+
}
|
|
377
|
+
defaultValue={['zhejiang', 'ningbo', 'jiangbei']}
|
|
378
|
+
/>
|
|
379
|
+
<br />
|
|
380
|
+
<br />
|
|
381
|
+
<div>
|
|
382
|
+
v2.5 起,filterTreeNode=false,且 label 为 ReactNode
|
|
383
|
+
时,无配合displayRender 使用,回显到input的内容也是符合预期
|
|
362
384
|
</div>
|
|
363
385
|
<Cascader
|
|
364
386
|
style={{ width: 300 }}
|
|
365
387
|
treeData={treedataWithNodeLabel}
|
|
366
|
-
placeholder="
|
|
367
|
-
|
|
368
|
-
list.map((v, i) => {
|
|
369
|
-
return list.length - 1 === i ? (
|
|
370
|
-
<React.Fragment key={i}>{v}</React.Fragment>
|
|
371
|
-
) : (
|
|
372
|
-
<React.Fragment key={i}>{v} / </React.Fragment>
|
|
373
|
-
);
|
|
374
|
-
})
|
|
375
|
-
}
|
|
388
|
+
placeholder="宁波为 ReactNode"
|
|
389
|
+
|
|
376
390
|
defaultValue={['zhejiang', 'ningbo', 'jiangbei']}
|
|
377
391
|
/>
|
|
378
392
|
</div>
|
|
379
|
-
</div>
|
|
380
393
|
);
|
|
381
394
|
};
|
|
382
395
|
Searchable.parameters = {
|
package/cascader/index.tsx
CHANGED
|
@@ -711,9 +711,32 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
711
711
|
);
|
|
712
712
|
};
|
|
713
713
|
|
|
714
|
+
renderDisplayText = (): ReactNode => {
|
|
715
|
+
const { displayProp, separator, displayRender } = this.props;
|
|
716
|
+
const { selectedKeys } = this.state;
|
|
717
|
+
let displayText: ReactNode = '';
|
|
718
|
+
if (selectedKeys.size) {
|
|
719
|
+
const displayPath = this.foundation.getItemPropPath([...selectedKeys][0], displayProp);
|
|
720
|
+
if (displayRender && typeof displayRender === 'function') {
|
|
721
|
+
displayText = displayRender(displayPath);
|
|
722
|
+
} else {
|
|
723
|
+
displayText = displayPath.map((path: ReactNode, index: number)=>(
|
|
724
|
+
<Fragment key={`${path}-${index}`}>
|
|
725
|
+
{
|
|
726
|
+
index<displayPath.length-1
|
|
727
|
+
? <>{path}{separator}</>
|
|
728
|
+
: path
|
|
729
|
+
}
|
|
730
|
+
</Fragment>
|
|
731
|
+
));
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
return displayText;
|
|
735
|
+
}
|
|
736
|
+
|
|
714
737
|
renderSelectContent = () => {
|
|
715
738
|
const { placeholder, filterTreeNode, multiple } = this.props;
|
|
716
|
-
const {
|
|
739
|
+
const { checkedKeys } = this.state;
|
|
717
740
|
const searchable = Boolean(filterTreeNode);
|
|
718
741
|
if (!searchable) {
|
|
719
742
|
if (multiple) {
|
|
@@ -722,11 +745,9 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
722
745
|
}
|
|
723
746
|
return this.renderMultipleTags();
|
|
724
747
|
} else {
|
|
725
|
-
const displayText =
|
|
726
|
-
this.foundation.renderDisplayText([...selectedKeys][0]) :
|
|
727
|
-
'';
|
|
748
|
+
const displayText = this.renderDisplayText();
|
|
728
749
|
const spanCls = cls({
|
|
729
|
-
[`${prefixcls}-selection-placeholder`]: !displayText
|
|
750
|
+
[`${prefixcls}-selection-placeholder`]: !displayText,
|
|
730
751
|
});
|
|
731
752
|
return <span className={spanCls}>{displayText ? displayText : placeholder}</span>;
|
|
732
753
|
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { DatePicker, Space, Input, Button, Select } from '@douyinfe/semi-ui';
|
|
3
|
+
import { Position } from '@douyinfe/semi-foundation/tooltip/foundation';
|
|
4
|
+
import { strings } from '@douyinfe/semi-foundation/tooltip/constants';
|
|
5
|
+
import * as dateFns from 'date-fns';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Test with Chromatic
|
|
9
|
+
*/
|
|
10
|
+
export default function App() {
|
|
11
|
+
const spacing = [200, 400];
|
|
12
|
+
const [date, setDate] = React.useState();
|
|
13
|
+
const [insetInput, setInsetInput] = React.useState(true);
|
|
14
|
+
const [position, setPosition] = React.useState('leftTopOver');
|
|
15
|
+
const [needConfirm, setNeedConfirm] = React.useState(false);
|
|
16
|
+
const [density, setDensity] = React.useState(true);
|
|
17
|
+
|
|
18
|
+
const props = {
|
|
19
|
+
defaultOpen: true,
|
|
20
|
+
motion: false,
|
|
21
|
+
insetInput,
|
|
22
|
+
defaultPickerValue: '2021-12-01',
|
|
23
|
+
position,
|
|
24
|
+
density: density ? 'compact' : 'default',
|
|
25
|
+
autoAdjustOverflow: false,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const positionOptionList = strings.POSITION_SET.map((position) => ({
|
|
29
|
+
value: position,
|
|
30
|
+
label: position,
|
|
31
|
+
key: position,
|
|
32
|
+
}));
|
|
33
|
+
|
|
34
|
+
const triggerRender = ({ placeholder }) => {
|
|
35
|
+
const format = 'Pp';
|
|
36
|
+
const value = (date && dateFns.format(date, format)) || placeholder;
|
|
37
|
+
return <Input value={value} readOnly />;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const handleDateChange = (date) => {
|
|
41
|
+
setDate(date);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const handleBtnClick = () => {
|
|
45
|
+
setInsetInput(!insetInput);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const handleReset = () => {
|
|
49
|
+
setInsetInput(true);
|
|
50
|
+
setPosition('leftTopOver');
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const handleToggleNeedConfirm = () => {
|
|
54
|
+
setNeedConfirm(!needConfirm);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const handleToggleDensity = () => {
|
|
58
|
+
setDensity(!density);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<div style={{ height: '200vh' }}>
|
|
63
|
+
<div style={{ marginBottom: 12 }}>
|
|
64
|
+
<Space>
|
|
65
|
+
<Button onClick={handleBtnClick}>
|
|
66
|
+
{`insetInput=${insetInput}`}
|
|
67
|
+
</Button>
|
|
68
|
+
<Button onClick={handleToggleNeedConfirm}>
|
|
69
|
+
{`needConfirm=${needConfirm}`}
|
|
70
|
+
</Button>
|
|
71
|
+
<Button onClick={handleToggleDensity}>
|
|
72
|
+
{`小尺寸=${density}`}
|
|
73
|
+
</Button>
|
|
74
|
+
<Select
|
|
75
|
+
style={{ width: 200 }}
|
|
76
|
+
optionList={positionOptionList}
|
|
77
|
+
placeholder='选择position'
|
|
78
|
+
value={position}
|
|
79
|
+
onChange={setPosition}
|
|
80
|
+
showClear
|
|
81
|
+
/>
|
|
82
|
+
<Button onClick={handleReset} theme="solid">reset</Button>
|
|
83
|
+
</Space>
|
|
84
|
+
</div>
|
|
85
|
+
<Space wrap spacing={spacing}>
|
|
86
|
+
<DatePicker placeholder='选择单个日期' {...props} />
|
|
87
|
+
<DatePicker placeholder='选择月' {...props} type='month' />
|
|
88
|
+
<DatePicker placeholder='选择日期时间' {...props} type='dateTime' needConfirm={needConfirm} />
|
|
89
|
+
<DatePicker placeholder='选择日期范围' {...props} type='dateRange' />
|
|
90
|
+
<DatePicker placeholder='选择日期时间范围' {...props} type='dateTimeRange' needConfirm={needConfirm} />
|
|
91
|
+
<DatePicker placeholder='format=Pp' {...props} format='yyyy-MM-dd HH:mm:ss' type='dateTimeRange' />
|
|
92
|
+
</Space>
|
|
93
|
+
</div>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
App.parameters = {
|
|
98
|
+
chromatic: {
|
|
99
|
+
disableSnapshot: false,
|
|
100
|
+
delay: 3000,
|
|
101
|
+
viewports: [1800]
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
App.storyName = 'inset input';
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { DatePicker, Space, Button } from '@douyinfe/semi-ui';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Test with Cypress
|
|
6
|
+
* Don't modify DOM structure
|
|
7
|
+
*/
|
|
8
|
+
export default function App() {
|
|
9
|
+
const [needConfirm, setNeedConfirm] = React.useState(false);
|
|
10
|
+
|
|
11
|
+
const spacing = [200, 400];
|
|
12
|
+
const props = {
|
|
13
|
+
insetInput: true,
|
|
14
|
+
defaultPickerValue: '2021-12-01',
|
|
15
|
+
motion: false,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const handleToggleNeedConfirm = () => {
|
|
19
|
+
setNeedConfirm(!needConfirm);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<div style={{ height: '300vh' }}>
|
|
24
|
+
<div style={{ marginBottom: 12 }}>
|
|
25
|
+
<Space>
|
|
26
|
+
<Button onClick={handleToggleNeedConfirm} data-cy="btn">
|
|
27
|
+
{`needConfirm=${needConfirm}`}
|
|
28
|
+
</Button>
|
|
29
|
+
</Space>
|
|
30
|
+
</div>
|
|
31
|
+
<Space wrap spacing={spacing}>
|
|
32
|
+
<div data-cy="date">
|
|
33
|
+
<DatePicker placeholder="选择单个日期" {...props} />
|
|
34
|
+
</div>
|
|
35
|
+
<div data-cy="month">
|
|
36
|
+
<DatePicker
|
|
37
|
+
{...props}
|
|
38
|
+
placeholder="选择月"
|
|
39
|
+
type="month"
|
|
40
|
+
defaultValue="2021-12"
|
|
41
|
+
timePickerOpts={{
|
|
42
|
+
scrollItemProps: { motion: false },
|
|
43
|
+
}}
|
|
44
|
+
/>
|
|
45
|
+
</div>
|
|
46
|
+
<div data-cy="dateTime">
|
|
47
|
+
<DatePicker placeholder="选择日期时间" {...props} type="dateTime" needConfirm={needConfirm} />
|
|
48
|
+
</div>
|
|
49
|
+
<div data-cy="dateRange">
|
|
50
|
+
<DatePicker placeholder="选择日期范围" {...props} type="dateRange" />
|
|
51
|
+
</div>
|
|
52
|
+
<div data-cy="dateTimeRange">
|
|
53
|
+
<DatePicker
|
|
54
|
+
placeholder="选择日期时间范围"
|
|
55
|
+
{...props}
|
|
56
|
+
type="dateTimeRange"
|
|
57
|
+
needConfirm={needConfirm}
|
|
58
|
+
/>
|
|
59
|
+
</div>
|
|
60
|
+
<div data-cy="customFormat">
|
|
61
|
+
<DatePicker placeholder="选择日期范围" {...props} type="dateRange" format="Pp" />
|
|
62
|
+
</div>
|
|
63
|
+
</Space>
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
App.parameters = { chromatic: { disableSnapshot: true } };
|
|
69
|
+
App.storyName = 'inset input e2e test';
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { default as YearButton } from './YearButton';
|
|
2
2
|
export { default as PanelOpen } from './PanelOpen';
|
|
3
3
|
export { default as FixInputRangeFocus } from './FixInputRangeFocus';
|
|
4
|
+
export { default as InsetInput } from './InsetInput';
|
|
5
|
+
export { default as InsetInputE2E } from './InsetInputE2E';
|
package/datePicker/dateInput.tsx
CHANGED
|
@@ -1,22 +1,28 @@
|
|
|
1
|
-
/* eslint-disable jsx-a11y/click-events-have-key-events
|
|
1
|
+
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
|
2
|
+
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
|
2
3
|
/* eslint-disable max-lines-per-function */
|
|
3
4
|
/* eslint-disable no-unused-vars */
|
|
4
5
|
import React from 'react';
|
|
5
6
|
import cls from 'classnames';
|
|
6
7
|
import PropTypes from 'prop-types';
|
|
8
|
+
|
|
7
9
|
import DateInputFoundation, {
|
|
8
10
|
DateInputAdapter,
|
|
9
11
|
DateInputFoundationProps,
|
|
10
|
-
RangeType
|
|
12
|
+
RangeType,
|
|
13
|
+
InsetInputChangeProps,
|
|
14
|
+
InsetInputChangeFoundationProps,
|
|
11
15
|
} from '@douyinfe/semi-foundation/datePicker/inputFoundation';
|
|
12
16
|
import { cssClasses, strings } from '@douyinfe/semi-foundation/datePicker/constants';
|
|
13
17
|
import { noop } from '@douyinfe/semi-foundation/utils/function';
|
|
14
18
|
import isNullOrUndefined from '@douyinfe/semi-foundation/utils/isNullOrUndefined';
|
|
15
|
-
import BaseComponent, { BaseProps } from '../_base/baseComponent';
|
|
16
|
-
import Input from '../input/index';
|
|
17
19
|
import { IconCalendar, IconCalendarClock, IconClear } from '@douyinfe/semi-icons';
|
|
18
20
|
import { BaseValueType, ValueType } from '@douyinfe/semi-foundation/datePicker/foundation';
|
|
19
21
|
|
|
22
|
+
import BaseComponent, { BaseProps } from '../_base/baseComponent';
|
|
23
|
+
import Input from '../input/index';
|
|
24
|
+
import { InsetDateInput, InsetTimeInput } from './insetInput';
|
|
25
|
+
|
|
20
26
|
export interface DateInputProps extends DateInputFoundationProps, BaseProps {
|
|
21
27
|
insetLabel?: React.ReactNode;
|
|
22
28
|
prefix?: React.ReactNode;
|
|
@@ -26,9 +32,10 @@ export interface DateInputProps extends DateInputFoundationProps, BaseProps {
|
|
|
26
32
|
onBlur?: (e: React.MouseEvent<HTMLInputElement>) => void;
|
|
27
33
|
onFocus?: (e: React.MouseEvent<HTMLInputElement>, rangeType?: RangeType) => void;
|
|
28
34
|
onClear?: (e: React.MouseEvent<HTMLDivElement>) => void;
|
|
35
|
+
onInsetInputChange?: (options: InsetInputChangeProps) => void;
|
|
36
|
+
value?: Date[];
|
|
29
37
|
}
|
|
30
38
|
|
|
31
|
-
|
|
32
39
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
33
40
|
export default class DateInput extends BaseComponent<DateInputProps, {}> {
|
|
34
41
|
static propTypes = {
|
|
@@ -55,6 +62,8 @@ export default class DateInput extends BaseComponent<DateInputProps, {}> {
|
|
|
55
62
|
rangeInputStartRef: PropTypes.object,
|
|
56
63
|
rangeInputEndRef: PropTypes.object,
|
|
57
64
|
rangeSeparator: PropTypes.string,
|
|
65
|
+
insetInput: PropTypes.bool,
|
|
66
|
+
insetInputValue: PropTypes.object,
|
|
58
67
|
};
|
|
59
68
|
|
|
60
69
|
static defaultProps = {
|
|
@@ -91,6 +100,7 @@ export default class DateInput extends BaseComponent<DateInputProps, {}> {
|
|
|
91
100
|
notifyRangeInputClear: (...args) => this.props.onRangeClear(...args),
|
|
92
101
|
notifyRangeInputFocus: (...args) => this.props.onFocus(...args),
|
|
93
102
|
notifyTabPress: (...args) => this.props.onRangeEndTabPress(...args),
|
|
103
|
+
notifyInsetInputChange: options => this.props.onInsetInputChange(options),
|
|
94
104
|
};
|
|
95
105
|
}
|
|
96
106
|
|
|
@@ -139,6 +149,10 @@ export default class DateInput extends BaseComponent<DateInputProps, {}> {
|
|
|
139
149
|
this.handleRangeInputFocus(e, 'rangeStart');
|
|
140
150
|
};
|
|
141
151
|
|
|
152
|
+
handleInsetInputChange = (options: InsetInputChangeFoundationProps) => {
|
|
153
|
+
this.foundation.handleInsetInputChange(options);
|
|
154
|
+
};
|
|
155
|
+
|
|
142
156
|
getRangeInputValue = (rangeStart: string, rangeEnd: string) => {
|
|
143
157
|
const { rangeSeparator } = this.props;
|
|
144
158
|
const rangeInputValue = `${rangeStart}${rangeSeparator}${rangeEnd}`;
|
|
@@ -225,11 +239,11 @@ export default class DateInput extends BaseComponent<DateInputProps, {}> {
|
|
|
225
239
|
const rangePlaceholder = Array.isArray(placeholder) ? placeholder : [placeholder, placeholder];
|
|
226
240
|
const [rangeStartPlaceholder, rangeEndPlaceholder] = rangePlaceholder;
|
|
227
241
|
const inputLeftWrapperCls = cls(`${prefixCls}-range-input-wrapper-start`, `${prefixCls}-range-input-wrapper`, {
|
|
228
|
-
[`${prefixCls}-range-input-wrapper-active`]: rangeInputFocus === 'rangeStart',
|
|
229
|
-
[`${prefixCls}-range-input-wrapper-start-with-prefix`]: this.props.prefix || this.props.insetLabel
|
|
242
|
+
[`${prefixCls}-range-input-wrapper-active`]: rangeInputFocus === 'rangeStart' && !disabled,
|
|
243
|
+
[`${prefixCls}-range-input-wrapper-start-with-prefix`]: this.props.prefix || this.props.insetLabel,
|
|
230
244
|
});
|
|
231
245
|
const inputRightWrapperCls = cls(`${prefixCls}-range-input-wrapper-end`, `${prefixCls}-range-input-wrapper`, {
|
|
232
|
-
[`${prefixCls}-range-input-wrapper-active`]: rangeInputFocus === 'rangeEnd'
|
|
246
|
+
[`${prefixCls}-range-input-wrapper-active`]: rangeInputFocus === 'rangeEnd' && !disabled,
|
|
233
247
|
});
|
|
234
248
|
return (
|
|
235
249
|
<>
|
|
@@ -281,7 +295,72 @@ export default class DateInput extends BaseComponent<DateInputProps, {}> {
|
|
|
281
295
|
);
|
|
282
296
|
}
|
|
283
297
|
|
|
284
|
-
|
|
298
|
+
renderInputInset() {
|
|
299
|
+
const {
|
|
300
|
+
type,
|
|
301
|
+
handleInsetDateFocus,
|
|
302
|
+
handleInsetTimeFocus,
|
|
303
|
+
value,
|
|
304
|
+
insetInputValue,
|
|
305
|
+
prefixCls,
|
|
306
|
+
rangeInputStartRef,
|
|
307
|
+
rangeInputEndRef,
|
|
308
|
+
density,
|
|
309
|
+
} = this.props;
|
|
310
|
+
|
|
311
|
+
const _isRangeType = type.includes('Range');
|
|
312
|
+
const newInsetInputValue = this.foundation.getInsetInputValue({ value, insetInputValue });
|
|
313
|
+
const { datePlaceholder, timePlaceholder } = this.foundation.getInsetInputPlaceholder();
|
|
314
|
+
|
|
315
|
+
const insetInputWrapperCls = `${prefixCls}-inset-input-wrapper`;
|
|
316
|
+
const separatorCls = `${prefixCls}-inset-input-separator`;
|
|
317
|
+
|
|
318
|
+
return (
|
|
319
|
+
<div className={insetInputWrapperCls} x-type={type}>
|
|
320
|
+
<InsetDateInput
|
|
321
|
+
forwardRef={rangeInputStartRef}
|
|
322
|
+
insetInputValue={newInsetInputValue}
|
|
323
|
+
placeholder={datePlaceholder}
|
|
324
|
+
valuePath={'monthLeft.dateInput'}
|
|
325
|
+
onChange={this.handleInsetInputChange}
|
|
326
|
+
onFocus={e => handleInsetDateFocus(e, 'rangeStart')}
|
|
327
|
+
/>
|
|
328
|
+
<InsetTimeInput
|
|
329
|
+
disabled={!newInsetInputValue.monthLeft.dateInput}
|
|
330
|
+
insetInputValue={newInsetInputValue}
|
|
331
|
+
placeholder={timePlaceholder}
|
|
332
|
+
type={type}
|
|
333
|
+
valuePath={'monthLeft.timeInput'}
|
|
334
|
+
onChange={this.handleInsetInputChange}
|
|
335
|
+
onFocus={handleInsetTimeFocus}
|
|
336
|
+
/>
|
|
337
|
+
{_isRangeType && (
|
|
338
|
+
<>
|
|
339
|
+
<div className={separatorCls}>{density === 'compact' ? null : '-'}</div>
|
|
340
|
+
<InsetDateInput
|
|
341
|
+
forwardRef={rangeInputEndRef}
|
|
342
|
+
insetInputValue={newInsetInputValue}
|
|
343
|
+
placeholder={datePlaceholder}
|
|
344
|
+
valuePath={'monthRight.dateInput'}
|
|
345
|
+
onChange={this.handleInsetInputChange}
|
|
346
|
+
onFocus={e => handleInsetDateFocus(e, 'rangeEnd')}
|
|
347
|
+
/>
|
|
348
|
+
<InsetTimeInput
|
|
349
|
+
disabled={!newInsetInputValue.monthRight.dateInput}
|
|
350
|
+
insetInputValue={newInsetInputValue}
|
|
351
|
+
placeholder={timePlaceholder}
|
|
352
|
+
type={type}
|
|
353
|
+
valuePath={'monthRight.timeInput'}
|
|
354
|
+
onChange={this.handleInsetInputChange}
|
|
355
|
+
onFocus={handleInsetTimeFocus}
|
|
356
|
+
/>
|
|
357
|
+
</>
|
|
358
|
+
)}
|
|
359
|
+
</div>
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
renderTriggerInput() {
|
|
285
364
|
const {
|
|
286
365
|
placeholder,
|
|
287
366
|
type,
|
|
@@ -311,6 +390,8 @@ export default class DateInput extends BaseComponent<DateInputProps, {}> {
|
|
|
311
390
|
onRangeEndTabPress,
|
|
312
391
|
rangeInputFocus,
|
|
313
392
|
rangeSeparator,
|
|
393
|
+
insetInput,
|
|
394
|
+
insetInputValue,
|
|
314
395
|
...rest
|
|
315
396
|
} = this.props;
|
|
316
397
|
const dateIcon = <IconCalendar aria-hidden />;
|
|
@@ -358,4 +439,9 @@ export default class DateInput extends BaseComponent<DateInputProps, {}> {
|
|
|
358
439
|
/>
|
|
359
440
|
);
|
|
360
441
|
}
|
|
442
|
+
|
|
443
|
+
render() {
|
|
444
|
+
const { insetInput } = this.props;
|
|
445
|
+
return insetInput ? this.renderInputInset() : this.renderTriggerInput();
|
|
446
|
+
}
|
|
361
447
|
}
|