Module: RailsuiCharts::ChartHelper
- Defined in:
- lib/railsui_charts/chart_helper.rb
Constant Summary collapse
- CIRCULAR_TYPES =
Forms whose placeholder should be a disc rather than a plotting area.
%i[pie donut polar_area radar].freeze
Instance Method Summary collapse
- #railsui_chart(data, type: :line, **options) ⇒ Object
-
#railsui_chart_empty(title: nil, description: nil, height: nil) ⇒ Object
Holds the chart's footprint so a card keeps its shape whether or not the query came back with anything.
- #railsui_chart_error(title: nil, description: nil, height: nil) ⇒ Object
-
#railsui_chart_skeleton(height: nil, type: :line, label: "Loading chart", align: :left) ⇒ Object
Server-rendered placeholder for a chart whose data has not arrived yet — the thing a Turbo frame shows before it swaps in the real one.
-
#railsui_small_multiples(series, type: :line, height: 120, columns: 3, **options) ⇒ Object
One small chart per series, sharing a y-scale.
-
#shared_scale(entries) ⇒ Object
Facets only compare if they share a scale.
Instance Method Details
#railsui_chart(data, type: :line, **options) ⇒ Object
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/railsui_charts/chart_helper.rb', line 8 def railsui_chart(data, type: :line, **) # An empty dataset is a normal day one, not an error. Rendering axes # around nothing looks like a chart that failed rather than a chart with # nothing to show yet. return railsui_chart_empty(**()) if ApexOptionsBuilder.blank?(data) config = ApexOptionsBuilder.new(data, type: type, **).build id = [:id] || "rui-chart-#{SecureRandom.hex(4)}" table = [:accessible] != false ? accessibility_table(config, id: id) : nil content_tag(:div, id: id, class: "railsui-chart", # Charts draw when they scroll into view, so the space has to # be held from the start. Without it the page is short on # load and grows under the reader as they scroll. style: reserved_height(config), data: { controller: "railsui-chart", "railsui-chart-options-value": config.to_json }) do table end end |
#railsui_chart_empty(title: nil, description: nil, height: nil) ⇒ Object
Holds the chart's footprint so a card keeps its shape whether or not the query came back with anything.
74 75 76 |
# File 'lib/railsui_charts/chart_helper.rb', line 74 def railsui_chart_empty(title: nil, description: nil, height: nil) chart_state(:empty, title: title || "No data", description: description, height: height) end |
#railsui_chart_error(title: nil, description: nil, height: nil) ⇒ Object
78 79 80 |
# File 'lib/railsui_charts/chart_helper.rb', line 78 def railsui_chart_error(title: nil, description: nil, height: nil) chart_state(:error, title: title || "Couldn't load this chart", description: description, height: height) end |
#railsui_chart_skeleton(height: nil, type: :line, label: "Loading chart", align: :left) ⇒ Object
Server-rendered placeholder for a chart whose data has not arrived yet — the thing a Turbo frame shows before it swaps in the real one. It keeps the chart footprint and avoids drawing fake chart geometry before data exists.
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/railsui_charts/chart_helper.rb', line 86 def railsui_chart_skeleton(height: nil, type: :line, label: "Loading chart", align: :left) alignment = skeleton_alignment(align) content_tag(:div, class: "railsui-chart-state railsui-chart-state--loading railsui-chart-state--loading-#{alignment}", style: state_height(height), role: "status", aria: { label: label, busy: true }) do content_tag(:div, class: "railsui-chart-skeleton", aria: { hidden: true }) do safe_join([ content_tag(:span, "", class: "railsui-skeleton-bar railsui-skeleton-bar--label"), content_tag(:span, "", class: "railsui-skeleton-bar railsui-skeleton-bar--value"), content_tag(:span, "", class: "railsui-skeleton-bar railsui-skeleton-bar--meta"), content_tag(:span, "", class: "railsui-chart-skeleton__plot"), content_tag(:span, "", class: "railsui-skeleton-bar railsui-skeleton-bar--footer") ]) end end end |
#railsui_small_multiples(series, type: :line, height: 120, columns: 3, **options) ⇒ Object
One small chart per series, sharing a y-scale.
This is the honest answer when there are more categories than a single chart can hold. Eight lines on one axis is a plate of spaghetti, and a ninth colour is not distinguishable from the others anyway — facets scale where colour does not.
<%= railsui_small_multiples @plans, type: :area, columns: 3 %>
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/railsui_charts/chart_helper.rb', line 39 def railsui_small_multiples(series, type: :line, height: 120, columns: 3, **) return railsui_chart_empty(**()) if ApexOptionsBuilder.blank?(series) entries = Array(series) shared = shared_scale(entries) content_tag(:div, class: "railsui-small-multiples", style: "--rui-small-multiple-columns: #{columns.to_i}") do safe_join(entries.each_with_index.map do |entry, index| content_tag(:div, class: "railsui-small-multiple") do safe_join([ content_tag(:p, entry[:name] || entry["name"] || "Series #{index + 1}", class: "railsui-small-multiple__title"), # Every facet takes the same colour. The title carries identity # here, so spending a hue on it would say nothing extra. railsui_chart(entry[:data] || entry["data"], type: type, height: height, yaxis: shared.merge(tickAmount: 3), **) ]) end end) end end |
#shared_scale(entries) ⇒ Object
Facets only compare if they share a scale. Left to themselves each one would fit its own data and a small series would look like a large one.
62 63 64 65 66 67 68 69 70 |
# File 'lib/railsui_charts/chart_helper.rb', line 62 def shared_scale(entries) values = entries.flat_map { |entry| Array(entry[:data] || entry["data"]).map { |point| ApexOptionsBuilder.value_of(point) } }.compact return {} if values.empty? min, max = values.minmax return {} if min == max { min: min, max: max } end |