Class: LightningUiKit::ChartComponent
- Inherits:
-
BaseComponent
- Object
- BaseComponent
- LightningUiKit::ChartComponent
- Defined in:
- app/components/lightning_ui_kit/chart_component.rb
Constant Summary collapse
- TYPES =
%i[bar line area].freeze
- VIEW_WIDTH =
640- PAD_RIGHT =
16- PAD_TOP =
12- AXIS_PAD_LEFT =
44
Instance Attribute Summary collapse
-
#height ⇒ Object
readonly
Returns the value of attribute height.
-
#series ⇒ Object
readonly
Returns the value of attribute series.
-
#type ⇒ Object
readonly
Returns the value of attribute type.
Instance Method Summary collapse
- #area? ⇒ Boolean
- #area_path(points) ⇒ Object
- #bar? ⇒ Boolean
-
#bar_path(bar) ⇒ Object
Path for a bar with rounded top corners and a square base.
- #bars ⇒ Object
- #chart_id ⇒ Object
- #classes ⇒ Object
- #count ⇒ Object
- #data_attrs ⇒ Object
- #empty? ⇒ Boolean
- #gradient_id(index) ⇒ Object
-
#hover_columns ⇒ Object
Invisible full-height bands (one per category) that drive the hover tooltip.
-
#initialize(data:, type: :bar, series: nil, x_key: :label, height: 260, show_grid: true, show_legend: true, show_axis: true, **options) ⇒ ChartComponent
constructor
A new instance of ChartComponent.
- #line_points(series) ⇒ Object
- #payload_for(index) ⇒ Object
- #plot_bottom ⇒ Object
- #plot_height ⇒ Object
- #plot_left ⇒ Object
- #plot_right ⇒ Object
- #plot_top ⇒ Object
- #plot_width ⇒ Object
- #point_x(index) ⇒ Object
- #polyline(points) ⇒ Object
- #show_axis? ⇒ Boolean
- #show_grid? ⇒ Boolean
- #show_legend? ⇒ Boolean
- #stimulus_data ⇒ Object
- #value_for(row, series) ⇒ Object
- #view_height ⇒ Object
-
#view_width ⇒ Object
--- geometry ---.
- #x_label(row) ⇒ Object
- #x_positions ⇒ Object
- #y_for(value) ⇒ Object
- #y_ticks(steps = 4) ⇒ Object
Constructor Details
#initialize(data:, type: :bar, series: nil, x_key: :label, height: 260, show_grid: true, show_legend: true, show_axis: true, **options) ⇒ ChartComponent
Returns a new instance of ChartComponent.
9 10 11 12 13 14 15 16 17 18 19 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 9 def initialize(data:, type: :bar, series: nil, x_key: :label, height: 260, show_grid: true, show_legend: true, show_axis: true, **) @data = Array(data).map { |row| row.respond_to?(:to_h) ? row.to_h.symbolize_keys : row } @type = TYPES.include?(type) ? type : :bar @x_key = x_key.to_sym @height = height.to_i @show_grid = show_grid @show_legend = show_legend @show_axis = show_axis @series = build_series(series) @options = end |
Instance Attribute Details
#height ⇒ Object (readonly)
Returns the value of attribute height.
21 22 23 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 21 def height @height end |
#series ⇒ Object (readonly)
Returns the value of attribute series.
21 22 23 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 21 def series @series end |
#type ⇒ Object (readonly)
Returns the value of attribute type.
21 22 23 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 21 def type @type end |
Instance Method Details
#area? ⇒ Boolean
27 28 29 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 27 def area? @type == :area end |
#area_path(points) ⇒ Object
155 156 157 158 159 160 161 162 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 155 def area_path(points) return "" if points.empty? segments = ["M #{points.first[0].round(2)} #{plot_bottom.round(2)}"] points.each { |x, y| segments << "L #{x.round(2)} #{y.round(2)}" } segments << "L #{points.last[0].round(2)} #{plot_bottom.round(2)} Z" segments.join(" ") end |
#bar? ⇒ Boolean
23 24 25 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 23 def @type == :bar end |
#bar_path(bar) ⇒ Object
Path for a bar with rounded top corners and a square base.
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 165 def () x = [:x] y = [:y] w = [:width] h = [:height] return "" if h <= 0 || w <= 0 r = [6.0, w / 2.0, h].min x2 = x + w bottom = y + h [ "M #{r2(x)} #{r2(bottom)}", "L #{r2(x)} #{r2(y + r)}", "Q #{r2(x)} #{r2(y)} #{r2(x + r)} #{r2(y)}", "L #{r2(x2 - r)} #{r2(y)}", "Q #{r2(x2)} #{r2(y)} #{r2(x2)} #{r2(y + r)}", "L #{r2(x2)} #{r2(bottom)}", "Z" ].join(" ") end |
#bars ⇒ Object
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 120 def group_width = inner = group_width * 0.2 band = group_width - inner = @series.empty? ? band : band / @series.size @data.each_with_index.flat_map do |row, i| group_x = plot_left + i * group_width + inner / 2.0 @series.each_with_index.map do |s, si| value = value_for(row, s) y = y_for(value) { x: group_x + si * , y: y, width: * 0.9, height: [plot_bottom - y, 0].max, color: s[:color], label: x_label(row), series_label: s[:label], value: format_number(value) } end end end |
#chart_id ⇒ Object
54 55 56 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 54 def chart_id @chart_id ||= "lui-chart-#{object_id}" end |
#classes ⇒ Object
47 48 49 50 51 52 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 47 def classes merge_classes([ "lui:relative lui:w-full lui:text-foreground", @options[:class] ].compact.join(" ")) end |
#count ⇒ Object
88 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 88 def count = @data.size |
#data_attrs ⇒ Object
66 67 68 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 66 def data_attrs @options[:data] || {} end |
#empty? ⇒ Boolean
31 32 33 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 31 def empty? @data.empty? || @series.empty? end |
#gradient_id(index) ⇒ Object
58 59 60 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 58 def gradient_id(index) "#{chart_id}-grad-#{index}" end |
#hover_columns ⇒ Object
Invisible full-height bands (one per category) that drive the hover tooltip.
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 187 def hover_columns step = (count > 1) ? plot_width.to_f / (count - 1) : plot_width.to_f @data.each_with_index.map do |row, i| if x = plot_left + i * w = else x = point_x(i) - step / 2.0 w = step end left = [x, plot_left].max right = [x + w, plot_right].min {x: left, width: [right - left, 0].max, label: x_label(row), payload: payload_for(i)} end end |
#line_points(series) ⇒ Object
145 146 147 148 149 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 145 def line_points(series) @data.each_with_index.map do |row, i| [point_x(i), y_for(value_for(row, series))] end end |
#payload_for(index) ⇒ Object
204 205 206 207 208 209 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 204 def payload_for(index) row = @data[index] @series.map do |s| {label: s[:label], value: format_number(value_for(row, s)), color: s[:color]} end.to_json end |
#plot_bottom ⇒ Object
82 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 82 def plot_bottom = @height - (@show_axis ? 28 : 8) |
#plot_height ⇒ Object
86 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 86 def plot_height = plot_bottom - plot_top |
#plot_left ⇒ Object
76 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 76 def plot_left = @show_axis ? AXIS_PAD_LEFT : 8 |
#plot_right ⇒ Object
78 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 78 def plot_right = VIEW_WIDTH - PAD_RIGHT |
#plot_top ⇒ Object
80 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 80 def plot_top = PAD_TOP |
#plot_width ⇒ Object
84 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 84 def plot_width = plot_right - plot_left |
#point_x(index) ⇒ Object
100 101 102 103 104 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 100 def point_x(index) return plot_left + plot_width / 2.0 if count <= 1 plot_left + (index.to_f / (count - 1)) * plot_width end |
#polyline(points) ⇒ Object
151 152 153 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 151 def polyline(points) points.map { |x, y| "#{x.round(2)},#{y.round(2)}" }.join(" ") end |
#show_axis? ⇒ Boolean
39 40 41 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 39 def show_axis? @show_axis end |
#show_grid? ⇒ Boolean
35 36 37 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 35 def show_grid? @show_grid end |
#show_legend? ⇒ Boolean
43 44 45 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 43 def show_legend? @show_legend && @series.any? end |
#stimulus_data ⇒ Object
62 63 64 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 62 def stimulus_data {controller: "lui-chart"}.merge(data_attrs) end |
#value_for(row, series) ⇒ Object
92 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 92 def value_for(row, series) = row[series[:key]].to_f |
#view_height ⇒ Object
74 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 74 def view_height = @height |
#view_width ⇒ Object
--- geometry ---
72 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 72 def view_width = VIEW_WIDTH |
#x_label(row) ⇒ Object
90 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 90 def x_label(row) = row[@x_key] |
#x_positions ⇒ Object
113 114 115 116 117 118 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 113 def x_positions @data.each_with_index.map do |row, i| x = ? plot_left + i * + / 2.0 : point_x(i) {x: x, label: x_label(row)} end end |
#y_for(value) ⇒ Object
94 95 96 97 98 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 94 def y_for(value) return plot_bottom if chart_max.zero? plot_bottom - (value.to_f / chart_max) * plot_height end |
#y_ticks(steps = 4) ⇒ Object
106 107 108 109 110 111 |
# File 'app/components/lightning_ui_kit/chart_component.rb', line 106 def y_ticks(steps = 4) (0..steps).map do |i| value = chart_max * i / steps {label: format_number(value), y: y_for(value)} end end |