Skip to content

Commit

Permalink
🦊 hue bug, issue: #79
Browse files Browse the repository at this point in the history
  • Loading branch information
hxf31891 committed Jan 31, 2024
1 parent bf38dff commit bd8bdff
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 89 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-best-gradient-color-picker",
"version": "3.0.2",
"version": "3.0.3",
"description": "An easy to use color/gradient picker for React.js",
"type": "module",
"sideEffects": [
Expand Down
14 changes: 7 additions & 7 deletions src/components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,17 @@ export function ColorPicker({
const [bounds, setBounds] = useState({})
const safeValue = objectToString(value)

document
?.getElementsByTagName('head')[0]
?.insertAdjacentHTML(
'beforeend',
'<link rel="stylesheet" href="https://gradient-package-demo.web.app/packagestyles.css" />'
)

useEffect(() => {
if (contRef && contRef?.current) {
setBounds(contRef?.current?.getBoundingClientRect())
}

document
?.getElementsByTagName('head')[0]
?.insertAdjacentHTML(
'beforeend',
'<link rel="stylesheet" href="https://gradient-package-demo.web.app/packagestyles.css" />'
)
}, [])

return (
Expand Down
4 changes: 4 additions & 0 deletions src/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ export default function PickerContextWrapper({
setTinyColor(tinycolor(currentColor))
}, [currentColor])

useEffect(() => {
setInternalHue(hue)
}, [hue])

const createGradientStr = (newColors: GradientProps[]) => {
const sorted = newColors.sort(
(a: GradientProps, b: GradientProps) => a.left - b.left
Expand Down
117 changes: 69 additions & 48 deletions src/hooks/useColorPicker.js → src/hooks/useColorPicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ import { low, high, getColors, formatInputValues } from '../utils/formatters.js'
import { rgb2cmyk } from '../utils/converters.js'
import { config } from '../constants.js'
import tc from 'tinycolor2'
import { ColorsProps, GradientProps } from '../shared/types.js'

const { defaultColor, defaultGradient } = config

export const useColorPicker = (value, onChange) => {
export const useColorPicker = (
value: string,
onChange: (arg0: string) => void
) => {
// if (!value || !onChange) {
// console.log(
// 'RBGCP ERROR - YOU MUST PASS A VALUE AND CALLBACK TO THE useColorPicker HOOK'
Expand All @@ -20,9 +24,13 @@ export const useColorPicker = (value, onChange) => {
const degreeStr =
gradientType === 'linear-gradient' ? `${degrees}deg` : 'circle'
const colors = getColors(value)
const indexedColors = colors?.map((c, i) => ({ ...c, index: i }))
const indexedColors = colors?.map((c: ColorsProps, i: number) => ({
...c,
index: i,
}))
const currentColorObj =
indexedColors?.filter((c) => isUpperCase(c.value))[0] || indexedColors[0]
indexedColors?.filter((c: ColorsProps) => isUpperCase(c.value))[0] ||
indexedColors[0]
const currentColor = currentColorObj?.value
const selectedPoint = currentColorObj?.index
const currentLeft = currentColorObj?.left
Expand All @@ -35,14 +43,20 @@ export const useColorPicker = (value, onChange) => {
isGradient: true,
gradientType: gradientType,
degrees: degreeStr,
colors: colors?.map((c) => ({ ...c, value: c.value?.toLowerCase() })),
colors: colors?.map((c: ColorsProps) => ({
...c,
value: c.value?.toLowerCase(),
})),
}
} else {
return {
isGradient: false,
gradientType: null,
degrees: null,
colors: colors?.map((c) => ({ ...c, value: c.value?.toLowerCase() })),
colors: colors?.map((c: ColorsProps) => ({
...c,
value: c.value?.toLowerCase(),
})),
}
}
} else {
Expand All @@ -58,6 +72,7 @@ export const useColorPicker = (value, onChange) => {

useEffect(() => {
if (tc(currentColor)?.isValid() && previousColors[0] !== currentColor) {
// @ts-expect-error - currentColor type issue
setPreviousColors([currentColor, ...previousColors.slice(0, 19)])
}
}, [currentColor, previousColors])
Expand All @@ -72,7 +87,7 @@ export const useColorPicker = (value, onChange) => {
onChange(`radial-gradient(circle, ${remaining}`)
}

const setDegrees = (newDegrees) => {
const setDegrees = (newDegrees: number) => {
const remaining = value.split(/,(.+)/)[1]
onChange(
`linear-gradient(${formatInputValues(
Expand All @@ -88,78 +103,82 @@ export const useColorPicker = (value, onChange) => {
}
}

const setSolid = (startingColor) => {
let newValue = startingColor || defaultColor
const setSolid = (startingColor: string) => {
const newValue = startingColor || defaultColor
onChange(newValue)
}

const setGradient = (startingGradiant) => {
let newValue = startingGradiant || defaultGradient
const setGradient = (startingGradiant: string) => {
const newValue = startingGradiant || defaultGradient
onChange(newValue)
}

const createGradientStr = (newColors) => {
let sorted = newColors.sort((a, b) => a.left - b.left)
let colorString = sorted?.map((cc) => `${cc?.value} ${cc.left}%`)
const createGradientStr = (newColors: GradientProps[]) => {
const sorted = newColors.sort(
(a: GradientProps, b: GradientProps) => a.left - b.left
)
const colorString = sorted?.map(
(cc: ColorsProps) => `${cc?.value} ${cc.left}%`
)
onChange(`${gradientType}(${degreeStr}, ${colorString.join(', ')})`)
}

const handleGradient = (newColor, left = currentLeft) => {
let remaining = colors?.filter((c) => !isUpperCase(c.value))
let newColors = [
{ value: newColor.toUpperCase(), left: left },
const handleGradient = (newColor: string, left?: number) => {
const remaining = colors?.filter((c: ColorsProps) => !isUpperCase(c.value))
const newColors = [
{ value: newColor.toUpperCase(), left: left || currentLeft },
...remaining,
]
createGradientStr(newColors)
}

const handleChange = (newColor) => {
const handleChange = (newColor: string) => {
if (isGradient) {
handleGradient(newColor)
} else {
onChange(newColor)
}
}

const setR = (newR) => {
let newVal = formatInputValues(newR, 0, 255)
const setR = (newR: number) => {
const newVal = formatInputValues(newR, 0, 255)
handleChange(`rgba(${newVal}, ${g}, ${b}, ${a})`)
}

const setG = (newG) => {
let newVal = formatInputValues(newG, 0, 255)
const setG = (newG: number) => {
const newVal = formatInputValues(newG, 0, 255)
handleChange(`rgba(${r}, ${newVal}, ${b}, ${a})`)
}

const setB = (newB) => {
let newVal = formatInputValues(newB, 0, 255)
const setB = (newB: number) => {
const newVal = formatInputValues(newB, 0, 255)
handleChange(`rgba(${r}, ${g}, ${newVal}, ${a})`)
}

const setA = (newA) => {
let newVal = formatInputValues(newA, 0, 100)
const setA = (newA: number) => {
const newVal = formatInputValues(newA, 0, 100)
handleChange(`rgba(${r}, ${g}, ${b}, ${newVal / 100})`)
}

const setHue = (newHue) => {
let newVal = formatInputValues(newHue, 0, 360)
let tinyNew = tc({ h: newVal, s: s, l: l })
let { r, g, b } = tinyNew.toRgb()
const setHue = (newHue: number) => {
const newVal = formatInputValues(newHue, 0, 360)
const tinyNew = tc({ h: newVal, s: s, l: l })
const { r, g, b } = tinyNew.toRgb()
handleChange(`rgba(${r}, ${g}, ${b}, ${a})`)
}

const setSaturation = (newSat) => {
let newVal = formatInputValues(newSat, 0, 100)
let tinyNew = tc({ h: h, s: newVal / 100, l: l })
let { r, g, b } = tinyNew.toRgb()
const setSaturation = (newSat: number) => {
const newVal = formatInputValues(newSat, 0, 100)
const tinyNew = tc({ h: h, s: newVal / 100, l: l })
const { r, g, b } = tinyNew.toRgb()
handleChange(`rgba(${r}, ${g}, ${b}, ${a})`)
}

const setLightness = (newLight) => {
let newVal = formatInputValues(newLight, 0, 100)
let tinyNew = tc({ h: h, s: s, l: newVal / 100 })
const setLightness = (newLight: number) => {
const newVal = formatInputValues(newLight, 0, 100)
const tinyNew = tc({ h: h, s: s, l: newVal / 100 })
if (tinyNew?.isValid()) {
let { r, g, b } = tinyNew.toRgb()
const { r, g, b } = tinyNew.toRgb()
handleChange(`rgba(${r}, ${g}, ${b}, ${a})`)
} else {
console.log(
Expand All @@ -181,13 +200,13 @@ export const useColorPicker = (value, onChange) => {
}

const valueToCmyk = () => {
let { c, m, y, k } = rgb2cmyk(r, g, b)
const { c, m, y, k } = rgb2cmyk(r, g, b)
return `cmyk(${c}, ${m}, ${y}, ${k})`
}

const setSelectedPoint = (index) => {
const setSelectedPoint = (index: number) => {
if (isGradient) {
let newGradStr = colors?.map((cc, i) => ({
const newGradStr = colors?.map((cc: GradientProps, i: number) => ({
...cc,
value: i === index ? high(cc) : low(cc),
}))
Expand All @@ -199,9 +218,9 @@ export const useColorPicker = (value, onChange) => {
}
}

const addPoint = (left) => {
let newColors = [
...colors.map((c) => ({ ...c, value: low(c) })),
const addPoint = (left: number) => {
const newColors = [
...colors.map((c: GradientProps) => ({ ...c, value: low(c) })),
{ value: currentColor, left: left },
]
createGradientStr(newColors)
Expand All @@ -212,10 +231,12 @@ export const useColorPicker = (value, onChange) => {
}
}

const deletePoint = (index) => {
const deletePoint = (index: number) => {
if (colors?.length > 2) {
let pointToDelete = index || selectedPoint
let remaining = colors?.filter((rc, i) => i !== pointToDelete)
const pointToDelete = index || selectedPoint
const remaining = colors?.filter(
(rc: ColorsProps, i: number) => i !== pointToDelete
)
createGradientStr(remaining)
if (!index) {
console.log(
Expand All @@ -229,7 +250,7 @@ export const useColorPicker = (value, onChange) => {
}
}

const setPointLeft = (left) => {
const setPointLeft = (left: number) => {
handleGradient(currentColor, formatInputValues(left, 0, 100))
}

Expand Down
44 changes: 32 additions & 12 deletions src/hooks/usePaintHue.js → src/hooks/usePaintHue.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,33 @@
import { useEffect } from 'react'
import { useEffect, RefObject } from 'react'
import tinycolor from 'tinycolor2'

const usePaintHue = (canvas, squareSize) => {
const usePaintHue = (
canvas: RefObject<HTMLCanvasElement>,
squareSize: number
) => {
useEffect(() => {
const ctx = canvas?.current?.getContext('2d', { willReadFrequently: true })
ctx.rect(0, 0, squareSize, 14)
if (ctx) {
ctx.rect(0, 0, squareSize, 14)

const gradient = ctx.createLinearGradient(0, 0, squareSize, 0)
for (let i = 0; i <= 360; i += 30) {
gradient.addColorStop(i / 360, `hsl(${i}, 100%, 50%)`)
const gradient = ctx.createLinearGradient(0, 0, squareSize, 0)
for (let i = 0; i <= 360; i += 30) {
gradient.addColorStop(i / 360, `hsl(${i}, 100%, 50%)`)
}
ctx.fillStyle = gradient
ctx.fill()
}
ctx.fillStyle = gradient
ctx.fill()
}, [canvas, squareSize])
}

export default usePaintHue

export const usePaintSat = (canvas, h, l, squareSize) => {
export const usePaintSat = (
canvas: RefObject<HTMLCanvasElement>,
h: number,
l: number,
squareSize: number
) => {
useEffect(() => {
const ctx = canvas?.current?.getContext('2d', { willReadFrequently: true })
if (ctx) {
Expand All @@ -33,7 +43,12 @@ export const usePaintSat = (canvas, h, l, squareSize) => {
}, [canvas, h, l, squareSize])
}

export const usePaintLight = (canvas, h, s, squareSize) => {
export const usePaintLight = (
canvas: RefObject<HTMLCanvasElement>,
h: number,
s: number,
squareSize: number
) => {
useEffect(() => {
const ctx = canvas?.current?.getContext('2d', { willReadFrequently: true })
if (ctx) {
Expand All @@ -49,15 +64,20 @@ export const usePaintLight = (canvas, h, s, squareSize) => {
}, [canvas, h, s, squareSize])
}

export const usePaintBright = (canvas, h, s, squareSize) => {
export const usePaintBright = (
canvas: RefObject<HTMLCanvasElement>,
h: number,
s: number,
squareSize: number
) => {
useEffect(() => {
const ctx = canvas?.current?.getContext('2d', { willReadFrequently: true })
if (ctx) {
ctx.rect(0, 0, squareSize, 14)

const gradient = ctx.createLinearGradient(0, 0, squareSize, 0)
for (let i = 0; i <= 100; i += 10) {
let hsl = tinycolor({ h: h, s: s, v: i })
const hsl = tinycolor({ h: h, s: s, v: i })
gradient.addColorStop(i / 100, hsl.toHslString())
}
ctx.fillStyle = gradient
Expand Down
21 changes: 0 additions & 21 deletions src/hooks/usePaintSquare.js

This file was deleted.

Loading

0 comments on commit bd8bdff

Please sign in to comment.