feat: ColorPicker presets should support key (#51794)

This commit is contained in:
lijianan 2024-11-28 09:53:08 +08:00 committed by GitHub
parent 3bff61e5a5
commit e18d7707f1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 48 additions and 16 deletions

View File

@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { ColorPicker, Flex, Input } from 'antd'; import { ColorPicker, Flex, Input } from 'antd';
import { createStyles } from 'antd-style';
import type { ColorPickerProps, GetProp } from 'antd'; import type { ColorPickerProps, GetProp } from 'antd';
import { createStyles } from 'antd-style';
import { generateColor } from 'antd/es/color-picker/util'; import { generateColor } from 'antd/es/color-picker/util';
import classNames from 'classnames'; import classNames from 'classnames';
@ -61,7 +61,7 @@ const DebouncedColorPicker: React.FC<React.PropsWithChildren<ThemeColorPickerPro
<ColorPicker <ColorPicker
value={value} value={value}
onChange={setValue} onChange={setValue}
presets={[{ label: 'PresetColors', colors: PRESET_COLORS }]} presets={[{ label: 'PresetColors', key: 'PresetColors', colors: PRESET_COLORS }]}
> >
{children} {children}
</ColorPicker> </ColorPicker>

View File

@ -12,7 +12,7 @@ import Form from '../../form';
import theme from '../../theme'; import theme from '../../theme';
import { AggregationColor } from '../color'; import { AggregationColor } from '../color';
import ColorPicker from '../ColorPicker'; import ColorPicker from '../ColorPicker';
import type { ColorPickerProps, ColorValueType } from '../interface'; import type { ColorPickerProps, ColorValueType, PresetsItem } from '../interface';
import { generateColor } from '../util'; import { generateColor } from '../util';
function doMouseMove( function doMouseMove(
@ -178,6 +178,7 @@ describe('ColorPicker', () => {
onChange={handleColorChange} onChange={handleColorChange}
presets={[ presets={[
{ {
key: 'Recommended',
label: 'Recommended', label: 'Recommended',
colors: [ colors: [
'#000000', '#000000',
@ -193,6 +194,7 @@ describe('ColorPicker', () => {
], ],
}, },
{ {
key: 'Recent',
label: 'Recent', label: 'Recent',
colors: [], colors: [],
}, },
@ -243,7 +245,8 @@ describe('ColorPicker', () => {
}); });
describe('preset collapsed', () => { describe('preset collapsed', () => {
const recommendedPreset = { const recommendedPreset: PresetsItem = {
key: 'Recommended',
label: 'Recommended', label: 'Recommended',
colors: ['#f00', '#0f0', '#00f'], colors: ['#f00', '#0f0', '#00f'],
}; };
@ -263,6 +266,7 @@ describe('ColorPicker', () => {
presets={[ presets={[
recommendedPreset, recommendedPreset,
{ {
key: 'Recent',
label: 'Recent', label: 'Recent',
colors: ['#f00d', '#0f0d', '#00fd'], colors: ['#f00d', '#0f0d', '#00fd'],
defaultOpen: false, defaultOpen: false,
@ -381,6 +385,7 @@ describe('ColorPicker', () => {
open open
presets={[ presets={[
{ {
key: 'test',
label: 'test', label: 'test',
colors: ['#0000001A'], colors: ['#0000001A'],
}, },
@ -949,6 +954,22 @@ describe('ColorPicker', () => {
expect(onChangeColor.toHexString()).toBe('#2ddcb4'); expect(onChangeColor.toHexString()).toBe('#2ddcb4');
}); });
it('test the same key', () => {
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
render(
<ColorPicker
open
presets={[
{ label: <span>aaa</span>, colors: ['#333'], key: 'a', defaultOpen: true },
{ label: <span>bbb</span>, colors: ['#666'], key: 'b', defaultOpen: true },
{ label: <span>ccc</span>, colors: ['#999'], key: 'c', defaultOpen: true },
]}
/>,
);
expect(errorSpy).not.toHaveBeenCalled();
errorSpy.mockRestore();
});
describe('should disable colorInput', () => { describe('should disable colorInput', () => {
it('Should defaultValue work with disabledFormat', async () => { it('Should defaultValue work with disabledFormat', async () => {
const { container } = render(<ColorPicker defaultValue="#000000" disabledFormat />); const { container } = render(<ColorPicker defaultValue="#000000" disabledFormat />);

View File

@ -35,7 +35,10 @@ export const isBright = (value: AggregationColor, bgColorToken: string) => {
return r * 0.299 + g * 0.587 + b * 0.114 > 192; return r * 0.299 + g * 0.587 + b * 0.114 > 192;
}; };
const genCollapsePanelKey = ({ label }: PresetsItem) => `panel-${label}`; const genCollapsePanelKey = (preset: PresetsItem, index: number) => {
const mergedKey = preset.key ?? index;
return `panel-${mergedKey}`;
};
const ColorPresets: FC<ColorPresetsProps> = ({ prefixCls, presets, value: color, onChange }) => { const ColorPresets: FC<ColorPresetsProps> = ({ prefixCls, presets, value: color, onChange }) => {
const [locale] = useLocale('ColorPicker'); const [locale] = useLocale('ColorPicker');
@ -48,9 +51,11 @@ const ColorPresets: FC<ColorPresetsProps> = ({ prefixCls, presets, value: color,
const activeKeys = useMemo( const activeKeys = useMemo(
() => () =>
presetsValue.reduce<string[]>((acc, preset) => { presetsValue.reduce<string[]>((acc, preset, i) => {
const { defaultOpen = true } = preset; const { defaultOpen = true } = preset;
if (defaultOpen) acc.push(genCollapsePanelKey(preset)); if (defaultOpen) {
acc.push(genCollapsePanelKey(preset, i));
}
return acc; return acc;
}, []), }, []),
[presetsValue], [presetsValue],
@ -60,8 +65,8 @@ const ColorPresets: FC<ColorPresetsProps> = ({ prefixCls, presets, value: color,
onChange?.(colorValue); onChange?.(colorValue);
}; };
const items: CollapseProps['items'] = presetsValue.map((preset) => ({ const items = presetsValue.map<NonNullable<CollapseProps['items']>[number]>((preset, i) => ({
key: genCollapsePanelKey(preset), key: genCollapsePanelKey(preset, i),
label: <div className={`${colorPresetsPrefixCls}-label`}>{preset?.label}</div>, label: <div className={`${colorPresetsPrefixCls}-label`}>{preset?.label}</div>,
children: ( children: (
<div className={`${colorPresetsPrefixCls}-items`}> <div className={`${colorPresetsPrefixCls}-items`}>

View File

@ -5,11 +5,9 @@ import type { ColorPickerProps } from 'antd';
type Presets = Required<ColorPickerProps>['presets'][number]; type Presets = Required<ColorPickerProps>['presets'][number];
const genPresets = (presets = presetPalettes) => function genPresets(presets = presetPalettes) {
Object.entries(presets).map<Presets>(([label, colors]) => ({ return Object.entries(presets).map<Presets>(([label, colors]) => ({ label, colors, key: label }));
label, }
colors,
}));
const HorizontalLayoutDemo = () => { const HorizontalLayoutDemo = () => {
const { token } = theme.useToken(); const { token } = theme.useToken();

View File

@ -5,8 +5,9 @@ import type { ColorPickerProps } from 'antd';
type Presets = Required<ColorPickerProps>['presets'][number]; type Presets = Required<ColorPickerProps>['presets'][number];
const genPresets = (presets = presetPalettes) => function genPresets(presets = presetPalettes) {
Object.entries(presets).map<Presets>(([label, colors]) => ({ label, colors })); return Object.entries(presets).map<Presets>(([label, colors]) => ({ label, colors, key: label }));
}
const Demo: React.FC = () => { const Demo: React.FC = () => {
const { token } = theme.useToken(); const { token } = theme.useToken();

View File

@ -1,4 +1,5 @@
import type { CSSProperties, FC, ReactNode } from 'react'; import type { CSSProperties, FC, ReactNode } from 'react';
import React from 'react';
import type { import type {
ColorGenInput, ColorGenInput,
ColorPickerProps as RcColorPickerProps, ColorPickerProps as RcColorPickerProps,
@ -33,7 +34,13 @@ export interface PresetsItem {
* @default true * @default true
*/ */
defaultOpen?: boolean; defaultOpen?: boolean;
/**
* The key of the panel
* @since 5.23.0
*/
key: React.Key;
} }
export type TriggerType = 'click' | 'hover'; export type TriggerType = 'click' | 'hover';
export type TriggerPlacement = TooltipPlacement; // Alias, to prevent breaking changes. export type TriggerPlacement = TooltipPlacement; // Alias, to prevent breaking changes.