ruby_ui 1.0.0.pre.alpha.4

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 (166) hide show
  1. checksums.yaml +7 -0
  2. data/lib/generators/rbui/base_generator.rb +17 -0
  3. data/lib/generators/rbui/component_generator.rb +137 -0
  4. data/lib/generators/rbui/install/install_generator.rb +194 -0
  5. data/lib/rbui/accordion/accordion.rb +17 -0
  6. data/lib/rbui/accordion/accordion_content.rb +21 -0
  7. data/lib/rbui/accordion/accordion_default_content.rb +17 -0
  8. data/lib/rbui/accordion/accordion_default_trigger.rb +19 -0
  9. data/lib/rbui/accordion/accordion_icon.rb +38 -0
  10. data/lib/rbui/accordion/accordion_item.rb +28 -0
  11. data/lib/rbui/accordion/accordion_trigger.rb +16 -0
  12. data/lib/rbui/alert/alert.rb +36 -0
  13. data/lib/rbui/alert/alert_description.rb +17 -0
  14. data/lib/rbui/alert/alert_title.rb +17 -0
  15. data/lib/rbui/alert_dialog/alert_dialog.rb +26 -0
  16. data/lib/rbui/alert_dialog/alert_dialog_action.rb +17 -0
  17. data/lib/rbui/alert_dialog/alert_dialog_cancel.rb +21 -0
  18. data/lib/rbui/alert_dialog/alert_dialog_content.rb +45 -0
  19. data/lib/rbui/alert_dialog/alert_dialog_description.rb +17 -0
  20. data/lib/rbui/alert_dialog/alert_dialog_footer.rb +17 -0
  21. data/lib/rbui/alert_dialog/alert_dialog_header.rb +17 -0
  22. data/lib/rbui/alert_dialog/alert_dialog_title.rb +17 -0
  23. data/lib/rbui/alert_dialog/alert_dialog_trigger.rb +18 -0
  24. data/lib/rbui/aspect_ratio/aspect_ratio.rb +33 -0
  25. data/lib/rbui/avatar/avatar.rb +31 -0
  26. data/lib/rbui/avatar/avatar_fallback.rb +17 -0
  27. data/lib/rbui/avatar/avatar_image.rb +26 -0
  28. data/lib/rbui/badge/badge.rb +60 -0
  29. data/lib/rbui/base.rb +29 -0
  30. data/lib/rbui/button/button.rb +97 -0
  31. data/lib/rbui/calendar/calendar.rb +39 -0
  32. data/lib/rbui/calendar/calendar_body.rb +19 -0
  33. data/lib/rbui/calendar/calendar_days.rb +104 -0
  34. data/lib/rbui/calendar/calendar_header.rb +17 -0
  35. data/lib/rbui/calendar/calendar_next.rb +43 -0
  36. data/lib/rbui/calendar/calendar_prev.rb +43 -0
  37. data/lib/rbui/calendar/calendar_title.rb +27 -0
  38. data/lib/rbui/calendar/calendar_weekdays.rb +33 -0
  39. data/lib/rbui/card/card.rb +17 -0
  40. data/lib/rbui/card/card_content.rb +17 -0
  41. data/lib/rbui/card/card_description.rb +17 -0
  42. data/lib/rbui/card/card_footer.rb +17 -0
  43. data/lib/rbui/card/card_header.rb +17 -0
  44. data/lib/rbui/card/card_title.rb +17 -0
  45. data/lib/rbui/chart/chart.rb +23 -0
  46. data/lib/rbui/checkbox/checkbox.rb +23 -0
  47. data/lib/rbui/checkbox/checkbox_group.rb +20 -0
  48. data/lib/rbui/clipboard/clipboard.rb +42 -0
  49. data/lib/rbui/clipboard/clipboard_popover.rb +40 -0
  50. data/lib/rbui/clipboard/clipboard_source.rb +19 -0
  51. data/lib/rbui/clipboard/clipboard_trigger.rb +20 -0
  52. data/lib/rbui/codeblock/codeblock.rb +105 -0
  53. data/lib/rbui/collapsible/collapsible.rb +25 -0
  54. data/lib/rbui/collapsible/collapsible_content.rb +18 -0
  55. data/lib/rbui/collapsible/collapsible_trigger.rb +19 -0
  56. data/lib/rbui/combobox/combobox.rb +24 -0
  57. data/lib/rbui/combobox/combobox_content.rb +31 -0
  58. data/lib/rbui/combobox/combobox_empty.rb +21 -0
  59. data/lib/rbui/combobox/combobox_group.rb +38 -0
  60. data/lib/rbui/combobox/combobox_input.rb +22 -0
  61. data/lib/rbui/combobox/combobox_item.rb +53 -0
  62. data/lib/rbui/combobox/combobox_list.rb +29 -0
  63. data/lib/rbui/combobox/combobox_search_input.rb +56 -0
  64. data/lib/rbui/combobox/combobox_separator.rb +15 -0
  65. data/lib/rbui/combobox/combobox_trigger.rb +52 -0
  66. data/lib/rbui/combobox/combobox_value.rb +27 -0
  67. data/lib/rbui/command/command.rb +9 -0
  68. data/lib/rbui/command/command_dialog.rb +17 -0
  69. data/lib/rbui/command/command_dialog_content.rb +48 -0
  70. data/lib/rbui/command/command_dialog_trigger.rb +29 -0
  71. data/lib/rbui/command/command_empty.rb +19 -0
  72. data/lib/rbui/command/command_group.rb +40 -0
  73. data/lib/rbui/command/command_input.rb +56 -0
  74. data/lib/rbui/command/command_item.rb +32 -0
  75. data/lib/rbui/command/command_list.rb +17 -0
  76. data/lib/rbui/context_menu/context_menu.rb +26 -0
  77. data/lib/rbui/context_menu/context_menu_content.rb +25 -0
  78. data/lib/rbui/context_menu/context_menu_item.rb +66 -0
  79. data/lib/rbui/context_menu/context_menu_label.rb +24 -0
  80. data/lib/rbui/context_menu/context_menu_separator.rb +19 -0
  81. data/lib/rbui/context_menu/context_menu_trigger.rb +20 -0
  82. data/lib/rbui/dialog/dialog.rb +25 -0
  83. data/lib/rbui/dialog/dialog_content.rb +78 -0
  84. data/lib/rbui/dialog/dialog_description.rb +17 -0
  85. data/lib/rbui/dialog/dialog_footer.rb +17 -0
  86. data/lib/rbui/dialog/dialog_header.rb +17 -0
  87. data/lib/rbui/dialog/dialog_middle.rb +17 -0
  88. data/lib/rbui/dialog/dialog_title.rb +17 -0
  89. data/lib/rbui/dialog/dialog_trigger.rb +20 -0
  90. data/lib/rbui/dropdown_menu/dropdown_menu.rb +26 -0
  91. data/lib/rbui/dropdown_menu/dropdown_menu_content.rb +22 -0
  92. data/lib/rbui/dropdown_menu/dropdown_menu_item.rb +28 -0
  93. data/lib/rbui/dropdown_menu/dropdown_menu_label.rb +17 -0
  94. data/lib/rbui/dropdown_menu/dropdown_menu_separator.rb +19 -0
  95. data/lib/rbui/dropdown_menu/dropdown_menu_trigger.rb +18 -0
  96. data/lib/rbui/form/form.rb +15 -0
  97. data/lib/rbui/form/form_field.rb +20 -0
  98. data/lib/rbui/form/form_field_error.rb +20 -0
  99. data/lib/rbui/form/form_field_hint.rb +15 -0
  100. data/lib/rbui/form/form_field_label.rb +15 -0
  101. data/lib/rbui/hover_card/hover_card.rb +27 -0
  102. data/lib/rbui/hover_card/hover_card_content.rb +22 -0
  103. data/lib/rbui/hover_card/hover_card_trigger.rb +20 -0
  104. data/lib/rbui/input/input.rb +26 -0
  105. data/lib/rbui/link/link.rb +97 -0
  106. data/lib/rbui/pagination/pagination.rb +19 -0
  107. data/lib/rbui/pagination/pagination_content.rb +17 -0
  108. data/lib/rbui/pagination/pagination_ellipsis.rb +42 -0
  109. data/lib/rbui/pagination/pagination_item.rb +28 -0
  110. data/lib/rbui/popover/popover.rb +26 -0
  111. data/lib/rbui/popover/popover_content.rb +27 -0
  112. data/lib/rbui/popover/popover_trigger.rb +20 -0
  113. data/lib/rbui/radio_button/radio_button.rb +22 -0
  114. data/lib/rbui/railtie.rb +52 -0
  115. data/lib/rbui/select/select.rb +23 -0
  116. data/lib/rbui/select/select_content.rb +32 -0
  117. data/lib/rbui/select/select_group.rb +15 -0
  118. data/lib/rbui/select/select_input.rb +22 -0
  119. data/lib/rbui/select/select_item.rb +52 -0
  120. data/lib/rbui/select/select_label.rb +17 -0
  121. data/lib/rbui/select/select_trigger.rb +54 -0
  122. data/lib/rbui/select/select_value.rb +27 -0
  123. data/lib/rbui/sheet/sheet.rb +17 -0
  124. data/lib/rbui/sheet/sheet_content.rb +77 -0
  125. data/lib/rbui/sheet/sheet_description.rb +17 -0
  126. data/lib/rbui/sheet/sheet_footer.rb +17 -0
  127. data/lib/rbui/sheet/sheet_header.rb +17 -0
  128. data/lib/rbui/sheet/sheet_middle.rb +17 -0
  129. data/lib/rbui/sheet/sheet_title.rb +17 -0
  130. data/lib/rbui/sheet/sheet_trigger.rb +17 -0
  131. data/lib/rbui/shortcut_key/shortcut_key.rb +17 -0
  132. data/lib/rbui/table/table.rb +19 -0
  133. data/lib/rbui/table/table_body.rb +17 -0
  134. data/lib/rbui/table/table_caption.rb +17 -0
  135. data/lib/rbui/table/table_cell.rb +17 -0
  136. data/lib/rbui/table/table_footer.rb +17 -0
  137. data/lib/rbui/table/table_head.rb +17 -0
  138. data/lib/rbui/table/table_header.rb +17 -0
  139. data/lib/rbui/table/table_row.rb +17 -0
  140. data/lib/rbui/tabs/tabs.rb +25 -0
  141. data/lib/rbui/tabs/tabs_content.rb +26 -0
  142. data/lib/rbui/tabs/tabs_list.rb +17 -0
  143. data/lib/rbui/tabs/tabs_trigger.rb +28 -0
  144. data/lib/rbui/textarea/textarea.rb +26 -0
  145. data/lib/rbui/theme_toggle/theme_toggle.rb +41 -0
  146. data/lib/rbui/tooltip/tooltip.rb +26 -0
  147. data/lib/rbui/tooltip/tooltip_content.rb +26 -0
  148. data/lib/rbui/tooltip/tooltip_trigger.rb +19 -0
  149. data/lib/rbui/typography/typography_blockquote.rb +17 -0
  150. data/lib/rbui/typography/typography_h1.rb +17 -0
  151. data/lib/rbui/typography/typography_h2.rb +17 -0
  152. data/lib/rbui/typography/typography_h3.rb +17 -0
  153. data/lib/rbui/typography/typography_h4.rb +17 -0
  154. data/lib/rbui/typography/typography_inline_code.rb +17 -0
  155. data/lib/rbui/typography/typography_inline_link.rb +22 -0
  156. data/lib/rbui/typography/typography_large.rb +17 -0
  157. data/lib/rbui/typography/typography_lead.rb +17 -0
  158. data/lib/rbui/typography/typography_list.rb +47 -0
  159. data/lib/rbui/typography/typography_list_item.rb +17 -0
  160. data/lib/rbui/typography/typography_muted.rb +17 -0
  161. data/lib/rbui/typography/typography_p.rb +17 -0
  162. data/lib/rbui/typography/typography_small.rb +17 -0
  163. data/lib/rbui/version.rb +5 -0
  164. data/lib/rbui.rb +57 -0
  165. data/lib/ruby_ui.rb +1 -0
  166. metadata +291 -0
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBUI
4
+ class Link < Base
5
+ def initialize(href: "#", variant: :link, size: :md, icon: false, **attrs)
6
+ @href = href
7
+ @variant = variant.to_sym
8
+ @size = size.to_sym
9
+ @icon = icon
10
+ super(**attrs)
11
+ end
12
+
13
+ def view_template(&)
14
+ a(href: @href, **attrs, &)
15
+ end
16
+
17
+ private
18
+
19
+ def size_classes
20
+ if @icon
21
+ case @size
22
+ when :sm then "h-6 w-6"
23
+ when :md then "h-9 w-9"
24
+ when :lg then "h-10 w-10"
25
+ when :xl then "h-12 w-12"
26
+ end
27
+ else
28
+ case @size
29
+ when :sm then "px-3 py-1.5 h-8 text-xs"
30
+ when :md then "px-4 py-2 h-9 text-sm"
31
+ when :lg then "px-4 py-2 h-10 text-base"
32
+ when :xl then "px-6 py-3 h-12 text-base"
33
+ end
34
+ end
35
+ end
36
+
37
+ def primary_classes
38
+ tokens(
39
+ "whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground shadow hover:bg-primary/90",
40
+ size_classes
41
+ )
42
+ end
43
+
44
+ def link_classes
45
+ tokens(
46
+ "whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 text-primary underline-offset-4 hover:underline",
47
+ size_classes
48
+ )
49
+ end
50
+
51
+ def secondary_classes
52
+ tokens(
53
+ "whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-secondary text-secondary-foreground hover:bg-opacity-80",
54
+ size_classes
55
+ )
56
+ end
57
+
58
+ def destructive_classes
59
+ tokens(
60
+ "whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
61
+ size_classes
62
+ )
63
+ end
64
+
65
+ def outline_classes
66
+ tokens(
67
+ "whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
68
+ size_classes
69
+ )
70
+ end
71
+
72
+ def ghost_classes
73
+ tokens(
74
+ "whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 hover:bg-accent hover:text-accent-foreground",
75
+ size_classes
76
+ )
77
+ end
78
+
79
+ def default_classes
80
+ case @variant
81
+ when :primary then primary_classes
82
+ when :link then link_classes
83
+ when :secondary then secondary_classes
84
+ when :destructive then destructive_classes
85
+ when :outline then outline_classes
86
+ when :ghost then ghost_classes
87
+ end
88
+ end
89
+
90
+ def default_attrs
91
+ {
92
+ type: "button",
93
+ class: default_classes
94
+ }
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBUI
4
+ class Pagination < Base
5
+ def view_template(&)
6
+ nav(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ aria: {label: "pagination"},
14
+ class: "mx-auto flex w-full justify-center",
15
+ role: "navigation"
16
+ }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBUI
4
+ class PaginationContent < Base
5
+ def view_template(&)
6
+ ul(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "flex flex-row items-center gap-1"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBUI
4
+ class PaginationEllipsis < Base
5
+ def view_template(&block)
6
+ li do
7
+ span(**attrs) do
8
+ icon
9
+ span(class: "sr-only") { "More pages" }
10
+ end
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def icon
17
+ svg(
18
+ xmlns: "http://www.w3.org/2000/svg",
19
+ width: "24",
20
+ height: "24",
21
+ viewbox: "0 0 24 24",
22
+ fill: "none",
23
+ stroke: "currentColor",
24
+ stroke_width: "2",
25
+ stroke_linecap: "round",
26
+ stroke_linejoin: "round",
27
+ class: "h-4 w-4"
28
+ ) do |s|
29
+ s.circle(cx: "12", cy: "12", r: "1")
30
+ s.circle(cx: "19", cy: "12", r: "1")
31
+ s.circle(cx: "5", cy: "12", r: "1")
32
+ end
33
+ end
34
+
35
+ def default_attrs
36
+ {
37
+ aria: {hidden: true},
38
+ class: "flex h-9 w-9 items-center justify-center"
39
+ }
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBUI
4
+ class PaginationItem < Base
5
+ def initialize(href: "#", active: false, **attrs)
6
+ @href = href
7
+ @active = active
8
+ super(**attrs)
9
+ end
10
+
11
+ def view_template(&block)
12
+ li do
13
+ a(href: @href, **attrs, &block)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def default_attrs
20
+ {
21
+ aria: {current: @active ? "page" : nil},
22
+ class: tokens(
23
+ RBUI::Button.new(variant: @active ? :outline : :ghost).attrs[:class]
24
+ )
25
+ }
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBUI
4
+ class Popover < Base
5
+ def initialize(options: {}, **attrs)
6
+ @options = options
7
+ super(**attrs)
8
+ end
9
+
10
+ def view_template(&)
11
+ div(**attrs, &)
12
+ end
13
+
14
+ private
15
+
16
+ def default_attrs
17
+ {
18
+ data: {
19
+ controller: "rbui--popover",
20
+ rbui__popover_options_value: @options.to_json,
21
+ rbui__popover_trigger_value: @options[:trigger] || "hover"
22
+ }
23
+ }
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBUI
4
+ class PopoverContent < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ data: {
14
+ rbui__popover_target: "content"
15
+ },
16
+ class: [
17
+ "hidden z-50 rounded-md border bg-background p-1 text-foreground shadow-md outline-none",
18
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0",
19
+ "data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
20
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
21
+ "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
22
+ "absolute"
23
+ ]
24
+ }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBUI
4
+ class PopoverTrigger < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ data: {
14
+ rbui__popover_target: "trigger"
15
+ },
16
+ class: "inline-block"
17
+ }
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBUI
4
+ class RadioButton < Base
5
+ def view_template
6
+ input(**attrs)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ type: "radio",
14
+ data: {
15
+ rbui__form_field_target: "input",
16
+ action: "input->rbui--form-field#onInput invalid->rbui--form-field#onInvalid"
17
+ },
18
+ class: "h-4 w-4 p-0 border-primary rounded-full flex-none"
19
+ }
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,52 @@
1
+ module RBUI
2
+ if defined?(Rails)
3
+ class Railtie < ::Rails::Railtie
4
+ generators do
5
+ require_relative "../generators/rbui/install/install_generator"
6
+
7
+ config.app_generators do |g|
8
+ g.templates.unshift File.expand_path("../templates", __FILE__)
9
+ end
10
+
11
+ initializer "rbui.set_generator_namespace" do
12
+ Rails::Generators.namespace(RBUI::Generators, as: "rbui")
13
+ end
14
+ end
15
+
16
+ # Add component loading
17
+ config.to_prepare do
18
+ # Define the path to the RBUI components
19
+ rbui_components_path = Rails.root.join("app/components/rbui")
20
+
21
+ # Check if the RBUI components directory exists
22
+ if Dir.exist?(rbui_components_path)
23
+ # Find all Ruby files in the RBUI components directory and its subdirectories
24
+ Dir[rbui_components_path.join("**", "*.rb")].each do |file|
25
+ # Get the relative path of the file from the RBUI components directory
26
+ relative_path = Pathname.new(file).relative_path_from(rbui_components_path)
27
+
28
+ # Convert the file path to a component name
29
+ # e.g., "form/input.rb" becomes ["Form", "Input"]
30
+ component_name_parts = relative_path.to_s.chomp(".rb").split("/").map(&:camelize)
31
+
32
+ # Create the full component name with RBUI namespace
33
+ # e.g., "RBUI::Form::Input"
34
+ full_component_name = "RBUI::#{component_name_parts.join("::")}"
35
+
36
+ begin
37
+ # Check if the component is already defined
38
+ if defined?(full_component_name.constantize)
39
+ # If it's defined, load (or reload) the file
40
+ load file
41
+ end
42
+ rescue NameError
43
+ # If the constant isn't defined (i.e., the component doesn't exist),
44
+ # we'll skip this file and move to the next one
45
+ next
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBUI
4
+ class Select < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ data: {
14
+ controller: "rbui--select",
15
+ rbui__select_open_value: "false",
16
+ action: "click@window->rbui--select#clickOutside",
17
+ rbui__select_rbui__select_item_outlet: ".item"
18
+ },
19
+ class: "group/select w-full relative"
20
+ }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBUI
4
+ class SelectContent < Base
5
+ def initialize(**attrs)
6
+ @id = "content#{SecureRandom.hex(4)}"
7
+ super
8
+ end
9
+
10
+ def view_template(&block)
11
+ div(**attrs) do
12
+ div(
13
+ class: "max-h-96 min-w-max overflow-auto rounded-md border bg-background p-1 text-foreground shadow-md animate-out group-data-[rbui--select-open-value=true]/select:animate-in fade-out-0 group-data-[rbui--select-open-value=true]/select:fade-in-0 zoom-out-95 group-data-[rbui--select-open-value=true]/select:zoom-in-95 slide-in-from-top-2", &block
14
+ )
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def default_attrs
21
+ {
22
+ id: @id,
23
+ role: "listbox",
24
+ tabindex: "-1",
25
+ data: {
26
+ rbui__select_target: "content"
27
+ },
28
+ class: "hidden w-full absolute top-0 left-0 z-50"
29
+ }
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBUI
4
+ class SelectGroup < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {}
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBUI
4
+ class SelectInput < Base
5
+ def view_template
6
+ input(**attrs)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "hidden",
14
+ data: {
15
+ rbui__select_target: "input",
16
+ rbui__form_field_target: "input",
17
+ action: "change->rbui--form-field#onChange invalid->rbui--form-field#onInvalid"
18
+ }
19
+ }
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBUI
4
+ class SelectItem < Base
5
+ def initialize(value: nil, **attrs)
6
+ @value = value
7
+ super(**attrs)
8
+ end
9
+
10
+ def view_template(&block)
11
+ div(**attrs) do
12
+ selected_icon
13
+ block&.call
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def selected_icon
20
+ svg(
21
+ xmlns: "http://www.w3.org/2000/svg",
22
+ viewbox: "0 0 24 24",
23
+ fill: "none",
24
+ stroke: "currentColor",
25
+ class: "invisible group-aria-selected:visible mr-2 h-4 w-4 flex-none",
26
+ stroke_width: "2",
27
+ stroke_linecap: "round",
28
+ stroke_linejoin: "round"
29
+ ) do |s|
30
+ s.path(
31
+ d: "M20 6 9 17l-5-5"
32
+ )
33
+ end
34
+ end
35
+
36
+ def default_attrs
37
+ {
38
+ role: "option",
39
+ tabindex: "0",
40
+ class: "item group relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
41
+ data: {
42
+ controller: "rbui--select-item",
43
+ action: "click->rbui--select#selectItem keydown.enter->rbui--select#selectItem keydown.down->rbui--select#handleKeyDown keydown.up->rbui--select#handleKeyUp keydown.esc->rbui--select#handleEsc",
44
+ rbui__select_target: "item"
45
+ },
46
+ data_value: @value,
47
+ data_orientation: "vertical",
48
+ aria_selected: "false"
49
+ }
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBUI
4
+ class SelectLabel < Base
5
+ def view_template(&)
6
+ h3(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "px-2 py-1.5 text-sm font-semibold"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBUI
4
+ class SelectTrigger < Base
5
+ def view_template(&block)
6
+ button(**attrs) do
7
+ block&.call
8
+ icon
9
+ end
10
+ end
11
+
12
+ private
13
+
14
+ def icon
15
+ svg(
16
+ xmlns: "http://www.w3.org/2000/svg",
17
+ viewbox: "0 0 24 24",
18
+ fill: "none",
19
+ stroke: "currentColor",
20
+ class: "ml-2 h-4 w-4 shrink-0 opacity-50",
21
+ stroke_width: "2",
22
+ stroke_linecap: "round",
23
+ stroke_linejoin: "round"
24
+ ) do |s|
25
+ s.path(
26
+ d: "m7 15 5 5 5-5"
27
+ )
28
+ s.path(
29
+ d: "m7 9 5-5 5 5"
30
+ )
31
+ end
32
+ end
33
+
34
+ def default_attrs
35
+ {
36
+ data: {
37
+ action: "rbui--select#onClick",
38
+ rbui__select_target: "trigger"
39
+ },
40
+ type: "button",
41
+ role: "combobox",
42
+ aria: {
43
+ controls: "radix-:r0:",
44
+ expanded: "false",
45
+ autocomplete: "none",
46
+ haspopup: "listbox",
47
+ activedescendant: true
48
+ },
49
+ class:
50
+ "truncate w-full flex h-9 items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
51
+ }
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBUI
4
+ class SelectValue < Base
5
+ def initialize(placeholder: nil, **attrs)
6
+ @placeholder = placeholder
7
+ super(**attrs)
8
+ end
9
+
10
+ def view_template(&block)
11
+ span(**attrs) do
12
+ block ? block.call : @placeholder
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def default_attrs
19
+ {
20
+ data: {
21
+ rbui__select_target: "value"
22
+ },
23
+ class: "pointer-events-none"
24
+ }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBUI
4
+ class Sheet < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ data: {controller: "rbui--sheet"}
14
+ }
15
+ end
16
+ end
17
+ end