gum-jsx 1.5.0 → 1.6.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 CHANGED
@@ -1,24 +1,38 @@
1
1
  <div align="center">
2
- <img src="image/logo.png" alt="logo" width="500" />
2
+ <img src="images/logo.svg" alt="logo" width="500" />
3
3
  <br/>
4
4
  </div>
5
5
 
6
6
  <div align="center">
7
- <img src="image/nexus.svg" alt="nexus" width="250" />
7
+ <img src="images/nexus.svg" alt="nexus" width="250" />
8
8
  <br/><br/>
9
9
  </div>
10
10
 
11
- A language for creating visualizations using a React-like JSX dialect that evaluates to SVG. Designed for general graphics, plots, graphs, and network diagrams.
11
+ <p align="center">
12
+ Gum is a JSX vector graphics language that evaluates to SVG.
13
+ <br/>
14
+ It is designed for plots, diagrams, flow charts, and more.
15
+ </p>
12
16
 
13
- Head to **[compendiumlabs.ai/gum](https://compendiumlabs.ai/gum)** for a live demo and documentation. For Python bindings, see [gum.py](https://github.com/CompendiumLabs/gum.py).
17
+ <p align="center">
18
+ <a href="https://compendiumlabs.ai/gum/studio">Live Demo</a>
19
+ |
20
+ <a href="https://compendiumlabs.ai/gum/docs">Documentation</a>
21
+ |
22
+ <a href="https://compendiumlabs.ai/gum/docs/gala">Gallery</a>
23
+ </p>
14
24
 
15
- # Installation
25
+ ## Installation
16
26
 
17
27
  ```bash
18
28
  bun i gum-jsx
19
29
  ```
20
30
 
21
- # Usage
31
+ This will install the `gum` command and the `gum-jsx` package. Add a `-g` flag to install globally. To download the skill file (which is just a zip), click on the release on the right or use `skills/gum-jsx.skill`.
32
+
33
+ See [react-gum-jsx](https://github.com/CompendiumLabs/react-gum-jsx) for React bindings. See [gum.py](https://github.com/CompendiumLabs/gum.py) for a Python wrapper.
34
+
35
+ ## Library Usage
22
36
 
23
37
  Write some `gum.jsx` code:
24
38
 
@@ -38,49 +52,50 @@ const svg = elem.svg()
38
52
 
39
53
  Which will produce the following:
40
54
 
41
- <img src="image/plot.png" alt="sine wave plot" width="750" />
55
+ <img src="images/plot.svg" alt="sine wave plot" width="750" />
42
56
 
43
57
  You can also use JavaScript directly:
44
58
 
45
59
  ```javascript
46
60
  import { Svg, Box, Text, Circle, Plot, SymLine, pi, sin } from 'gum'
47
61
  const elem = new Plot({
48
- children: new SymLine({ fy: sin, stroke: blue, stroke_width: 2 }),
62
+ children: [ new SymLine({ fy: sin, stroke: blue, stroke_width: 2 }) ],
49
63
  xlim: [0, 2*pi], ylim: [-1.5, 1.5], grid: true, margin: [0.2, 0.1], aspect: 2,
50
64
  })
51
65
  const svg = elem.svg()
52
66
  ```
53
67
 
54
- # CLI
68
+ ## Command Line
55
69
 
56
- You can use the `gum` command to convert `gum.jsx` into SVG text or PNG data. You can even just display it directly in the terminal! For the latter you need a terminal that supports images, such as `ghostty` or `kitty`. There are a bunch of code examples in `docs/code/` and `docs/gallery/` to try out.
70
+ You can use the `gum` command to convert `gum.jsx` into SVG text or PNG data. You can even just display it directly in the terminal. For the latter you need a terminal that supports images, such as `ghostty` or `kitty`. There are a bunch of code examples in `docs/code/` and `gala/code/` to try out.
57
71
 
58
72
  Generate an SVG from a `gum.jsx` file:
59
73
 
60
74
  ```bash
61
- cat input.jsx | bun run cli -f svg > output.svg
75
+ gum input.jsx -o output.svg
62
76
  ```
63
77
 
64
78
  Generate a PNG from a `gum.jsx` file:
65
79
 
66
80
  ```bash
67
- cat input.jsx | bun run cli -f png > output.png
81
+ gum input.jsx -o output.png
68
82
  ```
69
83
 
70
84
  Display a `gum.jsx` file in the terminal:
71
85
  ```bash
72
- cat input.jsx | bun run cli
86
+ gum input.jsx
73
87
  ```
74
88
 
75
89
  CLI options:
76
90
 
77
91
  | Option | Description | Default |
78
92
  |--------|-------------|---------|
79
- | `-s, --size <size>` | Image size in pixels | 500 |
93
+ | `file` | Gum JSX file to render | stdin |
94
+ | `-s, --size <size>` | Image size in pixels | 1000 |
80
95
  | `-t, --theme <theme>` | Theme: `light` or `dark` | light |
81
- | `-w, --width <width>` | Width of the PNG | null |
82
- | `-h, --height <height>` | Height of the PNG | null |
83
- | `-f, --format <format>` | Format: `svg` or `png` | `svg` |
84
- | `-b, --background <color>` | Background color | null (transparent) |
85
- | `-o, --output <output>` | Output file | null (stdout) |
86
- | `-u, --update` | Live update display | false |
96
+ | `-b, --background <color>` | Background color | white |
97
+ | `-f, --format <format>` | Format: `json`, `svg`, `png`, `kitty` | auto |
98
+ | `-o, --output <output>` | Output file | stdout |
99
+ | `-w, --width <width>` | Max width of the PNG | auto |
100
+ | `-h, --height <height>` | Max height of the PNG | auto |
101
+ | `-d, --dev` | Live update display | off |
package/docs/code/Arc.jsx CHANGED
@@ -1,4 +1,4 @@
1
- // elliptical and circular arcs using degree ranges
1
+ // elliptical and circular arcs using start and end angles
2
2
  <Group>
3
3
  <Arc pos={[0.32, 0.5]} size={[0.44, 0.32]} start={-45} end={210} stroke={blue} stroke-width={2} />
4
4
  <Arc pos={[0.72, 0.5]} size={0.32} start={90} end={-150} stroke={red} stroke-width={2} />
@@ -1,6 +1,6 @@
1
- // Two boxes with text in them that have black borders and gray interiors. The box in the upper left says "hello" and the box in the lower right says "world!". The arrowhead from "Hello" is filled in red and the arrowhead to "World!" is filled in blue.
2
- <Network aspect node-fill={gray} edge-arrow>
3
- <Node id="hello" pos={[0.25, 0.25]}>Hello</Node>
4
- <Node id="world" pos={[0.75, 0.75]}>World!</Node>
5
- <Edge start="hello" end="world" start-fill={red} end-fill={blue} />
1
+ // Two boxes with text in them that have black borders and gray interiors. The box in the upper left says "hello" and the box in the lower right says "world!". There is a city-block path connecting the two boxes. The arrowhead from "Hello" is filled in red and the arrowhead to "World!" is filled in blue.
2
+ <Network aspect node-fill={gray} edge-arrow edge-rounded={0.025}>
3
+ <Node id="hello" pos={[0.3, 0.25]}>Hello</Node>
4
+ <Node id="world" pos={[0.7, 0.75]}>World!</Node>
5
+ <Edge start="hello" end="world" points={[[0.3, 0.5], [0.7, 0.5]]}/>
6
6
  </Network>
@@ -1,6 +1,23 @@
1
- // Two boxes with text in them that have black borders and gray interiors. The box in the upper left says "hello" and the box in the lower right says "world!".
2
- <Network aspect node-fill={gray}>
3
- <Node id="hello" pos={[0.25, 0.25]}>Hello</Node>
4
- <Node id="world" pos={[0.75, 0.75]}>World!</Node>
5
- <Edge start="hello" end="world" />
1
+ // A simple connected network where each rounded node contains an emoji icon stacked above a text label. The example shows idea design launch.
2
+ <Network aspect={2} node-fill={gray} node-rounded node-padding node-ysize={0.35}>
3
+ <Node id="idea" pos={[0.2, 0.5]}>
4
+ <VStack spacing={0.15}>
5
+ <Text>💡</Text>
6
+ <Text stack-size={0.25}>Idea</Text>
7
+ </VStack>
8
+ </Node>
9
+ <Node id="design" pos={[0.5, 0.5]}>
10
+ <VStack spacing={0.15}>
11
+ <Text>🎨</Text>
12
+ <Text stack-size={0.25}>Design</Text>
13
+ </VStack>
14
+ </Node>
15
+ <Node id="launch" pos={[0.8, 0.5]}>
16
+ <VStack spacing={0.15}>
17
+ <Text>🚀</Text>
18
+ <Text stack-size={0.25}>Launch</Text>
19
+ </VStack>
20
+ </Node>
21
+ <Edge start="idea" end="design" />
22
+ <Edge start="design" end="launch" />
6
23
  </Network>
@@ -0,0 +1,15 @@
1
+ // a city-block route in blue with rounded corners, with the underlying
2
+ // vertices marked as black dots to show how the corners are rounded
3
+ const points = [
4
+ [0.10, 0.20],
5
+ [0.40, 0.20],
6
+ [0.40, 0.80],
7
+ [0.70, 0.80],
8
+ [0.70, 0.50],
9
+ [0.90, 0.50],
10
+ ]
11
+ return <Frame margin>
12
+ <Line opacity={0.3} points={points} />
13
+ <RoundedLine stroke={blue} stroke-width={2} radius={0.08} points={points} />
14
+ <Points point-size={0.015} points={points} />
15
+ </Frame>
@@ -1,9 +1,9 @@
1
- // 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.
1
+ // 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
2
2
  const emoji = [ '🍇', '🥦', '🍔', '🍉', '🍍', '🌽', '🍩', '🥝', '🍟' ]
3
3
  return <TitleFrame title="Fruits & Veggies" margin padding rounded>
4
4
  <Grid rows={3} spacing={0.05}>
5
5
  {emoji.map(e =>
6
- <Frame aspect rounded fill padding><Text>{e}</Text></Frame>
6
+ <Frame aspect rounded padding><Text>{e}</Text></Frame>
7
7
  )}
8
8
  </Grid>
9
9
  </TitleFrame>
package/docs/meta.json CHANGED
@@ -18,7 +18,8 @@
18
18
  "Shape",
19
19
  "Fill",
20
20
  "Spline",
21
- "Arrow"
21
+ "Arrow",
22
+ "RoundedLine"
22
23
  ],
23
24
  "text": [
24
25
  "Text",
package/docs/text/Arc.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # Arc
2
2
 
3
- *Inherits*: [Element](/docs/Element)
3
+ *Inherits*: **Path** > [Element](/docs/Element)
4
4
 
5
5
  This draws an elliptical arc that inscribes its allocated rectangle, like [Ellipse](/docs/Ellipse), but only over a selected angular interval.
6
6
 
7
7
  Parameters:
8
- - `degrees` = `[0, 360]` start and end angle in degrees
9
- - `range` — alias for `degrees`
8
+ - `start` — first angle in degrees
9
+ - `end` — second angle in degrees
10
10
 
11
- Angles follow gum's usual screen-space convention: `0` points right and `90` points down.
11
+ Angles follow the current coordinate system: `0` points right and positive angles follow positive y. In the default screen coordinate system, `90` points down; inside a default [Graph](/docs/Graph), where y is flipped upward, `90` points up. The two angles are treated as an interval; their order does not change the drawn arc.
@@ -13,7 +13,8 @@ Parameters:
13
13
  - `start-dir` / `end-dir` — the direction of the arrowheads at the start and end
14
14
  - `arrow` / `arrow-start` / `arrow-end` — toggles whether the respective arrowheads are included. Defaults to `true` for `arrow-end` and `false` for `arrow-start`, meaning a directed graph edge
15
15
  - `arrow-size` = `0.04` — size of the arrowhead
16
- - `curve` = `null` — curvature factor forwarded to the spline (`null` or zero means straight line)
16
+ - `curve` = `null` — curvature factor forwarded to the [Spline](/docs/Spline) (`null` or zero means straight line)
17
+ - `rounded` = `null` — corner radius for a city-block path through `points`. When set, the shaft is a [RoundedLine](/docs/RoundedLine) (takes precedence over `curve`)
17
18
 
18
19
  Subunit names:
19
20
  - `line` — forwarded to the shaft line
package/docs/text/Edge.md CHANGED
@@ -13,4 +13,5 @@ Parameters:
13
13
  - `points` — the intermediate points to draw the spline between
14
14
  - `arrow` / `arrow-start` / `arrow-end` — toggles whether the respective arrowheads are included. Defaults to `true` for `arrow-end` and `false` for `arrow-start`, meaning a directed graph edge
15
15
  - `arrow-size` = `0.04` — the arrowhead size to use for both arrows
16
- - `curve` = `2` — curvature factor forwarded to the spline
16
+ - `curve` = `2` — curvature factor forwarded to the [Spline](/docs/Spline)
17
+ - `rounded` = `null` — corner radius for a city-block path using [RoundedLine](/docs/RoundedLine)
@@ -0,0 +1,13 @@
1
+ # RoundedLine
2
+
3
+ *Inherits*: **Path** > [Element](/docs/Element)
4
+
5
+ The `RoundedLine` element draws a polyline through a series of points with rounded corners at each interior vertex. It is most useful for *city-block* (right-angle) routes — for instance, edges in a network diagram that you want to bend cleanly around obstacles rather than curving with [Spline](/docs/Spline). Spline curvature along an otherwise-straight `points` route produces undulating bumps; `RoundedLine` keeps the straight segments straight and only rounds the turns.
6
+
7
+ Each interior vertex is replaced by a circular arc whose radius is derived from `radius` in coord space. When the coordinate system is not square, `RoundedLine` uses the smaller mapped axis so corners stay circular in pixel space instead of stretching into ellipses. If a segment is too short for the requested radius, the corner is automatically clamped so adjacent corners can never overlap.
8
+
9
+ For straight-line polylines (no corner rounding) use [Line](/docs/Line). For smooth curves through points use [Spline](/docs/Spline).
10
+
11
+ Parameters:
12
+ - `points` — array of point coordinates (minimum of 2 required)
13
+ - `radius` = `0.05` — corner back-off distance in coord space, applied at each interior vertex
@@ -2,17 +2,19 @@
2
2
 
3
3
  *Inherits*: [Group](/docs/Group) > [Element](/docs/Element)
4
4
 
5
- Stack one or more **Element** either vertically or horizontally. There are specialized components **VStack** and **HStack** that don't take the `direc` argument. Proportional spacing between children can be specified with the `spacing` parameter. This handles child positioning and sizing, so any `pos`/`size` arguments will be overridden.
5
+ Stack one or more **Element** either vertically or horizontally. There are specialized components **VStack** and **HStack** that don't take the `direc` argument. This element handles child positioning and sizing, so any child `pos`/`size` arguments will be overridden. Proportional spacing between children can be specified with the `spacing` parameter.
6
6
 
7
- Elements can specify their own sizing with the `stack-size` parameter, which controls the child's relative share of the available space along the stack axis (do not use `size`/`xsize`/`ysize` on child elements, this will be overridden). If `stack-size` is not specified and `stack-expand` is not set to `false`, space will be distributed according to the child's aspect ratio. If `stack-expand` is set to `false`, the child will be given an even share of the remaining space.
7
+ The simplest case is when all children have aspect ratios. In the **HStack** case, the overall aspect ratio of the stack is the sum of the child aspect ratios. Children are allocated space in proportion to their aspect ratios. The **VStack** case is similar, but we need to deal in inverse aspect ratio terms.
8
+
9
+ When some children lack aspect ratios, they will be allocated any remaining space evenly. Regardless of whether a child has an aspect ratio or not, it can be given a fixed size with the `stack-size` parameter. This is specified as a fraction between 0 and 1, independent of spacing.
8
10
 
9
11
  Whenever possible, the aspect ratio of the overall stack is set so that all elements with defined aspect ratios will reach full width (in the **VStack** case) or full height (in the **HStack** case).
10
12
 
11
13
  Child parameters:
12
14
  - `stack-size` = `null` — the child's relative share of the available space along the stack axis
13
- - `stack-expand` = `true` — whether to expand the child to fill the remaining space
14
15
 
15
16
  Parameters:
16
17
  - `direc` — the direction of stacking: `v` or `h`
17
18
  - `spacing` = `0` — total amount of space to add between child elements
19
+ - `justify` = `center` — how to justify children along the stack axis
18
20
  - `even` = `false` — whether to distribute sizes evenly (`stack-size = 1 / n`)
@@ -6,23 +6,23 @@ const col = {
6
6
  }
7
7
 
8
8
  return <Slide title="Macroeconomic Flows">
9
- <Network aspect={2} coord={[0, 0, 1.6, 0.8]} node-ysize={0.16} node-rounded={0.06} node-fill={gray} node-text-color="#333" edge-stroke-width={2} edge-arrow-size={0.02} edge-stroke="#444">
10
- <Node id="trade" pos={[0.8, 0.15]} fill={col.trade} fill-opacity={0.15} border-stroke={col.trade} wrap={6}>Foreign Trade</Node>
11
- <Node id="prod" pos={[0.3, 0.4]} fill={col.prod} fill-opacity={0.15} border-stroke={col.prod} wrap={6}>Producers (Firms)</Node>
12
- <Node id="cons" pos={[1.3, 0.4]} fill={col.cons} fill-opacity={0.15} border-stroke={col.cons} wrap={6}>Consumers (Households)</Node>
13
- <Node id="govt" pos={[0.8, 0.65]} ysize={0.12} fill={col.govt} fill-opacity={0.15} border-stroke={col.govt} wrap={6}>Government</Node>
9
+ <Network aspect={2} coord={[0, 0, 1.6, 0.8]} node-ysize={0.16} node-rounded={0.06} node-fill={gray} node-fill-opacity={0.15} edge-stroke-width={1} edge-arrow-size={0.04} edge-stroke="#444" edge-arrow edge-arrow-curve={2.5} node-text-wrap={6}>
10
+ <Node id="trade" pos={[0.8, 0.15]} fill={col.trade} border-stroke={col.trade} text-color={col.trade}>Foreign Trade</Node>
11
+ <Node id="prod" pos={[0.3, 0.4]} fill={col.prod} border-stroke={col.prod} text-color={col.prod}>Producers (Firms)</Node>
12
+ <Node id="cons" pos={[1.3, 0.4]} fill={col.cons} border-stroke={col.cons} text-color={col.cons}>Consumers (Households)</Node>
13
+ <Node id="govt" pos={[0.8, 0.65]} ysize={0.12} fill={col.govt} border-stroke={col.govt} text-color={col.govt}>Government</Node>
14
14
 
15
- <Edge start="prod" end="cons" arrow />
16
- <Edge start="govt" end="prod" end-side="s" arrow curve={2.5} />
17
- <Edge start="govt" end="cons" end-side="s" arrow curve={2.5} />
18
- <Edge start="trade" end="prod" end-side="n" arrow curve={2.5} />
19
- <Edge start="trade" end="cons" end-side="n" arrow curve={2.5} />
15
+ <Edge start="prod" end="cons" />
16
+ <Edge start="govt" end="prod" end-side="s" />
17
+ <Edge start="govt" end="cons" end-side="s" />
18
+ <Edge start="trade" end="prod" end-side="n" />
19
+ <Edge start="trade" end="cons" end-side="n" />
20
20
 
21
21
  <Text pos={[0.8, 0.35]} ysize={0.05} color={col.prod}>Goods + Services →</Text>
22
22
  <Text pos={[0.8, 0.45]} ysize={0.05} color={col.cons}>← Wages, Rent, Profit</Text>
23
- <Text pos={[0.3, 0.65]} ysize={0.04} color={darkgray} spin={30}>Subsidies / Taxes</Text>
24
- <Text pos={[1.3, 0.65]} ysize={0.04} color={darkgray} spin={-30}>Transfers / Taxes</Text>
25
- <Text pos={[0.3, 0.13]} ysize={0.04} color={darkgray} spin={-30}>Imports / Exports</Text>
26
- <Text pos={[1.3, 0.13]} ysize={0.04} color={darkgray} spin={30}>Transfers</Text>
23
+ <Text pos={[0.3, 0.65]} ysize={0.045} spin={30}>Subsidies / Taxes</Text>
24
+ <Text pos={[1.3, 0.65]} ysize={0.045} spin={-30}>Transfers / Taxes</Text>
25
+ <Text pos={[0.3, 0.13]} ysize={0.045} spin={-30}>Imports / Exports</Text>
26
+ <Text pos={[1.3, 0.13]} ysize={0.045} spin={30}>Transfers</Text>
27
27
  </Network>
28
28
  </Slide>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gum-jsx",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "Language for vector graphics generation.",
5
5
  "type": "module",
6
6
  "author": "Douglas Hanley",
@@ -41,7 +41,7 @@
41
41
  "scripts": {
42
42
  "cli": "bun ./scripts/gum.ts",
43
43
  "test": "bun ./scripts/test.ts",
44
- "skill": "bun ./scripts/skill.ts && zip -r skills/gum-jsx.skill skills/gum-jsx",
44
+ "skill": "bun ./scripts/skill.ts && cd skills/gum-jsx && zip -r gum-jsx.skill * && mv gum-jsx.skill ..",
45
45
  "claude": "bun run skill && bun ./scripts/claude.ts"
46
46
  },
47
47
  "bin": {
@@ -51,6 +51,7 @@
51
51
  "@types/node": "^25.2.3",
52
52
  "@types/papaparse": "^5.5.2",
53
53
  "acorn-jsx": "^5.3.2",
54
+ "canvas": "^3.2.3",
54
55
  "emojibase-regex": "^17.0.0",
55
56
  "katex": "^0.16.33",
56
57
  "linebreak": "^1.1.0",
@@ -60,7 +61,6 @@
60
61
  },
61
62
  "optionalDependencies": {
62
63
  "@modelcontextprotocol/sdk": "^1.25.3",
63
- "@resvg/resvg-js": "^2.6.2",
64
64
  "commander": "^14.0.3",
65
65
  "express": "^5.2.1",
66
66
  "zod": "^4.3.6"
package/prompt/gen.md CHANGED
@@ -1,49 +1,43 @@
1
1
  # Using CLI commands
2
2
 
3
- To test the output of a particular `gum.jsx` snippet or file, you can pipe it to the `gum` command, which is assumed to be installed globally. If you have vision capabilities, this can be useful for see the actual output of the code, either in SVG or PNG format. Even without vision, one can infer properties of the output by reading the SVG output directly.
3
+ To test the output of a particular Gum JSX snippet or file, you can pipe it to the `gum` command. If this command is not available globally, try to install the `gum-jsx` package with Bun (preferred) or NPM.
4
+
5
+ If you have vision capabilities, seeing an actual image can be useful for see the actual output of the code, either in SVG or PNG format. Even without vision, one can infer properties of the output by reading the SVG output directly.
4
6
 
5
7
  For one off tests, pipe the code using `echo`. It is recommended that you use single quotes as the outer delimiter, to accommodate code that includes double quotes for component properties (e.g. `justify="left"`).
6
8
 
7
9
  For more difficult tasks, use a file provide the filename as an argument or `cat` it in. Using a file allows you to view and refine your code repeatedly. If you wish to avoid output redirection to a file, use the `-o` option to write to a file.
8
10
 
9
- In general, it makes a lot of sense to write a draft to a file, view its output, then refine the code until you're satisfied. This way you can start simple and add complexity as needed.
11
+ In general, it makes a lot of sense to write a draft to a file, view its output, then refine the code until you're satisfied. This way you can start simple and add complexity as needed. When in doubt, write the output file to the same directory as the input file with the same base name but with the appropriate extension.
10
12
 
11
13
  **Examples:**
12
14
  ```bash
13
- # Generate SVG from a gum.jsx snippet
14
- echo '<Rectangle rounded fill={blue} />' | gum -f svg > output.svg
15
-
16
- # Generate PNG from a gum.jsx snippet
17
- echo '<Rectangle rounded fill={blue} />' | gum -f png > output.png
15
+ # generate an .svg file from a .jsx file
16
+ gum test.jsx -o test.svg
18
17
 
19
- # Generate SVG from a .jsx file
20
- cat test.jsx | gum -f svg > output.svg
18
+ # generate a .png file from a .jsx file
19
+ gum test.jsx -o test.png
21
20
 
22
- # Generate PNG from a .jsx file
23
- cat test.jsx | gum -f png > output.png
21
+ # generate SVG from a Gum JSX snippet and print to stdout
22
+ echo '<Rectangle rounded fill={blue} />' | gum
24
23
 
25
- # Generate SVG from a .jsx file without redirection
26
- gum test.jsx -o output.svg
27
-
28
- # Generate PNG from a .jsx file without redirection
29
- gum test.jsx -o output.png
24
+ # generate PNG from a Gum JSX snippet and save to file
25
+ echo '<Rectangle rounded fill={blue} />' | gum -o test.png
30
26
  ```
31
27
 
32
28
  **CLI options:**
33
- - `file`: gum.jsx file to render (reads from stdin if not provided)
29
+ - `file`: Gum JSX file to render (reads from stdin if not provided)
34
30
  - `-t, --theme <theme>`: theme to use (default: light)
35
31
  - `-b, --background <color>`: background color (default: white)
36
- - `-i, --input <input>`: input format (default: jsx)
37
- - `-f, --format <format>`: output format: svg or png (default: kitty or auto-detected)
32
+ - `-f, --format <format>`: output format: json, svg, png, kitty (default: auto)
38
33
  - `-o, --output <output>`: output file (default: stdout)
39
34
  - `-s, --size <size>`: size of the SVG (default: 1000)
40
- - `-w, --width <width>`: width of the PNG (default: auto)
41
- - `-h, --height <height>`: height of the PNG (default: auto)
42
- - `-u, --update`: enable live update display
35
+ - `-w, --width <width>`: max width of the PNG (default: null)
36
+ - `-h, --height <height>`: max height of the PNG (default: null)
43
37
 
44
- # Using in TypeScript
38
+ # Using Gum in TypeScript
45
39
 
46
- You can use gum.jsx directly in TypeScript/JavaScript code by importing from the `gum-jsx` package. This is useful for programmatic generation, integration into other tools, or when you want to avoid the CLI.
40
+ There are a couple of ways to use Gum in TypeScript. You can evaluate JSX strings directly, or you can construct Gum components directly. If you want to use Gum components in React, you can use the `react-gum-jsx` package.
47
41
 
48
42
  ## Evaluating JSX strings
49
43
 
@@ -77,7 +71,7 @@ const tree = evaluateGum(code, {
77
71
 
78
72
  ## Using components directly
79
73
 
80
- You can also construct components directly by importing them from `gum-jsx` and calling their constructors. Each component takes a single args object.
74
+ You can also construct Gum components directly by importing them from `gum-jsx` and calling their constructors. Each component takes a single args object.
81
75
 
82
76
  ```typescript
83
77
  import { Svg, Rectangle, Circle, HStack, Text, blue, red, white } from 'gum-jsx'
@@ -99,3 +93,38 @@ When constructing manually, note that:
99
93
  - Utility functions like `range`, `linspace`, `zip` are also available from `gum-jsx`
100
94
  - Call `.svg()` on the top-level `Svg` element to get the SVG string output
101
95
  - The realized size of the SVG is available on the `Svg` element as `size`
96
+
97
+ ## Using in React with `react-gum-jsx`
98
+
99
+ You can use Gum components directly in React components by importing from the `react-gum-jsx` package. This is useful for creating interactive visualizations in React.
100
+
101
+ Here's an example of how to use Gum in a React component. It's basically the same as what you would pass to `evaluateGum` but as a default export:
102
+
103
+ ```tsx
104
+ import { blue, red } from 'gum-jsx'
105
+ import { GUM } from 'react-gum-jsx'
106
+ const { Frame, HStack, Square, Circle, Text } = GUM
107
+
108
+ export default function Demo() {
109
+ return <Frame padding margin rounded>
110
+ <HStack padding>
111
+ <Square fill={blue} />
112
+ <Circle fill={red} />
113
+ <Text>Hello</Text>
114
+ </HStack>
115
+ </Frame>
116
+ }
117
+ ```
118
+
119
+ To run this in a CLI setting, just pass a file with a default export to the `gum-react` command that comes with the `react-gum-jsx` package. This takes very similar arguments to the regular `gum` command.
120
+
121
+ If you are in a web setting, you'll need to wrap this export in a `<Gum>` component, which takes roughly the same arguments as `evaluateGum`. This would look like:
122
+
123
+ ```tsx
124
+ import { Gum } from 'react-gum-jsx'
125
+ <Gum size={[640, 360]}>
126
+ <Demo />
127
+ </Gum>
128
+ ```
129
+
130
+ If the inner component has an `aspect` it will be embedded inside the given size bounds. If it is aspectless, it will be stretched to fill the given size bounds.