@douyinfe/semi-ui 2.6.0-beta.0 → 2.7.0
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/button/__test__/button.test.js +7 -0
- package/button/buttonGroup.tsx +5 -2
- package/button/index.tsx +1 -1
- 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 +105 -2
- package/dist/css/semi.min.css +1 -1
- package/dist/umd/semi-ui.js +949 -163
- 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 +13 -0
- package/lib/cjs/button/Button.d.ts +4 -4
- package/lib/cjs/button/buttonGroup.d.ts +3 -2
- package/lib/cjs/button/buttonGroup.js +6 -2
- package/lib/cjs/button/index.d.ts +5 -6
- 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/iconButton/index.d.ts +2 -2
- package/lib/cjs/navigation/Item.d.ts +2 -2
- package/lib/cjs/navigation/Item.js +8 -6
- package/lib/cjs/navigation/SubNav.js +2 -2
- package/lib/cjs/radio/radioGroup.js +6 -0
- package/lib/cjs/select/index.js +5 -2
- package/lib/cjs/table/Body/index.d.ts +2 -0
- package/lib/cjs/table/Body/index.js +13 -4
- package/lib/cjs/tag/group.d.ts +2 -0
- package/lib/cjs/tag/group.js +4 -2
- package/lib/cjs/tooltip/index.js +6 -2
- 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/button/Button.d.ts +4 -4
- package/lib/es/button/buttonGroup.d.ts +3 -2
- package/lib/es/button/buttonGroup.js +5 -2
- package/lib/es/button/index.d.ts +5 -6
- 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/iconButton/index.d.ts +2 -2
- package/lib/es/navigation/Item.d.ts +2 -2
- package/lib/es/navigation/Item.js +8 -6
- package/lib/es/navigation/SubNav.js +2 -2
- package/lib/es/radio/radioGroup.js +6 -0
- package/lib/es/select/index.js +5 -2
- package/lib/es/table/Body/index.d.ts +2 -0
- package/lib/es/table/Body/index.js +13 -4
- package/lib/es/tag/group.d.ts +2 -0
- package/lib/es/tag/group.js +4 -2
- package/lib/es/tooltip/index.js +6 -2
- 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/navigation/Item.tsx +15 -12
- package/navigation/SubNav.tsx +4 -4
- 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/Body/index.tsx +15 -4
- package/table/__test__/table.test.js +18 -0
- package/table/_story/v2/FixedExpandedRow/index.jsx +95 -0
- package/table/_story/v2/index.js +2 -1
- package/tag/group.tsx +5 -3
- package/tooltip/_story/tooltip.stories.js +702 -625
- package/tooltip/index.tsx +2 -2
- 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
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
-
import DatePickerFoundation, { DatePickerAdapter, DatePickerFoundationProps, DatePickerFoundationState, DayStatusType, PresetType, Type } from '@douyinfe/semi-foundation/lib/es/datePicker/foundation';
|
|
3
|
+
import DatePickerFoundation, { DatePickerAdapter, DatePickerFoundationProps, DatePickerFoundationState, DayStatusType, PresetType, Type, RangeType } from '@douyinfe/semi-foundation/lib/es/datePicker/foundation';
|
|
4
4
|
import BaseComponent from '../_base/baseComponent';
|
|
5
5
|
import { DateInputProps } from './dateInput';
|
|
6
6
|
import MonthsGrid, { MonthsGridProps } from './monthsGrid';
|
|
7
7
|
import { YearAndMonthProps } from './yearAndMonth';
|
|
8
8
|
import '@douyinfe/semi-foundation/lib/es/datePicker/datePicker.css';
|
|
9
9
|
import { Locale } from '../locale/interface';
|
|
10
|
-
import { RangeType } from '@douyinfe/semi-foundation/lib/es/datePicker/inputFoundation';
|
|
11
10
|
import { TimePickerProps } from '../timePicker/TimePicker';
|
|
11
|
+
import { InsetInputChangeProps } from '@douyinfe/semi-foundation/lib/es/datePicker/inputFoundation';
|
|
12
12
|
export interface DatePickerProps extends DatePickerFoundationProps {
|
|
13
13
|
'aria-describedby'?: React.AriaAttributes['aria-describedby'];
|
|
14
14
|
'aria-errormessage'?: React.AriaAttributes['aria-errormessage'];
|
|
@@ -143,6 +143,7 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
|
|
|
143
143
|
autoSwitchDate: boolean;
|
|
144
144
|
syncSwitchMonth: boolean;
|
|
145
145
|
rangeSeparator: " ~ ";
|
|
146
|
+
insetInput: boolean;
|
|
146
147
|
};
|
|
147
148
|
triggerElRef: React.MutableRefObject<HTMLElement>;
|
|
148
149
|
panelRef: React.RefObject<HTMLDivElement>;
|
|
@@ -171,6 +172,7 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
|
|
|
171
172
|
renderQuickControls(): JSX.Element;
|
|
172
173
|
handleOpenPanel: () => void;
|
|
173
174
|
handleInputChange: DatePickerFoundation['handleInputChange'];
|
|
175
|
+
handleInsetInputChange: (options: InsetInputChangeProps) => void;
|
|
174
176
|
handleInputComplete: DatePickerFoundation['handleInputComplete'];
|
|
175
177
|
handleInputBlur: DateInputProps['onBlur'];
|
|
176
178
|
handleInputFocus: DatePickerFoundation['handleInputFocus'];
|
|
@@ -181,6 +183,9 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
|
|
|
181
183
|
handleRangeInputClear: DatePickerFoundation['handleRangeInputClear'];
|
|
182
184
|
handleRangeEndTabPress: DatePickerFoundation['handleRangeEndTabPress'];
|
|
183
185
|
isAnotherPanelHasOpened: (currentRangeInput: RangeType) => boolean;
|
|
186
|
+
handleInsetDateFocus: (e: React.FocusEvent, rangeType: 'rangeStart' | 'rangeEnd') => void;
|
|
187
|
+
handleInsetTimeFocus: () => void;
|
|
188
|
+
handlePanelVisibleChange: (visible: boolean) => void;
|
|
184
189
|
renderInner(extraProps?: Partial<DatePickerProps>): JSX.Element;
|
|
185
190
|
handleConfirm: (e: React.MouseEvent) => void;
|
|
186
191
|
handleCancel: (e: React.MouseEvent) => void;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import _isEqual from "lodash/isEqual";
|
|
1
2
|
import _isFunction from "lodash/isFunction";
|
|
2
3
|
import _get from "lodash/get";
|
|
3
4
|
import _isDate from "lodash/isDate";
|
|
@@ -12,6 +13,10 @@ import _concatInstanceProperty from "@babel/runtime-corejs3/core-js-stable/insta
|
|
|
12
13
|
/* eslint-disable jsx-a11y/click-events-have-key-events,jsx-a11y/interactive-supports-focus */
|
|
13
14
|
|
|
14
15
|
/* eslint-disable max-len */
|
|
16
|
+
|
|
17
|
+
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
|
18
|
+
|
|
19
|
+
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
|
15
20
|
import React from 'react';
|
|
16
21
|
import classnames from 'classnames';
|
|
17
22
|
import PropTypes from 'prop-types';
|
|
@@ -65,6 +70,8 @@ export default class DatePicker extends BaseComponent {
|
|
|
65
70
|
return _this.foundation.handleInputChange(...arguments);
|
|
66
71
|
};
|
|
67
72
|
|
|
73
|
+
this.handleInsetInputChange = options => this.foundation.handleInsetInputChange(options);
|
|
74
|
+
|
|
68
75
|
this.handleInputComplete = v => this.foundation.handleInputComplete(v);
|
|
69
76
|
|
|
70
77
|
this.handleInputBlur = e => this.foundation.handleInputBlur(_get(e, 'nativeEvent.target.value'), e);
|
|
@@ -93,6 +100,30 @@ export default class DatePicker extends BaseComponent {
|
|
|
93
100
|
}
|
|
94
101
|
};
|
|
95
102
|
|
|
103
|
+
this.handleInsetDateFocus = (e, rangeType) => {
|
|
104
|
+
const monthGridFoundation = _get(this, 'monthGrid.current.foundation');
|
|
105
|
+
|
|
106
|
+
if (monthGridFoundation) {
|
|
107
|
+
monthGridFoundation.showDatePanel(strings.PANEL_TYPE_LEFT);
|
|
108
|
+
monthGridFoundation.showDatePanel(strings.PANEL_TYPE_RIGHT);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
this.handleInputFocus(e, rangeType);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
this.handleInsetTimeFocus = () => {
|
|
115
|
+
const monthGridFoundation = _get(this, 'monthGrid.current.foundation');
|
|
116
|
+
|
|
117
|
+
if (monthGridFoundation) {
|
|
118
|
+
monthGridFoundation.showTimePicker(strings.PANEL_TYPE_LEFT);
|
|
119
|
+
monthGridFoundation.showTimePicker(strings.PANEL_TYPE_RIGHT);
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
this.handlePanelVisibleChange = visible => {
|
|
124
|
+
this.foundation.handlePanelVisibleChange(visible);
|
|
125
|
+
};
|
|
126
|
+
|
|
96
127
|
this.handleConfirm = e => this.foundation.handleConfirm();
|
|
97
128
|
|
|
98
129
|
this.handleCancel = e => this.foundation.handleCancel();
|
|
@@ -116,19 +147,43 @@ export default class DatePicker extends BaseComponent {
|
|
|
116
147
|
dropdownStyle,
|
|
117
148
|
density,
|
|
118
149
|
topSlot,
|
|
119
|
-
bottomSlot
|
|
150
|
+
bottomSlot,
|
|
151
|
+
insetInput,
|
|
152
|
+
type,
|
|
153
|
+
format,
|
|
154
|
+
rangeSeparator
|
|
120
155
|
} = this.props;
|
|
156
|
+
const {
|
|
157
|
+
insetInputValue,
|
|
158
|
+
value
|
|
159
|
+
} = this.state;
|
|
121
160
|
const wrapCls = classnames(cssClasses.PREFIX, {
|
|
122
161
|
[cssClasses.PANEL_YAM]: this.adapter.typeIsYearOrMonth(),
|
|
123
162
|
["".concat(cssClasses.PREFIX, "-compact")]: density === 'compact'
|
|
124
163
|
}, dropdownClassName);
|
|
164
|
+
const insetInputProps = {
|
|
165
|
+
dateFnsLocale,
|
|
166
|
+
format,
|
|
167
|
+
insetInputValue,
|
|
168
|
+
rangeSeparator,
|
|
169
|
+
type,
|
|
170
|
+
value: value,
|
|
171
|
+
handleInsetDateFocus: this.handleInsetDateFocus,
|
|
172
|
+
handleInsetTimeFocus: this.handleInsetTimeFocus,
|
|
173
|
+
onInsetInputChange: this.handleInsetInputChange,
|
|
174
|
+
rangeInputStartRef: this.rangeInputStartRef,
|
|
175
|
+
rangeInputEndRef: this.rangeInputEndRef,
|
|
176
|
+
density
|
|
177
|
+
};
|
|
125
178
|
return /*#__PURE__*/React.createElement("div", {
|
|
126
179
|
ref: this.panelRef,
|
|
127
180
|
className: wrapCls,
|
|
128
181
|
style: dropdownStyle
|
|
129
182
|
}, topSlot && /*#__PURE__*/React.createElement("div", {
|
|
130
183
|
className: "".concat(cssClasses.PREFIX, "-topSlot")
|
|
131
|
-
}, topSlot),
|
|
184
|
+
}, topSlot), insetInput && /*#__PURE__*/React.createElement(DateInput, _Object$assign({}, insetInputProps, {
|
|
185
|
+
insetInput: true
|
|
186
|
+
})), this.adapter.typeIsYearOrMonth() ? this.renderYearMonthPanel(locale, localeCode) : this.renderMonthGrid(locale, localeCode, dateFnsLocale), this.renderQuickControls(), bottomSlot && /*#__PURE__*/React.createElement("div", {
|
|
132
187
|
className: "".concat(cssClasses.PREFIX, "-bottomSlot")
|
|
133
188
|
}, bottomSlot), this.renderFooter(locale, localeCode));
|
|
134
189
|
};
|
|
@@ -192,7 +247,8 @@ export default class DatePicker extends BaseComponent {
|
|
|
192
247
|
position: position,
|
|
193
248
|
visible: panelShow,
|
|
194
249
|
stopPropagation: stopPropagation,
|
|
195
|
-
spacing: spacing
|
|
250
|
+
spacing: spacing,
|
|
251
|
+
onVisibleChange: this.handlePanelVisibleChange
|
|
196
252
|
}, children);
|
|
197
253
|
};
|
|
198
254
|
|
|
@@ -205,7 +261,9 @@ export default class DatePicker extends BaseComponent {
|
|
|
205
261
|
prevTimeZone: null,
|
|
206
262
|
motionEnd: false,
|
|
207
263
|
rangeInputFocus: undefined,
|
|
208
|
-
autofocus: props.autoFocus || this.isRangeType(props.type, props.triggerRender) && (props.open || props.defaultOpen)
|
|
264
|
+
autofocus: props.autoFocus || this.isRangeType(props.type, props.triggerRender) && (props.open || props.defaultOpen),
|
|
265
|
+
insetInputValue: null,
|
|
266
|
+
triggerDisabled: undefined
|
|
209
267
|
};
|
|
210
268
|
this.adapter.setCache('cachedSelectedValue', null);
|
|
211
269
|
this.triggerElRef = /*#__PURE__*/React.createRef();
|
|
@@ -308,6 +366,17 @@ export default class DatePicker extends BaseComponent {
|
|
|
308
366
|
inputValue
|
|
309
367
|
});
|
|
310
368
|
},
|
|
369
|
+
updateInsetInputValue: insetInputValue => {
|
|
370
|
+
const {
|
|
371
|
+
insetInput
|
|
372
|
+
} = this.props;
|
|
373
|
+
|
|
374
|
+
if (insetInput && !_isEqual(insetInputValue, this.state.insetInputValue)) {
|
|
375
|
+
this.setState({
|
|
376
|
+
insetInputValue
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
},
|
|
311
380
|
needConfirm: () => {
|
|
312
381
|
var _context;
|
|
313
382
|
|
|
@@ -382,7 +451,38 @@ export default class DatePicker extends BaseComponent {
|
|
|
382
451
|
}
|
|
383
452
|
},
|
|
384
453
|
couldPanelClosed: () => this.focusRecordsRef.current.rangeStart && this.focusRecordsRef.current.rangeEnd,
|
|
385
|
-
isEventTarget: e => e && e.target === e.currentTarget
|
|
454
|
+
isEventTarget: e => e && e.target === e.currentTarget,
|
|
455
|
+
setInsetInputFocus: () => {
|
|
456
|
+
const {
|
|
457
|
+
rangeInputFocus
|
|
458
|
+
} = this.state;
|
|
459
|
+
|
|
460
|
+
switch (rangeInputFocus) {
|
|
461
|
+
case 'rangeEnd':
|
|
462
|
+
if (document.activeElement !== this.rangeInputEndRef.current) {
|
|
463
|
+
const inputEndNode = _get(this, 'rangeInputEndRef.current');
|
|
464
|
+
|
|
465
|
+
inputEndNode && inputEndNode.focus();
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
break;
|
|
469
|
+
|
|
470
|
+
case 'rangeStart':
|
|
471
|
+
default:
|
|
472
|
+
if (document.activeElement !== this.rangeInputStartRef.current) {
|
|
473
|
+
const inputStartNode = _get(this, 'rangeInputStartRef.current');
|
|
474
|
+
|
|
475
|
+
inputStartNode && inputStartNode.focus();
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
break;
|
|
479
|
+
}
|
|
480
|
+
},
|
|
481
|
+
setTriggerDisabled: disabled => {
|
|
482
|
+
this.setState({
|
|
483
|
+
triggerDisabled: disabled
|
|
484
|
+
});
|
|
485
|
+
}
|
|
386
486
|
});
|
|
387
487
|
}
|
|
388
488
|
|
|
@@ -440,7 +540,8 @@ export default class DatePicker extends BaseComponent {
|
|
|
440
540
|
syncSwitchMonth,
|
|
441
541
|
onPanelChange,
|
|
442
542
|
timeZone,
|
|
443
|
-
triggerRender
|
|
543
|
+
triggerRender,
|
|
544
|
+
insetInput
|
|
444
545
|
} = this.props;
|
|
445
546
|
const {
|
|
446
547
|
value,
|
|
@@ -488,7 +589,8 @@ export default class DatePicker extends BaseComponent {
|
|
|
488
589
|
onPanelChange: onPanelChange,
|
|
489
590
|
timeZone: timeZone,
|
|
490
591
|
focusRecordsRef: this.focusRecordsRef,
|
|
491
|
-
triggerRender: triggerRender
|
|
592
|
+
triggerRender: triggerRender,
|
|
593
|
+
insetInput: insetInput
|
|
492
594
|
});
|
|
493
595
|
}
|
|
494
596
|
|
|
@@ -524,20 +626,23 @@ export default class DatePicker extends BaseComponent {
|
|
|
524
626
|
triggerRender,
|
|
525
627
|
size,
|
|
526
628
|
inputReadOnly,
|
|
527
|
-
rangeSeparator
|
|
629
|
+
rangeSeparator,
|
|
630
|
+
insetInput
|
|
528
631
|
} = this.props;
|
|
529
632
|
const {
|
|
530
633
|
value,
|
|
531
634
|
inputValue,
|
|
532
|
-
rangeInputFocus
|
|
635
|
+
rangeInputFocus,
|
|
636
|
+
triggerDisabled
|
|
533
637
|
} = this.state; // This class is not needed when triggerRender is function
|
|
534
638
|
|
|
535
639
|
const isRangeType = this.isRangeType(type, triggerRender);
|
|
640
|
+
const inputDisabled = disabled || insetInput && triggerDisabled;
|
|
536
641
|
const inputCls = classnames("".concat(cssClasses.PREFIX, "-input"), {
|
|
537
642
|
["".concat(cssClasses.PREFIX, "-range-input")]: isRangeType,
|
|
538
643
|
[_concatInstanceProperty(_context3 = "".concat(cssClasses.PREFIX, "-range-input-")).call(_context3, size)]: isRangeType && size,
|
|
539
|
-
["".concat(cssClasses.PREFIX, "-range-input-active")]: isRangeType && rangeInputFocus && !
|
|
540
|
-
["".concat(cssClasses.PREFIX, "-range-input-disabled")]: isRangeType &&
|
|
644
|
+
["".concat(cssClasses.PREFIX, "-range-input-active")]: isRangeType && rangeInputFocus && !inputDisabled,
|
|
645
|
+
["".concat(cssClasses.PREFIX, "-range-input-disabled")]: isRangeType && inputDisabled,
|
|
541
646
|
[_concatInstanceProperty(_context4 = "".concat(cssClasses.PREFIX, "-range-input-")).call(_context4, validateStatus)]: isRangeType && validateStatus
|
|
542
647
|
});
|
|
543
648
|
const phText = placeholder || locale.placeholder[type]; // i18n
|
|
@@ -545,9 +650,9 @@ export default class DatePicker extends BaseComponent {
|
|
|
545
650
|
|
|
546
651
|
const props = _Object$assign(_Object$assign({}, extraProps), {
|
|
547
652
|
placeholder: phText,
|
|
548
|
-
disabled,
|
|
653
|
+
disabled: inputDisabled,
|
|
549
654
|
inputValue,
|
|
550
|
-
value,
|
|
655
|
+
value: value,
|
|
551
656
|
onChange: this.handleInputChange,
|
|
552
657
|
onEnterPress: this.handleInputComplete,
|
|
553
658
|
// TODO: remove in next major version
|
|
@@ -560,7 +665,7 @@ export default class DatePicker extends BaseComponent {
|
|
|
560
665
|
format,
|
|
561
666
|
multiple,
|
|
562
667
|
validateStatus,
|
|
563
|
-
inputReadOnly,
|
|
668
|
+
inputReadOnly: inputReadOnly || insetInput,
|
|
564
669
|
// onClick: this.handleOpenPanel,
|
|
565
670
|
onBlur: this.handleInputBlur,
|
|
566
671
|
onFocus: this.handleInputFocus,
|
|
@@ -569,13 +674,13 @@ export default class DatePicker extends BaseComponent {
|
|
|
569
674
|
size,
|
|
570
675
|
autofocus: this.state.autofocus,
|
|
571
676
|
dateFnsLocale,
|
|
572
|
-
rangeInputStartRef: this.rangeInputStartRef,
|
|
573
|
-
rangeInputEndRef: this.rangeInputEndRef,
|
|
574
677
|
rangeInputFocus,
|
|
575
678
|
rangeSeparator,
|
|
576
679
|
onRangeBlur: this.handleRangeInputBlur,
|
|
577
680
|
onRangeClear: this.handleRangeInputClear,
|
|
578
|
-
onRangeEndTabPress: this.handleRangeEndTabPress
|
|
681
|
+
onRangeEndTabPress: this.handleRangeEndTabPress,
|
|
682
|
+
rangeInputStartRef: insetInput ? null : this.rangeInputStartRef,
|
|
683
|
+
rangeInputEndRef: insetInput ? null : this.rangeInputEndRef
|
|
579
684
|
});
|
|
580
685
|
|
|
581
686
|
return /*#__PURE__*/React.createElement("div", {
|
|
@@ -723,5 +828,6 @@ DatePicker.defaultProps = {
|
|
|
723
828
|
spacing: numbers.SPACING,
|
|
724
829
|
autoSwitchDate: true,
|
|
725
830
|
syncSwitchMonth: false,
|
|
726
|
-
rangeSeparator: strings.DEFAULT_SEPARATOR_RANGE
|
|
831
|
+
rangeSeparator: strings.DEFAULT_SEPARATOR_RANGE,
|
|
832
|
+
insetInput: false
|
|
727
833
|
};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import _Object$assign from "@babel/runtime-corejs3/core-js-stable/object/assign";
|
|
2
2
|
import _trimInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/trim";
|
|
3
|
+
import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes";
|
|
3
4
|
import React from 'react';
|
|
4
5
|
import { forwardStatics } from '@douyinfe/semi-foundation/lib/es/utils/object';
|
|
6
|
+
import { numbers, strings } from '@douyinfe/semi-foundation/lib/es/datePicker/constants';
|
|
5
7
|
import DatePicker from './datePicker';
|
|
6
8
|
import ConfigContext from '../configProvider/context';
|
|
7
9
|
import LocaleConsumer from '../locale/localeConsumer';
|
|
@@ -29,6 +31,24 @@ export default forwardStatics( /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
29
31
|
propsObj.rangeSeparator = " ".concat(_trimInstanceProperty(rangeSeparator).call(rangeSeparator), " ");
|
|
30
32
|
}
|
|
31
33
|
|
|
34
|
+
if (propsObj.insetInput) {
|
|
35
|
+
var _context;
|
|
36
|
+
|
|
37
|
+
if (!propsObj.position) {
|
|
38
|
+
propsObj.position = strings.POSITION_INLINE_INPUT;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* When insetInput is `true` and `position` includes `over`, use 1px `spacing` to solve the problem of border-radius leakage in the upper left corner
|
|
42
|
+
*
|
|
43
|
+
* @see https://user-images.githubusercontent.com/26477537/158817185-126a5f33-41f7-414a-8e36-8d1be2dda5cd.png
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
if (_includesInstanceProperty(_context = propsObj.position).call(_context, 'Over') && !propsObj.spacing) {
|
|
48
|
+
propsObj.spacing = numbers.SPACING_INSET_INPUT;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
32
52
|
return /*#__PURE__*/React.createElement(ConfigContext.Consumer, null, _ref => {
|
|
33
53
|
let {
|
|
34
54
|
timeZone
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { InsetInputValue, Type, InsetInputChangeFoundationProps } from '@douyinfe/semi-foundation/lib/es/datePicker/inputFoundation';
|
|
2
|
+
import { InputProps } from '../input';
|
|
3
|
+
export interface InsetDateInputProps {
|
|
4
|
+
forwardRef: InputProps['forwardRef'];
|
|
5
|
+
insetInputValue: InsetInputValue;
|
|
6
|
+
placeholder: string;
|
|
7
|
+
valuePath: string;
|
|
8
|
+
onChange: (options: InsetInputChangeFoundationProps) => void;
|
|
9
|
+
onFocus: InputProps['onFocus'];
|
|
10
|
+
}
|
|
11
|
+
export interface InsetTimeInputProps {
|
|
12
|
+
disabled: boolean;
|
|
13
|
+
insetInputValue: InsetInputValue;
|
|
14
|
+
placeholder: string;
|
|
15
|
+
valuePath: string;
|
|
16
|
+
type: Type;
|
|
17
|
+
onChange: (options: InsetInputChangeFoundationProps) => void;
|
|
18
|
+
onFocus: InputProps['onFocus'];
|
|
19
|
+
}
|
|
20
|
+
export declare function InsetDateInput(props: InsetDateInputProps): JSX.Element;
|
|
21
|
+
export declare function InsetTimeInput(props: InsetTimeInputProps): JSX.Element;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import _get from "lodash/get";
|
|
2
|
+
import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes";
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import Input from '../input';
|
|
5
|
+
export function InsetDateInput(props) {
|
|
6
|
+
const {
|
|
7
|
+
insetInputValue,
|
|
8
|
+
valuePath,
|
|
9
|
+
onFocus,
|
|
10
|
+
onChange,
|
|
11
|
+
placeholder,
|
|
12
|
+
forwardRef
|
|
13
|
+
} = props;
|
|
14
|
+
|
|
15
|
+
const value = _get(insetInputValue, valuePath);
|
|
16
|
+
|
|
17
|
+
return /*#__PURE__*/React.createElement(Input, {
|
|
18
|
+
value: value,
|
|
19
|
+
onChange: (value, event) => {
|
|
20
|
+
onChange({
|
|
21
|
+
value,
|
|
22
|
+
event,
|
|
23
|
+
insetInputValue,
|
|
24
|
+
valuePath
|
|
25
|
+
});
|
|
26
|
+
},
|
|
27
|
+
onFocus: onFocus,
|
|
28
|
+
placeholder: placeholder,
|
|
29
|
+
ref: forwardRef
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
export function InsetTimeInput(props) {
|
|
33
|
+
const {
|
|
34
|
+
insetInputValue,
|
|
35
|
+
valuePath,
|
|
36
|
+
type,
|
|
37
|
+
onFocus,
|
|
38
|
+
onChange,
|
|
39
|
+
placeholder,
|
|
40
|
+
disabled
|
|
41
|
+
} = props;
|
|
42
|
+
|
|
43
|
+
const _isTimeType = _includesInstanceProperty(type).call(type, 'Time');
|
|
44
|
+
|
|
45
|
+
if (!_isTimeType) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const value = _get(insetInputValue, valuePath);
|
|
50
|
+
|
|
51
|
+
return /*#__PURE__*/React.createElement(Input, {
|
|
52
|
+
value: value,
|
|
53
|
+
onChange: (value, event) => {
|
|
54
|
+
onChange({
|
|
55
|
+
value,
|
|
56
|
+
event,
|
|
57
|
+
insetInputValue,
|
|
58
|
+
valuePath
|
|
59
|
+
});
|
|
60
|
+
},
|
|
61
|
+
onFocus: onFocus,
|
|
62
|
+
placeholder: placeholder,
|
|
63
|
+
disabled: disabled
|
|
64
|
+
});
|
|
65
|
+
}
|
|
@@ -9,6 +9,8 @@ import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/ins
|
|
|
9
9
|
|
|
10
10
|
/* eslint-disable jsx-a11y/interactive-supports-focus,jsx-a11y/click-events-have-key-events */
|
|
11
11
|
|
|
12
|
+
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
|
13
|
+
|
|
12
14
|
/* eslint-disable react/no-did-update-set-state */
|
|
13
15
|
|
|
14
16
|
/* eslint-disable max-len */
|
|
@@ -284,6 +286,9 @@ export default class MonthsGrid extends BaseComponent {
|
|
|
284
286
|
monthRight,
|
|
285
287
|
currentPanelHeight
|
|
286
288
|
} = this.state;
|
|
289
|
+
const {
|
|
290
|
+
insetInput
|
|
291
|
+
} = this.props;
|
|
287
292
|
const panelDetail = panelType === strings.PANEL_TYPE_RIGHT ? monthRight : monthLeft;
|
|
288
293
|
const {
|
|
289
294
|
isTimePickerOpen,
|
|
@@ -306,7 +311,7 @@ export default class MonthsGrid extends BaseComponent {
|
|
|
306
311
|
style.minWidth = wrap.getBoundingClientRect().width;
|
|
307
312
|
}
|
|
308
313
|
|
|
309
|
-
if (this.leftIsYearOrTime() && this.rightIsYearOrTime()) {
|
|
314
|
+
if (this.leftIsYearOrTime() && this.rightIsYearOrTime() && !insetInput) {
|
|
310
315
|
/**
|
|
311
316
|
* left和right同时为tpk时,panel会有一个minHeight
|
|
312
317
|
* 如果缓存的currentPanelHeight为0,则需要计算滚动列表的高度
|
|
@@ -316,7 +321,7 @@ export default class MonthsGrid extends BaseComponent {
|
|
|
316
321
|
* When left and right are tpk at the same time, the panel will have a minHeight
|
|
317
322
|
* If the cached currentPanelHeight is 0, you need to calculate the height of the scrolling list
|
|
318
323
|
* If there is a cached value, use currentPanelHeight (if this height is less than the actual value, it will affect the number of cycles in the ScrollList to render the list)
|
|
319
|
-
* See packages/semi-foundation/scrollList/
|
|
324
|
+
* See packages/semi-foundation/scrollList/itemFoundation.js initWheelList function
|
|
320
325
|
*/
|
|
321
326
|
style.minHeight = currentPanelHeight ? currentPanelHeight : this.calcScrollListHeight();
|
|
322
327
|
}
|
|
@@ -324,10 +329,14 @@ export default class MonthsGrid extends BaseComponent {
|
|
|
324
329
|
monthCls = classnames(monthCls, "".concat(prefixCls, "-yam-showing"));
|
|
325
330
|
}
|
|
326
331
|
|
|
332
|
+
const _isDatePanelOpen = !(isYearPickerOpen || isTimePickerOpen);
|
|
333
|
+
|
|
334
|
+
const xOpenType = _isDatePanelOpen ? 'date' : isYearPickerOpen ? 'year' : 'time';
|
|
327
335
|
return /*#__PURE__*/React.createElement("div", {
|
|
328
336
|
className: monthCls,
|
|
329
337
|
key: panelType,
|
|
330
|
-
style: style
|
|
338
|
+
style: style,
|
|
339
|
+
"x-open-type": xOpenType
|
|
331
340
|
}, yearAndMonthLayer, timePickerLayer, this.foundation.isRangeType() ? panelContent : isYearPickerOpen || isTimePickerOpen ? null : panelContent, this.renderSwitch(panelType));
|
|
332
341
|
}
|
|
333
342
|
|
|
@@ -538,10 +547,11 @@ export default class MonthsGrid extends BaseComponent {
|
|
|
538
547
|
locale,
|
|
539
548
|
disabledTimePicker,
|
|
540
549
|
density,
|
|
541
|
-
dateFnsLocale
|
|
542
|
-
|
|
550
|
+
dateFnsLocale,
|
|
551
|
+
insetInput
|
|
552
|
+
} = this.props; // Type: date, dateRange, year, month, inset input no rendering required
|
|
543
553
|
|
|
544
|
-
if (!_includesInstanceProperty(type).call(type, 'Time')) {
|
|
554
|
+
if (!_includesInstanceProperty(type).call(type, 'Time') || insetInput) {
|
|
545
555
|
return null;
|
|
546
556
|
} // switch year/month & time
|
|
547
557
|
|
|
@@ -614,7 +624,8 @@ export default class MonthsGrid extends BaseComponent {
|
|
|
614
624
|
monthRight
|
|
615
625
|
} = this.state;
|
|
616
626
|
const {
|
|
617
|
-
type
|
|
627
|
+
type,
|
|
628
|
+
insetInput
|
|
618
629
|
} = this.props;
|
|
619
630
|
const monthGridCls = classnames({
|
|
620
631
|
["".concat(prefixCls, "-month-grid")]: true
|
|
@@ -636,6 +647,7 @@ export default class MonthsGrid extends BaseComponent {
|
|
|
636
647
|
className: monthGridCls,
|
|
637
648
|
"x-type": type,
|
|
638
649
|
"x-panel-yearandmonth-open-type": yearOpenType,
|
|
650
|
+
"x-insetInput": insetInput ? "true" : "false",
|
|
639
651
|
ref: current => this.cacheRefCurrent('monthGrid', current)
|
|
640
652
|
}, content);
|
|
641
653
|
}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { BaseFormApi } from '@douyinfe/semi-foundation/lib/es/form/interface';
|
|
2
|
+
export default function useFormApi<T extends Record<string, any> = any>(): BaseFormApi<T>;
|
|
@@ -19,7 +19,7 @@ export interface IconButtonProps extends ButtonProps {
|
|
|
19
19
|
}
|
|
20
20
|
declare class IconButton extends PureComponent<IconButtonProps> {
|
|
21
21
|
static defaultProps: {
|
|
22
|
-
iconPosition:
|
|
22
|
+
iconPosition: "left";
|
|
23
23
|
prefixCls: string;
|
|
24
24
|
loading: boolean;
|
|
25
25
|
noHorizontalPadding: boolean;
|
|
@@ -36,7 +36,7 @@ declare class IconButton extends PureComponent<IconButtonProps> {
|
|
|
36
36
|
noHorizontalPadding: PropTypes.Requireable<string | boolean | any[]>;
|
|
37
37
|
children: PropTypes.Requireable<PropTypes.ReactNodeLike>;
|
|
38
38
|
theme: PropTypes.Requireable<string>;
|
|
39
|
-
iconPosition: PropTypes.Requireable<
|
|
39
|
+
iconPosition: PropTypes.Requireable<"left" | "right">;
|
|
40
40
|
className: PropTypes.Requireable<string>;
|
|
41
41
|
onMouseEnter: PropTypes.Requireable<(...args: any[]) => any>;
|
|
42
42
|
onMouseLeave: PropTypes.Requireable<(...args: any[]) => any>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import BaseComponent, { BaseProps } from '../_base/baseComponent';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
|
-
import ItemFoundation, { ItemProps, SelectedItemProps
|
|
4
|
+
import ItemFoundation, { ItemAdapter, ItemProps, SelectedItemProps } from '@douyinfe/semi-foundation/lib/es/navigation/itemFoundation';
|
|
5
5
|
export interface NavItemProps extends ItemProps, BaseProps {
|
|
6
6
|
children?: React.ReactNode;
|
|
7
7
|
disabled?: boolean;
|
|
@@ -63,7 +63,7 @@ export default class NavItem extends BaseComponent<NavItemProps, NavItemState> {
|
|
|
63
63
|
constructor(props: NavItemProps);
|
|
64
64
|
_invokeContextFunc(funcName: string, ...args: any[]): any;
|
|
65
65
|
get adapter(): ItemAdapter<NavItemProps, NavItemState>;
|
|
66
|
-
renderIcon(icon: React.ReactNode, pos: string, isToggleIcon?: boolean): JSX.Element;
|
|
66
|
+
renderIcon(icon: React.ReactNode, pos: string, isToggleIcon?: boolean, key?: number | string): JSX.Element;
|
|
67
67
|
setItemRef: (ref: HTMLLIElement) => void;
|
|
68
68
|
wrapTooltip: (node: React.ReactNode) => JSX.Element;
|
|
69
69
|
handleClick: (e: React.MouseEvent) => void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import _noop from "lodash/noop";
|
|
2
1
|
import _times from "lodash/times";
|
|
2
|
+
import _noop from "lodash/noop";
|
|
3
3
|
import _Object$assign from "@babel/runtime-corejs3/core-js-stable/object/assign";
|
|
4
4
|
import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes";
|
|
5
5
|
import _concatInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/concat";
|
|
@@ -14,7 +14,7 @@ import cls from 'classnames';
|
|
|
14
14
|
import isNullOrUndefined from '@douyinfe/semi-foundation/lib/es/utils/isNullOrUndefined';
|
|
15
15
|
import { cloneDeep, isSemiIcon } from '../_utils';
|
|
16
16
|
import ItemFoundation from '@douyinfe/semi-foundation/lib/es/navigation/itemFoundation';
|
|
17
|
-
import {
|
|
17
|
+
import { cssClasses, strings } from '@douyinfe/semi-foundation/lib/es/navigation/constants';
|
|
18
18
|
import Tooltip from '../tooltip';
|
|
19
19
|
import NavContext from './nav-context';
|
|
20
20
|
import Dropdown from '../dropdown';
|
|
@@ -118,6 +118,7 @@ export default class NavItem extends BaseComponent {
|
|
|
118
118
|
var _context3;
|
|
119
119
|
|
|
120
120
|
let isToggleIcon = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
121
|
+
let key = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
|
|
121
122
|
|
|
122
123
|
if (this.props.isSubNav) {
|
|
123
124
|
return null;
|
|
@@ -138,7 +139,8 @@ export default class NavItem extends BaseComponent {
|
|
|
138
139
|
["".concat(clsPrefix, "-icon-info")]: !isToggleIcon
|
|
139
140
|
});
|
|
140
141
|
return /*#__PURE__*/React.createElement("i", {
|
|
141
|
-
className: className
|
|
142
|
+
className: className,
|
|
143
|
+
key: key
|
|
142
144
|
}, isSemiIcon(icon) ? /*#__PURE__*/React.cloneElement(icon, {
|
|
143
145
|
size: icon.props.size || iconSize
|
|
144
146
|
}) : icon);
|
|
@@ -178,12 +180,12 @@ export default class NavItem extends BaseComponent {
|
|
|
178
180
|
|
|
179
181
|
if (mode === strings.MODE_VERTICAL && !limitIndent && !isCollapsed) {
|
|
180
182
|
const iconAmount = icon && !indent ? level : level - 1;
|
|
181
|
-
placeholderIcons = _times(iconAmount,
|
|
183
|
+
placeholderIcons = _times(iconAmount, index => this.renderIcon(null, strings.ICON_POS_RIGHT, false, index));
|
|
182
184
|
}
|
|
183
185
|
|
|
184
|
-
itemChildren = /*#__PURE__*/React.createElement(React.Fragment, null, placeholderIcons, this.context.toggleIconPosition === strings.TOGGLE_ICON_LEFT && this.renderIcon(toggleIcon, strings.ICON_POS_RIGHT, true), icon || indent || isInSubNav ? this.renderIcon(icon, strings.ICON_POS_LEFT) : null, !isNullOrUndefined(text) ? /*#__PURE__*/React.createElement("span", {
|
|
186
|
+
itemChildren = /*#__PURE__*/React.createElement(React.Fragment, null, placeholderIcons, this.context.toggleIconPosition === strings.TOGGLE_ICON_LEFT && this.renderIcon(toggleIcon, strings.ICON_POS_RIGHT, true, 'key-toggle-pos-right'), icon || indent || isInSubNav ? this.renderIcon(icon, strings.ICON_POS_LEFT, false, 'key-position-left') : null, !isNullOrUndefined(text) ? /*#__PURE__*/React.createElement("span", {
|
|
185
187
|
className: "".concat(cssClasses.PREFIX, "-item-text")
|
|
186
|
-
}, text) : '', this.context.toggleIconPosition === strings.TOGGLE_ICON_RIGHT && this.renderIcon(toggleIcon, strings.ICON_POS_RIGHT, true));
|
|
188
|
+
}, text) : '', this.context.toggleIconPosition === strings.TOGGLE_ICON_RIGHT && this.renderIcon(toggleIcon, strings.ICON_POS_RIGHT, true, 'key-toggle-pos-right'));
|
|
187
189
|
}
|
|
188
190
|
|
|
189
191
|
if (typeof link === 'string') {
|
|
@@ -203,7 +203,7 @@ export default class SubNav extends BaseComponent {
|
|
|
203
203
|
if (mode === strings.MODE_VERTICAL && !limitIndent && !isCollapsed) {
|
|
204
204
|
/* Different icons' amount means different indents.*/
|
|
205
205
|
const iconAmount = icon && !indent ? level : level - 1;
|
|
206
|
-
placeholderIcons = _times(iconAmount, index => this.renderIcon(null, strings.ICON_POS_RIGHT, false,
|
|
206
|
+
placeholderIcons = _times(iconAmount, index => this.renderIcon(null, strings.ICON_POS_RIGHT, false, false, index));
|
|
207
207
|
}
|
|
208
208
|
|
|
209
209
|
const titleDiv = /*#__PURE__*/React.createElement("div", {
|
|
@@ -215,7 +215,7 @@ export default class SubNav extends BaseComponent {
|
|
|
215
215
|
onKeyPress: this.handleKeyPress
|
|
216
216
|
}, /*#__PURE__*/React.createElement("div", {
|
|
217
217
|
className: "".concat(prefixCls, "-item-inner")
|
|
218
|
-
}, placeholderIcons, this.context.toggleIconPosition === strings.TOGGLE_ICON_LEFT && this.renderIcon(toggleIconType, strings.ICON_POS_RIGHT, withTransition, true, 'key-toggle-position-left'), icon || indent || isInSubNav && mode !== strings.MODE_HORIZONTAL ? this.renderIcon(icon, strings.ICON_POS_LEFT,
|
|
218
|
+
}, placeholderIcons, this.context.toggleIconPosition === strings.TOGGLE_ICON_LEFT && this.renderIcon(toggleIconType, strings.ICON_POS_RIGHT, withTransition, true, 'key-toggle-position-left'), icon || indent || isInSubNav && mode !== strings.MODE_HORIZONTAL ? this.renderIcon(icon, strings.ICON_POS_LEFT, false, false, 'key-inSubNav-position-left') : null, /*#__PURE__*/React.createElement("span", {
|
|
219
219
|
className: "".concat(prefixCls, "-item-text")
|
|
220
220
|
}, text), this.context.toggleIconPosition === strings.TOGGLE_ICON_RIGHT && this.renderIcon(toggleIconType, strings.ICON_POS_RIGHT, withTransition, true, 'key-toggle-position-right')));
|
|
221
221
|
return titleDiv;
|
|
@@ -32,6 +32,12 @@ class RadioGroup extends BaseComponent {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
componentDidUpdate(prevProps) {
|
|
35
|
+
if (typeof prevProps.value === 'number' && isNaN(prevProps.value) && typeof this.props.value === 'number' && isNaN(this.props.value)) {
|
|
36
|
+
// `NaN === NaN` returns false, and this will fail the next if check
|
|
37
|
+
// therefore triggering an infinite loop
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
35
41
|
if (prevProps.value !== this.props.value) {
|
|
36
42
|
this.foundation.handlePropValueChange(this.props.value);
|
|
37
43
|
}
|