ruby_ui 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. checksums.yaml +7 -0
  2. data/lib/generators/ruby_ui/component_generator.rb +130 -0
  3. data/lib/generators/ruby_ui/install/install_generator.rb +90 -0
  4. data/lib/generators/ruby_ui/javascript_utils.rb +36 -0
  5. data/lib/ruby_ui/accordion/accordion.rb +17 -0
  6. data/lib/ruby_ui/accordion/accordion_content.rb +21 -0
  7. data/lib/ruby_ui/accordion/accordion_default_content.rb +17 -0
  8. data/lib/ruby_ui/accordion/accordion_default_trigger.rb +19 -0
  9. data/lib/ruby_ui/accordion/accordion_icon.rb +38 -0
  10. data/lib/ruby_ui/accordion/accordion_item.rb +28 -0
  11. data/lib/ruby_ui/accordion/accordion_trigger.rb +17 -0
  12. data/lib/ruby_ui/alert/alert.rb +36 -0
  13. data/lib/ruby_ui/alert/alert_description.rb +17 -0
  14. data/lib/ruby_ui/alert/alert_title.rb +17 -0
  15. data/lib/ruby_ui/alert_dialog/alert_dialog.rb +26 -0
  16. data/lib/ruby_ui/alert_dialog/alert_dialog_action.rb +17 -0
  17. data/lib/ruby_ui/alert_dialog/alert_dialog_cancel.rb +21 -0
  18. data/lib/ruby_ui/alert_dialog/alert_dialog_content.rb +45 -0
  19. data/lib/ruby_ui/alert_dialog/alert_dialog_description.rb +17 -0
  20. data/lib/ruby_ui/alert_dialog/alert_dialog_footer.rb +17 -0
  21. data/lib/ruby_ui/alert_dialog/alert_dialog_header.rb +17 -0
  22. data/lib/ruby_ui/alert_dialog/alert_dialog_title.rb +17 -0
  23. data/lib/ruby_ui/alert_dialog/alert_dialog_trigger.rb +18 -0
  24. data/lib/ruby_ui/aspect_ratio/aspect_ratio.rb +33 -0
  25. data/lib/ruby_ui/avatar/avatar.rb +31 -0
  26. data/lib/ruby_ui/avatar/avatar_fallback.rb +17 -0
  27. data/lib/ruby_ui/avatar/avatar_image.rb +26 -0
  28. data/lib/ruby_ui/badge/badge.rb +60 -0
  29. data/lib/ruby_ui/base.rb +22 -0
  30. data/lib/ruby_ui/button/button.rb +97 -0
  31. data/lib/ruby_ui/calendar/calendar.rb +39 -0
  32. data/lib/ruby_ui/calendar/calendar_body.rb +19 -0
  33. data/lib/ruby_ui/calendar/calendar_days.rb +104 -0
  34. data/lib/ruby_ui/calendar/calendar_header.rb +17 -0
  35. data/lib/ruby_ui/calendar/calendar_next.rb +43 -0
  36. data/lib/ruby_ui/calendar/calendar_prev.rb +43 -0
  37. data/lib/ruby_ui/calendar/calendar_title.rb +27 -0
  38. data/lib/ruby_ui/calendar/calendar_weekdays.rb +33 -0
  39. data/lib/ruby_ui/card/card.rb +17 -0
  40. data/lib/ruby_ui/card/card_content.rb +17 -0
  41. data/lib/ruby_ui/card/card_description.rb +17 -0
  42. data/lib/ruby_ui/card/card_footer.rb +17 -0
  43. data/lib/ruby_ui/card/card_header.rb +17 -0
  44. data/lib/ruby_ui/card/card_title.rb +17 -0
  45. data/lib/ruby_ui/chart/chart.rb +23 -0
  46. data/lib/ruby_ui/checkbox/checkbox.rb +23 -0
  47. data/lib/ruby_ui/checkbox/checkbox_group.rb +20 -0
  48. data/lib/ruby_ui/clipboard/clipboard.rb +42 -0
  49. data/lib/ruby_ui/clipboard/clipboard_popover.rb +40 -0
  50. data/lib/ruby_ui/clipboard/clipboard_source.rb +19 -0
  51. data/lib/ruby_ui/clipboard/clipboard_trigger.rb +20 -0
  52. data/lib/ruby_ui/codeblock/codeblock.rb +102 -0
  53. data/lib/ruby_ui/collapsible/collapsible.rb +25 -0
  54. data/lib/ruby_ui/collapsible/collapsible_content.rb +18 -0
  55. data/lib/ruby_ui/collapsible/collapsible_trigger.rb +19 -0
  56. data/lib/ruby_ui/combobox/combobox.rb +24 -0
  57. data/lib/ruby_ui/combobox/combobox_content.rb +31 -0
  58. data/lib/ruby_ui/combobox/combobox_empty.rb +21 -0
  59. data/lib/ruby_ui/combobox/combobox_group.rb +38 -0
  60. data/lib/ruby_ui/combobox/combobox_input.rb +22 -0
  61. data/lib/ruby_ui/combobox/combobox_item.rb +53 -0
  62. data/lib/ruby_ui/combobox/combobox_list.rb +27 -0
  63. data/lib/ruby_ui/combobox/combobox_search_input.rb +56 -0
  64. data/lib/ruby_ui/combobox/combobox_separator.rb +15 -0
  65. data/lib/ruby_ui/combobox/combobox_trigger.rb +52 -0
  66. data/lib/ruby_ui/combobox/combobox_value.rb +27 -0
  67. data/lib/ruby_ui/command/command.rb +9 -0
  68. data/lib/ruby_ui/command/command_dialog.rb +17 -0
  69. data/lib/ruby_ui/command/command_dialog_content.rb +48 -0
  70. data/lib/ruby_ui/command/command_dialog_trigger.rb +29 -0
  71. data/lib/ruby_ui/command/command_empty.rb +19 -0
  72. data/lib/ruby_ui/command/command_group.rb +40 -0
  73. data/lib/ruby_ui/command/command_input.rb +56 -0
  74. data/lib/ruby_ui/command/command_item.rb +32 -0
  75. data/lib/ruby_ui/command/command_list.rb +17 -0
  76. data/lib/ruby_ui/context_menu/context_menu.rb +26 -0
  77. data/lib/ruby_ui/context_menu/context_menu_content.rb +25 -0
  78. data/lib/ruby_ui/context_menu/context_menu_item.rb +66 -0
  79. data/lib/ruby_ui/context_menu/context_menu_label.rb +24 -0
  80. data/lib/ruby_ui/context_menu/context_menu_separator.rb +19 -0
  81. data/lib/ruby_ui/context_menu/context_menu_trigger.rb +20 -0
  82. data/lib/ruby_ui/dialog/dialog.rb +25 -0
  83. data/lib/ruby_ui/dialog/dialog_content.rb +78 -0
  84. data/lib/ruby_ui/dialog/dialog_description.rb +17 -0
  85. data/lib/ruby_ui/dialog/dialog_footer.rb +17 -0
  86. data/lib/ruby_ui/dialog/dialog_header.rb +17 -0
  87. data/lib/ruby_ui/dialog/dialog_middle.rb +17 -0
  88. data/lib/ruby_ui/dialog/dialog_title.rb +17 -0
  89. data/lib/ruby_ui/dialog/dialog_trigger.rb +20 -0
  90. data/lib/ruby_ui/dropdown_menu/dropdown_menu.rb +26 -0
  91. data/lib/ruby_ui/dropdown_menu/dropdown_menu_content.rb +22 -0
  92. data/lib/ruby_ui/dropdown_menu/dropdown_menu_item.rb +28 -0
  93. data/lib/ruby_ui/dropdown_menu/dropdown_menu_label.rb +17 -0
  94. data/lib/ruby_ui/dropdown_menu/dropdown_menu_separator.rb +19 -0
  95. data/lib/ruby_ui/dropdown_menu/dropdown_menu_trigger.rb +18 -0
  96. data/lib/ruby_ui/form/form.rb +15 -0
  97. data/lib/ruby_ui/form/form_field.rb +20 -0
  98. data/lib/ruby_ui/form/form_field_error.rb +20 -0
  99. data/lib/ruby_ui/form/form_field_hint.rb +15 -0
  100. data/lib/ruby_ui/form/form_field_label.rb +15 -0
  101. data/lib/ruby_ui/hover_card/hover_card.rb +27 -0
  102. data/lib/ruby_ui/hover_card/hover_card_content.rb +22 -0
  103. data/lib/ruby_ui/hover_card/hover_card_trigger.rb +20 -0
  104. data/lib/ruby_ui/input/input.rb +26 -0
  105. data/lib/ruby_ui/link/link.rb +97 -0
  106. data/lib/ruby_ui/masked_input/masked_input.rb +15 -0
  107. data/lib/ruby_ui/pagination/pagination.rb +19 -0
  108. data/lib/ruby_ui/pagination/pagination_content.rb +17 -0
  109. data/lib/ruby_ui/pagination/pagination_ellipsis.rb +42 -0
  110. data/lib/ruby_ui/pagination/pagination_item.rb +28 -0
  111. data/lib/ruby_ui/popover/popover.rb +26 -0
  112. data/lib/ruby_ui/popover/popover_content.rb +27 -0
  113. data/lib/ruby_ui/popover/popover_trigger.rb +20 -0
  114. data/lib/ruby_ui/radio_button/radio_button.rb +22 -0
  115. data/lib/ruby_ui/select/select.rb +23 -0
  116. data/lib/ruby_ui/select/select_content.rb +32 -0
  117. data/lib/ruby_ui/select/select_group.rb +15 -0
  118. data/lib/ruby_ui/select/select_input.rb +22 -0
  119. data/lib/ruby_ui/select/select_item.rb +52 -0
  120. data/lib/ruby_ui/select/select_label.rb +17 -0
  121. data/lib/ruby_ui/select/select_trigger.rb +54 -0
  122. data/lib/ruby_ui/select/select_value.rb +27 -0
  123. data/lib/ruby_ui/sheet/sheet.rb +17 -0
  124. data/lib/ruby_ui/sheet/sheet_content.rb +77 -0
  125. data/lib/ruby_ui/sheet/sheet_description.rb +17 -0
  126. data/lib/ruby_ui/sheet/sheet_footer.rb +17 -0
  127. data/lib/ruby_ui/sheet/sheet_header.rb +17 -0
  128. data/lib/ruby_ui/sheet/sheet_middle.rb +17 -0
  129. data/lib/ruby_ui/sheet/sheet_title.rb +17 -0
  130. data/lib/ruby_ui/sheet/sheet_trigger.rb +17 -0
  131. data/lib/ruby_ui/shortcut_key/shortcut_key.rb +17 -0
  132. data/lib/ruby_ui/table/table.rb +19 -0
  133. data/lib/ruby_ui/table/table_body.rb +17 -0
  134. data/lib/ruby_ui/table/table_caption.rb +17 -0
  135. data/lib/ruby_ui/table/table_cell.rb +17 -0
  136. data/lib/ruby_ui/table/table_footer.rb +17 -0
  137. data/lib/ruby_ui/table/table_head.rb +17 -0
  138. data/lib/ruby_ui/table/table_header.rb +17 -0
  139. data/lib/ruby_ui/table/table_row.rb +17 -0
  140. data/lib/ruby_ui/tabs/tabs.rb +25 -0
  141. data/lib/ruby_ui/tabs/tabs_content.rb +26 -0
  142. data/lib/ruby_ui/tabs/tabs_list.rb +17 -0
  143. data/lib/ruby_ui/tabs/tabs_trigger.rb +28 -0
  144. data/lib/ruby_ui/textarea/textarea.rb +26 -0
  145. data/lib/ruby_ui/theme_toggle/theme_toggle.rb +41 -0
  146. data/lib/ruby_ui/tooltip/tooltip.rb +26 -0
  147. data/lib/ruby_ui/tooltip/tooltip_content.rb +26 -0
  148. data/lib/ruby_ui/tooltip/tooltip_trigger.rb +19 -0
  149. data/lib/ruby_ui/typography/heading.rb +60 -0
  150. data/lib/ruby_ui/typography/inline_code.rb +17 -0
  151. data/lib/ruby_ui/typography/inline_link.rb +22 -0
  152. data/lib/ruby_ui/typography/text.rb +53 -0
  153. data/lib/ruby_ui/typography/typography_blockquote.rb +17 -0
  154. data/lib/ruby_ui.rb +5 -0
  155. metadata +280 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 518fa1b05606796f9ae57a444aa55f5a5f0fcad5280c1e0ed75fa4778dbe978f
4
+ data.tar.gz: 58c2a5717af15d0326258044a7ffc862d06cb3f3c3cc47f54a269b465bca2bcf
5
+ SHA512:
6
+ metadata.gz: c17770afaf73e476ba5d2a52bd60d4f4ab00c80e84f7390e9870099cd85a827f81992a6a8d1dd2fd246b34785b6fb2640a95d5f7ad5b08b697a710eb29c89db5
7
+ data.tar.gz: d70e491efc576db70d0fa7ea559ce16472a7fdd4f2a7a3a770ec15bc62b25da2ec12d12932baed3a966b9d44f2f0cb8704235f3bb016397b5e483cfe30cb1645
@@ -0,0 +1,130 @@
1
+ require_relative "javascript_utils"
2
+ module RubyUI
3
+ module Generators
4
+ class ComponentGenerator < Rails::Generators::Base
5
+ include RubyUI::Generators::JavascriptUtils
6
+
7
+ namespace "ruby_ui:component"
8
+
9
+ source_root File.expand_path("../../ruby_ui", __dir__)
10
+ argument :component_name, type: :string, required: true
11
+
12
+ def generate_component
13
+ if component_not_found?
14
+ say "Component not found: #{component_name}", :red
15
+ exit
16
+ end
17
+
18
+ say "Generating component files"
19
+ end
20
+
21
+ def copy_main_component_file
22
+ main_component_file_path = File.join(component_folder_path, "#{component_folder_name}.rb")
23
+
24
+ # some components dont't have a main component, eg. Typography
25
+ return unless File.exist? main_component_file_path
26
+
27
+ say "Generating main component"
28
+
29
+ copy_file main_component_file_path, Rails.root.join("app/components/ruby_ui", "#{component_folder_name}.rb")
30
+ end
31
+
32
+ def copy_related_component_files
33
+ return if related_components_file_paths.empty?
34
+
35
+ say "Generating related components"
36
+
37
+ related_components_file_paths.each do |file_path|
38
+ component_file_name = file_path.split("/").last
39
+ copy_file file_path, Rails.root.join("app/components/ruby_ui", component_folder_name, component_file_name)
40
+ end
41
+ end
42
+
43
+ def copy_js_files
44
+ return if js_controller_file_paths.empty?
45
+
46
+ say "Generating Stimulus controllers"
47
+
48
+ js_controller_file_paths.each do |file_path|
49
+ controller_file_name = file_path.split("/").last
50
+ copy_file file_path, Rails.root.join("app/javascript/controllers/ruby_ui", controller_file_name)
51
+ end
52
+
53
+ # Importmap doesn't have controller manifest, instead it uses `eagerLoadControllersFrom("controllers", application)`
54
+ if !using_importmap?
55
+ say "Updating Stimulus controllers manifest"
56
+ run "rake stimulus:manifest:update"
57
+ end
58
+ end
59
+
60
+ def install_dependencies
61
+ return if dependencies.blank?
62
+
63
+ say "Installing dependencies"
64
+
65
+ install_components_dependencies(dependencies["components"])
66
+ install_gems_dependencies(dependencies["gems"])
67
+ install_js_packages(dependencies["js_packages"])
68
+ end
69
+
70
+ private
71
+
72
+ def component_not_found? = !Dir.exist?(component_folder_path)
73
+
74
+ def component_folder_name = component_name.underscore
75
+
76
+ def component_folder_path = File.join(self.class.source_root, component_folder_name)
77
+
78
+ def main_component_file_path = File.join(component_folder_path, "#{component_folder_name}.rb")
79
+
80
+ def related_components_file_paths = Dir.glob(File.join(component_folder_path, "*.rb")) - [main_component_file_path]
81
+
82
+ def js_controller_file_paths = Dir.glob(File.join(component_folder_path, "*.js"))
83
+
84
+ def install_components_dependencies(components)
85
+ components&.each do |component|
86
+ run "bin/rails generate ruby_ui:component #{component}"
87
+ end
88
+ end
89
+
90
+ def install_gems_dependencies(gems)
91
+ gems&.each do |ruby_gem|
92
+ run "bundle show #{ruby_gem} > /dev/null 2>&1 || bundle add #{ruby_gem}"
93
+ end
94
+ end
95
+
96
+ def install_js_packages(js_packages)
97
+ js_packages&.each do |js_package|
98
+ install_js_package(js_package)
99
+ end
100
+ end
101
+
102
+ def pin_motion
103
+ say <<~TEXT
104
+ WARNING: Installing motion from CDN because `bin/importmap pin motion` doesn't download the correct file.
105
+ TEXT
106
+
107
+ inject_into_file Rails.root.join("config/importmap.rb"), <<~RUBY
108
+ pin "motion", to: "https://cdn.jsdelivr.net/npm/motion@11.11.17/+esm"\n
109
+ RUBY
110
+ end
111
+
112
+ def pin_tippy_js
113
+ say <<~TEXT
114
+ WARNING: Installing tippy.js from CDN because `bin/importmap pin tippy.js` doesn't download the correct file.
115
+ TEXT
116
+
117
+ inject_into_file Rails.root.join("config/importmap.rb"), <<~RUBY
118
+ pin "tippy.js", to: "https://cdn.jsdelivr.net/npm/tippy.js@6.3.7/+esm"
119
+ pin "@popperjs/core", to: "https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/+esm"\n
120
+ RUBY
121
+ end
122
+
123
+ def dependencies
124
+ @dependencies ||= YAML.load_file(File.join(__dir__, "dependencies.yml")).freeze
125
+
126
+ @dependencies[component_folder_name]
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,90 @@
1
+ require "rails/generators"
2
+ require_relative "../javascript_utils"
3
+
4
+ module RubyUI
5
+ module Generators
6
+ class InstallGenerator < Rails::Generators::Base
7
+ include RubyUI::Generators::JavascriptUtils
8
+
9
+ namespace "ruby_ui:install"
10
+
11
+ source_root File.expand_path("templates", __dir__)
12
+
13
+ def install_phlex_rails
14
+ say "Checking for phlex-rails"
15
+
16
+ if gem_installed?("phlex-rails")
17
+ if Gem::Specification.find_by_name("phlex-rails").version < "2.0.0.beta2"
18
+ say "You need to upgrade to phlex-rails 2 to use RubyUI", :red
19
+ exit
20
+ else
21
+ say "phlex-rails is already installed", :green
22
+ end
23
+ else
24
+ say "Adding phlex-rails to Gemfile"
25
+ run %(bundle add phlex-rails --github="phlex-ruby/phlex-rails")
26
+
27
+ say "Running phlex-rails structure"
28
+ run "bin/rails generate phlex:install"
29
+ end
30
+ end
31
+
32
+ def install_tailwind_merge
33
+ say "Checking for tailwind_merge"
34
+
35
+ if gem_installed?("tailwind_merge")
36
+ say "tailwind_merge is already installed", :green
37
+ else
38
+ say "Adding phlex-rails to Gemfile"
39
+ run %(bundle add tailwind_merge)
40
+ end
41
+ end
42
+
43
+ def install_ruby_ui_initializer
44
+ say "Creating RubyUI initializer"
45
+ template "ruby_ui.rb.erb", Rails.root.join("config/initializers/ruby_ui.rb")
46
+ end
47
+
48
+ def add_ruby_ui_module_to_components_base
49
+ say "Adding RubyUI Kit to Components::Base"
50
+ insert_into_file Rails.root.join("app/components/base.rb"), after: "include Components" do
51
+ "\n include RubyUI"
52
+ end
53
+ end
54
+
55
+ def add_tailwind_css
56
+ say "Adding RubyUI styles to application css"
57
+ template "application.tailwind.css.erb", Rails.root.join("app/assets/stylesheets/application.tailwind.css")
58
+ end
59
+
60
+ def add_tailwind_config
61
+ say "Adding RubyUI config to tailwind config"
62
+
63
+ if File.exist?(Rails.root.join("tailwind.config.js")) # tailwindcss js package
64
+ template "tailwind.config.js.js-package.erb", Rails.root.join("tailwind.config.js")
65
+ elsif File.exist?(Rails.root.join("config/tailwind.config.js")) # tailwindcss-rails gem
66
+ template "tailwind.config.js.tailwindcss-rails.erb", Rails.root.join("config/tailwind.config.js")
67
+ else
68
+ say "Cannot find tailwind.config.js. You will need to install tailwind config manually", :red
69
+ end
70
+ end
71
+
72
+ def install_tailwind_animate
73
+ say "Installing tailwindcss-animate plugin"
74
+
75
+ install_js_package("tailwindcss-animate")
76
+ end
77
+
78
+ def add_ruby_ui_base
79
+ say "Adding RubyUI::Base component"
80
+ template "../../../../ruby_ui/base.rb", Rails.root.join("app/components/ruby_ui/base.rb")
81
+ end
82
+
83
+ private
84
+
85
+ def gem_installed?(name)
86
+ Gem::Specification.find_all_by_name(name).any?
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,36 @@
1
+ module RubyUI
2
+ module Generators
3
+ module JavascriptUtils
4
+ def install_js_package(package)
5
+ if using_importmap?
6
+ pin_with_importmap(package)
7
+ elsif using_yarn?
8
+ run "yarn add #{package}"
9
+ elsif using_npm?
10
+ run "npm install #{package}"
11
+ else
12
+ say "Could not detect the package manager, you need to install '#{package}' manually", :red
13
+ end
14
+ end
15
+
16
+ def pin_with_importmap(package)
17
+ case package
18
+ when "motion"
19
+ pin_motion
20
+ when "tippy.js"
21
+ pin_tippy_js
22
+ else
23
+ run "bin/importmap pin #{package}"
24
+ end
25
+ end
26
+
27
+ def using_importmap?
28
+ File.exist?(Rails.root.join("config/importmap.rb")) && File.exist?(Rails.root.join("bin/importmap"))
29
+ end
30
+
31
+ def using_npm? = File.exist?(Rails.root.join("package-lock.json"))
32
+
33
+ def using_yarn? = File.exist?(Rails.root.join("yarn.lock"))
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class Accordion < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "w-full"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class AccordionContent < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ data: {
14
+ ruby_ui__accordion_target: "content"
15
+ },
16
+ class: "overflow-y-hidden",
17
+ style: "height: 0px;"
18
+ }
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class AccordionDefaultContent < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "pb-4 pt-0 text-sm"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class AccordionDefaultTrigger < Base
5
+ def view_template(&block)
6
+ div(class: "flex items-center justify-between w-full") do
7
+ p(&block)
8
+ RubyUI.AccordionIcon
9
+ end
10
+ end
11
+
12
+ def default_attrs
13
+ {
14
+ data: {action: "click->ruby-ui--accordion#toggle"},
15
+ class: "w-full flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline"
16
+ }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class AccordionIcon < Base
5
+ def view_template(&block)
6
+ span(**attrs) do
7
+ if block
8
+ block.call
9
+ else
10
+ icon
11
+ end
12
+ end
13
+ end
14
+
15
+ def icon
16
+ svg(
17
+ xmlns: "http://www.w3.org/2000/svg",
18
+ viewbox: "0 0 20 20",
19
+ fill: "currentColor",
20
+ class: "w-4 h-4"
21
+ ) do |s|
22
+ s.path(
23
+ fill_rule: "evenodd",
24
+ d:
25
+ "M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z",
26
+ clip_rule: "evenodd"
27
+ )
28
+ end
29
+ end
30
+
31
+ def default_attrs
32
+ {
33
+ class: "opacity-50",
34
+ data: {ruby_ui__accordion_target: "icon"}
35
+ }
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class AccordionItem < Base
5
+ def initialize(open: false, rotate_icon: 180, **attrs)
6
+ @open = open
7
+ @rotate_icon = rotate_icon
8
+ super(**attrs)
9
+ end
10
+
11
+ def view_template(&)
12
+ div(**attrs, &)
13
+ end
14
+
15
+ private
16
+
17
+ def default_attrs
18
+ {
19
+ data: {
20
+ controller: "ruby-ui--accordion",
21
+ ruby_ui__accordion_open_value: @open,
22
+ ruby_ui__accordion_rotate_icon_value: @rotate_icon
23
+ },
24
+ class: "border-b"
25
+ }
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class AccordionTrigger < Base
5
+ def view_template(&)
6
+ button(**attrs, &)
7
+ end
8
+
9
+ def default_attrs
10
+ {
11
+ type: "button",
12
+ data: {action: "click->ruby-ui--accordion#toggle"},
13
+ class: "w-full flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class Alert < Base
5
+ def initialize(variant: nil, **attrs)
6
+ @variant = variant
7
+ super(**attrs) # must be called after variant is set
8
+ end
9
+
10
+ def view_template(&)
11
+ div(**attrs, &)
12
+ end
13
+
14
+ private
15
+
16
+ def colors
17
+ case @variant
18
+ when nil
19
+ "ring-border bg-muted/20 text-foreground [&>svg]:opacity-80"
20
+ when :warning
21
+ "ring-warning/20 bg-warning/5 text-warning [&>svg]:text-warning/80"
22
+ when :success
23
+ "ring-success/20 bg-success/5 text-success [&>svg]:text-success/80"
24
+ when :destructive
25
+ "ring-destructive/20 bg-destructive/5 text-destructive [&>svg]:text-destructive/80"
26
+ end
27
+ end
28
+
29
+ def default_attrs
30
+ base_classes = "backdrop-blur relative w-full ring-1 ring-inset rounded-lg px-4 py-4 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg~*]:pl-8"
31
+ {
32
+ class: [base_classes, colors]
33
+ }
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class AlertDescription < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "text-sm [&_p]:leading-relaxed"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class AlertTitle < Base
5
+ def view_template(&)
6
+ h5(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "mb-1 font-medium leading-none tracking-tight"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class AlertDialog < Base
5
+ def initialize(open: false, **attrs)
6
+ @open = open
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: "ruby-ui--alert-dialog",
20
+ ruby_ui__alert_dialog_open_value: @open.to_s
21
+ },
22
+ class: "inline-block"
23
+ }
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class AlertDialogAction < Base
5
+ def view_template(&)
6
+ render RubyUI::Button.new(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ variant: :primary
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class AlertDialogCancel < Base
5
+ def view_template(&)
6
+ render RubyUI::Button.new(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ variant: :outline,
14
+ data: {
15
+ action: "click->ruby-ui--alert-dialog#dismiss"
16
+ },
17
+ class: "mt-2 sm:mt-0"
18
+ }
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class AlertDialogContent < Base
5
+ def view_template(&block)
6
+ template(**attrs) do
7
+ div(data: {controller: "ruby-ui--alert-dialog"}) do
8
+ background
9
+ container(&block)
10
+ end
11
+ end
12
+ end
13
+
14
+ def background
15
+ div(
16
+ data_state: "open",
17
+ class:
18
+ "fixed inset-0 z-50 bg-black/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
19
+ style: "pointer-events:auto",
20
+ data_aria_hidden: "true",
21
+ aria_hidden: "true"
22
+ )
23
+ end
24
+
25
+ def container(&)
26
+ div(
27
+ role: "alertdialog",
28
+ data_state: "open",
29
+ class: "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg md:w-full",
30
+ style: "pointer-events:auto",
31
+ &
32
+ )
33
+ end
34
+
35
+ private
36
+
37
+ def default_attrs
38
+ {
39
+ data: {
40
+ ruby_ui__alert_dialog_target: "content"
41
+ }
42
+ }
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class AlertDialogDescription < Base
5
+ def view_template(&)
6
+ p(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "text-sm text-muted-foreground"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class AlertDialogFooter < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class AlertDialogHeader < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "flex flex-col space-y-2 text-center sm:text-left"
14
+ }
15
+ end
16
+ end
17
+ end