Public
Edited
Aug 3, 2023
Importers
Insert cell
Insert cell
import { sha256, sha3, keccak256 } from '@godtide/cryptographic-hash-functions'
Insert cell
import {viewroutine, ask} from '@tomlarkworthy/viewroutine'
Insert cell
import {inspect} from "@observablehq/inspector"
Insert cell
import {settle as settled} from "@mjbo/settling-input"
Insert cell
import {embed as vega} from "@vega/hello-vega-embed"
Insert cell
fetchEventSource = (await import('@microsoft/fetch-event-source')).fetchEventSource
Insert cell
Insert cell
function button(content) {
const el = htl.html`<button>${content}`;
let resolve, reject;
const promise = new Promise((resolve_, reject_) => {
resolve = resolve_;
reject = reject_;
});
el.addEventListener('click', () => resolve());
invalidation.then(() => reject());
el.promise = promise;
return el;
}
Insert cell
Insert cell
{
const request = new Request('https://swapi.dev/api/people/1/', {
method: 'GET',
});
await approval(`${request.method} ${request.url}`);
const response = await fetch(request);
const json = await response.json();
return json;
}
Insert cell
viewof approval = APPROVAL()
Insert cell
function APPROVAL() {
let enqueue
const generator = Generators.observe((enqueue_) => {
enqueue = enqueue_;
});

setTimeout(WORKER, 0);
let $tbody;
const $self = htl.html`
<h2>Actions awaiting approval</h2>
<table style="display: block; height: 12rem; overflow-y: scroll">
<thead>
<tr>
<th>Approve
<th>Deny
<th>ID
<th style="width: 80rem">Name
</tr>
</thead>
${$tbody = htl.html`<tbody>`}
</table>
`/* htl.html */;
return Object.defineProperties($self, {
value: {
get: () => SUBMIT,
},
});

function SUBMIT(s) {
if (typeof s !== 'object') {
s = { name: s };
}

const { name } = s;
return new Promise((resolve, reject) => {
enqueue({ name, resolve, reject });
});
}

async function WORKER() {
const inProgress = [];
let nextId = 0;
for await (const { name, resolve, reject } of generator) {
const id = nextId++;
const $approve = htl.html.fragment`
<button onclick=${() => APPROVE(id)}>Approve
`/* htl.html.fragment */;
const $deny = htl.html.fragment`
<button onclick=${() => DENY(id)}>Deny
`/* htl.html.fragment */;

PUSH({ id, name, resolve, reject, $approve, $deny });
RENDER();
}

function PUSH(d) {
inProgress.push(d);
}

function POP(id) {
const index = inProgress.findIndex((d) => d.id === id);
if (index < 0) throw 'bad index';
const [d] = inProgress.splice(index, 1);
return d;
}

function APPROVE(id) {
const { resolve } = POP(id);
resolve();
RENDER();
}

function DENY(id) {
const { reject } = POP(id);
reject();
RENDER();
}

function RENDER() {
$tbody.replaceChildren(htl.html.fragment`
${inProgress.map(({ id, name, $approve, $deny }) => htl.html.fragment`
<tr>
<td>${$approve}
<td>${$deny}
<td>${id}
<td>${name}
`/* htl.html.fragment */)}
`/* htl.html.fragment */);
}
};
}
Insert cell
{
await (yield button('Start Example')).promise;
const width = 128;
const height = 128;
const gif = new GIF({
width,
height,
});

const canvas = DOM.canvas(width, height);
const ctx = canvas.getContext('2d');
for (let i=0, n=32; i<n; ++i) {
ctx.fillStyle = `rgb(${256*i/n|0}, ${256*i/n|0}, ${256*i/n|0})`;
ctx.fillRect(0, 0, width, height);

gif.addFrame(ctx, { copy: true });
yield canvas;
}

yield await gif.renderToHTML();
}
Insert cell
Insert cell
GIF = {
const workerScript = await FileAttachment("gif.worker.js").url();

return class GIF extends (await require(await FileAttachment("gif.js").url())) {
constructor(options) {
super({ workerScript, ...options });
}

renderToURL() {
return new Promise((resolve, reject) => {
this.on('finished', (blob) => {
const url = URL.createObjectURL(blob);
resolve(url);
});

super.render();
});
}

async renderToHTML() {
const url = await this.renderToURL();
return htl.html`<a href=${url}><img src=${url}>`;
}
};
}
Insert cell
{
await (yield button('Start')).promise;
yield 'hello';
}
Insert cell
Insert cell
class WebMWriter extends (await require(await FileAttachment("webm-writer-0.3.0.js").url()).catch(() => window.WebMWriter)) {
async renderToURL() {
const blob = await this.complete();
return URL.createObjectURL(blob);
}

async renderToHTML() {
const url = await this.renderToURL();
return htl.html`<a href=${url}><video style=${{ width: `${width}px` }} autoplay loop src=${url}>`;
}
}
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