diff --git a/packages/components/date-picker/__tests__/datePicker.spec.ts b/packages/components/date-picker/__tests__/datePicker.spec.ts index e501cab93..fa0d32a95 100644 --- a/packages/components/date-picker/__tests__/datePicker.spec.ts +++ b/packages/components/date-picker/__tests__/datePicker.spec.ts @@ -145,43 +145,31 @@ describe('DatePicker', () => { expect(onUpdateValue).toBeCalledWith(newDate) }) - test('defaultOpenValue work', async () => { - const wrapper = DatePickerMount({ - props: { - value: undefined, - defaultOpenValue: new Date('2021-10-11'), - }, - }) - - const headerContentBtns = wrapper.findComponent(DatePanel).find('.ix-date-panel-header-content').findAll('button') - expect(headerContentBtns.some(btn => btn.text().indexOf('2021') > -1)).toBeTruthy() - expect(headerContentBtns.some(btn => btn.text().indexOf('10') > -1)).toBeTruthy() - }) - test('datetime panel switch work', async () => { const wrapper = DatePickerMount({ props: { type: 'datetime', value: new Date('2021-10-11'), + allowInput: true, }, }) expect(wrapper.findComponent(DatePanel).isVisible()).toBeTruthy() expect(wrapper.findComponent(TimePanel).isVisible()).toBeFalsy() - await wrapper.findComponent(Content).find('.ix-date-picker-board-time-input').trigger('focus') + await wrapper.findComponent(Content).find('.ix-date-picker-overlay-inputs-time-input').trigger('focus') expect(wrapper.findComponent(DatePanel).isVisible()).toBeFalsy() expect(wrapper.findComponent(TimePanel).isVisible()).toBeTruthy() - await wrapper.findComponent(Content).find('.ix-date-picker-board-date-input').trigger('focus') + await wrapper.findComponent(Content).find('.ix-date-picker-overlay-inputs-date-input').trigger('focus') expect(wrapper.findComponent(DatePanel).isVisible()).toBeTruthy() expect(wrapper.findComponent(TimePanel).isVisible()).toBeFalsy() - await wrapper.findComponent(Content).find('.ix-date-picker-board-time-input').trigger('input') + await wrapper.findComponent(Content).find('.ix-date-picker-overlay-inputs-time-input').trigger('input') expect(wrapper.findComponent(DatePanel).isVisible()).toBeFalsy() expect(wrapper.findComponent(TimePanel).isVisible()).toBeTruthy() - await wrapper.findComponent(Content).find('.ix-date-picker-board-date-input').trigger('input') + await wrapper.findComponent(Content).find('.ix-date-picker-overlay-inputs-date-input').trigger('input') expect(wrapper.findComponent(DatePanel).isVisible()).toBeTruthy() expect(wrapper.findComponent(TimePanel).isVisible()).toBeFalsy() }) @@ -198,7 +186,7 @@ describe('DatePicker', () => { }, }) - await wrapper.findComponent(Content).find('.ix-date-picker-board-time-input').trigger('focus') + await wrapper.findComponent(Content).find('.ix-date-picker-overlay-inputs-time-input').trigger('focus') const timePanel = wrapper.findComponent(TimePanel) as VueWrapper<ɵTimePanelInstance> @@ -234,14 +222,22 @@ describe('DatePicker', () => { }, }) - await wrapper.findComponent(Content).find('.ix-date-picker-board-date-input').find('input').setValue('2021-11-22') + await wrapper + .findComponent(Content) + .find('.ix-date-picker-overlay-inputs-date-input') + .find('input') + .setValue('2021-11-22') expect(onUpdateValue).toBeCalledWith(new Date('2021-11-22 00:00:00')) expect(onChange).toBeCalledWith(new Date('2021-11-22 00:00:00'), new Date('2021-10-11 00:00:00')) onUpdateValue.mockClear() onChange.mockClear() - await wrapper.findComponent(Content).find('.ix-date-picker-board-time-input').find('input').setValue('13:03:04') + await wrapper + .findComponent(Content) + .find('.ix-date-picker-overlay-inputs-time-input') + .find('input') + .setValue('13:03:04') expect(onUpdateValue).toBeCalledWith(new Date('2021-10-11 13:03:04')) expect(onChange).toBeCalledWith(new Date('2021-10-11 13:03:04'), new Date('2021-10-11 00:00:00')) @@ -265,11 +261,11 @@ describe('DatePicker', () => { }) expect(wrapper.find('.ix-date-picker').find('input').element.value).toBe('2021-10-11 13/03/04') - expect(wrapper.findComponent(Content).find('.ix-date-picker-board-date-input').find('input').element.value).toBe( - '2021年10月11日', - ) - expect(wrapper.findComponent(Content).find('.ix-date-picker-board-time-input').find('input').element.value).toBe( - '13时03分04秒', - ) + expect( + wrapper.findComponent(Content).find('.ix-date-picker-overlay-inputs-date-input').find('input').element.value, + ).toBe('2021年10月11日') + expect( + wrapper.findComponent(Content).find('.ix-date-picker-overlay-inputs-time-input').find('input').element.value, + ).toBe('13时03分04秒') }) }) diff --git a/packages/components/date-picker/__tests__/dateRangePicker.spec.ts b/packages/components/date-picker/__tests__/dateRangePicker.spec.ts index 4fee92e59..56a519a26 100644 --- a/packages/components/date-picker/__tests__/dateRangePicker.spec.ts +++ b/packages/components/date-picker/__tests__/dateRangePicker.spec.ts @@ -181,23 +181,6 @@ describe('DateRangePicker', () => { expect(onUpdateValue).toBeCalledWith([newFromDate, newToDate]) }) - test('defaultOpenValue work', async () => { - const wrapper = DateRangePickerMount({ - props: { - value: undefined, - defaultOpenValue: [new Date('2021-10-11 00:00:00'), new Date('2021-11-11 00:00:00')], - }, - }) - - const [fromDatePanel, toDatePanel] = wrapper.findAllComponents(DatePanel) - const fromHeaderContentBtns = fromDatePanel.find('.ix-date-panel-header-content').findAll('button') - const toHeaderContentBtns = toDatePanel.find('.ix-date-panel-header-content').findAll('button') - expect(fromHeaderContentBtns.some(btn => btn.text().indexOf('2021') > -1)).toBeTruthy() - expect(fromHeaderContentBtns.some(btn => btn.text().indexOf('10') > -1)).toBeTruthy() - expect(toHeaderContentBtns.some(btn => btn.text().indexOf('2021') > -1)).toBeTruthy() - expect(toHeaderContentBtns.some(btn => btn.text().indexOf('11') > -1)).toBeTruthy() - }) - test('datetime time select work', async () => { const onChange = vi.fn() const onUpdateValue = vi.fn() @@ -210,7 +193,10 @@ describe('DateRangePicker', () => { }, }) - await wrapper.findComponent(RangeContent).findAll('.ix-date-range-picker-board-time-input')[0].trigger('focus') + await wrapper + .findComponent(RangeContent) + .findAll('.ix-date-range-picker-overlay-inputs-time-input')[0] + .trigger('focus') const fromTimePanel = wrapper.findAllComponents(TimePanel)[0] as unknown as VueWrapper<ɵTimePanelInstance> const toTimePanel = wrapper.findAllComponents(TimePanel)[1] as unknown as VueWrapper<ɵTimePanelInstance> @@ -247,11 +233,11 @@ describe('DateRangePicker', () => { const dateInputs = wrapper .findComponent(RangeContent) - .findAll('.ix-date-range-picker-board-date-input') + .findAll('.ix-date-range-picker-overlay-inputs-date-input') .map(el => el.find('input')) const timeInputs = wrapper .findComponent(RangeContent) - .findAll('.ix-date-range-picker-board-time-input') + .findAll('.ix-date-range-picker-overlay-inputs-time-input') .map(el => el.find('input')) await dateInputs[0].setValue('2021-11-22') diff --git a/packages/components/date-picker/docs/Index.zh.md b/packages/components/date-picker/docs/Index.zh.md index bacd49297..171a8baac 100644 --- a/packages/components/date-picker/docs/Index.zh.md +++ b/packages/components/date-picker/docs/Index.zh.md @@ -25,6 +25,8 @@ order: 0 | `disabled` | 是否禁用状态 | `boolean` | `false` | - | 使用 `control` 时,此配置无效 | | `disabledDate` | 不可选择的日期 | `(date: Date) => boolean` | - | - | - | | `format` | 展示的格式 | `string` | - | ✅ | 默认值参见 `defaultFormat`, 更多用法参考[date-fns](https://date-fns.org/v2.27.0/docs/format) | +| `timeFormat` | `'datetime'`下的时间格式 | `string` | - | ✅ | 全局配置同`TimePicker`的format, 仅在`'datetime'`类型下生效,可用于配置时间面板的列显示,参考[TimePicker](/components/time-picker/zh) | +| `dateFormat` | `'datetime'`下的日期格式 | `string` | - | ✅ | 全局配置同`DatePicker`的`'date'`类型format, 仅在`'datetime'`类型下生效 | | `overlayClassName` | 日期面板的 `class` | `string` | - | - | - | | `overlayContainer` | 自定义浮层容器节点 | `string \| HTMLElement \| () => string \| HTMLElement` | - | ✅ | - | | `overlayRender` | 自定义日期面板内容的渲染 | `(children:VNode[]) => VNodeChild` | - | - | - | @@ -68,14 +70,13 @@ const defaultFormat = { | 名称 | 说明 | 类型 | 默认值 | 全局配置 | 备注 | | --- | --- | --- | --- | --- | --- | | `v-model:value` | 当前选中的日期 | `number \| string \| Date` | - | - | 如果传入 `string` 类型,会根据 `format` 解析成 `Date`,使用 `control` 时,此配置无效 | -| `defaultOpenValue` | 打开面板时默认选中的值 | `number \| string \| Date` | - | - | `value` 为空时,高亮的值 | | `footer` | 自定义底部按钮 | `boolean \| ButtonProps[] \| VNode \| #footer` | `false` | - | 默认会根据 `type` 的不同渲染相应的按钮,如果传入 `false` 则不显示 | | `placeholder` | 选择框默认文本 | `string \| #placeholder` | - | - | 可以通过国际化配置默认值 | -| `timePanelOptions` | 时间选择面板配置 | `TimePanelOptions` | `false` | - | 仅在 `type='datetime'` 时生效 | +| `timePanelOptions` | 时间选择面板配置 | `PickerTimePanelOptions` | - | - | 仅在 `type='datetime'` 时生效 | | `onChange` | 值改变后的回调 | `(value: Date, oldValue: Date) => void` | - | - | - | | `onInput` | 输入后的回调 | `(evt: Event) => void` | - | - | - | -#### TimePanelOptions +#### PickerTimePanelOptions | 名称 | 说明 | 类型 | 默认值 | 全局配置 | 备注 | | --- | --- | --- | --- | --- | --- | @@ -94,14 +95,57 @@ const defaultFormat = { | 名称 | 说明 | 类型 | 默认值 | 全局配置 | 备注 | | --- | --- | --- | --- | --- | --- | | `v-model:value` | 当前选中的日期 | `Array` | - | - | 如果传入 `string` 类型,会根据 `format` 解析成 `Date`,使用 `control` 时,此配置无效 | -| `defaultOpenValue` | 打开面板时默认选中的值 | `Array` | - | - | `value` 为空时,高亮的值 | | `footer` | 自定义底部按钮 | `boolean \| ButtonProps[] \| VNode \| #footer` | `false` | - | 默认会根据 `type` 的不同渲染相应的按钮,如果传入 `false` 则不显示 | | `placeholder` | 选择框默认文本 | `string[] \| #placeholder=placement:'start'\|'end'` | - | - | 默认使用 `i18n` 配置 | | `separator` | 自定义分隔符图标 | `string \| VNode \| #separator` | - | ✅ | - | -| `timePanelOptions` | 时间选择面板配置 | `TimePanelOptions \| TimePanelOptions[]` | `false` | - | 如果需要对前后的时间选择器配置不同的禁用条件,可以传入一个数组 | +| `timePanelOptions` | 时间选择面板配置 | `PickerTimePanelOptions \| PickerTimePanelOptions[]` | - | - | 如果需要对前后的时间选择器使用不同配置,可以传入一个数组 | | `onChange` | 值改变后的回调 | `(value: Date[], oldValue: Date[]) => void` | - | - | - | | `onInput` | 输入后的回调 | `(isFrom: boolean, evt: Event) => void` | - | - | - | +### IxDatePickerPanel + +#### DatePickerPanelProps + +| 名称 | 说明 | 类型 | 默认值 | 全局配置 | 备注 | +| --- | --- | --- | --- | --- | --- | +| `v-model:activeValue` | 当前激活状态的日期 | `Date` | - | - | 配合键盘操作使用 | +| `cellTooltip` | 日期节点的tooltip | `(cell: { value: Date, disabled: boolean }) => string | void` | - | - | - | +| `disabledDate` | 不可选择的日期 | `(date: Date) => boolean` | - | - | - | +| `type` | 设置选择器面板类型 | `'date' \| 'week' \| 'month' \| 'quarter' \| 'year' \| 'datetime'` | `'date'` | - | - | +| `timePanelOptions` | 时间选择面板配置 | `TimePanelOptions` | - | - | - | +| `visible` | 当前可见的面板 | `'datePanel' \| 'timePanel' \| visible` | - | - | 在非 `datetime` 类型时,`timepanel` 无效 | +| `onChange` | 值改变后的回调 | `(value: Date | undefined) => void` | - | - | - | + +### IxDateRangePickerPanel + +#### DateRangePickerPanelProps + +| 名称 | 说明 | 类型 | 默认值 | 全局配置 | 备注 | +| --- | --- | --- | --- | --- | --- | +| `v-model:activeValue` | 当前激活状态的日期 | `Date[]` | - | - | 配合键盘操作使用 | +| `cellTooltip` | 日期节点的tooltip | `(cell: { value: Date, disabled: boolean }) => string | void` | - | - | - | +| `disabledDate` | 不可选择的日期 | `(date: Date) => boolean` | - | - | - | +| `type` | 设置选择器面板类型 | `'date' \| 'week' \| 'month' \| 'quarter' \| 'year' \| 'datetime'` | `'date'` | - | - | +| `timePanelOptions` | 时间选择面板配置 | `TimePanelOptions \| TimePanelOptions[]` | - | - | 如果需要对前后的时间选择器使用不同配置,可以传入一个数组 | +| `visible` | 当前可见的面板 | `'datePanel' \| 'timePanel' \| boolean` | - | - | 在非 `datetime` 类型时,`timepanel` 无效 | +| `onChange` | 值改变后的回调 | `(value: Date[] | undefined) => void` | - | - | - | + +#### TimePanelOptions + +| 名称 | 说明 | 类型 | 默认值 | 全局配置 | 备注 | +| --- | --- | --- | --- | --- | --- | +| `disabledHours` | 禁用部分小时选项 | `(selectedAmPm: string | undefined) => number[]` | ``() => []`` | - | - | +| `disabledMinutes` | 禁用部分分钟选项 | `(selectedHour: number | undefined, selectedAmPm: string | undefined) => number[]` | `() => []` | - | - | +| `disabledSeconds` | 禁用部分秒选项 | `(selectedHour: number | undefined, selectedMinute: number | undefined, selectedAmPm: string | undefined)=>number[]` | `() => []` | - | - | +| `hideDisabledOptions` | 隐藏禁止选择的options |`boolean` |`false` | - | - | +| `hourStep` | 小时选项的间隔 | `number` | `1` | - | - | +| `minuteStep` | 分钟选项的间隔 | `number` | `1` | - | - | +| `secondStep` | 秒选项的间隔 | `number` | `1` | - | - | +| `hourEnabled` | 是否显示小时选择列 | `boolean` | `true` | - | - | +| `minuteEnabled` | 是否显示分钟选择列 | `boolean` | `true` | - | - | +| `secondEnabled` | 是否显示秒选择列 | `boolean` | `true` | - | - | +| `use12Hours` | 是否显示AM\PM选择列 | `boolean` | `false` | - | - | + ## 主题变量 @@ -110,49 +154,49 @@ const defaultFormat = { | `@date-picker-line-height` | `@form-line-height` | - | - | | `@date-picker-color` | `@form-color` | - | - | | `@date-range-picker-trigger-separator-margin` | `@spacing-xl` | - | - | -| `@date-picker-panel-font-size` | `@font-size-md` | - | - | -| `@date-picker-panel-color` | `@text-color` | - | - | -| `@date-picker-panel-color-inverse` | `@text-color-inverse` | - | - | -| `@date-picker-panel-active-color` | `@color-primary` | - | - | -| `@date-picker-panel-in-range-color` | `@color-blue-l50` | - | - | -| `@date-picker-panel-disabled-color` | `@text-color-disabled` | - | - | -| `@date-picker-panel-disabled-background-color` | `@color-graphite-l50` | - | - | -| `@date-picker-panel-background-color` | `@background-color-component` | - | - | -| `@date-picker-panel-border-width` | `@border-width-sm` | - | - | -| `@date-picker-panel-border-style` | `@border-style` | - | - | -| `@date-picker-panel-border-color` | `@border-color` | - | - | -| `@date-picker-panel-header-padding` | `0 0 @spacing-xs 0` | - | - | -| `@date-picker-panel-header-height` | `@height-md` | - | - | -| `@date-picker-panel-header-item-padding` | `0 @spacing-xs` | - | - | -| `@date-picker-panel-header-border-bottom` | `none` | - | - | -| `@date-picker-panel-header-button-font-size` | `@font-size-lg` | - | - | -| `@date-picker-panel-header-button-font-weight` | `@font-weight-lg` | - | - | -| `@date-picker-panel-header-content-spacing` | `@spacing-lg` | - | - | -| `@date-picker-panel-header-padding-lg` | `0 0 @spacing-2xl` | - | - | -| `@date-picker-panel-body-padding` | `0` | - | - | -| `@date-picker-panel-body-padding-lg` | `0` | - | - | -| `@date-picker-panel-body-font-size` | `@font-size-md` | - | - | -| `@date-picker-panel-body-header-margin-bottom` | `@spacing-md` | - | - | -| `@date-picker-panel-body-header-font-weight` | `@font-weight-md` | - | - | -| `@date-picker-panel-body-header-background-color` | `@color-graphite-l50` | - | - | -| `@date-picker-panel-cell-width` | `28px` | - | - | -| `@date-picker-panel-cell-height` | `28px` | - | - | -| `@date-picker-panel-cell-width-lg` | `52px` | - | - | -| `@date-picker-panel-cell-height-lg` | `24px` | - | - | -| `@date-picker-panel-cell-padding` | `2px 0` | - | - | -| `@date-picker-panel-cell-inner-padding` | `4px` | - | - | -| `@date-picker-panel-cell-padding-lg` | `@spacing-lg 0` | - | - | -| `@date-picker-panel-cell-inner-padding-lg` | `0` | - | - | -| `@date-picker-panel-cell-trigger-width` | `20px` | - | - | -| `@date-picker-panel-cell-trigger-height` | `20px` | - | - | -| `@date-picker-panel-cell-trigger-width-lg` | `52px` | - | - | -| `@date-picker-panel-cell-trigger-height-lg` | `24px` | - | - | -| `@date-picker-panel-cell-border-radius` | `@border-radius-full` | - | - | -| `@date-picker-panel-cell-border-radius-lg` | `@border-radius-sm` | - | - | -| `@date-picker-panel-cell-hover-background-color` | `@color-graphite-l50` | - | - | -| `@date-picker-panel-cell-hover-color` | `@color-primary` | - | - | -| `@date-picker-panel-cell-current-border-color` | `@color-blue-l40` | - | - | -| `@date-picker-panel-cell-current-color` | `@color-primary` | - | - | +| `@date-panel-font-size` | `@font-size-md` | - | - | +| `@date-panel-color` | `@text-color` | - | - | +| `@date-panel-color-inverse` | `@text-color-inverse` | - | - | +| `@date-panel-active-color` | `@color-primary` | - | - | +| `@date-panel-in-range-color` | `@color-blue-l50` | - | - | +| `@date-panel-disabled-color` | `@text-color-disabled` | - | - | +| `@date-panel-disabled-background-color` | `@color-graphite-l50` | - | - | +| `@date-panel-background-color` | `@background-color-component` | - | - | +| `@date-panel-border-width` | `@border-width-sm` | - | - | +| `@date-panel-border-style` | `@border-style` | - | - | +| `@date-panel-border-color` | `@border-color` | - | - | +| `@date-panel-header-padding` | `0 0 @spacing-xs 0` | - | - | +| `@date-panel-header-height` | `@height-md` | - | - | +| `@date-panel-header-item-padding` | `0 @spacing-xs` | - | - | +| `@date-panel-header-border-bottom` | `none` | - | - | +| `@date-panel-header-button-font-size` | `@font-size-lg` | - | - | +| `@date-panel-header-button-font-weight` | `@font-weight-lg` | - | - | +| `@date-panel-header-content-spacing` | `@spacing-lg` | - | - | +| `@date-panel-header-padding-lg` | `0 0 @spacing-2xl` | - | - | +| `@date-panel-body-padding` | `0` | - | - | +| `@date-panel-body-padding-lg` | `0` | - | - | +| `@date-panel-body-font-size` | `@font-size-md` | - | - | +| `@date-panel-body-header-margin-bottom` | `@spacing-md` | - | - | +| `@date-panel-body-header-font-weight` | `@font-weight-md` | - | - | +| `@date-panel-body-header-background-color` | `@color-graphite-l50` | - | - | +| `@date-panel-cell-width` | `28px` | - | - | +| `@date-panel-cell-height` | `28px` | - | - | +| `@date-panel-cell-width-lg` | `52px` | - | - | +| `@date-panel-cell-height-lg` | `24px` | - | - | +| `@date-panel-cell-padding` | `2px 0` | - | - | +| `@date-panel-cell-inner-padding` | `4px` | - | - | +| `@date-panel-cell-padding-lg` | `@spacing-lg 0` | - | - | +| `@date-panel-cell-inner-padding-lg` | `0` | - | - | +| `@date-panel-cell-trigger-width` | `20px` | - | - | +| `@date-panel-cell-trigger-height` | `20px` | - | - | +| `@date-panel-cell-trigger-width-lg` | `52px` | - | - | +| `@date-panel-cell-trigger-height-lg` | `24px` | - | - | +| `@date-panel-cell-border-radius` | `@border-radius-full` | - | - | +| `@date-panel-cell-border-radius-lg` | `@border-radius-sm` | - | - | +| `@date-panel-cell-hover-background-color` | `@color-graphite-l50` | - | - | +| `@date-panel-cell-hover-color` | `@color-primary` | - | - | +| `@date-panel-cell-current-border-color` | `@color-blue-l40` | - | - | +| `@date-panel-cell-current-color` | `@color-primary` | - | - | | `@date-picker-overlay-footer-border-width` | `@form-border-width` | - | - | | `@date-picker-overlay-footer-border-style` | `@form-border-style` | - | - | | `@date-picker-overlay-footer-border-color` | `@form-border-color` | - | - | @@ -178,10 +222,15 @@ const defaultFormat = { | `@date-range-picker-overlay-footer-border-color` | `@color-graphite-l30` | - | - | | `@date-range-picker-overlay-footer-padding` | `@spacing-sm 0` | - | - | | `@date-range-picker-overlay-footer-button-margin-left` | `@date-picker-overlay-footer-button-margin-left` | - | - | +| `@date-picker-panel-width` | `220px` | - | - | +| `@date-picker-panel-max-height` | `260px` | - | - | | `@date-range-picker-panel-width` | `220px` | - | - | | `@date-range-picker-panel-max-height` | `260px` | - | - | | `@date-range-picker-panel-border-width` | `0` | - | - | | `@date-range-picker-panel-border-style` | `none` | - | - | | `@date-range-picker-panel-border-color` | `none` | - | - | | `@date-range-picker-panel-border-radius` | `0` | - | - | +| `@date-range-picker-panel-separator-margin` | `0 @spacing-lg` | - | - | +| `@date-range-picker-panel-separator-width` | `1px` | - | - | +| `@date-range-picker-panel-separator-color` | `@date-panel-border-color` | - | - | \ No newline at end of file diff --git a/packages/components/date-picker/index.ts b/packages/components/date-picker/index.ts index 10bcf05f7..d17d8270a 100644 --- a/packages/components/date-picker/index.ts +++ b/packages/components/date-picker/index.ts @@ -5,21 +5,36 @@ * found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE */ -import type { DatePickerComponent, DateRangePickerComponent } from './src/types' +import type { + DatePanelComponent, + DatePickerComponent, + DateRangePanelComponent, + DateRangePickerComponent, +} from './src/types' import DatePicker from './src/DatePicker' import DateRangePicker from './src/DateRangePicker' +import DatePanel from './src/panel/Panel' +import DateRangePanel from './src/panel/RangePanel' const IxDatePicker = DatePicker as unknown as DatePickerComponent +const IxDatePanel = DatePanel as unknown as DatePanelComponent const IxDateRangePicker = DateRangePicker as unknown as DateRangePickerComponent +const IxDateRangePanel = DateRangePanel as unknown as DateRangePanelComponent -export { IxDatePicker, IxDateRangePicker } +export { IxDatePicker, IxDatePanel, IxDateRangePicker, IxDateRangePanel } export type { DatePickerInstance, DatePickerComponent, DatePickerPublicProps as DatePickerProps, + DatePanelInstance, + DatePanelComponent, + DatePanelPublicProps as DatePanelProps, DateRangePickerInstance, DateRangePickerComponent, DateRangePickerPublicProps as DateRangePickerProps, + DateRangePanelInstance, + DateRangePanelComponent, + DateRangePanelPublicProps as DateRangePanelProps, } from './src/types' diff --git a/packages/components/date-picker/src/DatePicker.tsx b/packages/components/date-picker/src/DatePicker.tsx index 25f360b94..e3a204763 100644 --- a/packages/components/date-picker/src/DatePicker.tsx +++ b/packages/components/date-picker/src/DatePicker.tsx @@ -45,7 +45,7 @@ export default defineComponent({ const { accessor, handleChange } = pickerStateContext const controlContext = useControl(dateConfig, formatContext, inputEnableStatus, accessor.valueRef, handleChange) - const { overlayOpened, setOverlayOpened } = useOverlayState(props, controlContext) + const { overlayOpened, overlayVisible, onAfterLeave, setOverlayOpened } = useOverlayState(props, controlContext) const handleKeyDown = useKeyboardEvents(setOverlayOpened) const context = { @@ -58,6 +58,8 @@ export default defineComponent({ inputRef, inputEnableStatus, overlayOpened, + overlayVisible, + onAfterLeave, setOverlayOpened, handleKeyDown, controlContext, diff --git a/packages/components/date-picker/src/DateRangePicker.tsx b/packages/components/date-picker/src/DateRangePicker.tsx index 90eb38bcd..f9da19e12 100644 --- a/packages/components/date-picker/src/DateRangePicker.tsx +++ b/packages/components/date-picker/src/DateRangePicker.tsx @@ -45,7 +45,10 @@ export default defineComponent({ const { accessor, handleChange } = pickerStateContext const rangeControlContext = useRangeControl(dateConfig, formatContext, inputEnableStatus, accessor.valueRef) - const { overlayOpened, setOverlayOpened } = useOverlayState(props, rangeControlContext) + const { overlayOpened, overlayVisible, onAfterLeave, setOverlayOpened } = useOverlayState( + props, + rangeControlContext, + ) const handleKeyDown = useRangeKeyboardEvents(rangeControlContext, setOverlayOpened, handleChange) const renderSeparator = () => slots.separator?.() ?? props.separator ?? locale.dateRangePicker.separator @@ -60,6 +63,8 @@ export default defineComponent({ inputRef, inputEnableStatus, overlayOpened, + overlayVisible, + onAfterLeave, setOverlayOpened, rangeControlContext, renderSeparator, diff --git a/packages/components/date-picker/src/composables/useActiveDate.ts b/packages/components/date-picker/src/composables/useActiveDate.ts deleted file mode 100644 index bbc5d2483..000000000 --- a/packages/components/date-picker/src/composables/useActiveDate.ts +++ /dev/null @@ -1,177 +0,0 @@ -/** - * @license - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE - */ - -import type { DatePickerProps, DatePickerType, DateRangePickerProps } from '../types' -import type { DateConfig } from '@idux/components/config' - -import { type ComputedRef, computed, watch } from 'vue' - -import { convertArray, useState } from '@idux/cdk/utils' - -import { convertToDate, sortRangeValue } from '../utils' - -export interface ActiveDateContext { - activeDate: ComputedRef - setActiveDate: (value: Date) => void -} - -export interface RangeActiveDateContext { - fromActiveDate: ComputedRef - toActiveDate: ComputedRef - setFromActiveDate: (value: Date) => void - setToActiveDate: (value: Date) => void -} - -export function useActiveDate( - dateConfig: DateConfig, - props: DatePickerProps, - valueRef: ComputedRef, - formatRef: ComputedRef, -): ActiveDateContext { - const defaultOpenValue = computed( - () => convertToDate(dateConfig, props.defaultOpenValue ?? dateConfig.now(), formatRef.value)!, - ) - const [activeDate, setActiveDate] = useState(valueRef.value ?? defaultOpenValue.value) - - watch(valueRef, value => setActiveDate(value ?? defaultOpenValue.value)) - - return { - activeDate, - setActiveDate, - } -} - -const viewTypeMap: Record = { - date: 'month', - datetime: 'month', - week: 'month', - month: 'year', - quarter: 'year', - year: 'year', -} - -export function useRangeActiveDate( - dateConfig: DateConfig, - props: DateRangePickerProps, - valuesRef: ComputedRef<(Date | undefined)[] | undefined>, - isSelecting: ComputedRef, - overlayOpened: ComputedRef, - formatRef: ComputedRef, -): RangeActiveDateContext { - const { set, get } = dateConfig - const now = dateConfig.now() - - const fromPanelValue = computed(() => valuesRef.value?.[0]) - const toPanelValue = computed(() => valuesRef.value?.[1]) - - const defaultOpenValue = computed(() => { - const convertedValues = sortRangeValue(dateConfig, [ - ...convertArray(props.defaultOpenValue).map(v => convertToDate(dateConfig, v, formatRef.value)), - ]) - - return [convertedValues[0] ?? now, convertedValues[1]] - }) - - const calcValidActiveDate = (from: Date | undefined, to: Date | undefined, type: 'from' | 'to') => { - const viewType = viewTypeMap[props.type] - const viewSpan = props.type === 'year' ? 12 : 1 - const getViewDate = (value: Date) => - set(value, get(value, viewType) + (type === 'from' ? -viewSpan : viewSpan), viewType) - - if (!from) { - return type === 'from' ? now : getViewDate(now) - } - - if (!to) { - return type === 'from' ? from : getViewDate(from) - } - - const fromViewValue = get(from, viewType) - const toViewValue = get(to, viewType) - - /* eslint-disable indent */ - const valid = - props.type === 'year' - ? fromViewValue < toViewValue - viewSpan - : (() => { - const fromViewYearValue = get(from, 'year') - const toViewYearValue = get(to, 'year') - - return fromViewValue < toViewValue && fromViewYearValue <= toViewYearValue - })() - /* eslint-disable indent */ - - if (type === 'from') { - return valid ? from : getViewDate(to) - } - - return valid ? to : getViewDate(from) - } - - const initActiveDate = () => { - if (isSelecting.value) { - return - } - - const fromValue = valuesRef.value?.[0] ?? defaultOpenValue.value[0]! - const toValue = valuesRef.value?.[1] ?? defaultOpenValue.value[1] - - const valueAlreadyInView = [fromValue, toValue].every(value => { - if (!value) { - return true - } - - const yearValue = get(value, 'year') - if (viewTypeMap[props.type] === 'year') { - return [fromActiveDate, toActiveDate].map(activeDate => get(activeDate.value, 'year')).includes(yearValue) - } - - const monthValue = get(value, 'month') - return [fromActiveDate, toActiveDate].some( - activeDate => yearValue === get(activeDate.value, 'year') && monthValue === get(activeDate.value, 'month'), - ) - }) - if (valueAlreadyInView) { - return - } - - setFromActiveDate(fromValue) - setToActiveDate(calcValidActiveDate(fromValue, toValue, 'to')) - } - - const [fromActiveDate, setFromActiveDate] = useState(fromPanelValue.value ?? defaultOpenValue.value[0]!) - const [toActiveDate, setToActiveDate] = useState( - calcValidActiveDate( - fromPanelValue.value ?? defaultOpenValue.value[0], - toPanelValue.value ?? defaultOpenValue.value[1], - 'to', - ), - ) - - watch(valuesRef, initActiveDate) - watch(overlayOpened, opened => { - if (!opened) { - initActiveDate() - } - }) - - const handleFromActiveDateUpdate = (value: Date) => { - setFromActiveDate(value) - setToActiveDate(calcValidActiveDate(value, toActiveDate.value, 'to')) - } - const handleToActiveDateUpdate = (value: Date) => { - setToActiveDate(value) - setFromActiveDate(calcValidActiveDate(fromActiveDate.value, value, 'from')) - } - - return { - fromActiveDate, - toActiveDate, - setFromActiveDate: handleFromActiveDateUpdate, - setToActiveDate: handleToActiveDateUpdate, - } -} diff --git a/packages/components/date-picker/src/composables/useActiveValue.ts b/packages/components/date-picker/src/composables/useActiveValue.ts new file mode 100644 index 000000000..a4444aa2a --- /dev/null +++ b/packages/components/date-picker/src/composables/useActiveValue.ts @@ -0,0 +1,151 @@ +/** + * @license + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE + */ + +import type { DatePanelProps, DatePickerType, DateRangePanelProps } from '../types' +import type { DateConfig } from '@idux/components/config' + +import { type ComputedRef, computed, watch } from 'vue' + +import { useControlledProp } from '@idux/cdk/utils' + +export interface ActiveValueContext { + activeValue: ComputedRef + setActiveValue: (value: Date) => void +} + +export interface RangeActiveValueContext { + fromActiveValue: ComputedRef + toActiveValue: ComputedRef + setFromActiveValue: (value: Date) => void + setToActiveValue: (value: Date) => void +} + +export function useActiveValue(dateConfig: DateConfig, props: DatePanelProps): ActiveValueContext { + const [activeValue, setActiveValue] = useControlledProp(props, 'activeValue', props.value ?? dateConfig.now()) + + watch( + () => props.value, + value => setActiveValue(value ?? dateConfig.now()), + ) + + return { + activeValue, + setActiveValue, + } +} + +const viewTypeMap: Record = { + date: 'month', + datetime: 'month', + week: 'month', + month: 'year', + quarter: 'year', + year: 'year', +} + +export function useRangeActiveValue( + dateConfig: DateConfig, + props: DateRangePanelProps, + panelValue: ComputedRef<(Date | undefined)[] | undefined>, + isSelecting: ComputedRef, +): RangeActiveValueContext { + const { set, get } = dateConfig + const now = dateConfig.now() + + const fromPanelValue = computed(() => panelValue.value?.[0]) + const toPanelValue = computed(() => panelValue.value?.[1]) + + const calcValidActiveDate = (from: Date | undefined, to: Date | undefined, type: 'from' | 'to') => { + const viewType = viewTypeMap[props.type] + const viewSpan = props.type === 'year' ? 12 : 1 + const getViewDate = (value: Date) => + set(value, get(value, viewType) + (type === 'from' ? -viewSpan : viewSpan), viewType) + + if (!from) { + return type === 'from' ? now : getViewDate(now) + } + + if (!to) { + return type === 'from' ? from : getViewDate(from) + } + + const fromViewValue = get(from, viewType) + const toViewValue = get(to, viewType) + + /* eslint-disable indent */ + const valid = + props.type === 'year' + ? fromViewValue < toViewValue - viewSpan + : (() => { + const fromViewYearValue = get(from, 'year') + const toViewYearValue = get(to, 'year') + + return fromViewValue < toViewValue && fromViewYearValue <= toViewYearValue + })() + /* eslint-disable indent */ + + if (type === 'from') { + return valid ? from : getViewDate(to) + } + + return valid ? to : getViewDate(from) + } + + const initActiveDate = () => { + if (isSelecting.value) { + return + } + + const fromValue = panelValue.value?.[0] ?? now + const toValue = panelValue.value?.[1] + + const valueAlreadyInView = [fromValue, toValue].every(value => { + if (!value) { + return true + } + + const yearValue = get(value, 'year') + if (viewTypeMap[props.type] === 'year') { + return [fromActiveValue, toActiveValue].map(activeDate => get(activeDate.value, 'year')).includes(yearValue) + } + + const monthValue = get(value, 'month') + return [fromActiveValue, toActiveValue].some( + activeDate => yearValue === get(activeDate.value, 'year') && monthValue === get(activeDate.value, 'month'), + ) + }) + if (valueAlreadyInView) { + return + } + + setActiveValue([fromValue, calcValidActiveDate(fromValue, toValue, 'to')]) + } + + const [activeValue, setActiveValue] = useControlledProp(props, 'activeValue', [ + fromPanelValue.value ?? now, + calcValidActiveDate(fromPanelValue.value ?? now, toPanelValue.value, 'to'), + ]) + const fromActiveValue = computed(() => activeValue.value[0]) + const toActiveValue = computed(() => activeValue.value[1]) + + watch(panelValue, initActiveDate) + watch(() => props.visible, initActiveDate) + + const handleFromActiveValueUpdate = (value: Date) => { + setActiveValue([value, calcValidActiveDate(value, toActiveValue.value, 'to')]) + } + const handleToActiveValueUpdate = (value: Date) => { + setActiveValue([calcValidActiveDate(fromActiveValue.value, value, 'from'), value]) + } + + return { + fromActiveValue, + toActiveValue, + setFromActiveValue: handleFromActiveValueUpdate, + setToActiveValue: handleToActiveValueUpdate, + } +} diff --git a/packages/components/date-picker/src/composables/useControl.ts b/packages/components/date-picker/src/composables/useControl.ts index 2361d260c..b78708a70 100644 --- a/packages/components/date-picker/src/composables/useControl.ts +++ b/packages/components/date-picker/src/composables/useControl.ts @@ -18,7 +18,7 @@ import { applyDateTime, convertToDate, isSameDateTime } from '../utils' export interface PickerControlContext { inputValue: ComputedRef dateInputValue: ComputedRef - timeInputVaue: ComputedRef + timeInputValue: ComputedRef panelValue: ComputedRef dateInputFocused: ComputedRef timeInputFocused: ComputedRef @@ -32,8 +32,7 @@ export interface PickerControlContext { handleTimeInput: (evt: Event) => void handleDateInputClear: () => void handleTimeInputClear: () => void - handleDatePanelChange: (value: Date) => void - handleTimePanelChange: (value: Date) => void + handlePanelChange: (value: Date | undefined) => void handleDateInputFocus: () => void handleTimeInputFocus: () => void handleDateInputBlur: () => void @@ -51,7 +50,7 @@ export function useControl( const [inputValue, setInputValue] = useState('') const [dateInputValue, setDateInputValue] = useState('') - const [timeInputVaue, setTimeInputValue] = useState('') + const [timeInputValue, setTimeInputValue] = useState('') const [panelValue, setPanelValue] = useState(undefined) const [visiblePanel, setVisiblePanel] = useState<'datePanel' | 'timePanel'>('datePanel') const [dateInputFocused, setDateInputFocused] = useState(false) @@ -89,7 +88,7 @@ export function useControl( } const { parse, format } = dateConfig - const parsedValue = parse(timeInputVaue.value, timeFormatRef.value) + const parsedValue = parse(timeInputValue.value, timeFormatRef.value) if (force || !isSameDateTime(dateConfig, parsedValue, currValue, ['hour', 'minute', 'second'])) { setTimeInputValue(format(currValue, timeFormatRef.value)) @@ -167,15 +166,8 @@ export function useControl( setTimeInputValue('') } - function handleDatePanelChange(value: Date) { - handleChange( - panelValue.value ? applyDateTime(dateConfig, panelValue.value, value, ['hour', 'minute', 'second']) : value, - ) - } - function handleTimePanelChange(value: Date) { - handleChange( - panelValue.value ? applyDateTime(dateConfig, panelValue.value, value, ['year', 'month', 'date']) : value, - ) + function handlePanelChange(value: Date | undefined) { + handleChange(value) } function handleDateInputFocus() { @@ -196,7 +188,7 @@ export function useControl( return { inputValue, dateInputValue, - timeInputVaue, + timeInputValue, dateInputFocused, timeInputFocused, panelValue, @@ -210,8 +202,7 @@ export function useControl( handleTimeInput, handleDateInputClear, handleTimeInputClear, - handleDatePanelChange, - handleTimePanelChange, + handlePanelChange, handleDateInputFocus, handleTimeInputFocus, handleDateInputBlur, diff --git a/packages/components/date-picker/src/composables/useKeyboardEvents.ts b/packages/components/date-picker/src/composables/useKeyboardEvents.ts index 8d453766b..07d16ac31 100644 --- a/packages/components/date-picker/src/composables/useKeyboardEvents.ts +++ b/packages/components/date-picker/src/composables/useKeyboardEvents.ts @@ -20,7 +20,7 @@ export function useRangeKeyboardEvents( setOverlayOpened: (opened: boolean) => void, handleChange: (value: (Date | undefined)[] | undefined) => void, ): (evt: KeyboardEvent) => void { - const { isSelecting, bufferUpdated, buffer } = rangeControl + const { bufferUpdated, buffer } = rangeControl return (evt: KeyboardEvent) => { switch (evt.code) { case 'Escape': @@ -28,7 +28,7 @@ export function useRangeKeyboardEvents( break case 'Enter': - if (!isSelecting.value && bufferUpdated.value) { + if (bufferUpdated.value) { handleChange(buffer.value) } setOverlayOpened(false) diff --git a/packages/components/date-picker/src/composables/useOverlayProps.ts b/packages/components/date-picker/src/composables/useOverlayProps.ts index 1a3d76d95..cdc541381 100644 --- a/packages/components/date-picker/src/composables/useOverlayProps.ts +++ b/packages/components/date-picker/src/composables/useOverlayProps.ts @@ -13,7 +13,7 @@ import { type ComputedRef, computed } from 'vue' const defaultOffset: [number, number] = [0, 8] export function useOverlayProps(context: DatePickerContext | DateRangePickerContext): ComputedRef<ɵOverlayProps> { return computed(() => { - const { props, config, accessor, mergedPrefixCls, overlayOpened, setOverlayOpened } = context + const { props, config, accessor, mergedPrefixCls, overlayOpened, setOverlayOpened, onAfterLeave } = context return { clickOutside: true, disabled: accessor.disabled.value || props.readonly, @@ -24,6 +24,7 @@ export function useOverlayProps(context: DatePickerContext | DateRangePickerCont trigger: 'manual', visible: overlayOpened.value, 'onUpdate:visible': setOverlayOpened, + onAfterLeave, } }) } diff --git a/packages/components/date-picker/src/composables/useOverlayState.ts b/packages/components/date-picker/src/composables/useOverlayState.ts index 5d3e65a78..5af8abcfb 100644 --- a/packages/components/date-picker/src/composables/useOverlayState.ts +++ b/packages/components/date-picker/src/composables/useOverlayState.ts @@ -10,13 +10,15 @@ import type { PickerControlContext } from './useControl' import type { PickerRangeControlContext } from './useRangeControl' import type { ComputedRef } from 'vue' -import { onMounted } from 'vue' +import { onMounted, watch } from 'vue' -import { useControlledProp } from '@idux/cdk/utils' +import { useControlledProp, useState } from '@idux/cdk/utils' export interface OverlayStateContext { overlayOpened: ComputedRef + overlayVisible: ComputedRef setOverlayOpened: (open: boolean) => void + onAfterLeave: () => void } export function useOverlayState( @@ -24,6 +26,16 @@ export function useOverlayState( control: PickerControlContext | PickerRangeControlContext, ): OverlayStateContext { const [overlayOpened, setOverlayOpened] = useControlledProp(props, 'open', false) + const [overlayVisible, setOverlayVisible] = useState(false) + watch( + overlayOpened, + open => { + if (open) { + setOverlayVisible(true) + } + }, + { immediate: true }, + ) const changeOpenedState = (open: boolean) => { setOverlayOpened(open) @@ -32,11 +44,17 @@ export function useOverlayState( } } + const onAfterLeave = () => { + if (!overlayOpened.value) { + setOverlayVisible(false) + } + } + onMounted(() => { if (props.autofocus) { - setOverlayOpened(true) + changeOpenedState(true) } }) - return { overlayOpened, setOverlayOpened: changeOpenedState } + return { overlayOpened, overlayVisible, setOverlayOpened: changeOpenedState, onAfterLeave } } diff --git a/packages/components/date-picker/src/composables/useRangeControl.ts b/packages/components/date-picker/src/composables/useRangeControl.ts index dc242746b..9a9c85622 100644 --- a/packages/components/date-picker/src/composables/useRangeControl.ts +++ b/packages/components/date-picker/src/composables/useRangeControl.ts @@ -18,8 +18,6 @@ import { type PickerControlContext, useControl } from './useControl' export interface PickerRangeControlContext { buffer: ComputedRef<(Date | undefined)[] | undefined> - panelValue: ComputedRef<(Date | undefined)[] | undefined> - isSelecting: ComputedRef bufferUpdated: ComputedRef visiblePanel: ComputedRef<'datePanel' | 'timePanel'> @@ -29,8 +27,7 @@ export interface PickerRangeControlContext { toControl: PickerControlContext init: (force?: boolean) => void - handleDatePanelCellClick: (value: Date) => void - handleDatePanelCellMouseenter: (value: Date) => void + handlePanelChange: (value: Date[] | undefined) => void } export function useRangeControl( @@ -49,8 +46,6 @@ export function useRangeControl( setBufferUpdated(true) } - const [selectingDate, setSelectingDate] = useState<(Date | undefined)[] | undefined>(buffer.value) - const [isSelecting, setIsSelecting] = useState(false) const [visiblePanel, setVisiblePanel] = useState<'datePanel' | 'timePanel'>('datePanel') const handleVisiblePanelUpdate = (value: 'datePanel' | 'timePanel') => { @@ -63,14 +58,6 @@ export function useRangeControl( const fromDateRef = computed(() => rangeValueRef.value[0]) const toDateRef = computed(() => rangeValueRef.value[1]) - const panelValue = computed(() => { - if (isSelecting.value) { - return sortRangeValue(dateConfig, [...convertArray(selectingDate.value)], 'date') - } - - return convertArray(buffer.value) - }) - watch(valueRef, handleBufferUpdate) const getValidBufferValue = (value: Date | undefined, isFrom: boolean) => { @@ -99,34 +86,13 @@ export function useRangeControl( const init = (force = false) => { handleBufferUpdate(valueRef.value) - handleVisiblePanelUpdate('datePanel') setBufferUpdated(false) fromControl.init(force) toControl.init(force) } - const handleDatePanelCellClick = (value: Date) => { - if (!isSelecting.value) { - setIsSelecting(true) - setSelectingDate([value, undefined]) - } else { - setIsSelecting(false) - handleBufferUpdate([selectingDate.value?.[0], value]) - } - } - - const handleDatePanelCellMouseenter = (value: Date) => { - if (!isSelecting.value) { - return - } - - setSelectingDate([selectingDate.value?.[0], value]) - } - return { buffer, - panelValue, - isSelecting, bufferUpdated, visiblePanel, @@ -136,8 +102,7 @@ export function useRangeControl( toControl, init, - handleDatePanelCellClick, - handleDatePanelCellMouseenter, + handlePanelChange: handleBufferUpdate, } } diff --git a/packages/components/date-picker/src/composables/useRangePanelState.ts b/packages/components/date-picker/src/composables/useRangePanelState.ts new file mode 100644 index 000000000..8da801fe5 --- /dev/null +++ b/packages/components/date-picker/src/composables/useRangePanelState.ts @@ -0,0 +1,72 @@ +/** + * @license + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE + */ + +import type { DateRangePanelProps } from '../types' +import type { DateConfig } from '@idux/components/config' + +import { type ComputedRef, computed, watch } from 'vue' + +import { callEmit, convertArray, useState } from '@idux/cdk/utils' + +import { sortRangeValue } from '../utils' + +export interface RangePanelStateContext { + panelValue: ComputedRef<(Date | undefined)[] | undefined> + isSelecting: ComputedRef + handleChange: (value: (Date | undefined)[]) => void + handleDatePanelCellClick: (value: Date) => void + handleDatePanelCellMouseenter: (value: Date) => void +} + +export function useRangePanelState(props: DateRangePanelProps, dateConfig: DateConfig): RangePanelStateContext { + const [selectingDate, setSelectingDate] = useState<(Date | undefined)[] | undefined>(props.value) + const [isSelecting, setIsSelecting] = useState(false) + watch( + () => props.visible, + () => { + setIsSelecting(false) + }, + ) + + const panelValue = computed(() => { + if (isSelecting.value) { + return sortRangeValue(dateConfig, [...convertArray(selectingDate.value)], 'date') + } + + return convertArray(props.value) + }) + + const handleChange = (value: (Date | undefined)[]) => { + callEmit(props.onChange, sortRangeValue(dateConfig, value, 'date') as Date[]) + } + + const handleDatePanelCellClick = (value: Date) => { + if (!isSelecting.value) { + setIsSelecting(true) + setSelectingDate([value, undefined]) + } else { + setIsSelecting(false) + handleChange([selectingDate.value?.[0], value]) + } + } + + const handleDatePanelCellMouseenter = (value: Date) => { + if (!isSelecting.value) { + return + } + + setSelectingDate([selectingDate.value?.[0], value]) + } + + return { + panelValue, + isSelecting, + handleChange, + handleDatePanelCellClick, + handleDatePanelCellMouseenter, + } +} diff --git a/packages/components/date-picker/src/content/Content.tsx b/packages/components/date-picker/src/content/Content.tsx index b16ed0bab..279012148 100644 --- a/packages/components/date-picker/src/content/Content.tsx +++ b/packages/components/date-picker/src/content/Content.tsx @@ -5,16 +5,14 @@ * found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE */ -import { defineComponent, inject, onMounted, onUpdated, ref } from 'vue' +import { defineComponent, inject, onMounted, ref } from 'vue' -import { ɵDatePanel } from '@idux/components/_private/date-panel' import { ɵFooter } from '@idux/components/_private/footer' import { ɵInput, type ɵInputInstance } from '@idux/components/_private/input' -import { ɵTimePanel } from '@idux/components/_private/time-panel' -import { useActiveDate } from '../composables/useActiveDate' import { useInputProps } from '../composables/useInputProps' import { useTimePanelProps } from '../composables/useTimePanelProps' +import Panel from '../panel/Panel' import { datePickerToken } from '../token' export default defineComponent({ @@ -22,18 +20,15 @@ export default defineComponent({ const context = inject(datePickerToken)! const { props, - dateConfig, mergedPrefixCls, - formatRef, dateFormatRef, timeFormatRef, slots, - overlayOpened, inputEnableStatus, inputRef, controlContext: { dateInputValue, - timeInputVaue, + timeInputValue, visiblePanel, panelValue, dateInputFocused, @@ -46,39 +41,44 @@ export default defineComponent({ handleTimeInputFocus, handleDateInputBlur, handleTimeInputBlur, - handleDatePanelChange, - handleTimePanelChange, + handlePanelChange, }, + overlayVisible, setOverlayOpened, handleKeyDown, handleClear, } = context - const { activeDate, setActiveDate } = useActiveDate(dateConfig, props, panelValue, formatRef) - const inputInstance = ref<ɵInputInstance>() - const setInputRef = () => { + onMounted(() => { + if (inputEnableStatus.value.allowInput !== 'overlay') { + return + } + + inputRef.value = inputInstance.value?.getInputElement() + }) + + const _handleDateInputFocus = (evt: FocusEvent) => { + handleDateInputFocus() + if (inputEnableStatus.value.allowInput === 'overlay') { + inputRef.value = evt.target as HTMLInputElement + } + } + const _handleTimeInputFocus = (evt: FocusEvent) => { + handleTimeInputFocus() if (inputEnableStatus.value.allowInput === 'overlay') { - inputRef.value = inputInstance.value?.getInputElement() + inputRef.value = evt.target as HTMLInputElement } } - onMounted(setInputRef) - onUpdated(setInputRef) - const handleDatePanelCellClick = (value: Date) => { - handleDatePanelChange(value) + const _handlePanelChange = (value: Date | undefined) => { + handlePanelChange(value) if (!inputEnableStatus.value.enableOverlayTimeInput) { setOverlayOpened(false) } } - const handleMouseDown = (e: MouseEvent) => { - if (!(e.target instanceof HTMLInputElement)) { - e.preventDefault() - } - } - const _handleDateInputClear = (evt: Event) => { if (!inputEnableStatus.value.enableOverlayTimeInput) { handleClear(evt) @@ -96,18 +96,19 @@ export default defineComponent({ } return ( -
+
<ɵInput ref={inputInstance} {...inputProps.value} class={`${prefixCls}-date-input`} v-slots={slots} value={dateInputValue.value} - clearVisible={!!dateInputValue.value} + clearVisible={!!dateInputValue.value && !!inputEnableStatus.value.allowInput} focused={dateInputFocused.value} placeholder={dateFormatRef.value} + readonly={!inputEnableStatus.value.allowInput} onInput={handleDateInput} - onFocus={handleDateInputFocus} + onFocus={_handleDateInputFocus} onBlur={handleDateInputBlur} onKeydown={handleKeyDown} onClear={_handleDateInputClear} @@ -117,12 +118,13 @@ export default defineComponent({ {...inputProps.value} class={`${prefixCls}-time-input`} v-slots={slots} - value={timeInputVaue.value} - clearVisible={!!timeInputVaue.value} - placeholder={timeFormatRef.value} + value={timeInputValue.value} + clearVisible={!!timeInputValue.value && !!inputEnableStatus.value.allowInput} focused={timeInputFocused.value} + placeholder={timeFormatRef.value} + readonly={!inputEnableStatus.value.allowInput} onInput={handleTimeInput} - onFocus={handleTimeInputFocus} + onFocus={_handleTimeInputFocus} onBlur={handleTimeInputBlur} onKeydown={handleKeyDown} onClear={handleTimeInputClear} @@ -134,42 +136,27 @@ export default defineComponent({ return () => { const prefixCls = `${mergedPrefixCls.value}-overlay` - const boardPrefixCls = `${mergedPrefixCls.value}-board` - const datePanelType = props.type === 'datetime' ? 'date' : props.type + const inputsCls = `${prefixCls}-inputs` - const datePanelProps = { + const paneProps = { cellTooltip: props.cellTooltip, disabledDate: props.disabledDate, - type: datePanelType, - value: panelValue.value, - visible: overlayOpened.value, - activeDate: activeDate.value, - onCellClick: handleDatePanelCellClick, - 'onUpdate:activeDate': setActiveDate, - } - const _timePanelProps = { - ...timePanelProps.value, - activeValue: activeDate.value, value: panelValue.value, - visible: visiblePanel.value === 'timePanel', - onChange: handleTimePanelChange, - 'onUpdate:activeValue': setActiveDate, + type: props.type, + timePanelOptions: timePanelProps.value, + visible: overlayVisible.value && visiblePanel.value, + onChange: _handlePanelChange, } const children = [ -
- {renderInputs(boardPrefixCls)} -
- <ɵDatePanel v-show={visiblePanel.value === 'datePanel'} v-slots={slots} {...datePanelProps} /> - {inputEnableStatus.value.enableOverlayTimeInput && ( - <ɵTimePanel v-show={visiblePanel.value === 'timePanel'} {..._timePanelProps} /> - )} -
+
+ {renderInputs(inputsCls)} +
, <ɵFooter v-slots={slots} class={`${prefixCls}-footer`} footer={props.footer} />, ] - return props.overlayRender ? props.overlayRender(children) :
{children}
+ return props.overlayRender ? props.overlayRender(children) :
{children}
} }, }) diff --git a/packages/components/date-picker/src/content/RangeContent.tsx b/packages/components/date-picker/src/content/RangeContent.tsx index 2448ef18d..6ea4b1b34 100644 --- a/packages/components/date-picker/src/content/RangeContent.tsx +++ b/packages/components/date-picker/src/content/RangeContent.tsx @@ -5,16 +5,14 @@ * found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE */ -import { defineComponent, inject, onMounted, onUpdated, ref } from 'vue' +import { defineComponent, inject, onMounted, ref } from 'vue' -import { ɵDatePanel } from '@idux/components/_private/date-panel' import { ɵFooter } from '@idux/components/_private/footer' import { ɵInput, type ɵInputInstance } from '@idux/components/_private/input' -import { ɵTimePanel } from '@idux/components/_private/time-panel' -import { useRangeActiveDate } from '../composables/useActiveDate' import { useInputProps } from '../composables/useInputProps' import { useRangeTimePanelProps } from '../composables/useTimePanelProps' +import RangePanel from '../panel/RangePanel' import { dateRangePickerToken } from '../token' export default defineComponent({ @@ -22,46 +20,27 @@ export default defineComponent({ const context = inject(dateRangePickerToken)! const { props, - dateConfig, locale, slots, - overlayOpened, - formatRef, dateFormatRef, timeFormatRef, - rangeControlContext: { - buffer, - panelValue, - visiblePanel, - isSelecting, - fromControl, - toControl, - handleDatePanelCellClick, - handleDatePanelCellMouseenter, - }, + rangeControlContext: { buffer, visiblePanel, fromControl, toControl, handlePanelChange }, mergedPrefixCls, inputEnableStatus, inputRef, handleChange, handleKeyDown, + overlayVisible, renderSeparator, setOverlayOpened, } = context - const { fromActiveDate, toActiveDate, setFromActiveDate, setToActiveDate } = useRangeActiveDate( - dateConfig, - props, - panelValue, - isSelecting, - overlayOpened, - formatRef, - ) - const inputInstance = ref<ɵInputInstance>() onMounted(() => { - inputRef.value = inputInstance.value?.getInputElement() - }) - onUpdated(() => { + if (inputEnableStatus.value.allowInput !== 'overlay') { + return + } + inputRef.value = inputInstance.value?.getInputElement() }) @@ -79,13 +58,12 @@ export default defineComponent({ const inputProps = useInputProps(context) const timePanelProps = useRangeTimePanelProps(props, timeFormatRef) - const renderBoard = (isFrom: boolean) => { - const { enableOverlayDateInput, enableOverlayTimeInput } = inputEnableStatus.value - const boardPrefixCls = `${mergedPrefixCls.value}-board` + const renderInputsSide = (prefixCls: string, isFrom: boolean) => { + const { enableOverlayTimeInput } = inputEnableStatus.value const { dateInputValue, - timeInputVaue, + timeInputValue, dateInputFocused, timeInputFocused, handleDateInput, @@ -96,22 +74,35 @@ export default defineComponent({ handleTimeInputFocus, handleDateInputBlur, handleTimeInputBlur, - handleTimePanelChange, } = isFrom ? fromControl : toControl - const inputs = enableOverlayDateInput && ( -
+ const _handleDateInputFocus = (evt: FocusEvent) => { + handleDateInputFocus() + if (inputEnableStatus.value.allowInput === 'overlay') { + inputRef.value = evt.target as HTMLInputElement + } + } + const _handleTimeInputFocus = (evt: FocusEvent) => { + handleTimeInputFocus() + if (inputEnableStatus.value.allowInput === 'overlay') { + inputRef.value = evt.target as HTMLInputElement + } + } + + return ( +
<ɵInput ref={isFrom ? inputInstance : undefined} {...inputProps.value} - class={`${boardPrefixCls}-date-input`} + class={`${prefixCls}-date-input`} v-slots={slots} value={dateInputValue.value} - clearVisible={!!dateInputValue.value} + clearVisible={!!dateInputValue.value && !!inputEnableStatus.value.allowInput} focused={dateInputFocused.value} placeholder={dateFormatRef.value} + readonly={!inputEnableStatus.value.allowInput} onInput={handleDateInput} - onFocus={handleDateInputFocus} + onFocus={_handleDateInputFocus} onBlur={handleDateInputBlur} onKeydown={handleKeyDown} onClear={handleDateInputClear} @@ -119,14 +110,15 @@ export default defineComponent({ {enableOverlayTimeInput && ( <ɵInput {...inputProps.value} - class={`${boardPrefixCls}-time-input`} + class={`${prefixCls}-time-input`} v-slots={slots} - value={timeInputVaue.value} - clearVisible={!!timeInputVaue.value} + value={timeInputValue.value} + clearVisible={!!timeInputValue.value && !!inputEnableStatus.value.allowInput} focused={timeInputFocused.value} placeholder={timeFormatRef.value} + readonly={!inputEnableStatus.value.allowInput} onInput={handleTimeInput} - onFocus={handleTimeInputFocus} + onFocus={_handleTimeInputFocus} onBlur={handleTimeInputBlur} onKeydown={handleKeyDown} onClear={handleTimeInputClear} @@ -134,52 +126,39 @@ export default defineComponent({ )}
) + } + + return () => { + const prefixCls = `${mergedPrefixCls.value}-overlay` + const inputsCls = `${prefixCls}-inputs` - const timeValue = panelValue.value?.[isFrom ? 0 : 1] - const activeDate = isFrom ? fromActiveDate.value : toActiveDate.value - const datePanelProps = { + const panelProps = { + value: buffer.value as Date[], cellTooltip: props.cellTooltip, disabledDate: props.disabledDate, - type: props.type === 'datetime' ? 'date' : props.type, - value: panelValue.value, - visible: overlayOpened.value, - activeDate, - onCellClick: handleDatePanelCellClick, - onCellMouseenter: handleDatePanelCellMouseenter, - 'onUpdate:activeDate': isFrom ? setFromActiveDate : setToActiveDate, - } - const _timePanelProps = { - ...timePanelProps.value[isFrom ? 0 : 1], - activeValue: timeValue ?? activeDate, - value: timeValue, - visible: visiblePanel.value === 'timePanel', - onChange: handleTimePanelChange, - 'onUpdate:activeValue': isFrom ? setFromActiveDate : setToActiveDate, + type: props.type, + timePanelOptions: timePanelProps.value, + visible: overlayVisible.value && visiblePanel.value, + onChange: handlePanelChange, } - return ( -
- {inputs} -
- <ɵDatePanel v-show={visiblePanel.value !== 'timePanel'} v-slots={slots} {...datePanelProps} /> - {inputEnableStatus.value.enableOverlayTimeInput && ( - <ɵTimePanel v-show={visiblePanel.value === 'timePanel'} {..._timePanelProps} /> - )} -
-
- ) - } - - return () => { - const prefixCls = `${mergedPrefixCls.value}-overlay` + const panelSlots = { + cell: slots.cell, + separator: inputEnableStatus.value.enableOverlayDateInput + ? () =>
+ : undefined, + } const children = [
- {renderBoard(true)} -
- {inputEnableStatus.value.enableOverlayDateInput && renderSeparator()} -
- {renderBoard(false)} + {inputEnableStatus.value.enableOverlayDateInput && ( +
+ {renderInputsSide(inputsCls, true)} +
{renderSeparator()}
+ {renderInputsSide(inputsCls, false)} +
+ )} +
, <ɵFooter v-slots={slots} diff --git a/packages/components/date-picker/src/panel/Panel.tsx b/packages/components/date-picker/src/panel/Panel.tsx new file mode 100644 index 000000000..6ceeec638 --- /dev/null +++ b/packages/components/date-picker/src/panel/Panel.tsx @@ -0,0 +1,79 @@ +/** + * @license + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE + */ + +import { computed, defineComponent } from 'vue' + +import { callEmit } from '@idux/cdk/utils' +import { ɵDatePanel } from '@idux/components/_private/date-panel' +import { ɵTimePanel } from '@idux/components/_private/time-panel' +import { useDateConfig, useGlobalConfig } from '@idux/components/config' + +import { useActiveValue } from '../composables/useActiveValue' +import { datePanelProps } from '../types' +import { applyDateTime } from '../utils' + +export default defineComponent({ + name: 'IxDatePanel', + props: datePanelProps, + setup(props, { slots }) { + const common = useGlobalConfig('common') + const mergedPrefixCls = computed(() => `${common.prefixCls}-date-picker-panel`) + const dateConfig = useDateConfig() + + const { activeValue, setActiveValue } = useActiveValue(dateConfig, props) + + function handleChange(value: Date | undefined) { + callEmit(props.onChange, value) + } + function handleDatePanelChange(value: Date) { + handleChange(props.value ? applyDateTime(dateConfig, props.value, value, ['hour', 'minute', 'second']) : value) + } + function handleTimePanelChange(value: Date) { + handleChange(props.value ? applyDateTime(dateConfig, props.value, value, ['year', 'month', 'date']) : value) + } + + const handleDatePanelCellClick = (value: Date) => { + handleDatePanelChange(value) + } + + const handleMouseDown = (e: MouseEvent) => { + if (!(e.target instanceof HTMLInputElement)) { + e.preventDefault() + } + } + + return () => { + const datePanelType = props.type === 'datetime' ? 'date' : props.type + + const datePanelProps = { + cellTooltip: props.cellTooltip, + disabledDate: props.disabledDate, + type: datePanelType, + value: props.value, + visible: props.type === 'datetime' ? props.visible === 'datePanel' : !!props.visible, + activeDate: activeValue.value, + onCellClick: handleDatePanelCellClick, + 'onUpdate:activeDate': setActiveValue, + } + const _timePanelProps = { + ...props.timePanelOptions, + activeValue: activeValue.value, + value: props.value, + visible: props.type === 'datetime' ? props.visible === 'timePanel' : false, + onChange: handleTimePanelChange, + 'onUpdate:activeValue': setActiveValue, + } + + return ( +
+ <ɵDatePanel v-show={props.visible !== 'timePanel'} v-slots={slots} {...datePanelProps} /> + {props.type === 'datetime' && <ɵTimePanel v-show={props.visible === 'timePanel'} {..._timePanelProps} />} +
+ ) + } + }, +}) diff --git a/packages/components/date-picker/src/panel/RangePanel.tsx b/packages/components/date-picker/src/panel/RangePanel.tsx new file mode 100644 index 000000000..6d9bb57be --- /dev/null +++ b/packages/components/date-picker/src/panel/RangePanel.tsx @@ -0,0 +1,91 @@ +/** + * @license + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE + */ + +import { computed, defineComponent } from 'vue' + +import { isArray } from 'lodash-es' + +import { ɵDatePanel } from '@idux/components/_private/date-panel' +import { ɵTimePanel } from '@idux/components/_private/time-panel' +import { useDateConfig, useGlobalConfig } from '@idux/components/config' + +import { useRangeActiveValue } from '../composables/useActiveValue' +import { useRangePanelState } from '../composables/useRangePanelState' +import { dateRangePanelProps } from '../types' + +export default defineComponent({ + name: 'IxDateRangePanel', + props: dateRangePanelProps, + setup(props, { slots }) { + const common = useGlobalConfig('common') + const mergedPrefixCls = computed(() => `${common.prefixCls}-date-range-picker-panel`) + const dateConfig = useDateConfig() + + const { handleChange, handleDatePanelCellClick, handleDatePanelCellMouseenter, panelValue, isSelecting } = + useRangePanelState(props, dateConfig) + const { fromActiveValue, toActiveValue, setFromActiveValue, setToActiveValue } = useRangeActiveValue( + dateConfig, + props, + panelValue, + isSelecting, + ) + + const handleMouseDown = (e: MouseEvent) => { + if (!(e.target instanceof HTMLInputElement)) { + e.preventDefault() + } + } + + const renderSide = (isFrom: boolean) => { + const timeValue = panelValue.value?.[isFrom ? 0 : 1] + const activeValue = isFrom ? fromActiveValue.value : toActiveValue.value + + const handleTimePanelChange = (value: Date) => { + handleChange(isFrom ? [value, panelValue.value?.[1]] : [panelValue.value?.[0], value]) + } + + const datePanelProps = { + cellTooltip: props.cellTooltip, + disabledDate: props.disabledDate, + type: props.type === 'datetime' ? 'date' : props.type, + value: panelValue.value, + visible: props.type === 'datetime' ? props.visible === 'datePanel' : !!props.visible, + activeDate: activeValue, + onCellClick: handleDatePanelCellClick, + onCellMouseenter: handleDatePanelCellMouseenter, + 'onUpdate:activeDate': isFrom ? setFromActiveValue : setToActiveValue, + } + const _timePanelProps = { + ...((isArray(props.timePanelOptions) ? props.timePanelOptions[isFrom ? 0 : 1] : props.timePanelOptions) ?? {}), + activeValue: timeValue ?? activeValue, + value: timeValue, + visible: props.type === 'datetime' ? props.visible === 'timePanel' : false, + onChange: handleTimePanelChange, + 'onUpdate:activeValue': isFrom ? setFromActiveValue : setToActiveValue, + } + + return ( +
+ <ɵDatePanel v-show={props.visible !== 'timePanel'} v-slots={slots} {...datePanelProps} /> + {props.type === 'datetime' && <ɵTimePanel v-show={props.visible === 'timePanel'} {..._timePanelProps} />} +
+ ) + } + + return () => { + const prefixCls = mergedPrefixCls.value + + return ( +
+ {renderSide(true)} + {slots.separator?.() ??
} + {renderSide(false)} +
+ ) + } + }, +}) diff --git a/packages/components/date-picker/src/types.ts b/packages/components/date-picker/src/types.ts index 1d978150f..3fb70fb03 100644 --- a/packages/components/date-picker/src/types.ts +++ b/packages/components/date-picker/src/types.ts @@ -13,7 +13,7 @@ import type { DefineComponent, HTMLAttributes, PropType, VNode, VNodeChild } fro import { controlPropDef } from '@idux/cdk/forms' import { ɵPortalTargetDef } from '@idux/cdk/portal' -export interface TimePanelOptions { +export interface PickerTimePanelOptions { disabledHours?: (selectedAmPm: string | undefined) => number[] disabledMinutes?: (selectedHour: number | undefined, selectedAmPm: string | undefined) => number[] disabledSeconds?: ( @@ -25,6 +25,9 @@ export interface TimePanelOptions { hourStep?: number minuteStep?: number secondStep?: number +} + +export interface TimePanelOptions extends PickerTimePanelOptions { hourEnabled?: boolean minuteEnabled?: boolean secondEnabled?: boolean @@ -95,10 +98,9 @@ export const datePickerProps = { ...datePickerCommonProps, value: [String, Date, Number], - defaultOpenValue: [String, Date, Number], footer: { type: [Boolean, Array, Object] as PropType, default: false }, placeholder: String, - timePanelOptions: Object as PropType, + timePanelOptions: Object as PropType, 'onUpdate:value': [Function, Array] as PropType void>>, onChange: [Function, Array] as PropType void>>, onInput: [Function, Array] as PropType void>>, @@ -116,11 +118,10 @@ export const dateRangePickerProps = { ...datePickerCommonProps, value: Array as PropType<(number | string | Date | undefined)[]>, - defaultOpenValue: Array as PropType<(number | string | Date)[]>, footer: { type: [Boolean, Array, Object] as PropType, default: true }, placeholder: Array as PropType, separator: [String, Object] as PropType, - timePanelOptions: [Object, Array] as PropType, + timePanelOptions: [Object, Array] as PropType, 'onUpdate:value': [Function, Array] as PropType void>>, onChange: [Function, Array] as PropType< MaybeArray<(value: Date[] | undefined, oldValue: Date[] | undefined) => void> @@ -137,3 +138,53 @@ export type DateRangePickerComponent = DefineComponent< export type DateRangePickerInstance = InstanceType> export type DatePickerType = 'date' | 'week' | 'month' | 'quarter' | 'year' | 'datetime' + +export const datePanelProps = { + activeValue: Date as PropType, + cellTooltip: Function as PropType<(cell: { value: Date; disabled: boolean }) => string | void>, + disabledDate: Function as PropType<(date: Date) => boolean>, + value: Date as PropType, + type: { + type: String as PropType, + default: 'date', + }, + timePanelOptions: { + type: Object as PropType, + default: () => ({}), + }, + visible: [String, Boolean] as PropType<'datePanel' | 'timePanel' | boolean>, + + onChange: [Function, Array] as PropType void>>, + 'onUpdate:activeValue': [Function, Array] as PropType void>>, +} as const +export type DatePanelProps = ExtractInnerPropTypes +export type DatePanelPublicProps = ExtractPublicPropTypes +export type DatePanelComponent = DefineComponent< + Omit & DatePanelPublicProps +> +export type DatePanelInstance = InstanceType> + +export const dateRangePanelProps = { + activeValue: Array as PropType, + cellTooltip: Function as PropType<(cell: { value: Date; disabled: boolean }) => string | void>, + disabledDate: Function as PropType<(date: Date) => boolean>, + value: Array as PropType, + type: { + type: String as PropType, + default: 'date', + }, + timePanelOptions: { + type: Array as PropType, + default: () => [], + }, + visible: [String, Boolean] as PropType<'datePanel' | 'timePanel' | boolean>, + + onChange: [Function, Array] as PropType void>>, + 'onUpdate:activeValue': [Function, Array] as PropType void>>, +} as const +export type DateRangePanelProps = ExtractInnerPropTypes +export type DateRangePanelPublicProps = ExtractPublicPropTypes +export type DateRangePanelComponent = DefineComponent< + Omit & DateRangePanelPublicProps +> +export type DateRangePanelInstance = InstanceType> diff --git a/packages/components/date-picker/style/index.less b/packages/components/date-picker/style/index.less index 0a981dc1d..02738f961 100644 --- a/packages/components/date-picker/style/index.less +++ b/packages/components/date-picker/style/index.less @@ -6,13 +6,11 @@ .@{date-picker-prefix} { .date-picker-trigger(); - .date-picker-board(); &-overlay { width: @date-picker-overlay-width; padding: @date-picker-overlay-padding; - - .date-picker-panel(); + .date-picker-inputs(); &-body { padding: @date-picker-overlay-body-padding; @@ -31,9 +29,18 @@ } } +.@{date-picker-prefix}-panel { + width: @date-picker-panel-width; + max-height: @date-picker-panel-max-height; + .@{time-panel-prefix} { + height: @date-picker-panel-max-height; + } + + .date-picker-panel(); +} + .@{date-range-picker-prefix} { .date-picker-trigger(); - .date-picker-board(); &-input { display: flex; @@ -45,22 +52,25 @@ &-overlay { padding: @date-range-picker-overlay-padding; - .date-picker-panel(); + .date-picker-inputs(); &-body { - display: flex; padding: @date-range-picker-overlay-body-padding; } &-separator { display: flex; justify-content: center; align-items: flex-start; + flex-shrink: 0; width: @date-range-picker-overlay-separator-width; padding: @date-range-picker-overlay-separator-padding; text-align: center; font-size: @date-range-picker-overlay-separator-font-size; color: @date-picker-color; } + &-inputs-side { + width: 100%; + } &-footer { text-align: end; @@ -73,14 +83,28 @@ } } } +} + +.@{date-range-picker-prefix}-panel { + max-height: @date-range-picker-panel-max-height; + .@{time-panel-prefix} { + height: @date-range-picker-panel-max-height; + } + + border: @date-range-picker-panel-border-width @date-range-picker-panel-border-style + @date-range-picker-panel-border-color; + border-radius: @date-range-picker-panel-border-radius; + display: flex; - &-board { + &-side { width: @date-range-picker-panel-width; + } - &-panel .@{time-panel-prefix} { - border: @date-range-picker-panel-border-width @date-range-picker-panel-border-style - @date-range-picker-panel-border-color; - border-radius: @date-range-picker-panel-border-radius; - } + &-separator { + width: @date-range-picker-panel-separator-width; + margin: @date-range-picker-panel-separator-margin; + background-color: @date-range-picker-panel-separator-color; } + + .date-picker-panel(); } diff --git a/packages/components/date-picker/style/mixin.less b/packages/components/date-picker/style/mixin.less index d191c4313..50fdf6094 100644 --- a/packages/components/date-picker/style/mixin.less +++ b/packages/components/date-picker/style/mixin.less @@ -20,7 +20,7 @@ z-index: @date-picker-overlay-zindex; border-radius: @date-picker-overlay-border-radius; box-shadow: @date-picker-overlay-box-shadow; - background-color: @date-picker-panel-background-color; + background-color: @date-panel-background-color; &-body { outline: none; @@ -28,37 +28,29 @@ } } -.date-picker-board() { - &-board { - & &-inputs { - display: flex; - justify-content: center; - margin-bottom: @date-picker-overlay-inputs-margin-bottom; - - input { - color: @date-picker-color; - } +.date-picker-inputs() { + & &-inputs { + display: flex; + justify-content: center; + margin-bottom: @date-picker-overlay-inputs-margin-bottom; + + input { + color: @date-picker-color; + } - .@{input-prefix}-focused { - box-shadow: none; - } + .@{input-prefix}-focused { + box-shadow: none; } - & &-date-input { + + &-date-input { width: @date-picker-overlay-date-input-width; } - & &-date-input:only-child { + &-date-input:only-child { width: 100%; } - & &-time-input { + &-time-input { width: @date-picker-overlay-time-input-width; margin-left: @date-picker-overlay-input-gap; } - - &-panel { - max-height: @date-range-picker-panel-max-height; - .@{time-panel-prefix} { - height: @date-range-picker-panel-max-height; - } - } } } \ No newline at end of file diff --git a/packages/components/date-picker/style/panel.less b/packages/components/date-picker/style/panel.less index 4bc71f010..48ed0fb33 100644 --- a/packages/components/date-picker/style/panel.less +++ b/packages/components/date-picker/style/panel.less @@ -4,17 +4,17 @@ flex-direction: column; text-align: center; width: 100%; - font-size: @date-picker-panel-font-size; - background: @date-picker-panel-background-color; + font-size: @date-panel-font-size; + background: @date-panel-background-color; // ======================= Header ======================= &-header { display: flex; - padding: @date-picker-panel-header-padding; - line-height: @date-picker-panel-header-height - @date-picker-panel-border-width; - border-bottom: @date-picker-panel-header-border-bottom; - color: @date-picker-panel-color; + padding: @date-panel-header-padding; + line-height: @date-panel-header-height - @date-panel-border-width; + border-bottom: @date-panel-header-border-bottom; + color: @date-panel-color; transition: color @transition-duration-base; > * { @@ -22,14 +22,14 @@ } button { - font-size: @date-picker-panel-header-button-font-size; - font-weight: @date-picker-panel-header-button-font-weight; + font-size: @date-panel-header-button-font-size; + font-weight: @date-panel-header-button-font-weight; transition: color @transition-duration-base; background-color: transparent; border-style: none; &:hover { - color: @date-picker-panel-active-color; + color: @date-panel-active-color; } } @@ -40,7 +40,7 @@ position: relative; display: inline-block; visibility: hidden; - padding: @date-picker-panel-header-item-padding; + padding: @date-panel-header-item-padding; &.visible { visibility: visible; @@ -51,7 +51,7 @@ flex: auto; button:not(:first-child) { - margin-left: @date-picker-panel-header-content-spacing; + margin-left: @date-panel-header-content-spacing; } } } @@ -59,8 +59,8 @@ // ======================= Body ======================= &-body { - padding: @date-picker-panel-body-padding; - font-size: @date-picker-panel-body-font-size; + padding: @date-panel-body-padding; + font-size: @date-panel-body-font-size; table { width: 100%; @@ -79,11 +79,11 @@ display: flex; justify-content: center; align-items: center; - min-width: @date-picker-panel-cell-width; - height: @date-picker-panel-cell-height; - margin-bottom: @date-picker-panel-body-header-margin-bottom; - font-weight: @date-picker-panel-body-header-font-weight; - background-color: @date-picker-panel-body-header-background-color; + min-width: @date-panel-cell-width; + height: @date-panel-cell-height; + margin-bottom: @date-panel-body-header-margin-bottom; + font-weight: @date-panel-body-header-font-weight; + background-color: @date-panel-body-header-background-color; } } @@ -94,50 +94,50 @@ padding-bottom: 0; } &-cell { - padding: @date-picker-panel-cell-padding; - color: @date-picker-panel-color; + padding: @date-panel-cell-padding; + color: @date-panel-color; overflow: hidden; cursor: pointer; &-out-view { - color: @date-picker-panel-disabled-color; + color: @date-panel-disabled-color; } &-inner { display: flex; align-items: center; justify-content: center; - min-width: @date-picker-panel-cell-width; - height: @date-picker-panel-cell-height; - line-height: @date-picker-panel-cell-height; - padding: @date-picker-panel-cell-inner-padding; - border-radius: @date-picker-panel-cell-border-radius; + min-width: @date-panel-cell-width; + height: @date-panel-cell-height; + line-height: @date-panel-cell-height; + padding: @date-panel-cell-inner-padding; + border-radius: @date-panel-cell-border-radius; } &-trigger { - width: @date-picker-panel-cell-trigger-width; - height: @date-picker-panel-cell-trigger-height; + width: @date-panel-cell-trigger-width; + height: @date-panel-cell-trigger-height; display: flex; align-items: center; justify-content: center; - border-radius: @date-picker-panel-cell-border-radius; + border-radius: @date-panel-cell-border-radius; transition: background @transition-duration-base, border @transition-duration-base; } &-current:not(&-selected) .@{date-panel-prefix}-cell-trigger { - border: @date-picker-panel-border-width @date-picker-panel-border-style - @date-picker-panel-cell-current-border-color; - color: @date-picker-panel-cell-current-color; + border: @date-panel-border-width @date-panel-border-style + @date-panel-cell-current-border-color; + color: @date-panel-cell-current-color; } &-selected .@{date-panel-prefix}-cell-trigger { - color: @date-picker-panel-color-inverse; - background: @date-picker-panel-active-color; + color: @date-panel-color-inverse; + background: @date-panel-active-color; } &-in-range { .@{date-panel-prefix}-cell-inner { - background: @date-picker-panel-in-range-color; + background: @date-panel-in-range-color; border-radius: 0; } &:not(.@{date-panel-prefix}-cell-selected) .@{date-panel-prefix}-cell-inner { @@ -146,18 +146,18 @@ } &-disabled { - color: @date-picker-panel-disabled-color; + color: @date-panel-disabled-color; cursor: not-allowed; .@{date-panel-prefix}-cell-inner { border-radius: 0; - background: @date-picker-panel-disabled-background-color; + background: @date-panel-disabled-background-color; } } &-disabled&-today { .@{date-panel-prefix}-cell-trigger { - border-color: @date-picker-panel-disabled-color; + border-color: @date-panel-disabled-color; } } } @@ -166,8 +166,8 @@ .@{date-panel-prefix}-cell { &:hover:not(&-selected):not(&-disabled) { .@{date-panel-prefix}-cell-trigger { - background: @date-picker-panel-cell-hover-background-color; - color: @date-picker-panel-cell-hover-color; + background: @date-panel-cell-hover-background-color; + color: @date-panel-cell-hover-color; } } } @@ -178,19 +178,19 @@ &:hover { .@{date-panel-prefix}-cell:not(.@{date-panel-prefix}-cell-disabled) .@{date-panel-prefix}-cell-inner { border-radius: 0; - background: @date-picker-panel-cell-hover-background-color; - color: @date-picker-panel-cell-hover-color; + background: @date-panel-cell-hover-background-color; + color: @date-panel-cell-hover-color; } .@{date-panel-prefix}-cell:not(.@{date-panel-prefix}-cell-disabled):first-child { .@{date-panel-prefix}-cell-inner { - border-top-left-radius: @date-picker-panel-cell-border-radius; - border-bottom-left-radius: @date-picker-panel-cell-border-radius; + border-top-left-radius: @date-panel-cell-border-radius; + border-bottom-left-radius: @date-panel-cell-border-radius; } } .@{date-panel-prefix}-cell:not(.@{date-panel-prefix}-cell-disabled):last-child { .@{date-panel-prefix}-cell-inner { - border-top-right-radius: @date-picker-panel-cell-border-radius; - border-bottom-right-radius: @date-picker-panel-cell-border-radius; + border-top-right-radius: @date-panel-cell-border-radius; + border-bottom-right-radius: @date-panel-cell-border-radius; } } } @@ -203,12 +203,12 @@ .@{date-panel-prefix}-cell-selected { z-index: 0; .@{date-panel-prefix}-cell-trigger { - color: @date-picker-panel-color-inverse; - background: @date-picker-panel-active-color; + color: @date-panel-color-inverse; + background: @date-panel-active-color; } &.@{date-panel-prefix}-cell-in-range { - @edge-bg-width: @date-picker-panel-cell-width * 1.5; - @translate-x: @edge-bg-width * 0.5 - @date-picker-panel-cell-width * 0.5; + @edge-bg-width: @date-panel-cell-width * 1.5; + @translate-x: @edge-bg-width * 0.5 - @date-panel-cell-width * 0.5; &.@{date-panel-prefix}-cell-start .@{date-panel-prefix}-cell-inner, &.@{date-panel-prefix}-cell-end .@{date-panel-prefix}-cell-inner { @@ -216,9 +216,9 @@ &::before { z-index: 0; position: absolute; - background: @date-picker-panel-in-range-color; - width: @date-picker-panel-cell-width * 1.5; - height: @date-picker-panel-cell-height; + background: @date-panel-in-range-color; + width: @date-panel-cell-width * 1.5; + height: @date-panel-cell-height; content: ''; } .@{date-panel-prefix}-cell-trigger { @@ -228,17 +228,17 @@ } &.@{date-panel-prefix}-cell-start .@{date-panel-prefix}-cell-inner::before { transform: ~'translateX(@{translate-x})'; - border-top-left-radius: @date-picker-panel-cell-border-radius; - border-bottom-left-radius: @date-picker-panel-cell-border-radius; + border-top-left-radius: @date-panel-cell-border-radius; + border-bottom-left-radius: @date-panel-cell-border-radius; } &.@{date-panel-prefix}-cell-end .@{date-panel-prefix}-cell-inner::before { transform: ~'translateX(-@{translate-x})'; - border-top-right-radius: @date-picker-panel-cell-border-radius; - border-bottom-right-radius: @date-picker-panel-cell-border-radius; + border-top-right-radius: @date-panel-cell-border-radius; + border-bottom-right-radius: @date-panel-cell-border-radius; } &.@{date-panel-prefix}-cell-start.@{date-panel-prefix}-cell-end { .@{date-panel-prefix}-cell-inner::before { - width: @date-picker-panel-cell-width; + width: @date-panel-cell-width; transform: none; } } @@ -251,15 +251,15 @@ &-month { .@{date-panel-prefix} { &-header { - padding: @date-picker-panel-header-padding-lg; + padding: @date-panel-header-padding-lg; } &-body { - padding: @date-picker-panel-body-padding-lg; + padding: @date-panel-body-padding-lg; } &-cell { - padding: @date-picker-panel-cell-padding-lg; + padding: @date-panel-cell-padding-lg; &:first-child .@{date-panel-prefix}-cell-inner { justify-content: flex-start; @@ -269,32 +269,32 @@ } &-inner { - min-width: @date-picker-panel-cell-width-lg; - height: @date-picker-panel-cell-height-lg; - padding: @date-picker-panel-cell-inner-padding-lg; - border-radius: @date-picker-panel-cell-border-radius-lg; + min-width: @date-panel-cell-width-lg; + height: @date-panel-cell-height-lg; + padding: @date-panel-cell-inner-padding-lg; + border-radius: @date-panel-cell-border-radius-lg; } &-trigger { - width: @date-picker-panel-cell-trigger-width-lg; - height: @date-picker-panel-cell-trigger-height-lg; - border-radius: @date-picker-panel-cell-border-radius-lg; + width: @date-panel-cell-trigger-width-lg; + height: @date-panel-cell-trigger-height-lg; + border-radius: @date-panel-cell-border-radius-lg; } &-selected { &.@{date-panel-prefix}-cell-in-range { &.@{date-panel-prefix}-cell-start .@{date-panel-prefix}-cell-inner { - border-top-left-radius: @date-picker-panel-cell-border-radius-lg; - border-bottom-left-radius: @date-picker-panel-cell-border-radius-lg; + border-top-left-radius: @date-panel-cell-border-radius-lg; + border-bottom-left-radius: @date-panel-cell-border-radius-lg; } &.@{date-panel-prefix}-cell-end .@{date-panel-prefix}-cell-inner { - border-top-right-radius: @date-picker-panel-cell-border-radius-lg; - border-bottom-right-radius: @date-picker-panel-cell-border-radius-lg; + border-top-right-radius: @date-panel-cell-border-radius-lg; + border-bottom-right-radius: @date-panel-cell-border-radius-lg; } } } &-in-range { .@{date-panel-prefix}-cell-inner { - background: @date-picker-panel-in-range-color; + background: @date-panel-in-range-color; border-radius: 0; } } diff --git a/packages/components/date-picker/style/themes/default.variable.less b/packages/components/date-picker/style/themes/default.variable.less index 4b588f902..d557c124e 100644 --- a/packages/components/date-picker/style/themes/default.variable.less +++ b/packages/components/date-picker/style/themes/default.variable.less @@ -5,65 +5,65 @@ // Range Trigger @date-range-picker-trigger-separator-margin: @spacing-xl; -// Panel -@date-picker-panel-font-size: @font-size-md; -@date-picker-panel-color: @text-color; -@date-picker-panel-color-inverse: @text-color-inverse; -@date-picker-panel-active-color: @color-primary; -@date-picker-panel-in-range-color: @color-blue-l50; -@date-picker-panel-disabled-color: @text-color-disabled; -@date-picker-panel-disabled-background-color: @color-graphite-l50; -@date-picker-panel-background-color: @background-color-component; -@date-picker-panel-border-width: @border-width-sm; -@date-picker-panel-border-style: @border-style; -@date-picker-panel-border-color: @border-color; - -@date-picker-panel-header-padding: 0 0 @spacing-xs 0; -@date-picker-panel-header-height: @height-md; -@date-picker-panel-header-item-padding: 0 @spacing-xs; -@date-picker-panel-header-border-bottom: none; -@date-picker-panel-header-button-font-size: @font-size-lg; -@date-picker-panel-header-button-font-weight: @font-weight-lg; -@date-picker-panel-header-content-spacing: @spacing-lg; -@date-picker-panel-header-padding-lg: 0 0 @spacing-2xl; - -@date-picker-panel-body-padding: 0; -@date-picker-panel-body-padding-lg: 0; -@date-picker-panel-body-font-size: @font-size-md; -@date-picker-panel-body-header-margin-bottom: @spacing-md; -@date-picker-panel-body-header-font-weight: @font-weight-md; -@date-picker-panel-body-header-background-color: @color-graphite-l50; - -@date-picker-panel-cell-width: 28px; -@date-picker-panel-cell-height: 28px; -@date-picker-panel-cell-width-lg: 52px; -@date-picker-panel-cell-height-lg: 24px; - -@date-picker-panel-cell-padding: 2px 0; -@date-picker-panel-cell-inner-padding: 4px; -@date-picker-panel-cell-padding-lg: @spacing-lg 0; -@date-picker-panel-cell-inner-padding-lg: 0; - -@date-picker-panel-cell-trigger-width: 20px; -@date-picker-panel-cell-trigger-height: 20px; -@date-picker-panel-cell-trigger-width-lg: 52px; -@date-picker-panel-cell-trigger-height-lg: 24px; - -@date-picker-panel-cell-border-radius: @border-radius-full; -@date-picker-panel-cell-border-radius-lg: @border-radius-sm; -@date-picker-panel-cell-hover-background-color: @color-graphite-l50; -@date-picker-panel-cell-hover-color: @color-primary; - -@date-picker-panel-cell-current-border-color: @color-blue-l40; -@date-picker-panel-cell-current-color: @color-primary; +// Date Panel +@date-panel-font-size: @font-size-md; +@date-panel-color: @text-color; +@date-panel-color-inverse: @text-color-inverse; +@date-panel-active-color: @color-primary; +@date-panel-in-range-color: @color-blue-l50; +@date-panel-disabled-color: @text-color-disabled; +@date-panel-disabled-background-color: @color-graphite-l50; +@date-panel-background-color: @background-color-component; +@date-panel-border-width: @border-width-sm; +@date-panel-border-style: @border-style; +@date-panel-border-color: @border-color; +@date-panel-header-padding: 0 0 @spacing-xs 0; +@date-panel-header-height: @height-md; +@date-panel-header-item-padding: 0 @spacing-xs; +@date-panel-header-border-bottom: none; +@date-panel-header-button-font-size: @font-size-lg; +@date-panel-header-button-font-weight: @font-weight-lg; +@date-panel-header-content-spacing: @spacing-lg; +@date-panel-header-padding-lg: 0 0 @spacing-2xl; + +@date-panel-body-padding: 0; +@date-panel-body-padding-lg: 0; +@date-panel-body-font-size: @font-size-md; +@date-panel-body-header-margin-bottom: @spacing-md; +@date-panel-body-header-font-weight: @font-weight-md; +@date-panel-body-header-background-color: @color-graphite-l50; + +@date-panel-cell-width: 28px; +@date-panel-cell-height: 28px; +@date-panel-cell-width-lg: 52px; +@date-panel-cell-height-lg: 24px; + +@date-panel-cell-padding: 2px 0; +@date-panel-cell-inner-padding: 4px; +@date-panel-cell-padding-lg: @spacing-lg 0; +@date-panel-cell-inner-padding-lg: 0; + +@date-panel-cell-trigger-width: 20px; +@date-panel-cell-trigger-height: 20px; +@date-panel-cell-trigger-width-lg: 52px; +@date-panel-cell-trigger-height-lg: 24px; + +@date-panel-cell-border-radius: @border-radius-full; +@date-panel-cell-border-radius-lg: @border-radius-sm; +@date-panel-cell-hover-background-color: @color-graphite-l50; +@date-panel-cell-hover-color: @color-primary; + +@date-panel-cell-current-border-color: @color-blue-l40; +@date-panel-cell-current-color: @color-primary; + +// Overlay @date-picker-overlay-footer-border-width: @form-border-width; @date-picker-overlay-footer-border-style: @form-border-style; @date-picker-overlay-footer-border-color: @form-border-color; @date-picker-overlay-footer-padding: @spacing-sm @spacing-lg; @date-picker-overlay-footer-button-margin-left: @spacing-sm; -// Overlay @date-picker-overlay-zindex: @zindex-l4-3; @date-picker-overlay-width: 252px; @date-picker-overlay-border-radius: @border-radius-sm; @@ -88,9 +88,17 @@ @date-range-picker-overlay-footer-padding: @spacing-sm 0; @date-range-picker-overlay-footer-button-margin-left: @date-picker-overlay-footer-button-margin-left; +// Date Picker Panel +@date-picker-panel-width: 220px; +@date-picker-panel-max-height: 260px; + @date-range-picker-panel-width: 220px; @date-range-picker-panel-max-height: 260px; @date-range-picker-panel-border-width: 0; @date-range-picker-panel-border-style: none; @date-range-picker-panel-border-color: none; -@date-range-picker-panel-border-radius: 0; \ No newline at end of file +@date-range-picker-panel-border-radius: 0; + +@date-range-picker-panel-separator-margin: 0 @spacing-lg; +@date-range-picker-panel-separator-width: 1px; +@date-range-picker-panel-separator-color: @date-panel-border-color; \ No newline at end of file diff --git a/packages/components/form/docs/Index.zh.md b/packages/components/form/docs/Index.zh.md index f7a8bf8cc..33ceb8731 100644 --- a/packages/components/form/docs/Index.zh.md +++ b/packages/components/form/docs/Index.zh.md @@ -130,9 +130,9 @@ export default defineComponent({ | `@form-padding-horizontal-sm` | `@spacing-sm - 2px` | - | - | | `@form-padding-horizontal-md` | `@spacing-md` | - | - | | `@form-padding-horizontal-lg` | `@spacing-sm + 2px` | - | - | -| `@form-padding-vertical-sm` | `max( (round(((@form-height-sm - @form-font-size-sm * @form-line-height) / 2) * 10) / 10) - @form-border-width, 0)` | - | - | -| `@form-padding-vertical-md` | `max( (round(((@form-height-md - @form-font-size-md * @form-line-height) / 2) * 10) / 10) - @form-border-width, 2px)` | - | - | -| `@form-padding-vertical-lg` | `(ceil(((@form-height-lg - @form-font-size-lg * @form-line-height) / 2) * 10) / 10) - @form-border-width` | - | - | +| `@form-padding-vertical-sm` | `max( (round(((@form-height-sm - @form-font-size-sm * @form-line-height) / 2) * 10) / 10) - @form-border-width, 0 )` | - | - | +| `@form-padding-vertical-md` | `max( (round(((@form-height-md - @form-font-size-md * @form-line-height) / 2) * 10) / 10) - @form-border-width, 2px )` | - | - | +| `@form-padding-vertical-lg` | `(ceil(((@form-height-lg - @form-font-size-lg * @form-line-height) / 2) * 10) / 10) - @form-border-width` | - | - | | `@form-border-width` | `@border-width-sm` | - | - | | `@form-border-style` | `@border-style` | - | - | | `@form-border-color` | `@border-color` | - | - | diff --git a/packages/components/index.ts b/packages/components/index.ts index 0e2a6d8e0..dccd8dc9d 100644 --- a/packages/components/index.ts +++ b/packages/components/index.ts @@ -21,7 +21,7 @@ import { IxCascader } from '@idux/components/cascader' import { IxCheckbox, IxCheckboxGroup } from '@idux/components/checkbox' import { IxCollapse, IxCollapsePanel } from '@idux/components/collapse' import { IxComment } from '@idux/components/comment' -import { IxDatePicker, IxDateRangePicker } from '@idux/components/date-picker' +import { IxDatePanel, IxDatePicker, IxDateRangePanel, IxDateRangePicker } from '@idux/components/date-picker' import { IxDivider } from '@idux/components/divider' import { IxDrawer, IxDrawerProvider } from '@idux/components/drawer' import { IxDropdown } from '@idux/components/dropdown' @@ -91,7 +91,9 @@ const components = [ IxCollapse, IxCollapsePanel, IxDatePicker, + IxDatePanel, IxDateRangePicker, + IxDateRangePanel, IxDivider, IxDrawer, IxDrawerProvider, diff --git a/packages/components/types.d.ts b/packages/components/types.d.ts index 6bf7828cf..959accdc1 100644 --- a/packages/components/types.d.ts +++ b/packages/components/types.d.ts @@ -17,7 +17,12 @@ import type { CarouselComponent } from '@idux/components/carousel' import type { CascaderComponent } from '@idux/components/cascader' import type { CheckboxComponent, CheckboxGroupComponent } from '@idux/components/checkbox' import type { CollapseComponent, CollapsePanelComponent } from '@idux/components/collapse' -import type { DatePickerComponent, DateRangePickerComponent } from '@idux/components/date-picker' +import type { + DatePanelComponent, + DatePickerComponent, + DateRangePanelComponent, + DateRangePickerComponent, +} from '@idux/components/date-picker' import type { DividerComponent } from '@idux/components/divider' import type { DrawerComponent, DrawerProviderComponent } from '@idux/components/drawer' import type { DropdownComponent } from '@idux/components/dropdown' @@ -101,7 +106,9 @@ declare module 'vue' { IxCollapse: CollapseComponent IxCollapsePanel: CollapsePanelComponent IxDatePicker: DatePickerComponent + IxDatePanel: DatePanelComponent IxDateRangePicker: DateRangePickerComponent + IxDateRangePanel: DateRangePanelComponent IxDivider: DividerComponent IxDrawer: DrawerComponent IxDrawerProvider: DrawerProviderComponent