a tool for shared writing and social publishing
at update/thread-viewer 162 lines 5.6 kB view raw
1"use client"; 2 3import { 4 ColorPicker as SpectrumColorPicker, 5 parseColor, 6 Color, 7 ColorArea, 8 ColorThumb, 9 ColorSlider, 10 Input, 11 ColorField, 12 SliderTrack, 13 ColorSwatch, 14} from "react-aria-components"; 15import { pickers } from "../ThemeSetter"; 16import { Separator } from "components/Layout"; 17import { onMouseDown } from "src/utils/iosInputMouseDown"; 18 19export let thumbStyle = 20 "w-4 h-4 rounded-full border-2 border-white shadow-[0_0_0_1px_#8C8C8C,inset_0_0_0_1px_#8C8C8C]"; 21 22export const ColorPicker = (props: { 23 label?: string; 24 helpText?: string; 25 value: Color | undefined; 26 alpha?: boolean; 27 image?: boolean; 28 setValue: (c: Color) => void; 29 openPicker: pickers; 30 thisPicker: pickers; 31 setOpenPicker: (thisPicker: pickers) => void; 32 closePicker: () => void; 33 disabled?: boolean; 34 children?: React.ReactNode; 35}) => { 36 return ( 37 <SpectrumColorPicker value={props.value} onChange={props.setValue}> 38 <div className="flex flex-col w-full gap-2"> 39 <div className="colorPickerLabel flex gap-2 items-center "> 40 <button 41 disabled={props.disabled} 42 className="flex gap-2 items-center disabled:text-tertiary" 43 onClick={() => { 44 if (props.openPicker === props.thisPicker) { 45 props.setOpenPicker("null"); 46 } else { 47 props.setOpenPicker(props.thisPicker); 48 } 49 }} 50 > 51 <ColorSwatch 52 color={props.value} 53 className={`w-6 h-6 rounded-full border-2 border-white shadow-[0_0_0_1px_#8C8C8C] ${props.disabled ? "opacity-50" : ""}`} 54 style={{ 55 backgroundSize: "cover", 56 }} 57 /> 58 <strong className="w-max">{props.label}</strong> 59 </button> 60 61 <div className="flex gap-1"> 62 {props.value === undefined ? ( 63 <div>default</div> 64 ) : props.disabled ? ( 65 <div className="text-tertiary italic">hidden</div> 66 ) : ( 67 <ColorField className="w-fit gap-1"> 68 <Input 69 onMouseDown={onMouseDown} 70 onFocus={(e) => { 71 e.currentTarget.setSelectionRange( 72 1, 73 e.currentTarget.value.length, 74 ); 75 }} 76 onKeyDown={(e) => { 77 if (e.key === "Enter") { 78 e.currentTarget.blur(); 79 } else return; 80 }} 81 onBlur={(e) => { 82 props.setValue(parseColor(e.currentTarget.value)); 83 }} 84 className="w-[72px] bg-transparent outline-hidden disabled:text-tertiary" 85 /> 86 </ColorField> 87 )} 88 {props.alpha && !props.disabled && ( 89 <> 90 <Separator classname="my-1" /> 91 <ColorField 92 className={`w-[48px] pl-[6px] ${props.disabled ? "opacity-50" : ""}`} 93 channel="alpha" 94 > 95 <Input 96 disabled={props.disabled} 97 onMouseDown={onMouseDown} 98 onFocus={(e) => { 99 e.currentTarget.setSelectionRange( 100 0, 101 e.currentTarget.value.length - 1, 102 ); 103 }} 104 onKeyDown={(e) => { 105 if (e.key === "Enter") { 106 e.currentTarget.blur(); 107 } else return; 108 }} 109 className="w-[72px] bg-transparent outline-hidden " 110 /> 111 </ColorField> 112 </> 113 )} 114 </div> 115 </div> 116 {props.openPicker === props.thisPicker && ( 117 <div className="w-full flex flex-col gap-2 px-1 pb-2"> 118 { 119 <> 120 {props.helpText && ( 121 <div className="text-sm leading-tight text-tertiary pl-7 -mt-2.5"> 122 {props.helpText} 123 </div> 124 )} 125 <ColorArea 126 className="w-full h-[128px] rounded-md" 127 colorSpace="hsb" 128 xChannel="saturation" 129 yChannel="brightness" 130 > 131 <ColorThumb className={thumbStyle} /> 132 </ColorArea> 133 <ColorSlider colorSpace="hsb" className="w-full" channel="hue"> 134 <SliderTrack className="h-2 w-full rounded-md"> 135 <ColorThumb className={`${thumbStyle} mt-[4px]`} /> 136 </SliderTrack> 137 </ColorSlider> 138 {props.alpha && ( 139 <ColorSlider 140 colorSpace="hsb" 141 className="w-full mt-1 rounded-full" 142 style={{ 143 backgroundImage: `url(/transparent-bg.png)`, 144 backgroundRepeat: "repeat", 145 backgroundSize: "8px", 146 }} 147 channel="alpha" 148 > 149 <SliderTrack className="h-2 w-full rounded-md"> 150 <ColorThumb className={`${thumbStyle} mt-[4px]`} /> 151 </SliderTrack> 152 </ColorSlider> 153 )} 154 {props.children} 155 </> 156 } 157 </div> 158 )} 159 </div> 160 </SpectrumColorPicker> 161 ); 162};