Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/components/color-picker/_example/eye-dropper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import React from 'react';
import { ColorPicker } from 'tdesign-react';

export default function EyeDropperExample() {
return <ColorPicker eyeDropper defaultValue="#0052d9" />;
}
63 changes: 47 additions & 16 deletions packages/components/color-picker/components/panel/header.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import React from 'react';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { COLOR_MODES } from '@tdesign/common-js/color-picker/constants';

import { isEyeDropperSupported, openEyeDropper } from '@tdesign/common-js/color-picker/eyedropper';

Check failure on line 3 in packages/components/color-picker/components/panel/header.tsx

View workflow job for this annotation

GitHub Actions / test

Cannot find module '@tdesign/common-js/color-picker/eyedropper' or its corresponding type declarations.
Comment thread
RylanBot marked this conversation as resolved.
Outdated
import { useLocaleReceiver } from '../../../locale/LocalReceiver';
import Radio from '../../../radio';

import type { RadioValue } from '../../../radio';
import type { TdColorModes } from '../../interface';
import type { TdColorPickerProps } from '../../type';
Expand All @@ -12,30 +11,62 @@
mode?: TdColorModes;
onModeChange?: (value: RadioValue, context: { e: React.ChangeEvent<HTMLInputElement> }) => void;
baseClassName?: string;
onEyeDropperPick?: (hex: string) => void;
}

const supported = isEyeDropperSupported();

const Header = (props: ColorPanelHeaderProps) => {
const [local, t] = useLocaleReceiver('colorPicker');
const { baseClassName, mode = 'monochrome', colorModes, onModeChange, eyeDropper, onEyeDropperPick } = props;
const [picking, setPicking] = useState(false);
const abortRef = useRef<AbortController | null>(null);

useEffect(() => () => { abortRef.current?.abort(); }, []);

const { baseClassName, mode = 'monochrome', colorModes, onModeChange } = props;
const handleEyeDropperClick = useCallback(async () => {
if (picking || !supported) return;
abortRef.current = new AbortController();
setPicking(true);
try {
const hex = await openEyeDropper(abortRef.current.signal);
if (hex) onEyeDropperPick?.(hex);
} finally {
setPicking(false);
abortRef.current = null;
}
}, [picking, onEyeDropperPick]);

const isSingleMode = colorModes?.length === 1;

if (isSingleMode) {
return null;
}
if (isSingleMode && !eyeDropper) return null;

return (
<div className={`${baseClassName}__head`}>
<div className={`${baseClassName}__mode`}>
<Radio.Group variant="default-filled" size="small" value={mode} onChange={onModeChange}>
{Object.keys(COLOR_MODES).map((key) => (
<Radio.Button key={key} value={key}>
{t(local[COLOR_MODES[key]])}
</Radio.Button>
))}
</Radio.Group>
</div>
{!isSingleMode && (
<div className={`${baseClassName}__mode`}>
<Radio.Group variant="default-filled" size="small" value={mode} onChange={onModeChange}>
{Object.keys(COLOR_MODES).map((key) => (
<Radio.Button key={key} value={key}>
{t(local[COLOR_MODES[key]])}
</Radio.Button>
))}
</Radio.Group>
</div>
)}
{eyeDropper && (
<button
className={[`${baseClassName}__eyedropper`, !supported && 't-is-disabled'].filter(Boolean).join(' ')}
title={t(local.eyeDropper) || '吸色'}

Check failure on line 60 in packages/components/color-picker/components/panel/header.tsx

View workflow job for this annotation

GitHub Actions / test

Property 'eyeDropper' does not exist on type 'ColorPickerConfig'.
disabled={!supported || picking}
onClick={handleEyeDropperClick}
type="button"
>
<svg viewBox="0 0 16 16" width="1em" height="1em" fill="currentColor" aria-hidden="true">
<path d="M13.354.646a2.207 2.207 0 0 0-3.121 0L8.75 2.129l-.604-.604a1 1 0 1 0-1.414 1.414l.25.25L1.47 9.2A2.5 2.5 0 0 0 .75 11v.25H.5a.5.5 0 0 0 0 1h.25V12.5a.5.5 0 0 0 1 0v-.25H2a2.5 2.5 0 0 0 1.8-.72l5.982-5.982.25.25a1 1 0 1 0 1.414-1.414l-.604-.604 1.483-1.483a2.207 2.207 0 0 0 0-3.121zM3.094 11.78A1.5 1.5 0 0 1 2 12.25H1.75v-.25A1.5 1.5 0 0 1 2.22 10.906L8 5.121l.879.879-5.785 5.78z"/>
</svg>
</button>
)}
</div>
);
};
Expand Down
11 changes: 10 additions & 1 deletion packages/components/color-picker/components/panel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const Panel = forwardRef<HTMLDivElement, ColorPickerProps>((props, ref) => {
disabled,
enableAlpha,
enableMultipleGradient,
eyeDropper,
format,
style,
swatchColors,
Expand Down Expand Up @@ -114,6 +115,14 @@ const Panel = forwardRef<HTMLDivElement, ColorPickerProps>((props, ref) => {
emitColorChange();
};

const handleEyeDropperPick = useCallback(
(hex: string) => {
updateColor(hex);
emitColorChange('eyedropper');
},
[emitColorChange], // eslint-disable-line react-hooks/exhaustive-deps
);

/**
* 最近使用颜色变化
*/
Expand Down Expand Up @@ -281,7 +290,7 @@ const Panel = forwardRef<HTMLDivElement, ColorPickerProps>((props, ref) => {
style={{ ...style }}
ref={ref}
>
<PanelHeader baseClassName={baseClassName} mode={mode} colorModes={colorModes} onModeChange={handleModeChange} />
<PanelHeader baseClassName={baseClassName} mode={mode} colorModes={colorModes} onModeChange={handleModeChange} eyeDropper={eyeDropper} onEyeDropperPick={handleEyeDropperPick} />
<div className={`${baseClassName}__body`}>
{isGradient && (
<LinearGradient
Expand Down
8 changes: 7 additions & 1 deletion packages/components/color-picker/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ export interface TdColorPickerProps {
* @default true
*/
enableMultipleGradient?: boolean;
/**
* 是否开启吸色功能,启用后面板顶部出现吸色按钮,仅支持 Chrome/Edge 等现代浏览器
* @default false
*/
eyeDropper?: boolean;
/**
* 格式化色值。`enableAlpha` 为真时,`HEX8/RGBA/HSLA/HSVA` 有效
* @default RGB
Expand Down Expand Up @@ -111,7 +116,8 @@ export type ColorPickerChangeTrigger =
| 'palette-alpha-bar'
| 'input'
| 'preset'
| 'recent';
| 'recent'
| 'eyedropper';

export interface ColorObject {
alpha: number;
Expand Down
Loading