trevl 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.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/NOTICE +9 -0
  4. data/README.md +431 -0
  5. data/Rakefile +10 -0
  6. data/assets/trendence-logo.svg +17 -0
  7. data/assets/trevl-logo.svg +20 -0
  8. data/docs/screenshots/01_bar_chart.png +0 -0
  9. data/docs/screenshots/02_column_chart.png +0 -0
  10. data/docs/screenshots/03_line_chart.png +0 -0
  11. data/docs/screenshots/04_pie_chart.png +0 -0
  12. data/docs/screenshots/05_computed_fields.png +0 -0
  13. data/docs/screenshots/06_postprocess_top_n.png +0 -0
  14. data/docs/screenshots/10_multi_series.png +0 -0
  15. data/examples/01_bar_chart.yml +16 -0
  16. data/examples/02_column_chart.yml +19 -0
  17. data/examples/03_line_chart.yml +21 -0
  18. data/examples/04_pie_chart.yml +15 -0
  19. data/examples/05_computed_fields.yml +26 -0
  20. data/examples/06_postprocess_top_n.yml +21 -0
  21. data/examples/07_score_kpi.yml +13 -0
  22. data/examples/08_table.yml +14 -0
  23. data/examples/09_template_inheritance.yml +25 -0
  24. data/examples/10_multi_series.yml +23 -0
  25. data/lib/trevl/auth/bearer_token.rb +23 -0
  26. data/lib/trevl/configuration.rb +24 -0
  27. data/lib/trevl/core_ext/hash.rb +37 -0
  28. data/lib/trevl/data_source/api.rb +86 -0
  29. data/lib/trevl/data_source/base.rb +19 -0
  30. data/lib/trevl/data_source/cube.rb +70 -0
  31. data/lib/trevl/data_source/static.rb +30 -0
  32. data/lib/trevl/data_source.rb +38 -0
  33. data/lib/trevl/errors.rb +9 -0
  34. data/lib/trevl/highcharts_asset.rb +45 -0
  35. data/lib/trevl/html_renderer.rb +91 -0
  36. data/lib/trevl/notebook/display.rb +53 -0
  37. data/lib/trevl/notebook.rb +41 -0
  38. data/lib/trevl/processor.rb +106 -0
  39. data/lib/trevl/renderer/data_fetcher.rb +63 -0
  40. data/lib/trevl/renderer/ref_parser.rb +61 -0
  41. data/lib/trevl/renderer/transform.rb +104 -0
  42. data/lib/trevl/renderer.rb +345 -0
  43. data/lib/trevl/schema/component.json +337 -0
  44. data/lib/trevl/schema/document.json +41 -0
  45. data/lib/trevl/template_store.rb +38 -0
  46. data/lib/trevl/validator.rb +96 -0
  47. data/lib/trevl/version.rb +5 -0
  48. data/lib/trevl.rb +99 -0
  49. data/llms.txt +171 -0
  50. data/notebooks/demo.ipynb +312 -0
  51. data/notebooks/exploration.ipynb +164 -0
  52. data/scripts/generate_screenshots.rb +107 -0
  53. metadata +137 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 18b85bde0894ec3023141a8e20862d0bc2641ece9cab486b0743d765fdae45e3
4
+ data.tar.gz: 57b043cd9f75abdd5a8a3b4f63276c9526c7893f059eaa7d9acd19d9c68de0df
5
+ SHA512:
6
+ metadata.gz: c06f1cffb20b1ea8185d89425395702a44c443f1f4928011876f8eccc5f04218a413c25edd610613abc35da88c9694b91a60304158f0b48a72239cdb1963d090
7
+ data.tar.gz: 4224f7d0f8675a6de3ceca6c3665f9df884275b01d4efe835621b10e81bd4a0e0b7708651b7953908d6e1c39b875da0f4c4f27688d1d889c8c010ebf78c6c77b
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Trendence Institut GmbH
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 all
13
+ 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 THE
21
+ SOFTWARE.
data/NOTICE ADDED
@@ -0,0 +1,9 @@
1
+ Third-party notice
2
+
3
+ This project renders charts with Highcharts, which is NOT covered by the MIT
4
+ licence in LICENSE and is not distributed with this project. Highcharts is
5
+ commercial software by Highsoft AS. Using it, whether from the CDN or from a
6
+ local copy, requires a valid licence from Highsoft for anything beyond the
7
+ uses their terms grant for free.
8
+
9
+ See https://www.highcharts.com/license
data/README.md ADDED
@@ -0,0 +1,431 @@
1
+ <p align="center">
2
+ <img src="assets/trevl-logo.svg" alt="TREVL" width="220" />
3
+ <br /><br />
4
+ <img src="assets/trendence-logo.svg" alt="Trendence" width="140" />
5
+ </p>
6
+
7
+ <h3 align="center">Write YAML, get Highcharts.</h3>
8
+
9
+ <p align="center">
10
+ <a href="https://trevl.trendence.com">DSL Documentation</a> &middot;
11
+ <a href="notebooks/demo.ipynb">Demo Notebook</a> &middot;
12
+ <a href="https://github.com/trendence/trevl">GitHub</a>
13
+ </p>
14
+
15
+ ---
16
+
17
+ [Trendence](https://www.trendence.com) is a Berlin-based HR data and analytics company. We believe data visualization should be modern, AI-ready, and accessible. That's why we've been building TREVL -- the **TR**Endence **V**isualization **L**anguage -- a custom DSL designed to make chart creation as simple as writing a few lines of YAML. A language humans easily can use and robots love.
18
+
19
+ ## AI-First Design
20
+
21
+ TREVL is built for humans and machines. Every feature is designed so that LLMs can generate, validate, and iterate on visualizations autonomously:
22
+
23
+ - **`Trevl.schema_reference`** -- compact reference (~1500 tokens) optimized for system prompts
24
+ - **`Trevl.validate(yaml)`** -- structured error feedback for self-correction loops
25
+ - **`Trevl.examples`** -- 10 annotated examples for few-shot learning
26
+ - **`Trevl::DataSource.for("name").field_names("endpoint")`** -- discover available data fields
27
+ - **[`llms.txt`](llms.txt)** -- machine-readable reference in the repo root
28
+ - **JSON Schema** -- formal validation for editors, CI, and AI agents
29
+
30
+ ```ruby
31
+ # 1. Discover: what fields does this endpoint return?
32
+ Trevl::DataSource.for("myapi").field_names("salary")
33
+ # => ["q10", "q50", "q90"]
34
+
35
+ # 2. Reference: get the compact TREVL spec for a system prompt
36
+ Trevl.schema_reference
37
+ # => "# TREVL — TREndence Visualization Language\n..."
38
+
39
+ # 3. Examples: few-shot learning material
40
+ Trevl.examples.first
41
+ # => {name: "bar_chart", description: "Simple bar chart...", yaml: "..."}
42
+
43
+ # 4. Validate: catch errors before rendering
44
+ Trevl.validate(yaml).errors
45
+ # => ["[my_chart] Missing required field(s): api, highchartsData (at )"]
46
+
47
+ # 5. Render: YAML → Highcharts JSON
48
+ Trevl.render(yaml)
49
+ ```
50
+
51
+ ## Features
52
+
53
+ - **Declarative YAML** -- define charts, scores, tables, and filters without writing JavaScript
54
+ - **Pluggable data sources** -- REST APIs, CubeJS, static/in-memory data, or build your own
55
+ - **Computed fields** -- per-row JavaScript transformations via ExecJS
56
+ - **Postprocess** -- full-dataset transforms (sort, filter, aggregate) in JavaScript
57
+ - **Template inheritance** -- share chart styles with deep merge
58
+ - **JSON Schema validation** -- catch errors before rendering
59
+ - **iRuby notebooks** -- render interactive Highcharts directly in Jupyter
60
+ - **Fully offline** -- bundled Highcharts JS, no CDN needed
61
+ - **Standalone** -- no Rails, no framework dependencies
62
+
63
+ ## Installation
64
+
65
+ ```ruby
66
+ gem "trevl", github: "trendence/trevl"
67
+ ```
68
+
69
+ **Prerequisites:** Ruby >= 3.1, Node.js (`brew install node`) for computed fields.
70
+
71
+ ## Quick Start
72
+
73
+ ```ruby
74
+ require "trevl"
75
+
76
+ # 1. Register a data source
77
+ Trevl::DataSource.register("demo", Trevl::DataSource::Static.new(
78
+ data: {
79
+ "pirates" => {
80
+ "data" => [
81
+ {"name" => "Guybrush", "barrels" => 12},
82
+ {"name" => "LeChuck", "barrels" => 47},
83
+ {"name" => "Elaine", "barrels" => 3},
84
+ {"name" => "Stan", "barrels" => 28},
85
+ {"name" => "Murray", "barrels" => 0}
86
+ ]
87
+ }
88
+ }
89
+ ))
90
+
91
+ # 2. Render
92
+ results = Trevl.render(<<~YAML)
93
+ components:
94
+ - id: rum_consumption
95
+ type: chart
96
+ api: demo
97
+ highchartsData:
98
+ chart:
99
+ type: bar
100
+ title:
101
+ text: Annual Rum Consumption by Pirate (Barrels)
102
+ colors: ["#8B4513"]
103
+ series:
104
+ - name: Rum (barrels)
105
+ data:
106
+ x: "$pirates.data.name"
107
+ y: "$pirates.data.barrels"
108
+ YAML
109
+
110
+ # 3. Done -- results.first["highchartsData"] is ready for Highcharts
111
+ ```
112
+
113
+ <p align="center">
114
+ <img src="docs/screenshots/01_bar_chart.png" alt="Bar Chart" width="600" />
115
+ </p>
116
+
117
+ ## Examples Gallery
118
+
119
+ <table>
120
+ <tr>
121
+ <td><img src="docs/screenshots/02_column_chart.png" alt="Column Chart" width="400" /></td>
122
+ <td><img src="docs/screenshots/03_line_chart.png" alt="Line Chart" width="400" /></td>
123
+ </tr>
124
+ <tr>
125
+ <td><img src="docs/screenshots/04_pie_chart.png" alt="Pie Chart" width="400" /></td>
126
+ <td><img src="docs/screenshots/05_computed_fields.png" alt="Computed Fields" width="400" /></td>
127
+ </tr>
128
+ <tr>
129
+ <td><img src="docs/screenshots/06_postprocess_top_n.png" alt="Postprocess Top-N" width="400" /></td>
130
+ <td><img src="docs/screenshots/10_multi_series.png" alt="Multi Series" width="400" /></td>
131
+ </tr>
132
+ </table>
133
+
134
+ See [`examples/`](examples/) for the YAML source of each chart.
135
+
136
+ ## HTML Export
137
+
138
+ Render TREVL to an HTML file:
139
+
140
+ ```ruby
141
+ html = Trevl.render_to_html(yaml, width: 1000, height: 500)
142
+ File.write("chart.html", html)
143
+ ```
144
+
145
+ The output is a complete HTML document that pulls Highcharts from the CDN. Point `highcharts_path` at a local copy (see [Highcharts](#highcharts)) and it is embedded inline instead, which makes the file self-contained and usable offline. Open it in any browser, or take a screenshot for AI agents:
146
+
147
+ ```ruby
148
+ # Grover gem (Puppeteer wrapper)
149
+ Grover.new(html).to_png
150
+
151
+ # Ferrum (Chrome DevTools Protocol)
152
+ browser = Ferrum::Browser.new
153
+ browser.content = html
154
+ browser.screenshot(path: "chart.png")
155
+
156
+ # Playwright MCP (for AI agents)
157
+ # browser_navigate → browser_take_screenshot
158
+ ```
159
+
160
+ ## iRuby Notebooks
161
+
162
+ ```ruby
163
+ require "trevl"
164
+ require "trevl/notebook"
165
+
166
+ nb = Trevl::Notebook.new
167
+
168
+ nb.chart(<<~YAML, data: {"salary" => {"data" => [...]}})
169
+ components:
170
+ - id: chart
171
+ type: chart
172
+ api: static
173
+ highchartsData:
174
+ chart:
175
+ type: column
176
+ series:
177
+ - data:
178
+ x: "$salary.data.level"
179
+ y: "$salary.data.value"
180
+ YAML
181
+ ```
182
+
183
+ Highcharts is bundled -- charts render offline. See [`notebooks/demo.ipynb`](notebooks/demo.ipynb) for 5 working examples.
184
+
185
+ ## Data Sources
186
+
187
+ ### Static (in-memory)
188
+
189
+ ```ruby
190
+ Trevl::DataSource.register("mydata", Trevl::DataSource::Static.new(
191
+ data: {"endpoint" => {"data" => [...], "meta" => {...}}}
192
+ ))
193
+ ```
194
+
195
+ ### REST API
196
+
197
+ ```ruby
198
+ Trevl::DataSource.register("myapi", Trevl::DataSource::Api.new(
199
+ base_url: "https://api.example.com/v1",
200
+ auth: Trevl::Auth::BearerToken.new(ENV["API_TOKEN"])
201
+ ))
202
+ ```
203
+
204
+ ### CubeJS
205
+
206
+ ```ruby
207
+ Trevl::DataSource.register("cube", Trevl::DataSource::Cube.new(
208
+ url: "https://cube.example.com/cubejs-api/v1",
209
+ token: ENV["CUBE_TOKEN"]
210
+ ))
211
+ ```
212
+
213
+ ### Custom
214
+
215
+ ```ruby
216
+ class MySource < Trevl::DataSource::Base
217
+ def fetch(endpoint, params = {}, resource: nil)
218
+ {"data" => MyDB.query(endpoint, params), "meta" => {}}
219
+ end
220
+ end
221
+
222
+ Trevl::DataSource.register("db", MySource.new)
223
+ ```
224
+
225
+ ### Per-render injection
226
+
227
+ Instead of registering globally, pass data directly to a render call.
228
+ Per-render data takes precedence over the registry and never touches shared
229
+ state — the right choice when the data differs per request (e.g. web apps
230
+ serving concurrent users).
231
+
232
+ For inline rows, pass the raw hash as `data:` — it answers any `api:` name in
233
+ the document, and components may omit `api:` entirely:
234
+
235
+ ```ruby
236
+ Trevl.render(yaml, data: {"scores" => rows_for_this_request})
237
+ Trevl.render_to_html(yaml, data: {"scores" => rows_for_this_request})
238
+ ```
239
+
240
+ For full control (multiple sources, API/Cube instances), pass `data_sources:`
241
+ — entries win over `data:` for their name:
242
+
243
+ ```ruby
244
+ source = Trevl::DataSource::Api.new(base_url: "https://api.example.com/v1")
245
+
246
+ Trevl.render(yaml, data_sources: {"mydata" => source})
247
+ ```
248
+
249
+ ## Validation
250
+
251
+ Validate TREVL YAML before rendering — catch errors early, not at render time.
252
+
253
+ ```ruby
254
+ result = Trevl.validate(<<~YAML)
255
+ components:
256
+ - id: my_chart
257
+ type: chart
258
+ YAML
259
+
260
+ result.valid? # => false
261
+ result.errors # => ["[my_chart] Missing required field(s): api, highchartsData (at )"]
262
+ ```
263
+
264
+ Powered by [JSON Schema (draft 2020-12)](lib/trevl/schema/component.json) -- covers all 5 component types with conditional validation. The schema files work standalone in VS Code, CI pipelines, or any JSON Schema-compatible tool.
265
+
266
+ Ideal for AI agents: generate TREVL, validate, self-correct, render.
267
+
268
+ Full docs: [trevl.trendence.com/validation](https://trevl.trendence.com/validation)
269
+
270
+ ## YAML Reference
271
+
272
+ ### Component Types
273
+
274
+ | Type | Description |
275
+ |------|-------------|
276
+ | `chart` | Highcharts visualization (bar, column, line, pie, ...) |
277
+ | `score` | Single KPI value with optional unit |
278
+ | `table` | Data table with column definitions |
279
+ | `text` | Static text / HTML content |
280
+ | `filter` | Filter options bound to data |
281
+
282
+ ### Variable References
283
+
284
+ ```yaml
285
+ "$endpoint.data.fieldName" # data row field
286
+ "$endpoint.meta.fieldName" # metadata field
287
+ "$resource.endpoint.data.fieldName" # with resource qualifier
288
+ "$computedFieldName" # computed field shorthand
289
+ ```
290
+
291
+ ### Computed Fields
292
+
293
+ Per-row JavaScript expressions:
294
+
295
+ ```yaml
296
+ computed:
297
+ - name: color
298
+ arguments:
299
+ val: "$salary.data.value"
300
+ code: 'val > 60000 ? "#003F85" : "#ccc"'
301
+ ```
302
+
303
+ ### Postprocess
304
+
305
+ Full-dataset JavaScript transforms:
306
+
307
+ ```yaml
308
+ postprocess: |
309
+ $result = $result
310
+ .sort((a, b) => b.value - a.value)
311
+ .slice(0, 10);
312
+ ```
313
+
314
+ ### Templates
315
+
316
+ ```ruby
317
+ Trevl.template_store.register("blue_bar", {
318
+ "highchartsData" => {
319
+ "chart" => {"type" => "bar"},
320
+ "colors" => ["#003F85"]
321
+ }
322
+ })
323
+ ```
324
+
325
+ ```yaml
326
+ - id: my_chart
327
+ template: blue_bar
328
+ highchartsData:
329
+ title:
330
+ text: My Chart
331
+ ```
332
+
333
+ Deep merge: component overrides template at the same path.
334
+
335
+ ## Auth
336
+
337
+ ```ruby
338
+ # Bearer token
339
+ auth = Trevl::Auth::BearerToken.new("token")
340
+
341
+ # Custom -- any object with #apply(headers, url:)
342
+ class MyAuth
343
+ def apply(headers, url: nil)
344
+ headers["Authorization"] = "Bearer #{fetch_token}"
345
+ end
346
+ end
347
+ ```
348
+
349
+ ## Configuration
350
+
351
+ ```ruby
352
+ Trevl.configure do |c|
353
+ c.logger = Logger.new($stdout, level: :info)
354
+ c.template_store = my_custom_store
355
+ end
356
+ ```
357
+
358
+ ## Highcharts
359
+
360
+ TREVL produces Highcharts configuration; it does not ship Highcharts. Highcharts is
361
+ commercial software by [Highsoft](https://www.highcharts.com/license) and is
362
+ deliberately not bundled here, so using it requires your own licence.
363
+
364
+ `Trevl.render` returns plain configuration hashes and never touches Highcharts at all.
365
+ Only the HTML export and the notebook display load it, and by default they reference
366
+ the CDN:
367
+
368
+ ```ruby
369
+ Trevl.configure do |c|
370
+ c.highcharts_url = "https://code.highcharts.com/11.4.0/highcharts.js" # default
371
+ c.highcharts_modules = ["https://code.highcharts.com/11.4.0/highcharts-more.js"]
372
+ end
373
+ ```
374
+
375
+ Set `highcharts_path` to a local file and it gets inlined instead of linked, which is
376
+ what you want for offline use or air-gapped rendering:
377
+
378
+ ```ruby
379
+ Trevl.configure do |c|
380
+ c.highcharts_path = "/opt/highcharts/highcharts.js"
381
+ end
382
+ ```
383
+
384
+ `highcharts_modules` accepts URLs and local paths under the same rule: a path is
385
+ inlined, a URL is referenced.
386
+
387
+ ### In a Rails app
388
+
389
+ If your app already renders charts, it almost certainly ships Highcharts through the
390
+ asset pipeline. In that case, do nothing: pass the hash from `Trevl.render` to your
391
+ existing frontend and let the bundle you already load draw it.
392
+
393
+ ```ruby
394
+ components = Trevl.render(yaml, data: {"rows" => rows})
395
+ # hand components.first["highchartsData"] to your Stimulus controller
396
+ ```
397
+
398
+ Only the server-side HTML export needs its own copy. The leanest way to give it one is
399
+ to reuse the file the asset pipeline already has:
400
+
401
+ ```ruby
402
+ # config/initializers/trevl.rb
403
+ Trevl.configure do |c|
404
+ local = Rails.root.join("vendor/javascript/highcharts.js")
405
+ c.highcharts_path = local if local.exist?
406
+ end
407
+ ```
408
+
409
+ Without that initializer the export falls back to the CDN, which is fine for anything
410
+ that renders in a browser with network access.
411
+
412
+ ## Development
413
+
414
+ ```bash
415
+ bin/setup # install dependencies
416
+ bundle exec rspec # 140 specs
417
+ bundle exec standardrb # lint
418
+ bin/console # interactive console
419
+ ```
420
+
421
+ ## Language Specification
422
+
423
+ The full TREVL v3.0 specification lives at **[trevl.trendence.com](https://trevl.trendence.com)** -- covering component schemas, query definitions, filter operators, computed fields, postprocess patterns, template inheritance, and data source integration.
424
+
425
+ ## License
426
+
427
+ MIT -- see [LICENSE](LICENSE).
428
+
429
+ Highcharts is not covered by that licence and is not distributed with this project.
430
+ Using it requires a licence from Highsoft; see [NOTICE](NOTICE) and
431
+ [highcharts.com/license](https://www.highcharts.com/license).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "standard/rake"
9
+
10
+ task default: %i[spec standard]
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg aria-hidden="true" enable-background="new 0 0 733.8 140.4" version="1.1" width="733" height="140" viewBox="0 0 733 140" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
3
+ <g fill="#006ADF">
4
+ <path d="m542.9 108.6v-63.3h9s3.3-0.1 5.7 2.9 2.3 4.7 2.3 4.7 4.7-7.6 17.2-7.6 22.1 9.3 22.1 21.8v41.4h-9.7s-7.6-0.8-7.7-9.6v-26.9s0.4-11.4-9.9-11.4-11.8 11.4-11.8 14.9v33.2h-17.2z" />
5
+ <path d="m332.9 108.6v-63.3h9s3.3-0.1 5.7 2.9 2.3 4.7 2.3 4.7 4.7-7.6 17.2-7.6 22.1 9.3 22.1 21.8v41.4h-9.7s-7.6-0.8-7.7-9.6v-26.9s0.4-11.4-9.9-11.4-11.8 11.4-11.8 14.9v33.2h-17.2z" />
6
+ <path d="m731.7 83.2s0.4-1.3 0.4-6-1.2-14.1-8.8-22.6-16.8-10.2-23.1-10.2-15.7 2.1-23.2 10.8-9.8 20.1-7.6 30.2 8.3 17.7 19.8 22.3 24.6 1.2 30.8-2.7 8.7-7.4 8.7-7.4l-11.7-9s-5.4 6.2-14 6.2c0 0-8.8 0.4-13.5-4.3-3.8-3.9-3.6-7.2-3.6-7.2h45.8zm-31.4-23.9c11.6 0 13.9 10.5 13.9 10.5h-27.6s2-10.5 13.7-10.5z" />
7
+ <path d="m532.7 83s0.4-1.3 0.4-6-1.2-14.1-8.8-22.6-16.8-10.2-23.1-10.2-15.7 2.1-23.2 10.8-9.8 20.1-7.6 30.3 8.3 17.7 19.8 22.3 24.6 1.2 30.8-2.7 8.7-7.4 8.7-7.4l-11.7-9.1s-5.4 6.2-14 6.2c0 0-8.8 0.4-13.5-4.3-3.8-3.9-3.6-7.2-3.6-7.2h45.8zm-31.4-24c11.6 0 13.9 10.5 13.9 10.5h-27.6s2-10.5 13.7-10.5z" />
8
+ <path d="m323.4 83.2s0.4-1.3 0.4-6-1.2-14.1-8.8-22.6-16.8-10.1-23-10.1-15.7 2.1-23.2 10.8-9.8 20.1-7.6 30.2 8.3 17.7 19.8 22.3 24.6 1.2 30.8-2.7 8.7-7.4 8.7-7.4l-11.6-9.2s-5.4 6.2-14 6.2c0 0-8.8 0.4-13.5-4.3-3.8-3.9-3.6-7.2-3.6-7.2h45.6zm-31.4-23.9c11.6 0 13.9 10.5 13.9 10.5h-27.6s2.1-10.5 13.7-10.5z" />
9
+ <path d="m428.8 45.5c5.8 0 11.2 1.6 15.9 4.3v-31.3h16.7l0.1 90.5h-8.2s-5.3 0-7.5-4.7c-4.9 3.1-10.7 4.9-17 4.9-17.6 0-31.9-14.3-31.9-31.8 0.1-17.6 14.4-31.9 31.9-31.9zm0 47.9c8.9 0 16.1-7.2 16.1-16.1s-7.2-16.1-16.1-16.1-16.1 7.2-16.1 16.1 7.3 16.1 16.1 16.1z" />
10
+ <path d="m173.4 45.6v-16.8h17.7v16.8h10.2v13.1h-10.3v28.3s-0.4 5.4 5.2 5.4h8v16.4h-12.9s-8.5 0.5-14.1-5.6c-4.3-4.7-3.9-12.4-3.9-12.4v-32h-10.3v-13.2h10.4z" />
11
+ <path d="m256.7 62.4l-2.4 0.1s-10.3 0.1-14.8 6.1c-4.3 5.7-3.5 12.4-3.5 12.4v27.4h-17.6v-63h9.6s2.7-0.2 5.2 3c2.5 3.1 2.1 5.6 2.1 5.6s1-3.6 5.8-6.5 10.2-2.7 10.2-2.7h5.6v17.4l-0.2 0.2z" />
12
+ <path d="m651.6 87.2c-2.9 3.9-7.6 6.4-12.9 6.4-8.9 0-16.1-7.2-16.1-16.1s7.2-16.1 16.1-16.1c5.4 0 10.2 2.7 13.2 6.8l12.9-9c-5.8-8.2-15.3-13.6-26.1-13.6-17.6 0-31.8 14.3-31.8 31.8 0 17.6 14.3 31.8 31.8 31.8 10.5 0 19.8-5.1 25.6-12.9l-12.7-9.1z" />
13
+ <circle cx="69.7" cy="69.5" r="13.4" />
14
+ <path d="m69.7 28.8c-22.5 0-40.7 18.2-40.7 40.7 0 8.1 2.4 15.7 6.5 22 0.1 0.1 0.1 0.2 0.2 0.3 0 0 0 0.1 0.1 0.1 1.5 2.2 4 3.6 6.9 3.6 4.6 0 8.3-3.7 8.3-8.3 0-1.7-0.5-3.2-1.4-4.6 0-0.1-0.1-0.1-0.1-0.2-2.4-3.7-3.8-8.2-3.8-13 0-13.3 10.8-24.1 24.1-24.1s24.1 10.8 24.1 24.1-10.8 24.1-24.1 24.1c-0.9 0-1.7 0-2.5-0.1h-0.1-0.1-0.8c-4.6 0-8.3 3.7-8.3 8.3 0 4.3 3.2 7.8 7.3 8.3h0.4c1.3 0.1 2.7 0.2 4.1 0.2 22.5 0 40.7-18.2 40.7-40.7s-18.3-40.7-40.8-40.7z" />
15
+ <path d="m69.7 0.6c-6.6 0-13 1-19.1 2.7-0.5 0.1-0.9 0.2-1.3 0.4-3.3 1.2-5.7 4.4-5.7 8.1 0 4.8 3.9 8.7 8.7 8.7 0.7 0 1.3-0.1 1.9-0.2 0.4-0.1 0.7-0.2 1-0.3 4.6-1.3 9.5-2.1 14.5-2.1 28.5 0 51.6 23.1 51.6 51.6s-23.1 51.6-51.6 51.6-51.6-23.1-51.6-51.6c0-14.7 6.2-28 16.1-37.4 0.2-0.1 0.3-0.3 0.5-0.4 1.5-1.6 2.4-3.7 2.4-6 0-4.8-3.9-8.7-8.7-8.7-2 0-3.9 0.7-5.4 1.9-0.4 0.3-0.8 0.7-1.1 1-12.9 12.5-21.1 30.1-21.1 49.6 0 38 30.8 68.9 68.9 68.9s68.9-30.8 68.9-68.9-30.8-68.9-68.9-68.9z" />
16
+ </g>
17
+ </svg>
@@ -0,0 +1,20 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 92 36" width="92" height="36">
2
+ <!-- TREVL logo: letters in Trendence blue, E = colorful bar chart -->
3
+
4
+ <!-- T - Trendence blue -->
5
+ <text x="0" y="27" font-family="Inter, -apple-system, sans-serif" font-size="28" font-weight="700" fill="#006ADF" letter-spacing="-1">T</text>
6
+
7
+ <!-- R - Trendence blue -->
8
+ <text x="17" y="27" font-family="Inter, -apple-system, sans-serif" font-size="28" font-weight="700" fill="#006ADF" letter-spacing="-1">R</text>
9
+
10
+ <!-- E as three horizontal bars in brand colors -->
11
+ <rect x="38" y="7" width="18" height="5" rx="1.5" fill="#8B3A9F"/>
12
+ <rect x="38" y="14" width="12" height="5" rx="1.5" fill="#E8922F"/>
13
+ <rect x="38" y="21" width="16" height="5" rx="1.5" fill="#E85D3A"/>
14
+
15
+ <!-- V - Trendence blue -->
16
+ <text x="58" y="27" font-family="Inter, -apple-system, sans-serif" font-size="28" font-weight="700" fill="#006ADF" letter-spacing="-1">V</text>
17
+
18
+ <!-- L - Trendence blue -->
19
+ <text x="76" y="27" font-family="Inter, -apple-system, sans-serif" font-size="28" font-weight="700" fill="#006ADF" letter-spacing="-1">L</text>
20
+ </svg>
Binary file
Binary file
Binary file
@@ -0,0 +1,16 @@
1
+ # Simple bar chart. Use when you want horizontal bars comparing categories.
2
+ components:
3
+ - id: rum_consumption
4
+ type: chart
5
+ api: demo
6
+ highchartsData:
7
+ chart:
8
+ type: bar
9
+ title:
10
+ text: Annual Rum Consumption by Pirate (Barrels)
11
+ colors: ["#8B4513"]
12
+ series:
13
+ - name: Rum (barrels)
14
+ data:
15
+ x: "$pirates.data.name"
16
+ y: "$pirates.data.barrels"
@@ -0,0 +1,19 @@
1
+ # Vertical column chart. Use for comparing values across categories side by side.
2
+ components:
3
+ - id: treasure_haul
4
+ type: chart
5
+ api: demo
6
+ highchartsData:
7
+ chart:
8
+ type: column
9
+ title:
10
+ text: Treasure Haul by Quarter (Doubloons)
11
+ colors: ["#DAA520"]
12
+ plotOptions:
13
+ column:
14
+ borderRadius: 4
15
+ series:
16
+ - name: Doubloons
17
+ data:
18
+ x: "$loot.data.quarter"
19
+ y: "$loot.data.doubloons"
@@ -0,0 +1,21 @@
1
+ # Line chart for time series. Use when showing trends over time.
2
+ components:
3
+ - id: monkey_sightings
4
+ type: chart
5
+ api: demo
6
+ highchartsData:
7
+ chart:
8
+ type: line
9
+ title:
10
+ text: Three-Headed Monkey Sightings per Month
11
+ xAxis:
12
+ type: category
13
+ yAxis:
14
+ title:
15
+ text: Sightings
16
+ series:
17
+ - name: Sightings
18
+ color: "#2E7D32"
19
+ data:
20
+ x: "$monkeys.data.month"
21
+ y: "$monkeys.data.sightings"
@@ -0,0 +1,15 @@
1
+ # Pie chart for proportions. Use when showing parts of a whole.
2
+ components:
3
+ - id: mutiny_vote
4
+ type: chart
5
+ api: demo
6
+ highchartsData:
7
+ chart:
8
+ type: pie
9
+ title:
10
+ text: Mutiny Board Election Results
11
+ series:
12
+ - name: Votes
13
+ data:
14
+ name: "$candidates.data.candidate"
15
+ y: "$candidates.data.votes"
@@ -0,0 +1,26 @@
1
+ # Computed fields with conditional coloring. Use when you need per-row logic.
2
+ # Arguments bind $references to JS variables. Code is a JS expression.
3
+ # Computed field results are accessible as row fields via $endpoint.data.fieldName.
4
+ components:
5
+ - id: insult_mastery
6
+ type: chart
7
+ api: demo
8
+ computed:
9
+ - name: color
10
+ arguments:
11
+ val: "$pirates.data.skill"
12
+ code: 'val > 80 ? "#2E7D32" : val > 50 ? "#E65100" : "#C62828"'
13
+ highchartsData:
14
+ chart:
15
+ type: bar
16
+ title:
17
+ text: Insult Sword Fighting Skill Rating
18
+ plotOptions:
19
+ bar:
20
+ colorByPoint: true
21
+ series:
22
+ - name: Skill
23
+ data:
24
+ x: "$pirates.data.name"
25
+ y: "$pirates.data.skill"
26
+ color: "$pirates.data.color"
@@ -0,0 +1,21 @@
1
+ # Postprocess: sort and take top N. Use when you need to filter/sort the full dataset.
2
+ # $result is the data array. Reassign it with the transformed result.
3
+ components:
4
+ - id: top_islands
5
+ type: chart
6
+ api: demo
7
+ postprocess: |
8
+ $result = $result
9
+ .sort(function(a, b) { return b.buried - a.buried; })
10
+ .slice(0, 5);
11
+ highchartsData:
12
+ chart:
13
+ type: bar
14
+ title:
15
+ text: Top 5 Islands by Buried Treasure
16
+ colors: ["#DAA520"]
17
+ series:
18
+ - name: Chests buried
19
+ data:
20
+ x: "$islands.data.name"
21
+ y: "$islands.data.buried"
@@ -0,0 +1,13 @@
1
+ # Score component for a single KPI value. Use for dashboards with key numbers.
2
+ components:
3
+ - id: crew_morale
4
+ type: score
5
+ api: demo
6
+ display:
7
+ value: "$morale.data.score"
8
+ unit: "%"
9
+ header:
10
+ title: Crew Morale
11
+ format:
12
+ minimumFractionDigits: 0
13
+ maximumFractionDigits: 0