keystone_ui 0.52.0 → 0.53.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/index.js +2 -0
- data/app/assets/javascripts/keystone_ui/search_select_controller.js +69 -0
- data/app/components/keystone/ui/search_select_component.html.erb +9 -0
- data/app/components/keystone/ui/search_select_component.rb +22 -0
- data/app/helpers/keystone_ui_helper.rb +4 -0
- data/config/importmap.rb +1 -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 +29 -2
- data/the_local/agents/keystone_ui-info.md +12 -4
- data/the_local/agents/keystone_ui-install.md +4 -3
- data/the_local/interface.yml +4 -0
- metadata +6 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e7f6b6d63755b597d7b876ddba35bd4f6bbdb6039b0b16be57197cf4af01ea48
|
|
4
|
+
data.tar.gz: c2093a32f35bf5beb3a469cfffe14033e491f8e6435bb32003b203652574f990
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ac7541139dd31e4269cbca2dc13e3201d6c44ffd9b4a8088f90a2361f15cee3e627d808277b31e7a5981c0c19d56fa453cb186350870cf48d5416d7ef0ab6a2b
|
|
7
|
+
data.tar.gz: bf3cb63e70d990d5b01bee266a2446d15cd8f7b710b63c767e129134312d9f6e999d6e56ef6d709614ff4a63699b303e231cbebed874001ce4c03f7c46756401
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import ColorPickerController from "keystone_ui/color_picker_controller"
|
|
2
2
|
import MultiSelectController from "keystone_ui/multi_select_controller"
|
|
3
|
+
import SearchSelectController from "keystone_ui/search_select_controller"
|
|
3
4
|
import SwipeDeckController from "keystone_ui/swipe_deck_controller"
|
|
4
5
|
import ColumnPickerController from "keystone_ui/column_picker_controller"
|
|
5
6
|
import FileUploadController from "keystone_ui/file_upload_controller"
|
|
@@ -20,6 +21,7 @@ import { keepPageThemeInStep } from "keystone_ui/page_theme"
|
|
|
20
21
|
export function registerControllers(application) {
|
|
21
22
|
application.register("color-picker", ColorPickerController)
|
|
22
23
|
application.register("multi-select", MultiSelectController)
|
|
24
|
+
application.register("search-select", SearchSelectController)
|
|
23
25
|
application.register("swipe-deck", SwipeDeckController)
|
|
24
26
|
application.register("column-picker", ColumnPickerController)
|
|
25
27
|
application.register("file-upload", FileUploadController)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
|
2
|
+
|
|
3
|
+
const escaped = (text) => String(text).replace(/[&<>"']/g, (character) => `&#${character.charCodeAt(0)};`)
|
|
4
|
+
|
|
5
|
+
export default class extends Controller {
|
|
6
|
+
static targets = ["id", "input", "list", "newFields"]
|
|
7
|
+
static values = { url: String, newLabel: String }
|
|
8
|
+
|
|
9
|
+
async search() {
|
|
10
|
+
const response = await fetch(`${this.urlValue}?q=${encodeURIComponent(this.inputTarget.value)}`, { headers: { Accept: "application/json" } })
|
|
11
|
+
this.matches = await response.json()
|
|
12
|
+
this.highlighted = -1
|
|
13
|
+
this.draw()
|
|
14
|
+
this.listTarget.classList.remove("hidden")
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
key(event) {
|
|
18
|
+
if (event.key === "Enter") return this.pickHighlighted(event)
|
|
19
|
+
if (event.key === "Escape") return this.listTarget.classList.add("hidden")
|
|
20
|
+
|
|
21
|
+
const moves = { ArrowDown: 1, ArrowUp: -1 }
|
|
22
|
+
if (!(event.key in moves) || !this.matches) return
|
|
23
|
+
|
|
24
|
+
event.preventDefault()
|
|
25
|
+
this.highlighted = Math.min(Math.max(this.highlighted + moves[event.key], 0), this.choiceCount() - 1)
|
|
26
|
+
this.draw()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
pickHighlighted(event) {
|
|
30
|
+
if (this.highlighted === undefined || this.highlighted < 0) return
|
|
31
|
+
|
|
32
|
+
const match = this.matches[this.highlighted]
|
|
33
|
+
if (match) this.choose({ params: match, preventDefault: () => event.preventDefault() })
|
|
34
|
+
else this.chooseNew(event)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
draw() {
|
|
38
|
+
this.listTarget.innerHTML = this.matches.map((match, index) => this.option(match, index === this.highlighted)).join("") + this.newOption(this.highlighted === this.matches.length)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
choiceCount() {
|
|
42
|
+
return this.matches.length + (this.newLabelValue ? 1 : 0)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
choose(event) {
|
|
46
|
+
event.preventDefault()
|
|
47
|
+
this.idTarget.value = String(event.params.id)
|
|
48
|
+
this.inputTarget.value = event.params.label
|
|
49
|
+
if (this.hasNewFieldsTarget) this.newFieldsTarget.classList.add("hidden")
|
|
50
|
+
this.listTarget.classList.add("hidden")
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
chooseNew(event) {
|
|
54
|
+
event.preventDefault()
|
|
55
|
+
this.idTarget.value = ""
|
|
56
|
+
if (this.hasNewFieldsTarget) this.newFieldsTarget.classList.remove("hidden")
|
|
57
|
+
this.listTarget.classList.add("hidden")
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
newOption(highlighted = false) {
|
|
61
|
+
if (!this.newLabelValue) return ""
|
|
62
|
+
|
|
63
|
+
return `<li role="option" class="ks-menu-option" data-action="mousedown->search-select#chooseNew" aria-selected="${highlighted}">${escaped(this.newLabelValue)}</li>`
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
option(match, highlighted = false) {
|
|
67
|
+
return `<li role="option" class="ks-menu-option" data-action="mousedown->search-select#choose" data-search-select-id-param="${escaped(match.id)}" data-search-select-label-param="${escaped(match.label)}" aria-selected="${highlighted}">${escaped(match.label)}</li>`
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<div class="<%= WRAPPER_CLASSES %>" data-controller="search-select" data-search-select-url-value="<%= url %>" data-search-select-new-label-value="<%= new_label %>">
|
|
2
|
+
<label class="<%= LABEL_CLASSES %>"><%= label %></label>
|
|
3
|
+
<input type="hidden" name="<%= name %>" value="<%= selected_id %>" data-search-select-target="id">
|
|
4
|
+
<input type="text" autocomplete="off" value="<%= selected_label %>" class="<%= Keystone::Ui::InputComponent::BASE_CLASSES %>" data-search-select-target="input" data-action="input->search-select#search keydown->search-select#key">
|
|
5
|
+
<ul role="listbox" class="<%= LIST_CLASSES %>" data-search-select-target="list"></ul>
|
|
6
|
+
<% if content? %>
|
|
7
|
+
<div class="hidden" data-search-select-target="newFields"><%= content %></div>
|
|
8
|
+
<% end %>
|
|
9
|
+
</div>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Keystone
|
|
4
|
+
module Ui
|
|
5
|
+
class SearchSelectComponent < ViewComponent::Base
|
|
6
|
+
WRAPPER_CLASSES = "ks-form-field relative"
|
|
7
|
+
LABEL_CLASSES = "ks-label"
|
|
8
|
+
LIST_CLASSES = "ks-menu absolute z-10 w-full hidden"
|
|
9
|
+
|
|
10
|
+
attr_reader :name, :label, :url, :selected_id, :selected_label, :new_label
|
|
11
|
+
|
|
12
|
+
def initialize(name:, label:, url:, selected_id: nil, selected_label: nil, new_label: nil)
|
|
13
|
+
@name = name
|
|
14
|
+
@label = label
|
|
15
|
+
@url = url
|
|
16
|
+
@selected_id = selected_id
|
|
17
|
+
@selected_label = selected_label
|
|
18
|
+
@new_label = new_label
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -193,6 +193,10 @@ module KeystoneUiHelper
|
|
|
193
193
|
render Keystone::Ui::MultiSelectComponent.new(**args)
|
|
194
194
|
end
|
|
195
195
|
|
|
196
|
+
def ui_search_select(**args, &block)
|
|
197
|
+
render Keystone::Ui::SearchSelectComponent.new(**args), &block
|
|
198
|
+
end
|
|
199
|
+
|
|
196
200
|
def ui_swipe_deck(**args, &block)
|
|
197
201
|
render Keystone::Ui::SwipeDeckComponent.new(**args), &block
|
|
198
202
|
end
|
data/config/importmap.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
pin "keystone_ui/index", to: "keystone_ui/index.js"
|
|
2
2
|
pin "keystone_ui/color_picker_controller", to: "keystone_ui/color_picker_controller.js"
|
|
3
3
|
pin "keystone_ui/multi_select_controller", to: "keystone_ui/multi_select_controller.js"
|
|
4
|
+
pin "keystone_ui/search_select_controller", to: "keystone_ui/search_select_controller.js"
|
|
4
5
|
pin "keystone_ui/swipe_deck_controller", to: "keystone_ui/swipe_deck_controller.js"
|
|
5
6
|
pin "keystone_ui/column_picker_controller", to: "keystone_ui/column_picker_controller.js"
|
|
6
7
|
pin "keystone_ui/file_upload_controller", to: "keystone_ui/file_upload_controller.js"
|
data/lib/keystone_ui/safelist.rb
CHANGED
|
@@ -51,6 +51,7 @@ module Keystone
|
|
|
51
51
|
Keystone::Ui::ShowPageComponent,
|
|
52
52
|
Keystone::Ui::OptionCardComponent,
|
|
53
53
|
Keystone::Ui::RadioCardComponent,
|
|
54
|
+
Keystone::Ui::SearchSelectComponent,
|
|
54
55
|
Keystone::Ui::CheckboxRowComponent,
|
|
55
56
|
Keystone::Ui::ProgressComponent,
|
|
56
57
|
Keystone::Ui::ColorPickerComponent,
|
data/lib/keystone_ui/version.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: keystone_ui-develop
|
|
3
|
-
description: Use PROACTIVELY for building or editing screens in a Rails app that has keystone_ui — page shells with Back links and breadcrumbs, forms and fields, data tables with saved columns, desktop navigation, sidebars and bottom tabs, action menus for a record's Edit and Delete, dashboards with stat cards, charts, funnels and goal buckets, amounts shown in green or red as a gain or loss, info buttons and breakdowns, marketing sections, a light/dark theme switch — MUST BE USED instead of hand-writing ERB and Tailwind for UI.
|
|
3
|
+
description: Use PROACTIVELY for building or editing screens in a Rails app that has keystone_ui — page shells with Back links and breadcrumbs, forms and fields, a search field that picks a record or enters a new one, data tables with saved columns, desktop navigation, sidebars and bottom tabs, action menus for a record's Edit and Delete, dashboards with stat cards, charts, funnels and goal buckets, amounts shown in green or red as a gain or loss, info buttons and breakdowns, marketing sections, a light/dark theme switch — MUST BE USED instead of hand-writing ERB and Tailwind for UI.
|
|
4
4
|
tools: Bash, Read, Write, Edit, Grep
|
|
5
5
|
scope: UI — pages, forms, tables, navigation, dashboards
|
|
6
6
|
---
|
|
@@ -52,6 +52,7 @@ not available in the app yet, that is `keystone_ui-install`'s job.
|
|
|
52
52
|
- `ui_textarea` — a bare styled textarea with no label.
|
|
53
53
|
- `ui_select` — a bare styled select with no label.
|
|
54
54
|
- `ui_multi_select` — a dropdown of checkboxes posting every checked value.
|
|
55
|
+
- `ui_search_select` — a form field that searches the app as a person types and submits the id of the record they pick.
|
|
55
56
|
- `ui_file_upload` — a file drop zone with selected-file feedback.
|
|
56
57
|
- `ui_color_picker` — a colour swatch that writes a hex value into a hidden input.
|
|
57
58
|
- `ui_radio_card` — a selectable card backed by a radio input.
|
|
@@ -302,6 +303,31 @@ two exceptions: `ui_page`'s `padding:` treats any value other than `:none` as
|
|
|
302
303
|
`"status[]"`. `options:` is `[[label, value], ...]` and `selected:` is the
|
|
303
304
|
values to check. Its button reads "All <label>" with nothing checked and
|
|
304
305
|
"N selected" otherwise.
|
|
306
|
+
- `ui_search_select(name:, label:, url:, selected_id: nil, selected_label: nil, new_label: nil)`
|
|
307
|
+
is one field inside a `ui_form`, for picking one record from more than a
|
|
308
|
+
select can list. Each keystroke sends `GET url?q=<typed text>` with
|
|
309
|
+
`Accept: application/json`, and the app answers with a JSON array of
|
|
310
|
+
`{ "id": ..., "label": ... }` objects in the order to list them. Labels
|
|
311
|
+
are shown as plain text. Picking a match by click, or by the arrow keys
|
|
312
|
+
and Enter, puts its id in a hidden input named `name` and its label in
|
|
313
|
+
the field. Escape closes the list.
|
|
314
|
+
- The app owns the search endpoint: the route, which records it searches,
|
|
315
|
+
how it matches the typed text, how many matches it returns, and which
|
|
316
|
+
records the current user may see. Ask the developer for each, and scope
|
|
317
|
+
the query to the current account.
|
|
318
|
+
- `selected_id:` and `selected_label:` open the field with a record already
|
|
319
|
+
chosen, such as on an edit screen, so the form submits that id unchanged
|
|
320
|
+
when nothing else is picked.
|
|
321
|
+
- Typing without picking leaves the hidden id as it was, so the form submits
|
|
322
|
+
the last picked id, or `selected_id:`, whatever the field shows.
|
|
323
|
+
- `new_label:` adds a last choice, such as "Enter a new address", shown in
|
|
324
|
+
the list after each search. Picking it clears the hidden id and shows the
|
|
325
|
+
block passed to the helper, which holds the fields for a new record such
|
|
326
|
+
as `ui_form_field` calls. Picking a match afterwards hides them again.
|
|
327
|
+
- The block's fields are submitted whether shown or hidden, so the app's
|
|
328
|
+
controller treats a blank id as "create from the new fields" and a present
|
|
329
|
+
id as "use that record and ignore the new fields". Ask the developer
|
|
330
|
+
whether a person may enter a new record, and what `new_label:` says.
|
|
305
331
|
- `ui_file_upload(name:, label: nil, accept: nil, multiple: false, hint: nil)`
|
|
306
332
|
needs the enclosing form to be multipart.
|
|
307
333
|
- `ui_color_picker(name:, value: "#000000", label: nil)` writes the chosen
|
|
@@ -516,7 +542,8 @@ two exceptions: `ui_page`'s `padding:` treats any value other than `:none` as
|
|
|
516
542
|
and rejecting sends `swipe-deck:skip`. Both carry `detail.itemId` (the
|
|
517
543
|
item's `id`, or its position) and `detail.card`, and `complete` carries
|
|
518
544
|
`detail.value` from an input marked `data-swipe-deck-value`, or `null`.
|
|
519
|
-
- For these, the pipeline's URLs
|
|
545
|
+
- For these, the pipeline's URLs, the column picker's save URL and the
|
|
546
|
+
search select's search URL, do not
|
|
520
547
|
invent routes or how the outcome is stored. Ask the developer, then
|
|
521
548
|
build what they pick.
|
|
522
549
|
|
|
@@ -12,7 +12,7 @@ nothing and gives no steps.
|
|
|
12
12
|
|
|
13
13
|
keystone_ui is a Rails engine gem that supplies a host app's UI as view helpers
|
|
14
14
|
built on ViewComponent. Screens are built from named pieces — page shells,
|
|
15
|
-
sections, panels, grids, forms and fields, data tables, navigation, cards, stat
|
|
15
|
+
sections, panels, grids, forms and fields, search dropdowns, data tables, navigation, cards, stat
|
|
16
16
|
tiles, charts, funnels, goal buckets, pipelines, breakdowns and info buttons —
|
|
17
17
|
instead of hand-written ERB and Tailwind. Every class the UI renders lives in the
|
|
18
18
|
gem, so two pages built from the same helpers cannot disagree about spacing,
|
|
@@ -78,6 +78,14 @@ One decision: is keystone_ui set up in the app?
|
|
|
78
78
|
it: which hideable columns to hide and their order. With a save address, a
|
|
79
79
|
"Columns" menu lets the user change it. A locked first column stays in view
|
|
80
80
|
while the table scrolls sideways and is never hidden or moved.
|
|
81
|
+
- **Search dropdowns.** A search dropdown picks one record by its id from
|
|
82
|
+
matches the host serves. As the user types, it requests the host's search
|
|
83
|
+
address with the text as `q` and expects JSON back: a list of matches, each
|
|
84
|
+
with an `id` and a `label`. Picking a match submits its id under the field's
|
|
85
|
+
name. When the dropdown offers a choice to enter a new record, picking it
|
|
86
|
+
submits an empty id and shows the new record's fields the page placed inside
|
|
87
|
+
the dropdown, and picking a match afterwards hides them again. The arrow keys
|
|
88
|
+
move through the list, Enter picks, and Escape closes it.
|
|
81
89
|
- **Action menus.** Each action is a label, an address and an HTTP method. A
|
|
82
90
|
plain visit is a link, and any other method is a button, so an action that
|
|
83
91
|
changes data is never a bare link. A delete asks for confirmation by default.
|
|
@@ -98,9 +106,9 @@ One decision: is keystone_ui set up in the app?
|
|
|
98
106
|
- **Static Tailwind classes.** Class names are never interpolated, so Tailwind's
|
|
99
107
|
scanner finds them. Sizes that depend on data, such as a progress bar's
|
|
100
108
|
width, use an inline style. The host needs tailwindcss-rails v4+.
|
|
101
|
-
- **Interactivity is Stimulus.** Dropdowns, modals, tab
|
|
102
|
-
picker, info buttons, charts, copy buttons and the theme toggle ship as
|
|
109
|
+
- **Interactivity is Stimulus.** Dropdowns, search dropdowns, modals, tab
|
|
110
|
+
switchers, the column picker, info buttons, charts, copy buttons and the theme toggle ship as
|
|
103
111
|
Stimulus controllers, so a host writes no JavaScript. Components that post,
|
|
104
112
|
such as the column picker and the pipeline, post to endpoints the host or
|
|
105
113
|
another gem owns.
|
|
106
|
-
- Ruby >= 3.2, ViewComponent >= 2.0 and < 5, keystone_ui-styles >= 0.
|
|
114
|
+
- Ruby >= 3.2, ViewComponent >= 2.0 and < 5, keystone_ui-styles >= 0.25.0.
|
|
@@ -50,7 +50,7 @@ built on ViewComponent; hook it in before building any screen with those helpers
|
|
|
50
50
|
## How to use it
|
|
51
51
|
|
|
52
52
|
1. Confirm the prerequisites: Ruby >= 3.2 and **tailwindcss-rails v4+** in the
|
|
53
|
-
host app. The gem brings ViewComponent and keystone_ui-styles 0.
|
|
53
|
+
host app. The gem brings ViewComponent and keystone_ui-styles 0.25.0 or later with it.
|
|
54
54
|
Tailwind does not have to be initialized first, because the generator creates
|
|
55
55
|
the stylesheet if it is missing.
|
|
56
56
|
|
|
@@ -92,7 +92,8 @@ built on ViewComponent; hook it in before building any screen with those helpers
|
|
|
92
92
|
- `app/javascript/controllers/index.js not found` — ask the developer where
|
|
93
93
|
the Stimulus application is set up and add those two lines there. Without
|
|
94
94
|
them, dropdowns, modals, file uploads, the column picker, the theme toggle,
|
|
95
|
-
the info button's popups
|
|
95
|
+
the info button's popups, the search select's list of matches and the other
|
|
96
|
+
interactive components do nothing.
|
|
96
97
|
`registerControllers(application)` also copies `data-theme` and `data-look`
|
|
97
98
|
from each page Turbo renders onto the `<html>` tag. Without it, a Turbo
|
|
98
99
|
visit keeps the theme and look of the first page loaded.
|
|
@@ -159,7 +160,7 @@ built on ViewComponent; hook it in before building any screen with those helpers
|
|
|
159
160
|
```
|
|
160
161
|
|
|
161
162
|
Buttons, panels, cards, alerts, badges, form fields, the modal, the mobile
|
|
162
|
-
action menu, the action menu, the column picker, multi select, copy button, theme toggle,
|
|
163
|
+
action menu, the action menu, the column picker, multi select, search select, copy button, theme toggle,
|
|
163
164
|
checkbox row, radio card, option card, file upload and colour picker read
|
|
164
165
|
these variables. So do the data display components: stat card, chart card,
|
|
165
166
|
card link, CTA banner, feature grid, hero, data table, code, accordion,
|
data/the_local/interface.yml
CHANGED
|
@@ -52,6 +52,7 @@ develop:
|
|
|
52
52
|
- ui_settings_link
|
|
53
53
|
- ui_color_picker
|
|
54
54
|
- ui_multi_select
|
|
55
|
+
- ui_search_select
|
|
55
56
|
- ui_swipe_deck
|
|
56
57
|
- ui_column_picker
|
|
57
58
|
- ui_form
|
|
@@ -137,6 +138,9 @@ sources:
|
|
|
137
138
|
- app/components/keystone/ui/mobile_header_component.html.erb
|
|
138
139
|
- app/components/keystone/ui/modal_component.rb
|
|
139
140
|
- app/components/keystone/ui/multi_select_component.rb
|
|
141
|
+
- app/components/keystone/ui/search_select_component.rb
|
|
142
|
+
- app/components/keystone/ui/search_select_component.html.erb
|
|
143
|
+
- app/assets/javascripts/keystone_ui/search_select_controller.js
|
|
140
144
|
- app/components/keystone/ui/nav_dropdown_component.rb
|
|
141
145
|
- app/components/keystone/ui/nav_item_component.rb
|
|
142
146
|
- app/components/keystone/ui/navbar_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.53.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.27.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.27.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: view_component
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -67,6 +67,7 @@ files:
|
|
|
67
67
|
- app/assets/javascripts/keystone_ui/modal_controller.js
|
|
68
68
|
- app/assets/javascripts/keystone_ui/multi_select_controller.js
|
|
69
69
|
- app/assets/javascripts/keystone_ui/page_theme.js
|
|
70
|
+
- app/assets/javascripts/keystone_ui/search_select_controller.js
|
|
70
71
|
- app/assets/javascripts/keystone_ui/stat_card_info_controller.js
|
|
71
72
|
- app/assets/javascripts/keystone_ui/swipe_deck_controller.js
|
|
72
73
|
- app/assets/javascripts/keystone_ui/tab_switcher_controller.js
|
|
@@ -186,6 +187,8 @@ files:
|
|
|
186
187
|
- app/components/keystone/ui/radio_card_component.html.erb
|
|
187
188
|
- app/components/keystone/ui/radio_card_component.rb
|
|
188
189
|
- app/components/keystone/ui/saved_layout.rb
|
|
190
|
+
- app/components/keystone/ui/search_select_component.html.erb
|
|
191
|
+
- app/components/keystone/ui/search_select_component.rb
|
|
189
192
|
- app/components/keystone/ui/section_component.html.erb
|
|
190
193
|
- app/components/keystone/ui/section_component.rb
|
|
191
194
|
- app/components/keystone/ui/select_component.html.erb
|