trackplot 0.1.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/LICENSE.txt +21 -0
- package/README.md +363 -0
- package/app/assets/javascripts/trackplot/index.js +1541 -0
- package/package.json +20 -0
package/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Eagerworks
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
# Trackplot
|
|
2
|
+
|
|
3
|
+
**Drop-in D3.js charts for Rails.** Write Ruby, get beautiful interactive visualizations. No JavaScript required.
|
|
4
|
+
|
|
5
|
+
Trackplot gives you a Recharts-like DSL that feels right at home in your `.erb` templates. Under the hood it renders a `<trackplot-chart>` custom element powered by D3.js — with animations, tooltips, theming, and Turbo support out of the box.
|
|
6
|
+
|
|
7
|
+
```erb
|
|
8
|
+
<%= trackplot_chart @monthly_sales do |c| %>
|
|
9
|
+
<% c.line :revenue, color: "#6366f1", curve: true %>
|
|
10
|
+
<% c.bar :orders, color: "#06b6d4", opacity: 0.6 %>
|
|
11
|
+
<% c.axis :x, data_key: :month %>
|
|
12
|
+
<% c.axis :y, format: :currency %>
|
|
13
|
+
<% c.tooltip format: :currency %>
|
|
14
|
+
<% c.reference_line y: 10_000, label: "Goal" %>
|
|
15
|
+
<% c.legend %>
|
|
16
|
+
<% c.grid %>
|
|
17
|
+
<% end %>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
That's it. No JavaScript files to write, no chart config objects to manage, no build step drama.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 10 Chart Types
|
|
25
|
+
|
|
26
|
+
| Cartesian | Radial | Other |
|
|
27
|
+
|-----------|--------|-------|
|
|
28
|
+
| Line | Pie / Donut | Horizontal Bar |
|
|
29
|
+
| Bar | Radar | Funnel |
|
|
30
|
+
| Area (+ stacked) | | Candlestick (OHLC) |
|
|
31
|
+
| Scatter | | |
|
|
32
|
+
|
|
33
|
+
Mix and match freely — bars + lines on the same chart just work.
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
Add to your Gemfile:
|
|
38
|
+
|
|
39
|
+
```ruby
|
|
40
|
+
gem "trackplot"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### With importmap (default Rails 7+)
|
|
44
|
+
|
|
45
|
+
You're done. The engine auto-registers D3 from CDN and pins the trackplot module.
|
|
46
|
+
|
|
47
|
+
### With esbuild / jsbundling-rails
|
|
48
|
+
|
|
49
|
+
Install D3 and trackplot from npm:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
yarn add d3 trackplot
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Then import it in your `app/javascript/application.js`:
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
import "trackplot"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Quick Start
|
|
62
|
+
|
|
63
|
+
Pass any array of hashes (or ActiveRecord collection) and describe what you want:
|
|
64
|
+
|
|
65
|
+
```erb
|
|
66
|
+
<%= trackplot_chart @data, height: "300px" do |c| %>
|
|
67
|
+
<% c.line :temperature, color: "#ef4444", curve: true %>
|
|
68
|
+
<% c.axis :x, data_key: :date %>
|
|
69
|
+
<% c.axis :y, label: "Temp (F)" %>
|
|
70
|
+
<% c.tooltip %>
|
|
71
|
+
<% c.grid %>
|
|
72
|
+
<% end %>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Your data can use symbol or string keys — Trackplot normalizes both:
|
|
76
|
+
|
|
77
|
+
```ruby
|
|
78
|
+
@data = [
|
|
79
|
+
{ date: "Mon", temperature: 72 },
|
|
80
|
+
{ date: "Tue", temperature: 68 },
|
|
81
|
+
{ date: "Wed", temperature: 75 }
|
|
82
|
+
]
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Chart Types
|
|
86
|
+
|
|
87
|
+
### Line
|
|
88
|
+
|
|
89
|
+
```erb
|
|
90
|
+
<% c.line :revenue, color: "#6366f1", curve: true, dashed: true %>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Options: `color`, `curve` (smooth), `dashed`, `stroke_width`, `dot` (true/false), `dot_size`.
|
|
94
|
+
|
|
95
|
+
### Bar
|
|
96
|
+
|
|
97
|
+
```erb
|
|
98
|
+
<% c.bar :sales, color: "#06b6d4", opacity: 0.8, radius: 6 %>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Multiple bar series render as grouped bars automatically. Options: `color`, `opacity`, `radius` (corner rounding), `stack` (group name for stacking).
|
|
102
|
+
|
|
103
|
+
### Area
|
|
104
|
+
|
|
105
|
+
```erb
|
|
106
|
+
<% c.area :revenue, color: "#8b5cf6", curve: true %>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Renders a gradient fill with a stroke line. Stack multiple areas by giving them the same `stack` name:
|
|
110
|
+
|
|
111
|
+
```erb
|
|
112
|
+
<% c.area :revenue, stack: "main", color: "#10b981", curve: true %>
|
|
113
|
+
<% c.area :costs, stack: "main", color: "#f59e0b", curve: true %>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Scatter
|
|
117
|
+
|
|
118
|
+
```erb
|
|
119
|
+
<% c.scatter :weight, color: "#ec4899", dot_size: 6 %>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Options: `color`, `dot_size`, `opacity`, `x_key` (override x-axis key).
|
|
123
|
+
|
|
124
|
+
### Pie / Donut
|
|
125
|
+
|
|
126
|
+
```erb
|
|
127
|
+
<% c.pie :value, label_key: :segment %>
|
|
128
|
+
<% c.pie :value, label_key: :segment, donut: true %>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Options: `label_key`, `donut`, `pad_angle`.
|
|
132
|
+
|
|
133
|
+
### Radar
|
|
134
|
+
|
|
135
|
+
```erb
|
|
136
|
+
<% c.radar :player_a, color: "#6366f1" %>
|
|
137
|
+
<% c.radar :player_b, color: "#ef4444" %>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Options: `color`, `opacity`, `stroke_width`, `dot`, `dot_size`.
|
|
141
|
+
|
|
142
|
+
### Horizontal Bar
|
|
143
|
+
|
|
144
|
+
```erb
|
|
145
|
+
<% c.horizontal_bar :popularity, color: "#14b8a6" %>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Same options as regular bar. The x-axis `data_key` becomes the category axis.
|
|
149
|
+
|
|
150
|
+
### Candlestick
|
|
151
|
+
|
|
152
|
+
```erb
|
|
153
|
+
<% c.candlestick open: :open, high: :high, low: :low, close: :close %>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Options: `up_color`, `down_color`.
|
|
157
|
+
|
|
158
|
+
### Funnel
|
|
159
|
+
|
|
160
|
+
```erb
|
|
161
|
+
<% c.funnel :count, label_key: :stage %>
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Options: `label_key`.
|
|
165
|
+
|
|
166
|
+
### Combined Charts
|
|
167
|
+
|
|
168
|
+
Layer different series types on the same chart:
|
|
169
|
+
|
|
170
|
+
```erb
|
|
171
|
+
<%= trackplot_chart @data do |c| %>
|
|
172
|
+
<% c.bar :revenue, color: "#06b6d4", opacity: 0.6 %>
|
|
173
|
+
<% c.line :profit, color: "#6366f1", curve: true %>
|
|
174
|
+
<% c.axis :x, data_key: :month %>
|
|
175
|
+
<% c.axis :y %>
|
|
176
|
+
<% c.tooltip %>
|
|
177
|
+
<% c.legend %>
|
|
178
|
+
<% c.grid %>
|
|
179
|
+
<% end %>
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Components
|
|
183
|
+
|
|
184
|
+
### Axis
|
|
185
|
+
|
|
186
|
+
```erb
|
|
187
|
+
<% c.axis :x, data_key: :month %>
|
|
188
|
+
<% c.axis :y, label: "Revenue ($)", format: :currency, tick_count: 5 %>
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Options: `data_key`, `label`, `format`, `tick_count`, `tick_rotation`.
|
|
192
|
+
|
|
193
|
+
### Tooltip
|
|
194
|
+
|
|
195
|
+
```erb
|
|
196
|
+
<% c.tooltip format: :currency %>
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Options: `format`, `label_format`.
|
|
200
|
+
|
|
201
|
+
### Legend
|
|
202
|
+
|
|
203
|
+
```erb
|
|
204
|
+
<% c.legend position: :top %>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Options: `position` (`:top` or `:bottom`), `clickable`.
|
|
208
|
+
|
|
209
|
+
### Grid
|
|
210
|
+
|
|
211
|
+
```erb
|
|
212
|
+
<% c.grid horizontal: true, vertical: true %>
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Options: `horizontal` (default true), `vertical`.
|
|
216
|
+
|
|
217
|
+
### Reference Line
|
|
218
|
+
|
|
219
|
+
Draw horizontal or vertical lines for targets, thresholds, or annotations:
|
|
220
|
+
|
|
221
|
+
```erb
|
|
222
|
+
<% c.reference_line y: 5000, label: "Target", color: "#ef4444" %>
|
|
223
|
+
<% c.reference_line x: "Mar", label: "Launch", color: "#6366f1", dashed: false %>
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Options: `y` or `x` (value), `label`, `color`, `dashed` (default true), `stroke_width`.
|
|
227
|
+
|
|
228
|
+
## Number Formatting
|
|
229
|
+
|
|
230
|
+
Both axes and tooltips accept format presets or raw D3 format strings:
|
|
231
|
+
|
|
232
|
+
| Preset | Output | Example |
|
|
233
|
+
|--------|--------|---------|
|
|
234
|
+
| `:currency` | `$1,234` | `format: :currency` |
|
|
235
|
+
| `:percent` | `42%` | `format: :percent` |
|
|
236
|
+
| `:compact` | `1.2k` | `format: :compact` |
|
|
237
|
+
| `:decimal` | `1,234.56` | `format: :decimal` |
|
|
238
|
+
| `:integer` | `1,234` | `format: :integer` |
|
|
239
|
+
|
|
240
|
+
Or pass a raw D3 format string: `format: "$,.2f"`.
|
|
241
|
+
|
|
242
|
+
## Theming
|
|
243
|
+
|
|
244
|
+
Four built-in themes, plus fully custom themes via Hash:
|
|
245
|
+
|
|
246
|
+
```erb
|
|
247
|
+
<%= trackplot_chart @data, theme: :dark do |c| %>
|
|
248
|
+
...
|
|
249
|
+
<% end %>
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Available presets: `:default`, `:dark`, `:vibrant`, `:minimal`.
|
|
253
|
+
|
|
254
|
+
Custom theme (merges with defaults):
|
|
255
|
+
|
|
256
|
+
```erb
|
|
257
|
+
<%= trackplot_chart @data, theme: { colors: ["#ff0000", "#00ff00"], background: "#111" } do |c| %>
|
|
258
|
+
...
|
|
259
|
+
<% end %>
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Theme properties: `colors`, `background`, `text_color`, `axis_color`, `grid_color`, `tooltip_bg`, `tooltip_text`, `tooltip_border`, `font`.
|
|
263
|
+
|
|
264
|
+
## Click Events
|
|
265
|
+
|
|
266
|
+
Every interactive element (bars, dots, pie slices, funnel stages...) dispatches a `trackplot:click` CustomEvent that bubbles up the DOM:
|
|
267
|
+
|
|
268
|
+
```javascript
|
|
269
|
+
document.addEventListener("trackplot:click", function(e) {
|
|
270
|
+
console.log(e.detail)
|
|
271
|
+
// => { chartType: "bar", dataKey: "revenue", datum: {...}, index: 2, value: 4200 }
|
|
272
|
+
})
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Works great with Stimulus:
|
|
276
|
+
|
|
277
|
+
```html
|
|
278
|
+
<div data-controller="chart" data-action="trackplot:click->chart#onClick">
|
|
279
|
+
<%= trackplot_chart @data do |c| %>
|
|
280
|
+
...
|
|
281
|
+
<% end %>
|
|
282
|
+
</div>
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## Turbo Support
|
|
286
|
+
|
|
287
|
+
Trackplot is built for Turbo. Charts clean up before Turbo caches pages, survive morphing, and re-render cleanly on Turbo Stream updates.
|
|
288
|
+
|
|
289
|
+
### Stable IDs for Turbo Streams
|
|
290
|
+
|
|
291
|
+
Pass `id:` so `turbo_stream.replace` can target your chart:
|
|
292
|
+
|
|
293
|
+
```erb
|
|
294
|
+
<%= trackplot_chart @data, id: "revenue-chart" do |c| %>
|
|
295
|
+
<% c.line :revenue, curve: true %>
|
|
296
|
+
<% c.axis :x, data_key: :month %>
|
|
297
|
+
<% c.axis :y %>
|
|
298
|
+
<% end %>
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Then push updates from your server:
|
|
302
|
+
|
|
303
|
+
```erb
|
|
304
|
+
<%= turbo_stream.replace "revenue-chart" do %>
|
|
305
|
+
<%= trackplot_chart @fresh_data, id: "revenue-chart" do |c| %>
|
|
306
|
+
<% c.line :revenue, curve: true %>
|
|
307
|
+
<% c.axis :x, data_key: :month %>
|
|
308
|
+
<% c.axis :y %>
|
|
309
|
+
<% end %>
|
|
310
|
+
<% end %>
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Programmatic Data Updates
|
|
314
|
+
|
|
315
|
+
Update chart data from JavaScript (e.g., from a Stimulus controller receiving ActionCable broadcasts):
|
|
316
|
+
|
|
317
|
+
```javascript
|
|
318
|
+
const chart = document.getElementById("revenue-chart")
|
|
319
|
+
chart.updateData(newDataArray)
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
The `trackplot:render` event fires after every render:
|
|
323
|
+
|
|
324
|
+
```javascript
|
|
325
|
+
document.addEventListener("trackplot:render", function(e) {
|
|
326
|
+
console.log("Chart ready:", e.target.id)
|
|
327
|
+
})
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## Chart Options
|
|
331
|
+
|
|
332
|
+
Pass options directly to `trackplot_chart`:
|
|
333
|
+
|
|
334
|
+
| Option | Default | Description |
|
|
335
|
+
|--------|---------|-------------|
|
|
336
|
+
| `id:` | auto-generated | Stable DOM id for Turbo targeting |
|
|
337
|
+
| `width:` | `"100%"` | CSS width |
|
|
338
|
+
| `height:` | `"400px"` | CSS height |
|
|
339
|
+
| `animate:` | `true` | Entry animations |
|
|
340
|
+
| `theme:` | `:default` | Theme preset or custom Hash |
|
|
341
|
+
| `class:` | `nil` | Additional CSS classes |
|
|
342
|
+
|
|
343
|
+
## Development
|
|
344
|
+
|
|
345
|
+
Run the test suite:
|
|
346
|
+
|
|
347
|
+
```bash
|
|
348
|
+
ruby -Ilib -Itest -e "Dir['test/**/*_test.rb'].each { |f| require File.expand_path(f) }"
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
Boot the demo app:
|
|
352
|
+
|
|
353
|
+
```bash
|
|
354
|
+
cd test/dummy && bin/rails server
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
## License
|
|
358
|
+
|
|
359
|
+
MIT License. See [LICENSE.txt](LICENSE.txt).
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
*Made️ by [eagerworks](https://eagerworks.com)*
|