diff --git a/packages/common b/packages/common
index f11bd16214..9453de9316 160000
--- a/packages/common
+++ b/packages/common
@@ -1 +1 @@
-Subproject commit f11bd1621477a7fbe2a0b6751aac958db34b95c8
+Subproject commit 9453de93160f466ff3c8ba5638d26c56dc46031c
diff --git a/packages/components/color-picker/__tests__/__snapshots__/color-picker-panel.test.tsx.snap b/packages/components/color-picker/__tests__/__snapshots__/color-picker-panel.test.tsx.snap
index 34fdf314cf..2afcd99bac 100644
--- a/packages/components/color-picker/__tests__/__snapshots__/color-picker-panel.test.tsx.snap
+++ b/packages/components/color-picker/__tests__/__snapshots__/color-picker-panel.test.tsx.snap
@@ -74,6 +74,7 @@ exports[`ColorPickerPanel > :props > :colorModes[monochrome,linear-gradient] 1`]
/>
+
+
+
+
diff --git a/packages/components/color-picker/color-picker-panel-props.ts b/packages/components/color-picker/color-picker-panel-props.ts
index db17d95655..d2f449e232 100644
--- a/packages/components/color-picker/color-picker-panel-props.ts
+++ b/packages/components/color-picker/color-picker-panel-props.ts
@@ -22,6 +22,8 @@ export default {
type: Boolean,
default: true,
},
+ /** 是否开启吸色功能,启用后面板顶部出现吸色按钮,仅支持 Chrome/Edge 等现代浏览器 */
+ eyeDropper: Boolean,
/** 格式化色值。`enableAlpha` 为真时,`HEX8/RGBA/HSLA/HSVA` 有效 */
format: {
type: String as PropType
,
diff --git a/packages/components/color-picker/components/panel/header.tsx b/packages/components/color-picker/components/panel/header.tsx
index 90426793a8..8b1cfed342 100644
--- a/packages/components/color-picker/components/panel/header.tsx
+++ b/packages/components/color-picker/components/panel/header.tsx
@@ -1,6 +1,6 @@
-import { defineComponent, PropType, ref, watch } from 'vue';
-
+import { defineComponent, PropType, ref, watch, onUnmounted } from 'vue';
import { COLOR_MODES } from '@tdesign/common-js/color-picker/constants';
+import { isEyeDropperSupported, openEyeDropper } from '../../utils/eyedropper';
import { useConfig } from '@tdesign/shared-hooks';
import { RadioButton as TRadioButton, RadioGroup as TRadioGroup } from '../../../radio';
import props from '../../color-picker-panel-props';
@@ -17,35 +17,75 @@ export default defineComponent({
},
onModeChange: {
type: Function,
- default: () => {
- return () => {};
- },
+ default: () => () => {},
+ },
+ onEyeDropperPick: {
+ type: Function as PropType<(hex: string) => void>,
+ default: () => () => {},
},
},
setup(props) {
const { globalConfig } = useConfig('colorPicker');
const baseClassName = useBaseClassName();
const modeValue = ref(props.mode);
- const handleModeChange = (v: string) => props.onModeChange(v);
+ const picking = ref(false);
+ const supported = isEyeDropperSupported();
+ let abortCtrl: AbortController | null = null;
+
watch(
() => props.mode,
(v) => (modeValue.value = v),
);
- return () => {
- if (props.colorModes?.length === 1) {
- return null;
+
+ onUnmounted(() => {
+ abortCtrl?.abort();
+ });
+
+ const handleModeChange = (v: string) => props.onModeChange(v);
+
+ const handleEyeDropperClick = async () => {
+ if (picking.value || !supported) return;
+ abortCtrl = new AbortController();
+ picking.value = true;
+ try {
+ const hex = await openEyeDropper(abortCtrl.signal);
+ if (hex) props.onEyeDropperPick(hex);
+ } finally {
+ picking.value = false;
+ abortCtrl = null;
}
+ };
+
+ return () => {
+ const showModeSwitch = (props.colorModes?.length ?? 0) !== 1;
+ const showEyeDropper = props.eyeDropper;
+ if (!showModeSwitch && !showEyeDropper) return null;
+
return (
-
-
- {Object.keys(COLOR_MODES).map((key) => (
-
- {Reflect.get(globalConfig.value, COLOR_MODES[key as keyof typeof COLOR_MODES])}
-
- ))}
-
-
+ {showModeSwitch && (
+
+
+ {Object.keys(COLOR_MODES).map((key) => (
+
+ {Reflect.get(globalConfig.value, COLOR_MODES[key as keyof typeof COLOR_MODES])}
+
+ ))}
+
+
+ )}
+ {showEyeDropper && (
+
+ )}
);
};
diff --git a/packages/components/color-picker/components/panel/index.tsx b/packages/components/color-picker/components/panel/index.tsx
index 9688bab301..898ae02958 100644
--- a/packages/components/color-picker/components/panel/index.tsx
+++ b/packages/components/color-picker/components/panel/index.tsx
@@ -111,6 +111,11 @@ export default defineComponent({
},
);
+ const handleEyeDropperPick = (hex: string) => {
+ color.value.update(hex);
+ emitColorChange('eyedropper');
+ };
+
/**
* mode change
* @param newMode
@@ -289,7 +294,12 @@ export default defineComponent({
return (
-
+
{isGradient.value ? (
| boolean | null;
@@ -198,7 +208,8 @@ export type ColorPickerChangeTrigger =
| 'palette-alpha-bar'
| 'input'
| 'preset'
- | 'recent';
+ | 'recent'
+ | 'eyedropper';
export interface ColorObject {
alpha: number;
diff --git a/packages/components/color-picker/utils/eyedropper.ts b/packages/components/color-picker/utils/eyedropper.ts
new file mode 100644
index 0000000000..04e8c1e623
--- /dev/null
+++ b/packages/components/color-picker/utils/eyedropper.ts
@@ -0,0 +1,26 @@
+interface EyeDropperInstance {
+ open(options?: { signal?: AbortSignal }): Promise<{ sRGBHex: string }>;
+}
+
+interface EyeDropperConstructor {
+ new (): EyeDropperInstance;
+}
+
+function getEyeDropperCtor(): EyeDropperConstructor | undefined {
+ if (typeof window === 'undefined') return undefined;
+ const { EyeDropper } = window as Window & { EyeDropper?: unknown };
+ return typeof EyeDropper === 'function' ? (EyeDropper as EyeDropperConstructor) : undefined;
+}
+
+export const isEyeDropperSupported = (): boolean => getEyeDropperCtor() !== undefined;
+
+export const openEyeDropper = async (signal?: AbortSignal): Promise => {
+ const Ctor = getEyeDropperCtor();
+ if (!Ctor) return null;
+ try {
+ const result = await new Ctor().open(signal ? { signal } : undefined);
+ return result.sRGBHex;
+ } catch {
+ return null;
+ }
+};
diff --git a/packages/components/config-provider/type.ts b/packages/components/config-provider/type.ts
index 1063c48d23..55a4f1450a 100644
--- a/packages/components/config-provider/type.ts
+++ b/packages/components/config-provider/type.ts
@@ -384,6 +384,11 @@ export interface ColorPickerConfig {
* @default ''
*/
clearConfirmText?: string;
+ /**
+ * 语言配置,“吸色” 吸色按钮文案
+ * @default ''
+ */
+ eyeDropper?: string;
/**
* 语言配置,“最近使用颜色” 区域标题文本
* @default ''