99 lines
2.7 KiB
TypeScript
99 lines
2.7 KiB
TypeScript
import { shallowRef } from 'vue';
|
|
import type { ComputedRef, ShallowRef } from 'vue';
|
|
import { defaultWindow } from '@/types';
|
|
import type { ConfigurableWindow } from '@/types';
|
|
import { useSupported } from '@/composables/utilities/useSupported';
|
|
|
|
export interface EyeDropperOpenOptions {
|
|
/**
|
|
* An `AbortSignal` that can be used to cancel the operation.
|
|
*
|
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal
|
|
*/
|
|
signal?: AbortSignal;
|
|
}
|
|
|
|
export interface EyeDropperResult {
|
|
/**
|
|
* The selected color, in sRGB hexadecimal format (e.g. `#a1b2c3`).
|
|
*/
|
|
sRGBHex: string;
|
|
}
|
|
|
|
export interface EyeDropper {
|
|
open: (options?: EyeDropperOpenOptions) => Promise<EyeDropperResult>;
|
|
[Symbol.toStringTag]: 'EyeDropper';
|
|
}
|
|
|
|
export type EyeDropperConstructor = new () => EyeDropper;
|
|
|
|
export interface UseEyeDropperOptions extends ConfigurableWindow {
|
|
/**
|
|
* Initial `sRGBHex` value before any color has been picked.
|
|
*
|
|
* @default ''
|
|
*/
|
|
initialValue?: string;
|
|
}
|
|
|
|
export interface UseEyeDropperReturn {
|
|
/**
|
|
* Whether the [EyeDropper API](https://developer.mozilla.org/en-US/docs/Web/API/EyeDropper) is supported
|
|
*/
|
|
isSupported: ComputedRef<boolean>;
|
|
|
|
/**
|
|
* The most recently picked color, in sRGB hexadecimal format
|
|
*/
|
|
sRGBHex: ShallowRef<string>;
|
|
|
|
/**
|
|
* Open the eyedropper and let the user pick a color. Resolves with the
|
|
* result, or `undefined` when the API is unsupported.
|
|
*/
|
|
open: (openOptions?: EyeDropperOpenOptions) => Promise<EyeDropperResult | undefined>;
|
|
}
|
|
|
|
/**
|
|
* @name useEyeDropper
|
|
* @category Browser
|
|
* @description Reactive wrapper around the [EyeDropper API](https://developer.mozilla.org/en-US/docs/Web/API/EyeDropper) for picking colors from the screen.
|
|
*
|
|
* @param {UseEyeDropperOptions} [options={}] Options
|
|
* @returns {UseEyeDropperReturn} `isSupported`, `sRGBHex`, and `open()`
|
|
*
|
|
* @example
|
|
* const { isSupported, sRGBHex, open } = useEyeDropper();
|
|
* if (isSupported.value)
|
|
* await open();
|
|
*
|
|
* @since 0.0.14
|
|
*/
|
|
export function useEyeDropper(options: UseEyeDropperOptions = {}): UseEyeDropperReturn {
|
|
const {
|
|
window = defaultWindow,
|
|
initialValue = '',
|
|
} = options;
|
|
|
|
const isSupported = useSupported(() => !!window && 'EyeDropper' in window);
|
|
const sRGBHex = shallowRef(initialValue);
|
|
|
|
async function open(openOptions?: EyeDropperOpenOptions): Promise<EyeDropperResult | undefined> {
|
|
if (!isSupported.value || !window)
|
|
return;
|
|
|
|
const EyeDropperCtor = (window as unknown as { EyeDropper: EyeDropperConstructor }).EyeDropper;
|
|
const eyeDropper = new EyeDropperCtor();
|
|
const result = await eyeDropper.open(openOptions);
|
|
sRGBHex.value = result.sRGBHex;
|
|
|
|
return result;
|
|
}
|
|
|
|
return {
|
|
isSupported,
|
|
sRGBHex,
|
|
open,
|
|
};
|
|
}
|