Observable Generators
The Observable standard library includes several generator utilities. These are available by default in Markdown as Generators
, but you can import them explicitly:
import {Generators} from "observablehq:stdlib";
input(element)
Source · Returns an async generator that yields whenever the given element emits an input event, with the given element’s current value. (It’s a bit fancier than that because we special-case a few element types.) The built-in view
function uses this.
const nameInput = display(document.createElement("input"));
const name = Generators.input(nameInput);
name
observe(initialize)
Source · Returns an async generator that immediately invokes the specified initialize function, being passed a change callback function, and yields the passed value whenever change is called. The initialize function may optionally return a dispose function that will be called when the generator is terminated.
const hash = Generators.observe((change) => {
const changed = () => change(location.hash);
addEventListener("hashchange", changed);
changed();
return () => removeEventListener("hashchange", changed);
});
hash
queue(change)
Source · Returns an async generator that immediately invokes the specified initialize function, being passed a change callback function, and yields the passed value whenever change is called. The initialize function may optionally return a dispose function that will be called when the generator is terminated.
This is identical to Generators.observe
except that if change is called multiple times before the consumer has a chance to process the yielded result, values will not be dropped; use this if you require that the consumer not miss a yielded value.
const hash = Generators.queue((change) => {
const changed = () => change(location.hash);
addEventListener("hashchange", changed);
changed();
return () => removeEventListener("hashchange", changed);
});
hash
now()
Source · Returns a generator that repeatedly yields Date.now()
, forever. This generator is available by default as now
in Markdown.
const now = Generators.now();
now
width(element)
Source · Returns an async generator that yields the width of the given target element. Using a ResizeObserver, the generator will yield whenever the width of the element changes. This generator for the main
element is available by default as width
in Markdown.
const width = Generators.width(document.querySelector("main"));
width
dark()
Source · Returns an async generator that yields a boolean indicating whether the page is currently displayed with a dark color scheme.
const dark = Generators.dark();
If the page supports both light and dark mode (as with the default theme), the value reflects the user’s preferred color scheme. The generator will yield a new value if the preferred color changes — as when the user changes their system settings, or if the user’s system adapts automatically to the diurnal cycle — allowing you to update the display as needed without requiring a page reload.
If the page only supports light mode, the value is always false; likewise it is always true if the page only has a dark theme.
The current theme is:
The current theme is: *${dark ? "dark" : "light"}*.
This generator is available by default as dark
in Markdown. It can be used to pick a color scheme for a chart, or an appropriate mix-blend-mode:
Plot.plot({
height: 260,
color: {scheme: dark ? "turbo" : "ylgnbu"},
marks: [
Plot.rectY(
olympians,
Plot.binX(
{y2: "count"},
{
x: "weight",
fill: "weight",
z: "sex",
mixBlendMode: dark ? "screen" : "multiply"
}
)
),
Plot.ruleY([0])
]
})