ruby_ui 1.1.0 → 1.2.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/lib/generators/ruby_ui/component_generator.rb +5 -1
- data/lib/generators/ruby_ui/dependencies.yml +10 -0
- data/lib/generators/ruby_ui/install/install_generator.rb +1 -1
- data/lib/generators/ruby_ui/javascript_utils.rb +4 -0
- data/lib/ruby_ui/combobox/combobox.rb +7 -1
- data/lib/ruby_ui/combobox/combobox_badge.rb +17 -0
- data/lib/ruby_ui/combobox/combobox_badge_trigger.rb +47 -0
- data/lib/ruby_ui/combobox/combobox_checkbox.rb +1 -7
- data/lib/ruby_ui/combobox/combobox_clear_button.rb +40 -0
- data/lib/ruby_ui/combobox/combobox_controller.js +243 -53
- data/lib/ruby_ui/combobox/combobox_docs.rb +199 -64
- data/lib/ruby_ui/combobox/combobox_input_trigger.rb +64 -0
- data/lib/ruby_ui/combobox/combobox_item.rb +5 -7
- data/lib/ruby_ui/combobox/combobox_item_indicator.rb +30 -0
- data/lib/ruby_ui/combobox/combobox_list_group.rb +1 -1
- data/lib/ruby_ui/combobox/combobox_popover.rb +0 -5
- data/lib/ruby_ui/combobox/combobox_radio.rb +1 -8
- data/lib/ruby_ui/combobox/combobox_toggle_all_checkbox.rb +1 -7
- data/lib/ruby_ui/combobox/combobox_trigger.rb +19 -19
- data/lib/ruby_ui/data_table/data_table.rb +29 -0
- data/lib/ruby_ui/data_table/data_table_bulk_actions.rb +18 -0
- data/lib/ruby_ui/data_table/data_table_column_toggle.rb +62 -0
- data/lib/ruby_ui/data_table/data_table_column_visibility_controller.js +14 -0
- data/lib/ruby_ui/data_table/data_table_controller.js +57 -0
- data/lib/ruby_ui/data_table/data_table_docs.rb +180 -0
- data/lib/ruby_ui/data_table/data_table_expand_toggle.rb +53 -0
- data/lib/ruby_ui/data_table/data_table_form.rb +39 -0
- data/lib/ruby_ui/data_table/data_table_kaminari_adapter.rb +17 -0
- data/lib/ruby_ui/data_table/data_table_manual_adapter.rb +17 -0
- data/lib/ruby_ui/data_table/data_table_pagination.rb +100 -0
- data/lib/ruby_ui/data_table/data_table_pagination_bar.rb +15 -0
- data/lib/ruby_ui/data_table/data_table_pagy_adapter.rb +17 -0
- data/lib/ruby_ui/data_table/data_table_per_page_select.rb +35 -0
- data/lib/ruby_ui/data_table/data_table_row_checkbox.rb +30 -0
- data/lib/ruby_ui/data_table/data_table_search.rb +57 -0
- data/lib/ruby_ui/data_table/data_table_search_controller.js +62 -0
- data/lib/ruby_ui/data_table/data_table_select_all_checkbox.rb +21 -0
- data/lib/ruby_ui/data_table/data_table_selection_summary.rb +25 -0
- data/lib/ruby_ui/data_table/data_table_sort_head.rb +112 -0
- data/lib/ruby_ui/data_table/data_table_toolbar.rb +15 -0
- data/lib/ruby_ui/masked_input/masked_input.rb +11 -1
- data/lib/ruby_ui/masked_input/masked_input_controller.js +13 -0
- data/lib/ruby_ui/native_select/native_select.rb +39 -0
- data/lib/ruby_ui/native_select/native_select_docs.rb +83 -0
- data/lib/ruby_ui/native_select/native_select_group.rb +15 -0
- data/lib/ruby_ui/native_select/native_select_icon.rb +39 -0
- data/lib/ruby_ui/native_select/native_select_option.rb +15 -0
- data/lib/ruby_ui.rb +1 -1
- metadata +43 -3
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class Views::Docs::Combobox < Views::Base
|
|
4
|
-
@@code_example = nil
|
|
5
|
-
|
|
6
4
|
def view_template
|
|
7
5
|
component = "Combobox"
|
|
8
6
|
div(class: "max-w-2xl mx-auto w-full py-10 space-y-10") do
|
|
@@ -10,51 +8,159 @@ class Views::Docs::Combobox < Views::Base
|
|
|
10
8
|
|
|
11
9
|
Heading(level: 2) { "Usage" }
|
|
12
10
|
|
|
13
|
-
render Docs::VisualCodeExample.new(title: "
|
|
11
|
+
render Docs::VisualCodeExample.new(title: "Basic", context: self) do
|
|
14
12
|
<<~RUBY
|
|
15
|
-
div
|
|
13
|
+
div(class: "w-96") do
|
|
16
14
|
Combobox do
|
|
17
|
-
|
|
15
|
+
ComboboxInputTrigger(placeholder: "Select framework...")
|
|
18
16
|
|
|
19
17
|
ComboboxPopover do
|
|
20
|
-
|
|
18
|
+
ComboboxList do
|
|
19
|
+
ComboboxEmptyState { "No results found." }
|
|
20
|
+
|
|
21
|
+
ComboboxItem do
|
|
22
|
+
ComboboxRadio(name: "framework", value: "rails")
|
|
23
|
+
span { "Rails" }
|
|
24
|
+
end
|
|
25
|
+
ComboboxItem do
|
|
26
|
+
ComboboxRadio(name: "framework", value: "hanami")
|
|
27
|
+
span { "Hanami" }
|
|
28
|
+
end
|
|
29
|
+
ComboboxItem do
|
|
30
|
+
ComboboxRadio(name: "framework", value: "nextjs")
|
|
31
|
+
span { "Next.js" }
|
|
32
|
+
end
|
|
33
|
+
ComboboxItem do
|
|
34
|
+
ComboboxRadio(name: "framework", value: "nuxt")
|
|
35
|
+
span { "Nuxt" }
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
RUBY
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
render Docs::VisualCodeExample.new(title: "Popup", context: self) do
|
|
45
|
+
<<~RUBY
|
|
46
|
+
div(class: "w-96") do
|
|
47
|
+
Combobox do
|
|
48
|
+
ComboboxTrigger(placeholder: "Select framework...")
|
|
49
|
+
|
|
50
|
+
ComboboxPopover do
|
|
51
|
+
ComboboxSearchInput(placeholder: "Search framework...")
|
|
21
52
|
|
|
22
53
|
ComboboxList do
|
|
23
|
-
ComboboxEmptyState { "No
|
|
54
|
+
ComboboxEmptyState { "No results found." }
|
|
55
|
+
|
|
56
|
+
ComboboxItem do
|
|
57
|
+
ComboboxRadio(name: "fw2", value: "rails")
|
|
58
|
+
span { "Rails" }
|
|
59
|
+
end
|
|
60
|
+
ComboboxItem do
|
|
61
|
+
ComboboxRadio(name: "fw2", value: "hanami")
|
|
62
|
+
span { "Hanami" }
|
|
63
|
+
end
|
|
64
|
+
ComboboxItem do
|
|
65
|
+
ComboboxRadio(name: "fw2", value: "nextjs")
|
|
66
|
+
span { "Next.js" }
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
RUBY
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
render Docs::VisualCodeExample.new(title: "Multiple", context: self) do
|
|
76
|
+
<<~RUBY
|
|
77
|
+
div(class: "w-96") do
|
|
78
|
+
Combobox do
|
|
79
|
+
ComboboxBadgeTrigger(clear_button: true)
|
|
80
|
+
|
|
81
|
+
ComboboxPopover do
|
|
82
|
+
ComboboxList do
|
|
83
|
+
ComboboxEmptyState { "No results found." }
|
|
84
|
+
|
|
85
|
+
ComboboxItem do
|
|
86
|
+
ComboboxCheckbox(name: "frameworks[]", value: "rails")
|
|
87
|
+
span { "Rails" }
|
|
88
|
+
end
|
|
89
|
+
ComboboxItem do
|
|
90
|
+
ComboboxCheckbox(name: "frameworks[]", value: "hanami")
|
|
91
|
+
span { "Hanami" }
|
|
92
|
+
end
|
|
93
|
+
ComboboxItem do
|
|
94
|
+
ComboboxCheckbox(name: "frameworks[]", value: "sinatra")
|
|
95
|
+
span { "Sinatra" }
|
|
96
|
+
end
|
|
97
|
+
ComboboxItem do
|
|
98
|
+
ComboboxCheckbox(name: "frameworks[]", value: "nextjs", checked: true)
|
|
99
|
+
span { "Next.js" }
|
|
100
|
+
end
|
|
101
|
+
ComboboxItem do
|
|
102
|
+
ComboboxCheckbox(name: "frameworks[]", value: "nuxt")
|
|
103
|
+
span { "Nuxt" }
|
|
104
|
+
end
|
|
105
|
+
ComboboxItem do
|
|
106
|
+
ComboboxCheckbox(name: "frameworks[]", value: "svelte")
|
|
107
|
+
span { "SvelteKit" }
|
|
108
|
+
end
|
|
109
|
+
ComboboxItem do
|
|
110
|
+
ComboboxCheckbox(name: "frameworks[]", value: "remix")
|
|
111
|
+
span { "Remix" }
|
|
112
|
+
end
|
|
113
|
+
ComboboxItem do
|
|
114
|
+
ComboboxCheckbox(name: "frameworks[]", value: "astro")
|
|
115
|
+
span { "Astro" }
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
RUBY
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
render Docs::VisualCodeExample.new(title: "Groups", context: self) do
|
|
125
|
+
<<~RUBY
|
|
126
|
+
div(class: "w-96") do
|
|
127
|
+
Combobox do
|
|
128
|
+
ComboboxInputTrigger(placeholder: "Select food...")
|
|
129
|
+
|
|
130
|
+
ComboboxPopover do
|
|
131
|
+
ComboboxList do
|
|
132
|
+
ComboboxEmptyState { "No results found." }
|
|
24
133
|
|
|
25
134
|
ComboboxListGroup(label: "Fruits") do
|
|
26
135
|
ComboboxItem do
|
|
27
136
|
ComboboxRadio(name: "food", value: "apple")
|
|
28
137
|
span { "Apple" }
|
|
29
138
|
end
|
|
30
|
-
|
|
31
139
|
ComboboxItem do
|
|
32
140
|
ComboboxRadio(name: "food", value: "banana")
|
|
33
141
|
span { "Banana" }
|
|
34
142
|
end
|
|
35
143
|
end
|
|
36
144
|
|
|
37
|
-
ComboboxListGroup(label: "
|
|
145
|
+
ComboboxListGroup(label: "Vegetables") do
|
|
38
146
|
ComboboxItem do
|
|
39
|
-
ComboboxRadio(name: "food", value: "
|
|
147
|
+
ComboboxRadio(name: "food", value: "broccoli")
|
|
40
148
|
span { "Broccoli" }
|
|
41
149
|
end
|
|
42
|
-
|
|
43
150
|
ComboboxItem do
|
|
44
151
|
ComboboxRadio(name: "food", value: "carrot")
|
|
45
152
|
span { "Carrot" }
|
|
46
153
|
end
|
|
47
154
|
end
|
|
48
155
|
|
|
49
|
-
ComboboxListGroup(label: "
|
|
156
|
+
ComboboxListGroup(label: "Grains") do
|
|
50
157
|
ComboboxItem do
|
|
51
|
-
ComboboxRadio(name: "food", value: "
|
|
52
|
-
span { "
|
|
158
|
+
ComboboxRadio(name: "food", value: "rice")
|
|
159
|
+
span { "Rice" }
|
|
53
160
|
end
|
|
54
|
-
|
|
55
161
|
ComboboxItem do
|
|
56
|
-
ComboboxRadio(name: "food", value: "
|
|
57
|
-
span { "
|
|
162
|
+
ComboboxRadio(name: "food", value: "wheat")
|
|
163
|
+
span { "Wheat" }
|
|
58
164
|
end
|
|
59
165
|
end
|
|
60
166
|
end
|
|
@@ -64,57 +170,55 @@ class Views::Docs::Combobox < Views::Base
|
|
|
64
170
|
RUBY
|
|
65
171
|
end
|
|
66
172
|
|
|
67
|
-
render Docs::VisualCodeExample.new(title: "
|
|
173
|
+
render Docs::VisualCodeExample.new(title: "Custom Items", context: self) do
|
|
68
174
|
<<~RUBY
|
|
69
|
-
div
|
|
70
|
-
Combobox
|
|
71
|
-
|
|
175
|
+
div(class: "w-96") do
|
|
176
|
+
Combobox do
|
|
177
|
+
ComboboxInputTrigger(placeholder: "Select status...")
|
|
72
178
|
|
|
73
179
|
ComboboxPopover do
|
|
74
|
-
ComboboxSearchInput(placeholder: "Pick value or type anything")
|
|
75
|
-
|
|
76
180
|
ComboboxList do
|
|
77
|
-
ComboboxEmptyState { "No
|
|
181
|
+
ComboboxEmptyState { "No results found." }
|
|
78
182
|
|
|
79
|
-
ComboboxItem
|
|
80
|
-
|
|
81
|
-
|
|
183
|
+
ComboboxItem do
|
|
184
|
+
ComboboxRadio(name: "status", value: "backlog", data: {text: "Backlog"})
|
|
185
|
+
svg(xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewbox: "0 0 24 24", fill: "none", stroke: "currentColor", stroke_width: "2", class: "text-muted-foreground") { |s| s.circle(cx: "12", cy: "12", r: "10") }
|
|
186
|
+
span { "Backlog" }
|
|
82
187
|
end
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
span { "Apple" }
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
ComboboxItem do
|
|
91
|
-
ComboboxCheckbox(name: "food", value: "banana")
|
|
92
|
-
span { "Banana" }
|
|
93
|
-
end
|
|
188
|
+
ComboboxItem do
|
|
189
|
+
ComboboxRadio(name: "status", value: "todo", data: {text: "Todo"})
|
|
190
|
+
svg(xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewbox: "0 0 24 24", fill: "none", stroke: "currentColor", stroke_width: "2", class: "text-blue-500") { |s| s.circle(cx: "12", cy: "12", r: "10") }
|
|
191
|
+
span { "Todo" }
|
|
94
192
|
end
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
span { "Broccoli" }
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
ComboboxItem do
|
|
103
|
-
ComboboxCheckbox(name: "food", value: "carrot")
|
|
104
|
-
span { "Carrot" }
|
|
105
|
-
end
|
|
193
|
+
ComboboxItem do
|
|
194
|
+
ComboboxRadio(name: "status", value: "done", data: {text: "Done"})
|
|
195
|
+
svg(xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewbox: "0 0 24 24", fill: "none", stroke: "currentColor", stroke_width: "2", class: "text-green-500") { |s| s.path(d: "M22 11.08V12a10 10 0 1 1-5.93-9.14"); s.path(d: "m9 11 3 3L22 4") }
|
|
196
|
+
span { "Done" }
|
|
106
197
|
end
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
RUBY
|
|
203
|
+
end
|
|
107
204
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
205
|
+
render Docs::VisualCodeExample.new(title: "Invalid", context: self) do
|
|
206
|
+
<<~RUBY
|
|
207
|
+
div(class: "w-96") do
|
|
208
|
+
Combobox do
|
|
209
|
+
ComboboxInputTrigger(placeholder: "Required field", aria: {invalid: "true"})
|
|
113
210
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
211
|
+
ComboboxPopover do
|
|
212
|
+
ComboboxList do
|
|
213
|
+
ComboboxEmptyState { "No results found." }
|
|
214
|
+
|
|
215
|
+
ComboboxItem do
|
|
216
|
+
ComboboxRadio(name: "req", value: "option1")
|
|
217
|
+
span { "Option 1" }
|
|
218
|
+
end
|
|
219
|
+
ComboboxItem do
|
|
220
|
+
ComboboxRadio(name: "req", value: "option2")
|
|
221
|
+
span { "Option 2" }
|
|
118
222
|
end
|
|
119
223
|
end
|
|
120
224
|
end
|
|
@@ -125,27 +229,58 @@ class Views::Docs::Combobox < Views::Base
|
|
|
125
229
|
|
|
126
230
|
render Docs::VisualCodeExample.new(title: "Disabled", context: self) do
|
|
127
231
|
<<~RUBY
|
|
128
|
-
div(class: "w-96") do
|
|
232
|
+
div(class: "w-96 space-y-2") do
|
|
129
233
|
Combobox do
|
|
130
|
-
ComboboxTrigger(disabled: true, placeholder: "
|
|
234
|
+
ComboboxTrigger(disabled: true, placeholder: "Disabled trigger")
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
Combobox do
|
|
238
|
+
ComboboxInputTrigger(placeholder: "Disabled input", disabled: true)
|
|
131
239
|
end
|
|
132
240
|
end
|
|
133
241
|
RUBY
|
|
134
242
|
end
|
|
135
243
|
|
|
136
|
-
render Docs::VisualCodeExample.new(title: "
|
|
244
|
+
render Docs::VisualCodeExample.new(title: "Auto Highlight", context: self) do
|
|
137
245
|
<<~RUBY
|
|
138
246
|
div(class: "w-96") do
|
|
139
247
|
Combobox do
|
|
140
|
-
|
|
248
|
+
ComboboxInputTrigger(placeholder: "Type to search...")
|
|
249
|
+
|
|
250
|
+
ComboboxPopover do
|
|
251
|
+
ComboboxList do
|
|
252
|
+
ComboboxEmptyState { "No results found." }
|
|
253
|
+
|
|
254
|
+
ComboboxItem do
|
|
255
|
+
ComboboxRadio(name: "color", value: "red")
|
|
256
|
+
span { "Red" }
|
|
257
|
+
end
|
|
258
|
+
ComboboxItem do
|
|
259
|
+
ComboboxRadio(name: "color", value: "green")
|
|
260
|
+
span { "Green" }
|
|
261
|
+
end
|
|
262
|
+
ComboboxItem do
|
|
263
|
+
ComboboxRadio(name: "color", value: "blue")
|
|
264
|
+
span { "Blue" }
|
|
265
|
+
end
|
|
266
|
+
ComboboxItem do
|
|
267
|
+
ComboboxRadio(name: "color", value: "yellow")
|
|
268
|
+
span { "Yellow" }
|
|
269
|
+
end
|
|
270
|
+
ComboboxItem do
|
|
271
|
+
ComboboxRadio(name: "color", value: "purple")
|
|
272
|
+
span { "Purple" }
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
end
|
|
141
276
|
end
|
|
142
277
|
end
|
|
143
278
|
RUBY
|
|
144
279
|
end
|
|
145
280
|
|
|
146
|
-
render Components::ComponentSetup::Tabs.new(component_name:
|
|
281
|
+
render Components::ComponentSetup::Tabs.new(component_name: component)
|
|
147
282
|
|
|
148
|
-
render Docs::ComponentsTable.new(component_files(
|
|
283
|
+
render Docs::ComponentsTable.new(component_files(component))
|
|
149
284
|
end
|
|
150
285
|
end
|
|
151
286
|
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RubyUI
|
|
4
|
+
class ComboboxInputTrigger < Base
|
|
5
|
+
def initialize(placeholder: "", **)
|
|
6
|
+
@placeholder = placeholder
|
|
7
|
+
super(**)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def view_template
|
|
11
|
+
div(**attrs) do
|
|
12
|
+
input(
|
|
13
|
+
type: "text",
|
|
14
|
+
placeholder: @placeholder,
|
|
15
|
+
autocomplete: "off",
|
|
16
|
+
autocorrect: "off",
|
|
17
|
+
spellcheck: "false",
|
|
18
|
+
class: "flex-1 border-0 px-0 bg-transparent outline-none focus:ring-0 placeholder:text-muted-foreground text-sm disabled:cursor-not-allowed",
|
|
19
|
+
data: {
|
|
20
|
+
ruby_ui__combobox_target: "inputTrigger",
|
|
21
|
+
action: "keyup->ruby-ui--combobox#filterItems input->ruby-ui--combobox#filterItems"
|
|
22
|
+
}
|
|
23
|
+
)
|
|
24
|
+
chevron_icon
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def default_attrs
|
|
31
|
+
{
|
|
32
|
+
class: "flex h-9 w-full items-center rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2 aria-invalid:border-destructive",
|
|
33
|
+
data: {
|
|
34
|
+
ruby_ui__combobox_target: "trigger",
|
|
35
|
+
placeholder: @placeholder,
|
|
36
|
+
action: "click->ruby-ui--combobox#openPopover focusin->ruby-ui--combobox#openPopover"
|
|
37
|
+
},
|
|
38
|
+
aria: {
|
|
39
|
+
haspopup: "listbox",
|
|
40
|
+
expanded: "false"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def chevron_icon
|
|
46
|
+
span(class: "shrink-0 flex items-center justify-center size-6 rounded-sm hover:bg-muted hover:text-foreground") do
|
|
47
|
+
svg(
|
|
48
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
49
|
+
width: "24",
|
|
50
|
+
height: "24",
|
|
51
|
+
viewbox: "0 0 24 24",
|
|
52
|
+
fill: "none",
|
|
53
|
+
stroke: "currentColor",
|
|
54
|
+
stroke_width: "2",
|
|
55
|
+
stroke_linecap: "round",
|
|
56
|
+
stroke_linejoin: "round",
|
|
57
|
+
class: "pointer-events-none size-4 text-muted-foreground"
|
|
58
|
+
) do |s|
|
|
59
|
+
s.path(d: "m6 9 6 6 6-6")
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -3,19 +3,17 @@
|
|
|
3
3
|
module RubyUI
|
|
4
4
|
class ComboboxItem < Base
|
|
5
5
|
def view_template(&)
|
|
6
|
-
label(**attrs
|
|
6
|
+
label(**attrs) do
|
|
7
|
+
yield if block_given?
|
|
8
|
+
render ComboboxItemIndicator.new
|
|
9
|
+
end
|
|
7
10
|
end
|
|
8
11
|
|
|
9
12
|
private
|
|
10
13
|
|
|
11
14
|
def default_attrs
|
|
12
15
|
{
|
|
13
|
-
class: [
|
|
14
|
-
"flex flex-row w-full text-wrap [&>span,&>div]:truncate gap-2 items-center rounded-sm px-2 py-1 text-sm outline-none cursor-pointer",
|
|
15
|
-
"select-none has-[:checked]:bg-accent hover:bg-accent p-2",
|
|
16
|
-
"[&>svg]:pointer-events-none [&>svg]:size-4 [&>svg]:shrink-0 aria-[current=true]:bg-accent aria-[current=true]:ring aria-[current=true]:ring-offset-2",
|
|
17
|
-
"has-disabled:opacity-50 has-disabled:cursor-not-allowed"
|
|
18
|
-
],
|
|
16
|
+
class: "relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground aria-[current=true]:bg-accent has-[input:disabled]:opacity-50 has-[input:disabled]:cursor-not-allowed",
|
|
19
17
|
role: "option",
|
|
20
18
|
data: {
|
|
21
19
|
ruby_ui__combobox_target: "item"
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RubyUI
|
|
4
|
+
class ComboboxItemIndicator < Base
|
|
5
|
+
def view_template
|
|
6
|
+
svg(
|
|
7
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
8
|
+
width: "24",
|
|
9
|
+
height: "24",
|
|
10
|
+
viewbox: "0 0 24 24",
|
|
11
|
+
fill: "none",
|
|
12
|
+
stroke: "currentColor",
|
|
13
|
+
stroke_width: "2",
|
|
14
|
+
stroke_linecap: "round",
|
|
15
|
+
stroke_linejoin: "round",
|
|
16
|
+
**attrs
|
|
17
|
+
) do |s|
|
|
18
|
+
s.path(d: "M20 6 9 17l-5-5")
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def default_attrs
|
|
25
|
+
{
|
|
26
|
+
class: "ml-auto size-4 shrink-0 opacity-0 peer-checked:opacity-100"
|
|
27
|
+
}
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -12,16 +12,11 @@ module RubyUI
|
|
|
12
12
|
{
|
|
13
13
|
class: "inset-auto m-0 absolute border bg-background shadow-lg rounded-lg",
|
|
14
14
|
role: "popover",
|
|
15
|
-
autofocus: true,
|
|
16
15
|
popover: true,
|
|
17
16
|
data: {
|
|
18
17
|
ruby_ui__combobox_target: "popover",
|
|
19
18
|
action: %w[
|
|
20
19
|
toggle->ruby-ui--combobox#handlePopoverToggle
|
|
21
|
-
keydown.down->ruby-ui--combobox#keyDownPressed
|
|
22
|
-
keydown.up->ruby-ui--combobox#keyUpPressed
|
|
23
|
-
keydown.enter->ruby-ui--combobox#keyEnterPressed
|
|
24
|
-
keydown.esc->ruby-ui--combobox#closePopover:prevent
|
|
25
20
|
resize@window->ruby-ui--combobox#updatePopoverWidth
|
|
26
21
|
]
|
|
27
22
|
}
|
|
@@ -10,14 +10,7 @@ module RubyUI
|
|
|
10
10
|
|
|
11
11
|
def default_attrs
|
|
12
12
|
{
|
|
13
|
-
class:
|
|
14
|
-
"aspect-square h-4 w-4 rounded-full border border-primary accent-primary text-primary shadow",
|
|
15
|
-
"focus:outline-none",
|
|
16
|
-
"focus-visible:ring-1 focus-visible:ring-ring",
|
|
17
|
-
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
18
|
-
"checked:bg-primary checked:text-primary-foreground",
|
|
19
|
-
"aria-disabled:cursor-not-allowed aria-disabled:opacity-50 aria-disabled:pointer-events-none"
|
|
20
|
-
],
|
|
13
|
+
class: "peer sr-only",
|
|
21
14
|
data: {
|
|
22
15
|
ruby_ui__combobox_target: "input",
|
|
23
16
|
ruby_ui__form_field_target: "input",
|
|
@@ -10,13 +10,7 @@ module RubyUI
|
|
|
10
10
|
|
|
11
11
|
def default_attrs
|
|
12
12
|
{
|
|
13
|
-
class:
|
|
14
|
-
"peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background accent-primary",
|
|
15
|
-
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
16
|
-
"checked:bg-primary checked:text-primary-foreground",
|
|
17
|
-
"aria-disabled:cursor-not-allowed aria-disabled:opacity-50 aria-disabled:pointer-events-none",
|
|
18
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
|
19
|
-
],
|
|
13
|
+
class: "peer sr-only disabled:cursor-not-allowed",
|
|
20
14
|
data: {
|
|
21
15
|
ruby_ui__combobox_target: "toggleAll",
|
|
22
16
|
action: "change->ruby-ui--combobox#toggleAllItems"
|
|
@@ -9,7 +9,7 @@ module RubyUI
|
|
|
9
9
|
|
|
10
10
|
def view_template
|
|
11
11
|
button(**attrs) do
|
|
12
|
-
span(class: "truncate", data: {ruby_ui__combobox_target: "triggerContent"}) do
|
|
12
|
+
span(class: "truncate text-muted-foreground", data: {ruby_ui__combobox_target: "triggerContent"}) do
|
|
13
13
|
@placeholder
|
|
14
14
|
end
|
|
15
15
|
icon
|
|
@@ -26,12 +26,13 @@ module RubyUI
|
|
|
26
26
|
"hover:bg-accent hover:text-accent-foreground",
|
|
27
27
|
"disabled:pointer-events-none disabled:opacity-50",
|
|
28
28
|
"aria-disabled:pointer-events-none aria-disabled:opacity-50 aria-disabled:cursor-not-allowed",
|
|
29
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
|
29
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
30
|
+
"aria-invalid:border-destructive"
|
|
30
31
|
],
|
|
31
32
|
data: {
|
|
32
33
|
placeholder: @placeholder,
|
|
33
34
|
ruby_ui__combobox_target: "trigger",
|
|
34
|
-
action: "ruby-ui--combobox#togglePopover"
|
|
35
|
+
action: "click->ruby-ui--combobox#togglePopover focus->ruby-ui--combobox#openPopover"
|
|
35
36
|
},
|
|
36
37
|
aria: {
|
|
37
38
|
haspopup: "listbox",
|
|
@@ -41,22 +42,21 @@ module RubyUI
|
|
|
41
42
|
end
|
|
42
43
|
|
|
43
44
|
def icon
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
)
|
|
45
|
+
span(class: "shrink-0 flex items-center justify-center size-6 rounded-sm hover:bg-muted hover:text-foreground") do
|
|
46
|
+
svg(
|
|
47
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
48
|
+
width: "24",
|
|
49
|
+
height: "24",
|
|
50
|
+
viewbox: "0 0 24 24",
|
|
51
|
+
fill: "none",
|
|
52
|
+
stroke: "currentColor",
|
|
53
|
+
stroke_width: "2",
|
|
54
|
+
stroke_linecap: "round",
|
|
55
|
+
stroke_linejoin: "round",
|
|
56
|
+
class: "pointer-events-none size-4 text-muted-foreground"
|
|
57
|
+
) do |s|
|
|
58
|
+
s.path(d: "m6 9 6 6 6-6")
|
|
59
|
+
end
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RubyUI
|
|
4
|
+
class DataTable < Base
|
|
5
|
+
register_element :turbo_frame, tag: "turbo-frame"
|
|
6
|
+
|
|
7
|
+
def initialize(id:, **attrs)
|
|
8
|
+
@id = id
|
|
9
|
+
super(**attrs)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def view_template(&block)
|
|
13
|
+
turbo_frame(id: @id, target: "_top") do
|
|
14
|
+
div(**attrs) do
|
|
15
|
+
yield if block
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def default_attrs
|
|
23
|
+
{
|
|
24
|
+
class: "w-full space-y-4",
|
|
25
|
+
data: {controller: "ruby-ui--data-table"}
|
|
26
|
+
}
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RubyUI
|
|
4
|
+
class DataTableBulkActions < Base
|
|
5
|
+
def view_template(&)
|
|
6
|
+
div(**attrs, &)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def default_attrs
|
|
12
|
+
{
|
|
13
|
+
class: "hidden items-center gap-2",
|
|
14
|
+
data: {"ruby-ui--data-table-target": "bulkActions"}
|
|
15
|
+
}
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|