keystone_ui 0.45.0 → 0.47.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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/keystone_ui/line_chart_controller.js +4 -2
- data/app/components/keystone/ui/bar_chart_component.html.erb +13 -0
- data/app/components/keystone/ui/bar_chart_component.rb +82 -0
- data/app/helpers/keystone_ui_helper.rb +4 -0
- data/lib/keystone_ui/safelist.rb +1 -0
- data/lib/keystone_ui/version.rb +1 -1
- data/the_local/agents/keystone_ui-develop.md +5 -0
- data/the_local/interface.yml +1 -0
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 20f1ebc15a9b1a15a854e634286e510b9b224167f3f56181ab756744afaa3f44
|
|
4
|
+
data.tar.gz: a53452a7e08710ca4659937d39bb6d7384f84daa768f6d8afda29c330677a4a3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 96a47743d927612dbc8cbed5b0ab0f12c8c34ae1df1555377613b1b33962b5a8ab15732e72983879724f03c18d79da3aec22d9973bc3b8a8396b9306b8f671dc
|
|
7
|
+
data.tar.gz: 7a0a0e1d2910d253f1f424e65082cd63c3bd40e4b3dbf83cdc67186bfbff72e9116c4c8d4b548bfddf5c59a5ee8b6ceb18051f0a8489e3592a12bb95f2460db5
|
|
@@ -59,6 +59,8 @@ const LIGHT_THEMES = ["light", "custom"]
|
|
|
59
59
|
|
|
60
60
|
export const isDarkMode = (theme, prefersDark) => theme === "dark" || (prefersDark && !LIGHT_THEMES.includes(theme))
|
|
61
61
|
|
|
62
|
+
export const drawnDark = (element, prefersDark) => isDarkMode(element.closest("[data-theme]")?.dataset.theme, prefersDark)
|
|
63
|
+
|
|
62
64
|
const CHART_COLOR_COUNT = 5
|
|
63
65
|
|
|
64
66
|
const INHERITED_FONTS = ["", "inherit"]
|
|
@@ -86,7 +88,7 @@ export const styleDatasets = (datasets, theme, resolve) => {
|
|
|
86
88
|
|
|
87
89
|
export const watchTheme = ({ document, matchMedia, MutationObserver }, onChange) => {
|
|
88
90
|
const observer = new MutationObserver(onChange)
|
|
89
|
-
observer.observe(document.documentElement, { attributes: true, attributeFilter: ["data-theme", "data-look"] })
|
|
91
|
+
observer.observe(document.documentElement, { attributes: true, attributeFilter: ["data-theme", "data-look", "style"] })
|
|
90
92
|
observer.observe(document.head, { childList: true, subtree: true, characterData: true })
|
|
91
93
|
const darkPreference = matchMedia("(prefers-color-scheme: dark)")
|
|
92
94
|
darkPreference.addEventListener("change", onChange)
|
|
@@ -136,7 +138,7 @@ export default class extends Controller {
|
|
|
136
138
|
return match ? read(match[1]) || color : color
|
|
137
139
|
}
|
|
138
140
|
|
|
139
|
-
const dark =
|
|
141
|
+
const dark = drawnDark(this.element, matchMedia("(prefers-color-scheme: dark)").matches)
|
|
140
142
|
return { theme: themeColors(read, dark, styles.fontFamily), resolve }
|
|
141
143
|
}
|
|
142
144
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<svg class="ks-bar-chart" viewBox="0 0 <%= Keystone::Ui::BarChartComponent::WIDTH %> <%= Keystone::Ui::BarChartComponent::HEIGHT %>" role="img">
|
|
2
|
+
<% ticks.each do |tick| %>
|
|
3
|
+
<line class="ks-bar-chart-grid" x1="<%= Keystone::Ui::BarChartComponent::LEFT %>" x2="<%= Keystone::Ui::BarChartComponent::WIDTH - Keystone::Ui::BarChartComponent::RIGHT %>" y1="<%= tick[:y].round(2) %>" y2="<%= tick[:y].round(2) %>"></line>
|
|
4
|
+
<text class="ks-bar-chart-text" data-axis-tick x="<%= axis_x %>" y="<%= (tick[:y] + 4).round(2) %>" text-anchor="end"><%= tick[:label] %></text>
|
|
5
|
+
<% end %>
|
|
6
|
+
<% drawn_bars.each do |bar| %>
|
|
7
|
+
<rect class="<%= bar[:classes] %>" x="<%= bar[:x].round(2) %>" y="<%= bar[:y].round(2) %>" width="<%= bar[:width].round(2) %>" height="<%= bar[:height].round(2) %>"></rect>
|
|
8
|
+
<% if show_values? %>
|
|
9
|
+
<text class="ks-bar-chart-value" x="<%= bar[:center].round(2) %>" y="<%= (bar[:y] - 4).round(2) %>" text-anchor="middle"><%= bar[:value] %></text>
|
|
10
|
+
<% end %>
|
|
11
|
+
<text class="ks-bar-chart-text" data-bar-label x="<%= bar[:center].round(2) %>" y="<%= label_baseline %>" text-anchor="middle"><%= bar[:label] %></text>
|
|
12
|
+
<% end %>
|
|
13
|
+
</svg>
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Keystone
|
|
4
|
+
module Ui
|
|
5
|
+
class BarChartComponent < ViewComponent::Base
|
|
6
|
+
WIDTH = 600
|
|
7
|
+
HEIGHT = 240
|
|
8
|
+
LEFT = 40
|
|
9
|
+
RIGHT = 8
|
|
10
|
+
TOP = 18
|
|
11
|
+
BOTTOM = 24
|
|
12
|
+
BAR_SHARE = 0.7
|
|
13
|
+
TICK_COUNT = 4
|
|
14
|
+
ROUND_STEPS = [ 1, 2, 2.5, 5, 10 ].freeze
|
|
15
|
+
|
|
16
|
+
attr_reader :bars
|
|
17
|
+
|
|
18
|
+
def initialize(bars:, show_values: false)
|
|
19
|
+
@bars = bars
|
|
20
|
+
@show_values = show_values
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def show_values?
|
|
24
|
+
@show_values
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def drawn_bars
|
|
28
|
+
bars.each_with_index.map do |bar, index|
|
|
29
|
+
height = bar[:value].to_f / axis_max * plot_height
|
|
30
|
+
{ x: LEFT + (index * band) + (band * (1 - BAR_SHARE) / 2), y: TOP + plot_height - height, width: band * BAR_SHARE, height: height,
|
|
31
|
+
center: LEFT + (index * band) + (band / 2), label: bar[:label], value: bar[:value],
|
|
32
|
+
classes: [ "ks-bar-chart-bar", ("ks-bar-chart-bar-shaded" if bar[:shaded]) ].compact.join(" ") }
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def ticks
|
|
37
|
+
(0..TICK_COUNT).map do |position|
|
|
38
|
+
value = (step * position).round(6)
|
|
39
|
+
{ y: TOP + plot_height - (value / axis_max * plot_height), label: (value % 1).zero? ? value.to_i.to_s : value.to_s }
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def axis_x
|
|
44
|
+
LEFT - 6
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def label_baseline
|
|
48
|
+
HEIGHT - 6
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
def axis_max
|
|
54
|
+
step * (largest / step).ceil
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def step
|
|
58
|
+
@step ||= begin
|
|
59
|
+
raw = largest / TICK_COUNT
|
|
60
|
+
magnitude = 10.0**Math.log10(raw).floor
|
|
61
|
+
ROUND_STEPS.map { |round| round * magnitude }.find { |candidate| candidate >= raw }
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def largest
|
|
66
|
+
bars.map { |bar| bar[:value].to_f }.select(&:positive?).max || 1.0
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def band
|
|
70
|
+
plot_width / [ bars.size, 1 ].max
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def plot_width
|
|
74
|
+
WIDTH - LEFT - RIGHT
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def plot_height
|
|
78
|
+
HEIGHT - TOP - BOTTOM
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -21,6 +21,10 @@ module KeystoneUiHelper
|
|
|
21
21
|
render Keystone::Ui::LineChartComponent.new(**args)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
def ui_bar_chart(**args)
|
|
25
|
+
render Keystone::Ui::BarChartComponent.new(**args)
|
|
26
|
+
end
|
|
27
|
+
|
|
24
28
|
def ui_cta_banner(**args, &block)
|
|
25
29
|
render Keystone::Ui::CtaBannerComponent.new(**args), &block
|
|
26
30
|
end
|
data/lib/keystone_ui/safelist.rb
CHANGED
data/lib/keystone_ui/version.rb
CHANGED
|
@@ -82,6 +82,7 @@ not available in the app yet, that is `keystone_ui-install`'s job.
|
|
|
82
82
|
- `ui_swipe_deck` — a stack of cards accepted or rejected by button or swipe.
|
|
83
83
|
- `ui_chart_card` — a titled card holding a chart.
|
|
84
84
|
- `ui_line_chart` — a line chart with one line per series, over labels or dates.
|
|
85
|
+
- `ui_bar_chart` — a bar chart drawn on the server, which needs no JavaScript and prints.
|
|
85
86
|
- `ui_funnel` — a conversion funnel drawn as bars or one joined shape.
|
|
86
87
|
- `ui_bucket` — an upright container filled toward a goal.
|
|
87
88
|
- `ui_bucket_series` — a wrapping row of buckets.
|
|
@@ -455,6 +456,10 @@ two exceptions: `ui_page`'s `padding:` treats any value other than `:none` as
|
|
|
455
456
|
|
|
456
457
|
- `ui_chart_card(title:, height: :md)` takes a block holding a chart, with
|
|
457
458
|
`height:` `:sm` `:md` `:lg`.
|
|
459
|
+
- `ui_bar_chart(bars:, show_values: false)` — `bars:` is
|
|
460
|
+
`[{ label:, value:, shaded: }, ...]`, where `shaded: true` draws a bar
|
|
461
|
+
faded. It is drawn on the server as an SVG, so use it, not
|
|
462
|
+
`ui_line_chart`, for a chart that must print or show without JavaScript.
|
|
458
463
|
- `ui_line_chart(series:, labels: nil, dates: nil, height: :md)` —
|
|
459
464
|
`series:` is `[{ name:, data:, color:, dashed: }, ...]`, where `color:`
|
|
460
465
|
is a CSS colour and `dashed: true` is optional. Pass exactly one of
|
data/the_local/interface.yml
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: keystone_ui
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.47.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tyler Schneider
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 0.
|
|
18
|
+
version: 0.22.0
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 0.
|
|
25
|
+
version: 0.22.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: view_component
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -82,6 +82,8 @@ files:
|
|
|
82
82
|
- app/components/keystone/ui/alert_component.rb
|
|
83
83
|
- app/components/keystone/ui/badge_component.html.erb
|
|
84
84
|
- app/components/keystone/ui/badge_component.rb
|
|
85
|
+
- app/components/keystone/ui/bar_chart_component.html.erb
|
|
86
|
+
- app/components/keystone/ui/bar_chart_component.rb
|
|
85
87
|
- app/components/keystone/ui/bottom_nav_component.html.erb
|
|
86
88
|
- app/components/keystone/ui/bottom_nav_component.rb
|
|
87
89
|
- app/components/keystone/ui/bottom_nav_item_component.html.erb
|