Skip to content

Commit 45f09c1

Browse files
committed
fix #1327; document resize
1 parent 58acf8b commit 45f09c1

File tree

3 files changed

+63
-25
lines changed

3 files changed

+63
-25
lines changed

docs/javascript.md

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ A program block looks like this (note the semicolon):
2828
const foo = 1 + 2;
2929
```
3030

31-
A program block doesn’t display anything by default, but you can call [`display`](#explicit-display) to display something.
31+
A program block doesn’t display anything by default, but you can call [`display`](#display(value)) to display something.
3232

3333
JavaScript blocks do not show their code by default. If you want to show the code, use the `echo` directive:
3434

@@ -129,7 +129,7 @@ Expressions cannot declare top-level reactive variables. To declare a variable,
129129

130130
## Explicit display
131131

132-
The built-in `display` function displays the specified value.
132+
The built-in [`display` function](#display(value)) displays the specified value.
133133

134134
```js echo
135135
const x = Math.random();
@@ -202,7 +202,7 @@ Inputs.button("Click me", {value: 0, reduce: (i) => displayThere(++i)})
202202

203203
## Implicit display
204204

205-
JavaScript expression fenced code blocks are implicitly wrapped with a call to [`display`](#explicit-display). For example, this arithmetic expression displays implicitly:
205+
JavaScript expression fenced code blocks are implicitly wrapped with a call to [`display`](#display(value)). For example, this arithmetic expression displays implicitly:
206206

207207
```js echo
208208
1 + 2 // implicit display
@@ -238,23 +238,17 @@ Implicit display also implicitly awaits promises.
238238

239239
## Responsive display
240240

241-
In Markdown, the built-in `width` reactive variable represents the current width of the main element. This variable is implemented by [`Generators.width`](./lib/generators#width(element)) and backed by a [`ResizeObserver`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver). The reactive width can be a handy thing to pass, say, as the **width** option to [Observable Plot](./lib/plot).
241+
In Markdown, the built-in [`width` reactive variable](#width) represents the current width of the main element. This variable is implemented by [`Generators.width`](./lib/generators#width(element)) and backed by a [`ResizeObserver`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver). The reactive width can be a handy thing to pass, say, as the **width** option to [Observable Plot](./lib/plot).
242242

243-
```html echo
244-
The current width is ${width}.
245-
```
246-
247-
```js
248-
import {resize} from "npm:@observablehq/stdlib";
243+
```js echo
244+
Plot.barX([9, 4, 8, 1, 11, 3, 4, 2, 7, 5]).plot({width})
249245
```
250246

251-
For more control, or in a [grid](./css/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](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver), and the element returned by the render function is inserted into the DOM.
247+
For non-top-level elements, as when rendering content within an inline expression, use the built-in [`resize` function](#resize(render)) instead. This takes a _render_ function which is called whenever the width or height [changes](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver), and the element returned by the render function is inserted into the DOM.
252248

253249
```html echo
254-
<div class="grid grid-cols-4">
255-
<div class="card">
256-
${resize((width) => `This card is ${width}px wide.`)}
257-
</div>
250+
<div class="card">
251+
${resize((width) => Plot.barX([9, 4, 8, 1, 11, 3, 4, 2, 7, 5]).plot({width}))}
258252
</div>
259253
```
260254

@@ -272,3 +266,45 @@ If your container defines a height, such as `240px` in the example below, then y
272266
```
273267

274268
<div class="tip">If you are using <code>resize</code> with both <code>width</code> and <code>height</code> and see nothing rendered, it may be because your parent container does not have its own height specified. When both arguments are used, the rendered element is implicitly <code>position: absolute</code> to avoid affecting the size of its parent and causing a feedback loop.</div>
269+
270+
## display(*value*)
271+
272+
Displays the specified *value* in the current context, returning *value*. If *value* is a DOM element or node, it is inserted directly into the page. Otherwise, if the current context is a fenced code block, inspects the specified *value*; or, if the current context is an inline expression, coerces the specified *value* to a string and displays it as text.
273+
274+
```js echo
275+
display(1 + 2);
276+
```
277+
278+
See [Explicit display](#explicit-display) for more.
279+
280+
## resize(*render*)
281+
282+
Creates and returns a DIV element to contain responsive content; then, using a [`ResizeObserver`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver) to observe changes to the returned element’s size, calls the specified *render* function with the new width and height whenever the size changes. The element returned by the *render* function is inserted into the DIV element, replacing any previously-rendered content. This is useful for responsive charts.
283+
284+
```js echo
285+
resize((width) => `I am ${width} pixels wide.`)
286+
```
287+
288+
If the *render* function returns a promise, the promise is implicitly awaited. If the resulting value is null, the DIV element is cleared; otherwise, if the resulting value is not a DOM element, it is coerced to a string and displayed as text.
289+
290+
See [Responsive display](#responsive-display) for more.
291+
292+
## width
293+
294+
The current width of the main element in pixels as a reactive variable. A fenced code block or inline expression that references `width` will re-run whenever the width of the main element changes, such as when the window is resized; often used for responsive charts.
295+
296+
```js echo
297+
width
298+
```
299+
300+
See [`Generators.width`](./lib/generators#width(element)) for implementation.
301+
302+
## now
303+
304+
The current time in milliseconds since Unix epoch as a reactive variable. A fenced code block or inline expression that references `now` will run continuously; often used for simple animations.
305+
306+
```js echo
307+
now
308+
```
309+
310+
See [`Generators.now`](./lib/generators#now()) for implementation.

docs/lib/generators.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {Generators} from "npm:@observablehq/stdlib";
88

99
## input(*element*)
1010

11-
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](<../reactivity#inputs>) uses this.
11+
[Source](https://github.com/observablehq/framework/blob/main/src/client/stdlib/generators/input.js) · 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](<../reactivity#inputs>) uses this.
1212

1313
```js echo
1414
const nameInput = display(document.createElement("input"));
@@ -19,9 +19,9 @@ const name = Generators.input(nameInput);
1919
name
2020
```
2121

22-
## observe(*change*)
22+
## observe(*initialize*)
2323

24-
Returns an async generator that yields whenever the callback function *change* is called, with the value passed.
24+
[Source](https://github.com/observablehq/framework/blob/main/src/client/stdlib/generators/observe.js) · 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.
2525

2626
```js echo
2727
const hash = Generators.observe((change) => {
@@ -37,7 +37,9 @@ hash
3737

3838
## queue(*change*)
3939

40-
Returns an async generator that yields whenever the callback function *change* is called, with the value passed. 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.
40+
[Source](https://github.com/observablehq/framework/blob/main/src/client/stdlib/generators/queue.js) · 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.
41+
42+
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.
4143

4244
```js run=false
4345
const hash = Generators.queue((change) => {
@@ -53,7 +55,7 @@ hash
5355

5456
## now()
5557

56-
Returns a generator that repeatedly yields `Date.now()`, forever. This generator is available by default as `now` in Markdown.
58+
[Source](https://github.com/observablehq/framework/blob/main/src/client/stdlib/generators/now.js) · Returns a generator that repeatedly yields `Date.now()`, forever. This generator is available by default as `now` in Markdown.
5759

5860
```js run=false
5961
const now = Generators.now();
@@ -65,7 +67,7 @@ now
6567

6668
## width(*element*)
6769

68-
Returns an async generator that yields the width of the given target *element*. Using a [ResizeObserver](https://developer.mozilla.org/en-US/docs/Web/API/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.
70+
[Source](https://github.com/observablehq/framework/blob/main/src/client/stdlib/generators/width.js) · Returns an async generator that yields the width of the given target *element*. Using a [ResizeObserver](https://developer.mozilla.org/en-US/docs/Web/API/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.
6971

7072
```js run=false
7173
const width = Generators.width(document.querySelector("main"));
@@ -77,7 +79,7 @@ width
7779

7880
## dark() <a href="https://github.com/observablehq/framework/releases/tag/v1.3.0" class="observablehq-version-badge" data-version="^1.3.0" title="Added in 1.3.0"></a>
7981

80-
Returns an async generator that yields a boolean indicating whether the page is currently displayed with a dark [color scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme).
82+
[Source](https://github.com/observablehq/framework/blob/main/src/client/stdlib/generators/dark.js) · Returns an async generator that yields a boolean indicating whether the page is currently displayed with a dark [color scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme).
8183

8284
If the page supports both light and dark mode (as with the [default theme](../themes)), the value reflects the user’s [preferred color scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-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.
8385

src/client/stdlib/resize.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// TODO Automatically disconnect the observer when the returned DIV is detached.
22
export function resize(
3-
render: (width: number, height: number) => Node | null | Promise<Node | null>,
3+
render: (width: number, height: number) => Node | string | null | Promise<Node | string | null>,
44
invalidation?: Promise<void>
55
): Node {
66
const div = document.createElement("div");
@@ -24,6 +24,6 @@ export function resize(
2424
return div;
2525
}
2626

27-
function isElement(node: Node): node is HTMLElement {
28-
return node.nodeType === 1;
27+
function isElement(node: Node | string): node is HTMLElement {
28+
return typeof node === "object" && node.nodeType === 1;
2929
}

0 commit comments

Comments
 (0)