Skip to content

Commit ac82b51

Browse files
committed
Merge branch 'main' into fil/brush
2 parents db508ce + 14d6e43 commit ac82b51

File tree

297 files changed

+33045
-3514
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

297 files changed

+33045
-3514
lines changed

.github/ISSUE_TEMPLATE/bug.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
name: Bug
3+
about: Something isn’t working
4+
labels: "bug"
5+
---

.github/ISSUE_TEMPLATE/enhancement.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
name: Enhancement
3+
about: New feature or request
4+
labels: "enhancement"
5+
---

CHANGELOG-2023.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ Plot.bollingerY(aapl, {x: "Date", y: "Close", n: 20, k: 2}).plot()
233233

234234
The [arrow mark](https://observablehq.com/plot/marks/arrow) supports a new **sweep** option to control the bend orientation. Below, we set this option to *-y* to draw arrows bulging right, independent of the relative vertical positions of its source and target.
235235

236-
[<img src="./img/arc-diagram.png" width="521" alt="Detail of an arc diagram connecting characters in Les Misérables that appear in the same chapters.">](https://observablehq.com/@observablehq/plot-arc-diagram?intent=fork)
236+
[<img src="./img/arc-diagram.png" width="521" alt="Detail of an arc diagram connecting characters in Les Misérables that appear in the same chapters.">](https://observablehq.com/@observablehq/plot-arc-diagram)
237237

238238
```js
239239
Plot.plot({

CHANGELOG.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,117 @@
22

33
Year: **Current (2024)** · [2023](./CHANGELOG-2023.md) · [2022](./CHANGELOG-2022.md) · [2021](./CHANGELOG-2021.md)
44

5+
## 0.6.16
6+
7+
[Released August 6, 2024.](https://github.com/observablehq/plot/releases/tag/v0.6.16)
8+
9+
The new [waffle mark](https://observablehq.com/plot/marks/waffle) 🧇 displays a quantity (or quantitative extent) for a given category; unlike a [bar](https://observablehq.com/plot/marks/bar), a waffle is subdivided into cells that allow easier counting, making waffles useful for reading and comparing exact quantities. Plot’s waffle mark is highly configurable: it supports stacking, positive and negative values, rounded corners, partial cells for fractional counts, automatic row or column size determination (with optional override), and more!
10+
11+
[<img src="./img/waffle.png" width="708" alt="a waffle chart of Olympic athletes by weight">](https://observablehq.com/plot/marks/waffle)
12+
13+
```js
14+
Plot.plot({
15+
fx: {interval: 10},
16+
color: {legend: true},
17+
marks: [Plot.waffleY(olympians, Plot.groupZ({y: "count"}, {fill: "sex", sort: "sex", fx: "weight", unit: 10}))]
18+
})
19+
```
20+
21+
22+
All marks now support GeoJSON data and GeoJSON property shorthand, making it easier to work with GeoJSON. For example, below the data `counties` is a GeoJSON FeatureCollection, and `unemployment` refers to a property on each feature; the **fill** option is thus shorthand for `(d) => d.properties.unemployment`. The [geo mark](https://observablehq.com/plot/marks/geo) now also supports the **tip** option (via an implicit [centroid transform](https://observablehq.com/plot/transforms/centroid)), making it easier to use Plot’s [interactive tooltips](https://observablehq.com/plot/interactions/pointer).
23+
24+
[<img src="./img/geo-tip.png" width="708" alt="a choropleth map of unemployment by U.S. county">](https://observablehq.com/plot/marks/geo)
25+
26+
```js
27+
Plot.plot({
28+
projection: "albers-usa",
29+
color: {
30+
type: "quantile",
31+
n: 9,
32+
scheme: "blues",
33+
label: "Unemployment (%)",
34+
legend: true
35+
},
36+
marks: [
37+
Plot.geo(counties, {
38+
fill: "unemployment",
39+
title: (d) => `${d.properties.name} ${d.properties.unemployment}%`,
40+
tip: true
41+
})
42+
]
43+
})
44+
```
45+
46+
All marks now also support column name channel shorthand when using Apache Arrow tables as data, and we’ve added detection of Arrow date-type columns. (Arrow represents temporal data using BigInt rather than Date.)
47+
48+
```js
49+
Plot.dot(gistemp, {x: "Date", y: "Anomaly"}).plot() // gistemp is an Arrow Table!
50+
```
51+
52+
The rect-like marks ([rect](https://observablehq.com/plot/marks/rect), [bar](https://observablehq.com/plot/marks/bar), [cell](https://observablehq.com/plot/marks/cell), and [frame](https://observablehq.com/plot/marks/frame)) now support individual rounding options for each side (**rx1**, **ry1**, *etc.*) and corner (**rx1y1**, **rx2y1**, *etc.*). This allows you to round just the top side of rects. You can even use a negative corner radius on the bottom side for seamless stacking, as in the histogram of Olympic athletes below.
53+
54+
[<img src="./img/rect-rounded.png" width="708" alt="a histogram of Olympic athletes by weight">](https://observablehq.com/plot/marks/rect)
55+
56+
```js
57+
Plot.plot({
58+
color: {legend: true},
59+
marks: [
60+
Plot.rectY(olympians, Plot.binX({y: "count"}, {x: "weight", fill: "sex", ry2: 4, ry1: -4, clip: "frame"})),
61+
Plot.ruleY([0])
62+
]
63+
})
64+
```
65+
66+
Plot now respects the projection **domain** when determining the default plot height. Previously, the map below would use a default square aspect ratio for the *conic-conformal* projection regardless of the specified **domain**, but now the map is perfectly sized to fit North Carolina. (Plot also now chooses a smarter default plot height when the ordinal *y* scale domain is empty.)
67+
68+
<img src="./img/geo-nc.png" width="659" alt="an unlabeled map showing the outline and counties of North Carolina">
69+
70+
```js
71+
Plot.plot({
72+
projection: {.
73+
type: "conic-conformal",
74+
parallels: [34 + 20 / 60, 36 + 10 / 60],
75+
rotate: [79, 0],
76+
domain: state
77+
},
78+
marks: [
79+
Plot.geo(counties, {strokeOpacity: 0.2}),
80+
Plot.geo(state)
81+
]
82+
})
83+
```
84+
85+
The [marker options](https://observablehq.com/plot/features/markers) now render as intended on marks with varying aesthetics, such as the spiraling arrows of varying thickness and color below.
86+
87+
<img src="./img/group-marker.png" width="659" alt="several spiraling lines emanate from the center of the image, with rainbow color and increasing thickness, each capped with a pointed arrow at the end">
88+
89+
```js
90+
Plot.plot({
91+
inset: 40,
92+
axis: null,
93+
marks: [
94+
Plot.line(d3.range(400), {
95+
x: (i) => i * Math.sin(i / 100 + ((i % 5) * 2 * Math.PI) / 5),
96+
y: (i) => i * Math.cos(i / 100 + ((i % 5) * 2 * Math.PI) / 5),
97+
z: (i) => i % 5,
98+
stroke: (i) => -i,
99+
strokeWidth: (i) => i ** 1.1 / 100,
100+
markerEnd: "arrow"
101+
})
102+
]
103+
})
104+
```
105+
106+
This release includes a few more new features, bug fixes, and improvements:
107+
108+
The new **className** [mark option](https://observablehq.com/plot/features/marks#mark-options) specifies an optional `class` attribute for rendered marks, allowing styling of marks via external stylesheets or easier selection via JavaScript; thanks, @RLesser! Plot now reuses `clipPath` elements, when possible, when the **clip** mark option is set to *frame* or *projection*.
109+
110+
The [difference mark](https://observablehq.com/plot/marks/difference) now supports a horizontal orientation via [differenceX](https://observablehq.com/plot/marks/difference#differenceX), and the [shift transform](https://observablehq.com/plot/transforms/shift) now likewise supports [shiftY](https://observablehq.com/plot/transforms/shift#shiftY). The [Voronoi mark](https://observablehq.com/plot/marks/delaunay) is now compatible with the pointer transform: only the pointed Voronoi cell is rendered; the Voronoi mark now also renders as intended with non-exclusive facets (as when using the *exclude* facet mode). The [tip mark](https://observablehq.com/plot/marks/tip) no longer displays channels containing literal color values by default.
111+
112+
## 0.6.15
113+
114+
[Released June 11, 2024.](https://github.com/observablehq/plot/releases/tag/v0.6.15)
115+
5116
## 0.6.14
6117

7118
[Released March 12, 2024.](https://github.com/observablehq/plot/releases/tag/v0.6.14)

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
# Observable Plot
22

3-
[<img src="./img/plot.svg" width="320" alt="The Observable Plot logo, spelling out the letters P-L-O-T in pastel shapes.">](https://observablehq.com/plot/)
3+
[<img src="https://observablehq.com/plot/plot.svg" width="320" alt="The Observable Plot logo, spelling out the letters P-L-O-T in pastel shapes.">](https://observablehq.com/plot/)
44

55
[**Observable Plot**](https://observablehq.com/plot/) is a free, [open-source](./LICENSE), JavaScript library for visualizing tabular data, focused on accelerating exploratory data analysis. It has a concise, memorable, yet expressive API, featuring [scales](https://observablehq.com/plot/features/scales) and [layered marks](https://observablehq.com/plot/features/marks) in the *grammar of graphics* style.
66

7+
<a href="https://observablehq.observablehq.cloud/oss-analytics/@observablehq/plot">
8+
<picture>
9+
<source media="(prefers-color-scheme: dark)" srcset="https://observablehq.observablehq.cloud/oss-analytics/@observablehq/plot/downloads-dark.svg">
10+
<img alt="Daily downloads of Observable Plot" src="https://observablehq.observablehq.cloud/oss-analytics/@observablehq/plot/downloads.svg">
11+
</picture>
12+
</a>
13+
14+
<sub>Daily downloads of Observable Plot · [oss-analytics](https://observablehq.observablehq.cloud/oss-analytics/)</sub>
15+
716
## Documentation 📚
817

918
https://observablehq.com/plot/

docs/.vitepress/config.ts

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ import plot from "./markdown-it-plot.js";
66
// https://vitepress.dev/reference/site-config
77
// prettier-ignore
88
export default defineConfig({
9-
title: "Observable Plot",
9+
title: "Plot",
1010
description: "The JavaScript library for exploratory data visualization",
11+
appearance: "force-auto",
1112
base: "/plot/",
1213
cleanUrls: true,
1314
vite: {
@@ -16,6 +17,16 @@ export default defineConfig({
1617
{find: "@observablehq/plot", replacement: path.resolve("./src/index.js")},
1718
{find: /^.*\/VPFooter\.vue$/, replacement: fileURLToPath(new URL("./theme/CustomFooter.vue", import.meta.url))}
1819
]
20+
},
21+
define: {
22+
__APP_VERSION__: JSON.stringify(process.env.npm_package_version)
23+
}
24+
},
25+
vue: {
26+
template: {
27+
compilerOptions: {
28+
isCustomElement: (tag) => tag.startsWith("observable-")
29+
}
1930
}
2031
},
2132
markdown: {
@@ -24,13 +35,17 @@ export default defineConfig({
2435
}
2536
},
2637
head: [
38+
["link", {rel: "preconnect", href: "https://fonts.gstatic.com", crossorigin: ""}],
39+
["link", {rel: "preload", as: "style", href: "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Spline+Sans+Mono:ital,wght@0,300..700;1,300..700&display=swap"}],
40+
["link", {rel: "stylesheet", href: "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Spline+Sans+Mono:ital,wght@0,300..700;1,300..700&display=swap"}],
2741
["link", {rel: "apple-touch-icon", href: "https://static.observablehq.com/favicon-512.0667824687f99c942a02e06e2db1a060911da0bf3606671676a255b1cf97b4fe.png"}],
2842
["link", {rel: "icon", type: "image/png", href: "https://static.observablehq.com/favicon-512.0667824687f99c942a02e06e2db1a060911da0bf3606671676a255b1cf97b4fe.png", sizes: "512x512"}],
2943
["script", {async: "", src: "https://www.googletagmanager.com/gtag/js?id=G-9B88TP6PKQ"}],
30-
["script", {}, "window.dataLayer=window.dataLayer||[];\nfunction gtag(){dataLayer.push(arguments);}\ngtag('js',new Date());\ngtag('config','G-9B88TP6PKQ');"]
44+
["script", {}, "window.dataLayer=window.dataLayer||[];\nfunction gtag(){dataLayer.push(arguments);}\ngtag('js',new Date());\ngtag('config','G-9B88TP6PKQ');"],
45+
["script", {async: "", defer: "", src: "https://static.observablehq.com/assets/components/observable-made-by.js"}],
3146
],
3247
sitemap: {
33-
hostname: 'https://observablehq.com/plot/'
48+
hostname: "https://observablehq.com/plot/"
3449
},
3550
themeConfig: {
3651
// https://vitepress.dev/reference/default-theme-config
@@ -39,19 +54,14 @@ export default defineConfig({
3954
light: "/observable-light.svg",
4055
dark: "/observable-dark.svg"
4156
},
42-
nav: [
43-
{text: "Home", link: "/"},
44-
{text: "Examples", link: "https://observablehq.com/@observablehq/plot-gallery"},
45-
{text: "Community", link: "/community"},
46-
{text: "D3", link: "https://d3js.org"}
47-
],
4857
sidebar: [
4958
{
5059
text: "Introduction",
5160
items: [
5261
{text: "What is Plot?", link: "/what-is-plot"},
5362
{text: "Why Plot?", link: "/why-plot"},
54-
{text: "Getting started", link: "/getting-started"}
63+
{text: "Getting started", link: "/getting-started"},
64+
{text: "Examples", link: "https://observablehq.com/@observablehq/plot-gallery"}
5565
]
5666
},
5767
{
@@ -68,6 +78,7 @@ export default defineConfig({
6878
{text: "Legends", link: "/features/legends"},
6979
{text: "Curves", link: "/features/curves"},
7080
{text: "Formats", link: "/features/formats"},
81+
{text: "Intervals", link: "/features/intervals"},
7182
{text: "Markers", link: "/features/markers"},
7283
{text: "Shorthand", link: "/features/shorthand"},
7384
{text: "Accessibility", link: "/features/accessibility"}
@@ -105,7 +116,8 @@ export default defineConfig({
105116
{text: "Tick", link: "/marks/tick"},
106117
{text: "Tip", link: "/marks/tip"},
107118
{text: "Tree", link: "/marks/tree"},
108-
{text: "Vector", link: "/marks/vector"}
119+
{text: "Vector", link: "/marks/vector"},
120+
{text: "Waffle", link: "/marks/waffle"}
109121
]
110122
},
111123
{
@@ -143,13 +155,6 @@ export default defineConfig({
143155
search: {
144156
provider: "local"
145157
},
146-
socialLinks: [
147-
{icon: "github", link: "https://github.com/observablehq/plot"},
148-
{icon: "x", link: "https://twitter.com/observablehq"},
149-
{icon: "slack", link: "https://observablehq.com/slack/join"},
150-
{icon: "linkedin", link: "https://www.linkedin.com/company/observable"},
151-
{icon: "youtube", link: "https://www.youtube.com/c/Observablehq"}
152-
],
153158
footer: {
154159
message: "Library released under <a style='text-decoration:underline;' href='https://github.com/observablehq/plot/blob/main/LICENSE'>ISC License</a>.",
155160
copyright: `Copyright 2020–${new Date().getUTCFullYear()} Observable, Inc.`

docs/.vitepress/markdown-it-plot.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export default function plot(md) {
2626
directives.includes("hidden")
2727
? `<div style="display: none;">\n`
2828
: href
29-
? `<a class="plot-fork no-icon" href="${md.utils.escapeHtml(href)}?intent=fork" target="_blank" title="Open on Observable">Fork</a>`
29+
? `<a class="plot-fork no-icon" href="${md.utils.escapeHtml(href)}" target="_blank" title="Open on Observable">Fork</a>`
3030
: ""
3131
}`;
3232
if (/^Plot\.plot\(/.test(content)) {

docs/.vitepress/theme/CustomFooter.vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
<li class="mb2"><a target="_blank" href="https://observablehq.com/plot">Plot</a></li>
2626
<li class="mb2"><a target="_blank" href="https://observablehq.com/data-integrations">Integrations</a></li>
2727
<li class="mb2"><a target="_blank" href="https://observablehq.com/pricing">Pricing</a></li>
28-
<li class="mb2"><a target="_blank" href="https://observablehq.com/enterprise">Enterprise</a></li>
2928
</ul>
3029
</div>
3130
</div>

docs/.vitepress/theme/CustomLayout.vue

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import DefaultTheme from "vitepress/theme-without-fonts";
44
import ExamplesGrid from "./ExamplesGrid.vue";
55
import ObservablePromo from "./ObservablePromo.vue";
6+
import VersionAndStars from "./VersionAndStars.vue";
67

78
const {Layout} = DefaultTheme;
89

@@ -16,6 +17,12 @@ const {Layout} = DefaultTheme;
1617
<template #home-features-after>
1718
<ObservablePromo />
1819
</template>
20+
<template #nav-bar-content-after>
21+
<div style="display: flex; gap: 1rem;">
22+
<VersionAndStars />
23+
<observable-made-by />
24+
</div>
25+
</template>
1926
</Layout>
2027
</template>
2128

@@ -35,4 +42,19 @@ const {Layout} = DefaultTheme;
3542
background-color: rgba(37, 37, 41, 0.5);
3643
}
3744

45+
/* Remove unnecessary elements that are empty in our implementation */
46+
.VPNavBarExtra,
47+
.VPNavBarHamburger {
48+
display: none !important;
49+
}
50+
51+
/* rounded corners for search field */
52+
@media (min-width: 768px) {
53+
.DocSearch-Button {
54+
border-radius: 1000px;
55+
padding-right: 0.75rem;
56+
height: 2rem;
57+
}
58+
}
59+
3860
</style>

docs/.vitepress/theme/ExamplesGrid.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ onUnmounted(() => {
4949
<template>
5050
<div :class="$style.examples" ref="container" :style="`transform: translate(${60 - x * 10}vw, 33%);`">
5151
<div v-for="(d, i) in sample" :style="`--delay: ${((i % xn) / xn + (d3.randomLcg(1 / i)()) - 0.4) * 1}s;`">
52-
<a :href="`https://observablehq.com/${d.path}${d.path.includes('?') ? '&' : '?'}intent=fork`" :title="[d.title, d.author].filter(Boolean).join('\n')" target="_blank" :style="`--x: ${(i % xn) - xn / 2 + (Math.floor(i / xn) % 2) * 0.5}; --y: ${Math.floor(i / xn) - yn / 2};`">
52+
<a :href="`https://observablehq.com/${d.path}`" :title="[d.title, d.author].filter(Boolean).join('\n')" target="_blank" :style="`--x: ${(i % xn) - xn / 2 + (Math.floor(i / xn) % 2) * 0.5}; --y: ${Math.floor(i / xn) - yn / 2};`">
5353
<img :src="`https://static.observableusercontent.com/thumbnail/${d.thumbnail}.jpg`" width="640" height="400" />
5454
</a>
5555
</div>

0 commit comments

Comments
 (0)