railsui_charts 0.1.0 → 0.1.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7c8dc823b54699d34aa3086a00c101d2af00be11f62c1934ce61cb2d47fca6be
4
- data.tar.gz: 1b3e956f025a5121406c9a11d66d17b43208e43fde6afd445a965bc2ffccb612
3
+ metadata.gz: 90aab15c8c1ef133527f757c7e24344da84a62a190825a13decee8979cf79892
4
+ data.tar.gz: db6626712782f3a93d92ea8c149d9fbe27cece328b1cfca4b611269dd06a8c0b
5
5
  SHA512:
6
- metadata.gz: 7834d2e0790b218314615c6948fa6e59c0280a3f806d528fc931edc721383bc31ff24cb4344f3716fc269b7f8c697fdace6044d9ef3ecfcbe9461e303b371a77
7
- data.tar.gz: 2425d97d2acd25b4147d37b31319cc83842f1db83d46d3d15582bed61dc212aef0c1dce0c5a46425a9b0e14874a6541c93fe7d1fb31440aaf53dc137de9e82cb
6
+ metadata.gz: 94345b1a73e7cdd1e2760ee58462f6af60396019295cb0a05a5f300120c2d5ed192d64770cb38254abfa959e94ca5ab51ed9353107163e5f2eb75a22e42611a9
7
+ data.tar.gz: e89fad7105008595f9de2070044287e1c193a09ab83dd327492a794106259d24783fc30ed580e19c07a40c8a7ea06ed2fbb7ac5780d620af0eafe7ce643da9d8
data/CHANGELOG.md CHANGED
@@ -6,6 +6,27 @@ public API may change between minor versions.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.1.2]
10
+
11
+ ### Fixed
12
+
13
+ - Tooltips on pie, donut and polar area charts rendered as an empty box. A
14
+ circular chart hands the tooltip a flat array of numbers and names the
15
+ hovered slice with `seriesIndex`; reading it as one array per series gave
16
+ every value `undefined`, and rows without a value are dropped. The slice now
17
+ shows its name and its formatted value.
18
+
19
+ ## [0.1.1]
20
+
21
+ ### Fixed
22
+
23
+ - Legend markers now start where the rest of the card does. A left-aligned
24
+ legend is inset by ApexCharts' own chrome and padding before the first item's
25
+ margin applies, so the markers sat 28px right of the axis labels and the
26
+ heading above them. The correction is measured against a rendered chart
27
+ rather than derived, and the mobile breakpoint — which uses a tighter gap
28
+ between items — is corrected to match.
29
+
9
30
  ## [0.1.0]
10
31
 
11
32
  First release.
@@ -46,5 +67,7 @@ First release.
46
67
  reachable only by hovering a mark
47
68
  - Animation stops when the reader has asked for reduced motion
48
69
 
49
- [Unreleased]: https://github.com/getrailsui/railsui_charts/compare/v0.1.0...HEAD
70
+ [Unreleased]: https://github.com/getrailsui/railsui_charts/compare/v0.1.2...HEAD
71
+ [0.1.2]: https://github.com/getrailsui/railsui_charts/compare/v0.1.1...v0.1.2
72
+ [0.1.1]: https://github.com/getrailsui/railsui_charts/compare/v0.1.0...v0.1.1
50
73
  [0.1.0]: https://github.com/getrailsui/railsui_charts/releases/tag/v0.1.0
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # Rails UI Charts
2
2
 
3
+ [![Gem Version](https://img.shields.io/gem/v/railsui_charts.svg)](https://rubygems.org/gems/railsui_charts)
3
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
5
 
5
6
  Production-ready chart components for Rails. Built on [ApexCharts](https://apexcharts.com), wrapped in Rails-native helpers, and designed for Tailwind CSS.
@@ -14,8 +15,6 @@ Production-ready chart components for Rails. Built on [ApexCharts](https://apexc
14
15
  <%= railsui_chart [{ x: "A", y: 30 }, { x: "B", y: 50 }], type: :pie %>
15
16
  ```
16
17
 
17
- Or clone the [railsui.com site](https://github.com/justalever/railsui_app) and visit `/charts` for the full showcase.
18
-
19
18
  ## Why Rails UI Charts?
20
19
 
21
20
  AI can generate a first-draft chart in seconds. The hard part is the last 20%: accessibility, responsive behavior, dark mode, Turbo lifecycle support, loading and empty states, and a stable API that does not break when you upgrade.
@@ -128,8 +128,23 @@ export default class extends Controller {
128
128
  ...options,
129
129
  tooltip: {
130
130
  ...(options.tooltip || {}),
131
- custom: ({ series, dataPointIndex, w }) => {
131
+ custom: ({ series, seriesIndex, dataPointIndex, w }) => {
132
132
  const labels = w.globals.categoryLabels?.length ? w.globals.categoryLabels : w.globals.labels
133
+
134
+ // A pie, donut or polar area hands back one number per slice rather
135
+ // than one array per series, and names the hovered slice with
136
+ // seriesIndex — dataPointIndex means nothing there. Read as a
137
+ // cartesian series, every value came out undefined, and since rows
138
+ // without a value are dropped the tooltip rendered as an empty box.
139
+ if (!Array.isArray(series[0])) {
140
+ const slice = seriesIndex ?? dataPointIndex
141
+ // No row label: the slice's name is already the heading, and
142
+ // printing it twice in a two-line tooltip reads as a mistake.
143
+ const row = { label: "", value: series[slice], color: w.globals.colors[slice], format: rowFormats[slice] || null }
144
+
145
+ return this.tooltipMarkup(labels?.[slice], [row], null, format)
146
+ }
147
+
133
148
  const point = (index) => series[index]?.[dataPointIndex]
134
149
  const comparing = series.length === 2 && comparedDates.length > 0
135
150
 
@@ -128,8 +128,23 @@ export default class extends Controller {
128
128
  ...options,
129
129
  tooltip: {
130
130
  ...(options.tooltip || {}),
131
- custom: ({ series, dataPointIndex, w }) => {
131
+ custom: ({ series, seriesIndex, dataPointIndex, w }) => {
132
132
  const labels = w.globals.categoryLabels?.length ? w.globals.categoryLabels : w.globals.labels
133
+
134
+ // A pie, donut or polar area hands back one number per slice rather
135
+ // than one array per series, and names the hovered slice with
136
+ // seriesIndex — dataPointIndex means nothing there. Read as a
137
+ // cartesian series, every value came out undefined, and since rows
138
+ // without a value are dropped the tooltip rendered as an empty box.
139
+ if (!Array.isArray(series[0])) {
140
+ const slice = seriesIndex ?? dataPointIndex
141
+ // No row label: the slice's name is already the heading, and
142
+ // printing it twice in a two-line tooltip reads as a mistake.
143
+ const row = { label: "", value: series[slice], color: w.globals.colors[slice], format: rowFormats[slice] || null }
144
+
145
+ return this.tooltipMarkup(labels?.[slice], [row], null, format)
146
+ }
147
+
133
148
  const point = (index) => series[index]?.[dataPointIndex]
134
149
  const comparing = series.length === 2 && comparedDates.length > 0
135
150
 
@@ -14,6 +14,9 @@ module RailsuiCharts
14
14
 
15
15
  # Both sides of a dual axis are cut into this many intervals, so one grid
16
16
  # serves both scales.
17
+ LEGEND_INSET = 28
18
+ LEGEND_ITEM_GAP = 8
19
+ LEGEND_MOBILE_ITEM_GAP = 6
17
20
  AXIS_INTERVALS = 4
18
21
 
19
22
  # Apex reserves a gutter between the axis labels and the edge of its canvas.
@@ -247,7 +250,13 @@ module RailsuiCharts
247
250
  breakpoint: 640,
248
251
  options: {
249
252
  chart: { height: mobile_height },
250
- legend: { fontSize: font_size_sm, itemMargin: { horizontal: 6, vertical: 2 } },
253
+ # A tighter item gap needs a matching correction, or the mobile
254
+ # legend lands two pixels left of where the desktop one does.
255
+ legend: {
256
+ fontSize: font_size_sm,
257
+ itemMargin: { horizontal: LEGEND_MOBILE_ITEM_GAP, vertical: 2 },
258
+ offsetX: legend_offset(LEGEND_MOBILE_ITEM_GAP)
259
+ },
251
260
  xaxis: carry_over(config[:xaxis], { labels: { style: { fontSize: font_size_sm } } }),
252
261
  yaxis: mobile_yaxis(config[:yaxis]),
253
262
  grid: carry_over(config[:grid], { padding: { left: 0, right: 0 } }),
@@ -415,15 +424,28 @@ module RailsuiCharts
415
424
  show: true,
416
425
  position: "top",
417
426
  horizontalAlign: "left",
418
- offsetX: -8,
427
+ offsetX: legend_offset(LEGEND_ITEM_GAP),
419
428
  fontFamily: font_family,
420
429
  fontSize: font_size,
421
430
  labels: { colors: config_color(:text) },
422
431
  markers: { width: 8, height: 8, radius: 8, offsetX: -2 },
423
- itemMargin: { horizontal: 8, vertical: 0 }
432
+ itemMargin: { horizontal: LEGEND_ITEM_GAP, vertical: 0 }
424
433
  }
425
434
  end
426
435
 
436
+ # Left-aligning the legend does not put it where the eye expects. Apex
437
+ # insets it by its own chrome and padding before the first item's margin is
438
+ # even applied, so the markers sit indented from the axis labels and the
439
+ # heading above them — every other line in the card starts at one edge and
440
+ # the legend starts somewhere else.
441
+ #
442
+ # Measured against a rendered chart rather than derived: at offsetX 0 the
443
+ # marker lands LEGEND_INSET + the item gap to the right of the card edge,
444
+ # and the correction is linear in offsetX.
445
+ def legend_offset(item_gap)
446
+ -(LEGEND_INSET + item_gap)
447
+ end
448
+
427
449
  def comparison_fill
428
450
  # The comparison series gets a flat gradient rather than `opacity: 0`,
429
451
  # which would take its stroke down with it.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsuiCharts
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: railsui_charts
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Leverenz