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
@@ -1,12 +1,14 @@
1
- <%= render_component :sidebar do %>
2
- <%= render_component :sidebar_menu do %>
3
- <%= render_component :sidebar_menu_item, name: "Dashboard", value: root_path %>
4
-
5
- <% resource_items = registered_resources.map { |resource| [resource.model_name.human.pluralize, resource_url_for(resource, parent: nil)] } %>
6
- <%= render_component :sidebar_menu_item, name: "Resources", value: resource_items %>
7
- <% end %>
8
-
9
- <%#= render_component :sidebar_menu, separated: true do %>
10
- <%#= render_component :sidebar_menu_item, name: "Docs", value: "/" %>
11
- <%# end %>
12
- <% end %>
1
+ <%= render_component(:sidebar) do %>
2
+ <%=
3
+ render_component(:sidebar_menu) do |menu|
4
+ menu.with_item(name: "Dashboard", url: root_path, icon: "outline/home")
5
+ if registered_resources.any?
6
+ menu.with_item(name: "Resources", icon: "outline/grid") do |sub_menu|
7
+ registered_resources.each do |resource|
8
+ sub_menu.with_sub_item(name: resource.model_name.human.pluralize, url: resource_url_for(resource, parent: nil))
9
+ end
10
+ end
11
+ end
12
+ end
13
+ %>
14
+ <% end %>
@@ -1,5 +1,5 @@
1
- module Plutonium::Ui
2
- class ActionButtonComponent < Plutonium::Ui::Base
1
+ module PlutoniumUi
2
+ class ActionButtonComponent < PlutoniumUi::Base
3
3
  option :label
4
4
  option :to
5
5
  option :method
@@ -12,4 +12,4 @@ module Plutonium::Ui
12
12
  end
13
13
  end
14
14
 
15
- Plutonium::ComponentRegistry.register :action_button, to: Plutonium::Ui::ActionButtonComponent
15
+ Plutonium::ComponentRegistry.register :action_button, to: PlutoniumUi::ActionButtonComponent
@@ -0,0 +1,184 @@
1
+ module PlutoniumUi
2
+ module Attributes
3
+ extend ActiveSupport::Concern
4
+
5
+ # Provides methods for handling a base set of UI attributes.
6
+ # The attributes include `id`, `data`, `classname`, `controllers`, and `tooltip`.
7
+ #
8
+ # @example Usage
9
+ # class MyComponent < PlutoniumUi::Base
10
+ # include PlutoniumUi::Attributes
11
+ # private
12
+ # # default set of attributes
13
+ # def base_attributes
14
+ # {
15
+ # id: "my-id",
16
+ # classname: "my-class", # classname can be an array or string
17
+ # controller: "my-controller",
18
+ # data: {
19
+ # key1: :value1,
20
+ # key2: :value2
21
+ # },
22
+ # custom_key1: :custom_value1,
23
+ # custom_key2: :custom_value2
24
+ # }
25
+ # end
26
+ # end
27
+ #
28
+ # object = MyComponent.new(
29
+ # id: "my-preferred-id", # takes highest precedence, even over attributes hash
30
+ # classname: ["appended-class1", "appended-class2"], # appends to the class
31
+ # controllers: ["my-custom-controller"],
32
+ # # attributes hash allows us to override values set in base_attributes
33
+ # # hash is merged with attributes taking precedence
34
+ # attributes: {
35
+ # data: {
36
+ # key1: :overridden_value,
37
+ # key3: :attributes_value
38
+ # },
39
+ # custom_key1: :overridden_custom_value,
40
+ # attributes_custom_key1: :attributes_custom_value
41
+ # }
42
+ # )
43
+ # object.attributes_html
44
+ # # => id="my-preferred-id" class="my-class appended-class1 appended-class2" data-key1="overridden_value" data-key2="value2" data-key3="attributes_value" data-controller="my-controller my-custom-controller" custom_key1="overridden_custom_value" custom_key2="custom_value2" attributes_custom_key1="attributes_custom_value"
45
+
46
+ included do
47
+ option :id, optional: true
48
+ # These will be merged with base_attributes
49
+ option :data, default: proc { {} }
50
+ option :classname, optional: true
51
+ option :controllers, optional: true
52
+ option :tooltip, optional: true
53
+ # This will override values set in base_attributes
54
+ option :attributes, default: proc { {} }
55
+ end
56
+
57
+ # Returns a memoized hash of attributes for the current object.
58
+ #
59
+ # The hash includes merged attributes from `base_attributes` and `attributes`,
60
+ # and further processing is done to include specific fields like `id`,
61
+ # `classname`, `controllers`, and `data`. The `data` field is enriched
62
+ # with controller information.
63
+ #
64
+ # @return [Hash] The processed and merged attributes hash.
65
+ #
66
+ # @example Usage
67
+ # object = MyComponent.new
68
+ # attributes = object.attributes_hash
69
+ # # => { id: "some_id", title: "some_tooltip", class: "some_class", data: { controller: "some_controller", key: "value" } }
70
+ def attributes_hash
71
+ @attributes_hash ||= raw_attributes_hash.except(*filtered_attributes)
72
+ end
73
+
74
+ def raw_attributes_hash
75
+ @raw_attributes_hash ||= build_attributes_hash
76
+ end
77
+
78
+ # Generates an HTML-safe string of attributes for the current object.
79
+ #
80
+ # This method uses the `attributes_hash` method to get a hash of attributes
81
+ # and then converts it into an HTML-safe string using the `tag` helper.
82
+ #
83
+ # @return [String] An HTML-safe string of attributes.
84
+ #
85
+ # @example Usage
86
+ # object = MyComponent.new
87
+ # html_attributes = object.attributes_html
88
+ # # => 'id="some_id" title="some_tooltip" class="some_class" data-controller="some_controller" data-key="value"'
89
+ def attributes_html
90
+ convert_attributes_to_html(attributes_hash)
91
+ end
92
+
93
+ private
94
+
95
+ # Returns the base attributes for the object.
96
+ # This can be overridden in subclasses to provide additional attributes.
97
+ #
98
+ # @return [Hash] The base attributes hash.
99
+ def base_attributes
100
+ {}
101
+ end
102
+
103
+ # Returns the list of attributes that should be filtered from #attributes_hash
104
+ # Useful for allowing attributes to be overriden while not rendering them on the dom element.
105
+ #
106
+ # @return [Array] The list of attributes to filter.
107
+ def filtered_attributes
108
+ []
109
+ end
110
+
111
+ # Returns the list of attributes that are we include in our attributes_hash.
112
+ # Can be used in #filtered_attributes to simplify filtering.
113
+ #
114
+ # @return [Array] The list of possible attributes.
115
+ def possible_attributes
116
+ %i[id class data title]
117
+ end
118
+
119
+ # Builds the attributes hash by merging base attributes and custom attributes,
120
+ # and processing specific fields like id, classname, controllers, and data.
121
+ #
122
+ # @return [Hash] The processed and merged attributes hash.
123
+ def build_attributes_hash
124
+ merged_attributes = merge_base_and_custom_attributes
125
+ {
126
+ id: extract_id(merged_attributes),
127
+ title: tooltip,
128
+ class: extract_classname(merged_attributes),
129
+ data: build_data(merged_attributes)
130
+ }.deep_merge(merged_attributes).compact
131
+ end
132
+
133
+ # Merges base attributes with custom attributes.
134
+ #
135
+ # @return [Hash] The merged attributes.
136
+ def merge_base_and_custom_attributes
137
+ base_attributes.deep_merge(attributes)
138
+ end
139
+
140
+ # Extracts the id from the merged attributes or the current object.
141
+ #
142
+ # @param merged_attributes [Hash] The merged attributes hash.
143
+ # @return [Object] The extracted id.
144
+ def extract_id(merged_attributes)
145
+ [id, merged_attributes.delete(:id)].compact.first
146
+ end
147
+
148
+ # Extracts and combines class names from merged attributes and the current object.
149
+ #
150
+ # @param merged_attributes [Hash] The merged attributes hash.
151
+ # @return [String, nil] The combined class names.
152
+ def extract_classname(merged_attributes)
153
+ (Array(merged_attributes.delete(:classname)) + Array(classname)).compact.join(" ").presence
154
+ end
155
+
156
+ # Extracts and combines controller names from merged attributes and the current object.
157
+ #
158
+ # @param merged_attributes [Hash] The merged attributes hash.
159
+ # @return [String, nil] The combined controller names.
160
+ def extract_controllers(merged_attributes)
161
+ (Array(merged_attributes.delete(:controller)) + Array(controllers)).compact.join(" ").presence
162
+ end
163
+
164
+ # Builds the data hash by merging data from merged attributes and the current object,
165
+ # and adding controller information.
166
+ #
167
+ # @param merged_attributes [Hash] The merged attributes hash.
168
+ # @return [Hash] The built data hash.
169
+ def build_data(merged_attributes)
170
+ data = (merged_attributes.delete(:data) || {}).merge(self.data)
171
+ data[:controller] = extract_controllers(merged_attributes)
172
+ data.compact!
173
+ data
174
+ end
175
+
176
+ # Converts a hash of attributes to an HTML-safe string.
177
+ #
178
+ # @param attributes [Hash] The hash of attributes to convert.
179
+ # @return [String] An HTML-safe string of attributes.
180
+ def convert_attributes_to_html(attributes)
181
+ tag.attributes(attributes)
182
+ end
183
+ end
184
+ end
@@ -1,50 +1,29 @@
1
1
  require "view_component"
2
2
  require "dry-initializer"
3
-
4
- module Plutonium::Ui
3
+ require "active_support/notifications"
4
+
5
+ load File.join(__dir__, "attributes.rb")
6
+
7
+ module PlutoniumUi
8
+ # Base class for all Plutonium UI components.
9
+ # This class inherits from `ViewComponent::Base` and includes additional functionality
10
+ # provided by `Dry::Initializer` for managing component options, and the
11
+ # `PlutoniumUi::Attributes` module for handling UI attributes.
12
+ #
13
+ # It also includes `Plutonium::Helpers::ComponentHelper` for additional helper methods
14
+ # and delegates missing methods to the Rails helpers.
5
15
  class Base < ViewComponent::Base
6
16
  extend Dry::Initializer
7
17
  include Plutonium::Helpers::ComponentHelper
18
+ include PlutoniumUi::Attributes
8
19
 
9
20
  delegate_missing_to :helpers
10
-
11
- option :id, optional: true
12
- option :data, default: proc { {} }
13
- option :classname, optional: true
14
- option :tooltip, optional: true
15
- option :attributes, default: proc { {} }
16
-
17
- private
18
-
19
- def base_classname = nil
20
-
21
- def merged_classname
22
- [base_classname, classname].compact.join.presence
23
- end
24
-
25
- def component_attributes
26
- {id:, data:, class: merged_classname, title: tooltip}.merge(attributes).compact
27
- end
28
-
29
- def render_component_attributes
30
- attributes_to_string(component_attributes).html_safe
31
- end
32
-
33
- def render_icon(icon)
34
- Plutonium::Icons.render(icon)
35
- end
36
-
37
- def attributes_to_string(attributes, prefix = nil)
38
- attributes.map do |key, value|
39
- if value.is_a?(Hash)
40
- attributes_to_string(value, "#{prefix ? "#{prefix}-" : ""}#{key}")
41
- else
42
- "#{prefix ? "#{prefix}-" : ""}#{key}=\"#{value}\""
43
- end
44
- end.join(" ")
45
- end
46
21
  end
47
22
  end
48
23
 
49
- # Require components
50
- Dir.glob(File.expand_path("**/*.rb", __dir__)) { |component| load component unless component == __FILE__ }
24
+ ActiveSupport::Notifications.instrument("plutonium.components.load") do
25
+ # Require all component files within the same directory and subdirectories
26
+ Dir.glob(File.expand_path("**/*.rb", __dir__)) do |component_file_path|
27
+ load component_file_path unless component_file_path == __FILE__
28
+ end
29
+ end
@@ -1,3 +1,3 @@
1
- <div <%= render_component_attributes %>>
1
+ <div <%= attributes_html %>>
2
2
  <%= content %>
3
3
  </div>
@@ -1,14 +1,18 @@
1
- module Plutonium::Ui
2
- class BlockComponent < Plutonium::Ui::Base
1
+ module PlutoniumUi
2
+ class BlockComponent < PlutoniumUi::Base
3
3
  option :rounded, optional: true
4
4
  option :scroll, optional: true
5
5
 
6
6
  private
7
7
 
8
- def classname
9
- classnames = ["relative bg-white dark:bg-gray-800 shadow-md", rounded_classes, scroll_classes]
10
- classnames << super.presence
11
- classnames.compact.join " "
8
+ def base_attributes
9
+ {
10
+ classname: classnames
11
+ }
12
+ end
13
+
14
+ def classnames
15
+ ["relative bg-white dark:bg-gray-800 shadow-md", rounded_classes, scroll_classes]
12
16
  end
13
17
 
14
18
  def scroll_classes
@@ -37,4 +41,4 @@ module Plutonium::Ui
37
41
  end
38
42
  end
39
43
 
40
- Plutonium::ComponentRegistry.register :block, to: Plutonium::Ui::BlockComponent
44
+ Plutonium::ComponentRegistry.register :block, to: PlutoniumUi::BlockComponent
@@ -1,9 +1,9 @@
1
- module Plutonium::Ui
2
- class BreadcrumbsComponent < Plutonium::Ui::Base
1
+ module PlutoniumUi
2
+ class BreadcrumbsComponent < PlutoniumUi::Base
3
3
  option :resource_class
4
4
  option :parent, optional: true
5
5
  option :resource, optional: true
6
6
  end
7
7
  end
8
8
 
9
- Plutonium::ComponentRegistry.register :breadcrumbs, to: Plutonium::Ui::BreadcrumbsComponent
9
+ Plutonium::ComponentRegistry.register :breadcrumbs, to: PlutoniumUi::BreadcrumbsComponent
@@ -1,10 +1,10 @@
1
1
  <% if to %>
2
- <%= link_to to, role: "button", **component_attributes do %>
2
+ <%= link_to to, role: "button", **attributes_hash do %>
3
3
  <%= render_icon icon if icon %>
4
4
  <span><%= label %></span>
5
5
  <% end %>
6
6
  <% else %>
7
- <button <%= render_component_attributes %> type="<%= type %>" %>
7
+ <button <%= attributes_html %> type="<%= type %>" %>
8
8
  <%= render_icon icon if icon %>
9
9
  <span><%= label %></span>
10
10
  </button>
@@ -1,5 +1,5 @@
1
- module Plutonium::Ui
2
- class ButtonComponent < Plutonium::Ui::Base
1
+ module PlutoniumUi
2
+ class ButtonComponent < PlutoniumUi::Base
3
3
  option :label
4
4
  option :to, optional: true
5
5
  option :icon, optional: true
@@ -10,11 +10,16 @@ module Plutonium::Ui
10
10
 
11
11
  private
12
12
 
13
- def classname
13
+ def base_attributes
14
+ {
15
+ classname: classnames
16
+ }
17
+ end
18
+
19
+ def classnames
14
20
  classnames = ["text-center py-2.5 font-medium px-5", color_classes, shape_classes, size_classes]
15
21
  classnames << "flex items-center justify-center"
16
22
  classnames << "space-x-1" if icon.present? && label.present?
17
- classnames << super.presence
18
23
  classnames.join " "
19
24
  end
20
25
 
@@ -120,4 +125,4 @@ module Plutonium::Ui
120
125
  end
121
126
  end
122
127
 
123
- Plutonium::ComponentRegistry.register :button, to: Plutonium::Ui::ButtonComponent
128
+ Plutonium::ComponentRegistry.register :button, to: PlutoniumUi::ButtonComponent
@@ -1,5 +1,6 @@
1
1
  <% if current_turbo_frame.present? %>
2
2
  <%= turbo_frame_tag current_turbo_frame do %>
3
+ <%= render "flash" %>
3
4
  <%= content %>
4
5
  <% end %>
5
6
  <% else %>
@@ -1,6 +1,6 @@
1
- module Plutonium::Ui
2
- class DynaFrameContentComponent < Plutonium::Ui::Base
1
+ module PlutoniumUi
2
+ class DynaFrameContentComponent < PlutoniumUi::Base
3
3
  end
4
4
  end
5
5
 
6
- Plutonium::ComponentRegistry.register :dyna_frame_content, to: Plutonium::Ui::DynaFrameContentComponent
6
+ Plutonium::ComponentRegistry.register :dyna_frame_content, to: PlutoniumUi::DynaFrameContentComponent
@@ -1,4 +1,3 @@
1
-
2
- <%= turbo_frame_tag id, src: do %>
1
+ <%= turbo_frame_tag attributes_hash.delete(:id), **attributes_hash do %>
3
2
  <%= content %>
4
3
  <% end %>
@@ -1,11 +1,18 @@
1
- module Plutonium::Ui
2
- class DynaFrameHostComponent < Plutonium::Ui::Base
1
+ module PlutoniumUi
2
+ class DynaFrameHostComponent < PlutoniumUi::Base
3
3
  option :src
4
+ option :loading
4
5
 
5
- def id
6
- super || SecureRandom.hex
6
+ private
7
+
8
+ def base_attributes
9
+ {
10
+ id: SecureRandom.hex,
11
+ src:,
12
+ loading:
13
+ }
7
14
  end
8
15
  end
9
16
  end
10
17
 
11
- Plutonium::ComponentRegistry.register :dyna_frame_host, to: Plutonium::Ui::DynaFrameHostComponent
18
+ Plutonium::ComponentRegistry.register :dyna_frame_host, to: PlutoniumUi::DynaFrameHostComponent
@@ -1,7 +1,7 @@
1
- module Plutonium::Ui
2
- class EmptyCardComponent < Plutonium::Ui::Base
1
+ module PlutoniumUi
2
+ class EmptyCardComponent < PlutoniumUi::Base
3
3
  option :message
4
4
  end
5
5
  end
6
6
 
7
- Plutonium::ComponentRegistry.register :empty_card, to: Plutonium::Ui::EmptyCardComponent
7
+ Plutonium::ComponentRegistry.register :empty_card, to: PlutoniumUi::EmptyCardComponent
@@ -1,6 +1,6 @@
1
1
  require "simple_form"
2
2
 
3
- module Plutonium::Ui
3
+ module PlutoniumUi
4
4
  class FormBuilder < SimpleForm::FormBuilder
5
5
  def input(attribute_name, options = {}, &block)
6
6
  label_class = options.dig(:label_html, :class)
@@ -1,5 +1,5 @@
1
- module Plutonium::Ui
2
- class FormComponent < Plutonium::Ui::Base
1
+ module PlutoniumUi
2
+ class FormComponent < PlutoniumUi::Base
3
3
  option :form
4
4
  option :preferred_action_after_submit, default: proc { "show" }
5
5
 
@@ -20,4 +20,4 @@ module Plutonium::Ui
20
20
  end
21
21
  end
22
22
 
23
- Plutonium::ComponentRegistry.register :form, to: Plutonium::Ui::FormComponent
23
+ Plutonium::ComponentRegistry.register :form, to: PlutoniumUi::FormComponent
@@ -0,0 +1,25 @@
1
+ <div <%= attributes_html %>>
2
+ <%= render_component :panel, title: do |panel| %>
3
+ <% panel.with_action do %>
4
+ <button title="Back" class="mr-2 text-gray-600 dark:text-gray-300" style="display:none" data-frame-navigator-target="backButton">
5
+ <%= render_icon "outline/chevron-left", size: :xl %>
6
+ </button>
7
+ <% end %>
8
+
9
+ <% panel.with_action do %>
10
+ <button title="Home" class="mr-2 text-gray-600 dark:text-gray-300" style="display:none" data-frame-navigator-target="homeButton">
11
+ <%= render_icon "outline/home", size: :xl %>
12
+ </button>
13
+ <% end %>
14
+
15
+ <% panel.with_action do %>
16
+ <button title="Refresh" data-frame-navigator-target="refreshButton" style="display:none" class="text-gray-600 dark:text-gray-300">
17
+ <%= render_icon "outline/refresh", size: :xl %>
18
+ </button>
19
+ <% end %>
20
+
21
+ <%= render_component :dyna_frame_host, loading: :lazy, data: { "frame-navigator-target": "frame" }, src: do %>
22
+ <%= render_component :skeleton__table %>
23
+ <% end %>
24
+ <% end %>
25
+ </div>
@@ -0,0 +1,16 @@
1
+ module PlutoniumUi
2
+ class HasManyPanelComponent < PlutoniumUi::Base
3
+ option :title
4
+ option :src
5
+
6
+ private
7
+
8
+ def base_attributes
9
+ {
10
+ controller: %w[has-many-panel frame-navigator]
11
+ }
12
+ end
13
+ end
14
+ end
15
+
16
+ Plutonium::ComponentRegistry.register :has_many_panel, to: PlutoniumUi::HasManyPanelComponent
@@ -1,7 +1,7 @@
1
- module Plutonium::Ui
2
- class HeaderComponent < Plutonium::Ui::Base
1
+ module PlutoniumUi
2
+ class HeaderComponent < PlutoniumUi::Base
3
3
  option :title
4
4
  end
5
5
  end
6
6
 
7
- Plutonium::ComponentRegistry.register :header, to: Plutonium::Ui::HeaderComponent
7
+ Plutonium::ComponentRegistry.register :header, to: PlutoniumUi::HeaderComponent
@@ -1,8 +1,8 @@
1
- module Plutonium::Ui
2
- class InteractiveActionFormComponent < Plutonium::Ui::Base
1
+ module PlutoniumUi
2
+ class InteractiveActionFormComponent < PlutoniumUi::Base
3
3
  option :interaction
4
4
  option :interactive_action
5
5
  end
6
6
  end
7
7
 
8
- Plutonium::ComponentRegistry.register :interactive_action_form, to: Plutonium::Ui::InteractiveActionFormComponent
8
+ Plutonium::ComponentRegistry.register :interactive_action_form, to: PlutoniumUi::InteractiveActionFormComponent
@@ -0,0 +1,24 @@
1
+ <div <%= attributes_html %>>
2
+ <button
3
+ type="button"
4
+ data-resource-drop-down-target="trigger"
5
+ class="p-2 text-gray-500 rounded-lg hover:text-gray-900 hover:bg-gray-100 dark:text-gray-200 dark:hover:text-white dark:hover:bg-gray-700 focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600">
6
+ <span class="sr-only">View <%= label %></span>
7
+ <!-- Icon -->
8
+ <%= render_icon "solid/grid", size: :lg %>
9
+ </button>
10
+ <!-- Dropdown menu -->
11
+ <div
12
+ class="hidden overflow-hidden z-50 my-4 max-w-sm text-base list-none bg-white divide-y divide-gray-100 shadow-lg dark:bg-gray-700 dark:divide-gray-600 rounded-xl"
13
+ data-resource-drop-down-target="menu">
14
+ <div
15
+ class="block py-2 px-4 text-base font-medium text-center text-gray-700 bg-gray-50 dark:bg-gray-600 dark:text-gray-300">
16
+ <%= label %>
17
+ </div>
18
+ <div class="grid grid-cols-3 gap-4 p-4">
19
+ <% items.each do |item| %>
20
+ <%= item %>
21
+ <% end %>
22
+ </div>
23
+ </div>
24
+ </div>
@@ -0,0 +1,23 @@
1
+ module PlutoniumUi
2
+ class NavGridMenuComponent < PlutoniumUi::Base
3
+ renders_many :items, "PlutoniumUi::NavGridMenuItemComponent"
4
+
5
+ option :label
6
+
7
+ private
8
+
9
+ def base_attributes
10
+ # base attributes go here
11
+ {
12
+ classname: "nav-grid-menu",
13
+ controller: "nav-grid-menu resource-drop-down"
14
+ }
15
+ end
16
+
17
+ def render?
18
+ items.any?
19
+ end
20
+ end
21
+ end
22
+
23
+ Plutonium::ComponentRegistry.register :nav_grid_menu, to: PlutoniumUi::NavGridMenuComponent
@@ -0,0 +1,4 @@
1
+ <a <%= attributes_html %>>
2
+ <%= render_icon icon, size: :xl, classname: "text-gray-400 group-hover:text-gray-500 dark:text-gray-200 dark:group-hover:text-gray-400" %>
3
+ <div class="text-sm text-gray-900 dark:text-white"><%= name %></div>
4
+ </a>
@@ -0,0 +1,20 @@
1
+ module PlutoniumUi
2
+ class NavGridMenuItemComponent < PlutoniumUi::Base
3
+ option :name
4
+ option :icon
5
+ option :url, as: :href
6
+
7
+ private
8
+
9
+ def base_attributes
10
+ # base attributes go here
11
+ {
12
+ classname: "nav-grid-menu-item block p-4 text-center rounded-lg hover:bg-gray-100 dark:hover:bg-gray-600 group",
13
+ controller: "nav-grid-menu-item",
14
+ href:
15
+ }
16
+ end
17
+ end
18
+ end
19
+
20
+ Plutonium::ComponentRegistry.register :nav_grid_menu_item, to: PlutoniumUi::NavGridMenuItemComponent