Compare commits

...

6 Commits

Author SHA1 Message Date
neverland
711a131637
docs(changelog): vant@4.0.8 (#11490) 2023-01-15 11:15:08 +08:00
chenjiahan
6b01ba6d1a release: 4.0.8 2023-01-15 11:09:39 +08:00
neverland
b1b67015c3
fix(Picker): ensure title align in center (#11489) 2023-01-15 11:08:40 +08:00
neverland
a33610011a
chore(PickerGroup): remove redundant attrs (#11488) 2023-01-15 11:01:09 +08:00
neverland
f5f4ae6997
feat(PickerGroup): add next-step-text prop (#11487) 2023-01-15 10:53:00 +08:00
neverland
082a596568
docs(PickerGroup): fix missing tabs prop (#11486) 2023-01-15 10:14:25 +08:00
11 changed files with 1638 additions and 29 deletions

View File

@ -19,6 +19,23 @@ Vant follows [Semantic Versioning 2.0.0](https://semver.org/lang/zh-CN/).
## Details
### [v4.0.8](https://github.com/vant-ui/vant/compare/v4.0.7...v4.0.8)
`2023-01-15`
**Feature**
- PickerGroup: add next-step-text prop [#11487](https://github.com/vant-ui/vant/issues/11487)
**Bug Fixes**
- Picker: change confirm button color to primary color [#11479](https://github.com/vant-ui/vant/issues/11479)
- NumberKeyboard: change confirm button color to primary color [#11479](https://github.com/vant-ui/vant/issues/11479)
- Icons: add woff format to compat some special webview [#11485](https://github.com/vant-ui/vant/issues/11485)
- Picker: ensure title align in center [#11489](https://github.com/vant-ui/vant/issues/11489)
- Skeleton: fix can not register skeleton image component [#11470](https://github.com/vant-ui/vant/issues/11470) [#11469](https://github.com/vant-ui/vant/issues/11469)
- Tabs: incorrect insert position in some cases [#11462](https://github.com/vant-ui/vant/issues/11462)
### [v4.0.7](https://github.com/vant-ui/vant/compare/v4.0.6...v4.0.7)
`2023-01-02`

View File

@ -19,6 +19,23 @@ Vant 遵循 [Semver](https://semver.org/lang/zh-CN/) 语义化版本规范。
## 更新内容
### [v4.0.8](https://github.com/vant-ui/vant/compare/v4.0.7...v4.0.8)
`2023-01-15`
**Feature**
- PickerGroup: 新增 next-step-text 属性 [#11487](https://github.com/vant-ui/vant/issues/11487)
**Bug Fixes**
- Picker: 调整确认按钮的颜色为 primary color [#11479](https://github.com/vant-ui/vant/issues/11479)
- NumberKeyboard: 调整确认按钮的颜色为 primary color [#11479](https://github.com/vant-ui/vant/issues/11479)
- Icons: 增加 woff 格式来兼容个别 webview 环境 [#11485](https://github.com/vant-ui/vant/issues/11485)
- Picker: 修复标题文字可能不居中的问题 [#11489](https://github.com/vant-ui/vant/issues/11489)
- Skeleton: 修复全量引入组件时不会自动注册 Skeleton 子组件的问题 [#11470](https://github.com/vant-ui/vant/issues/11470) [#11469](https://github.com/vant-ui/vant/issues/11469)
- Tabs: 修复动态插入 Tab 时在个别情况下顺序错误的问题 [#11462](https://github.com/vant-ui/vant/issues/11462)
### [v4.0.7](https://github.com/vant-ui/vant/compare/v4.0.6...v4.0.7)
`2023-01-02`

View File

@ -1,6 +1,6 @@
{
"name": "vant",
"version": "4.0.7",
"version": "4.0.8",
"description": "Mobile UI Components built on Vue",
"main": "lib/vant.cjs.js",
"module": "es/index.mjs",

View File

@ -1,4 +1,9 @@
import { defineComponent, type InjectionKey, type ExtractPropTypes } from 'vue';
import {
ref,
defineComponent,
type InjectionKey,
type ExtractPropTypes,
} from 'vue';
// Utils
import { extend, makeArrayProp, createNamespace } from '../utils';
@ -20,6 +25,7 @@ export const PICKER_GROUP_KEY: InjectionKey<PickerGroupProvide> = Symbol(name);
export const pickerGroupProps = extend(
{
tabs: makeArrayProp<string>(),
nextStepText: String,
},
pickerToolbarProps
);
@ -34,26 +40,48 @@ export default defineComponent({
emits: ['confirm', 'cancel'],
setup(props, { emit, slots }) {
const activeTab = ref(0);
const { children, linkChildren } = useChildren(PICKER_GROUP_KEY);
linkChildren();
const showNextButton = () =>
activeTab.value < props.tabs.length - 1 && props.nextStepText;
const onConfirm = () => {
emit(
'confirm',
children.map((item) => item.confirm())
);
if (showNextButton()) {
activeTab.value++;
} else {
emit(
'confirm',
children.map((item) => item.confirm())
);
}
};
const onCancel = () => emit('cancel');
return () => {
const childNodes = slots.default?.();
const confirmButtonText = showNextButton()
? props.nextStepText
: props.confirmButtonText;
return (
<div class={bem()}>
<Toolbar {...props} onConfirm={onConfirm} onCancel={onCancel} />
<Tabs shrink class={bem('tabs')} animated>
<Toolbar
title={props.title}
cancelButtonText={props.cancelButtonText}
confirmButtonText={confirmButtonText}
onConfirm={onConfirm}
onCancel={onCancel}
/>
<Tabs
v-model:active={activeTab.value}
class={bem('tabs')}
shrink
animated
>
{props.tabs.map((title, index) => (
<Tab title={title} titleClass={bem('tab-title')}>
{childNodes?.[index]}

View File

@ -75,6 +75,54 @@ export default {
};
```
### Next Step Button
In some scenarios, in order to ensure that users can select all Pickers in turn, you can set the `next-step-text` prop of PickerGroup. After setting the `next-step-text` prop, if the user has not switched to the last tab, the button in the upper right corner will become "Next Step", and automatically switch to the next Picker after clicking. When the user switches to the last tab, the button in the upper right corner changes to "Confirm".
```html
<van-picker-group
title="Title"
:tabs="['Date', 'Time']"
next-step-text="Next Step"
@confirm="onConfirm"
@cancel="onCancel"
>
<van-date-picker
v-model="currentDate"
:min-date="minDate"
:max-date="maxDate"
/>
<van-time-picker v-model="currentTime" />
</van-picker-group>
```
```js
import { ref } from 'vue';
import { showToast } from 'vant';
export default {
setup() {
const currentDate = ref(['2022', '06', '01']);
const currentTime = ref(['12', '00']);
const onConfirm = () => {
showToast(
`${currentDate.value.join('/')} ${currentTime.value.join(':')}`
);
};
const onCancel = () => {
showToast('cancel');
};
return {
minDate: new Date(2020, 0, 1),
maxDate: new Date(2025, 5, 1),
currentDate,
currentTime,
};
},
};
```
### Select Date Range
Place two `DatePicker` components in the default slot of `PickerGroup` to select the time range.
@ -86,7 +134,11 @@ Place two `DatePicker` components in the default slot of `PickerGroup` to select
@confirm="onConfirm"
@cancel="onCancel"
>
<van-date-picker v-model="startDate" :min-date="minDate" :max-date="maxDate" />
<van-date-picker
v-model="startDate"
:min-date="minDate"
:max-date="maxDate"
/>
<van-date-picker v-model="endDate" :min-date="minDate" :max-date="maxDate" />
</van-picker-group>
```
@ -161,11 +213,13 @@ export default {
### Props
| Attribute | Description | Type | Default |
| ------------------- | ---------------------- | -------- | --------- |
| title | Toolbar title | _string_ | `''` |
| confirm-button-text | Text of confirm button | _string_ | `Confirm` |
| cancel-button-text | Text of cancel button | _string_ | `Cancel` |
| Attribute | Description | Type | Default |
| ----------------------- | ------------------------ | ---------- | --------- |
| tabs | Titles of tabs | _string[]_ | `[]` |
| title | Toolbar title | _string_ | `''` |
| next-step-text `v4.0.8` | Text of next step button | _string_ | `''` |
| confirm-button-text | Text of confirm button | _string_ | `Confirm` |
| cancel-button-text | Text of cancel button | _string_ | `Cancel` |
### Slots

View File

@ -75,6 +75,54 @@ export default {
};
```
### 下一步按钮
部分场景下,为了保证用户能够依次选择所有的 Picker你可以设置 PickerGroup 的 `next-step-text` 属性。在设置 `next-step-text` 属性后,如果用户未切换到最后一个标签页,那么右上角的按钮会变成「下一步」,点击后自动切换到下一个 Picker。当用户切换到最后一个标签页时右上角的按钮会变为「确认」。
```html
<van-picker-group
title="预约日期"
:tabs="['选择日期', '选择时间']"
next-step-text="下一步"
@confirm="onConfirm"
@cancel="onCancel"
>
<van-date-picker
v-model="currentDate"
:min-date="minDate"
:max-date="maxDate"
/>
<van-time-picker v-model="currentTime" />
</van-picker-group>
```
```js
import { ref } from 'vue';
import { showToast } from 'vant';
export default {
setup() {
const currentDate = ref(['2022', '06', '01']);
const currentTime = ref(['12', '00']);
const onConfirm = () => {
showToast(
`${currentDate.value.join('/')} ${currentTime.value.join(':')}`
);
};
const onCancel = () => {
showToast('cancel');
};
return {
minDate: new Date(2020, 0, 1),
maxDate: new Date(2025, 5, 1),
currentDate,
currentTime,
};
},
};
```
### 选择日期范围
`PickerGroup` 的默认插槽中放置两个 `DatePicker` 组件,可以实现选择日期范围的交互效果。
@ -86,7 +134,11 @@ export default {
@confirm="onConfirm"
@cancel="onCancel"
>
<van-date-picker v-model="startDate" :min-date="minDate" :max-date="maxDate" />
<van-date-picker
v-model="startDate"
:min-date="minDate"
:max-date="maxDate"
/>
<van-date-picker v-model="endDate" :min-date="minDate" :max-date="maxDate" />
</van-picker-group>
```
@ -161,11 +213,13 @@ export default {
### Props
| 参数 | 说明 | 类型 | 默认值 |
| ------------------- | ------------ | -------- | ------ |
| title | 顶部栏标题 | _string_ | `''` |
| confirm-button-text | 确认按钮文字 | _string_ | `确认` |
| cancel-button-text | 取消按钮文字 | _string_ | `取消` |
| 参数 | 说明 | 类型 | 默认值 |
| ----------------------- | ---------------- | ---------- | ------ |
| tabs | 设置标签页的标题 | _string[]_ | `[]` |
| title | 顶部栏标题 | _string_ | `''` |
| next-step-text `v4.0.8` | 下一步按钮的文字 | _string_ | `''` |
| confirm-button-text | 确认按钮的文字 | _string_ | `确认` |
| cancel-button-text | 取消按钮的文字 | _string_ | `取消` |
### Slots

View File

@ -0,0 +1,52 @@
<script setup lang="ts">
import { ref } from 'vue';
import { useTranslate } from '../../../docs/site';
import VanPickerGroup from '..';
import VanTimePicker from '../../time-picker';
import VanDatePicker from '../../date-picker';
import { showToast } from '../../toast';
const t = useTranslate({
'zh-CN': {
date: '选择日期',
time: '选择时间',
title: '预约日期',
nextStep: '下一步',
},
'en-US': {
date: 'Date',
time: 'Time',
title: 'Title',
nextStep: 'Next Step',
},
});
const currentTime = ref(['12', '00']);
const currentDate = ref(['2022', '06', '01']);
const minDate = new Date(2020, 0, 1);
const maxDate = new Date(2025, 5, 1);
const onConfirm = () => {
showToast(`${currentDate.value.join('/')} ${currentTime.value.join(':')}`);
};
const onCancel = () => {
showToast('cancel');
};
</script>
<template>
<van-picker-group
:title="t('title')"
:tabs="[t('date'), t('time')]"
:next-step-text="t('nextStep')"
@confirm="onConfirm"
@cancel="onCancel"
>
<van-date-picker
v-model="currentDate"
:min-date="minDate"
:max-date="maxDate"
/>
<van-time-picker v-model="currentTime" />
</van-picker-group>
</template>

View File

@ -2,6 +2,7 @@
import SelectDateTime from './SelectDateTime.vue';
import SelectTimeRange from './SelectTimeRange.vue';
import SelectDateRange from './SelectDateRange.vue';
import NextStepButton from './NextStepButton.vue';
import { useTranslate } from '../../../docs/site';
const t = useTranslate({
@ -9,11 +10,13 @@ const t = useTranslate({
selectDateTime: '选择日期时间',
selectDateRange: '选择日期范围',
selectTimeRange: '选择时间范围',
nextStepButton: '下一步按钮',
},
'en-US': {
selectDateTime: 'Select Date Time',
selectDateRange: 'Select Date Range',
selectTimeRange: 'Select Time Range',
nextStepButton: 'Next Step Button',
},
});
</script>
@ -23,6 +26,10 @@ const t = useTranslate({
<select-date-time />
</demo-block>
<demo-block card :title="t('nextStepButton')">
<next-step-button />
</demo-block>
<demo-block card :title="t('selectDateRange')">
<select-date-range />
</demo-block>

View File

@ -0,0 +1,54 @@
import { ref } from 'vue';
import { mount } from '../../../test';
import { Picker, PickerConfirmEventParams } from '../../picker';
import { PickerGroup } from '..';
test('should emit confirm event after clicking the confirm button', async () => {
const value1 = ref(['1']);
const value2 = ref(['2']);
const wrapper = mount({
setup(props, { emit }) {
const onConfirm = (params: PickerConfirmEventParams) => {
emit('confirm', params);
};
return () => (
<PickerGroup
title="Title"
tabs={['Tab1', 'Tab2']}
nextStepText="Next Step"
onConfirm={onConfirm}
>
<Picker
v-model={value1.value}
columns={[{ text: '1', value: '1' }]}
/>
<Picker
v-model={value2.value}
columns={[{ text: '2', value: '2' }]}
/>
</PickerGroup>
);
},
});
await wrapper.find('.van-picker__confirm').trigger('click');
expect(wrapper.emitted('confirm')).toBeFalsy();
await wrapper.find('.van-picker__confirm').trigger('click');
expect(wrapper.emitted('confirm')![0]).toEqual([
[
{
selectedIndexes: [0],
selectedOptions: [{ text: '1', value: '1' }],
selectedValues: ['1'],
},
{
selectedIndexes: [0],
selectedOptions: [{ text: '2', value: '2' }],
selectedValues: ['2'],
},
],
]);
});

View File

@ -37,6 +37,7 @@
user-select: none;
&__toolbar {
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
@ -61,12 +62,15 @@
}
&__title {
position: absolute;
left: 50%;
color: var(--van-text-color);
max-width: 50%;
font-weight: var(--van-font-bold);
font-size: var(--van-picker-title-font-size);
line-height: var(--van-picker-title-line-height);
text-align: center;
transform: translateX(-50%);
}
&__columns {