Use Curvenote - logo

NPM Version MIT License GitHub Stars Twitter Follow



The @curvenote/components package comes with a number of web-components for interative scientific writing. Variables need to be defined to drive your dynamic document, the r-var web component can specify a name and a value as attributes. In the following example, we will create reactive variables for $x$ and $y$ and then control them with sliders and dynamic text.

If we have ranges for two variables:
X: , which is
Y: , which is
Or you can set the value directly in the text for X= and Y= .
The product of X and Y is .

Here we have created three variables, one of which (xy) will update when either x or y is changed! The text is just normal html and we can interleave some reactive inputs to change the values of x or y. Also included in the example are a <r-range> and a <r-dynamic>, which correspond to a slider and dynamic text, respectively.

Reactive Variables

The syntax to create a reactive variable is simply writing the following HTML and including it in your page:

<r-var name="x" value="1"></r-var>

These variables are hidden in the DOM by default, you can change the styles globally or by changing the style to include display: block.

You can also create reactive variables which will execute a user-defined string with access to all other variables in the scope r-scope (more on that below!). Note here that the :value has a semi-colon to show that this should be executed to define the value.

<r-var name="xy" :value="x * y"></r-var>

As you might expect, this will multiply $x$ and $y$, and store the result in the variable xy.

Display Variables

To display an element create an r-display, which will just render value as text. As before, the syntax :value will evaluate the string and store the result.

<r-display :value="x"></r-display>

Remember that $x$ is a number that is reactive: .
Try setting the value of $x$ with the range input:

You can also :transform the value of a variable before you format it. For example, you might want to say that the admission to a park is 'free' when the value == 0.

The park admission is .

You can also use this :transform to say that the park admission is .
This is also quite useful if you want to use the transform to index into an array , in this case emoji array - but it could be numeric too!

Controlling Variables

What gets slightly more exciting is when you can bring these together with inputs that can be ranges or dynamic text elements that you can drag. This can be setup most easily using the bind attribute:

<r-dynamic bind="x"></r-dynamic>

This allows you to set the value of $x$ inline: or $y=$ . Or create a slider over a range:
Notice how all components update reactively to the r-range and r-display πŸš€.

For the <r-dynamic> component you can also add text inside of the dynamic text, for example, , includes an after="ΒΊC" attributes.

<r-dynamic bind="y" after="ΒΊC"></r-dynamic>

You can also create ranges with identical syntax:

<r-range bind="x"></r-range>

Events and Bind Syntax

There are times where you want more control over how your data gets displayed, updated or informs other variables. In the code above we have actually taken a shortcut to bind a range or dynamic text to a named variable. This amounts to the default two way connection:

<r-dynamic bind="x" ></r-dynamic>

When the variable x updates, the value is set, and when the control sends a change event, the updated value is set to the variable x! Under the hood, when the bind attribute is defined, the :value and the default event (e.g. :change) functions are automatically set.

<r-dynamic :value="x" :change="{ x: value }" ></r-dynamic>

As with other properties, the : syntax for the value property recomputes every time there is a change. For example, if you put :value="x" then anytime the variable x changes, the value of the control updates. However, this is not the case in reverse! You have to explicitly hook up to the :change event to change the variable (or variables) you want to update. This is done using a JSON dictionary of the form:
{ variable: value }
You can think of this as the following function:

function change(value) { return { "x": value }; }

Both the name of the event, as well as the arguments are specific to the component, for example, a drag-node in a chart might have the function:

function drag(x, y) { return { "phase": x, "amplitude": y / 300 }; }

As in the example above, you can update multiple variables at a time. If you choose to explicitly set these, and not just use the bind property, you can do some interesting things!


Namespaces are one honking great idea -- let's do more of those!

Tim Peters

The r-scope component allows you to split your document into logical blocks, and keep the variables in that scope distinct.

Scope: πŸ‘‹

The value of foo is .
The value of bar is .

Scope: 🌎

The value of foo is .
The value of bar is .

The scope must have a name, although it doesn't have to be unique. For example, if you want to add other elements or variables to that scope later on:

Scope: 🌎


You can also update variables in other scopes:

Scope: 🌝

🌝 🌎

That's it for an overview of using @curvenote/components, next up, is seeing the components that you have available to you out of the box!

Made with love by Curvenote
Last updated February 19th, 2021