gum-jsx 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -6
- package/claude/.claude-plugin/plugin.json +8 -0
- package/claude/.mcp.json +10 -0
- package/claude/skills/gum-jsx/SKILL.md +317 -0
- package/claude/skills/gum-jsx/references/layout.md +132 -0
- package/claude/skills/gum-jsx/references/networks.md +90 -0
- package/claude/skills/gum-jsx/references/plotting.md +129 -0
- package/claude/skills/gum-jsx/references/shapes.md +138 -0
- package/claude/skills/gum-jsx/references/symbolic.md +141 -0
- package/claude/skills/gum-jsx/references/text.md +114 -0
- package/claude/skills/gum-jsx/references/utilities.md +123 -0
- package/docs/code/group.jsx +1 -1
- package/docs/code/points.jsx +1 -1
- package/docs/code/rect.jsx +1 -1
- package/docs/code/stack.jsx +1 -1
- package/docs/code/symfield.jsx +1 -1
- package/docs/code/sympoints.jsx +1 -1
- package/docs/gala/complex_plot.jsx +4 -4
- package/docs/gala/metal_grid.jsx +1 -1
- package/docs/gala/plot_manual.jsx +2 -2
- package/docs/text/colors.md +1 -1
- package/docs/text/element.md +2 -0
- package/docs/text/graph.md +4 -2
- package/docs/text/group.md +2 -2
- package/docs/text/gum.md +1 -1
- package/docs/text/network.md +1 -1
- package/docs/text/plot.md +1 -1
- package/docs/text/symline.md +0 -2
- package/package.json +28 -35
- package/scripts/claude.ts +29 -0
- package/scripts/{cli.js → cli.ts} +23 -11
- package/scripts/mcp.ts +52 -0
- package/scripts/skill.ts +57 -0
- package/scripts/test.ts +32 -0
- package/src/elems/core.ts +740 -0
- package/src/elems/geometry.ts +600 -0
- package/src/elems/layout.ts +515 -0
- package/src/elems/network.ts +257 -0
- package/src/elems/plot.ts +702 -0
- package/src/elems/slide.ts +93 -0
- package/src/elems/symbolic.ts +346 -0
- package/src/elems/text.ts +424 -0
- package/src/{eval.js → eval.ts} +16 -6
- package/src/fonts/fonts.browser.ts +20 -0
- package/src/fonts/fonts.node.ts +17 -0
- package/src/fonts/fonts.ts +34 -0
- package/src/gum.ts +30 -0
- package/src/lib/const.ts +54 -0
- package/src/{math.js → lib/math.ts} +26 -14
- package/src/{parse.js → lib/parse.ts} +32 -24
- package/src/{term.js → lib/term.ts} +5 -5
- package/src/{text.js → lib/text.ts} +29 -24
- package/src/lib/theme.ts +140 -0
- package/src/lib/types.ts +49 -0
- package/src/lib/utils.ts +819 -0
- package/src/{meta.js → meta.ts} +14 -6
- package/src/{render.js → render.ts} +37 -13
- package/src/types/linebreak.d.ts +13 -0
- package/src/types/opentype.d.ts +381 -0
- package/index.d.ts +0 -1271
- package/scripts/server.js +0 -69
- package/src/defaults.js +0 -177
- package/src/fonts.browser.js +0 -16
- package/src/fonts.js +0 -32
- package/src/fonts.node.js +0 -17
- package/src/gum.js +0 -3416
- package/src/utils.js +0 -384
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Plotting Elements
|
|
2
|
+
|
|
3
|
+
## Graph
|
|
4
|
+
|
|
5
|
+
*Inherits*: **Group** > **Element**
|
|
6
|
+
|
|
7
|
+
This is the core graphing functionality used in **Plot** without the axes and labels. By default, the coordinate system is automatically inferred from the limits of child elements. This can be overridden with custom `xlim`/`ylim` specifications. The Elements that are passed to **Graph** can express their position and size information in this new coordinate system.
|
|
8
|
+
|
|
9
|
+
You'll often want to use this (directly or indirectly) to display mathematical curves, as they might otherwise come out looking upside down relative to what you expect (as higher y-values mean "down" in raw SVG).
|
|
10
|
+
|
|
11
|
+
Parameters:
|
|
12
|
+
- `xlim`/`ylim` = `[0, 1]` — the range over which to graph
|
|
13
|
+
- `padding` = `0` — limit padding to add when auto-detected from `elems`
|
|
14
|
+
- `coord` = `'auto'` — the coordinate system to use for the graph (overrides `xlim`/`ylim`)
|
|
15
|
+
|
|
16
|
+
**Example**
|
|
17
|
+
|
|
18
|
+
Prompt: a series of closely spaced squares rotating clockwise along a sinusoidal path
|
|
19
|
+
|
|
20
|
+
Generated code:
|
|
21
|
+
```jsx
|
|
22
|
+
<Graph ylim={[-1.5, 1.5]} padding={0.2} aspect={2}>
|
|
23
|
+
<SymPoints
|
|
24
|
+
fy={sin} xlim={[0, 2*pi]} size={0.5} N={100}
|
|
25
|
+
shape={x => <Square rounded spin={r2d*x} />}
|
|
26
|
+
/>
|
|
27
|
+
</Graph>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Plot
|
|
31
|
+
|
|
32
|
+
*Inherits*: **Group** > **Element**
|
|
33
|
+
|
|
34
|
+
Uses **Graph** to plot one or more elements over the desired limits and frame them with axes. If not specified by `xlim` and `ylim`, the limits of the plot will be computed from the bounding box of the constituent elements. By default, the `aspect` will be the ratio of the range of the `xlim` and `ylim`. See **Axis** for more details on how to customize the axes, ticks, and labels.
|
|
35
|
+
|
|
36
|
+
Parameters:
|
|
37
|
+
- `xlim`/`ylim` = `[0, 1]` — the range over which to graph
|
|
38
|
+
- `xanchor`/`yanchor` — the value at which to place the respective axis. Note that the `xanchor` is a y-value and vice versa. Defaults to `xmin`/`ymin`
|
|
39
|
+
- `xticks`/`yticks` = `5` — either an integer for evenly spaced ticks, a list of tick locations, or list of tick `**location, label]` pairs (see [Axis** for more details)
|
|
40
|
+
- `grid`/`xgrid`/`ygrid` = `false` — whether to show a grid in the background. If `true`, the grid lines match the specified ticks. Alternatively, you can pass a list of positions to override this
|
|
41
|
+
- `xlabel`/`ylabel` — a string or **Element** to use as the respective label
|
|
42
|
+
- `title` — a string or **Element** to use as the title
|
|
43
|
+
- `padding` = `0` — additional padding to add to auto-detected coordinate limits
|
|
44
|
+
- `margin` = `0` — margin to add around the plot (needed to include labels and title)
|
|
45
|
+
- `border` = `0` — border width to use
|
|
46
|
+
- `clip` = `false` — clip graph contents to specified coordinates
|
|
47
|
+
|
|
48
|
+
Subunits:
|
|
49
|
+
- `axis`/`xaxis`/`yaxis` — the axes, including lines, ticks, and tick labels
|
|
50
|
+
- `grid`/`xgrid`/`ygrid` — the grid lines arrayed under the graph
|
|
51
|
+
- `label`/`xlabel`/`ylabel` — the axis label elements
|
|
52
|
+
- `title` — the plot title element
|
|
53
|
+
|
|
54
|
+
**Example**
|
|
55
|
+
|
|
56
|
+
Prompt: plot an inverted sine wave with ticks labeled in multiples of π. There is a faint dashed grid. The x-axis is labeled "phase" and the y-axis is labeled "amplitude". The title is "Inverted Sine Wave".
|
|
57
|
+
|
|
58
|
+
Generated code:
|
|
59
|
+
```jsx
|
|
60
|
+
const xticks = linspace(0, 2, 6).slice(1).map(x => [x*pi, `${rounder(x, 1)} π`])
|
|
61
|
+
return <Plot aspect={phi} margin={0.25} xanchor={0} xticks={xticks} xlabel="phase" ylabel="amplitude" title="Inverted Sine Wave" xaxis-tick-side="both" grid grid-stroke-dasharray={3}>
|
|
62
|
+
<SymLine fy={x => -sin(x)} xlim={[0, 2*pi]} />
|
|
63
|
+
</Plot>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Axis
|
|
67
|
+
|
|
68
|
+
*Inherits*: **Group** > **Element**
|
|
69
|
+
|
|
70
|
+
A single vertical or horizontal axis for plotting. This includes the central line, the perpendicual ticks, and their associated tick labels. Note that the proper bounds encompass only the central line and ticks, while the tick labels may fall well outside of them. Use **HAxis** and **VAxis** for specific directions.
|
|
71
|
+
|
|
72
|
+
Because `Axis` is used primarily for **Plot**, the `tick-side` parameter is inverted for `VAxis`, meaning `outer` points up and `inner` points down. Meanwhile, for `HAxis`, `outer` points to the left and `inner` points to the right.
|
|
73
|
+
|
|
74
|
+
Parameters:
|
|
75
|
+
- `direc` — the orientation of the axis, either `v` (vertical) or `h` (horizontal)
|
|
76
|
+
- `ticks` — a list of tick `[location, label]` pairs. The label can either be an `Element` or a string
|
|
77
|
+
- `lim` = `[0, 1]` — the extent of the element along the main axis
|
|
78
|
+
- `tick-side` = `'both'` — one of `'inner'` / `'outer'` / `'both'` / `'none'` , or a pair representing a numerical range in `[0, 1]`, where zero is oriented in the inner direction
|
|
79
|
+
- `label-side` = same as `tick-side` but for the labels
|
|
80
|
+
- `children` = a list of `Element`s to use as the tick labels instead of `ticks`. These must have a `loc` to tell `Axis` where to place the label and associated tick.
|
|
81
|
+
|
|
82
|
+
Subunits:
|
|
83
|
+
- `line`: the central line along the main axis
|
|
84
|
+
- `tick`: the perpendicular tick marks (collectively)
|
|
85
|
+
- `label`: the labels annotating the tick marks (collectively)
|
|
86
|
+
|
|
87
|
+
**Example**
|
|
88
|
+
|
|
89
|
+
Prompt: a horizontal axis with 5 ticks labeled with emojis for: mount fuji, a rocket, a whale, a watermellon, and a donut
|
|
90
|
+
|
|
91
|
+
Generated code:
|
|
92
|
+
```jsx
|
|
93
|
+
const emoji = ['🗻', '🚀', '🐳', '🍉', '🍩']
|
|
94
|
+
const ticks = zip(linspace(0, 1, emoji.length), emoji)
|
|
95
|
+
return <Box padding={[0.5, 1]}>
|
|
96
|
+
<HAxis aspect={10} ticks={ticks} tick-side="outer" label-size={1} />
|
|
97
|
+
</Box>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## BarPlot
|
|
101
|
+
|
|
102
|
+
*Inherits*: **Plot** > **Group** > **Element**
|
|
103
|
+
|
|
104
|
+
Makes a plot featuring a bar graph. This largely wraps the functionality of **Plot** but takes care of labelling and arranging the `xaxis` information. You can provide `label` and `size` attributes to the child elements. The **Bar**/**VBar**/**HBar** elements are just very thin wrappers around **Rect** elements, and you can use other elements in their place if you wish.
|
|
105
|
+
|
|
106
|
+
To layout just the bars without axes, use the **Bars** element directly, which this wraps using **Plot**. This way, you can plot other elements alongside the bars, such as labels or error bars. By default, the bars will be placed at `[0, ..., N-1]` along the x-axis.
|
|
107
|
+
|
|
108
|
+
Child parameters:
|
|
109
|
+
- `label` — the label for the bar
|
|
110
|
+
- `size` — the height of the bar
|
|
111
|
+
|
|
112
|
+
Parameters:
|
|
113
|
+
- `direc` = `v` — the orientation of the bars in the plot
|
|
114
|
+
|
|
115
|
+
Subunit names:
|
|
116
|
+
- `bar` — keywords to pass to the underlying **Bars** element
|
|
117
|
+
|
|
118
|
+
**Example**
|
|
119
|
+
|
|
120
|
+
Prompt: A plot with three bars with black borders at "A", "B", and "C". The first bar is red and is the shortest, the second bar is blue and is the tallest, while the third bar is green and its height is in between.
|
|
121
|
+
|
|
122
|
+
Generated code:
|
|
123
|
+
```jsx
|
|
124
|
+
<BarPlot ylim={[0, 10]} yticks={6} ygrid title="Example BarPlot" xlabel="Category" ylabel="Value" margin={0.25}>
|
|
125
|
+
<Bar label="A" size={3} fill={red} />
|
|
126
|
+
<Bar label="B" size={8.5} fill={blue} />
|
|
127
|
+
<Bar label="C" size={6.5} fill={green} />
|
|
128
|
+
</BarPlot>
|
|
129
|
+
```
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Shapes Elements
|
|
2
|
+
|
|
3
|
+
## Rect
|
|
4
|
+
|
|
5
|
+
*Inherits*: **Element**
|
|
6
|
+
|
|
7
|
+
This makes a rectangle. Without any arguments it will fill its entire allocated space. Unless otherwise specified, it has a `null` aspect. Use **Square** for a square with a unit aspect.
|
|
8
|
+
|
|
9
|
+
Specifying a `rounded` argument will round the borders by the same amount for each corner. This can be either a scalar or a pair of scalars corresponding to the x and y radii of the corners. To specify different roundings for each corner, use the **RoundedRect** element.
|
|
10
|
+
|
|
11
|
+
Parameters:
|
|
12
|
+
- `rounded` = `null` — proportional border rounding, accepts either scalar or pair of scalars
|
|
13
|
+
|
|
14
|
+
**Example**
|
|
15
|
+
|
|
16
|
+
Prompt: a rectangle on the left side of the figure with an aspect of roughly 1/2
|
|
17
|
+
|
|
18
|
+
Generated code:
|
|
19
|
+
```jsx
|
|
20
|
+
<Rectangle pos={[0.25, 0.5]} rad={[0.1, 0.2]}/>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Ellipse
|
|
24
|
+
|
|
25
|
+
*Inherits*: **Element**
|
|
26
|
+
|
|
27
|
+
This makes an ellipse. Without any arguments it will inscribe its allocated space. Use **Circle** for a circle with a unit aspect.
|
|
28
|
+
|
|
29
|
+
**Example**
|
|
30
|
+
|
|
31
|
+
Prompt: two ellipses, one wider and one taller
|
|
32
|
+
|
|
33
|
+
Generated code:
|
|
34
|
+
```jsx
|
|
35
|
+
<Group>
|
|
36
|
+
<Ellipse pos={[0.3, 0.2]} rad={[0.2, 0.1]} />
|
|
37
|
+
<Ellipse pos={[0.6, 0.6]} rad={[0.2, 0.25]} />
|
|
38
|
+
</Group>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Line
|
|
42
|
+
|
|
43
|
+
*Inherits*: **Element**
|
|
44
|
+
|
|
45
|
+
The `Line` element draws line segments through a series of points. It accepts a list of two or more points and connects them with straight line segments.
|
|
46
|
+
|
|
47
|
+
There are specialized variants for vertical and horizontal lines called **VLine** and **HLine**, which allow you to specify the position of the line (`loc`) and the range of the line (`lim`). See **UnitLine** for more details.
|
|
48
|
+
|
|
49
|
+
For smooth curves through points, use **Spline** instead.
|
|
50
|
+
|
|
51
|
+
Parameters:
|
|
52
|
+
- `children` — array of point coordinates (minimum of 2 required)
|
|
53
|
+
|
|
54
|
+
**Example**
|
|
55
|
+
|
|
56
|
+
Prompt: draw a diagonal line in blue and a cup shaped line in red
|
|
57
|
+
|
|
58
|
+
Generated code:
|
|
59
|
+
```jsx
|
|
60
|
+
<Group>
|
|
61
|
+
<Line stroke={blue}>{[
|
|
62
|
+
[0.2, 0.2],
|
|
63
|
+
[0.8, 0.8],
|
|
64
|
+
]}</Line>
|
|
65
|
+
<Line stroke={red}>{[
|
|
66
|
+
[0.3, 0.3],
|
|
67
|
+
[0.3, 0.7],
|
|
68
|
+
[0.7, 0.7],
|
|
69
|
+
[0.7, 0.3],
|
|
70
|
+
]}</Line>
|
|
71
|
+
</Group>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Shape
|
|
75
|
+
|
|
76
|
+
*Inherits*: **Pointstring** > **Element**
|
|
77
|
+
|
|
78
|
+
The `Shape` element draws a closed polygon through a series of points. It accepts a list of two or more points and connects them with straight line segments, automatically closing the shape by connecting the last point back to the first.
|
|
79
|
+
|
|
80
|
+
For open multiple-segment paths, use **Line** instead.
|
|
81
|
+
|
|
82
|
+
Parameters:
|
|
83
|
+
- `children` — array of point coordinates (minimum of 2 required)
|
|
84
|
+
|
|
85
|
+
**Example**
|
|
86
|
+
|
|
87
|
+
Prompt: draw a blue triangle with a semi-transparent green square overlaid on top
|
|
88
|
+
|
|
89
|
+
Generated code:
|
|
90
|
+
```jsx
|
|
91
|
+
<Group>
|
|
92
|
+
<Shape fill={blue} stroke={none}>{[
|
|
93
|
+
[0.5, 0.2],
|
|
94
|
+
[0.8, 0.8],
|
|
95
|
+
[0.2, 0.8]
|
|
96
|
+
]}</Shape>
|
|
97
|
+
<Shape fill={green} stroke={none} opacity={0.5}>{[
|
|
98
|
+
[0.3, 0.3],
|
|
99
|
+
[0.7, 0.3],
|
|
100
|
+
[0.7, 0.7],
|
|
101
|
+
[0.3, 0.7]
|
|
102
|
+
]}</Shape>
|
|
103
|
+
</Group>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Spline
|
|
107
|
+
|
|
108
|
+
*Inherits*: **Path** > **Element**
|
|
109
|
+
|
|
110
|
+
This creates a smooth cardinal spline curve through a series of points. The tangent at each interior point is computed as the central difference between its neighbors, while endpoints use forward/backward differences. This produces a smooth, natural-looking curve that passes through all specified points.
|
|
111
|
+
|
|
112
|
+
The `curve` parameter controls the tension of the spline. Lower values (e.g., 0.5) create tighter curves with less overshoot, while higher values (e.g., 1.5) create looser, more flowing curves. The default value of 0.5 produces the canonical *Catmull-Rom* spline.
|
|
113
|
+
|
|
114
|
+
Parameters:
|
|
115
|
+
- `children` — array of point coordinates (minimum of 2 required)
|
|
116
|
+
- `curve` = `0.5` — tension parameter that scales the tangent vectors
|
|
117
|
+
- `closed` = `false` — toggles whether to make it a closed loop
|
|
118
|
+
- `tan1`/`tan2` — the tangent vectors at the first and last points
|
|
119
|
+
|
|
120
|
+
**Example**
|
|
121
|
+
|
|
122
|
+
Prompt: draw a blue cubic spline path filled with gray that looks like a pacman facing left, using 5 vertices. label the vertices with black dots and connect them with straight red lines. place the whole thing in a rounded frame.
|
|
123
|
+
|
|
124
|
+
Generated code:
|
|
125
|
+
```jsx
|
|
126
|
+
const points = [
|
|
127
|
+
[0.25, 0.25],
|
|
128
|
+
[0.75, 0.25],
|
|
129
|
+
[0.75, 0.75],
|
|
130
|
+
[0.25, 0.75],
|
|
131
|
+
[0.50, 0.50],
|
|
132
|
+
]
|
|
133
|
+
return <Frame rounded margin>
|
|
134
|
+
<Spline closed stroke={blue} fill={gray}>{points}</Spline>
|
|
135
|
+
<Shape stroke={red}>{points}</Shape>
|
|
136
|
+
<Points size={0.0075}>{points}</Points>
|
|
137
|
+
</Frame>
|
|
138
|
+
```
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Symbolic Elements
|
|
2
|
+
|
|
3
|
+
## SymPoints
|
|
4
|
+
|
|
5
|
+
*Inherits*: **Group** > **Element**
|
|
6
|
+
|
|
7
|
+
Flexible interface to generate sets of points symbolically or in combination with fixed inputs. The most common usage is to specify the range for x-values with `xlim` and a function to plot with `fy`. But you can specify the transpose with `ylim`/`fx`, or do a fully parametric path using `tlim`/`fx`/`fy`.
|
|
8
|
+
|
|
9
|
+
You can also specify the radius of the points functionally with `size` and the shape with `shape`. Both of these functions take `(x, y, t, i)` values as inputs and return the desired value for each point.
|
|
10
|
+
|
|
11
|
+
Parameters:
|
|
12
|
+
- `fx`/`fy` — a function mapping from x-values, y-values, or t-values
|
|
13
|
+
- `size` = `0.025` — a size or a function mapping from `(x, y, t, i)` values to a size
|
|
14
|
+
- `shape` = `Dot` — a shape or function mapping from `(x, y, t, i)` values to a shape
|
|
15
|
+
- `xlim`/`ylim`/`tlim` — a pair of numbers specifying variable limits
|
|
16
|
+
- `xvals`/`yvals`/`tvals` — a list of x-values, y-values, or t-values to use
|
|
17
|
+
- `N` — number of data points to generate when using limits
|
|
18
|
+
|
|
19
|
+
**Example**
|
|
20
|
+
|
|
21
|
+
Prompt: A plot of a sine wave in blue. There are white pill shaped line markers along the sine wave that are rotated to follow the slope of the curve.
|
|
22
|
+
|
|
23
|
+
Generated code:
|
|
24
|
+
```jsx
|
|
25
|
+
const Pill = args => <Rectangle fill={white} rounded={0.3} aspect={2} {...args} />
|
|
26
|
+
return <Plot xlim={[0, 2*pi]} ylim={[-1.5, 1.5]} grid fill={lightgray} margin={[0.25, 0.1]} aspect="auto">
|
|
27
|
+
<SymLine fy={sin} stroke={blue} stroke-width={2} />
|
|
28
|
+
<SymPoints fy={sin} size={0.125} N={11} shape={x => <Pill spin={-r2d*atan(cos(x))}/>} />
|
|
29
|
+
</Plot>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## SymLine
|
|
33
|
+
|
|
34
|
+
*Inherits*: **Line** > **Element**
|
|
35
|
+
|
|
36
|
+
Flexible interface to generate two-dimensional paths symbolically or in combination with fixed inputs. There are variety of acceptable input combinations, but the most common usage is to specify the range to use for x-values with `xlim` and a function to plot with `fy`. To plot a polygon instead of a line, use **SymShape**.
|
|
37
|
+
|
|
38
|
+
Alternatively, you can specify the transpose with `ylim`/`fx`, or even do a fully parametric path using `tlim`/`fx`/`fy`. In any of these cases, one can either specify limits with `xlim`/`ylim`/`tlim` or specific values with `xvals`/`yvals`/`tvals`.
|
|
39
|
+
|
|
40
|
+
Parameters:
|
|
41
|
+
- `fx`/`fy` — a function mapping from x-values, y-values, or t-values
|
|
42
|
+
- `xlim`/`ylim`/`tlim` — a pair of numbers specifying variable limits
|
|
43
|
+
- `xvals`/`yvals`/`tvals` — a list of x-values, y-values, or t-values to use
|
|
44
|
+
- `N` — number of data points to generate when using limits
|
|
45
|
+
|
|
46
|
+
**Example**
|
|
47
|
+
|
|
48
|
+
Prompt: plot two lines: (1) a sine wave in red; (2) the same sine wave with a lower amplitude higher frequency sine wave added on top (in blue)
|
|
49
|
+
|
|
50
|
+
Generated code:
|
|
51
|
+
```jsx
|
|
52
|
+
<Plot xlim={[0, 2*pi]} ylim={[-1.5, 1.5]} aspect={phi} margin={0.2} grid>
|
|
53
|
+
<SymLine fy={sin} stroke={red} stroke-width={2} />
|
|
54
|
+
<SymLine fy={x => sin(x) + 0.2*sin(5*x)} stroke={blue} stroke-width={2} />
|
|
55
|
+
</Plot>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## SymShape
|
|
59
|
+
|
|
60
|
+
*Inherits*: **Shape** > **Pointstring** > **Element**
|
|
61
|
+
|
|
62
|
+
Flexible interface to generate shapes symbolically or in combination with fixed inputs. Operates similarly to **Shape**, but generates a shape from the points generated by `fx`/`fy`.
|
|
63
|
+
|
|
64
|
+
Parameters:
|
|
65
|
+
- `fx`/`fy` — a function mapping from x-values, y-values, or t-values
|
|
66
|
+
- `xlim`/`ylim`/`tlim` — a pair of numbers specifying variable limits
|
|
67
|
+
- `xvals`/`yvals`/`tvals` — a list of x-values, y-values, or t-values to use
|
|
68
|
+
- `N` — number of data points to generate when using limits
|
|
69
|
+
|
|
70
|
+
**Example**
|
|
71
|
+
|
|
72
|
+
Prompt: Draw a rounded star shape with a blue fill. Wrap it in a rounded frame.
|
|
73
|
+
|
|
74
|
+
Generated code:
|
|
75
|
+
```jsx
|
|
76
|
+
const rad = t => 1 - 0.3 * cos(2.5 * t)**2
|
|
77
|
+
return <Frame rounded padding margin>
|
|
78
|
+
<SymShape aspect fill={blue}
|
|
79
|
+
tlim={[0, 2*pi]} N={200}
|
|
80
|
+
fx={t => rad(t) * sin(t)}
|
|
81
|
+
fy={t => rad(t) * cos(t)}
|
|
82
|
+
/>
|
|
83
|
+
</Frame>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## SymSpline
|
|
87
|
+
|
|
88
|
+
*Inherits*: **Spline** > **Path** > **Element**
|
|
89
|
+
|
|
90
|
+
Flexible interface to generate smooth two-dimensional spline curves symbolically or in combination with fixed inputs. Similar to **SymLine**, but produces smooth cardinal splines instead of straight line segments. See **Spline** for more details on the `curve` parameter.
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
Parameters:
|
|
94
|
+
- `fx`/`fy` — a function mapping from x-values, y-values, or t-values
|
|
95
|
+
- `xlim`/`ylim`/`tlim` — a pair of numbers specifying variable limits
|
|
96
|
+
- `xvals`/`yvals`/`tvals` — a list of x-values, y-values, or t-values to use
|
|
97
|
+
- `N` — number of data points to generate when using limits
|
|
98
|
+
- `curve` = `0.5` — tension parameter that scales the tangent vectors
|
|
99
|
+
|
|
100
|
+
**Example**
|
|
101
|
+
|
|
102
|
+
Prompt: smooth damped oscillation using sparse sampling (N=10)
|
|
103
|
+
|
|
104
|
+
Generated code:
|
|
105
|
+
```jsx
|
|
106
|
+
// shows how spline interpolates between discrete function samples
|
|
107
|
+
// display the true function in gray with low opacity
|
|
108
|
+
const decay = x => exp(-x/2) * sin(3*x)
|
|
109
|
+
|
|
110
|
+
return <Plot xlim={[0, 2*pi]} ylim={[-1, 1]} grid margin={0.15} aspect={phi}>
|
|
111
|
+
<SymLine fy={decay} opacity={0.25} N={200} />
|
|
112
|
+
<SymSpline fy={decay} N={10} stroke={blue} stroke-width={2} />
|
|
113
|
+
<SymPoints fy={decay} N={10} size={0.05} fill={red} />
|
|
114
|
+
</Plot>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## SymFill
|
|
118
|
+
|
|
119
|
+
*Inherits*: **Polygon** > **Element**
|
|
120
|
+
|
|
121
|
+
Flexible interface to generate filled in paths symbolically or in combination with fixed inputs. This generates a polygon by running through the points generated by `fx1`/`fy1` and then backwards through the points generated by `fx2`/`fy2`. To generate a simple filled curve, pass your function to `fy1` and let `fy2` be `0`.
|
|
122
|
+
|
|
123
|
+
Parameters:
|
|
124
|
+
- `fx1`/`fy1` — a function generating one of the bounds for the fill (or a constant)
|
|
125
|
+
- `fx2`/`fy2` — a function generating the other bound for the fill (or a constant)
|
|
126
|
+
- `xlim`/`ylim`/`tlim` — a pair of numbers specifying variable limits
|
|
127
|
+
- `xvals`/`yvals`/`tvals` — a list of x-values, y-values, or t-values to use
|
|
128
|
+
- `N` — number of data points to generate when using limits
|
|
129
|
+
|
|
130
|
+
**Example**
|
|
131
|
+
|
|
132
|
+
Prompt: a decaying sine wave filled in with blue
|
|
133
|
+
|
|
134
|
+
Generated code:
|
|
135
|
+
```jsx
|
|
136
|
+
const decay = x => exp(-0.1*x) * sin(x)
|
|
137
|
+
return <Graph xlim={[0, 6*pi]} ylim={[-1, 1]} aspect={phi}>
|
|
138
|
+
<SymFill fy1={decay} fy2={0} fill={blue} fill-opacity={0.5} N={250} />
|
|
139
|
+
<SymLine fy={decay} N={250} />
|
|
140
|
+
</Graph>
|
|
141
|
+
```
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Text Elements
|
|
2
|
+
|
|
3
|
+
## Text
|
|
4
|
+
|
|
5
|
+
*Inherits*: **VStack** > **Element**
|
|
6
|
+
|
|
7
|
+
Displays text and other elements. Uses built-in browser facilities when available to calculate font size and aspect ratio. Note that you will typically not set the font size of the text here, as this will fill the entire space with the provided text.
|
|
8
|
+
|
|
9
|
+
If `wrap` is specified, the text will be wrapped to the specified width. In either case, single newlines will be respected, though whitespace will be compressed. There are two wrapper elements related to text:
|
|
10
|
+
|
|
11
|
+
- **TextBox** / **TextFrame** can handle text with a border and background
|
|
12
|
+
- **TextStack** can handle multiple lines of text that are passed in as an array
|
|
13
|
+
|
|
14
|
+
Parameters:
|
|
15
|
+
- `children` — the text to display
|
|
16
|
+
- `wrap` = `null` — the width (in ems) to wrap the text at (if `null`, the text will not be wrapped)
|
|
17
|
+
- `spacing` = `0.2` — the spacing between lines of text
|
|
18
|
+
- `justify` = `'left'` — the horizontal justification of the text
|
|
19
|
+
- `color` = `black` — sets the text color using both stroke and fill (this is the usual way)
|
|
20
|
+
- `font-family` = `'IBMPlexSans'` — the font family (for display and size calculations)
|
|
21
|
+
- `font-weight` = `100` — the font weight (for display and size calculations)
|
|
22
|
+
|
|
23
|
+
**Example**
|
|
24
|
+
|
|
25
|
+
Prompt: The text "Hello World! You can mix text and other elements together." with a blue square between "and" and "other". Put it in a rounded frame with padding.
|
|
26
|
+
|
|
27
|
+
Generated code:
|
|
28
|
+
```jsx
|
|
29
|
+
<TextFrame rounded wrap={10}>
|
|
30
|
+
Hello World! You can mix text and <Square rounded fill={blue} /> other elements together.
|
|
31
|
+
</TextFrame>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Latex
|
|
35
|
+
|
|
36
|
+
*Inherits*: **Text** > **Element**
|
|
37
|
+
|
|
38
|
+
Creates a new `Math` math element from LaTeX source. Uses `MathJax` when available to render in SVG and calculate aspect ratio. As seen in the example, you will probably need to wrap the LaTeX in `{"..."}` to prevent syntax errors.
|
|
39
|
+
|
|
40
|
+
Parameters:
|
|
41
|
+
- `offset` — the position of the center of the element
|
|
42
|
+
- `scale` — the proportional size of the element
|
|
43
|
+
|
|
44
|
+
**Example**
|
|
45
|
+
|
|
46
|
+
Prompt: There are two latex equations framed by rounded borders arranged vertically. The top one shows a Gaussian integral and the bottom one shows a trigonometric identity. They are framed by a square with the title "Facts".
|
|
47
|
+
|
|
48
|
+
Generated code:
|
|
49
|
+
```jsx
|
|
50
|
+
<VStack spacing>
|
|
51
|
+
<TextFrame><Equation>{"\\int_0^{\\infty} \\exp(-x^2) dx = \\sqrt{\\pi}"}</Equation></TextFrame>
|
|
52
|
+
<TextFrame><Equation>{"\\sin^2(\\theta) + \\cos^2(\\theta) = 1"}</Equation></TextFrame>
|
|
53
|
+
</VStack>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## TitleFrame
|
|
57
|
+
|
|
58
|
+
*Inherits*: **Frame** > **Element**
|
|
59
|
+
|
|
60
|
+
A special type of **Frame** that places a title element in a box centered on the line at the top of the frame. The title element can be either a proper Element or a string, in which case it will be wrapped in a **Text** element.
|
|
61
|
+
|
|
62
|
+
Parameters:
|
|
63
|
+
- `title` — the text or element to use as the title
|
|
64
|
+
- `title-size` = `0.05` — the size of the title element
|
|
65
|
+
- `adjust` = `true` — whether to adjust the padding and margin to account for the title element
|
|
66
|
+
- `border` = `1` — the outer frame border width to use
|
|
67
|
+
|
|
68
|
+
Subunits:
|
|
69
|
+
- `title` — the title element
|
|
70
|
+
|
|
71
|
+
**Example**
|
|
72
|
+
|
|
73
|
+
Prompt: Various food emojis are arrnaged in a spaced out grid and framed with the title "Fruits & Veggies". Each emoji is framed by a rounded square with a gray background.
|
|
74
|
+
|
|
75
|
+
Generated code:
|
|
76
|
+
```jsx
|
|
77
|
+
const emoji = [ '🍇', '🥦', '🍔', '🍉', '🍍', '🌽', '🍩', '🥝', '🍟' ]
|
|
78
|
+
return <TitleFrame title="Fruits & Veggies" margin padding rounded>
|
|
79
|
+
<Grid rows={3} spacing={0.05}>
|
|
80
|
+
{emoji.map(e =>
|
|
81
|
+
<Frame aspect rounded fill padding><Text>{e}</Text></Frame>
|
|
82
|
+
)}
|
|
83
|
+
</Grid>
|
|
84
|
+
</TitleFrame>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Slide
|
|
88
|
+
|
|
89
|
+
*Inherits*: **TitleFrame** > **Frame** > **Group** > **Element**
|
|
90
|
+
|
|
91
|
+
Create a presentation slide with a title and some content. This stacks various `Text` elements and other `Element`s vertically. It will automatically apply the specified `wrap` value to the text elements. It defaults to using a `TitleFrame` for the title and a light gray rounded border.
|
|
92
|
+
|
|
93
|
+
Parameters:
|
|
94
|
+
- `children` = `[]` — a list of strings or `Element`s to array vertically
|
|
95
|
+
- `wrap` = `25` — the width (in ems) to wrap the text at (if `null`, the text will not be wrapped)
|
|
96
|
+
|
|
97
|
+
Subunits:
|
|
98
|
+
- `title` — the title element
|
|
99
|
+
- `text` — the text elements
|
|
100
|
+
|
|
101
|
+
**Example**
|
|
102
|
+
|
|
103
|
+
Prompt: A slide with a title, a plot of a sine wave, and some text describing the plot. Let the title be "The Art of the Sine Wave".
|
|
104
|
+
|
|
105
|
+
Generated code:
|
|
106
|
+
```jsx
|
|
107
|
+
<Slide title="The Art of the Sine Wave">
|
|
108
|
+
<Text>Here's a plot of a sine wave below. It has to be the right size to fit in with the figure correctly.</Text>
|
|
109
|
+
<Plot xlim={[0, 2*pi]} ylim={[-1.5, 1.5]} grid fill={lightgray} margin={[0.25, 0.05]} aspect={2}>
|
|
110
|
+
<SymLine fy={sin} stroke={blue} stroke-width={2} />
|
|
111
|
+
</Plot>
|
|
112
|
+
<Text>It ranges from low to high and has some extra vertical space to allow us to see the full curve.</Text>
|
|
113
|
+
</Slide>
|
|
114
|
+
```
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Utilities Elements
|
|
2
|
+
|
|
3
|
+
## Math
|
|
4
|
+
|
|
5
|
+
Here we collect a variety of global mathematical functions and constants. You can still use the core JavaScript `Math` library as well.
|
|
6
|
+
|
|
7
|
+
## Constants
|
|
8
|
+
|
|
9
|
+
- `e` — the base of the natural logarithm (e)
|
|
10
|
+
- `pi` — the geometric constant (π)
|
|
11
|
+
- `phi` — the golden ratio (φ)
|
|
12
|
+
- `r2d` — the conversion factor between radians and degrees (180/π)
|
|
13
|
+
- `d2r` — the conversion factor between degrees and radians (π/180)
|
|
14
|
+
|
|
15
|
+
## Functions
|
|
16
|
+
|
|
17
|
+
- `exp(x)` — the exponential function
|
|
18
|
+
- `log(x)` — the natural logarithm
|
|
19
|
+
- `sin(x)` — the sine function
|
|
20
|
+
- `cos(x)` — the cosine function
|
|
21
|
+
- `tan(x)` — the tangent function
|
|
22
|
+
- `abs(x)` — the absolute value
|
|
23
|
+
- `pow(x, y)` — the power function
|
|
24
|
+
- `sqrt(x)` — the square root function
|
|
25
|
+
- `sign(x)` — the sign function
|
|
26
|
+
- `floor(x)` — the floor function
|
|
27
|
+
- `ceil(x)` — the ceiling function
|
|
28
|
+
- `round(x)` — the rounding function
|
|
29
|
+
- `clamp(x, lim=[0, 1])` — clamp `x` to the range `lim`
|
|
30
|
+
- `rescale(x, lim=[0, 1])` — linearly rescale `x` to the range `lim`
|
|
31
|
+
|
|
32
|
+
**Example**
|
|
33
|
+
|
|
34
|
+
Prompt: plot the exponential of sin(x) over [0, 2π]
|
|
35
|
+
|
|
36
|
+
Generated code:
|
|
37
|
+
```jsx
|
|
38
|
+
<Box margin={0.15}>
|
|
39
|
+
<Plot aspect={phi} xlim={[0, 2*pi]} ylim={[0, 3]} grid>
|
|
40
|
+
<SymLine fy={x => exp(sin(x))} />
|
|
41
|
+
</Plot>
|
|
42
|
+
</Box>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Arrays
|
|
46
|
+
|
|
47
|
+
There are a number of functions designed to make working with arrays easier. They largely mimic similar functions found in core Python or the `numpy` library.
|
|
48
|
+
|
|
49
|
+
## Functions
|
|
50
|
+
|
|
51
|
+
- `zip(...arrs)` — combine arrays `arrs` element-wise
|
|
52
|
+
- `min(arrs)` — the minimum of arrays `arrs`
|
|
53
|
+
- `max(arrs)` — the maximum of arrays `arrs`
|
|
54
|
+
- `reshape(arr, shape)` — reshape array `arr` to given dimensions `shape`
|
|
55
|
+
- `split(arr, len)` — split array `arr` into subarrays of length `len`
|
|
56
|
+
- `sum(arr)` — sum the elements of array `arr`
|
|
57
|
+
- `all(arr)` — check if all elements of array `arr` are true
|
|
58
|
+
- `any(arr)` — check if any element of array `arr` is true
|
|
59
|
+
- `add(arr1, arr2)` — add arrays `arr1` and `arr2` element-wise
|
|
60
|
+
- `mul(arr1, arr2)` — multiply arrays `arr1` and `arr2` element-wise
|
|
61
|
+
- `cumsum(arr, first=true)` — compute the cumulative sum of array `arr` with the option to start at zero
|
|
62
|
+
- `norm(arr, degree=1)` — compute the `degree`-norm of array `arr`
|
|
63
|
+
- `normalize(arr, degree=1)` — normalize array `arr` to have `degree`-norm one
|
|
64
|
+
- `range(i0, i1, step=1)` — generate an array of evenly spaced values from `i0` to `i1` with spacing `step`
|
|
65
|
+
- `linspace(x0, x1, n=50)` — generate an array of `n` evenly spaced values between `x0` and `x1`
|
|
66
|
+
- `enumerate(arr)` — pair each element of array `arr` with its index
|
|
67
|
+
- `repeat(x, n)` — repeat array `x` a total of `n` times
|
|
68
|
+
- `meshgrid(x, y)` — create a mesh grid from arrays `x` and `y`
|
|
69
|
+
- `lingrid(xlim, ylim, N)` — create a 2D grid of `N = [Nx, Ny]` points over the ranges `xlim` and `ylim`
|
|
70
|
+
|
|
71
|
+
**Example**
|
|
72
|
+
|
|
73
|
+
Prompt: a scatter plot of points with emojis for: mount fuji, a rocket, a whale, a watermellon, and a donut
|
|
74
|
+
|
|
75
|
+
Generated code:
|
|
76
|
+
```jsx
|
|
77
|
+
<Plot xlim={[0, 6]} ylim={[0, 6]} xticks={7} yticks={7} margin={0.15}>
|
|
78
|
+
{ [ '🗻', '🚀', '🐋', '🍉', '🍩' ].map((e, i) =>
|
|
79
|
+
<Text pos={[i+1, i+1]} rad={0.4}>{e}</Text>
|
|
80
|
+
) }
|
|
81
|
+
</Plot>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Colors
|
|
85
|
+
|
|
86
|
+
There are a few functions designed to manipulate colors in HEX, RGB, and HSL formats.
|
|
87
|
+
|
|
88
|
+
**Constants**
|
|
89
|
+
|
|
90
|
+
- `none` = `'none'` — a transparent color
|
|
91
|
+
- `white` = `'#ffffff'` — a white color
|
|
92
|
+
- `black` = `'#000000'` — a black color
|
|
93
|
+
- `blue`= `'#1e88e5'` — a neon blue color
|
|
94
|
+
- `red`= `'#ff0d57'` — a neon red color
|
|
95
|
+
- `green`= `'#4caf50'` — a neon green color
|
|
96
|
+
- `yellow`= `'#ffb300'` — a neon yellow color
|
|
97
|
+
- `purple`= `'#9c27b0'` — a neon purple color
|
|
98
|
+
- `gray`= `'#f0f0f0'` — a light gray color
|
|
99
|
+
|
|
100
|
+
**Functions**
|
|
101
|
+
|
|
102
|
+
- `hex2rgb(hex)` — convert a HEX color string to an RGB array
|
|
103
|
+
- `rgb2hex(rgb)` — convert an RGB array to a HEX color string
|
|
104
|
+
- `rgb2hsl(rgb)` — convert an RGB array to an HSL array
|
|
105
|
+
- `palette(beg, end, lim=[0, 1])` — create a palette function that interpolates between two colors
|
|
106
|
+
|
|
107
|
+
**Example**
|
|
108
|
+
|
|
109
|
+
Prompt: A plot of an inverted sine wave where the line markers are sized in proportion to the amplitude and the color ranges from blue to red depending on the phase. The x-axis ticks are labeled with multiples of π. The x-axis is labeled "phase" and the y-axis is labeled "amplitude". The title is "Inverted Sine Wave".
|
|
110
|
+
|
|
111
|
+
Generated code:
|
|
112
|
+
```jsx
|
|
113
|
+
const func = x => -sin(x)
|
|
114
|
+
const pal = palette(blue, red, [-1, 1])
|
|
115
|
+
const size = (x, y) => 0.1 * (1+abs(y))/2
|
|
116
|
+
const shape = (x, y) => <Circle fill={pal(y)} />
|
|
117
|
+
const xticks = linspace(0, 2, 6).slice(1).map(x => [x*pi, `${rounder(x, 1)} π`])
|
|
118
|
+
return <Plot xlim={[0, 2*pi]} ylim={[-1, 1]} aspect={1.5} xanchor={0} xaxis-tick-side="both" xticks={xticks} grid xlabel="phase" ylabel="amplitude" title="Inverted Sine Wave" margin={0.25}>
|
|
119
|
+
<SymLine fy={func} />
|
|
120
|
+
<SymPoints fy={func} size={size} shape={shape} N={21}>
|
|
121
|
+
</SymPoints>
|
|
122
|
+
</Plot>
|
|
123
|
+
```
|
package/docs/code/group.jsx
CHANGED
package/docs/code/points.jsx
CHANGED
package/docs/code/rect.jsx
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// a rectangle on the left side of the figure with an aspect of roughly 1/2
|
|
2
|
-
<
|
|
2
|
+
<Rectangle pos={[0.25, 0.5]} rad={[0.1, 0.2]}/>
|
package/docs/code/stack.jsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// a wide blue rectangle on top, with red and green squares side by side on the bottom. each one has rounded corners.
|
|
2
2
|
<VStack spacing>
|
|
3
|
-
<
|
|
3
|
+
<Rectangle rounded fill={blue} />
|
|
4
4
|
<HStack stack-size={0.5} spacing>
|
|
5
5
|
<Square rounded fill={red} />
|
|
6
6
|
<Square rounded fill={green} />
|