diff --git a/packages/varlet-vue2-cli/site/components/snackbar/snackbar.less b/packages/varlet-vue2-cli/site/components/snackbar/snackbar.less index 3fa5125..bc31d5c 100644 --- a/packages/varlet-vue2-cli/site/components/snackbar/snackbar.less +++ b/packages/varlet-vue2-cli/site/components/snackbar/snackbar.less @@ -105,7 +105,7 @@ position: absolute; } - &-fade-enter-from, + &-fade-enter, &-fade-leave-to { opacity: 0; transform: translateY(-30px); diff --git a/packages/varlet-vue2-ui/src/date-picker/DatePicker.vue b/packages/varlet-vue2-ui/src/date-picker/DatePicker.vue index a938b6f..386ab1c 100644 --- a/packages/varlet-vue2-ui/src/date-picker/DatePicker.vue +++ b/packages/varlet-vue2-ui/src/date-picker/DatePicker.vue @@ -45,15 +45,21 @@ -
+
@@ -86,8 +93,13 @@ import YearPickerPanel from './src/year-picker-panel.vue' import DayPickerPanel from './src/day-picker-panel.vue' import { props, MONTH_LIST, WEEK_HEADER } from './props' import { isArray, toNumber } from '../utils/shared' +import { nextTickFrame } from '../utils/elements' import { pack } from '../locale' +let startX = 0 +let startY = 0 +let checkType = '' +let touchDirection const currentDate = dayjs().format('YYYY-MM-D') const [currentYear, currentMonth] = currentDate?.split('-') const monthDes = MONTH_LIST.find((month) => month.index === currentMonth) @@ -223,6 +235,17 @@ export default defineComponent({ isSameMonth() { return this.chooseMonth?.index === this.previewMonth.index }, + + getPanelType() { + if (this.isYearPanel) return 'year' + if (this.type === 'month' || this.isMonthPanel) return 'month' + if (this.type === 'date') return 'date' + return '' + }, + + isUntouchable() { + return !this.touchable || ['', 'year'].includes(this.getPanelType) + }, }, watch: { @@ -245,6 +268,10 @@ export default defineComponent({ }, immediate: true, }, + + getPanelType() { + this.resetState() + }, }, methods: { @@ -441,6 +468,42 @@ export default defineComponent({ this.previewMonth = monthDes this.previewYear = yearValue }, + + handleTouchstart(event) { + if (this.isUntouchable) return + const { clientX, clientY } = event.touches[0] + startX = clientX + startY = clientY + }, + + getDirection(x, y) { + return x >= y && x > 20 ? 'x' : 'y' + }, + + handleTouchmove(event) { + if (this.isUntouchable) return + const { clientX, clientY } = event.touches[0] + const x = clientX - startX + const y = clientY - startY + touchDirection = this.getDirection(Math.abs(x), Math.abs(y)) + checkType = x > 0 ? 'prev' : 'next' + }, + + handleTouchend() { + if (this.isUntouchable || touchDirection !== 'x') return + const componentRef = this.getPanelType === 'month' ? 'monthPanelEl' : 'dayPanelEl' + nextTickFrame(() => { + this.$refs[componentRef].forwardRef(checkType) + this.resetState() + }) + }, + + resetState() { + startY = 0 + startX = 0 + checkType = '' + touchDirection = undefined + }, }, }) diff --git a/packages/varlet-vue2-ui/src/date-picker/__tests__/__snapshots__/index.spec.js.snap b/packages/varlet-vue2-ui/src/date-picker/__tests__/__snapshots__/index.spec.js.snap index 593d81e..b15d82f 100644 --- a/packages/varlet-vue2-ui/src/date-picker/__tests__/__snapshots__/index.spec.js.snap +++ b/packages/varlet-vue2-ui/src/date-picker/__tests__/__snapshots__/index.spec.js.snap @@ -52,6 +52,120 @@ exports[`test allowedDates prop 1`] = `
" `; +exports[`test datePicker style and month 1`] = ` +"
+
+
+ 2021 +
+
+ +
+ 四月 +
+
+
+
+
+ +
+
+
+
+ +
2021
+
+
+
+ +
    +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
+
+
+
+
+
+
" +`; + exports[`test datePicker style and type 1`] = ` "
diff --git a/packages/varlet-vue2-ui/src/date-picker/__tests__/index.spec.js b/packages/varlet-vue2-ui/src/date-picker/__tests__/index.spec.js index 5f11410..5f9292f 100644 --- a/packages/varlet-vue2-ui/src/date-picker/__tests__/index.spec.js +++ b/packages/varlet-vue2-ui/src/date-picker/__tests__/index.spec.js @@ -39,6 +39,7 @@ describe('test datePicker style and type', () => { expect(wrapper.html()).toMatchSnapshot() }) + test('test datePicker style and month', async () => { const template = ` { expect(wrapper.vm.date).toBe('2021-05-19') }) -// test('test datePicker touchable prop', async () => { -// const wrapper = mount({ -// components: { -// [VarDatePicker.name]: VarDatePicker, -// }, -// data() { -// return { -// date: '2021-04-08', -// type: 'date', -// } -// }, -// template: ``, -// }) - -// const pickBodyEl = wrapper.findComponent('.var-date-picker-body') -// const headerEl = wrapper.findComponent('.var-picker-header__value') - -// await triggerDrag(pickBodyEl, 0, 100) -// expect(headerEl.text()).toBe('2021 四月') -// await triggerDrag(pickBodyEl, 100, 0) -// await delay(300) -// expect(headerEl.text()).toBe('2021 三月') -// }) +test('test datePicker touchable prop', async () => { + const wrapper = mount({ + components: { + [VarDatePicker.name]: VarDatePicker, + }, + data() { + return { + date: '2021-04-08', + type: 'date', + } + }, + template: ``, + }) + + const pickBodyEl = wrapper.findComponent('.var-date-picker-body') + const headerEl = wrapper.findComponent('.var-picker-header__value') + + await triggerDrag(pickBodyEl, 0, 100) + expect(headerEl.text()).toBe('2021 四月') + await triggerDrag(pickBodyEl, 100, 0) + await delay(300) + expect(headerEl.text()).toBe('2021 三月') +}) test('test value legal', async () => { const fn = jest.fn() diff --git a/packages/varlet-vue2-ui/src/date-picker/date-picker.less b/packages/varlet-vue2-ui/src/date-picker/date-picker.less index c4544f1..3128533 100644 --- a/packages/varlet-vue2-ui/src/date-picker/date-picker.less +++ b/packages/varlet-vue2-ui/src/date-picker/date-picker.less @@ -162,6 +162,7 @@ overflow: hidden; font-weight: 700; cursor: pointer; + user-select: none; div { width: 100%; @@ -196,6 +197,11 @@ &__button[var-date-picker-color-cover='true'] { color: var(--date-picker-main-color); } + + &__button-disabled { + color: var(--color-text-disabled) !important; + cursor: not-allowed; + } } .var-year-picker { @@ -258,9 +264,14 @@ &__button[var-date-picker-color-cover='true'] { color: var(--date-picker-main-color); } + + &__button-disabled { + color: var(--color-text-disabled) !important; + cursor: not-allowed; + } } - &-translatey-enter-from { + &-translatey-enter { opacity: 0; transform: translateY(100%); } @@ -281,7 +292,7 @@ transform: translateY(-100%); } - &-reverse-translatey-enter-from { + &-reverse-translatey-enter { opacity: 0; transform: translateY(-100%); } @@ -291,7 +302,7 @@ transform: translateY(100%); } - &-panel-fade-enter-from, + &-panel-fade-enter, &-panel-fade-leave-to { transition: 0.3s var(--cubic-bezier); opacity: 0; @@ -301,12 +312,12 @@ position: absolute; } - &-translatex-enter-from { + &-translatex-enter { opacity: 0; transform: translateX(100%); } - &-reverse-translatex-enter-from { + &-reverse-translatex-enter { opacity: 0; transform: translateX(-100%); } diff --git a/packages/varlet-vue2-ui/src/date-picker/docs/en-US.md b/packages/varlet-vue2-ui/src/date-picker/docs/en-US.md index 0986d34..5e248fd 100644 --- a/packages/varlet-vue2-ui/src/date-picker/docs/en-US.md +++ b/packages/varlet-vue2-ui/src/date-picker/docs/en-US.md @@ -124,21 +124,22 @@ export default { ### Props -| Prop | Description | Type | Default | -| ----- | -------------- | -------- | ---------- | -| `v-model` | Selected date(ISO 8601 format, `YYYY-MM-DD` or `YYYY-MM`)| _string[] \| string_ | `undefined` | -| `type` | Picker type, optional values`date, month` | _string_ | `date` | -| `allowed-dates` | Restricts which dates can be selected | _function_ | `-` | -| `color` | Picker color | _string_ | `#2979ff` | +| Prop | Description | Type | Default | +| ----- |-------------------------------------------------------------------------------------------------------------------| -------- | ---------- | +| `v-model` | Selected date(ISO 8601 format, `YYYY-MM-DD` or `YYYY-MM`) | _string[] \| string_ | `undefined` | +| `type` | Picker type, optional values`date, month` | _string_ | `date` | +| `allowed-dates` | Restricts which dates can be selected | _function_ | `-` | +| `color` | Picker color | _string_ | `#2979ff` | | `header-color` | Color of picker header. If not specified it will use the color defined by color prop or the default picker color. | _string_ | `#2979ff` | -| `shadow` | Whether to add a shadow | _boolean_ | `false` | -| `first-day-of-week` | Sets the first day of the week, starting with 0 for Sunday. | _string \| number_ | `0` | -| `min` | Minimum allowed date/month (ISO 8601 format) | _string_ | `-` | -| `max` | Maximum allowed date/month (ISO 8601 format) | _string_ | `-` | -| `show-current` | Whether to display the current date | _boolean_ | `true` | -| `readonly` | readonly | _boolean_ | `false` | -| `multiple` | Allow the selection of multiple dates | _boolean_ | `false` | -| `range` | Allow the selection of date range | _boolean_ | `false` | +| `shadow` | Whether to add a shadow | _boolean_ | `false` | +| `first-day-of-week` | Sets the first day of the week, starting with 0 for Sunday. | _string \| number_ | `0` | +| `min` | Minimum allowed date/month (ISO 8601 format) | _string_ | `-` | +| `max` | Maximum allowed date/month (ISO 8601 format) | _string_ | `-` | +| `show-current` | Whether to display the current date | _boolean_ | `true` | +| `readonly` | readonly | _boolean_ | `false` | +| `multiple` | Allow the selection of multiple dates | _boolean_ | `false` | +| `range` | Allow the selection of date range | _boolean_ | `false` | +| `touchable` | Allow switch panel by touch | _boolean_ | `true` | ### Events diff --git a/packages/varlet-vue2-ui/src/date-picker/docs/zh-CN.md b/packages/varlet-vue2-ui/src/date-picker/docs/zh-CN.md index cfcbaeb..5c5e31e 100644 --- a/packages/varlet-vue2-ui/src/date-picker/docs/zh-CN.md +++ b/packages/varlet-vue2-ui/src/date-picker/docs/zh-CN.md @@ -117,21 +117,22 @@ export default { ### 属性 -| 参数 | 说明 | 类型 | 默认值 | -|---------------------| -------------- | -------- | ---------- | -| `v-model` | 被选择的日期(ISO 8601 格式,`YYYY-MM-DD` 或 `YYYY-MM`)| _string[] \| string_ | `undefined` | -| `type` | 选择器类型,可选值为 `date month` | _string_ | `date` | -| `allowed-dates` | 限制可以选择的日期 | _function_ | `-` | -| `color` | 选择器的颜色 | _string_ | `#2979ff` | -| `header-color` | 标题背景色。如果未指定,将使用由 color 属性或默认颜色。 | _string_ | `#2979ff` | -| `shadow` | 是否添加阴影 | _boolean_ | `false` | -| `first-day-of-week` | 设置一周的第一天,从周日的 0 开始。 | _string \| number_ | `0` | -| `min` | 允许的最小日期/月份(ISO 8601格式) | _string_ | `-` | -| `max` | 允许的最大日期/月份(ISO 8601格式) | _string_ | `-` | -| `show-current` | 是否显示当前日期 | _boolean_ | `true` | -| `readonly` | 是否只读 | _boolean_ | `false` | -| `multiple` | 是否支持选择多个日期 | _boolean_ | `false` | -| `range` | 是否支持选择一个范围 | _boolean_ | `false` | +| 参数 | 说明 | 类型 | 默认值 | +|---------------------|----------------------------------------------| -------- | ---------- | +| `v-model` | 被选择的日期(ISO 8601 格式,`YYYY-MM-DD` 或 `YYYY-MM`) | _string[] \| string_ | `undefined` | +| `type` | 选择器类型,可选值为 `date month` | _string_ | `date` | +| `allowed-dates` | 限制可以选择的日期 | _function_ | `-` | +| `color` | 选择器的颜色 | _string_ | `#2979ff` | +| `header-color` | 标题背景色。如果未指定,将使用由 color 属性或默认颜色。 | _string_ | `#2979ff` | +| `shadow` | 是否添加阴影 | _boolean_ | `false` | +| `first-day-of-week` | 设置一周的第一天,从周日的 0 开始。 | _string \| number_ | `0` | +| `min` | 允许的最小日期/月份(ISO 8601格式) | _string_ | `-` | +| `max` | 允许的最大日期/月份(ISO 8601格式) | _string_ | `-` | +| `show-current` | 是否显示当前日期 | _boolean_ | `true` | +| `readonly` | 是否只读 | _boolean_ | `false` | +| `multiple` | 是否支持选择多个日期 | _boolean_ | `false` | +| `range` | 是否支持选择一个范围 | _boolean_ | `false` | +| `touchable` | 是否支持拖动切换面板 | _boolean_ | `true` | ### 事件 @@ -151,7 +152,7 @@ export default { | `multiple` | 自定义标题中的多选 | `choose: ['YYYY-MM-DD' \| 'YYYY-MM']` | ### 样式变量 -以下为组件使用的 css 变量,可以使用 [StyleProvider 组件](#/zh-CN/style-provider)进行样式定制 +以下为组件使用的 css 变量,可以使用 [StyleProvider 组件](#/zh-CN/style-provider) 进行样式定制 | 变量名 | 默认值 | | --- | --- | diff --git a/packages/varlet-vue2-ui/src/date-picker/props.ts b/packages/varlet-vue2-ui/src/date-picker/props.ts index eea964c..1d3d97c 100644 --- a/packages/varlet-vue2-ui/src/date-picker/props.ts +++ b/packages/varlet-vue2-ui/src/date-picker/props.ts @@ -163,4 +163,8 @@ export const props = { type: Boolean, default: false, }, + touchable: { + type: Boolean, + default: true, + }, } diff --git a/packages/varlet-vue2-ui/src/date-picker/src/day-picker-panel.vue b/packages/varlet-vue2-ui/src/date-picker/src/day-picker-panel.vue index af5ac9d..b45ee31 100644 --- a/packages/varlet-vue2-ui/src/date-picker/src/day-picker-panel.vue +++ b/packages/varlet-vue2-ui/src/date-picker/src/day-picker-panel.vue @@ -2,6 +2,7 @@
{{ filterDay(day) }} @@ -286,6 +287,9 @@ export default defineComponent({ outline: computeOutline(), textColor: isCover ? '' : textColorOrCover(), 'var-date-picker-color-cover': isCover, + class: { + 'var-day-picker__button-disabled': disabled, + }, } }, @@ -295,9 +299,16 @@ export default defineComponent({ this.$emit('check-preview', 'month', checkType) }, - chooseDay(day) { + chooseDay(day, event) { + const buttonEl = event.currentTarget + if (buttonEl.classList.contains('var-day-picker__button-disabled')) return + this.$emit('choose-day', day) }, + + forwardRef(checkType) { + this.$refs.headerEl.checkDate(checkType) + }, }, }) diff --git a/packages/varlet-vue2-ui/src/date-picker/src/month-picker-panel.vue b/packages/varlet-vue2-ui/src/date-picker/src/month-picker-panel.vue index dc9441d..8da199d 100644 --- a/packages/varlet-vue2-ui/src/date-picker/src/month-picker-panel.vue +++ b/packages/varlet-vue2-ui/src/date-picker/src/month-picker-panel.vue @@ -2,6 +2,7 @@
{{ getMonthAbbr(month.index) }} @@ -217,10 +218,16 @@ export default defineComponent({ color: !computeText() ? color : '', textColor: isCover ? '' : textColorOrCover(), 'var-date-picker-color-cover': isCover, + class: { + 'var-month-picker__button-disabled': disabled, + }, } }, - chooseMonth(month) { + chooseMonth(month, event) { + const buttonEl = event.currentTarget + if (buttonEl.classList.contains('var-month-picker__button-disabled')) return + this.$emit('choose-month', month) }, @@ -229,6 +236,10 @@ export default defineComponent({ this.panelKey += checkType === 'prev' ? -1 : 1 this.$emit('check-preview', 'year', checkType) }, + + forwardRef(checkType) { + this.$refs.headerEl.checkDate(checkType) + }, }, }) diff --git a/packages/varlet-vue2-ui/src/date-picker/src/panel-header.vue b/packages/varlet-vue2-ui/src/date-picker/src/panel-header.vue index 933ee6a..9285334 100644 --- a/packages/varlet-vue2-ui/src/date-picker/src/panel-header.vue +++ b/packages/varlet-vue2-ui/src/date-picker/src/panel-header.vue @@ -77,6 +77,8 @@ export default defineComponent({ methods: { checkDate(checkType) { + if ((checkType === 'prev' && this.disabled.left) || (checkType === 'next' && this.disabled.right)) return + this.$emit('check-date', checkType) this.reverse = checkType === 'prev' this.forwardOrBackNum += checkType === 'prev' ? -1 : 1 diff --git a/packages/varlet-vue2-ui/src/select/select.less b/packages/varlet-vue2-ui/src/select/select.less index 6121463..bff9b0f 100644 --- a/packages/varlet-vue2-ui/src/select/select.less +++ b/packages/varlet-vue2-ui/src/select/select.less @@ -35,7 +35,7 @@ } .var { - &-select-footer-margin-enter-from, + &-select-footer-margin-enter, &-select-footer-margin-leave-to { opacity: 0; margin-top: 2px !important; diff --git a/packages/varlet-vue2-ui/types/datePicker.d.ts b/packages/varlet-vue2-ui/types/datePicker.d.ts index 631b1b4..32cd566 100644 --- a/packages/varlet-vue2-ui/types/datePicker.d.ts +++ b/packages/varlet-vue2-ui/types/datePicker.d.ts @@ -14,6 +14,9 @@ export interface DatePickerProps { readonly?: boolean multiple?: boolean range?: boolean + touchable?: boolean + onChange?: (value: string | string[]) => void + onInput?: (value: string | string[]) => void } export class DatePicker extends VarComponent {