Public
Edited
May 13, 2024
Paused
Importers
Insert cell
Insert cell
Insert cell
Insert cell
invalidationListener = (target, eventType, theirInvalidation, listener) => {
target.addEventListener(eventType, listener);
theirInvalidation.then(() => target.removeEventListener(eventType, listener));
}
Insert cell
Insert cell
culoriToCss = (c) => culori.formatRgb(culori.rgb(c)).replace(/ /g, "")
Insert cell
culori = require("culori")
Insert cell
Insert cell
step = (group) => {
mutable allStepGroups = new Set([group, ...mutable allStepGroups]);
return htl.html`<h3 class="step-num-${group}"></h3>`;
}
Insert cell
mutable allStepGroups = new Set()
Insert cell
htl.html`
<h3>Styles are in this cell</h3>
${Array.from(allStepGroups).map(
(group) => htl.html`
<style>
:root {
counter-reset: step-counter-${group};
}
.step-num-${group} {
counter-increment: step-counter-${group};
}
.step-num-${group}::before {
content: "Step " counter(step-counter-${group})
}
</style>
`
)}
`
Insert cell
Insert cell
random = {
class Random {
number(a = null, b = null) {
if (a === null && b === null) [a, b] = [0, 1];
if (a !== null && b === null) [a, b] = [0, a];
return Math.random() * (b - a) + a;
}
int(a, b) {
return Math.floor(this.number(a, b));
}
choice(list) {
return list[this.int(list.length)];
}
}
return new Random();
}
Insert cell
Insert cell
monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
Insert cell
monthAbbr3 = monthNames.map((d) => d.slice(0, 3))
Insert cell
formatMonthAndYear = (d) => {
return `${monthAbbr3[d.getUTCMonth()]} ${d.getUTCFullYear()}`;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
twoDigit = d3.format("0>2")
Insert cell
formatDollars = d3.format("$.2f")
Insert cell
Insert cell
Insert cell
Insert cell
// Pass data through an arbitrary list of (async) functions.
// Copied this from @mootari
function pipe(...args) {
if (args.length < 2) return args[0];
const isPromise = (d) => d instanceof Promise || d?.then;
return args.reduce((d, fn) => {
if (d === null) return d;
if (isPromise(d)) return d.then(fn);
return fn(d);
});
}
Insert cell
function compose(...funcs) {
return (...args) => {
let nextArgs = args;
for (let i = funcs.length - 1; i >= 0; i--) {
nextArgs = [funcs[i](...nextArgs)];
}
return nextArgs[0];
};
}
Insert cell
Insert cell
function geomMean(data, fn = (d) => d) {
const acc = Array.from(data, fn).reduce((acc, v) => acc * v, 1);
return Math.pow(acc, 1 / data.length);
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
importExample = (cells, { importWiths = [] } = {}) => {
let code = `import {${cells.join(", ")}} `;
if (importWiths.length) {
code += `with {${importWiths.join(", ")}} `;
}
code += `from "${pinnedSlug}"`;
return htl.html`<div>
<div style="display: inline-block; width: 100px;">
${Copier("Copy import", {
value: code
})}
</div>
<code>${code}</code>
</div>`;
}
Insert cell
Insert cell
Insert cell
radToTurn = (rad) => rad / TAU
Insert cell
turnToRad = turn => turn * TAU
Insert cell
degToTurn = deg => deg / 360
Insert cell
turnToDeg = (turn) => turn * 360
Insert cell
Insert cell
Insert cell
Insert cell
rainbowifyHeaders()
Insert cell
pinnedSlug = getPinnedSlug()
Insert cell
import { getPinnedSlug } from "@mootari/toolbox"
Insert cell
import { spacer } from "@observablehq/fabians-toolbox"
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more