keystone_ui 0.30.0 → 0.31.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/components/keystone/ui/funnel_component.html.erb +33 -12
- data/app/components/keystone/ui/funnel_component.rb +27 -4
- data/lib/keystone_ui/version.rb +1 -1
- data/the_local/agents/keystone_ui-develop.md +20 -7
- data/the_local/agents/keystone_ui-info.md +7 -0
- data/the_local/interface.yml +1 -0
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a6c7e18e911657e41ed1a4eff2133400015bd7a58e0c437f6886d219173f01fa
|
|
4
|
+
data.tar.gz: 91b2f652bb7313d9cda361e126e969d06b64827e80118888a73cce3840471f68
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 466ea8fbb32ed4683db9537a52d7ba41d667f79dfa52aec27aaab85f5fc14b872fcc03b7d880136936133685fdc1af5f839aa4392c5ba698af62694e4a5832b0
|
|
7
|
+
data.tar.gz: 435630df203142fa669f0d93333e6b2637b2d4ec2d25b6e8fa1a7aa00e54ba5fdace3a3416905c144f706f18373ad78b8b11c067f5d1a62ee6453655358b4b77
|
|
@@ -1,14 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
<%
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
<% if joined? %>
|
|
2
|
+
<div class="<%= JOINED_CLASSES %>">
|
|
3
|
+
<% layers.each do |layer| %>
|
|
4
|
+
<% if layer.conversion_percent %>
|
|
5
|
+
<div></div>
|
|
6
|
+
<div class="<%= BAND_ROW_CLASSES %>">
|
|
7
|
+
<div class="<%= BAND_CLASSES %>" style="clip-path: <%= band_clip_path(layer) %>"></div>
|
|
8
|
+
<div class="<%= BAND_LABEL_ROW_CLASSES %>"><span class="<%= BAND_LABEL_CLASSES %>"><%= layer.conversion_percent %>%</span></div>
|
|
9
|
+
</div>
|
|
10
|
+
<% end %>
|
|
11
|
+
<div class="<%= WORDS_CLASSES %>">
|
|
9
12
|
<span class="<%= value_classes %>"><%= layer.value %></span>
|
|
13
|
+
<span class="<%= label_classes %>"><%= layer.label %></span>
|
|
14
|
+
</div>
|
|
15
|
+
<div class="<%= BLOCK_CLASSES %>">
|
|
16
|
+
<div class="<%= BLOCK_FILL_CLASSES %> <%= layer.color_classes %>" style="width: <%= layer.width_percent %>%"></div>
|
|
10
17
|
</div>
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
18
|
+
<% end %>
|
|
19
|
+
</div>
|
|
20
|
+
<% else %>
|
|
21
|
+
<div class="<%= container_classes %>">
|
|
22
|
+
<% layers.each do |layer| %>
|
|
23
|
+
<% if layer.conversion_percent %>
|
|
24
|
+
<div class="<%= transition_classes %>">↓ <%= layer.conversion_percent %>%</div>
|
|
25
|
+
<% end %>
|
|
26
|
+
<div class="<%= layer_classes %>">
|
|
27
|
+
<div class="<%= row_classes %>">
|
|
28
|
+
<span class="<%= label_classes %>"><%= layer.label %></span>
|
|
29
|
+
<span class="<%= value_classes %>"><%= layer.value %></span>
|
|
30
|
+
</div>
|
|
31
|
+
<div class="<%= bar_classes %> <%= layer.color_classes %>" style="width: <%= layer.width_percent %>%"></div>
|
|
32
|
+
</div>
|
|
33
|
+
<% end %>
|
|
34
|
+
</div>
|
|
35
|
+
<% end %>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module Keystone
|
|
4
4
|
module Ui
|
|
5
5
|
class FunnelComponent < ViewComponent::Base
|
|
6
|
-
Layer = Struct.new(:label, :value, :width_percent, :conversion_percent, :color_classes, keyword_init: true)
|
|
6
|
+
Layer = Struct.new(:label, :value, :width_percent, :conversion_percent, :color_classes, :previous_width_percent, keyword_init: true)
|
|
7
7
|
|
|
8
8
|
CONTAINER_CLASSES = "ks-funnel"
|
|
9
9
|
LAYER_CLASSES = "ks-funnel-layer"
|
|
@@ -12,6 +12,14 @@ module Keystone
|
|
|
12
12
|
VALUE_CLASSES = "ks-funnel-value text-sm tabular-nums"
|
|
13
13
|
BAR_CLASSES = "ks-funnel-bar h-8 transition-all"
|
|
14
14
|
TRANSITION_CLASSES = "ks-funnel-transition text-center text-xs"
|
|
15
|
+
BAND_LABEL_ROW_CLASSES = "absolute inset-0 flex items-center justify-center"
|
|
16
|
+
BAND_ROW_CLASSES = "relative h-7"
|
|
17
|
+
BLOCK_FILL_CLASSES = "h-full"
|
|
18
|
+
BLOCK_CLASSES = "flex justify-center h-12"
|
|
19
|
+
WORDS_CLASSES = "flex flex-col justify-center"
|
|
20
|
+
BAND_LABEL_CLASSES = "ks-funnel-band-label text-xs"
|
|
21
|
+
BAND_CLASSES = "ks-funnel-band absolute inset-0"
|
|
22
|
+
JOINED_CLASSES = "ks-funnel-joined grid grid-cols-[max-content_1fr]"
|
|
15
23
|
STEP_COLOR_CLASSES = {
|
|
16
24
|
accent: "ks-funnel-bar-accent",
|
|
17
25
|
sky: "ks-funnel-bar-sky",
|
|
@@ -20,10 +28,24 @@ module Keystone
|
|
|
20
28
|
rose: "ks-funnel-bar-rose"
|
|
21
29
|
}.freeze
|
|
22
30
|
|
|
23
|
-
attr_reader :steps
|
|
31
|
+
attr_reader :steps, :shape
|
|
32
|
+
|
|
33
|
+
def initialize(steps:, shape: :bars)
|
|
34
|
+
raise ArgumentError, "a funnel's shape is :bars or :joined, got #{shape.inspect}" unless %i[bars joined].include?(shape)
|
|
24
35
|
|
|
25
|
-
def initialize(steps:)
|
|
26
36
|
@steps = steps
|
|
37
|
+
@shape = shape
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def joined?
|
|
41
|
+
shape == :joined
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def band_clip_path(layer)
|
|
45
|
+
top = (100 - layer.previous_width_percent) / 2.0
|
|
46
|
+
bottom = (100 - layer.width_percent) / 2.0
|
|
47
|
+
|
|
48
|
+
"polygon(#{format("%g%%", top)} 0, #{format("%g%%", 100 - top)} 0, #{format("%g%%", 100 - bottom)} 100%, #{format("%g%%", bottom)} 100%)"
|
|
27
49
|
end
|
|
28
50
|
|
|
29
51
|
def layers
|
|
@@ -35,7 +57,8 @@ module Keystone
|
|
|
35
57
|
value: step[:value],
|
|
36
58
|
width_percent: width_percent(step[:value]),
|
|
37
59
|
conversion_percent: conversion_percent(step[:value], previous),
|
|
38
|
-
color_classes: color_classes(step[:color], index)
|
|
60
|
+
color_classes: color_classes(step[:color], index),
|
|
61
|
+
previous_width_percent: previous && width_percent(previous)
|
|
39
62
|
)
|
|
40
63
|
previous = step[:value]
|
|
41
64
|
layer
|
data/lib/keystone_ui/version.rb
CHANGED
|
@@ -337,13 +337,20 @@ outer element. See Conventions before using it.
|
|
|
337
337
|
the last, marks only whole days, and reads each day as a date such as
|
|
338
338
|
"Oct 2, 2026", which is also the heading a hovered point shows. The time of
|
|
339
339
|
day is dropped, so pass one value per day.
|
|
340
|
-
- `ui_funnel(steps:)` — a conversion funnel. `steps:` is
|
|
341
|
-
`[{ label:, value:, color: }, ...]` in order, with `color:` optional.
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
340
|
+
- `ui_funnel(steps:, shape: :bars)` — a conversion funnel. `steps:` is
|
|
341
|
+
`[{ label:, value:, color: }, ...]` in order, with `color:` optional. Each
|
|
342
|
+
step's width is its value as a share of the first step's value, and the
|
|
343
|
+
percent shown between two steps is the second step's value divided by the
|
|
344
|
+
first's. Each step takes the next colour in the order `:accent` `:sky`
|
|
345
|
+
`:violet` `:amber` `:rose`, starting again after `:rose`; a step passing one
|
|
346
|
+
of those symbols as `color:` uses it instead, and any other symbol raises.
|
|
347
|
+
Values are printed as given. Divide-by-zero safe, no JavaScript. `shape:`
|
|
348
|
+
`:bars` draws one bar per step, left-aligned, with the label and value on a
|
|
349
|
+
row above it and a `↓ N%` caption between two bars. `shape: :joined` draws
|
|
350
|
+
one shape: each step's value over its label in a column on the left, each
|
|
351
|
+
step's block centred at its width, and between two blocks a neutral band
|
|
352
|
+
that narrows from the block above to the block below, with the percent on it.
|
|
353
|
+
Any other `shape:` raises `ArgumentError`.
|
|
347
354
|
- `ui_bucket(goal:, actual:, label: nil, over: :success)` — an upright container
|
|
348
355
|
for one target, filled from the bottom toward `goal:`. It shows the optional
|
|
349
356
|
`label` on top, then `goal`, the container, `actual`, and the percent reached.
|
|
@@ -459,6 +466,12 @@ outer element. See Conventions before using it.
|
|
|
459
466
|
its neighbours rather than a point at zero. Whether a missing day is left
|
|
460
467
|
out or passed as a zero is the app's own rule, so ask the developer rather
|
|
461
468
|
than pick. Never format dates into strings and pass them as `labels:`.
|
|
469
|
+
For a funnel, whether it is drawn as separate bars or as one joined shape
|
|
470
|
+
is the developer's choice, so ask before passing `shape:`. If a joined
|
|
471
|
+
funnel shows its blocks but no band between them, the app's
|
|
472
|
+
keystone_ui-styles version does not define the `ks-funnel-band` classes, so
|
|
473
|
+
stop and hand that part to `keystone_ui-install`, and add no classes to fix
|
|
474
|
+
it.
|
|
462
475
|
Put the actions on a record, such as Edit and Delete, in an action menu
|
|
463
476
|
rather than in a row of buttons: `menu:` on the `ui_section` that shows the
|
|
464
477
|
record, `table.actions` for a table row, or `ui_action_menu` anywhere else.
|
|
@@ -129,6 +129,13 @@ holds the catalog.
|
|
|
129
129
|
- **Figures are numbers.** Components that measure or compare values, such as
|
|
130
130
|
progress bars, funnels and buckets, do arithmetic on them. Pass a number, not
|
|
131
131
|
a formatted string such as `"9,000"`. A bucket raises on one.
|
|
132
|
+
- **A funnel has two shapes.** Both size each step against the first step and
|
|
133
|
+
show the percent carried from one step to the next. The default draws one bar
|
|
134
|
+
per step, each with its label and value on a row above it. The joined shape
|
|
135
|
+
draws the steps as one figure: each step's value and label sit in a column on
|
|
136
|
+
the left, each step is a block centred at its width, and a neutral band
|
|
137
|
+
between two blocks narrows from one width to the next and holds the percent.
|
|
138
|
+
Any other shape raises `ArgumentError`. Neither shape needs JavaScript.
|
|
132
139
|
- **A line chart is labelled or dated.** A line chart draws one line per
|
|
133
140
|
series, and each series is a name and its values, with an optional colour
|
|
134
141
|
and an optional dashed line. Its horizontal axis is given one of two ways,
|
data/the_local/interface.yml
CHANGED
|
@@ -112,6 +112,7 @@ sources:
|
|
|
112
112
|
- app/components/keystone/ui/breadcrumbs_component.rb
|
|
113
113
|
- app/components/keystone/ui/breadcrumbs_component.html.erb
|
|
114
114
|
- app/components/keystone/ui/funnel_component.rb
|
|
115
|
+
- app/components/keystone/ui/funnel_component.html.erb
|
|
115
116
|
- app/components/keystone/ui/bucket_component.rb
|
|
116
117
|
- app/components/keystone/ui/bucket_series_component.rb
|
|
117
118
|
- app/components/keystone/ui/grid_component.rb
|
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.31.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.10.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.10.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: view_component
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|