Pure JS, shortest
Try this (more: hsv2rgb, rgb2hsl, hsl2rgb and sl22sv):
// input: r,g,b in [0,1], out: h in [0,360) and s,v in [0,1]
function rgb2hsv(r,g,b) {
let v=Math.max(r,g,b), c=v-Math.min(r,g,b);
let h= c && ((v==r) ? (g-b)/c : ((v==g) ? 2+(b-r)/c : 4+(r-g)/c));
return [60*(h<0?h+6:h), v&&c/v, v];
}
function rgb2hsv(r,g,b) {
let v=Math.max(r,g,b), c=v-Math.min(r,g,b);
let h= c && ((v==r) ? (g-b)/c : ((v==g) ? 2+(b-r)/c : 4+(r-g)/c));
return [60*(h<0?h+6:h), v&&c/v, v];
}
console.log(`rgb: (0.5,0.2,0.3) --> hsv: (${rgb2hsv(0.5,0.2,0.3)})`)
// ---------------
// UX
// ---------------
rgb= [0,0,0];
hs= [0,0,0];
let $ = x => document.querySelector(x);
let c = (x,s) => $(x).style.backgroundColor=s;
let hsv2rgb = (h,s,v, f= (n,k=(n+h/60)%6) => v - v*s*Math.max( Math.min(k,4-k,1), 0)) => [f(5),f(3),f(1)];
function changeRGB(i,e) {
rgb[i]=e.target.value/255;
hs = rgb2hsv(...rgb);
refresh();
}
function changeHS(i,e) {
hs[i]=e.target.value/(i?255:1);
rgb= hsv2rgb(...hs);
refresh();
}
function refresh() {
rr = rgb.map(x=>x*255|0).join(', ')
tr = `RGB: ${rr}`
th = `HSV: ${hs.map((x,i)=>i? (x*100).toFixed(2)+'%':x|0).join(', ')}`
$('.box').style.backgroundColor=`rgb(${rr})`;
$('.infoRGB').innerHTML=`${tr}`;
$('.infoHS').innerHTML =`${th}`;
$('#r').value=rgb[0]*255;
$('#g').value=rgb[1]*255;
$('#b').value=rgb[2]*255;
$('#h').value=hs[0];
$('#s').value=hs[1]*255;
$('#v').value=hs[2]*255;
}
refresh();
.box {
width: 50px;
height: 50px;
margin: 20px;
}
body {
display: flex;
}
This based on this formulas wiki - I made error analysis to show that results are correct