Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
42 changes: 41 additions & 1 deletion packages/components/color-picker/components/panel/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { defineComponent, PropType, ref, watch } from 'vue';

import { COLOR_MODES } from '@tdesign/common-js/color-picker/constants';
import { useConfig } from '@tdesign/shared-hooks';
import { isEyeDropperSupported, pickColor } from '../../utils/eyedropper.js';
import { Button as TButton } from '../../../button';
import { RadioButton as TRadioButton, RadioGroup as TRadioGroup } from '../../../radio';
import props from '../../color-picker-panel-props';
import { useBaseClassName } from '../../hooks';
Expand All @@ -21,12 +23,27 @@ export default defineComponent({
return () => {};
},
},
onEyeDropperPick: {
type: Function,
default: () => {
return () => {};
},
},
},
setup(props) {
emits: ['mode-change', 'eyedropper-pick'],
setup(props, { emit }) {
const { globalConfig } = useConfig('colorPicker');
const baseClassName = useBaseClassName();
const modeValue = ref(props.mode);
const handleModeChange = (v: string) => props.onModeChange(v);
const handleEyeDropperPick = async () => {
try {
const color = await pickColor();
props.onEyeDropperPick(color);
} catch (error: any) {
console.warn('EyeDropper pick failed:', error);
}
};
watch(
() => props.mode,
(v) => (modeValue.value = v),
Expand All @@ -46,6 +63,29 @@ export default defineComponent({
))}
</TRadioGroup>
</div>
{isEyeDropperSupported() ? (
<div class={`${baseClassName.value}__eyedropper`}>
<TButton size="small" variant="text" onClick={handleEyeDropperPick} tip="吸色">
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
xmlns="http://www.w3.org/2000/svg"
>
<g transform="rotate(45, 12, 12)">
<circle cx="12" cy="2.5" r="2.5" />
<rect x="11.2" y="5" width="1.6" height="2.5" />
<path d="M 9.6 7.5 L 11 18 L 12 19.5 L 13 18 L 14.4 7.5 Z" />
</g>
</svg>
</TButton>
</div>
) : null}
</div>
);
};
Expand Down
20 changes: 19 additions & 1 deletion packages/components/color-picker/components/panel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,19 @@ export default defineComponent({
});
};

/**
* 处理吸色事件
* @param pickedColor 吸色器返回的颜色值(hex格式)
*/
const handleEyeDropperPick = (pickedColor: string) => {
// 更新颜色状态
color.value.update(pickedColor);
// 强制更新 innerValue(触发响应式)
innerValue.value = color.value.getFormattedColor(props.format, props.enableAlpha);
// 触发变更事件
emitColorChange('eyedropper');
};

watch(
() => innerValue.value,
(newColor) => {
Expand Down Expand Up @@ -289,7 +302,12 @@ export default defineComponent({

return (
<div class={[`${baseClassName.value}__panel`, props.disabled ? statusClassNames.disabled : false]}>
<PanelHeader {...props} mode={mode.value} onModeChange={handleModeChange} />
<PanelHeader
{...props}
mode={mode.value}
onModeChange={handleModeChange}
onEyeDropperPick={handleEyeDropperPick}
/>
<div class={[`${baseClassName.value}__body`]}>
{isGradient.value ? (
<LinearGradient
Expand Down
3 changes: 2 additions & 1 deletion packages/components/color-picker/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@ export type ColorPickerChangeTrigger =
| 'palette-alpha-bar'
| 'input'
| 'preset'
| 'recent';
| 'recent'
| 'eyedropper';

export interface ColorObject {
alpha: number;
Expand Down
21 changes: 21 additions & 0 deletions packages/components/color-picker/utils/eyedropper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* EyeDropper API 支持检测
* @returns {boolean}
*/
export function isEyeDropperSupported() {
return typeof window !== 'undefined' && 'EyeDropper' in window;
}

/**
* 打开吸色器并获取颜色
* @returns {Promise<string>} 返回 hex 格式颜色值(如 "#123456")
*/
export async function pickColor() {
if (!isEyeDropperSupported()) {
throw new Error('EyeDropper API is not supported in this browser');
}

const eyeDropper = new window.EyeDropper();
const result = await eyeDropper.open();
return result.sRGBHex;
}