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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 35361b54c51210bbb266661591eca1601b6bb58e79f9c660fd57c10a22ded4ae
4
- data.tar.gz: ffef4296a6d940ec1e056c200fffec339699d01b44152b2fae77b64945a821fb
3
+ metadata.gz: 6957989b7a51f3fdd94ce32536025f31b9f3d1cc35fae4b92c1957da717ffd80
4
+ data.tar.gz: 9c3a4af4f7a27c7082ca8bf64578de1d96a415cf06019143bf1b9dbbc1f9b0ac
5
5
  SHA512:
6
- metadata.gz: 8b64c842d2200a213bba1d66f12fda4e13243ee507357d5344504b1d229d270842c4f270fda7ea9eaf5fea48e3e5ba38655ac928e5f8ee254d5f27274e26f349
7
- data.tar.gz: '01001180952d14a4d51abe980387aec7e32940012b2e8d917334f732bea4d83c97cec9cbe1badc2818fffde24977ec0be9577ec221a61ac27b6cad475f580394'
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
- Chart.register(...registerables)
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="relative inline-flex" data-controller="stat-card-info">
2
- <button type="button" class="<%= button_classes %>" data-action="click->stat-card-info#toggle" aria-label="More about this"><%= icon.html_safe %></button>
3
- <span class="<%= summary_classes %>"<%= ' data-stat-card-info-target="panel"'.html_safe unless content? %>><%= summary %></span>
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-stat-card-info-target="panel"><%= content %></span>
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 #{RadioCardComponent::DISCLOSURE_CLASSES} w-64"
9
- DETAIL_CLASSES = "ks-info-detail ks-radio-card-disclosure hidden absolute top-full right-0 z-20 w-72 text-sm"
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module KeystoneUi
4
- VERSION = "0.29.1"
4
+ VERSION = "0.29.3"
5
5
  end
@@ -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. Both panels render inside a `<span>`, so the block may hold
279
- text and inline elements only, such as a `ui_breakdown`, and never a `<div>`,
280
- list or table. Toggling needs the gem's Stimulus controllers registered.
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, tab switcher, progress, funnel, bucket, pipeline and
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) responds.
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,
@@ -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.1
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