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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/ruby_ui/component_generator.rb +5 -1
  3. data/lib/generators/ruby_ui/dependencies.yml +10 -0
  4. data/lib/generators/ruby_ui/install/install_generator.rb +1 -1
  5. data/lib/generators/ruby_ui/javascript_utils.rb +4 -0
  6. data/lib/ruby_ui/combobox/combobox.rb +7 -1
  7. data/lib/ruby_ui/combobox/combobox_badge.rb +17 -0
  8. data/lib/ruby_ui/combobox/combobox_badge_trigger.rb +47 -0
  9. data/lib/ruby_ui/combobox/combobox_checkbox.rb +1 -7
  10. data/lib/ruby_ui/combobox/combobox_clear_button.rb +40 -0
  11. data/lib/ruby_ui/combobox/combobox_controller.js +243 -53
  12. data/lib/ruby_ui/combobox/combobox_docs.rb +199 -64
  13. data/lib/ruby_ui/combobox/combobox_input_trigger.rb +64 -0
  14. data/lib/ruby_ui/combobox/combobox_item.rb +5 -7
  15. data/lib/ruby_ui/combobox/combobox_item_indicator.rb +30 -0
  16. data/lib/ruby_ui/combobox/combobox_list_group.rb +1 -1
  17. data/lib/ruby_ui/combobox/combobox_popover.rb +0 -5
  18. data/lib/ruby_ui/combobox/combobox_radio.rb +1 -8
  19. data/lib/ruby_ui/combobox/combobox_toggle_all_checkbox.rb +1 -7
  20. data/lib/ruby_ui/combobox/combobox_trigger.rb +19 -19
  21. data/lib/ruby_ui/data_table/data_table.rb +29 -0
  22. data/lib/ruby_ui/data_table/data_table_bulk_actions.rb +18 -0
  23. data/lib/ruby_ui/data_table/data_table_column_toggle.rb +62 -0
  24. data/lib/ruby_ui/data_table/data_table_column_visibility_controller.js +14 -0
  25. data/lib/ruby_ui/data_table/data_table_controller.js +57 -0
  26. data/lib/ruby_ui/data_table/data_table_docs.rb +180 -0
  27. data/lib/ruby_ui/data_table/data_table_expand_toggle.rb +53 -0
  28. data/lib/ruby_ui/data_table/data_table_form.rb +39 -0
  29. data/lib/ruby_ui/data_table/data_table_kaminari_adapter.rb +17 -0
  30. data/lib/ruby_ui/data_table/data_table_manual_adapter.rb +17 -0
  31. data/lib/ruby_ui/data_table/data_table_pagination.rb +100 -0
  32. data/lib/ruby_ui/data_table/data_table_pagination_bar.rb +15 -0
  33. data/lib/ruby_ui/data_table/data_table_pagy_adapter.rb +17 -0
  34. data/lib/ruby_ui/data_table/data_table_per_page_select.rb +35 -0
  35. data/lib/ruby_ui/data_table/data_table_row_checkbox.rb +30 -0
  36. data/lib/ruby_ui/data_table/data_table_search.rb +57 -0
  37. data/lib/ruby_ui/data_table/data_table_search_controller.js +62 -0
  38. data/lib/ruby_ui/data_table/data_table_select_all_checkbox.rb +21 -0
  39. data/lib/ruby_ui/data_table/data_table_selection_summary.rb +25 -0
  40. data/lib/ruby_ui/data_table/data_table_sort_head.rb +112 -0
  41. data/lib/ruby_ui/data_table/data_table_toolbar.rb +15 -0
  42. data/lib/ruby_ui/masked_input/masked_input.rb +11 -1
  43. data/lib/ruby_ui/masked_input/masked_input_controller.js +13 -0
  44. data/lib/ruby_ui/native_select/native_select.rb +39 -0
  45. data/lib/ruby_ui/native_select/native_select_docs.rb +83 -0
  46. data/lib/ruby_ui/native_select/native_select_group.rb +15 -0
  47. data/lib/ruby_ui/native_select/native_select_icon.rb +39 -0
  48. data/lib/ruby_ui/native_select/native_select_option.rb +15 -0
  49. data/lib/ruby_ui.rb +1 -1
  50. 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: "Single option", context: self) do
11
+ render Docs::VisualCodeExample.new(title: "Basic", context: self) do
14
12
  <<~RUBY
15
- div class: "w-96" do
13
+ div(class: "w-96") do
16
14
  Combobox do
17
- ComboboxTrigger placeholder: "Pick value"
15
+ ComboboxInputTrigger(placeholder: "Select framework...")
18
16
 
19
17
  ComboboxPopover do
20
- ComboboxSearchInput(placeholder: "Pick value or type anything")
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 result" }
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: "Vegetable") do
145
+ ComboboxListGroup(label: "Vegetables") do
38
146
  ComboboxItem do
39
- ComboboxRadio(name: "food", value: "brocoli")
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: "Others") do
156
+ ComboboxListGroup(label: "Grains") do
50
157
  ComboboxItem do
51
- ComboboxRadio(name: "food", value: "chocolate")
52
- span { "Chocolate" }
158
+ ComboboxRadio(name: "food", value: "rice")
159
+ span { "Rice" }
53
160
  end
54
-
55
161
  ComboboxItem do
56
- ComboboxRadio(name: "food", value: "milk")
57
- span { "Milk" }
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: "Multiple options", context: self) do
173
+ render Docs::VisualCodeExample.new(title: "Custom Items", context: self) do
68
174
  <<~RUBY
69
- div class: "w-96" do
70
- Combobox term: "things" do
71
- ComboboxTrigger placeholder: "Pick value"
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 result" }
181
+ ComboboxEmptyState { "No results found." }
78
182
 
79
- ComboboxItem(class: "mt-3") do
80
- ComboboxToggleAllCheckbox(name: "all", value: "all")
81
- span { "Select all" }
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
- ComboboxListGroup label: "Fruits" do
85
- ComboboxItem do
86
- ComboboxCheckbox(name: "food", value: "apple")
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
- ComboboxListGroup label: "Vegetable" do
97
- ComboboxItem do
98
- ComboboxCheckbox(name: "food", value: "brocoli")
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
- ComboboxListGroup label: "Others" do
109
- ComboboxItem do
110
- ComboboxCheckbox(name: "food", value: "chocolate")
111
- span { "Chocolate" }
112
- end
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
- ComboboxItem do
115
- ComboboxCheckbox(name: "food", value: "milk")
116
- span { "Milk" }
117
- end
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: "Pick value")
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: "Aria Disabled", context: self) do
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
- ComboboxTrigger(aria: {disabled: "true"}, placeholder: "Pick value")
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: "Combobox")
281
+ render Components::ComponentSetup::Tabs.new(component_name: component)
147
282
 
148
- render Docs::ComponentsTable.new(component_files("Combobox"))
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,7 +12,7 @@ module RubyUI
12
12
 
13
13
  def default_attrs
14
14
  {
15
- class: ["hidden has-[label:not(.hidden)]:flex flex-col py-1 gap-1 border-b", LABEL_CLASSES],
15
+ class: ["hidden has-[label:not(.hidden)]:flex flex-col py-1 gap-1", LABEL_CLASSES],
16
16
  role: "group"
17
17
  }
18
18
  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
- svg(
45
- xmlns: "http://www.w3.org/2000/svg",
46
- viewbox: "0 0 24 24",
47
- fill: "none",
48
- stroke: "currentColor",
49
- class: "ml-2 h-4 w-4 shrink-0 opacity-50",
50
- stroke_width: "2",
51
- stroke_linecap: "round",
52
- stroke_linejoin: "round"
53
- ) do |s|
54
- s.path(
55
- d: "m7 15 5 5 5-5"
56
- )
57
- s.path(
58
- d: "m7 9 5-5 5 5"
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