plutonium 0.10.3 → 0.11.1

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 (185) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -2
  3. data/app/assets/application.js.bk +31419 -0
  4. data/app/assets/plutonium-original.png +0 -0
  5. data/app/assets/plutonium-white.png +0 -0
  6. data/app/assets/plutonium.css +1 -0
  7. data/app/assets/plutonium.ico +0 -0
  8. data/app/assets/plutonium.js +12416 -0
  9. data/app/assets/plutonium.js.map +7 -0
  10. data/app/assets/plutonium.min.js +39 -0
  11. data/app/assets/plutonium.min.js.map +7 -0
  12. data/app/assets/plutonium.png +0 -0
  13. data/app/views/application/_flash_alerts.html.erb +2 -2
  14. data/app/views/application/_resource_header.html.erb +261 -697
  15. data/app/views/application/_resource_sidebar.html.erb +14 -12
  16. data/app/views/components/action_button/action_button_component.rb +3 -3
  17. data/app/views/components/attributes.rb +184 -0
  18. data/app/views/components/base.rb +19 -40
  19. data/app/views/components/block/block_component.html.erb +1 -1
  20. data/app/views/components/block/block_component.rb +11 -7
  21. data/app/views/components/breadcrumbs/breadcrumbs_component.rb +3 -3
  22. data/app/views/components/button/button_component.html.erb +2 -2
  23. data/app/views/components/button/button_component.rb +10 -5
  24. data/app/views/components/dyna_frame_content/dyna_frame_content_component.html.erb +1 -0
  25. data/app/views/components/dyna_frame_content/dyna_frame_content_component.rb +3 -3
  26. data/app/views/components/dyna_frame_host/dyna_frame_host_component.html.erb +1 -2
  27. data/app/views/components/dyna_frame_host/dyna_frame_host_component.rb +12 -5
  28. data/app/views/components/empty_card/empty_card_component.rb +3 -3
  29. data/app/views/components/form/form_builder.rb +1 -1
  30. data/app/views/components/form/form_component.rb +3 -3
  31. data/app/views/components/has_many_panel/has_many_panel_component.html.erb +25 -0
  32. data/app/views/components/has_many_panel/has_many_panel_component.rb +16 -0
  33. data/app/views/components/header/header_component.rb +3 -3
  34. data/app/views/components/interactive_action_form/interactive_action_form_component.rb +3 -3
  35. data/app/views/components/nav_grid_menu/nav_grid_menu_component.html.erb +24 -0
  36. data/app/views/components/nav_grid_menu/nav_grid_menu_component.rb +23 -0
  37. data/app/views/components/nav_grid_menu_item/nav_grid_menu_item_component.html.erb +4 -0
  38. data/app/views/components/nav_grid_menu_item/nav_grid_menu_item_component.rb +20 -0
  39. data/app/views/components/nav_user/nav_user_component.html.erb +50 -0
  40. data/app/views/components/nav_user/nav_user_component.rb +32 -0
  41. data/app/views/components/nav_user_link/nav_user_link_component.html.erb +7 -0
  42. data/app/views/components/nav_user_link/nav_user_link_component.rb +23 -0
  43. data/app/views/components/nav_user_section/nav_user_section_component.html.erb +7 -0
  44. data/app/views/components/nav_user_section/nav_user_section_component.rb +18 -0
  45. data/app/views/components/nested_resource_form_fields/nested_resource_form_fields_component.html.erb +1 -3
  46. data/app/views/components/nested_resource_form_fields/nested_resource_form_fields_component.rb +11 -5
  47. data/app/views/components/pagination/pagination_component.html.erb +1 -1
  48. data/app/views/components/pagination/pagination_component.rb +10 -7
  49. data/app/views/components/panel/panel_component.html.erb +13 -6
  50. data/app/views/components/panel/panel_component.rb +11 -5
  51. data/app/views/components/resource_header/resource_header_component.html.erb +83 -0
  52. data/app/views/components/resource_header/resource_header_component.rb +30 -0
  53. data/app/views/components/resource_layout/resource_layout_component.html.erb +49 -0
  54. data/app/views/components/resource_layout/resource_layout_component.rb +41 -0
  55. data/app/views/components/sidebar/sidebar_component.html.erb +3 -33
  56. data/app/views/components/sidebar/sidebar_component.rb +3 -3
  57. data/app/views/components/sidebar_menu/sidebar_menu_component.html.erb +4 -2
  58. data/app/views/components/sidebar_menu/sidebar_menu_component.rb +10 -6
  59. data/app/views/components/sidebar_menu_item/sidebar_menu_item_component.html.erb +63 -71
  60. data/app/views/components/sidebar_menu_item/sidebar_menu_item_component.rb +27 -8
  61. data/app/views/components/skeleton/table/table_component.html.erb +1 -1
  62. data/app/views/components/skeleton/table/table_component.rb +3 -3
  63. data/app/views/components/table/table_component.html.erb +40 -89
  64. data/app/views/components/table/table_component.rb +124 -28
  65. data/app/views/components/table_search_input/table_search_input_component.html.erb +1 -1
  66. data/app/views/components/table_search_input/table_search_input_component.rb +11 -6
  67. data/app/views/components/table_toolbar/table_toolbar_component.html.erb +1 -1
  68. data/app/views/components/table_toolbar/table_toolbar_component.rb +11 -3
  69. data/app/views/components/toolbar/toolbar_component.html.erb +2 -2
  70. data/app/views/components/toolbar/toolbar_component.rb +16 -8
  71. data/app/views/layouts/resource.html.erb +12 -45
  72. data/app/views/layouts/rodauth.html.erb +20 -36
  73. data/app/views/resource/_interactive_resource_action_form.html.erb +1 -1
  74. data/app/views/resource/_resource_details.html.erb +8 -5
  75. data/app/views/resource/_resource_table.html.erb +70 -1
  76. data/app/views/resource/interactive_resource_collection_action.html.erb +1 -0
  77. data/app/views/resource/interactive_resource_record_action.html.erb +1 -0
  78. data/app/views/resource/interactive_resource_recordless_action.html.erb +1 -0
  79. data/app/views/resource/new.html.erb +1 -0
  80. data/config/initializers/simple_form.rb +22 -2
  81. data/esbuild.config.js +35 -31
  82. data/lib/generators/pu/core/assets/assets_generator.rb +44 -0
  83. data/lib/generators/pu/core/assets/templates/tailwind.config.js +18 -0
  84. data/lib/generators/pu/core/install/install_generator.rb +4 -1
  85. data/lib/generators/pu/gem/dotenv/templates/config/initializers/001_ensure_required_env.rb +6 -0
  86. data/lib/generators/pu/gen/component/component_generator.rb +13 -10
  87. data/lib/generators/pu/gen/component/templates/component.html.erb.tt +1 -1
  88. data/lib/generators/pu/gen/component/templates/component.rb.tt +10 -4
  89. data/lib/generators/pu/pkg/app/app_generator.rb +4 -4
  90. data/lib/generators/pu/pkg/app/templates/app/controllers/concerns/controller.rb.tt +28 -0
  91. data/lib/generators/pu/pkg/app/templates/app/controllers/controller.rb.tt +5 -0
  92. data/lib/generators/pu/pkg/app/templates/app/controllers/dashboard_controller.rb.tt +1 -1
  93. data/lib/generators/pu/res/conn/conn_generator.rb +4 -4
  94. data/lib/generators/pu/res/conn/templates/app/controllers/resource_controller.rb.tt +1 -1
  95. data/lib/generators/pu/res/model/model_generator.rb +3 -3
  96. data/lib/generators/pu/res/scaffold/templates/policy.rb.tt +6 -0
  97. data/lib/generators/pu/service/sidekiq/sidekiq_generator.rb +0 -5
  98. data/lib/generators/pu/service/sidekiq/templates/app/sidekiq/sidekiq_job.rb +0 -2
  99. data/lib/plutonium/config.rb +2 -14
  100. data/lib/plutonium/core/associations/renderers/basic_renderer.rb +28 -0
  101. data/lib/plutonium/core/associations/renderers/factory.rb +36 -0
  102. data/lib/plutonium/core/associations/renderers/has_many_renderer.rb +16 -0
  103. data/lib/plutonium/core/autodiscovery/association_renderer_discoverer.rb +31 -0
  104. data/lib/plutonium/core/controllers/authorizable.rb +13 -17
  105. data/lib/plutonium/core/controllers/base.rb +3 -7
  106. data/lib/plutonium/core/controllers/presentable.rb +6 -1
  107. data/lib/plutonium/core/definers/association_renderer_definer.rb +33 -0
  108. data/lib/plutonium/core/fields/inputs/checkbox_input.rb +13 -0
  109. data/lib/plutonium/core/fields/inputs/factory.rb +1 -0
  110. data/lib/plutonium/core/fields/inputs/polymorphic_belongs_to_association_input.rb +1 -1
  111. data/lib/plutonium/core/ui/detail.rb +1 -0
  112. data/lib/plutonium/helpers/application_helper.rb +8 -9
  113. data/lib/plutonium/helpers/assets_helper.rb +41 -0
  114. data/lib/plutonium/helpers/display_helper.rb +13 -0
  115. data/lib/plutonium/helpers/form_helper.rb +1 -1
  116. data/lib/plutonium/helpers.rb +1 -0
  117. data/lib/plutonium/icons.rb +12 -5
  118. data/lib/plutonium/pkg/app.rb +10 -0
  119. data/lib/plutonium/pundit/context.rb +18 -0
  120. data/lib/plutonium/pundit/policy_finder.rb +25 -0
  121. data/lib/plutonium/railtie.rb +26 -8
  122. data/lib/plutonium/reloader.rb +18 -7
  123. data/lib/plutonium/resource/controller.rb +4 -0
  124. data/lib/plutonium/resource/policy.rb +69 -47
  125. data/lib/plutonium/resource/presenter.rb +1 -0
  126. data/lib/plutonium/resource/query_object.rb +139 -130
  127. data/lib/plutonium/rodauth/controller_methods.rb +7 -3
  128. data/lib/plutonium/version.rb +1 -1
  129. data/lib/plutonium.rb +9 -57
  130. data/package-lock.json +782 -17
  131. data/package.json +31 -8
  132. data/postcss.config.js +17 -7
  133. data/src/.npmignore +2 -0
  134. data/src/js/controllers/color_mode_controller.js +41 -0
  135. data/src/js/controllers/frame_navigator_controller.js +99 -0
  136. data/src/js/controllers/has_many_panel_controller.js +8 -0
  137. data/src/js/controllers/nav_grid_menu_controller.js +8 -0
  138. data/src/js/controllers/nav_grid_menu_item_controller.js +8 -0
  139. data/{app/views/components/tab_bar/tab_bar_controller.js → src/js/controllers/nav_user_controller.js} +2 -2
  140. data/src/js/controllers/nav_user_link_controller.js +8 -0
  141. data/src/js/controllers/nav_user_section_controller.js +8 -0
  142. data/src/js/controllers/register_controllers.js +45 -0
  143. data/{app/assets/javascripts → src/js}/controllers/resource_dismiss_controller.js +2 -0
  144. data/{app/assets/javascripts → src/js}/controllers/resource_drop_down_controller.js +2 -0
  145. data/src/js/controllers/resource_header_controller.js +8 -0
  146. data/src/js/controllers/resource_layout_controller.js +8 -0
  147. data/src/js/controllers/sidebar_menu_controller.js +8 -0
  148. data/src/js/controllers/sidebar_menu_item_controller.js +8 -0
  149. data/src/js/core.js +4 -0
  150. data/{app/assets/javascripts/plutonium-app.js → src/js/plutonium.js} +1 -1
  151. data/{app/assets/javascripts → src/js}/turbo/turbo_debug.js +2 -4
  152. data/tailwind.config.js +85 -84
  153. metadata +73 -39
  154. data/app/assets/build/plutonium.js +0 -5122
  155. data/app/assets/javascripts/controllers/index.js +0 -34
  156. data/app/assets/javascripts/plutonium.js +0 -1
  157. data/app/views/application/_color_modes.html.erb +0 -57
  158. data/app/views/components/tab_bar/tab_bar_component.html.erb +0 -11
  159. data/app/views/components/tab_bar/tab_bar_component.rb +0 -9
  160. data/app/views/resource/_nav_user.html.erb +0 -4
  161. data/app/views/resource/_tab_menu.html.erb +0 -13
  162. data/css.manifest +0 -3
  163. data/js.manifest +0 -4
  164. data/lib/generators/pu/pkg/app/templates/app/controllers/app_controller.rb.tt +0 -5
  165. data/lib/generators/pu/pkg/app/templates/app/controllers/package_controller.rb.tt +0 -26
  166. data/public/plutonium-assets/application.css +0 -25086
  167. data/public/plutonium-assets/plutonium-app-36KN5FVJ.js +0 -6
  168. data/public/plutonium-assets/plutonium-app-36KN5FVJ.js.map +0 -7
  169. data/public/plutonium-assets/plutonium-app-6WILQCTT.js +0 -39
  170. data/public/plutonium-assets/plutonium-app-6WILQCTT.js.map +0 -7
  171. data/public/plutonium-assets/plutonium.2d4f0c333cd000051d3b.css +0 -3424
  172. data/public/plutonium-assets/plutonium.50232e35b5495f5ad90d.css +0 -3415
  173. data/public/plutonium-assets/plutonium.8bee7a8482988b0360e3.css +0 -3420
  174. /data/{app/assets/build → lib/generators/pu/core/assets/templates}/.keep +0 -0
  175. /data/{app/assets/stylesheets → src/css}/plutonium.css +0 -0
  176. /data/{app/views/components/form → src/js/controllers}/form_controller.js +0 -0
  177. /data/{app/views/components/interactive_action_form → src/js/controllers}/interactive_action_form_controller.js +0 -0
  178. /data/{app/views/components/nested_resource_form_fields → src/js/controllers}/nested_resource_form_fields_controller.js +0 -0
  179. /data/{app/views/components/table → src/js/controllers}/table_controller.js +0 -0
  180. /data/{app/views/components/table_search_input → src/js/controllers}/table_search_input_controller.js +0 -0
  181. /data/{app/views/components/table_toolbar → src/js/controllers}/table_toolbar_controller.js +0 -0
  182. /data/{app/views/components/toolbar → src/js/controllers}/toolbar_controller.js +0 -0
  183. /data/{app/assets/javascripts → src/js}/turbo/index.js +0 -0
  184. /data/{app/assets/javascripts → src/js}/turbo/turbo_actions.js +0 -0
  185. /data/{app/assets/javascripts → src/js}/turbo/turbo_frame_monkey_patch.js +0 -0
@@ -0,0 +1,50 @@
1
+ <div <%= attributes_html %>>
2
+ <% if avatar_url.present? %>
3
+ <button
4
+ type="button"
5
+ class="flex mx-3 text-sm bg-gray-800 rounded-full md:mr-0 focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600"
6
+ aria-expanded="false"
7
+ id="user-nav-dropdown-toggle"
8
+ data-resource-drop-down-target="trigger">
9
+ <span class="sr-only">Open user menu</span>
10
+ <img
11
+ class="w-8 h-8 rounded-full"
12
+ src="<%= avatar_url %>"
13
+ alt="avatar" />
14
+ </button>
15
+ <% else %>
16
+ <button
17
+ type="button"
18
+ class="flex mx-3 text-sm border border-gray-600 text-gray-500 hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-white dark:hover:bg-gray-700 rounded-full md:mr-0 focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600"
19
+ aria-expanded="false"
20
+ id="user-nav-dropdown-toggle"
21
+ data-resource-drop-down-target="trigger">
22
+ <span class="sr-only">Open user menu</span>
23
+ <svg class="w-8 h-8" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 24 24">
24
+ <path fill-rule="evenodd" d="M12 4a4 4 0 1 0 0 8 4 4 0 0 0 0-8Zm-2 9a4 4 0 0 0-4 4v1a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2v-1a4 4 0 0 0-4-4h-4Z" clip-rule="evenodd"/>
25
+ </svg>
26
+ </button>
27
+ <% end %>
28
+ <!-- Dropdown menu -->
29
+ <div
30
+ class="hidden z-50 my-4 w-56 text-base list-none bg-white divide-y divide-gray-100 shadow dark:bg-gray-700 dark:divide-gray-600 rounded-xl"
31
+ data-resource-drop-down-target="menu">
32
+ <div class="py-3 px-4">
33
+ <% if name.present? %>
34
+ <span
35
+ class="block text-sm font-semibold text-gray-900 dark:text-white">
36
+ <%= name %>
37
+ </span>
38
+ <% end %>
39
+ <span
40
+ class="block text-sm text-gray-900 truncate dark:text-white">
41
+ <%= email %>
42
+ </span>
43
+ </div>
44
+
45
+ <% sections.each do |section| %>
46
+ <%= section %>
47
+ <% end %>
48
+
49
+ </div>
50
+ </div>
@@ -0,0 +1,32 @@
1
+ module PlutoniumUi
2
+ class NavUserComponent < PlutoniumUi::Base
3
+ renders_many :sections, "PlutoniumUi::NavUserSectionComponent"
4
+
5
+ option :email
6
+ option :name, optional: true
7
+ option :avatar_url, optional: true
8
+ option :logout_url, optional: true
9
+
10
+ private
11
+
12
+ def base_attributes
13
+ # base attributes go here
14
+ {
15
+ classname: "nav-user",
16
+ controller: "nav-user resource-drop-down"
17
+ }
18
+ end
19
+
20
+ def before_render
21
+ return unless logout_url.present?
22
+
23
+ content # get block to execute so our link gets added at the very end
24
+
25
+ with_section do |section|
26
+ section.with_link url: logout_url, label: "Sign out", data: {turbo: false}, classname: "rounded-b-lg"
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ Plutonium::ComponentRegistry.register :nav_user, to: PlutoniumUi::NavUserComponent
@@ -0,0 +1,7 @@
1
+ <a <%= attributes_html %>>
2
+ <span class="flex items-center">
3
+ <%= leading if leading.present? %>
4
+ <%= label %>
5
+ </span>
6
+ <%= trailing if trailing.present? %>
7
+ </a>
@@ -0,0 +1,23 @@
1
+ module PlutoniumUi
2
+ class NavUserLinkComponent < PlutoniumUi::Base
3
+ renders_one :leading
4
+ renders_one :trailing
5
+
6
+ option :label
7
+ option :url, as: :href
8
+
9
+ private
10
+
11
+ def base_attributes
12
+ # base attributes go here
13
+ {
14
+ id: "nav-user-link-#{label.parameterize}",
15
+ classname: "nav-user-link flex justify-between items-center py-2 px-4 text-sm hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white",
16
+ controller: "nav-user-link",
17
+ href:
18
+ }
19
+ end
20
+ end
21
+ end
22
+
23
+ Plutonium::ComponentRegistry.register :nav_user_link, to: PlutoniumUi::NavUserLinkComponent
@@ -0,0 +1,7 @@
1
+ <ul <%= attributes_html %>>
2
+ <% links.each do |link| %>
3
+ <li>
4
+ <%= link %>
5
+ </li>
6
+ <% end %>
7
+ </ul>
@@ -0,0 +1,18 @@
1
+ module PlutoniumUi
2
+ class NavUserSectionComponent < PlutoniumUi::Base
3
+ renders_many :links, "PlutoniumUi::NavUserLinkComponent"
4
+
5
+ private
6
+
7
+ def base_attributes
8
+ # base attributes go here
9
+ {
10
+ classname: "nav-user-section text-gray-700 dark:text-gray-300",
11
+ controller: "nav-user-section",
12
+ aria: {labelledby: "user-nav-dropdown-toggle"}
13
+ }
14
+ end
15
+ end
16
+ end
17
+
18
+ Plutonium::ComponentRegistry.register :nav_user_section, to: PlutoniumUi::NavUserSectionComponent
@@ -1,6 +1,4 @@
1
- <div data-controller="nested-resource-form-fields"
2
- data-nested-resource-form-fields-limit-value="<%= limit %>"
3
- <%= render_component_attributes %>>
1
+ <div <%= attributes_html %>>
4
2
  <h2 class="text-lg font-bold dark:text-white ">
5
3
  <%= label %>
6
4
  </h2>
@@ -1,5 +1,5 @@
1
- module Plutonium::Ui
2
- class NestedResourceFormFieldsComponent < Plutonium::Ui::Base
1
+ module PlutoniumUi
2
+ class NestedResourceFormFieldsComponent < PlutoniumUi::Base
3
3
  option :name
4
4
  option :resource_class
5
5
  option :form
@@ -10,8 +10,14 @@ module Plutonium::Ui
10
10
  option :update_only, optional: true
11
11
  option :limit, optional: true
12
12
 
13
- def base_classname
14
- "mt-6 mb-4"
13
+ def base_attributes
14
+ {
15
+ classname: "mt-6 mb-4",
16
+ controller: "nested-resource-form-fields",
17
+ data: {
18
+ "nested-resource-form-fields-limit-value": limit
19
+ }
20
+ }
15
21
  end
16
22
 
17
23
  def label
@@ -20,4 +26,4 @@ module Plutonium::Ui
20
26
  end
21
27
  end
22
28
 
23
- Plutonium::ComponentRegistry.register :nested_resource_form_fields, to: Plutonium::Ui::NestedResourceFormFieldsComponent
29
+ Plutonium::ComponentRegistry.register :nested_resource_form_fields, to: PlutoniumUi::NestedResourceFormFieldsComponent
@@ -1,4 +1,4 @@
1
- <div data-controller="pagination" <%= render_component_attributes %>>
1
+ <div <%= attributes_html %>>
2
2
  <%== pagy_info(pager) %>
3
3
  <% if pager.pages > 1 %>
4
4
  <%== pagy_nav(pager) %>
@@ -1,7 +1,7 @@
1
1
  require "pagy"
2
2
 
3
- module Plutonium::Ui
4
- class PaginationComponent < Plutonium::Ui::Base
3
+ module PlutoniumUi
4
+ class PaginationComponent < PlutoniumUi::Base
5
5
  include Pagy::Frontend
6
6
 
7
7
  option :pager
@@ -9,10 +9,6 @@ module Plutonium::Ui
9
9
  option :nav_aria_label, optional: true
10
10
  option :nav_i18n_key, optional: true
11
11
 
12
- def classname
13
- "flex flex-col items-center space-y-2 p-6 #{super}"
14
- end
15
-
16
12
  def pagy_nav(pagy, **vars)
17
13
  p_id = %( id="#{pagy_id}") if pagy_id
18
14
  link = pagy_link_proc(pagy, link_extra: "class=\"#{default_link_classes} #{page_link_classes}\"")
@@ -52,6 +48,13 @@ module Plutonium::Ui
52
48
 
53
49
  private
54
50
 
51
+ def base_attributes
52
+ {
53
+ classname: "flex flex-col items-center space-y-2 p-6",
54
+ controller: "pagination"
55
+ }
56
+ end
57
+
55
58
  def prev_html(pagy, text: pagy_t("pagy.prev"))
56
59
  link = pagy_link_proc(pagy, link_extra: "class=\"#{default_link_classes} #{page_link_classes} rounded-s-lg\"")
57
60
 
@@ -88,4 +91,4 @@ module Plutonium::Ui
88
91
  end
89
92
  end
90
93
 
91
- Plutonium::ComponentRegistry.register :pagination, to: Plutonium::Ui::PaginationComponent
94
+ Plutonium::ComponentRegistry.register :pagination, to: PlutoniumUi::PaginationComponent
@@ -1,10 +1,17 @@
1
1
  <%= render_component :block, rounded: :all do %>
2
- <div <%= render_component_attributes %>>
3
- <% if title.present? %>
4
- <h5 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">
5
- <%= title %>
6
- </h5>
7
- <% end %>
2
+ <div <%= attributes_html %>>
3
+ <div class="flex justify-between items-center mb-4">
4
+ <% if title.present? %>
5
+ <h5 class="text-2xl font-bold tracking-tight text-gray-900 dark:text-white">
6
+ <%= title %>
7
+ </h5>
8
+ <% end %>
9
+ <div class="flex">
10
+ <% actions.each do |action| %>
11
+ <%= action %>
12
+ <% end %>
13
+ </div>
14
+ </div>
8
15
  <%= content %>
9
16
  </div>
10
17
  <% end %>
@@ -1,11 +1,17 @@
1
- module Plutonium::Ui
2
- class PanelComponent < Plutonium::Ui::Base
1
+ module PlutoniumUi
2
+ class PanelComponent < PlutoniumUi::Base
3
+ renders_many :actions
4
+
3
5
  option :title, optional: true
4
6
 
5
- def classname
6
- "p-4 #{super}"
7
+ private
8
+
9
+ def base_attributes
10
+ {
11
+ classname: "p-4"
12
+ }
7
13
  end
8
14
  end
9
15
  end
10
16
 
11
- Plutonium::ComponentRegistry.register :panel, to: Plutonium::Ui::PanelComponent
17
+ Plutonium::ComponentRegistry.register :panel, to: PlutoniumUi::PanelComponent
@@ -0,0 +1,83 @@
1
+ <nav <%= attributes_html %>>
2
+ <div class="flex flex-wrap justify-between items-center">
3
+ <div class="flex justify-start items-center">
4
+ <% if sidebar_toggle %>
5
+ <button
6
+ data-drawer-target="drawer-navigation"
7
+ data-drawer-toggle="drawer-navigation"
8
+ aria-controls="drawer-navigation"
9
+ class="p-2 mr-2 text-gray-600 rounded-lg cursor-pointer lg:hidden hover:text-gray-900 hover:bg-gray-100 focus:bg-gray-100 dark:focus:bg-gray-700 focus:ring-2 focus:ring-gray-100 dark:focus:ring-gray-700 dark:text-gray-200 dark:hover:bg-gray-700 dark:hover:text-white">
10
+ <svg
11
+ aria-hidden="true"
12
+ class="w-6 h-6"
13
+ fill="currentColor"
14
+ viewBox="0 0 20 20"
15
+ xmlns="http://www.w3.org/2000/svg">
16
+ <path
17
+ fill-rule="evenodd"
18
+ d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h6a1 1 0 110 2H4a1 1 0 01-1-1zM3 15a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z"
19
+ clip-rule="evenodd"
20
+ ></path>
21
+ </svg>
22
+ <svg
23
+ aria-hidden="true"
24
+ class="hidden w-6 h-6"
25
+ fill="currentColor"
26
+ viewBox="0 0 20 20"
27
+ xmlns="http://www.w3.org/2000/svg">
28
+ <path
29
+ fill-rule="evenodd"
30
+ d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
31
+ clip-rule="evenodd"></path>
32
+ </svg>
33
+ <span class="sr-only">Toggle sidebar</span>
34
+ </button>
35
+ <% end %>
36
+ <% if brand_name.present? || brand_logo.present? %>
37
+ <a href="<%= root_path %>" class="flex items-center justify-between md:min-w-60">
38
+ <%= brand_logo if brand_logo.present? %>
39
+ <% if brand_name.present? %>
40
+ <span class="self-center text-2xl font-semibold whitespace-nowrap dark:text-white hidden xs:block">
41
+ <%= brand_name %>
42
+ </span>
43
+ <% end %>
44
+ </a>
45
+ <% end %>
46
+
47
+ <%= content %>
48
+ <%#
49
+ <form action="#" method="GET" class="hidden md:block md:pl-2">
50
+ <label for="topbar-search" class="sr-only">Search</label>
51
+ <div class="relative md:w-64">
52
+ <div
53
+ class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
54
+ <svg
55
+ class="w-5 h-5 text-gray-500 dark:text-gray-200"
56
+ fill="currentColor"
57
+ viewBox="0 0 20 20"
58
+ xmlns="http://www.w3.org/2000/svg">
59
+ <path
60
+ fill-rule="evenodd"
61
+ clip-rule="evenodd"
62
+ d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z"></path>
63
+ </svg>
64
+ </div>
65
+ <input
66
+ type="text"
67
+ name="email"
68
+ id="topbar-search"
69
+ class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full pl-10 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500"
70
+ placeholder="Search" />
71
+ </div>
72
+ </form>
73
+ %>
74
+ </div>
75
+ <% if actions.present? %>
76
+ <div class="flex items-center lg:order-2">
77
+ <% actions.each do |action| %>
78
+ <%= action %>
79
+ <% end %>
80
+ </div>
81
+ <% end %>
82
+ </div>
83
+ </nav>
@@ -0,0 +1,30 @@
1
+ module PlutoniumUi
2
+ class ResourceHeaderComponent < PlutoniumUi::Base
3
+ renders_one :brand_logo
4
+ renders_many :actions
5
+
6
+ option :brand_name, optional: true
7
+ option :default_brand_logo, default: -> { true }
8
+ option :sidebar_toggle, default: -> { false }
9
+
10
+ private
11
+
12
+ def base_attributes
13
+ # base attributes go here
14
+ {
15
+ classname: "resource-header bg-white border-b border-gray-200 px-4 py-2.5 dark:bg-gray-800 dark:border-gray-700 fixed left-0 right-0 top-0 z-50",
16
+ controller: "resource-header"
17
+ }
18
+ end
19
+
20
+ def before_render
21
+ return if brand_logo.present? || !default_brand_logo
22
+
23
+ with_brand_logo do
24
+ resource_logo_tag classname: "mr-3 h-10"
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ Plutonium::ComponentRegistry.register :resource_header, to: PlutoniumUi::ResourceHeaderComponent
@@ -0,0 +1,49 @@
1
+ <!DOCTYPE html>
2
+ <html <%= attributes_html %>>
3
+ <head>
4
+ <title><%= page_title %></title>
5
+ <meta charset="utf-8">
6
+ <meta name="viewport" content="width=device-width,initial-scale=1">
7
+ <%= csrf_meta_tags %>
8
+ <%= csp_meta_tag %>
9
+
10
+ <% if default_turbo_tag %>
11
+ <meta name="turbo-cache-control" content="no-cache">
12
+ <meta name="turbo-refresh-method" content="morph">
13
+ <meta name="turbo-refresh-scroll" content="preserve">
14
+ <% end %>
15
+
16
+ <%= meta %>
17
+ <%= favicon %>
18
+
19
+ <% if default_fonts_tag %>
20
+ <link rel="preconnect" href="https://fonts.googleapis.com">
21
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
22
+ <link href="https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900&display=swap" rel="stylesheet">
23
+ <% end %>
24
+
25
+ <% if default_assets_tag %>
26
+ <%= resource_stylesheet_tag %>
27
+ <%= resource_script_tag %>
28
+ <% end %>
29
+
30
+ <%= assets %>
31
+ <%= head %>
32
+ <%# <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/quill/1.3.7/quill.snow.min.css" integrity="sha512-/FHUK/LsH78K9XTqsR9hbzr21J8B8RwHR/r8Jv9fzry6NVAOVIGFKQCNINsbhK7a1xubVu2r5QZcz2T9cKpubw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
33
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/quill/1.3.7/quill.min.js" integrity="sha512-P2W2rr8ikUPfa31PLBo5bcBQrsa+TNj8jiKadtaIrHQGMo6hQM6RdPjQYxlNguwHz8AwSQ28VkBK6kHBLgd/8g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
34
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/slim-select/2.6.0/slimselect.min.css" integrity="sha512-GvqWM4KWH8mbgWIyvwdH8HgjUbyZTXrCq0sjGij9fDNiXz3vJoy3jCcAaWNekH2rJe4hXVWCJKN+bEW8V7AAEQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
35
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/slim-select/2.6.0/slimselect.min.js" integrity="sha512-0E8oaoA2v32h26IycsmRDShtQ8kMgD91zWVBxdIvUCjU3xBw81PV61QBsBqNQpWkp/zYJZip8Ag3ifmzz1wCKQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> %>
36
+ </head>
37
+ <body class="<%= body_classname %>">
38
+ <%= header %>
39
+ <%= sidebar %>
40
+ <main class="<%= build_main_classname %>">
41
+ <%= render "flash" %>
42
+ <%= content %>
43
+ </main>
44
+ </body>
45
+ </html>
46
+
47
+ <%#= modal_frame_tag do %>
48
+ <%#= yield(:modal) %>
49
+ <%# end %>
@@ -0,0 +1,41 @@
1
+ module PlutoniumUi
2
+ class ResourceLayoutComponent < PlutoniumUi::Base
3
+ renders_one :meta
4
+ renders_one :favicon
5
+ renders_one :assets
6
+ renders_one :head
7
+ renders_one :header
8
+ renders_one :sidebar
9
+
10
+ option :page_title
11
+ option :lang
12
+ option :body_classname, default: -> { "antialiased bg-gray-50 dark:bg-gray-900" }
13
+ option :main_classname, default: -> { "p-4 h-auto" }
14
+ option :header_adjustment, default: -> { "pt-20" }
15
+ option :sidebar_adjustment, default: -> { "lg:ml-64" }
16
+ option :default_turbo_tag, default: -> { true }
17
+ option :default_fonts_tag, default: -> { true }
18
+ option :default_assets_tag, default: -> { true }
19
+
20
+ private
21
+
22
+ def base_attributes
23
+ # base attributes go here
24
+ {
25
+ classname: "resource-layout",
26
+ controller: "resource-layout color-mode",
27
+ lang:
28
+ }
29
+ end
30
+
31
+ def build_main_classname
32
+ classname = Array(main_classname)
33
+ classname += Array(header_adjustment) if header.present?
34
+ classname += Array(sidebar_adjustment) if sidebar.present?
35
+
36
+ classname.join " "
37
+ end
38
+ end
39
+ end
40
+
41
+ Plutonium::ComponentRegistry.register :resource_layout, to: PlutoniumUi::ResourceLayoutComponent
@@ -55,36 +55,6 @@
55
55
  </div>
56
56
  -->
57
57
 
58
- <script>
59
- function updateColorMode() {
60
- // On page load or when changing themes, best to add inline in `head` to avoid FOUC
61
- if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
62
- document.documentElement.classList.add('dark')
63
- } else {
64
- document.documentElement.classList.remove('dark')
65
- }
66
- }
67
-
68
- function setLightColorMode() {
69
- // Whenever the user explicitly chooses light mode
70
- localStorage.theme = 'light'
71
- updateColorMode()
72
- }
73
-
74
- function setDarkColorMode() {
75
- // Whenever the user explicitly chooses dark mode
76
- localStorage.theme = 'dark'
77
- updateColorMode()
78
- }
79
-
80
- function setSystemColorMode() {
81
- // Whenever the user explicitly chooses to respect the OS preference
82
- localStorage.removeItem('theme')
83
- updateColorMode()
84
- }
85
-
86
- updateColorMode()
87
- </script>
88
58
 
89
59
  <!-- Color Modes -->
90
60
  <div data-controller="resource-drop-down">
@@ -105,7 +75,7 @@
105
75
  type="button"
106
76
  class="w-full block py-2 px-4 text-sm text-gray-700 hover:bg-gray-100 dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600"
107
77
  role="menuitem"
108
- onclick="setLightColorMode()"
78
+ data-action="click->color-mode#setLightColorMode"
109
79
  >
110
80
  <div class="flex justify-start">
111
81
  <svg class="w-6 h-6 me-2 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
@@ -120,7 +90,7 @@
120
90
  type="button"
121
91
  class="w-full block py-2 px-4 text-sm text-gray-700 hover:bg-gray-100 dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600"
122
92
  role="menuitem"
123
- onclick="setDarkColorMode()"
93
+ data-action="click->color-mode#setDarkColorMode"
124
94
  >
125
95
  <div class="flex justify-start">
126
96
  <svg class="w-6 h-6 me-2 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
@@ -135,7 +105,7 @@
135
105
  type="button"
136
106
  class="w-full block py-2 px-4 text-sm text-gray-700 hover:bg-gray-100 dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600"
137
107
  role="menuitem"
138
- onclick="setSystemColorMode()"
108
+ data-action="click->color-mode#setSystemColorMode"
139
109
  >
140
110
  <div class="flex justify-start">
141
111
  <svg class="w-6 h-6 me-2 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
@@ -1,5 +1,5 @@
1
- module Plutonium::Ui
2
- class SidebarComponent < Plutonium::Ui::Base
1
+ module PlutoniumUi
2
+ class SidebarComponent < PlutoniumUi::Base
3
3
  private
4
4
 
5
5
  def sidebar_class
@@ -12,4 +12,4 @@ module Plutonium::Ui
12
12
  end
13
13
  end
14
14
 
15
- Plutonium::ComponentRegistry.register :sidebar, to: Plutonium::Ui::SidebarComponent
15
+ Plutonium::ComponentRegistry.register :sidebar, to: PlutoniumUi::SidebarComponent
@@ -1,3 +1,5 @@
1
- <ul class="<%= menu_class %>">
2
- <%= content %>
1
+ <ul <%= attributes_html %>>
2
+ <% items.each do |item| %>
3
+ <%= item %>
4
+ <% end %>
3
5
  </ul>
@@ -1,13 +1,17 @@
1
- module Plutonium::Ui
2
- class SidebarMenuComponent < Plutonium::Ui::Base
3
- option :separated, optional: true
1
+ module PlutoniumUi
2
+ class SidebarMenuComponent < PlutoniumUi::Base
3
+ renders_many :items, "::PlutoniumUi::SidebarMenuItemComponent"
4
4
 
5
5
  private
6
6
 
7
- def menu_class
8
- "space-y-2 #{separated ? "pt-5 mt-5 border-t border-gray-200 dark:border-gray-700" : nil}"
7
+ def base_attributes
8
+ # base attributes go here
9
+ {
10
+ classname: "sidebar-menu space-y-2",
11
+ controller: "sidebar-menu"
12
+ }
9
13
  end
10
14
  end
11
15
  end
12
16
 
13
- Plutonium::ComponentRegistry.register :sidebar_menu, to: Plutonium::Ui::SidebarMenuComponent
17
+ Plutonium::ComponentRegistry.register :sidebar_menu, to: PlutoniumUi::SidebarMenuComponent