ソースを参照

feat: disabledDate add rangeInputFocus to second params (#1198)

* feat: disabledDate add rangeInputFocus to second params

* docs: update DatePicker disabledDate API

Co-authored-by: shijia.me <[email protected]>
走鹃 3 年 前
コミット
f727302cb7

+ 44 - 10
content/input/datepicker/index-en-US.md

@@ -608,6 +608,40 @@ class App extends React.Component {
 }
 ```
 
+When `type` contains `range`, dates can be disabled based on the focus state. The focus state is passed through the `rangeInputFocus` parameter in `options`.
+
+```jsx live=true
+import React from 'react';
+import { DatePicker } from '@douyinfe/semi-ui';
+import * as dateFns from 'date-fns';
+
+function App() {
+    const today = new Date();
+    const disabledDate = (date, options) => {
+        const { rangeInputFocus } = options;
+        const baseDate = dateFns.set(today, { hours: 0, minutes: 0, seconds: 0, milliseconds: 0 });
+        if (rangeInputFocus === 'rangeStart') {
+            const disabledStart = dateFns.subDays(baseDate, 2);
+            const disabledEnd = dateFns.addDays(baseDate, 2);
+            return disabledStart <= date && date <= disabledEnd;
+        } else if (rangeInputFocus === 'rangeEnd') {
+            const disabledStart = dateFns.subDays(baseDate, 3);
+            const disabledEnd = dateFns.addDays(baseDate, 3);
+            return disabledStart <= date && date <= disabledEnd;
+        } else {
+            return false;
+        }
+    };
+
+    return (
+        <div>
+            <h4>{`Start date disables 2 days before and 2 days after today, end date disables 3 days before and 3 days after today`}</h4>
+            <DatePicker motion={false} type='dateRange' disabledDate={disabledDate} defaultPickerValue={today} />
+        </div>
+    );
+}
+```
+
 ### Custom Display Format
 
 Pass parameter `format` to custom display format.
@@ -831,19 +865,19 @@ function Demo() {
 
 ## API Reference
 
-| Properties         | Instructions                                                                                                                                                                              | Type                                             | Default | Version    |
-|--------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------|---------|------------|
-| autoAdjustOverflow | Whether the floating layer automatically adjusts its direction when it is blocked                                                                                                         | boolean                                          | true    | **0.34.0** |
-| autoFocus          | Automatic access to focus                                                                                                                                                                 | boolean                                          | false   | **1.10.0** |
-| 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                                           | -       |            |
-| defaultOpen        | Panel displays or hides by default                                                                                                                                                        | boolean                                          | false   |            |
-| defaultPickerValue | Default panel date                                                                                                                                                                        | ValueType |         |            |
+| Properties         | Instructions                                                                                                                                                                           | Type      | Default | Version    |
+|--------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------|---------|------------|
+| autoAdjustOverflow | Whether the floating layer automatically adjusts its direction when it is blocked                                                                                                      | boolean   | true    | **0.34.0** |
+| autoFocus          | Automatic access to focus                                                                                                                                                              | boolean   | false   | **1.10.0** |
+| 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    | -       |            |
+| defaultOpen        | Panel displays or hides by default                                                                                                                                                     | boolean   | false   |            |
+| defaultPickerValue | Default panel date                                                                                                                                                                     | ValueType |         |            |
 | defaultValue       | Default value                                                                                                                                                                            | ValueType                                                                                                                                                                                                    |                                             |                           |  |
 | density            | Density of picker panel, one of `default`, `compact`                                                                 | string                                                                                                                                                                                                    | default                                        | **1.17.0**              |
 | disabled           | Is it disabled?                                                                                                                                                                           | boolean                                                                                                                                                                                                   | false                                                                                 |                           |
-| disabledDate       | The date is prohibited from the judgment method, and the date is prohibited when returned to true. Options parameter supported after 1.9.0 and rangeEnd supported after 1.29            | <ApiType detail='(date: Date, options: { rangeStart: string, rangeEnd: string }) => boolean'>(date, options) => boolean</ApiType>     | () = > false                                                                          |                           |
+| disabledDate       | The date is prohibited from the judgment method, and the date is prohibited when returned to true. Options parameter supported after 1.9.0, rangeEnd supported after 1.29 and rangeInputFocus is supported since 2.22            | <ApiType detail='(date: Date, options: { rangeStart: string, rangeEnd: string, rangeInputFocus: "rangeStart" \| "rangeEnd" \| false }) => boolean'>(date, options) => boolean</ApiType>     | () = > false                                                                          |                           |
 | disabledTime       | Time prohibition configuration, the return value will be transparently passed to [`TimePicker`](/en-US/input/timepicker#API_Reference) as a parameter    | <ApiType detail='(date: Date \| Date[], panelType?: string) => ({ disabledHours:() => number[], disabledMinutes: (hour: number) => number[], disabledSeconds: (hour: number, minute: number) => number[] })'>(date, panelType) => object</ApiType> | () => false        | **0.36.0**                |
 | disabledTimePicker | Disable time selection or not.                                                                                                                                                            | boolean                                                                                                                                                                                                   |                                                                                       | **0.32.0**                |
 | dropdownClassName  | CSS classname for drop-down menu                                                                                                                                                          | string                                                               |                                 | **1.13.0** |

+ 47 - 13
content/input/datepicker/index.md

@@ -578,6 +578,40 @@ import * as dateFns from 'date-fns';
 );
 ```
 
+范围选择时,可以根据 focus 状态禁用日期。focus 状态通过 options 中的 rangeInputFocus 参数传递。
+
+```jsx live=true
+import React from 'react';
+import { DatePicker } from '@douyinfe/semi-ui';
+import * as dateFns from 'date-fns';
+
+function App() {
+    const today = new Date();
+    const disabledDate = (date, options) => {
+        const { rangeInputFocus } = options;
+        const baseDate = dateFns.set(today, { hours: 0, minutes: 0, seconds: 0, milliseconds: 0 });
+        if (rangeInputFocus === 'rangeStart') {
+            const disabledStart = dateFns.subDays(baseDate, 2);
+            const disabledEnd = dateFns.addDays(baseDate, 2);
+            return disabledStart <= date && date <= disabledEnd;
+        } else if (rangeInputFocus === 'rangeEnd') {
+            const disabledStart = dateFns.subDays(baseDate, 3);
+            const disabledEnd = dateFns.addDays(baseDate, 3);
+            return disabledStart <= date && date <= disabledEnd;
+        } else {
+            return false;
+        }
+    };
+
+    return (
+        <div>
+            <h4>{`开始日期禁用今天前2日和后2日,结束日期禁用今天前3天和后3天`}</h4>
+            <DatePicker motion={false} type='dateRange' disabledDate={disabledDate} defaultPickerValue={today} />
+        </div>
+    );
+}
+```
+
 ### 自定义显示格式
 
 可以通过 `format` 自定义显示格式
@@ -794,19 +828,19 @@ function Demo() {
 
 ## API 参考
 
-| 属性 | 说明 | 类型 | 默认值 | 版本 |
-| --- | --- | --- | --- | --- |
-| autoAdjustOverflow | 浮层被遮挡时是否自动调整方向 | boolean | true | **0.34.0** |
-| autoFocus | 自动获取焦点 | boolean | false | **1.10.0** |
-| autoSwitchDate | 通过面板上方左右按钮、下拉菜单更改年月时,自动切换日期。仅对 date type 生效。 | boolean | true | **1.13.0** |
-| bottomSlot | 渲染底部额外区域 | ReactNode |  | **1.22.0** |
-| className | 类名 | string | - |  |
-| defaultOpen | 面板默认显示或隐藏 | boolean | false |  |
-| defaultPickerValue | 默认面板日期 | ValueType |  |  |
-| defaultValue | 默认值 | ValueType |  |  |
-| density | 面板的尺寸,可选值:`default`, `compact` | string | default | **1.17.0** |
-| disabled | 是否禁用 | boolean | false |  |
-| disabledDate | 日期禁止判断方法,返回为 true 时禁止该日期,options 参数 1.9.0 后支持,rangeEnd 1.29 后支持 | <ApiType detail='(date: Date, options: { rangeStart: string, rangeEnd: string }) => boolean'>(date, options) => boolean</ApiType> | () => false   |
+| 属性               | 说明                                                                      | 类型      | 默认值  | 版本       |
+|--------------------|-------------------------------------------------------------------------|-----------|---------|------------|
+| autoAdjustOverflow | 浮层被遮挡时是否自动调整方向                                              | boolean   | true    | **0.34.0** |
+| autoFocus          | 自动获取焦点                                                              | boolean   | false   | **1.10.0** |
+| autoSwitchDate     | 通过面板上方左右按钮、下拉菜单更改年月时,自动切换日期。仅对 date type 生效。 | boolean   | true    | **1.13.0** |
+| bottomSlot         | 渲染底部额外区域                                                          | ReactNode |         | **1.22.0** |
+| className          | 类名                                                                      | string    | -       |            |
+| defaultOpen        | 面板默认显示或隐藏                                                        | boolean   | false   |            |
+| defaultPickerValue | 默认面板日期                                                              | ValueType |         |            |
+| defaultValue       | 默认值                                                                    | ValueType |         |            |
+| density            | 面板的尺寸,可选值:`default`, `compact`                                    | string    | default | **1.17.0** |
+| disabled           | 是否禁用                                                                  | boolean   | false   |            |
+| disabledDate | 日期禁止判断方法,返回为 true 时禁止该日期,options 参数 1.9.0 后支持,其中 rangeEnd 1.29 后支持,rangeInputFocus 2.22 后支持 | <ApiType detail='(date: Date, options: { rangeStart: string, rangeEnd: string, rangeInputFocus: "rangeStart" \| "rangeEnd" \| false }) => boolean'>(date, options) => boolean</ApiType> | () => false   |
 | disabledTime | 时间禁止配置,返回值将会作为参数透传给 [`TimePicker`](/zh-CN/input/timepicker#API_参考) | <ApiType detail='(date: Date \| Date[], panelType?: string) => ({ disabledHours:() => number[], disabledMinutes: (hour: number) => number[], disabledSeconds: (hour: number, minute: number) => number[] })'>(date, panelType) => object</ApiType> | () => false | **0.36.0** |
 | disabledTimePicker | 是否禁止时间选择 | boolean |  | **0.32.0** |
 | dropdownClassName | 下拉列表的 CSS 类名 | string |  | **1.13.0** |

+ 12 - 0
cypress/integration/datePicker.spec.js

@@ -572,4 +572,16 @@ describe('DatePicker', () => {
         cy.get('.semi-popover .semi-datepicker-day-selected-start').contains('8');
         cy.get('.semi-popover .semi-datepicker-day-selected-end').contains('9');
     });
+
+    it('disabledDate by focus state', () => {
+        cy.visit('http://localhost:6006/iframe.html?id=datepicker--disabled-range&args=&viewMode=story');
+        cy.get('.semi-input').eq(0).click();
+        cy.get('.semi-datepicker-month-grid-left .semi-datepicker-day.semi-datepicker-day-disabled').should('have.length', 5);
+        cy.get('.semi-datepicker-month-grid-left .semi-datepicker-day.semi-datepicker-day-disabled').eq(0).contains('18');
+        cy.get('.semi-datepicker-month-grid-left .semi-datepicker-day.semi-datepicker-day-disabled').eq(4).contains('22');
+        cy.get('.semi-input').eq(1).click();
+        cy.get('.semi-datepicker-month-grid-left .semi-datepicker-day.semi-datepicker-day-disabled').should('have.length', 7);
+        cy.get('.semi-datepicker-month-grid-left .semi-datepicker-day.semi-datepicker-day-disabled').eq(0).contains('17');
+        cy.get('.semi-datepicker-month-grid-left .semi-datepicker-day.semi-datepicker-day-disabled').eq(6).contains('23');
+    });
 });

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

@@ -41,6 +41,10 @@ export type DayStatusType = {
 export type DisabledDateOptions = {
     rangeStart?: string;
     rangeEnd?: string;
+    /**
+     * current select of range type
+     */
+    rangeInputFocus?: 'rangeStart' | 'rangeEnd' | false;
 };
 export type PresetType = {
     start?: string | Date | number;
@@ -1187,7 +1191,8 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
      */
     _someDateDisabled(value: Date[]) {
         const stateValue = this.getState('value');
-        const disabledOptions = { rangeStart: '', rangeEnd: '' };
+        const { rangeInputFocus } = this.getStates();
+        const disabledOptions = { rangeStart: '', rangeEnd: '', rangeInputFocus };
 
         // DisabledDate needs to pass the second parameter
         if (this._isRangeType() && Array.isArray(stateValue)) {

+ 36 - 0
packages/semi-ui/datePicker/_story/v2/DisabledRange.tsx

@@ -0,0 +1,36 @@
+import React from 'react';
+import { DatePicker } from '../../../index';
+import { DisabledDateType } from '../../index';
+import * as dateFns from 'date-fns';
+
+App.storyName = '根据 focus 状态禁用日期';
+/**
+ * test with cy
+ */
+function App() {
+    const today = new Date('2021-10-20');
+    const disabledDate: DisabledDateType = (date, options) => {
+        const { rangeInputFocus } = options;
+        const baseDate = dateFns.set(today, { hours: 0, minutes: 0, seconds: 0, milliseconds: 0 });
+        if (rangeInputFocus === 'rangeStart') {
+            const disabledStart = dateFns.subDays(baseDate, 2);
+            const disabledEnd = dateFns.addDays(baseDate, 2);
+            return disabledStart <= date && date <= disabledEnd;
+        } else if (rangeInputFocus === 'rangeEnd') {
+            const disabledStart = dateFns.subDays(baseDate, 3);
+            const disabledEnd = dateFns.addDays(baseDate, 3);
+            return disabledStart <= date && date <= disabledEnd;
+        } else {
+            return false;
+        }
+    };
+
+    return (
+        <div>
+            <h4>{`开始禁用 ${dateFns.format(today, 'yyyy-MM-dd')} 的前 2 日和后 2 日,结束日期禁用当前日期的前 3 天和后 3 天`}</h4>
+            <DatePicker motion={false} type='dateRange' disabledDate={disabledDate} defaultPickerValue={today} />
+        </div>
+    );
+}
+
+export default App;

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

@@ -9,3 +9,4 @@ export { default as InputFormatDisabled } from './InputFormatDisabled';
 export { default as AutoFillTime } from './AutoFillTime';
 export { default as InputFormatConfirm } from './InputFormatConfirm';
 export { default as FixedTriggerRender } from './FixTriggerRender';
+export { default as DisabledRange } from './DisabledRange';

+ 2 - 1
packages/semi-ui/datePicker/month.tsx

@@ -100,8 +100,9 @@ export default class Month extends BaseComponent<MonthProps, MonthState> {
     }
 
     getSingleDayStatus(options: Partial<MonthProps> & { fullDate: string; todayText: string }) {
+        const { rangeInputFocus } = this.props;
         const { fullDate, todayText, selected, disabledDate, rangeStart, rangeEnd } = options;
-        const disabledOptions = { rangeStart, rangeEnd };
+        const disabledOptions = { rangeStart, rangeEnd, rangeInputFocus };
         const isToday = fullDate === todayText;
         const isSelected = selected.has(fullDate);