contrast-color icon indicating copy to clipboard operation
contrast-color copied to clipboard

TypeError: Cannot set property 'namedColors' of undefined

Open felixakiragreen opened this issue 4 years ago • 11 comments

When I try to use this lib, I get that error: TypeError: Cannot set property 'namedColors' of undefined (Regardless of whether I use the class or static method)

I can fix it by changing https://github.com/busterc/contrast-color/blob/main/lib/index.js#L211-L220 to:

function contrastColor({
  bgColor = '#FFFFFF',
  fgDarkColor = '#000000',
  fgLightColor = '#FFFFFF',
  defaultColor = '#000000',
  threshold = 128,
  customNamedColors = {},
} = {}) {
  const namedColors = { ...NAMED_COLORS, ...customNamedColors }

  const [
    namedBgColor,
    namedFgDarkColor,
    namedFgLightColor,
    namedDefaultColor,
  ] = [bgColor, fgDarkColor, fgLightColor, defaultColor].map(
    (p) => namedColors[p],
  )

(I'm just not calling this inside a function)

felixakiragreen avatar Apr 26 '21 18:04 felixakiragreen

I am also seeing this error. @busterc can we expect a new version fixing this?

steveoh avatar Jun 06 '22 23:06 steveoh

Hmm.. the tests don't fail and have 100% coverage. Can you attach a sample that is breaking?

busterc avatar Jun 07 '22 00:06 busterc

https://stackblitz.com/edit/vitejs-vite-s2thdh is a pretty simple example that shows the failure.

steveoh avatar Jun 07 '22 00:06 steveoh

What do you think about that sample @busterc

steveoh avatar Jun 07 '22 16:06 steveoh

I have the same error when importing the function in a TypeScript Angular application. There is another workaround I would like to add for those facing the same problem:

contrastColor.call({}, { bgColor: '#ffffff' });

This effectively binds an empty object to the this scope before calling the function...

loedeman avatar Jun 22 '22 10:06 loedeman

yah that works for me also @loedeman. It's a work around for now but I still hope @busterc can create a solution that doesn't change the calling api

steveoh avatar Jun 23 '22 00:06 steveoh

Thanks for the insights, I will resolve this when I get the time to find a thorough fix. I believe this is actually an issue with Rollup (and perhaps other bundlers).

busterc avatar Jun 23 '22 01:06 busterc

Thanks for the insights, I will resolve this when I get the time to find a thorough fix. I believe this is actually an issue with Rollup (and perhaps other bundlers).

Interesting thought. My repro is using esbuild and your build is using parcel. Where does rollup come into play?

steveoh avatar Jun 23 '22 02:06 steveoh

@busterc Niche little library you got here! Thank you 😊 But this error is a problem so I ended up just copy/pasting your implementation..

To anyone who can do without the named colours:

const contrastColor = ({
    bgColor = '#FFFFFF',
    fgDarkColor = '#000000',
    fgLightColor = '#FFFFFF',
    defaultColor = '#000000',
    threshold = 128,
} = {}) => {
    const hexChars = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' ]

    let bgColorArray = String(bgColor)
        .toUpperCase()
        .split('')
        .filter(c => hexChars.includes(c))

    switch (bgColorArray.length) {
    case 3:
    case 4:
        bgColorArray = bgColorArray.slice(0, 3).map(c => `${c}${c}`)
        break
    case 6:
    case 8:
        bgColorArray = bgColorArray
            .slice(0, 6)
            .reduce((acc, curr, n, arr) => n % 2 ? [ ...acc, `${arr[n - 1]}${curr}` ] : acc, [])
        break
    default:
        return defaultColor
    }

    const [ r, g, b ] = bgColorArray.map(h => parseInt(h, 16))
    const yiq = (r * 299 + g * 587 + b * 114) / 1000

    return yiq >= threshold ? fgDarkColor : fgLightColor
}

simunic-cz avatar Nov 28 '22 19:11 simunic-cz

Same problem here, when using the library in a Vue component with TypeScript

derwaldgeist avatar Jun 20 '24 19:06 derwaldgeist