Public
Edited
Jul 13, 2024
Comments locked
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
colors = {
const { items } = JSON.parse(tokens.textContent.trim());
yield items.map(({ name, value }) =>
Object.assign(
{
name
},
((color) => ({
hex: color.formatHex(),
rgb: color + "",
p3: hexToP3(value)
}))(d3.color(value))
)
);
}
Insert cell
Insert cell
Insert cell
hexToP3("#0f0")
Insert cell
rgbToP3("rgb(0, 255, 0)")
Insert cell
hexToP3("#0f00")
Insert cell
rgbToP3("rgba(0, 255, 0, 0%)")
Insert cell
hexToP3("#00ff00")
Insert cell
rgbToP3("rgba(none 255 none / none)")
Insert cell
hexToP3("#00ff00ff")
Insert cell
rgbToP3("rgba(0, 255, 0, 100%)")
Insert cell
rgbToP3("rgba(0, 254.9, 0, 1%)")
Insert cell
rgbToP3("rgba(., 255., 0, .)")
Insert cell
rgbToP3("rgba(none 255.0 0 / .%)")
Insert cell
Insert cell
{
/*!
* Many thanks to Dean Jackson, Nikita Vasilyev, David Darnes, and Andy Bell! - mg
*/
const color = "rgb(35, 64, 88)";
yield md`
<style>
/* sRGB color */
:root {
--salty-dog: ${color};
}

h1[id] {
color: var(--salty-dog);
}

@media (color-gamut: p3) {
/* Display P3 color, when supported */
:root {
--salty-dog: ${rgbToP3(color)};
}
}

style:only-child:before { content: "## Tweak main heading color (${hasP3})…" !important; }
</style>
`;
}
Insert cell
hasP3 = window.matchMedia("(color-gamut: p3)").matches
Insert cell
color = (values = [0, 0, 0], colorspace = "srgb") => {
const { 3: alpha = NaN, ...components } = values;
return `color(${colorspace} ${Object.values(components).join(" ")}${
+alpha == alpha ? ` / ${alpha}` : ""
})`;
}
Insert cell
hexToP3 = (hex = "", { colorspace = "display-p3" } = {}) => {
// Calculate richer P3 colors from HEX values
try {
let count;
const { 0: match } = hex.trim().match(/^#(?:[0-9a-f]{3,4}){1,2}$/i);
switch (match.length) {
case 5: // #RGBA
case 4: // #RGB
count = 1;
break;
case 9: // #RRGGBBAA
case 7: // #RRGGBB
count = 2;
break;
}
const _ = (x) => (parseInt(x, 16) / 255).toFixed(6) * 1;
const process = [(x) => _(x + x), (x) => _(x)][count - 1];
const components = match
.slice(1)
.match(new RegExp(`.{${count}}`, "g"))
.map(process);
return color(components, colorspace);
} catch (e) {
throw Error("Argument is not an hexadecimal color");
}
}
Insert cell
Insert cell
Insert cell
rgbToP3 = (() => {
const fractional = ["(?:[.]0*)?", "(?:[.]\\d*)?"];
const percentage =
"(?:100" + fractional[0] + "|[1-9]?\\d?" + fractional[1] + ")%";
const isRGB = new RegExp(
/* rgb(R G B[ / A]) | rgba(R G B[ / A]) */
[
"^rgba?\\(",
/* component values: none | 0 to 255 | 0% to 100% */
["R", "G", "B"]
.map(
(C) =>
["(?<", C, ">"].join("") +
[
"none",
"(?:255" +
fractional[0] +
"|(?:25[0-4]|2[0-4]\\d|1\\d{1,2}|[1-9]?\\d?)" +
fractional[1] +
")",
percentage
].join("|") +
")"
)
.join("(?:\\s*,\\s*|\\s+)"),
/* alpha channel value: none | 0 to 1 | 0% to 100% */
"(?:\\s*[,\\/]\\s*",
"(?<A>" +
[
"none",
"(?:1" + fractional[0] + "|0?" + fractional[1] + ")",
percentage
].join("|") +
")",
")?",
"\\)$"
].join(""),
"i"
);
return (rgba = "", { colorspace = "display-p3" } = {}) => {
// Calculate richer P3 colors from sRGB absolute values
try {
const components = rgba
.trim()
.match(isRGB)
.slice(1)
.map((x, i) =>
["none", ".", ".%"].includes(x)
? i < 3
? /* R, G, or B */ 0
: /* A */ [0, NaN][+(x === "none")]
: (
parseFloat(x, 10) /
((x || "").match(/%$/)
? /* percentage */ 100
: i < 3
? /* R, G, or B */ 255
: /* A */ 1)
).toFixed(6) * 1
);
return color(components, colorspace);
} catch (e) {
throw Error("Argument is not a sRGB color");
}
};
})()
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more