From ffe42ae401ede5a1e69c7d8c70983eebbc7bb2e1 Mon Sep 17 00:00:00 2001 From: Noblet Ouways <91417411+Dsaquel@users.noreply.github.com> Date: Tue, 24 Jun 2025 10:58:38 +0200 Subject: [PATCH] feat(components): [color-picker] add empty values attributes (#20962) * feat(components): [color-picker] add empty values attributes * chore: better * test: add test case * docs: update version --------- Co-authored-by: warmthsea <2586244885@qq.com> --- docs/en-US/component/color-picker.md | 32 ++++++++++--------- .../__tests__/color-picker.test.tsx | 17 ++++++++-- .../color-picker/src/color-picker.ts | 7 +++- .../color-picker/src/color-picker.vue | 10 +++--- 4 files changed, 43 insertions(+), 23 deletions(-) diff --git a/docs/en-US/component/color-picker.md b/docs/en-US/component/color-picker.md index 36824ef998..a7e52401d2 100644 --- a/docs/en-US/component/color-picker.md +++ b/docs/en-US/component/color-picker.md @@ -43,21 +43,23 @@ color-picker/sizes ### Attributes -| Name | Description | Type | Default | -| --------------------------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ------- | -| model-value / v-model | binding value | ^[string] | — | -| disabled | whether to disable the ColorPicker | ^[boolean] | false | -| size | size of ColorPicker | ^[enum]`'large' \| 'default' \| 'small'` | — | -| show-alpha | whether to display the alpha slider | ^[boolean] | false | -| color-format | color format of v-model | ^[enum]`'hsl' \| 'hsv' \| 'hex' \| 'rgb' \| 'hex' (when show-alpha is false) \| 'rgb' (when show-alpha is true)` | — | -| popper-class | custom class name for ColorPicker's dropdown | ^[string] | — | -| predefine | predefined color options | ^[object]`string[]` | — | -| validate-event | whether to trigger form validation | ^[boolean] | true | -| tabindex | ColorPicker tabindex | ^[string] / ^[number] | 0 | -| aria-label ^(a11y) ^(2.7.2) | ColorPicker aria-label | ^[string] | — | -| id | ColorPicker id | ^[string] | — | -| teleported ^(2.7.2) | whether color-picker popper is teleported to the body | ^[boolean] | true | -| label ^(a11y) ^(deprecated) | ColorPicker aria-label | ^[string] | — | +| Name | Description | Type | Default | +| --------------------------- | -------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ------- | +| model-value / v-model | binding value | ^[string] | — | +| disabled | whether to disable the ColorPicker | ^[boolean] | false | +| size | size of ColorPicker | ^[enum]`'large' \| 'default' \| 'small'` | — | +| show-alpha | whether to display the alpha slider | ^[boolean] | false | +| color-format | color format of v-model | ^[enum]`'hsl' \| 'hsv' \| 'hex' \| 'rgb' \| 'hex' (when show-alpha is false) \| 'rgb' (when show-alpha is true)` | — | +| popper-class | custom class name for ColorPicker's dropdown | ^[string] | — | +| predefine | predefined color options | ^[object]`string[]` | — | +| validate-event | whether to trigger form validation | ^[boolean] | true | +| tabindex | ColorPicker tabindex | ^[string] / ^[number] | 0 | +| aria-label ^(a11y) ^(2.7.2) | ColorPicker aria-label | ^[string] | — | +| empty-values ^(2.10.3) | empty values of component, [see config-provider](/en-US/component/config-provider#empty-values-configurations) | ^[array] | — | +| value-on-clear ^(2.10.3) | clear return value, [see config-provider](/en-US/component/config-provider#empty-values-configurations) | ^[string] / ^[number] / ^[boolean] / ^[Function] | — | +| id | ColorPicker id | ^[string] | — | +| teleported ^(2.7.2) | whether color-picker popper is teleported to the body | ^[boolean] | true | +| label ^(a11y) ^(deprecated) | ColorPicker aria-label | ^[string] | — | ### Events diff --git a/packages/components/color-picker/__tests__/color-picker.test.tsx b/packages/components/color-picker/__tests__/color-picker.test.tsx index 594c41848d..7c41f8bc8f 100644 --- a/packages/components/color-picker/__tests__/color-picker.test.tsx +++ b/packages/components/color-picker/__tests__/color-picker.test.tsx @@ -107,7 +107,7 @@ describe('Color-picker', () => { await wrapper.find('.el-color-picker__trigger').trigger('click') document.querySelector('.el-color-dropdown__btn')?.click() await nextTick() - expect(color.value).toEqual('') // should be empty #13239 + expect(color.value).toBeNull() wrapper.unmount() }) it('should pick a color contains alpha when confirm button click', async () => { @@ -119,7 +119,7 @@ describe('Color-picker', () => { await wrapper.find('.el-color-picker__trigger').trigger('click') document.querySelector('.el-color-dropdown__btn')?.click() await nextTick() - expect(color.value).toEqual('') // should be empty #13239 + expect(color.value).toBeNull() wrapper.unmount() }) it('should init the right color when open', async () => { @@ -166,7 +166,18 @@ describe('Color-picker', () => { '.el-color-dropdown__link-btn' ) clearBtn!.click() - expect(color.value).toEqual(null) + expect(color.value).toBeNull() + wrapper.unmount() + }) + it("should set '' as null when confirm button click", async () => { + const color = ref('') + const wrapper = mount(() => ( + + )) + await wrapper.find('.el-color-picker__trigger').trigger('click') + document.querySelector('.el-color-dropdown__btn')?.click() + + expect(color.value).toBeNull() wrapper.unmount() }) it('should change hue when clicking the hue bar', async () => { diff --git a/packages/components/color-picker/src/color-picker.ts b/packages/components/color-picker/src/color-picker.ts index 73d27d2608..d3c3cce09f 100644 --- a/packages/components/color-picker/src/color-picker.ts +++ b/packages/components/color-picker/src/color-picker.ts @@ -1,6 +1,10 @@ import { isNil } from 'lodash-unified' import { buildProps, definePropType, isString } from '@element-plus/utils' -import { useAriaProps, useSizeProp } from '@element-plus/hooks' +import { + useAriaProps, + useEmptyValuesProps, + useSizeProp, +} from '@element-plus/hooks' import { useTooltipContentProps } from '@element-plus/components/tooltip' import { CHANGE_EVENT, UPDATE_MODEL_EVENT } from '@element-plus/constants' @@ -66,6 +70,7 @@ export const colorPickerProps = buildProps({ type: Boolean, default: true, }, + ...useEmptyValuesProps, ...useAriaProps(['ariaLabel']), } as const) export const colorPickerEmits = { diff --git a/packages/components/color-picker/src/color-picker.vue b/packages/components/color-picker/src/color-picker.vue index fb520f82d3..ce6eb17819 100644 --- a/packages/components/color-picker/src/color-picker.vue +++ b/packages/components/color-picker/src/color-picker.vue @@ -130,6 +130,7 @@ import { useFormSize, } from '@element-plus/components/form' import { + useEmptyValues, useFocusController, useLocale, useNamespace, @@ -165,6 +166,7 @@ const ns = useNamespace('color') const { formItem } = useFormItem() const colorSize = useFormSize() const colorDisabled = useFormDisabled() +const { valueOnClear, isEmptyValue } = useEmptyValues(props, null) const { inputId: buttonId, isLabeledByFormItem } = useFormItemInputId(props, { formItemContext: formItem, @@ -287,7 +289,7 @@ function handleConfirm() { } function confirmValue() { - const value = color.value + const value = isEmptyValue(color.value) ? valueOnClear.value : color.value emit(UPDATE_MODEL_EVENT, value) emit(CHANGE_EVENT, value) if (props.validateEvent) { @@ -309,9 +311,9 @@ function confirmValue() { function clear() { debounceSetShowPicker(false) - emit(UPDATE_MODEL_EVENT, null) - emit(CHANGE_EVENT, null) - if (props.modelValue !== null && props.validateEvent) { + emit(UPDATE_MODEL_EVENT, valueOnClear.value) + emit(CHANGE_EVENT, valueOnClear.value) + if (props.modelValue !== valueOnClear.value && props.validateEvent) { formItem?.validate('change').catch((err) => debugWarn(err)) } resetColor()