@lobehub/ui
Version:
Lobe UI is an open-source UI component library for building AIGC web apps
1 lines • 4.37 kB
Source Map (JSON)
{"version":3,"file":"SaturationArea.mjs","names":[],"sources":["../../../src/base-ui/ColorPicker/SaturationArea.tsx"],"sourcesContent":["'use client';\n\nimport { memo, type PointerEvent, useRef } from 'react';\n\nimport { styles } from './style';\n\nexport interface SaturationAreaProps {\n hue: number;\n label: string;\n onChange: (saturation: number, value: number) => void;\n onChangeComplete: (saturation: number, value: number) => void;\n saturation: number;\n value: number;\n}\n\nconst clamp = (n: number) => Math.min(1, Math.max(0, Math.round(n * 100) / 100));\n\nconst SaturationArea = memo<SaturationAreaProps>(\n ({ hue, label, onChange, onChangeComplete, saturation, value }) => {\n const areaRef = useRef<HTMLDivElement>(null);\n\n const fromPointer = (event: PointerEvent<HTMLDivElement>): [number, number] => {\n const rect = areaRef.current!.getBoundingClientRect();\n const next: [number, number] = [\n clamp((event.clientX - rect.left) / rect.width),\n clamp(1 - (event.clientY - rect.top) / rect.height),\n ];\n onChange(...next);\n return next;\n };\n\n return (\n <div\n aria-label={label}\n aria-valuemax={100}\n aria-valuemin={0}\n aria-valuenow={Math.round(saturation * 100)}\n aria-valuetext={`Saturation ${Math.round(saturation * 100)}%, brightness ${Math.round(value * 100)}%`}\n className={styles.saturation}\n ref={areaRef}\n role=\"slider\"\n tabIndex={0}\n style={{\n background: `linear-gradient(to top, #000, transparent), linear-gradient(to right, #fff, hsl(${hue} 100% 50%))`,\n }}\n onKeyDown={(event) => {\n const delta = event.shiftKey ? 0.1 : 0.01;\n const moves: Record<string, [number, number]> = {\n ArrowDown: [0, -delta],\n ArrowLeft: [-delta, 0],\n ArrowRight: [delta, 0],\n ArrowUp: [0, delta],\n };\n const move = moves[event.key];\n if (!move) return;\n event.preventDefault();\n const next: [number, number] = [clamp(saturation + move[0]), clamp(value + move[1])];\n onChange(...next);\n onChangeComplete(...next);\n }}\n onPointerDown={(event) => {\n event.currentTarget.setPointerCapture(event.pointerId);\n fromPointer(event);\n }}\n onPointerMove={(event) => {\n if (event.currentTarget.hasPointerCapture(event.pointerId)) fromPointer(event);\n }}\n onPointerUp={(event) => {\n event.currentTarget.releasePointerCapture(event.pointerId);\n onChangeComplete(...fromPointer(event));\n }}\n >\n <span\n className={styles.thumb}\n style={{ left: `${saturation * 100}%`, top: `${(1 - value) * 100}%` }}\n />\n </div>\n );\n },\n);\n\nSaturationArea.displayName = 'ColorPickerSaturationArea';\n\nexport default SaturationArea;\n"],"mappings":";;;;;AAeA,MAAM,SAAS,MAAc,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC;AAE/E,MAAM,iBAAiB,MACpB,EAAE,KAAK,OAAO,UAAU,kBAAkB,YAAY,YAAY;CACjE,MAAM,UAAU,OAAuB,IAAI;CAE3C,MAAM,eAAe,UAA0D;EAC7E,MAAM,OAAO,QAAQ,QAAS,sBAAsB;EACpD,MAAM,OAAyB,CAC7B,OAAO,MAAM,UAAU,KAAK,QAAQ,KAAK,KAAK,GAC9C,MAAM,KAAK,MAAM,UAAU,KAAK,OAAO,KAAK,MAAM,CACpD;EACA,SAAS,GAAG,IAAI;EAChB,OAAO;CACT;CAEA,OACE,oBAAC,OAAD;EACE,cAAY;EACZ,iBAAe;EACf,iBAAe;EACf,iBAAe,KAAK,MAAM,aAAa,GAAG;EAC1C,kBAAgB,cAAc,KAAK,MAAM,aAAa,GAAG,EAAE,gBAAgB,KAAK,MAAM,QAAQ,GAAG,EAAE;EACnG,WAAW,OAAO;EAClB,KAAK;EACL,MAAK;EACL,UAAU;EACV,OAAO,EACL,YAAY,mFAAmF,IAAI,aACrG;EACA,YAAY,UAAU;GACpB,MAAM,QAAQ,MAAM,WAAW,KAAM;GAOrC,MAAM,OAAO;IALX,WAAW,CAAC,GAAG,CAAC,KAAK;IACrB,WAAW,CAAC,CAAC,OAAO,CAAC;IACrB,YAAY,CAAC,OAAO,CAAC;IACrB,SAAS,CAAC,GAAG,KAAK;GAEH,EAAE,MAAM;GACzB,IAAI,CAAC,MAAM;GACX,MAAM,eAAe;GACrB,MAAM,OAAyB,CAAC,MAAM,aAAa,KAAK,EAAE,GAAG,MAAM,QAAQ,KAAK,EAAE,CAAC;GACnF,SAAS,GAAG,IAAI;GAChB,iBAAiB,GAAG,IAAI;EAC1B;EACA,gBAAgB,UAAU;GACxB,MAAM,cAAc,kBAAkB,MAAM,SAAS;GACrD,YAAY,KAAK;EACnB;EACA,gBAAgB,UAAU;GACxB,IAAI,MAAM,cAAc,kBAAkB,MAAM,SAAS,GAAG,YAAY,KAAK;EAC/E;EACA,cAAc,UAAU;GACtB,MAAM,cAAc,sBAAsB,MAAM,SAAS;GACzD,iBAAiB,GAAG,YAAY,KAAK,CAAC;EACxC;EAEA,UAAA,oBAAC,QAAD;GACE,WAAW,OAAO;GAClB,OAAO;IAAE,MAAM,GAAG,aAAa,IAAI;IAAI,KAAK,IAAI,IAAI,SAAS,IAAI;GAAG;EACrE,CAAA;CACE,CAAA;AAET,CACF;AAEA,eAAe,cAAc"}