From a340058c2e4cf218a3402cde3f160bf2ab05b75e Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Tue, 16 Jan 2024 16:34:21 -0800 Subject: [PATCH 1/2] =?UTF-8?q?Dash.resize=20=E2=86=92=20resize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/dashboard.css | 11 --------- docs/dashboard.md | 3 --- docs/grid.md | 4 ---- docs/javascript/display.md | 24 +++++++++++++++++++ docs/lib/dash.md | 11 --------- examples/plot/README.md | 2 +- src/build.ts | 1 - src/client/main.js | 3 ++- src/client/stdlib.js | 1 + src/client/stdlib/dash.ts | 1 - src/client/stdlib/recommendedLibraries.js | 1 - src/client/stdlib/{dash => }/resize.ts | 0 src/javascript/imports.ts | 2 -- src/rollup.ts | 14 +++++------ test/deploy-test.ts | 1 - .../_observablehq/stdlib/dash.js | 0 16 files changed, 34 insertions(+), 45 deletions(-) delete mode 100644 docs/dashboard.css delete mode 100644 docs/dashboard.md delete mode 100644 docs/lib/dash.md delete mode 100644 src/client/stdlib/dash.ts rename src/client/stdlib/{dash => }/resize.ts (100%) delete mode 100644 test/output/build/simple-public/_observablehq/stdlib/dash.js diff --git a/docs/dashboard.css b/docs/dashboard.css deleted file mode 100644 index 2b8a16ac9..000000000 --- a/docs/dashboard.css +++ /dev/null @@ -1,11 +0,0 @@ -@media (prefers-color-scheme: light) { - :root { - --theme-background: color-mix(in srgb, var(--theme-background-alt) 97%, black); - --theme-background-alt: rgb(255, 255, 255); - } -} - -#observablehq-main, -#observablehq-footer { - max-width: initial; -} diff --git a/docs/dashboard.md b/docs/dashboard.md deleted file mode 100644 index cb48b6e08..000000000 --- a/docs/dashboard.md +++ /dev/null @@ -1,3 +0,0 @@ - - -# Dashboard theme test diff --git a/docs/grid.md b/docs/grid.md index 3562a50ca..9d7b53214 100644 --- a/docs/grid.md +++ b/docs/grid.md @@ -3,10 +3,6 @@ toc: false theme: dashboard --- -```js -import {resize} from "npm:@observablehq/dash"; -``` - ```js function AppleStockChart({width}) { return Plot.plot({ diff --git a/docs/javascript/display.md b/docs/javascript/display.md index e48306ba4..af9828020 100644 --- a/docs/javascript/display.md +++ b/docs/javascript/display.md @@ -92,6 +92,30 @@ ${display(1), display(2)} ${display(1), display(2)} ``` +## Responsive display + +In Markdown, the built-in `width` reactive variable represents the current width of the main element. This can be a handy thing to pass, say, as the **width** option to [Observable Plot](../lib/plot). + +```html echo +The current width is ${width}. +``` + +```js +import {resize} from "npm:@observablehq/stdlib"; +``` + +For more control, or in a grid where you want to respond to either width or height changing, use the built-in `resize` helper. This takes a render function which is called whenever the width or height changes; the element returned by the render function is inserted into the DOM. + +```html echo +
+
+ ${resize((width) => html`This card is ${width}px wide.`)} +
+
+``` + +See also [`Generators.width`](../lib/generators#width(element)). + ## display(*value*) If `value` is a DOM node, adds it to the page. Otherwise, converts the given `value` to a suitable DOM node and displays that instead. Returns the given `value`. diff --git a/docs/lib/dash.md b/docs/lib/dash.md deleted file mode 100644 index e06b5d0c8..000000000 --- a/docs/lib/dash.md +++ /dev/null @@ -1,11 +0,0 @@ -# Observable Dash - -Dashboard components. - -```js run=false -import * as Dash from "npm:@observablehq/dash"; -``` - -```js echo -Dash -``` diff --git a/examples/plot/README.md b/examples/plot/README.md index 2b3b35da8..80f9697d5 100644 --- a/examples/plot/README.md +++ b/examples/plot/README.md @@ -32,4 +32,4 @@ Key performance indicators are displayed as “big numbers” with, in some case The charts are drawn — quite obviously ☺️ — with Observable Plot. The code for the downloads chart is isolated in the [`components/dailyPlot.js`](./docs/components/dailyPlot.js) file. The code for the burndown chart is adapted from Tom MacWright’s [GitHub Burndown chart](https://observablehq.com/@tmcw/github-burndown). -The size of the charts automatically adapts to their container’s dimensions with the built-in [`Dash.resize`](https://cli.observablehq.com/lib/dash) helper — part of a collection of helpers currently under development. +The size of the charts automatically adapts to their container’s dimensions with the built-in `resize` helper — part of a collection of helpers currently under development. diff --git a/src/build.ts b/src/build.ts index 549b2af22..a14f4622a 100644 --- a/src/build.ts +++ b/src/build.ts @@ -21,7 +21,6 @@ function clientBundles(clientPath: string): [entry: string, name: string][] { return [ [clientPath, "client.js"], ["./src/client/stdlib.js", "stdlib.js"], - ["./src/client/stdlib/dash.js", "stdlib/dash.js"], ["./src/client/stdlib/dot.js", "stdlib/dot.js"], ["./src/client/stdlib/duckdb.js", "stdlib/duckdb.js"], ["./src/client/stdlib/inputs.css", "stdlib/inputs.css"], diff --git a/src/client/main.js b/src/client/main.js index f33c62a10..58f2cade7 100644 --- a/src/client/main.js +++ b/src/client/main.js @@ -1,6 +1,6 @@ import {Runtime} from "observablehq:runtime"; import {registerDatabase, registerFile} from "observablehq:stdlib"; -import {DatabaseClient, FileAttachment, Generators, Mutable} from "observablehq:stdlib"; +import {DatabaseClient, FileAttachment, Generators, Mutable, resize} from "observablehq:stdlib"; import {inspect, inspectError} from "./inspect.js"; import * as recommendedLibraries from "./stdlib/recommendedLibraries.js"; import * as sampleDatasets from "./stdlib/sampleDatasets.js"; @@ -8,6 +8,7 @@ import * as sampleDatasets from "./stdlib/sampleDatasets.js"; const library = { now: () => Generators.now(), width: () => Generators.width(document.querySelector("main")), + resize: () => resize, DatabaseClient: () => DatabaseClient, FileAttachment: () => FileAttachment, Generators: () => Generators, diff --git a/src/client/stdlib.js b/src/client/stdlib.js index 9c0461ecd..0c08fe01c 100644 --- a/src/client/stdlib.js +++ b/src/client/stdlib.js @@ -2,3 +2,4 @@ export {DatabaseClient, registerDatabase} from "./stdlib/databaseClient.js"; export {AbstractFile, FileAttachment, registerFile} from "./stdlib/fileAttachment.js"; export * as Generators from "./stdlib/generators/index.js"; export {Mutable} from "./stdlib/mutable.js"; +export {resize} from "./stdlib/resize.js"; diff --git a/src/client/stdlib/dash.ts b/src/client/stdlib/dash.ts deleted file mode 100644 index 8b68f0e6e..000000000 --- a/src/client/stdlib/dash.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./dash/resize.js"; diff --git a/src/client/stdlib/recommendedLibraries.js b/src/client/stdlib/recommendedLibraries.js index dad82ddba..4b4387461 100644 --- a/src/client/stdlib/recommendedLibraries.js +++ b/src/client/stdlib/recommendedLibraries.js @@ -2,7 +2,6 @@ export const _ = () => import("npm:lodash").then((lodash) => lodash.default); export const aq = () => import("npm:arquero"); export const Arrow = () => import("npm:apache-arrow"); export const d3 = () => import("npm:d3"); -export const Dash = () => import("observablehq:stdlib/dash"); export const dot = () => import("observablehq:stdlib/dot").then((dot) => dot.default); export const duckdb = () => import("npm:@duckdb/duckdb-wasm"); export const DuckDBClient = () => import("observablehq:stdlib/duckdb").then((duckdb) => duckdb.DuckDBClient); diff --git a/src/client/stdlib/dash/resize.ts b/src/client/stdlib/resize.ts similarity index 100% rename from src/client/stdlib/dash/resize.ts rename to src/client/stdlib/resize.ts diff --git a/src/javascript/imports.ts b/src/javascript/imports.ts index b5dc22c28..f520f64cb 100644 --- a/src/javascript/imports.ts +++ b/src/javascript/imports.ts @@ -263,8 +263,6 @@ export function createImportResolver(root: string, base: "." | "_import" = "."): ? resolveBuiltin(base, path, "runtime.js") : specifier === "npm:@observablehq/stdlib" ? resolveBuiltin(base, path, "stdlib.js") - : specifier === "npm:@observablehq/dash" - ? resolveBuiltin(base, path, "stdlib/dash.js") // TODO publish to npm : specifier === "npm:@observablehq/dot" ? resolveBuiltin(base, path, "stdlib/dot.js") // TODO publish to npm : specifier === "npm:@observablehq/duckdb" diff --git a/src/rollup.ts b/src/rollup.ts index 1fecc692b..4e04d913b 100644 --- a/src/rollup.ts +++ b/src/rollup.ts @@ -63,12 +63,12 @@ export async function rollupClient(clientPath: string, {minify = false} = {}): P } // For reasons not entirely clear (to me), when we resolve a relative import to -// a TypeScript file, such as resolving observablehq:stdlib/dash to -// ./src/client/stdlib/dash.js, Rollup (or rollup-plugin-esbuild?) notices that -// there is a dash.ts and rewrites the import to dash.ts. But the imported file -// at runtime won’t be TypeScript and will only exist at dash.js, so here we -// rewrite the import back to what it was supposed to be. This is a dirty hack -// but it gets the job done. 🤷 https://github.com/observablehq/cli/issues/478 +// a TypeScript file, such as resolving observablehq:stdlib/foo to +// ./src/client/stdlib/foo.js, Rollup (or rollup-plugin-esbuild?) notices that +// there is a foo.ts and rewrites the import to foo.ts. But the imported file at +// runtime won’t be TypeScript and will only exist at foo.js, so here we rewrite +// the import back to what it was supposed to be. This is a dirty hack but it +// gets the job done. 🤷 https://github.com/observablehq/cli/issues/478 function rewriteTypeScriptImports(code: string): string { return code.replace(/(?<=\bimport\(([`'"])[\w./]+)\.ts(?=\1\))/g, ".js"); } @@ -91,8 +91,6 @@ async function resolveImport(source: string, specifier: string | AstNode): Promi ? {id: relativeUrl(source, getClientPath("./src/client/runtime.js")), external: true} : specifier === "npm:@observablehq/stdlib" ? {id: relativeUrl(source, getClientPath("./src/client/stdlib.js")), external: true} - : specifier === "npm:@observablehq/dash" - ? {id: relativeUrl(source, getClientPath("./src/client/stdlib/dash.js")), external: true} // TODO publish to npm : specifier === "npm:@observablehq/dot" ? {id: relativeUrl(source, getClientPath("./src/client/stdlib/dot.js")), external: true} // TODO publish to npm : specifier === "npm:@observablehq/duckdb" diff --git a/test/deploy-test.ts b/test/deploy-test.ts index 09b6cb614..a2de9f8c5 100644 --- a/test/deploy-test.ts +++ b/test/deploy-test.ts @@ -18,7 +18,6 @@ const EXTRA_FILES: string[] = [ "_observablehq/client.js", "_observablehq/runtime.js", "_observablehq/stdlib.js", - "_observablehq/stdlib/dash.js", "_observablehq/stdlib/dot.js", "_observablehq/stdlib/duckdb.js", "_observablehq/stdlib/inputs.css", diff --git a/test/output/build/simple-public/_observablehq/stdlib/dash.js b/test/output/build/simple-public/_observablehq/stdlib/dash.js deleted file mode 100644 index e69de29bb..000000000 From e83636a7d06043453f6c1285845afb4c8faddef1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Tue, 16 Jan 2024 16:47:18 -0800 Subject: [PATCH 2/2] fix Dash usage --- examples/google-analytics/docs/index.md | 37 +++++++++++++------------ examples/plot/docs/index.md | 6 ++-- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/examples/google-analytics/docs/index.md b/examples/google-analytics/docs/index.md index 5e453c32f..a7471ba07 100644 --- a/examples/google-analytics/docs/index.md +++ b/examples/google-analytics/docs/index.md @@ -1,5 +1,6 @@ - - +--- +theme: dashboard +--- ```js // Data @@ -286,31 +287,31 @@ function worldMap(data, {width, height, title, caption}) { _Summary of metrics from the [Google Analytics Data API](https://developers.google.com/analytics/devguides/reporting/data/v1/quickstart-client-libraries), pulled on ${date(d3.max(summary, d => d.date))}_
-
- ${Dash.resize((width) => BigNumber(`${summary[summary.length-1].active28d.toLocaleString("en-US")}`, {title: "Rolling 28-day Active users", plot: areaChart(summary, {width, metric: 'active28d'}), trend: getCompareValue(summary, 'active28d'), trendFormat: bigNumber}))} +
+ ${resize((width) => BigNumber(`${summary[summary.length-1].active28d.toLocaleString("en-US")}`, {title: "Rolling 28-day Active users", plot: areaChart(summary, {width, metric: 'active28d'}), trend: getCompareValue(summary, 'active28d'), trendFormat: bigNumber}))}
-
- ${Dash.resize((width) => BigNumber(`${bigPercent(summary[summary.length-1].engagementRate)}`, {title: "Engagement Rate", plot: lineChart(summary, {width, metric: 'engagementRate'}), trend: getCompareValue(summary, 'engagementRate'), trendFormat: percent}))} +
+ ${resize((width) => BigNumber(`${bigPercent(summary[summary.length-1].engagementRate)}`, {title: "Engagement Rate", plot: lineChart(summary, {width, metric: 'engagementRate'}), trend: getCompareValue(summary, 'engagementRate'), trendFormat: percent}))}
-
- ${Dash.resize((width) => BigNumber(`${bigPercent(summary[summary.length-1].wauPerMau)}`, {title: "WAU to MAU ratio", plot: lineChart(summary, {width, metric: 'wauPerMau'}), trend: getCompareValue(summary, 'wauPerMau'), trendFormat: percent}))} +
+ ${resize((width) => BigNumber(`${bigPercent(summary[summary.length-1].wauPerMau)}`, {title: "WAU to MAU ratio", plot: lineChart(summary, {width, metric: 'wauPerMau'}), trend: getCompareValue(summary, 'wauPerMau'), trendFormat: percent}))}
-
- ${Dash.resize((width) => BigNumber(`${summary[summary.length-1].engagedSessions.toLocaleString("en-US")}`, {title: "Engaged Sessions", plot: areaChart(summary, {width, metric: 'engagedSessions'}), trend: getCompareValue(summary, 'engagedSessions'), trendFormat: bigNumber}))} +
+ ${resize((width) => BigNumber(`${summary[summary.length-1].engagedSessions.toLocaleString("en-US")}`, {title: "Engaged Sessions", plot: areaChart(summary, {width, metric: 'engagedSessions'}), trend: getCompareValue(summary, 'engagedSessions'), trendFormat: bigNumber}))}
-
- ${Dash.resize((width, height) => horizonChart(channels, {width, height, metric:'active28d', title: 'Active users by channel', caption: 'Rolling 28-day active users', format: 's', z: 'channelGroup', color, order: color.domain.slice(1)}))} +
+ ${resize((width, height) => horizonChart(channels, {width, height, metric:'active28d', title: 'Active users by channel', caption: 'Rolling 28-day active users', format: 's', z: 'channelGroup', color, order: color.domain.slice(1)}))}
-
- ${Dash.resize((width, height) => worldMap(countryData, {width, height, title: "Active users by country", caption: 'Current rolling 28-day active users by country', lookup: countryLookup}))} +
+ ${resize((width, height) => worldMap(countryData, {width, height, title: "Active users by country", caption: 'Current rolling 28-day active users by country', lookup: countryLookup}))}
-
- ${Dash.resize((width, height) => marrimekoChart(filteredChannelBreakdown, {width, height, metric:'active28d', title: 'New vs. returning users by channel', caption: 'Rolling 28-day active users by channel and split by new vs. returning', format: '%', yDim: 'channelGroup', xDim: 'type', color}))} +
+ ${resize((width, height) => marrimekoChart(filteredChannelBreakdown, {width, height, metric:'active28d', title: 'New vs. returning users by channel', caption: 'Rolling 28-day active users by channel and split by new vs. returning', format: '%', yDim: 'channelGroup', xDim: 'type', color}))}
-
- ${Dash.resize((width, height) => Punchcard(hourly, {width, height, label: "active users"}))} +
+ ${resize((width, height) => Punchcard(hourly, {width, height, label: "active users"}))}
diff --git a/examples/plot/docs/index.md b/examples/plot/docs/index.md index d1d921936..693635137 100644 --- a/examples/plot/docs/index.md +++ b/examples/plot/docs/index.md @@ -57,11 +57,11 @@ const burndown = issues
- ${Dash.resize((width, height) => DailyPlot(downloads, {width, height, title: "Daily npm downloads", label: "downloads", domain: [0, 6000], versions}))} + ${resize((width, height) => DailyPlot(downloads, {width, height, title: "Daily npm downloads", label: "downloads", domain: [0, 6000], versions}))}
- ${Dash.resize((width) => Plot.plot({ + ${resize((width) => Plot.plot({ width, caption: "Downloads per version (last 7 days)", x: {label: null, tickFormat: "s", round: true, axis: "top"}, @@ -107,7 +107,7 @@ const burndown = issues
-
${Dash.resize((width, height) => Plot.plot({ +
${resize((width, height) => Plot.plot({ width, height, marginLeft: 0,