keystone_ui 0.29.1 → 0.29.3
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/index.js +3 -1
- data/app/assets/javascripts/keystone_ui/info_controller.js +40 -0
- data/app/assets/javascripts/keystone_ui/line_chart_controller.js +9 -3
- data/app/components/keystone/ui/info_component.html.erb +4 -4
- data/app/components/keystone/ui/info_component.rb +2 -2
- data/config/importmap.rb +2 -1
- data/lib/keystone_ui/version.rb +1 -1
- data/the_local/agents/keystone_ui-develop.md +13 -4
- data/the_local/agents/keystone_ui-info.md +7 -1
- data/the_local/agents/keystone_ui-install.md +6 -5
- data/the_local/interface.yml +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6957989b7a51f3fdd94ce32536025f31b9f3d1cc35fae4b92c1957da717ffd80
|
|
4
|
+
data.tar.gz: 9c3a4af4f7a27c7082ca8bf64578de1d96a415cf06019143bf1b9dbbc1f9b0ac
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 60cb001c00c818f4990338a8ad9575ba48d97fd1874dbc86ac03370959b49223cf82c4bf3b92d4b65ddbd0d92e7a5fceba909cbd558222dc584e96473402e910
|
|
7
|
+
data.tar.gz: 9148787bdf6de7526e77cd73012d156468183d0f5b3a21e5a873d71c6d677b35fbc2ad8c8adc7735b9ed9f0523912f3b80907bd8cc96eb1fa5ba52fea581d6a7
|
|
@@ -11,6 +11,7 @@ import ClipboardController from "keystone_ui/clipboard_controller"
|
|
|
11
11
|
import TabSwitcherController from "keystone_ui/tab_switcher_controller"
|
|
12
12
|
import AccordionController from "keystone_ui/accordion_controller"
|
|
13
13
|
import StatCardInfoController from "keystone_ui/stat_card_info_controller"
|
|
14
|
+
import InfoController from "keystone_ui/info_controller"
|
|
14
15
|
import AutoSubmitController from "keystone_ui/auto_submit_controller"
|
|
15
16
|
import LineChartController from "keystone_ui/line_chart_controller"
|
|
16
17
|
import ThemeToggleController from "keystone_ui/theme_toggle_controller"
|
|
@@ -30,10 +31,11 @@ export function registerControllers(application) {
|
|
|
30
31
|
application.register("tab-switcher", TabSwitcherController)
|
|
31
32
|
application.register("accordion", AccordionController)
|
|
32
33
|
application.register("stat-card-info", StatCardInfoController)
|
|
34
|
+
application.register("info", InfoController)
|
|
33
35
|
application.register("auto-submit", AutoSubmitController)
|
|
34
36
|
application.register("line-chart", LineChartController)
|
|
35
37
|
application.register("theme-toggle", ThemeToggleController)
|
|
36
38
|
keepPageThemeInStep()
|
|
37
39
|
}
|
|
38
40
|
|
|
39
|
-
export { ColorPickerController, MultiSelectController, SwipeDeckController, ColumnPickerController, FileUploadController, DropdownController, DismissController, ModalController, ClipboardController, TabSwitcherController, AccordionController, StatCardInfoController, AutoSubmitController, LineChartController }
|
|
41
|
+
export { ColorPickerController, MultiSelectController, SwipeDeckController, ColumnPickerController, FileUploadController, DropdownController, DismissController, ModalController, ClipboardController, TabSwitcherController, AccordionController, StatCardInfoController, InfoController, AutoSubmitController, LineChartController }
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
|
2
|
+
|
|
3
|
+
export default class extends Controller {
|
|
4
|
+
static targets = ["button", "summary", "detail"]
|
|
5
|
+
|
|
6
|
+
peek() {
|
|
7
|
+
this.summaryTarget.classList.remove("hidden")
|
|
8
|
+
this.place(this.summaryTarget)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
unpeek() {
|
|
12
|
+
this.summaryTarget.classList.add("hidden")
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
toggle(event) {
|
|
16
|
+
event.stopPropagation()
|
|
17
|
+
const shown = this.hasDetailTarget ? this.detailTarget : this.summaryTarget
|
|
18
|
+
shown.classList.toggle("hidden")
|
|
19
|
+
if (!shown.classList.contains("hidden")) this.place(shown)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
hide(event) {
|
|
23
|
+
if (this.hasDetailTarget && !this.element.contains(event.target)) this.detailTarget.classList.add("hidden")
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
close() {
|
|
27
|
+
this.summaryTarget.classList.add("hidden")
|
|
28
|
+
if (this.hasDetailTarget) this.detailTarget.classList.add("hidden")
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
place(shown) {
|
|
32
|
+
const button = this.buttonTarget.getBoundingClientRect()
|
|
33
|
+
Object.assign(shown.style, {
|
|
34
|
+
position: "fixed",
|
|
35
|
+
top: `${button.bottom}px`,
|
|
36
|
+
left: `${Math.max(8, button.right - shown.offsetWidth)}px`,
|
|
37
|
+
right: "auto"
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { Controller } from "@hotwired/stimulus"
|
|
2
|
-
import { Chart, registerables } from "chart.js"
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
const loadChart = async () => {
|
|
4
|
+
const { Chart, registerables } = await import("chart.js")
|
|
5
|
+
Chart.register(...registerables)
|
|
6
|
+
return Chart
|
|
7
|
+
}
|
|
5
8
|
|
|
6
9
|
export default class extends Controller {
|
|
7
10
|
static targets = ["canvas"]
|
|
8
11
|
static values = { data: Object }
|
|
9
12
|
|
|
10
|
-
connect() {
|
|
13
|
+
async connect() {
|
|
14
|
+
const Chart = await loadChart()
|
|
15
|
+
if (!this.element.isConnected) return
|
|
16
|
+
|
|
11
17
|
this.chart = new Chart(this.canvasTarget, {
|
|
12
18
|
type: "line",
|
|
13
19
|
data: this.resolveColors(this.dataValue),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
<span class="
|
|
2
|
-
<button type="button" class="<%= button_classes %>" data-action="click->
|
|
3
|
-
<span class="<%= summary_classes %>"
|
|
1
|
+
<span class="inline-flex" data-controller="info" data-action="click@window->info#hide scroll@window->info#close">
|
|
2
|
+
<button type="button" class="<%= button_classes %>" data-info-target="button" data-action="mouseenter->info#peek mouseleave->info#unpeek click->info#toggle" aria-label="More about this"><%= icon.html_safe %></button>
|
|
3
|
+
<span class="<%= summary_classes %>" data-info-target="summary"><%= summary %></span>
|
|
4
4
|
<% if content? %>
|
|
5
|
-
<span class="<%= detail_classes %>" data-
|
|
5
|
+
<span class="<%= detail_classes %>" data-info-target="detail"><%= content %></span>
|
|
6
6
|
<% end %>
|
|
7
7
|
</span>
|
|
@@ -5,8 +5,8 @@ module Keystone
|
|
|
5
5
|
class InfoComponent < ViewComponent::Base
|
|
6
6
|
BUTTON_CLASSES = RadioCardComponent::INFO_BUTTON_CLASSES
|
|
7
7
|
ICON = RadioCardComponent::INFO_ICON
|
|
8
|
-
SUMMARY_CLASSES = "ks-info-summary
|
|
9
|
-
DETAIL_CLASSES = "ks-info-detail ks-radio-card-disclosure hidden
|
|
8
|
+
SUMMARY_CLASSES = "ks-info-summary ks-radio-card-disclosure hidden z-30 w-64 text-sm"
|
|
9
|
+
DETAIL_CLASSES = "ks-info-detail ks-radio-card-disclosure hidden z-30 w-72 text-sm"
|
|
10
10
|
|
|
11
11
|
def initialize(summary:)
|
|
12
12
|
@summary = summary
|
data/config/importmap.rb
CHANGED
|
@@ -12,6 +12,7 @@ pin "keystone_ui/clipboard_controller", to: "keystone_ui/clipboard_controller.js
|
|
|
12
12
|
pin "keystone_ui/tab_switcher_controller", to: "keystone_ui/tab_switcher_controller.js"
|
|
13
13
|
pin "keystone_ui/accordion_controller", to: "keystone_ui/accordion_controller.js"
|
|
14
14
|
pin "keystone_ui/stat_card_info_controller", to: "keystone_ui/stat_card_info_controller.js"
|
|
15
|
+
pin "keystone_ui/info_controller", to: "keystone_ui/info_controller.js"
|
|
15
16
|
pin "keystone_ui/auto_submit_controller", to: "keystone_ui/auto_submit_controller.js"
|
|
16
17
|
pin "keystone_ui/line_chart_controller", to: "keystone_ui/line_chart_controller.js"
|
|
17
18
|
pin "keystone_ui/theme_toggle_controller", to: "keystone_ui/theme_toggle_controller.js"
|
|
@@ -19,4 +20,4 @@ pin "keystone_ui/page_theme", to: "keystone_ui/page_theme.js"
|
|
|
19
20
|
|
|
20
21
|
# Chart.js for the line-chart controller, so host apps don't pin it themselves.
|
|
21
22
|
# Vendored as a single self-contained bundle (deps inlined, no external imports).
|
|
22
|
-
pin "chart.js", to: "keystone_ui/chartjs.js"
|
|
23
|
+
pin "chart.js", to: "keystone_ui/chartjs.js", preload: false
|
data/lib/keystone_ui/version.rb
CHANGED
|
@@ -275,9 +275,16 @@ outer element. See Conventions before using it.
|
|
|
275
275
|
is optional and holds the full detail. With a block, tapping or clicking the
|
|
276
276
|
button toggles a second floating panel holding the block's content, and the
|
|
277
277
|
summary stays hover-only. With no block, tapping the button toggles the
|
|
278
|
-
summary itself.
|
|
279
|
-
|
|
280
|
-
|
|
278
|
+
summary itself. A second tap closes what the first opened, a click anywhere
|
|
279
|
+
else on the page closes the detail panel, and scrolling the page closes both
|
|
280
|
+
panels. Each panel opens just under the button with its right edge on the
|
|
281
|
+
button's right edge, and stays at least 8 pixels from the left edge of the
|
|
282
|
+
screen. The panels are placed against the screen, so the button can sit
|
|
283
|
+
inside a table or any other container that clips its contents without the
|
|
284
|
+
panels being cut off. Both panels render inside a `<span>`, so the block may
|
|
285
|
+
hold text and inline elements only, such as a `ui_breakdown`, and never a
|
|
286
|
+
`<div>`, list or table. Hovering and tapping both need the gem's Stimulus
|
|
287
|
+
controllers registered, and without them the button shows nothing.
|
|
281
288
|
- `ui_breakdown(lines:, total:)` — no block. A list of amounts ending in their
|
|
282
289
|
total. `lines:` is `[{ amount:, label: }, ...]` and `total:` is one
|
|
283
290
|
`{ amount:, label: }`, both required. Each line renders its amount
|
|
@@ -418,7 +425,9 @@ outer element. See Conventions before using it.
|
|
|
418
425
|
it, with the one-line explanation as `summary:` and, when the figure is a
|
|
419
426
|
sum of parts, a `ui_breakdown` in its block. Which amounts the breakdown
|
|
420
427
|
lists, and the wording of the summary, are the app's own, so ask the
|
|
421
|
-
developer rather than pick.
|
|
428
|
+
developer rather than pick. If an info button shows nothing when hovered or
|
|
429
|
+
tapped, the gem's Stimulus controllers are not registered, so stop and hand
|
|
430
|
+
that part to `keystone_ui-install`.
|
|
422
431
|
A field whose value must be one of a fixed list is a `:select` with
|
|
423
432
|
`options:`, and a field that accepts any text and offers common values is a
|
|
424
433
|
text field with `suggestions:`. Which one a field is, and which values it
|
|
@@ -93,7 +93,13 @@ holds the catalog.
|
|
|
93
93
|
beside anything. It takes a short summary, which is required, and shows it
|
|
94
94
|
when the button is hovered. Given nothing more, a tap shows the summary too.
|
|
95
95
|
Given a block of further detail, a tap opens that detail instead, in a panel
|
|
96
|
-
under the button, and the summary stays the hover text.
|
|
96
|
+
under the button, and the summary stays the hover text. Both popups are
|
|
97
|
+
placed against the screen, not against the element the button sits in, so a
|
|
98
|
+
table or any other container that clips its contents does not cut them off.
|
|
99
|
+
Each opens under the button with its right edge on the button's, and is kept
|
|
100
|
+
on the screen when the button is near the left edge. A second tap closes
|
|
101
|
+
what the first opened, a click anywhere else closes the detail, and
|
|
102
|
+
scrolling the page closes both.
|
|
97
103
|
- **A breakdown is text.** A breakdown lists amounts, each beside a label
|
|
98
104
|
saying what it is, and ends with a total set apart from the lines above it.
|
|
99
105
|
Every line and the total are an amount and a label, passed as
|
|
@@ -81,8 +81,8 @@ built on ViewComponent; hook it in before building any screen with those helpers
|
|
|
81
81
|
|
|
82
82
|
- `app/javascript/controllers/index.js not found` — ask the developer where
|
|
83
83
|
the Stimulus application is set up and add those two lines there. Without
|
|
84
|
-
them, dropdowns, modals, file uploads, the column picker, the theme toggle
|
|
85
|
-
and the other interactive components do nothing.
|
|
84
|
+
them, dropdowns, modals, file uploads, the column picker, the theme toggle,
|
|
85
|
+
the info button's popups and the other interactive components do nothing.
|
|
86
86
|
`registerControllers(application)` also copies `data-theme` and `data-look`
|
|
87
87
|
from each page Turbo renders onto the `<html>` tag. Without it, a Turbo
|
|
88
88
|
visit keeps the theme and look of the first page loaded.
|
|
@@ -153,8 +153,8 @@ built on ViewComponent; hook it in before building any screen with those helpers
|
|
|
153
153
|
checkbox row, radio card, option card, file upload and colour picker read
|
|
154
154
|
these variables. So do the data display components: stat card, chart card,
|
|
155
155
|
card link, CTA banner, feature grid, hero, data table, code, accordion,
|
|
156
|
-
disclosure, calculation,
|
|
157
|
-
swipe deck.
|
|
156
|
+
disclosure, calculation, info button, breakdown, tab switcher, progress,
|
|
157
|
+
funnel, bucket, pipeline and swipe deck.
|
|
158
158
|
So do the navigation components: navbar, nav item, nav dropdown, bottom nav,
|
|
159
159
|
mobile header and settings link. The desktop "Back" link and the breadcrumbs
|
|
160
160
|
on form and show pages use the mobile header's back link variables. The
|
|
@@ -244,7 +244,8 @@ built on ViewComponent; hook it in before building any screen with those helpers
|
|
|
244
244
|
exists after a boot, the Stimulus setup calls `registerControllers(application)`,
|
|
245
245
|
and the layout's `<html>` tag contains `<%= keystone_theme_attributes %>`. Then
|
|
246
246
|
load one page that renders a `ui_*` helper and confirm it is styled and that an
|
|
247
|
-
interactive component (a dropdown, a dismissible alert)
|
|
247
|
+
interactive component (a dropdown, a dismissible alert, an info button)
|
|
248
|
+
responds.
|
|
248
249
|
- **Importmap is the supported JS path.** For apps configured with importmap the
|
|
249
250
|
gem pins its own controllers, and the charting library they need, on boot, so
|
|
250
251
|
the host pins nothing. If the app bundles JavaScript instead (esbuild, bun,
|
data/the_local/interface.yml
CHANGED
|
@@ -97,6 +97,7 @@ sources:
|
|
|
97
97
|
- app/components/keystone/ui/calculation_component.rb
|
|
98
98
|
- app/components/keystone/ui/info_component.rb
|
|
99
99
|
- app/components/keystone/ui/info_component.html.erb
|
|
100
|
+
- app/assets/javascripts/keystone_ui/info_controller.js
|
|
100
101
|
- app/components/keystone/ui/breakdown_component.rb
|
|
101
102
|
- app/components/keystone/ui/breakdown_component.html.erb
|
|
102
103
|
- app/components/keystone/ui/feature_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.29.
|
|
4
|
+
version: 0.29.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tyler Schneider
|
|
@@ -62,6 +62,7 @@ files:
|
|
|
62
62
|
- app/assets/javascripts/keystone_ui/dropdown_controller.js
|
|
63
63
|
- app/assets/javascripts/keystone_ui/file_upload_controller.js
|
|
64
64
|
- app/assets/javascripts/keystone_ui/index.js
|
|
65
|
+
- app/assets/javascripts/keystone_ui/info_controller.js
|
|
65
66
|
- app/assets/javascripts/keystone_ui/line_chart_controller.js
|
|
66
67
|
- app/assets/javascripts/keystone_ui/modal_controller.js
|
|
67
68
|
- app/assets/javascripts/keystone_ui/multi_select_controller.js
|