diff --git a/packages/web-vue/CHANGELOG.md b/packages/web-vue/CHANGELOG.md index 6a94bc138..9a4b2e25c 100644 --- a/packages/web-vue/CHANGELOG.md +++ b/packages/web-vue/CHANGELOG.md @@ -2,6 +2,47 @@ changelog: true ``` +## 2.51.1 + +`2023-09-08` + +### 🐛 BugFix + +- **cascader:** fix empty state in Cascader Virtual list ([#2686](https://github.com/arco-design/arco-design-vue/pull/2686)) + + +## 2.51.0 + +`2023-09-01` + +### ⚠️ Important Attention + +- **form:** `form-item` render element adds `id` attribute, please pay attention to the impact on the original web page + +### 🆕 Feature + +- **form:** add scroll into view to the field ([#2680](https://github.com/arco-design/arco-design-vue/pull/2680)) +- **table:** Support displaying empty subtrees ([#2673](https://github.com/arco-design/arco-design-vue/pull/2673)) +- **select:** support boolean type ([#2661](https://github.com/arco-design/arco-design-vue/pull/2661)) + +### 🐛 BugFix + +- **typography:** Fix the problem of missing related component styles when importing on demand ([#2682](https://github.com/arco-design/arco-design-vue/pull/2682)) + + +## 2.50.2 + +`2023-08-25` + +### 🐛 BugFix + +- fix the wrong scrolling position of the virtual list ([#2665](https://github.com/arco-design/arco-design-vue/pull/2665)) + +### 💎 Enhancement + +- **input-number:** Optimize the long-press effect of the step button ([#2668](https://github.com/arco-design/arco-design-vue/pull/2668)) + + ## 2.50.1 `2023-08-18` diff --git a/packages/web-vue/CHANGELOG.zh-CN.md b/packages/web-vue/CHANGELOG.zh-CN.md index 3257c1bd9..571e74dd0 100644 --- a/packages/web-vue/CHANGELOG.zh-CN.md +++ b/packages/web-vue/CHANGELOG.zh-CN.md @@ -2,6 +2,47 @@ changelog: true ``` +## 2.51.1 + +`2023-09-08` + +### 🐛 问题修复 + +- **cascader:** 修复开启虚拟列表时空状态不显示 ([#2686](https://github.com/arco-design/arco-design-vue/pull/2686)) + + +## 2.51.0 + +`2023-09-01` + +### ⚠️ 重点注意 + +- **form:** `form-item` 渲染元素增加 `id` 属性,请注意对原始网页的影响 + +### 🆕 新增功能 + +- **form:** 新增滚动到指定表单字段 ([#2680](https://github.com/arco-design/arco-design-vue/pull/2680)) +- **table:** 支持显示空子树 ([#2673](https://github.com/arco-design/arco-design-vue/pull/2673)) +- **select:** 支持`boolean` 类型 ([#2661](https://github.com/arco-design/arco-design-vue/pull/2661)) + +### 🐛 问题修复 + +- **typography:** 修复按需导入时缺少相关组件样式的问题 ([#2682](https://github.com/arco-design/arco-design-vue/pull/2682)) + + +## 2.50.2 + +`2023-08-25` + +### 🐛 问题修复 + +- 修复虚拟滚动 scrollTop 位置不对 ([#2665](https://github.com/arco-design/arco-design-vue/pull/2665)) + +### 💎 功能优化 + +- **input-number:** 优化步长按钮的长按效果 ([#2668](https://github.com/arco-design/arco-design-vue/pull/2668)) + + ## 2.50.1 `2023-08-18` diff --git a/packages/web-vue/components/_components/virtual-list-v2/virtual-list.vue b/packages/web-vue/components/_components/virtual-list-v2/virtual-list.vue index 166dd9762..9d99a9ea9 100644 --- a/packages/web-vue/components/_components/virtual-list-v2/virtual-list.vue +++ b/packages/web-vue/components/_components/virtual-list-v2/virtual-list.vue @@ -165,15 +165,6 @@ export default defineComponent({ buffer, }); - const shouldScroll = ref(true); - const scrollData = reactive({ - scrollTop: 0, - scrollHeight: 0, - }); - // 数据发生修改 - watch(dataKeys, () => { - shouldScroll.value = false; - }); const currentList = computed(() => { if (props.threshold && data.value.length <= props.threshold) { return data.value; @@ -185,27 +176,17 @@ export default defineComponent({ const onScroll = (ev: Event) => { const { scrollTop, scrollHeight, offsetHeight } = ev.target as HTMLElement; - if (shouldScroll.value) { - scrollData.scrollTop = scrollTop; - scrollData.scrollHeight = scrollHeight; - const _start = getStartByScroll(scrollTop); - if (_start !== start.value) { - setStart(_start); - } - emit('scroll', ev); - const bottom = Math.floor(scrollHeight - (scrollTop + offsetHeight)); - if (bottom <= 0) { - emit('reachBottom', ev); - } - } else { - // 数据发生修改完成 (是否采用MutationObserver) - if (scrollHeight !== scrollData.scrollHeight) { - shouldScroll.value = true; - setTimeout(() => { - scrollTo(scrollData.scrollTop); - }, 10); - } - scrollTo(scrollData.scrollTop); + const _start = getStartByScroll(scrollTop); + if (_start !== start.value) { + setStart(_start); + nextTick(() => { + scrollTo(scrollTop); + }); + } + emit('scroll', ev); + const bottom = Math.floor(scrollHeight - (scrollTop + offsetHeight)); + if (bottom <= 0) { + emit('reachBottom', ev); } }; diff --git a/packages/web-vue/components/cascader/CHANGELOG.md b/packages/web-vue/components/cascader/CHANGELOG.md index ebec324ed..03c4f26a3 100644 --- a/packages/web-vue/components/cascader/CHANGELOG.md +++ b/packages/web-vue/components/cascader/CHANGELOG.md @@ -2,6 +2,15 @@ changelog: true ``` +## 2.51.1 + +`2023-09-08` + +### 🐛 BugFix + +- fix empty state in Cascader Virtual list ([#2686](https://github.com/arco-design/arco-design-vue/pull/2686)) + + ## 2.49.0 `2023-07-21` diff --git a/packages/web-vue/components/cascader/CHANGELOG.zh-CN.md b/packages/web-vue/components/cascader/CHANGELOG.zh-CN.md index d6c6af69b..f0a734edd 100644 --- a/packages/web-vue/components/cascader/CHANGELOG.zh-CN.md +++ b/packages/web-vue/components/cascader/CHANGELOG.zh-CN.md @@ -2,6 +2,15 @@ changelog: true ``` +## 2.51.1 + +`2023-09-08` + +### 🐛 问题修复 + +- 修复开启虚拟列表时空状态不显示 ([#2686](https://github.com/arco-design/arco-design-vue/pull/2686)) + + ## 2.49.0 `2023-07-21` diff --git a/packages/web-vue/components/cascader/cascader-column.tsx b/packages/web-vue/components/cascader/cascader-column.tsx index fec76d204..26e9d71e1 100644 --- a/packages/web-vue/components/cascader/cascader-column.tsx +++ b/packages/web-vue/components/cascader/cascader-column.tsx @@ -53,7 +53,11 @@ export default defineComponent({ class={`${prefixCls}-panel-column`} style={{ zIndex: props.totalLevel - props.level }} > - {isVirtual.value ? ( + {props.column.length === 0 ? ( + +
{renderEmpty()}
+
+ ) : isVirtual.value ? ( ) : ( - {props.column.length === 0 ? ( -
{renderEmpty()}
- ) : ( - - )} +
)} diff --git a/packages/web-vue/components/form/CHANGELOG.md b/packages/web-vue/components/form/CHANGELOG.md index 92a88d0f4..0cb543a9f 100644 --- a/packages/web-vue/components/form/CHANGELOG.md +++ b/packages/web-vue/components/form/CHANGELOG.md @@ -2,6 +2,15 @@ changelog: true ``` +## 2.51.0 + +`2023-09-01` + +### 🆕 Feature + +- add scroll into view to the field ([#2680](https://github.com/arco-design/arco-design-vue/pull/2680)) + + ## 2.44.2 `2023-03-17` diff --git a/packages/web-vue/components/form/CHANGELOG.zh-CN.md b/packages/web-vue/components/form/CHANGELOG.zh-CN.md index 4dda4047c..fc05ce8ee 100644 --- a/packages/web-vue/components/form/CHANGELOG.zh-CN.md +++ b/packages/web-vue/components/form/CHANGELOG.zh-CN.md @@ -2,6 +2,15 @@ changelog: true ``` +## 2.51.0 + +`2023-09-01` + +### 🆕 新增功能 + +- 新增滚动到指定表单字段 ([#2680](https://github.com/arco-design/arco-design-vue/pull/2680)) + + ## 2.44.2 `2023-03-17` diff --git a/packages/web-vue/components/form/README.en-US.md b/packages/web-vue/components/form/README.en-US.md index cd9c3550c..112697613 100644 --- a/packages/web-vue/components/form/README.en-US.md +++ b/packages/web-vue/components/form/README.en-US.md @@ -32,6 +32,8 @@ description: A form with data collection, verification and submission functions, @import ./__demo__/custom.md +@import ./__demo__/scroll.md + ## API @@ -48,6 +50,7 @@ description: A form with data collection, verification and submission functions, |disabled|Whether to disable the form|`boolean`|`-`|| |rules|Form item validation rules|`Record`|`-`|| |auto-label-width|Whether to enable automatic label width, it only takes effect under `layout="horizontal"`.|`boolean`|`false`|2.13.0| +|scroll-to-first-error|Scroll to the first error field after verification fails|`boolean`|`false`|2.51.0| ### `
` Events |Event Name|Description|Parameters| @@ -57,13 +60,14 @@ description: A form with data collection, verification and submission functions, |submit-failed|Triggered when verification failed|data: `{values: Record; errors: Record}`
ev: `Event`| ### `` Methods -|Method|Description|Parameters|Return| -|---|---|---|:---:| -|validate|Verify all form data|callback: `(errors: undefined \| Record) => void`|Promise>| -|validateField|Validate part of the form data|field: `string \| string[]`
callback: `(errors: undefined \| Record) => void`|Promise>| -|resetFields|Reset form data|field: `string \| string[]`|-| -|clearValidate|Clear verification status|field: `string \| string[]`|-| -|setFields|Set the value and status of the form item|data: `Record`|-| +|Method|Description|Parameters|Return|version| +|---|---|---|:---:|:---| +|validate|Verify all form data|callback: `(errors: undefined \| Record) => void`|Promise>|| +|validateField|Validate part of the form data|field: `string \| string[]`
callback: `(errors: undefined \| Record) => void`|Promise>|| +|resetFields|Reset form data|field: `string \| string[]`|-|| +|clearValidate|Clear verification status|field: `string \| string[]`|-|| +|setFields|Set the value and status of the form item|data: `Record`|-|| +|scrollToField|Scroll to the specified form item|field: `string`|-|2.51.0| diff --git a/packages/web-vue/components/form/README.zh-CN.md b/packages/web-vue/components/form/README.zh-CN.md index e37eda5c1..41b683fc0 100644 --- a/packages/web-vue/components/form/README.zh-CN.md +++ b/packages/web-vue/components/form/README.zh-CN.md @@ -30,6 +30,8 @@ description: 具有数据收集、校验和提交功能的表单,包含复选 @import ./__demo__/custom.md +@import ./__demo__/scroll.md + ## API @@ -46,6 +48,8 @@ description: 具有数据收集、校验和提交功能的表单,包含复选 |disabled|是否禁用表单|`boolean`|`-`|| |rules|表单项校验规则|`Record`|`-`|| |auto-label-width|是否开启自动标签宽度,仅在 `layout="horizontal"` 下生效。|`boolean`|`false`|2.13.0| +|id|表单控件 `id` 的前缀|`string`|`-`|| +|scroll-to-first-error|验证失败后滚动到第一个错误字段|`boolean`|`false`|2.51.0| ### `` Events |事件名|描述|参数| @@ -55,13 +59,14 @@ description: 具有数据收集、校验和提交功能的表单,包含复选 |submit-failed|验证失败时触发|data: `{values: Record; errors: Record}`
ev: `Event`| ### `` Methods -|方法名|描述|参数|返回值| -|---|---|---|---| -|validate|校验全部表单数据|callback: `(errors: undefined \| Record) => void`|Promise>| -|validateField|校验部分表单数据|field: `string \| string[]`
callback: `(errors: undefined \| Record) => void`|Promise>| -|resetFields|重置表单数据|field: `string \| string[]`|-| -|clearValidate|清除校验状态|field: `string \| string[]`|-| -|setFields|设置表单项的值和状态|data: `Record`|-| +|方法名|描述|参数|返回值|版本| +|---|---|---|---|:---| +|validate|校验全部表单数据|callback: `(errors: undefined \| Record) => void`|Promise>|| +|validateField|校验部分表单数据|field: `string \| string[]`
callback: `(errors: undefined \| Record) => void`|Promise>|| +|resetFields|重置表单数据|field: `string \| string[]`|-|| +|clearValidate|清除校验状态|field: `string \| string[]`|-|| +|setFields|设置表单项的值和状态|data: `Record`|-|| +|scrollToField|滚动到指定表单项|field: `string`|-|2.51.0| diff --git a/packages/web-vue/components/form/TEMPLATE.md b/packages/web-vue/components/form/TEMPLATE.md index 3473f22a3..c1930f02d 100644 --- a/packages/web-vue/components/form/TEMPLATE.md +++ b/packages/web-vue/components/form/TEMPLATE.md @@ -41,6 +41,8 @@ description: A form with data collection, verification and submission functions, @import ./__demo__/custom.md +@import ./__demo__/scroll.md + ## API %%API(form.vue)%% diff --git a/packages/web-vue/components/form/__demo__/scroll.md b/packages/web-vue/components/form/__demo__/scroll.md new file mode 100644 index 000000000..b7ea0b99c --- /dev/null +++ b/packages/web-vue/components/form/__demo__/scroll.md @@ -0,0 +1,67 @@ +```yaml +title: + zh-CN: 滚动到指定表单字段 + en-US: Scroll To Field +``` + +## zh-CN + +展示了提交失败自动滚动到第一个错误字段和手动滚动对应字段的使用方法。 + +--- + +## en-US + +Showed the usage methods for automatically scrolling to the first error field on submission failure and manually scrolling to the corresponding field. + +--- + +```vue + + + +``` diff --git a/packages/web-vue/components/form/__test__/__snapshots__/demo.test.ts.snap b/packages/web-vue/components/form/__test__/__snapshots__/demo.test.ts.snap index f3d9a6aa2..a0b8717bd 100644 --- a/packages/web-vue/components/form/__test__/__snapshots__/demo.test.ts.snap +++ b/packages/web-vue/components/form/__test__/__snapshots__/demo.test.ts.snap @@ -8,7 +8,7 @@ exports[` demo: render [async] correctly 1`] = ` -
+
@@ -22,7 +22,7 @@ exports[` demo: render [async] correctly 1`] = `
-
+
@@ -36,7 +36,7 @@ exports[` demo: render [async] correctly 1`] = `
-
+
@@ -75,7 +75,7 @@ exports[` demo: render [auto-width] correctly 1`] = `
-
+
@@ -89,7 +89,7 @@ exports[` demo: render [auto-width] correctly 1`] = `
-
+
@@ -103,7 +103,7 @@ exports[` demo: render [auto-width] correctly 1`] = `
-
+
@@ -145,7 +145,7 @@ exports[` demo: render [basic] correctly 1`] = `
-
+
@@ -159,7 +159,7 @@ exports[` demo: render [basic] correctly 1`] = `
-
+
@@ -173,7 +173,7 @@ exports[` demo: render [basic] correctly 1`] = `
-
+
@@ -219,7 +219,7 @@ exports[` demo: render [custom] correctly 1`] = `
-
+
@@ -238,7 +238,7 @@ exports[` demo: render [disabled] correctly 1`] = `
-
+
@@ -252,7 +252,7 @@ exports[` demo: render [disabled] correctly 1`] = `
-
+
@@ -266,7 +266,7 @@ exports[` demo: render [disabled] correctly 1`] = `
-
+
@@ -305,7 +305,7 @@ exports[` demo: render [dynamic] correctly 1`] = `
-
+
@@ -319,7 +319,7 @@ exports[` demo: render [dynamic] correctly 1`] = `
-
+
-
+
@@ -364,7 +364,7 @@ exports[` demo: render [extra] correctly 1`] = `
-
+
@@ -384,7 +384,7 @@ exports[` demo: render [extra] correctly 1`] = `
-
+
@@ -409,7 +409,7 @@ exports[` demo: render [grid] correctly 1`] = `
-
+
@@ -425,7 +425,7 @@ exports[` demo: render [grid] correctly 1`] = `
-
+
@@ -441,7 +441,7 @@ exports[` demo: render [grid] correctly 1`] = `
-
+
@@ -459,7 +459,7 @@ exports[` demo: render [grid] correctly 1`] = `
-
+
@@ -475,7 +475,7 @@ exports[` demo: render [grid] correctly 1`] = `
-
+
@@ -507,7 +507,7 @@ exports[` demo: render [layout] correctly 1`] = `
-
+
@@ -521,7 +521,7 @@ exports[` demo: render [layout] correctly 1`] = `
-
+
@@ -535,7 +535,7 @@ exports[` demo: render [layout] correctly 1`] = `
-
+
@@ -606,7 +606,7 @@ exports[` demo: render [nest] correctly 1`] = `
-
+
@@ -618,7 +618,7 @@ exports[` demo: render [nest] correctly 1`] = `
-
+
@@ -652,7 +652,7 @@ exports[` demo: render [nest] correctly 1`] = `
-
+
@@ -669,7 +669,7 @@ exports[` demo: render [nest] correctly 1`] = `
-
+
@@ -691,7 +691,7 @@ exports[` demo: render [nest] correctly 1`] = `
-
+
@@ -716,6 +716,285 @@ exports[` demo: render [nest] correctly 1`] = ` }" `; +exports[` demo: render [scroll] correctly 1`] = ` +"
+ +
+ +
+ +
+
+ +
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ + +
+
+" +`; + exports[`
demo: render [status] correctly 1`] = ` "
@@ -730,7 +1009,7 @@ exports[` demo: render [status] correctly 1`] = `
-
+
@@ -746,7 +1025,7 @@ exports[` demo: render [status] correctly 1`] = `
-
+
@@ -762,7 +1041,7 @@ exports[` demo: render [status] correctly 1`] = `
-
+
@@ -784,7 +1063,7 @@ exports[` demo: render [status] correctly 1`] = `
-
+
@@ -824,7 +1103,7 @@ exports[` demo: render [status] correctly 1`] = `
-
+
@@ -847,7 +1126,7 @@ exports[` demo: render [status] correctly 1`] = `
-
+
@@ -875,7 +1154,7 @@ exports[` demo: render [validation] correctly 1`] = `
-
+
@@ -888,7 +1167,7 @@ exports[` demo: render [validation] correctly 1`] = `
-
+
@@ -901,7 +1180,7 @@ exports[` demo: render [validation] correctly 1`] = `
-
+
@@ -915,7 +1194,7 @@ exports[` demo: render [validation] correctly 1`] = `
-
+
@@ -931,7 +1210,7 @@ exports[` demo: render [validation] correctly 1`] = `
-
+
Beijing / Haidian @@ -948,7 +1227,7 @@ exports[` demo: render [validation] correctly 1`] = `
-
+
@@ -962,7 +1241,7 @@ exports[` demo: render [validation] correctly 1`] = `
-
+
@@ -986,7 +1265,7 @@ exports[` demo: render [validation] correctly 1`] = `
-
+
@@ -1010,7 +1289,7 @@ exports[` demo: render [validation] correctly 1`] = `
-
+
@@ -1024,7 +1303,7 @@ exports[` demo: render [validation] correctly 1`] = `
-
+
@@ -1051,7 +1330,7 @@ exports[` demo: render [validation] correctly 1`] = `
-
+
@@ -1108,7 +1387,7 @@ exports[` demo: render [validation] correctly 1`] = `
-
+
-
+
Please select ... @@ -1145,7 +1424,7 @@ exports[` demo: render [validation] correctly 1`] = `
-
+
diff --git a/packages/web-vue/components/form/context.ts b/packages/web-vue/components/form/context.ts index 83034e32a..bb0436808 100644 --- a/packages/web-vue/components/form/context.ts +++ b/packages/web-vue/components/form/context.ts @@ -32,6 +32,7 @@ export interface FormContext { removeLabelWidth: (uid?: number) => void; maxLabelWidth: number; autoLabelWidth: boolean; + id?: string; } export interface FormItemContext { diff --git a/packages/web-vue/components/form/form-item.vue b/packages/web-vue/components/form/form-item.vue index 09d7641a8..5037cc87c 100644 --- a/packages/web-vue/components/form/form-item.vue +++ b/packages/web-vue/components/form/form-item.vue @@ -353,6 +353,9 @@ export default defineComponent({ const colProps = { ...(props.wrapperColProps ?? formCtx.wrapperColProps), }; + if (mergedId.value) { + colProps.id = mergedId.value; + } if (props.labelColFlex || formCtx.autoLabelWidth) { colProps.flex = 'auto'; } @@ -365,6 +368,13 @@ export default defineComponent({ const mergedWrapperStyle = computed( () => props.wrapperColStyle ?? formCtx.wrapperColStyle ); + const mergedId = computed(() => { + if (formCtx.id) { + return `${formCtx.id}_${field.value}`; + } + return field.value; + }); + // 记录初始值,用于重置表单 const initialValue = getValueByPath(formCtx.model, props.field); diff --git a/packages/web-vue/components/form/form.vue b/packages/web-vue/components/form/form.vue index 5a824e416..a20ddf1eb 100644 --- a/packages/web-vue/components/form/form.vue +++ b/packages/web-vue/components/form/form.vue @@ -1,5 +1,5 @@ @@ -12,11 +12,15 @@ import { provide, reactive, toRefs, + ref, } from 'vue'; +import scrollIntoView, { + Options as ScrollIntoViewOptions, +} from 'scroll-into-view-if-needed'; import { FormItemInfo, formInjectionKey } from './context'; import { getPrefixCls } from '../_utils/global-config'; import { Size } from '../_utils/constant'; -import { isArray, isFunction } from '../_utils/is'; +import { isArray, isFunction, isBoolean } from '../_utils/is'; import { FieldData, FieldRule, ValidatedError } from './interface'; import { useSize } from '../_hooks/use-size'; @@ -105,6 +109,21 @@ export default defineComponent({ type: Boolean, default: false, }, + /** + * @zh 表单控件 `id` 的前缀 + */ + id: { + type: String, + }, + /** + * @zh 验证失败后滚动到第一个错误字段 + * @en Scroll to the first error field after verification fails + * @version 2.51.0 + */ + scrollToFirstError: { + type: Boolean, + default: false, + }, }, emits: { /** @@ -143,7 +162,9 @@ export default defineComponent({ }, setup(props, { emit }) { const prefixCls = getPrefixCls('form'); + const formRef = ref(); const { + id, model, layout, disabled, @@ -219,6 +240,28 @@ export default defineComponent({ }); }; + const scrollToField = (field: string, options?: ScrollIntoViewOptions) => { + const node = formRef.value || document.body; + const fieldId = props.id ? `${props.id}_${field}` : field; + const fieldNode = node?.querySelector(`#${fieldId}`); + + if (fieldNode) { + scrollIntoView(fieldNode as HTMLDivElement, { + behavior: 'smooth', + block: 'nearest', + scrollMode: 'if-needed', + ...options, + }); + } + }; + + const scrollToFirstError = (field: string) => { + const options = !isBoolean(props.scrollToFirstError) + ? props.scrollToFirstError + : undefined; + scrollToField(field, options); + }; + const validate = ( callback?: (errors: undefined | Record) => void ): Promise> => { @@ -238,6 +281,10 @@ export default defineComponent({ } }); + if (hasError && props.scrollToFirstError) { + scrollToFirstError(Object.keys(errors)[0]); + } + if (isFunction(callback)) { callback(hasError ? errors : undefined); } @@ -271,6 +318,10 @@ export default defineComponent({ } }); + if (hasError && props.scrollToFirstError) { + scrollToFirstError(Object.keys(errors)[0]); + } + if (isFunction(callback)) { callback(hasError ? errors : undefined); } @@ -295,6 +346,8 @@ export default defineComponent({ } }); if (hasError) { + props.scrollToFirstError && + scrollToFirstError(Object.keys(errors)[0]); emit('submitFailed', { values: model.value, errors }, e); } else { emit('submitSuccess', model.value, e); @@ -310,6 +363,7 @@ export default defineComponent({ provide( formInjectionKey, reactive({ + id, layout, disabled, labelAlign, @@ -343,12 +397,14 @@ export default defineComponent({ return { cls, + formRef, handleSubmit, innerValidate: validate, innerValidateField: validateField, innerResetFields: resetFields, innerClearValidate: clearValidate, innerSetFields: setFields, + innerScrollToField: scrollToField, }; }, methods: { @@ -405,6 +461,16 @@ export default defineComponent({ setFields(data: Record) { return this.innerSetFields(data); }, + /** + * @zh 滚动到指定表单项 + * @en Scroll to the specified form item + * @param {string} field + * @public + * @version 2.51.0 + */ + scrollToField(field: string) { + return this.innerScrollToField(field); + }, }, }); diff --git a/packages/web-vue/components/input-number/CHANGELOG.md b/packages/web-vue/components/input-number/CHANGELOG.md index 606c536cc..492cb0f7f 100644 --- a/packages/web-vue/components/input-number/CHANGELOG.md +++ b/packages/web-vue/components/input-number/CHANGELOG.md @@ -2,6 +2,15 @@ changelog: true ``` +## 2.50.2 + +`2023-08-25` + +### 💎 Enhancement + +- Optimize the long-press effect of the step button ([#2668](https://github.com/arco-design/arco-design-vue/pull/2668)) + + ## 2.49.0 `2023-07-21` diff --git a/packages/web-vue/components/input-number/CHANGELOG.zh-CN.md b/packages/web-vue/components/input-number/CHANGELOG.zh-CN.md index 8e7044527..62987e3e4 100644 --- a/packages/web-vue/components/input-number/CHANGELOG.zh-CN.md +++ b/packages/web-vue/components/input-number/CHANGELOG.zh-CN.md @@ -2,6 +2,15 @@ changelog: true ``` +## 2.50.2 + +`2023-08-25` + +### 💎 功能优化 + +- 优化步长按钮的长按效果 ([#2668](https://github.com/arco-design/arco-design-vue/pull/2668)) + + ## 2.49.0 `2023-07-21` diff --git a/packages/web-vue/components/input-number/input-number.tsx b/packages/web-vue/components/input-number/input-number.tsx index c9a7a6c11..3279427c6 100644 --- a/packages/web-vue/components/input-number/input-number.tsx +++ b/packages/web-vue/components/input-number/input-number.tsx @@ -23,6 +23,7 @@ import { getKeyDownHandler, KEYBOARD_KEY } from '../_utils/keyboard'; type StepMethods = 'minus' | 'plus'; +const FIRST_DELAY = 800; const SPEED = 150; NP.enableBoundaryChecking(false); @@ -400,7 +401,7 @@ export default defineComponent({ if (needRepeat) { repeatTimer = window.setTimeout( () => (event.target as HTMLElement).dispatchEvent(event), - SPEED + repeatTimer ? SPEED : FIRST_DELAY ); } }; diff --git a/packages/web-vue/components/select/CHANGELOG.md b/packages/web-vue/components/select/CHANGELOG.md index f08cd64fe..2e8b3ec29 100644 --- a/packages/web-vue/components/select/CHANGELOG.md +++ b/packages/web-vue/components/select/CHANGELOG.md @@ -2,6 +2,15 @@ changelog: true ``` +## 2.51.0 + +`2023-09-01` + +### 🆕 Feature + +- support boolean type ([#2661](https://github.com/arco-design/arco-design-vue/pull/2661)) + + ## 2.47.1 `2023-06-09` diff --git a/packages/web-vue/components/select/CHANGELOG.zh-CN.md b/packages/web-vue/components/select/CHANGELOG.zh-CN.md index 8ec79da6b..180387ea7 100644 --- a/packages/web-vue/components/select/CHANGELOG.zh-CN.md +++ b/packages/web-vue/components/select/CHANGELOG.zh-CN.md @@ -2,6 +2,15 @@ changelog: true ``` +## 2.51.0 + +`2023-09-01` + +### 🆕 新增功能 + +- 支持`boolean` 类型 ([#2661](https://github.com/arco-design/arco-design-vue/pull/2661)) + + ## 2.47.1 `2023-06-09` diff --git a/packages/web-vue/components/select/README.en-US.md b/packages/web-vue/components/select/README.en-US.md index 63f011aff..6b05e8ae8 100644 --- a/packages/web-vue/components/select/README.en-US.md +++ b/packages/web-vue/components/select/README.en-US.md @@ -53,8 +53,8 @@ description: When users need to select one or more from a group of similar data, |Attribute|Description|Type|Default|version| |---|---|---|:---:|:---| |multiple|Whether to open multi-select mode (The search is turned on by default in the multi-select mode)|`boolean`|`false`|| -|model-value **(v-model)**|Value|`string\| number\| Record\| (string \| number \| Record)[]`|`-`|| -|default-value|Default value (uncontrolled mode)|`string\| number\| Record\| (string \| number \| Record)[]`|`'' \| []`|| +|model-value **(v-model)**|Value|`string\| number\| boolean\| Record\| (string \| number \| boolean \| Record)[]`|`-`|| +|default-value|Default value (uncontrolled mode)|`string\| number\| boolean\| Record\| (string \| number \| boolean \| Record)[]`|`'' \| []`|| |input-value **(v-model)**|The value of the input|`string`|`-`|| |default-input-value|The default value of the input (uncontrolled mode)|`string`|`''`|| |size|The size of the select|`'mini' \| 'small' \| 'medium' \| 'large'`|`'medium'`|| @@ -73,11 +73,11 @@ description: When users need to select one or more from a group of similar data, |default-popup-visible|Whether the popup is visible by default (uncontrolled mode)|`boolean`|`false`|| |unmount-on-close|Whether to destroy the element when the dropdown is closed|`boolean`|`false`|| |filter-option|Whether to filter options|`boolean \| ((inputValue: string, option: SelectOptionData) => boolean)`|`true`|| -|options|Option data|`(string \| number \| SelectOptionData \| SelectOptionGroup)[]`|`[]`|| +|options|Option data|`(string \| number \| boolean \| SelectOptionData \| SelectOptionGroup)[]`|`[]`|| |virtual-list-props|Pass the virtual list attribute, pass in this parameter to turn on virtual scrolling [VirtualListProps](#VirtualListProps)|`VirtualListProps`|`-`|| |trigger-props|Trigger props of the drop-down menu|`TriggerProps`|`-`|| |format-label|Format display content|`(data: SelectOptionData) => string`|`-`|| -|fallback-option|Options that do not exist in custom values|`boolean\| (( value: string \| number \| Record ) => SelectOptionData)`|`true`|2.10.0| +|fallback-option|Options that do not exist in custom values|`boolean\| (( value: string \| number \| boolean \| Record ) => SelectOptionData)`|`true`|2.10.0| |show-extra-options|Options that do not exist in custom values|`boolean`|`true`|2.10.0| |value-key|Used to determine the option key value attribute name|`string`|`'value'`|2.18.0| |search-delay|Delay time to trigger search event|`number`|`500`|2.18.0| @@ -90,15 +90,15 @@ description: When users need to select one or more from a group of similar data, |Event Name|Description|Parameters|version| |---|---|---|:---| -|change|Triggered when the value changes|value: ` string \| number \| Record \| (string \| number \| Record)[] `|| +|change|Triggered when the value changes|value: ` string \| number \| boolean \| Record \| (string \| number \| boolean \| Record)[] `|| |input-value-change|Triggered when the value of the input changes|inputValue: `string`|| |popup-visible-change|Triggered when the display state of the drop-down box changes|visible: `boolean`|| |clear|Triggered when the clear button is clicked|-|| -|remove|Triggered when the delete button of the label is clicked|removed: `string \| number \| Record \| undefined`|| +|remove|Triggered when the delete button of the label is clicked|removed: `string \| number \| boolean \| Record \| undefined`|| |search|Triggered when the user searches|inputValue: `string`|| |dropdown-scroll|Triggered when the drop-down scrolls|-|| |dropdown-reach-bottom|Triggered when the drop-down menu is scrolled to the bottom|-|| -|exceed-limit|Triggered when multiple selection exceeds the limit|value: `string \| number \| Record \| undefined`
ev: `Event`|2.18.0| +|exceed-limit|Triggered when multiple selection exceeds the limit|value: `string \| number \| boolean \| Record \| undefined`
ev: `Event`|2.18.0| ### `` Slots |插槽名|描述|参数|版本| @@ -119,7 +119,7 @@ description: 当用户需要从一组同类数据中选择一个或多个时, |参数名|描述|类型|默认值|版本| |---|---|---|:---:|:---| -|value|选项值(如不填,会从内容中获取)|`string\|number\|object`|`-`|| +|value|选项值(如不填,会从内容中获取)|`string\|number\|boolean\|object`|`-`|| |label|选项标签(如不填,会从内容中获取)|`string`|`-`|| |disabled|是否禁用|`boolean`|`false`|| |tag-props|展示的标签属性|`TagProps`|`-`|2.8.0| @@ -163,7 +163,7 @@ type FilterOption = boolean | ((inputValue: string, option: SelectOptionData) => |参数名|描述|类型|默认值| |---|---|---|:---:| -|value|选项值|`string \| number \| Record`|`-`| +|value|选项值|`string \| number \| boolean \| Record`|`-`| |label|选项内容|`string`|`-`| |disabled|是否禁用|`boolean`|`false`| |tagProps|选项对应的多选标签的属性|`any`|`-`| diff --git a/packages/web-vue/components/select/__demo__/basic.md b/packages/web-vue/components/select/__demo__/basic.md index 0bda0de9c..e353fdb65 100644 --- a/packages/web-vue/components/select/__demo__/basic.md +++ b/packages/web-vue/components/select/__demo__/basic.md @@ -28,6 +28,10 @@ Use the `trigger-props` property to customize the properties of the drop-down bo Guangzhou Disabled + + + + Beijing Shanghai @@ -44,6 +48,7 @@ Use the `trigger-props` property to customize the properties of the drop-down bo Guangzhou Disabled + diff --git a/packages/web-vue/components/select/__test__/__snapshots__/demo.test.ts.snap b/packages/web-vue/components/select/__test__/__snapshots__/demo.test.ts.snap index a3b30054d..dd5efc5d4 100644 --- a/packages/web-vue/components/select/__test__/__snapshots__/demo.test.ts.snap +++ b/packages/web-vue/components/select/__test__/__snapshots__/demo.test.ts.snap @@ -2,6 +2,11 @@ exports[` + + +
diff --git a/packages/web-vue/components/select/interface.ts b/packages/web-vue/components/select/interface.ts index 4aa5784b9..e344a8f00 100644 --- a/packages/web-vue/components/select/interface.ts +++ b/packages/web-vue/components/select/interface.ts @@ -5,18 +5,26 @@ import { VirtualListProps } from '../_components/virtual-list-v2/interface'; import { TriggerProps } from '../trigger'; export interface SelectProps { - options?: (string | number | SelectOptionData | SelectOptionGroup)[]; + options?: ( + | string + | number + | boolean + | SelectOptionData + | SelectOptionGroup + )[]; multiple?: boolean; modelValue?: | string | number + | boolean | Record - | (string | number | Record)[]; + | (string | number | boolean | Record)[]; defaultValue?: | string | number + | boolean | Record - | (string | number | Record)[]; + | (string | number | boolean | Record)[]; inputValue?: string; defaultInputValue?: string; size?: Size; @@ -41,7 +49,9 @@ export interface SelectProps { formatLabel?: (data: SelectOptionData) => string; fallbackOption?: | boolean - | ((value: string | number | Record) => SelectOptionData); + | (( + value: string | number | boolean | Record + ) => SelectOptionData); showExtraOptions?: boolean; valueKey?: string; searchDelay?: number; @@ -51,7 +61,11 @@ export interface SelectProps { showFooterOnEmpty?: boolean; } -export type SelectOptionValue = string | number | Record; +export type SelectOptionValue = + | string + | number + | boolean + | Record; export interface OptionValueWithKey { value: SelectOptionValue; @@ -65,7 +79,7 @@ export interface SelectOptionData { * @zh 选项值 * @en Option Value */ - value?: string | number | Record; + value?: string | number | boolean | Record; /** * @zh 选项内容 * @en Option content @@ -117,6 +131,7 @@ export interface SelectOptionGroup { export type SelectOption = | string | number + | boolean | SelectOptionData | SelectOptionGroup; diff --git a/packages/web-vue/components/select/option.vue b/packages/web-vue/components/select/option.vue index 817d465d0..db8eb5c40 100644 --- a/packages/web-vue/components/select/option.vue +++ b/packages/web-vue/components/select/option.vue @@ -63,7 +63,10 @@ export default defineComponent({ * @zh 选项值(如不填,会从内容中获取) * @en Option value (if not filled, it will be obtained from the content) */ - value: [String, Number, Object], + value: { + type: [String, Number, Boolean, Object], + default: undefined, + }, /** * @zh 选项标签(如不填,会从内容中获取) * @en Option label (if not filled, it will be obtained from the content) diff --git a/packages/web-vue/components/select/select.tsx b/packages/web-vue/components/select/select.tsx index aa7e96101..dc0969940 100644 --- a/packages/web-vue/components/select/select.tsx +++ b/packages/web-vue/components/select/select.tsx @@ -17,6 +17,7 @@ import { isNumber, isObject, isString, + isBoolean, isUndefined, } from '../_utils/is'; import { @@ -79,12 +80,14 @@ export default defineComponent({ * @en Value */ modelValue: { - type: [String, Number, Object, Array] as PropType< + type: [String, Number, Boolean, Object, Array] as PropType< | string | number + | boolean | Record - | (string | number | Record)[] + | (string | number | boolean | Record)[] >, + default: undefined, }, /** * @zh 默认值(非受控模式) @@ -92,11 +95,12 @@ export default defineComponent({ * @defaultValue '' \| [] */ defaultValue: { - type: [String, Number, Object, Array] as PropType< + type: [String, Number, Boolean, Object, Array] as PropType< | string | number + | boolean | Record - | (string | number | Record)[] + | (string | number | boolean | Record)[] >, default: (props: Data) => (isUndefined(props.multiple) ? '' : []), }, @@ -254,7 +258,7 @@ export default defineComponent({ */ options: { type: Array as PropType< - (string | number | SelectOptionData | SelectOptionGroup)[] + (string | number | boolean | SelectOptionData | SelectOptionGroup)[] >, default: () => [], }, @@ -290,7 +294,7 @@ export default defineComponent({ type: [Boolean, Function] as PropType< | boolean | (( - value: string | number | Record + value: string | number | boolean | Record ) => SelectOptionData) >, default: true, @@ -370,22 +374,24 @@ export default defineComponent({ value: | string | number + | boolean | Record - | (string | number | Record)[] + | (string | number | boolean | Record)[] ) => true, 'update:inputValue': (inputValue: string) => true, 'update:popupVisible': (visible: boolean) => true, /** * @zh 值发生改变时触发 * @en Triggered when the value changes - * @param { string | number | Record | (string | number | Record)[] } value + * @param { string | number | boolean | Record | (string | number | boolean | Record)[] } value */ 'change': ( value: | string | number + | boolean | Record - | (string | number | Record)[] + | (string | number | boolean | Record)[] ) => true, /** * @zh 输入框的值发生改变时触发 @@ -407,10 +413,11 @@ export default defineComponent({ /** * @zh 点击标签的删除按钮时触发 * @en Triggered when the delete button of the label is clicked - * @param {string | number | Record | undefined} removed + * @param {string | number | boolean | Record | undefined} removed */ - 'remove': (removed: string | number | Record | undefined) => - true, + 'remove': ( + removed: string | number | boolean | Record | undefined + ) => true, /** * @zh 用户搜索时触发 * @en Triggered when the user searches @@ -430,12 +437,12 @@ export default defineComponent({ /** * @zh 多选超出限制时触发 * @en Triggered when multiple selection exceeds the limit - * @param {string | number | Record | undefined} value + * @param {string | number | boolean | Record | undefined} value * @param {Event} ev * @version 2.18.0 */ 'exceedLimit': ( - value: string | number | Record | undefined, + value: string | number | boolean | Record | undefined, ev: Event ) => true, }, @@ -555,7 +562,10 @@ export default defineComponent({ const mergedValue = props.modelValue ?? _value.value; const valueArray = isArray(mergedValue) ? mergedValue - : mergedValue || isNumber(mergedValue) || isString(mergedValue) + : mergedValue || + isNumber(mergedValue) || + isString(mergedValue) || + isBoolean(mergedValue) ? [mergedValue] : []; return valueArray.map((value) => ({ @@ -596,7 +606,7 @@ export default defineComponent({ // extra value and option const getFallBackOption = ( - value: string | number | Record + value: string | number | boolean | Record ): SelectOptionData => { if (isFunction(props.fallbackOption)) { return props.fallbackOption(value); diff --git a/packages/web-vue/components/select/utils.ts b/packages/web-vue/components/select/utils.ts index 5df0bc18c..f0a6c3f3e 100644 --- a/packages/web-vue/components/select/utils.ts +++ b/packages/web-vue/components/select/utils.ts @@ -1,4 +1,10 @@ -import { isFunction, isNumber, isObject, isString } from '../_utils/is'; +import { + isBoolean, + isFunction, + isNumber, + isObject, + isString, +} from '../_utils/is'; import type { FilterOption, SelectOptionGroup, @@ -32,7 +38,7 @@ export const getKeyFromValue = ( if (isObject(value)) { return `__arco__option__object__${value[valueKey]}`; } - if (value || isNumber(value) || isString(value)) { + if (value || isNumber(value) || isString(value) || isBoolean(value)) { return `__arco__option__${typeof value}-${value}`; } return ''; diff --git a/packages/web-vue/components/slider/__test__/__snapshots__/demo.test.ts.snap b/packages/web-vue/components/slider/__test__/__snapshots__/demo.test.ts.snap index edfe4e142..13f586ca3 100644 --- a/packages/web-vue/components/slider/__test__/__snapshots__/demo.test.ts.snap +++ b/packages/web-vue/components/slider/__test__/__snapshots__/demo.test.ts.snap @@ -130,7 +130,7 @@ exports[` demo: render [step] correctly 1`] = `
-
+
@@ -144,7 +144,7 @@ exports[` demo: render [step] correctly 1`] = `
-
+