Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | 1x 15x 52x 1x 10x 10x 10x 10x 24x 1x 5x 5x 5x 10x 10x 10x 5x 5x 3x 3x 5x 25x 25x 25x 25x 25x 3x 1x | import React from 'react'; import { ColorResult, color as handleColor, hexToHsva, hsvaToRgbaString, validHex, hsvaToRgba, HsvaColor, rgbaStringToHsva, } from '@uiw/color-convert'; export interface SliderProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'color'> { prefixCls?: string; color?: string | HsvaColor; lightness?: number[]; customColorShades?: { color: string | HsvaColor; lightness: number[] }[]; onChange?: (color: ColorResult, evn: React.MouseEvent<HTMLDivElement, MouseEvent>) => void; } const hsvaCheck = (color?: string | HsvaColor): HsvaColor => { return (typeof color === 'string' && validHex(color) ? hexToHsva(color) : color || {}) as HsvaColor; }; // Check if values are within specified units of each other const withinRange = (val1: number, val2: number, tolerance: number = 2): boolean => Math.abs(val1 - val2) <= tolerance; const hsvaEqual = (c1: HsvaColor, c2: HsvaColor, lightnessArray?: number[]): boolean => { // Check for match within 2 units of all properties const baseMatch = withinRange(c1.h, c2.h) && withinRange(c1.s, c2.s) && withinRange(c1.a, c2.a); const exactMatch = baseMatch && withinRange(c1.v, c2.v); // If there's a match within range, return true Iif (exactMatch) return true; // If no exact match and a lightness array exists, // check if value is within range of any of the lightness array values Eif (lightnessArray) { return baseMatch && lightnessArray.some((lightness) => withinRange(c2.v, lightness)); } return false; }; const Slider = React.forwardRef<HTMLDivElement, SliderProps>((props, ref) => { const { prefixCls = 'w-color-slider', className, style, onChange, color, customColorShades = [ { color: '#000000', lightness: [50, 40, 30, 20, 10] }, { color: '#ffffff', lightness: [95, 90, 80, 70, 60] }, ], lightness = [80, 65, 50, 35, 20], ...other } = props; const hsva = hsvaCheck(color); // Find matching custom color and its lightness array const matchingCustomColor = customColorShades.find((shade) => { const customHsva = hsvaCheck(shade.color); const isMatch = hsvaEqual(customHsva, hsva, shade.lightness); return isMatch; }); // Determine which lightness array to use const activeLightness = matchingCustomColor ? matchingCustomColor.lightness : lightness; const handleClick = (rgbaStr: string, evn: React.MouseEvent<HTMLDivElement, MouseEvent>) => { const newHsva = rgbaStringToHsva(rgbaStr); onChange && onChange(handleColor(newHsva), evn); }; return ( <div ref={ref} style={{ display: 'flex', ...style }} className={[prefixCls, className || ''].filter(Boolean).join(' ')} {...other} > {activeLightness.map((num: number, idx: number) => { const newHsva = { ...hsva, v: num }; const rgba = hsvaToRgba(newHsva); const rgbaStr = `rgba(${rgba.r}, ${rgba.g}, ${rgba.b}, ${rgba.a})`; const checked = rgbaStr === hsvaToRgbaString(hsva); return ( <div key={idx} style={{ paddingLeft: 1, width: `${100 / activeLightness.length}%`, boxSizing: 'border-box', }} > <div onClick={(evn) => handleClick(rgbaStr, evn)} style={{ backgroundColor: rgbaStr, height: 12, cursor: 'pointer', ...(checked ? { borderRadius: 2, transform: 'scale(1, 1.5)', } : {}), }} /> </div> ); })} </div> ); }); Slider.displayName = 'Slider'; export default Slider; |