瀏覽代碼

feat: [DatePicker] insetInput support object type #1343 (#1405)

* feat: [DatePicker] insetInput support object type #1343

* fix: [DatePicker] update insetInput ts interface #1343

* chore: [DatePicker] export InsetInputProps ts interface

---------

Co-authored-by: shijia.me <[email protected]>
Co-authored-by: pointhalo <[email protected]>
走鹃 2 年之前
父節點
當前提交
8609109508

+ 2 - 2
content/input/datepicker/index-en-US.md

@@ -872,7 +872,7 @@ function Demo() {
 | autoSwitchDate     | When the year and month are changed through the left and right buttons and the drop-down menu at the top of the panel, the date is automatically switched. Only valid for `date` type. | boolean   | true    | **1.13.0** |
 | bottomSlot         | Render the bottom extra area                                                                                                                                                           | ReactNode |         | **1.22.0** |
 | className          | Class name                                                                                                                                                                             | string    | -       |            |
-| clearIcon | Can be used to customize the clear button, valid when showClear is true | ReactNode |  |**2.25.0** |
+| clearIcon          | Can be used to customize the clear button, valid when showClear is true                                                                                                                | ReactNode |         | **2.25.0** |
 | defaultOpen        | Panel displays or hides by default                                                                                                                                                     | boolean   | false   |            |
 | defaultPickerValue | Default panel date                                                                                                                                                                     | ValueType |         |            |
 | defaultValue       | Default value                                                                                                                                                                            | ValueType                                                                                                                                                                                                    |                                             |                           |  |
@@ -888,7 +888,7 @@ function Demo() {
 | format             | Date string format displayed in the input box                                                                                                                                             | string                                                                                                                                                                                                    | Corresponding to type: For details, see [Date and Time Format](#Date%20and%20Time%20Format) |                           |
 | getPopupContainer | Specifies the parent DOM, and the bullet layer will be rendered to the DOM, you need to set 'position: relative` | function():HTMLElement | () = > document.body |
 | inputReadOnly      | Is the text box readonly                                                                                                                                                                  | boolean                                                                                                                                                                                                   | false                                                                                 |                           |
-| insetInput        | Whether the input box is embedded in the panel                                                                                                                                            | boolean                                                                                                                                                                                                   | false                                                                                 | **2.7.0**                          |
+| insetInput        | Whether the input box is embedded in the panel. InsetInputProps type supported after v2.29                                                                                                                                | boolean  \| <ApiType detail='{ placeholder?: { dateStart?: string; dateEnd?: string; timeStart?: string; timeEnd?: string } }'>InsetInputProps</ApiType>                                                                                                                                                                                                | false                                                                                 | **2.7.0**                          |
 | inputStyle         | Input box style                                                                                                                                                                           | object                                                                                                                                                                                                    |                                                                                       |                           |
 | insetLabel         | Prefix label, lower priority than `prefix`                                                                                                                                                | string\|ReactNode                                                                                                                                                                                         |                                                                                       |                           |
 | max                | When multiple is set to true, the number of selected, non-pass or value is null\|undefined, unlimited.                                                                                     | number                                                                                                                                                                                                    | -                                                                                     |                           |

+ 2 - 2
content/input/datepicker/index.md

@@ -835,7 +835,7 @@ function Demo() {
 | autoSwitchDate     | 通过面板上方左右按钮、下拉菜单更改年月时,自动切换日期。仅对 date type 生效。 | boolean   | true    | **1.13.0** |
 | bottomSlot         | 渲染底部额外区域                                                          | ReactNode |         | **1.22.0** |
 | className          | 类名                                                                      | string    | -       |            |
-| clearIcon | 可用于自定义清除按钮, showClear为true时有效 | ReactNode |   | **2.25.0**|
+| clearIcon          | 可用于自定义清除按钮, showClear为true时有效                               | ReactNode |         | **2.25.0** |
 | defaultOpen        | 面板默认显示或隐藏                                                        | boolean   | false   |            |
 | defaultPickerValue | 默认面板日期                                                              | ValueType |         |            |
 | defaultValue       | 默认值                                                                    | ValueType |         |            |
@@ -851,7 +851,7 @@ function Demo() {
 | format | 在输入框内展现的日期串格式 | string | 与 type 对应:详见[日期时间格式](#日期时间格式) |  |
 | getPopupContainer | 指定父级 DOM,弹层将会渲染至该 DOM 中,自定义需要设置 `position: relative` | function():HTMLElement | () => document.body |  |
 | hideDisabledOptions | 隐藏禁止选择的时间 | boolean | false |  |
-| insetInput | 面板中是否嵌入输入框 | boolean | false |  | **2.7.0**
+| insetInput | 面板中是否嵌入输入框,InsetInputProps 类型 v2.29 支持  | boolean \| <ApiType detail='{ placeholder?: { dateStart?: string; dateEnd?: string; timeStart?: string; timeEnd?: string } }'>InsetInputProps</ApiType>  | false | **2.7.0** |
 | inputReadOnly | 文本框是否 readonly | boolean | false |  |
 | inputStyle | 输入框样式 | object |  |  |
 | insetLabel | 前缀标签,优先级低于 `prefix` | string\|ReactNode |  |  |

+ 1 - 1
packages/semi-foundation/datePicker/foundation.ts

@@ -168,7 +168,7 @@ export interface DatePickerFoundationProps extends ElementProps, RenderProps, Ev
     dateFnsLocale?: any;
     localeCode?: string;
     rangeSeparator?: string;
-    insetInput?: boolean;
+    insetInput?: DateInputFoundationProps['insetInput'];
     preventScroll?: boolean
 }
 

+ 13 - 3
packages/semi-foundation/datePicker/inputFoundation.ts

@@ -38,9 +38,19 @@ export interface DateInputElementProps {
     prefix?: any
 }
 
+export interface InsetInputProps {
+    placeholder?: {
+        dateStart?: string;
+        dateEnd?: string;
+        timeStart?: string;
+        timeEnd?: string
+    }
+    // showClear?: boolean
+}
+
 export interface DateInputFoundationProps extends DateInputElementProps, DateInputEventHandlerProps {
     [x: string]: any;
-    value?: BaseValueType[];
+    value?: Date[];
     disabled?: boolean;
     type?: Type;
     showClear?: boolean;
@@ -51,7 +61,7 @@ export interface DateInputFoundationProps extends DateInputElementProps, DateInp
     prefixCls?: string;
     rangeSeparator?: string;
     panelType?: PanelType;
-    insetInput?: boolean;
+    insetInput?: boolean | InsetInputProps;
     insetInputValue?: InsetInputValue;
     density?: typeof strings.DENSITY_SET[number];
     defaultPickerValue?: ValueType
@@ -81,7 +91,7 @@ export interface InsetInputChangeProps {
     insetInputValue: InsetInputValue
 }
 
-export interface DateInputAdapter extends DefaultAdapter {
+export interface DateInputAdapter extends DefaultAdapter<DateInputFoundationProps, Record<string, any>> {
     updateIsFocusing: (isFocusing: boolean) => void;
     notifyClick: DateInputFoundationProps['onClick'];
     notifyChange: DateInputFoundationProps['onChange'];

+ 2 - 2
packages/semi-foundation/datePicker/monthsGridFoundation.ts

@@ -20,7 +20,7 @@ import { includes, isSet, isEqual, isFunction } from 'lodash';
 import { zonedTimeToUtc } from '../utils/date-fns-extra';
 import { getDefaultFormatTokenByType } from './_utils/getDefaultFormatToken';
 import isNullOrUndefined from '../utils/isNullOrUndefined';
-import { BaseValueType, PresetPosition, ValueType } from './foundation';
+import { BaseValueType, DateInputFoundationProps, PresetPosition, ValueType } from './foundation';
 import { MonthDayInfo } from './monthFoundation';
 import { ArrayElement } from '../utils/type';
 
@@ -90,7 +90,7 @@ export interface MonthsGridFoundationProps extends MonthsGridElementProps {
     isAnotherPanelHasOpened?: (currentRangeInput: 'rangeStart' | 'rangeEnd') => boolean;
     focusRecordsRef?: any;
     triggerRender?: (props: Record<string, any>) => any;
-    insetInput: boolean;
+    insetInput: DateInputFoundationProps['insetInput'];
     presetPosition?: PresetPosition;
     renderQuickControls?: any;
     renderDateInput?: any

+ 60 - 0
packages/semi-ui/datePicker/_story/v2/FeatInsetInputProps.tsx

@@ -0,0 +1,60 @@
+import React from 'react';
+import { DatePicker, Space, Button } from '../../../index';
+import { DatePickerProps } from '../../index';
+
+/**
+ * Test with Chromatic
+ */
+export default function App() {
+    const spacing = [200, 400];
+    const [density, setDensity] = React.useState(false);
+    // const defaultValue = '2022-01-15';
+    // const defaultRangeValue = ['2022-12-10', '2022-01-15'];
+
+    const props: DatePickerProps = {
+        defaultOpen: true,
+        motion: false,
+        density: density ? 'compact' : 'default',
+        defaultPickerValue: '2022-01-15',
+        insetInput: {
+            placeholder: {
+                dateStart: '开始日期',
+                dateEnd: '开始日期',
+                timeStart: '开始时间',
+                timeEnd: '结束时间',
+            },
+        }
+    };
+
+    const handleToggleDensity = () => {
+        setDensity(!density);
+    };
+
+    return (
+        <div style={{ height: '200vh' }}>
+            <div style={{ marginBottom: 12 }}>
+                <Space>
+                    <Button onClick={handleToggleDensity}>
+                        {`小尺寸=${density}`}
+                    </Button>
+                </Space>
+            </div>
+            <Space wrap spacing={spacing}>
+                <DatePicker placeholder='选择单个日期' {...props} />
+                <DatePicker placeholder='选择月' {...props} type='month' />
+                <DatePicker placeholder='选择日期时间' {...props} type='dateTime' />
+                <DatePicker placeholder='选择日期范围' {...props} type='dateRange' />
+                <DatePicker placeholder='选择日期时间范围' {...props} type='dateTimeRange' />
+            </Space>
+        </div>
+    );
+}
+
+App.parameters = {
+    chromatic: {
+        disableSnapshot: false,
+        delay: 3000,
+        viewports: [1800]
+    },
+};
+App.storyName = 'insetInputProps';

+ 1 - 0
packages/semi-ui/datePicker/_story/v2/index.js

@@ -12,3 +12,4 @@ export { default as FixedTriggerRender } from './FixTriggerRender';
 export { default as DisabledRange } from './DisabledRange';
 export { default as FixDisabledMonth } from './FixDisabledMonth';
 export { default as FixRangePanelShift } from './FixRangePanelShift';
+export { default as FeatInsetInputProps } from './FeatInsetInputProps';

+ 10 - 6
packages/semi-ui/datePicker/dateInput.tsx

@@ -5,6 +5,7 @@
 import React from 'react';
 import cls from 'classnames';
 import PropTypes from 'prop-types';
+import { get } from 'lodash';
 
 import DateInputFoundation, {
     DateInputAdapter,
@@ -12,6 +13,7 @@ import DateInputFoundation, {
     RangeType,
     InsetInputChangeProps,
     InsetInputChangeFoundationProps,
+    InsetInputProps
 } from '@douyinfe/semi-foundation/datePicker/inputFoundation';
 import { cssClasses, strings } from '@douyinfe/semi-foundation/datePicker/constants';
 import { noop } from '@douyinfe/semi-foundation/utils/function';
@@ -62,7 +64,7 @@ export default class DateInput extends BaseComponent<DateInputProps, {}> {
         rangeInputStartRef: PropTypes.object,
         rangeInputEndRef: PropTypes.object,
         rangeSeparator: PropTypes.string,
-        insetInput: PropTypes.bool,
+        insetInput: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
         insetInputValue: PropTypes.object,
         defaultPickerValue: PropTypes.oneOfType([
             PropTypes.string,
@@ -202,7 +204,7 @@ export default class DateInput extends BaseComponent<DateInputProps, {}> {
                 aria-label="Clear range input value"
                 className={`${prefixCls}-range-input-clearbtn`}
                 onMouseDown={e => !disabled && this.handleRangeInputClear(e)}>
-                {clearIcon ? clearIcon :<IconClear aria-hidden />}
+                {clearIcon ? clearIcon : <IconClear aria-hidden />}
             </div>
         ) : null;
     }
@@ -313,10 +315,12 @@ export default class DateInput extends BaseComponent<DateInputProps, {}> {
             rangeInputStartRef,
             rangeInputEndRef,
             density,
+            insetInput,
         } = this.props;
 
         const _isRangeType = type.includes('Range');
         const newInsetInputValue = this.foundation.getInsetInputValue({ value, insetInputValue });
+        const { dateStart, dateEnd, timeStart, timeEnd } = get(insetInput, 'placeholder', {}) as InsetInputProps['placeholder'];
         const { datePlaceholder, timePlaceholder } = this.foundation.getInsetInputPlaceholder();
 
         const insetInputWrapperCls = `${prefixCls}-inset-input-wrapper`;
@@ -327,7 +331,7 @@ export default class DateInput extends BaseComponent<DateInputProps, {}> {
                 <InsetDateInput
                     forwardRef={rangeInputStartRef}
                     insetInputValue={newInsetInputValue}
-                    placeholder={datePlaceholder}
+                    placeholder={dateStart ?? datePlaceholder}
                     valuePath={'monthLeft.dateInput'}
                     onChange={this.handleInsetInputChange}
                     onFocus={e => handleInsetDateFocus(e, 'rangeStart')}
@@ -335,7 +339,7 @@ export default class DateInput extends BaseComponent<DateInputProps, {}> {
                 <InsetTimeInput
                     disabled={!newInsetInputValue.monthLeft.dateInput}
                     insetInputValue={newInsetInputValue}
-                    placeholder={timePlaceholder}
+                    placeholder={timeStart ?? timePlaceholder}
                     type={type}
                     valuePath={'monthLeft.timeInput'}
                     onChange={this.handleInsetInputChange}
@@ -347,7 +351,7 @@ export default class DateInput extends BaseComponent<DateInputProps, {}> {
                         <InsetDateInput
                             forwardRef={rangeInputEndRef}
                             insetInputValue={newInsetInputValue}
-                            placeholder={datePlaceholder}
+                            placeholder={dateEnd ?? datePlaceholder}
                             valuePath={'monthRight.dateInput'}
                             onChange={this.handleInsetInputChange}
                             onFocus={e => handleInsetDateFocus(e, 'rangeEnd')}
@@ -355,7 +359,7 @@ export default class DateInput extends BaseComponent<DateInputProps, {}> {
                         <InsetTimeInput
                             disabled={!newInsetInputValue.monthRight.dateInput}
                             insetInputValue={newInsetInputValue}
-                            placeholder={timePlaceholder}
+                            placeholder={timeEnd ?? timePlaceholder}
                             type={type}
                             valuePath={'monthRight.timeInput'}
                             onChange={this.handleInsetInputChange}

+ 3 - 3
packages/semi-ui/datePicker/datePicker.tsx

@@ -489,7 +489,7 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
         const { insetInput, dateFnsLocale, density, type, format, rangeSeparator, defaultPickerValue } = this.props;
         const { insetInputValue, value } = this.state;
 
-        const insetInputProps = {
+        const props = {
             dateFnsLocale,
             format,
             insetInputValue,
@@ -505,7 +505,7 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
             defaultPickerValue
         };
 
-        return insetInput ? <DateInput {...insetInputProps} insetInput={true} /> : null;
+        return insetInput ? <DateInput {...props} insetInput={insetInput} /> : null;
     }
 
     handleOpenPanel = () => this.foundation.openPanel();
@@ -603,7 +603,7 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
             format,
             multiple,
             validateStatus,
-            inputReadOnly: inputReadOnly || insetInput,
+            inputReadOnly: inputReadOnly || Boolean(insetInput),
             // onClick: this.handleOpenPanel,
             onBlur: this.handleInputBlur,
             onFocus: this.handleInputFocus,

+ 1 - 0
packages/semi-ui/datePicker/index.tsx

@@ -27,6 +27,7 @@ export type { MonthProps } from './month';
 export type { MonthsGridProps } from './monthsGrid';
 export type { QuickControlProps } from './quickControl';
 export type { YearAndMonthProps } from './yearAndMonth';
+export type { InsetInputProps } from '@douyinfe/semi-foundation/datePicker/inputFoundation';
 
 export default forwardStatics(
     React.forwardRef<DatePicker, DatePickerProps>((props, ref) => {

+ 6 - 5
packages/semi-ui/datePicker/quickControl.tsx

@@ -7,6 +7,7 @@ import Button from '../button/index';
 import Typography from '../typography/index';
 import { noop } from '@douyinfe/semi-foundation/utils/function';
 import { PresetsType, PresetType } from '@douyinfe/semi-foundation/datePicker/foundation';
+import { DateInputFoundationProps } from '@douyinfe/semi-foundation/datePicker/inputFoundation';
 
 const prefixCls = cssClasses.PREFIX;
 const { Text } = Typography;
@@ -16,7 +17,7 @@ export interface QuickControlProps {
     presetPosition: typeof strings.PRESET_POSITION_SET[number];
     onPresetClick: (preset: PresetType, e: React.MouseEvent) => void;
     type: string;
-    insetInput: boolean
+    insetInput: DateInputFoundationProps['insetInput']
 }
 
 class QuickControl extends PureComponent<QuickControlProps> {
@@ -25,7 +26,7 @@ class QuickControl extends PureComponent<QuickControlProps> {
         presetPosition: PropTypes.oneOf(strings.PRESET_POSITION_SET),
         onPresetClick: PropTypes.func,
         type: PropTypes.string,
-        insetInput: PropTypes.bool
+        insetInput: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
     };
 
     static defaultProps = {
@@ -74,15 +75,15 @@ class QuickControl extends PureComponent<QuickControlProps> {
         }
         return (
             <div className={wrapperCls} x-insetinput={insetInput ? "true" : "false"}>
-                { !isPanelTopAndBottom && <div className={headerCls}>快捷选择</div>}
+                {!isPanelTopAndBottom && <div className={headerCls}>快捷选择</div>}
                 <div className={contentWrapperCls}>
                     <div className={contentCls}>
                         {presets.map((item, index) => {
                             const _item: PresetType = typeof item === 'function' ? item() : item;
                             return (
-                                <Button size="small" type="primary" onClick={e => onPresetClick(_item, e)} key={index}>         
+                                <Button size="small" type="primary" onClick={e => onPresetClick(_item, e)} key={index}>
                                     <div className={itemCls}>
-                                        <Text 
+                                        <Text
                                             ellipsis={{ showTooltip: true }}
                                             className={ellipsisCls}
                                         >