Skip to content

Expose way to serialize and parse individual coords and alpha #649

@kleinfreund

Description

@kleinfreund

TL;DR: Expose ways to

  • serialize color coords/alpha
  • parse strings representing individual coords/alpha

Current status

Currently, one can already serialize individual coords with the help of Format and Type:

Demonstration using some extra code to configure the preferred CSS type per coord (e.g. <number> for RGB)
(function () {
	const preferredTypesBySpace = {
		oklab: ['<percentage>', '<number>', '<number>'],
		hsl: ['<number>', '<number>', '<percentage>'],
		srgb: ['<number>', '<number>', '<number>'],
	}

	function getSerializedValues(color) {
		const formatByCoords = color.space.getFormat('default')?.coords ?? []
		const preferredTypes = preferredTypesBySpace[color.space.id]
		return color.coords
			.map((coord, index) => {
				const type = formatByCoords[index].find(({ type }) => type === preferredTypes[index]) ?? formatByCoords[index][0]

				return type.serialize(coord, 5)
			})
	}

	const results = [
		new Color('oklab(88% 0.145 -0.392)'),
		new Color('hsl(270 50% 25%)'),
		new Color('rgb(100% 50% 22.33%)'),
	].map((color) => getSerializedValues(color))
	console.log(results)
	//> [ [ "88%", "0.145", "-0.392" ], [ "270", "50%", "25%" ], [ "255", "127.5", "56.942" ] ]
})()

However, this capability is not available for the alpha channel. One can serialize the alpha channel by hand using something like color.alpha.toPrecision(5).replace(/\.?0+$/, '') (this is just for the sake of illustration and not meant to be equivalent with what colorjs.io does internally), but the problem here is that this side-steps the internal precision logic.

So far, this covers serialization. What the library also handles is parsing. As far as I can tell, this functionality is not available to users for individual coords/alpha but only for complete colors.

Use case

I'm working on a color picker which, among other elements, has one input per coord/channel including alpha of the currently active format (e.g. H, S, L, A for HSL, R, G, B, A for RGB, and so forth). I'm in the process of replacing all the internal logic of the color picker with colorjs.io (saving me a ton of code for color conversions, etc.). This is almost complete, but the last puzzle is the serialization and deserialization between these input elements and my internal logic.

In short, I need to:

  • construct a new Color() from independent HTMLInputElements for internal storage
  • output that Color to those independent HTMLInputElements

Workarounds

  • Serialization: custom implementation for alpha
  • Parsing: trying to construct a CSS color out of the HTMLInputElements first and then letting new Color() parse it

I'm not a huge fan of these workarounds because it gives me little control over how I can react to partial/incomplete inputs (e.g. “12.%”) and because it means that the logic between serialization and parsing is separate and not necessarily matching. With one being in an external library, it could also get out of sync over time.

Notes & references

Metadata

Metadata

Assignees

No one assigned

    Labels

    API changeFor PRs that require API design reviewenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions