GithubHelp home page GithubHelp logo

ricokahler / color2k Goto Github PK

View Code? Open in Web Editor NEW
589.0 6.0 11.0 3.09 MB

a color parsing and manipulation lib served in roughly 2kB

Home Page: https://color2k.com

License: MIT License

JavaScript 4.25% TypeScript 91.02% CSS 4.54% Shell 0.20%
color-manipulation color color-parser css-in-js polished tinycolor chroma-js

color2k's Introduction

Donate to the ACLU | Shutdown ICE


Hi there 👋😄,

My name is Rico Kahler (he/him) and I build consumer-facing websites and apps as well as developer-facing tools.

I care deeply about UX, DX, performance, a11y, and SEO. I specialize in the tooling + React space and also work with serverless architectures and infrastructures using platforms like Vercel and frameworks like Serverless.

Most of my open source these days revolves around Next.js and Sanity.

Checkout my projects 👇 or say hi if you feel like it.

💛 JavaScript

✔️ Next.js

🌶 Sanity

💻 Apps

⚛️ React

  • hacker-ui — a work-in-progress component library
  • flair — a work-in-progress CSS-in-JS lib for React
  • hocify — converts hooks to HOCs for compatibility with class-based components.
  • react-mounting-transition — helps you add transitions to components you dynamically mount to the DOM

color2k's People

Contributors

delucis avatar dependabot[bot] avatar diondiondion avatar ljharb avatar myndex avatar okikio avatar renovate-bot avatar renovate[bot] avatar ricokahler avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

color2k's Issues

Put color2k in scope at color2k.com

Hi 👋 — good lib!

A suggestion: did you know... you can go to the momentjs website, open the debug console and play with moment() and all its facets? The same is true on the lodash website!

This is very handy! I was hoping to play with color2k in-situ, but no go. The code sandbox is, honestly, a convoluted bridge too far, and takes the user away from the best sandbox, a console sesh using your own site.

Example from the console when I'm on the Lodash website:

2020-05-17_16-58-32

SSR and Compile Time

First off, wanted to say that I love the creative approach here. Also, glad to hear that polished help inspire this work. Obviously the size difference has our interest piqued, but had some initial questions about the approach:

  1. Being unfamiliar with the intricacies of how canvas interacts with the DOM, any limitations with this approach when using SSR rendering?
  2. In polished, folks tend to either use our babel-plugin or others that preval functions where possible to remove the runtime impact and reduce bundle size. Given the canvas approach, I imagine there would need to be a custom plugin to render the canvas and do the work to precompile?

IE11 browser support

I just realised that color2k doesn't work in IE11 out of the box. 😭

It throws a syntax error when encountering the first line of this bit of code:

class ColorError extends Error {
constructor(color: string) {
super(`Failed to parse color: "${color}"`);
}
}

It would've been great if that was mentioned somewhere on the website or in the docs. I'm also wondering if this is the only incompatible part of the code, and if so, would you be happy to let Babel compile it for IE11? Not sure if that would cause a substantial increase in bundle size.

`mix` returns `NaN` values at extremes with fully transparent colors

When using the mix function with a colour that is fully transparent, it returns a value of "rgba(NaN, NaN, NaN, 0)" if the weight is fully at the transparent end of the two colors. Some examples:

// Not OK — these all return "rgba(NaN, NaN, NaN, 0)"
mix('red', 'transparent', 1);
mix('transparent', 'red', 0);
mix('rgba(0, 0, 0, 0)', 'red', 0);
mix('red', 'rgba(0, 0, 0, 0)', 1);

As soon as the colour is not fully transparent, or the weight is not at the extreme end of its range, the values are valid.

// OK
mix('rgba(0, 0, 0, 0.01)', 'red', 0); // "rgba(0, 0, 0, 0.01)"
mix('transparent', 'red', 0.01); // "rgba(255, 0, 0, 0.01)"

Curiously, the even edgier case of a transparent–transparent gradient works fine:

// Also OK
mix('transparent', 'transparent', 0); // "rgba(0, 0, 0, 0)"

I’m guessing there’s a divide by zero error somewhere maybe.

Bundle size: SSR w/ getComputedStyle

This lib used to be around 1.5kB in size because it deferred parsing colors to getComputedStyle instead of relying on javascript. This saves around 1kB because we can remove the compressed color map of named colors.

This implementation was removed in favor of a plain JS implementation because getComputedStyle does not work in SSR environments and attempts for conditionally imports did not pan out.

This issue exists to find a code path that works for both SSR and non-SSR environments and removes the named color map to get us back down to 2k

Package maintenance: semantic-release and microbundle

Some TODO items for myself

  • use semantic-release for auto-publishing
  • update renovate config to update on a bi-weekly or monthly cadence (evergreen is too much)
  • use microbundle to manage bundles

In particular, switching to microbundle would help us get the package score up on skypack and just keep up with bundling trends in general.

Would close #318 as well.

Non-sRGB/wide-gamut color spaces support

I got a question about whether or not this lib will support non-sRGB color spaces and I want to dedicate a GitHub issue to this for future reference in the readme.

The short answer is no 😅

To clarify: this issue is discussing whether or not this lib will support more colors than the current rbga 0 - 255 color gamut. This is also known as wide-gamut. This is different from color models (like CMYK etc).


The long answer is that support for non-sRGB color spaces is highly dependent on browser support for non-sRGB color spaces. In particular, because we parse colors using canvas, canvas itself must provide a way to get the color in a non-sRGB space. There are proposals on how this might work e.g.

// NOTE: Proposed syntax. Not yet implemented.
canvas.getContext("2d", { colorSpace: "p3" });

but (afaik), there is still no way to pull non-sRGB colors from canvas. Currently we use getImageData to pull the value of the color. ImageData.data only provides a Uint8ClampedArray with values between 0 and 255 inclusive (sRGB space).

Until we get those APIs, adding support for wide-gamut is blocked. Even when the support does come, it'll be a challenge to figure out how to integrate that color space in alongside sRGB while also keeping the bundle size down.

That's particularly challenging because this lib only supports two color models (i.e. rgba and hsla) to reduce branching in code. Wide gamut would support would definitely require supporting another color model and rgba and hsla probably won't be compatible with wide-gamut color spaces.


Edit: The implementation was switched to getComputedStyle which is faster however the limitations above mostly still apply.

Doesn't work on node 6

(v1.2.0, of course, has "main" as a TS file, so it breaks everywhere) v1.2.1 breaks on node 6 with a syntax error, which is a breaking change in a minor version. I think perhaps you're using exponentiation (a ** b) when Math.pow(a, b) would serve.

Additionally, v1.0.0+ uses .padStart, which is unavailable in node 6 - you can use https://npmjs.com/string.prototype.padstart for this.

Please fix this ASAP, so react-dates can continue depending on this package. I'll be happy to make a PR.

toHex sometimes returns the wrong color

The 2 specific examples I've seen are:

// #b00020 is a red
toHex(darken('#b00020', 0.2)) // returns #4d00e0 (a purple) instead of #7D0000
// this one seems to just switch the first 2 numbers
toHex('#03dac5') // returns #30dac5

I got the correct values from this tool. Here is a stackblitz where you can see the issue.

For the first one, if you drop the darkening factor to 0.18, it returns a red.

This may be related somehow to #211

Release candidate feedback

The latest version of color2k is marked as a release candidate so we can collect feedback and let it stabilize for a bit. I don't foresee any API changes during this time but just in case, here's an issue to collect small feedback items.

Also feel free to open up a new issue if you'd like to discuss something bigger in detail.

If all is silent, I'll probably slap the 1.0 about a month from now. (June 11th).

Node 6 Compatibility Suite / Migrate to `tape`

When version 1 of this lib was released, it (unknowingly) supported Node 6. See #351 for context.

Long story short, there should be some CI in place to ensure that this lib will continue supporting Node 6 in the future.

I need some help getting that done via Github actions. Any takers?

Bundled outputs

I recently adopted microbundle for this lib but I think I want to re-evaluate that decision. In the effort of compatibility and control, we'll be going back to manual rollup builds with the following entry points.

{
  "main": "./index.js",      // CJS ES5 compatible bundle
  "module": "./index.es.js", // ESM ES2017 compatible bundle
  "exports": {
    // see here: https://nodejs.org/api/packages.html#packages_conditional_exports
    "import": "./index.mjs", // ESM ES2017 compatible bundle
    "default": "./index.js", // same CJS ES5 compatible bundle
  }
}

There's still some details TBD but the goal is to have legacy compatibility while still not compromising on bundle size.

Additionally, I may explore some CI that generates a bundle size for each export.

cc @ljharb

Add compose-like chain function?

Polished and chroma have APIs that let these functions be chained together to do many color manipulation operations on one color.

chroma-js uses objects

chroma('pink').darken().saturate(2).hex()

and polished js API curries every function so that you can compose them

import { compose } from 'ramda' // Replace with any compose() function of your choice
import { lighten, desaturate } from 'polished'

// Create tone() helper
const tone = compose(lighten(0.1), desaturate(0.1))

Here's the ask/question:

If you've used those libs before: How often have you chain together multiple color functions together? Is it a use-case that this lib should provide some code for?

Please upvote 👍 or comment to provide feedback.

I have a PR that implements this with minimal code, I'm just wondering if people will use it.

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: Cannot find preset's package (github>whitesource/merge-confidence:beta)

Documentation improvements (hasBadContrast, opacify, transparentize)

Hi Rico, thanks for creating this library, great work! I'm currently in the process of migrating to color2k from chromaJS and the process has been very smooth.

Some parts of the documentation confused me, though:

  1. opacify, transparentize:
    The description of the amount parameter seems to have been copied & pasted from the darken function, should probably be changed to "the amount to increase the opacity/transparency by, given as a decimal between 0 and 1"
  2. hasBadContrast:
    Here it's more the function API that's confusing me, and the documentation didn't help much. How can a single colour have bad contrast; what's the "background colour"? (I just checked out the implementation, apparently it's white! 😅 )
    It would be useful to clarify this in the docs. It also seems to me like the function would be much more useful with a third parameter to specify the base colour, but luckily it's easy enough to write your own wrapper around getContrast.

Thanks for reading :)

Closed form for darken

color2k's darken lowers the lightness of a color until its brightness is lowered by the given amount:

function darken(color: string, amount: number): string {
if (amount === 0) return color;
const originalBrightness = getBrightness(color);
let currentBrightness = originalBrightness;
let currentColor = color;
while (Math.abs(currentBrightness - originalBrightness) < Math.abs(amount)) {
const direction = amount > 0 ? 1 : -1;
currentColor = lightnessDarken(currentColor, direction * step);
currentBrightness = getBrightness(currentColor);
if (currentBrightness <= 0) return '#000';
if (currentBrightness >= 1) return '#fff';
}
return currentColor;
}

I think you can see the issue above — it's implemented using a while loop which isn't too great.

This issue exists for someone to create a closed form for darken which just means to create a version of this function that doesn't use the loop. My brain can't do the math lol


For more context, darken in color2k is different from most darken implementations. We have this metric of "brightness" which is equal to:

function getBrightness(color: string): number {
return Math.pow(getLuminance(color), 0.5);
}

It's derived from Steven's Power Law for brightness where n is 0.5

image

IsDark and isLight support? I can not find

Maybe it will work for your project ...

import { parseToRgba } from "color2k";

const isDark = (color: string) => {
  let rgb = parseToRgba(color);
  let yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000;
  return yiq < 128;
}

Color conversion problem

Version: 2.0.0,

Problem: Try to convert a hex to HSLA and back to hex. The expected result is the same hex. (Currently, it's different)
This comes from the hsla function. It uses toFixed() and it loses the correct value. I think it shouldn't round the values.

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Awaiting Schedule

These updates are awaiting their schedule. Click on a checkbox to get an update now.

  • chore(deps): update all (babel-plugin-module-resolver, preact)
  • chore(deps): update babel monorepo (@babel/core, @babel/eslint-parser, @babel/node, @babel/preset-env, @babel/preset-react, @babel/preset-typescript, @babel/register)
  • chore(deps): update react monorepo to v18.3.0 (@types/react, @types/react-dom, react, react-dom)
  • chore(deps): update all (major) (@rollup/plugin-alias, @sanity/eslint-config-studio, actions/checkout, actions/setup-node, codecov/codecov-action, cssnano, eslint, preact-render-to-string, prettier, rollup, typescript)
  • chore(deps): update dependency semantic-release to v23

Detected dependencies

github-actions
.github/workflows/release.yml
  • actions/checkout v3
  • actions/setup-node v3
  • codecov/codecov-action v3
.github/workflows/test.yml
  • actions/checkout v3
  • actions/setup-node v3
  • codecov/codecov-action v3
npm
package.json
  • @babel/core 7.22.11
  • @babel/node 7.22.10
  • @babel/preset-env 7.22.14
  • @babel/preset-react 7.22.5
  • @babel/preset-typescript 7.22.11
  • @babel/register 7.22.5
  • @rollup/plugin-alias 4.0.4
  • @rollup/plugin-babel 6.0.4
  • @rollup/plugin-node-resolve 15.2.3
  • @rollup/plugin-terser 0.4.4
  • @sanity/eslint-config-studio 2.0.4
  • @types/jest 29.5.12
  • @types/react 18.2.73
  • @types/react-dom 18.2.23
  • @types/showdown 2.0.6
  • autoprefixer 10.4.19
  • @babel/eslint-parser 7.22.11
  • babel-plugin-module-resolver 5.0.0
  • cssnano 5.1.15
  • eslint 8.57.0
  • jest 29.7.0
  • postcss 8.4.38
  • preact 10.20.1
  • preact-render-to-string 5.2.6
  • prettier 2.8.8
  • react 18.2.0
  • react-dom 18.2.0
  • rollup 3.29.4
  • semantic-release 19.0.5
  • showdown 2.1.0
  • typescript 4.9.5
nvm
.nvmrc

  • Check this box to trigger a request for Renovate to run again on this repository

[Feature] Invert color

Thanks for the great library! This may be easily done with the provided API but it would be nice to be able to invert a color.

[newFeature] getDifferenceColor

Hi there,

Would be great to have a library where we could first check the difference between 2 colors.

Let say: ('#EDF0FC', '#B2C3F9'), that would generate a value or object where we could then pass to another function that would have the new color let say we pass the same ('#EDF0FC'), it should return the "#B2C3F9" color;

If we pass: '#1CA085' it should return '#007382'. So basically we would have the same difference applied to a new color.
With that in mind, with 1 single color I can calculate many others variations automatically.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.