maquina-components 0.4.4 → 0.5.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.
- checksums.yaml +4 -4
- data/README.md +19 -1
- data/app/assets/stylesheets/breadcrumbs.css +21 -0
- data/app/assets/stylesheets/combobox.css +36 -1
- data/app/assets/stylesheets/drawer.css +135 -0
- data/app/assets/stylesheets/menu_button.css +155 -0
- data/app/assets/stylesheets/separator.css +20 -0
- data/app/assets/stylesheets/sidebar.css +12 -0
- data/app/assets/stylesheets/stats.css +101 -0
- data/app/assets/tailwind/maquina_components_engine/engine.css +4 -0
- data/app/helpers/maquina_components/combobox_helper.rb +2 -1
- data/app/helpers/maquina_components/components_helper.rb +33 -0
- data/app/helpers/maquina_components/drawer_helper.rb +19 -0
- data/app/helpers/maquina_components/icons_helper.rb +68 -1
- data/app/javascript/controllers/breadcrumb_controller.js +39 -30
- data/app/javascript/controllers/combobox_controller.js +9 -0
- data/app/javascript/controllers/drawer_controller.js +287 -0
- data/app/javascript/controllers/drawer_trigger_controller.js +58 -0
- data/app/javascript/controllers/menu_button_controller.js +107 -29
- data/app/javascript/controllers/sidebar_controller.js +6 -8
- data/app/javascript/controllers/sidebar_trigger_controller.js +33 -4
- data/app/javascript/controllers/toaster_controller.js +12 -0
- data/app/views/components/_alert.html.erb +3 -1
- data/app/views/components/_badge.html.erb +7 -1
- data/app/views/components/_breadcrumbs.html.erb +1 -1
- data/app/views/components/_calendar.html.erb +1 -1
- data/app/views/components/_card.html.erb +1 -1
- data/app/views/components/_combobox.html.erb +3 -2
- data/app/views/components/_date_picker.html.erb +4 -3
- data/app/views/components/_drawer.html.erb +37 -0
- data/app/views/components/_dropdown.html.erb +21 -24
- data/app/views/components/_dropdown_menu.html.erb +1 -1
- data/app/views/components/_empty.html.erb +1 -1
- data/app/views/components/_header.html.erb +1 -1
- data/app/views/components/_menu_button.html.erb +29 -34
- data/app/views/components/_pagination.html.erb +1 -1
- data/app/views/components/_separator.html.erb +9 -10
- data/app/views/components/_sidebar.html.erb +1 -1
- data/app/views/components/_simple_table.html.erb +3 -1
- data/app/views/components/_table.html.erb +1 -1
- data/app/views/components/_toast.html.erb +6 -1
- data/app/views/components/_toaster.html.erb +1 -1
- data/app/views/components/_toggle_group.html.erb +1 -1
- data/app/views/components/alert/_description.html.erb +1 -1
- data/app/views/components/alert/_title.html.erb +1 -1
- data/app/views/components/breadcrumbs/_ellipsis.html.erb +1 -1
- data/app/views/components/breadcrumbs/_item.html.erb +1 -1
- data/app/views/components/breadcrumbs/_link.html.erb +1 -1
- data/app/views/components/breadcrumbs/_list.html.erb +1 -1
- data/app/views/components/breadcrumbs/_page.html.erb +1 -1
- data/app/views/components/breadcrumbs/_separator.html.erb +1 -1
- data/app/views/components/calendar/_header.html.erb +1 -1
- data/app/views/components/calendar/_week.html.erb +1 -1
- data/app/views/components/card/_action.html.erb +1 -1
- data/app/views/components/card/_content.html.erb +1 -1
- data/app/views/components/card/_description.html.erb +1 -1
- data/app/views/components/card/_footer.html.erb +1 -1
- data/app/views/components/card/_header.html.erb +1 -1
- data/app/views/components/card/_title.html.erb +1 -1
- data/app/views/components/combobox/_content.html.erb +1 -1
- data/app/views/components/combobox/_empty.html.erb +3 -3
- data/app/views/components/combobox/_group.html.erb +1 -1
- data/app/views/components/combobox/_input.html.erb +1 -1
- data/app/views/components/combobox/_label.html.erb +1 -1
- data/app/views/components/combobox/_list.html.erb +1 -1
- data/app/views/components/combobox/_option.html.erb +1 -1
- data/app/views/components/combobox/_separator.html.erb +1 -1
- data/app/views/components/combobox/_trigger.html.erb +1 -1
- data/app/views/components/drawer/_close.html.erb +14 -0
- data/app/views/components/drawer/_content.html.erb +7 -0
- data/app/views/components/drawer/_footer.html.erb +7 -0
- data/app/views/components/drawer/_header.html.erb +12 -0
- data/app/views/components/drawer/_provider.html.erb +14 -0
- data/app/views/components/drawer/_trigger.html.erb +14 -0
- data/app/views/components/dropdown_menu/_content.html.erb +1 -1
- data/app/views/components/dropdown_menu/_group.html.erb +1 -1
- data/app/views/components/dropdown_menu/_item.html.erb +1 -1
- data/app/views/components/dropdown_menu/_label.html.erb +3 -7
- data/app/views/components/dropdown_menu/_separator.html.erb +1 -1
- data/app/views/components/dropdown_menu/_shortcut.html.erb +3 -7
- data/app/views/components/dropdown_menu/_trigger.html.erb +1 -1
- data/app/views/components/empty/_content.html.erb +1 -1
- data/app/views/components/empty/_description.html.erb +3 -7
- data/app/views/components/empty/_header.html.erb +1 -1
- data/app/views/components/empty/_media.html.erb +5 -3
- data/app/views/components/empty/_title.html.erb +3 -7
- data/app/views/components/pagination/_content.html.erb +1 -1
- data/app/views/components/pagination/_item.html.erb +1 -1
- data/app/views/components/pagination/_link.html.erb +1 -1
- data/app/views/components/pagination/_next.html.erb +1 -1
- data/app/views/components/pagination/_previous.html.erb +1 -1
- data/app/views/components/sidebar/_content.html.erb +1 -1
- data/app/views/components/sidebar/_footer.html.erb +1 -1
- data/app/views/components/sidebar/_group.html.erb +1 -1
- data/app/views/components/sidebar/_header.html.erb +1 -1
- data/app/views/components/sidebar/_inset.html.erb +1 -1
- data/app/views/components/sidebar/_menu.html.erb +1 -1
- data/app/views/components/sidebar/_menu_button.html.erb +1 -1
- data/app/views/components/sidebar/_menu_item.html.erb +1 -1
- data/app/views/components/sidebar/_menu_link.html.erb +4 -7
- data/app/views/components/sidebar/_provider.html.erb +1 -1
- data/app/views/components/sidebar/_trigger.html.erb +1 -1
- data/app/views/components/stats/_stats_card.html.erb +32 -92
- data/app/views/components/stats/_stats_grid.html.erb +18 -24
- data/app/views/components/table/_body.html.erb +1 -1
- data/app/views/components/table/_caption.html.erb +3 -3
- data/app/views/components/table/_cell.html.erb +3 -3
- data/app/views/components/table/_footer.html.erb +1 -1
- data/app/views/components/table/_head.html.erb +3 -3
- data/app/views/components/table/_header.html.erb +1 -1
- data/app/views/components/table/_row.html.erb +1 -1
- data/app/views/components/toast/_action.html.erb +1 -1
- data/app/views/components/toast/_description.html.erb +1 -1
- data/app/views/components/toast/_title.html.erb +1 -1
- data/app/views/components/toggle_group/_item.html.erb +1 -1
- data/lib/generators/maquina_components/install/templates/maquina_components_helper.rb.tt +8 -0
- data/lib/generators/maquina_components/scaffold_templates/scaffold_templates_generator.rb +40 -0
- data/lib/generators/maquina_components/scaffold_templates/templates/_form.html.erb.tt +49 -0
- data/lib/generators/maquina_components/scaffold_templates/templates/edit.html.erb.tt +29 -0
- data/lib/generators/maquina_components/scaffold_templates/templates/index.html.erb.tt +58 -0
- data/lib/generators/maquina_components/scaffold_templates/templates/new.html.erb.tt +26 -0
- data/lib/generators/maquina_components/scaffold_templates/templates/partial.html.erb.tt +17 -0
- data/lib/generators/maquina_components/scaffold_templates/templates/show.html.erb.tt +53 -0
- data/lib/maquina-components.rb +5 -0
- data/lib/maquina_components/engine.rb +7 -3
- data/lib/maquina_components/version.rb +1 -1
- metadata +52 -3
- data/app/assets/stylesheets/maquina_components.css +0 -178
|
@@ -1,100 +1,40 @@
|
|
|
1
|
-
<%# locals: (title:, value:, icon: nil,
|
|
1
|
+
<%# locals: (title:, value:, icon: nil, subtitle: nil, css_classes: "", icon_classes: "", value_classes: "", container_class: "", icon_class: "", value_class: "", **html_options) %>
|
|
2
|
+
<%
|
|
3
|
+
# container_class / icon_class / value_class are legacy aliases
|
|
4
|
+
css_classes = css_classes.presence || container_class
|
|
5
|
+
icon_classes = icon_classes.presence || icon_class
|
|
6
|
+
value_classes = value_classes.presence || value_class
|
|
2
7
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
# Legacy string icon names map to built-in icons; symbols pass straight
|
|
9
|
+
# through; anything else renders as custom icon markup.
|
|
10
|
+
legacy_icons = {
|
|
11
|
+
"message-square" => :message_square,
|
|
12
|
+
"arrow-up" => :arrow_up,
|
|
13
|
+
"arrow-down" => :arrow_down,
|
|
14
|
+
"check-circle" => :check_circle,
|
|
15
|
+
"lightning-bolt" => :lightning_bolt,
|
|
16
|
+
"exclamation-circle" => :circle_alert,
|
|
17
|
+
"clipboard-list" => :clipboard_list,
|
|
18
|
+
"chart-bar" => :chart_bar
|
|
19
|
+
}
|
|
20
|
+
icon_name = icon.is_a?(Symbol) ? icon : legacy_icons[icon.to_s]
|
|
21
|
+
|
|
22
|
+
merged_data = merge_component_data(html_options, component: "stats-card")
|
|
23
|
+
%>
|
|
24
|
+
<%= tag.div class: css_classes.presence, data: merged_data, **html_options do %>
|
|
25
|
+
<div data-stats-part="body">
|
|
26
|
+
<div data-stats-part="text">
|
|
27
|
+
<p data-stats-part="title"><%= title %></p>
|
|
28
|
+
<p data-stats-part="value" class="<%= value_classes.presence %>"><%= value %></p>
|
|
14
29
|
<% if subtitle.present? %>
|
|
15
|
-
<p
|
|
30
|
+
<p data-stats-part="subtitle"><%= subtitle %></p>
|
|
16
31
|
<% end %>
|
|
17
32
|
</div>
|
|
33
|
+
|
|
18
34
|
<% if icon.present? %>
|
|
19
|
-
<div class="<%=
|
|
20
|
-
|
|
21
|
-
<% when "message-square" %>
|
|
22
|
-
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
23
|
-
<path
|
|
24
|
-
stroke-linecap="round"
|
|
25
|
-
stroke-linejoin="round"
|
|
26
|
-
stroke-width="2"
|
|
27
|
-
d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z"
|
|
28
|
-
/>
|
|
29
|
-
</svg>
|
|
30
|
-
<% when "arrow-up" %>
|
|
31
|
-
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
32
|
-
<path
|
|
33
|
-
stroke-linecap="round"
|
|
34
|
-
stroke-linejoin="round"
|
|
35
|
-
stroke-width="2"
|
|
36
|
-
d="M7 17L17 7M17 7H7M17 7V17"
|
|
37
|
-
/>
|
|
38
|
-
</svg>
|
|
39
|
-
<% when "arrow-down" %>
|
|
40
|
-
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
41
|
-
<path
|
|
42
|
-
stroke-linecap="round"
|
|
43
|
-
stroke-linejoin="round"
|
|
44
|
-
stroke-width="2"
|
|
45
|
-
d="M17 7L7 17M7 17H17M7 17V7"
|
|
46
|
-
/>
|
|
47
|
-
</svg>
|
|
48
|
-
<% when "check-circle" %>
|
|
49
|
-
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
50
|
-
<path
|
|
51
|
-
stroke-linecap="round"
|
|
52
|
-
stroke-linejoin="round"
|
|
53
|
-
stroke-width="2"
|
|
54
|
-
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
55
|
-
/>
|
|
56
|
-
</svg>
|
|
57
|
-
<% when "lightning-bolt" %>
|
|
58
|
-
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
59
|
-
<path
|
|
60
|
-
stroke-linecap="round"
|
|
61
|
-
stroke-linejoin="round"
|
|
62
|
-
stroke-width="2"
|
|
63
|
-
d="M13 10V3L4 14h7v7l9-11h-7z"
|
|
64
|
-
/>
|
|
65
|
-
</svg>
|
|
66
|
-
<% when "exclamation-circle" %>
|
|
67
|
-
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
68
|
-
<path
|
|
69
|
-
stroke-linecap="round"
|
|
70
|
-
stroke-linejoin="round"
|
|
71
|
-
stroke-width="2"
|
|
72
|
-
d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
73
|
-
/>
|
|
74
|
-
</svg>
|
|
75
|
-
<% when "clipboard-list" %>
|
|
76
|
-
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
77
|
-
<path
|
|
78
|
-
stroke-linecap="round"
|
|
79
|
-
stroke-linejoin="round"
|
|
80
|
-
stroke-width="2"
|
|
81
|
-
d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"
|
|
82
|
-
/>
|
|
83
|
-
</svg>
|
|
84
|
-
<% when "chart-bar" %>
|
|
85
|
-
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
86
|
-
<path
|
|
87
|
-
stroke-linecap="round"
|
|
88
|
-
stroke-linejoin="round"
|
|
89
|
-
stroke-width="2"
|
|
90
|
-
d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
|
|
91
|
-
/>
|
|
92
|
-
</svg>
|
|
93
|
-
<% else %>
|
|
94
|
-
<%# Allow custom SVG or icon HTML to be passed %>
|
|
95
|
-
<%= icon %>
|
|
96
|
-
<% end %>
|
|
35
|
+
<div data-stats-part="icon" class="<%= icon_classes.presence %>">
|
|
36
|
+
<%= icon_name ? builtin_icon_for(icon_name, class: "size-8") : icon %>
|
|
97
37
|
</div>
|
|
98
38
|
<% end %>
|
|
99
39
|
</div>
|
|
100
|
-
|
|
40
|
+
<% end %>
|
|
@@ -1,38 +1,32 @@
|
|
|
1
|
-
<%# locals: (cards: [], columns: 3,
|
|
1
|
+
<%# locals: (cards: [], columns: 3, action: nil, action_position: :end, css_classes: "", container_class: "", **html_options) %>
|
|
2
|
+
<%
|
|
3
|
+
# container_class is a legacy alias
|
|
4
|
+
css_classes = css_classes.presence || container_class
|
|
5
|
+
action_position = action_position.to_s
|
|
6
|
+
columns = columns.to_i.clamp(1, 6)
|
|
2
7
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
8
|
+
merged_data = merge_component_data(html_options,
|
|
9
|
+
component: "stats-grid",
|
|
10
|
+
columns: columns
|
|
11
|
+
)
|
|
12
|
+
merged_data[:"with-action"] = true if action.present?
|
|
13
|
+
%>
|
|
14
|
+
<%= tag.div class: css_classes.presence, data: merged_data, **html_options do %>
|
|
6
15
|
<% if action.present? && action_position == "start" %>
|
|
7
|
-
<div
|
|
16
|
+
<div data-stats-part="action" data-position="start">
|
|
8
17
|
<%= action %>
|
|
9
18
|
</div>
|
|
10
19
|
<% end %>
|
|
11
20
|
|
|
12
|
-
<div
|
|
13
|
-
class="<%= class_names(
|
|
14
|
-
"grid gap-4",
|
|
15
|
-
"grid-cols-1",
|
|
16
|
-
"sm:grid-cols-#{columns}",
|
|
17
|
-
container_class,
|
|
18
|
-
"flex-1": action.present?
|
|
19
|
-
) %>"
|
|
20
|
-
>
|
|
21
|
+
<div data-stats-part="grid">
|
|
21
22
|
<% cards.each do |card| %>
|
|
22
|
-
<%= render "components/stats/stats_card",
|
|
23
|
-
title: card[:title],
|
|
24
|
-
value: card[:value],
|
|
25
|
-
icon: card[:icon],
|
|
26
|
-
icon_class: card[:icon_class] || "",
|
|
27
|
-
subtitle: card[:subtitle],
|
|
28
|
-
value_class: card[:value_class] || "",
|
|
29
|
-
container_class: card[:container_class] || "" %>
|
|
23
|
+
<%= render "components/stats/stats_card", **card.symbolize_keys %>
|
|
30
24
|
<% end %>
|
|
31
25
|
</div>
|
|
32
26
|
|
|
33
27
|
<% if action.present? && action_position == "end" %>
|
|
34
|
-
<div
|
|
28
|
+
<div data-stats-part="action" data-position="end">
|
|
35
29
|
<%= action %>
|
|
36
30
|
</div>
|
|
37
31
|
<% end %>
|
|
38
|
-
|
|
32
|
+
<% end %>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<%# locals: (css_classes: "", **html_options) %>
|
|
2
|
-
<% merged_data = (html_options
|
|
2
|
+
<% merged_data = merge_component_data(html_options, table_part: :body) %>
|
|
3
3
|
<%= content_tag :tbody, class: css_classes.presence, data: merged_data, **html_options do %>
|
|
4
4
|
<%= yield %>
|
|
5
5
|
<% end %>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
<%# locals: (css_classes: "", **html_options) %>
|
|
2
|
-
<% merged_data = (html_options
|
|
1
|
+
<%# locals: (text: nil, content: nil, css_classes: "", **html_options) %>
|
|
2
|
+
<% merged_data = merge_component_data(html_options, table_part: :caption) %>
|
|
3
3
|
<%= content_tag :caption, class: css_classes.presence, data: merged_data, **html_options do %>
|
|
4
|
-
<%=
|
|
4
|
+
<%= text || content || yield %>
|
|
5
5
|
<% end %>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
<%# locals: (css_classes: "", **html_options) %>
|
|
2
|
-
<% merged_data = (html_options
|
|
1
|
+
<%# locals: (text: nil, content: nil, css_classes: "", **html_options) %>
|
|
2
|
+
<% merged_data = merge_component_data(html_options, table_part: :cell) %>
|
|
3
3
|
<%= content_tag :td, class: css_classes.presence, data: merged_data, **html_options do %>
|
|
4
|
-
<%=
|
|
4
|
+
<%= text || content || yield %>
|
|
5
5
|
<% end %>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<%# locals: (css_classes: "", **html_options) %>
|
|
2
|
-
<% merged_data = (html_options
|
|
2
|
+
<% merged_data = merge_component_data(html_options, table_part: :footer) %>
|
|
3
3
|
<%= content_tag :tfoot, class: css_classes.presence, data: merged_data, **html_options do %>
|
|
4
4
|
<%= yield %>
|
|
5
5
|
<% end %>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
<%# locals: (css_classes: "", scope: "col", **html_options) %>
|
|
1
|
+
<%# locals: (text: nil, content: nil, css_classes: "", scope: "col", **html_options) %>
|
|
2
2
|
<%
|
|
3
|
-
merged_data = (html_options
|
|
3
|
+
merged_data = merge_component_data(html_options, table_part: :head)
|
|
4
4
|
html_options[:scope] = scope if scope
|
|
5
5
|
%>
|
|
6
6
|
<%= content_tag :th, class: css_classes.presence, data: merged_data, **html_options do %>
|
|
7
|
-
<%=
|
|
7
|
+
<%= text || content || yield %>
|
|
8
8
|
<% end %>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<%# locals: (css_classes: "", sticky: false, **html_options) %>
|
|
2
2
|
<%
|
|
3
|
-
merged_data = (html_options
|
|
3
|
+
merged_data = merge_component_data(html_options, table_part: :header)
|
|
4
4
|
merged_data[:sticky] = "true" if sticky
|
|
5
5
|
%>
|
|
6
6
|
<%= content_tag :thead, class: css_classes.presence, data: merged_data, **html_options do %>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<%# locals: (css_classes: "", selected: false, **html_options) %>
|
|
2
2
|
<%
|
|
3
|
-
merged_data = (html_options
|
|
3
|
+
merged_data = merge_component_data(html_options, table_part: :row)
|
|
4
4
|
merged_data[:state] = :selected if selected
|
|
5
5
|
%>
|
|
6
6
|
<%= content_tag :tr, class: css_classes.presence, data: merged_data, **html_options do %>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<%# locals: (value:, pressed: false, disabled: false, aria_label: nil, css_classes: "", **html_options) %>
|
|
2
|
-
<% merged_data = (html_options
|
|
2
|
+
<% merged_data = merge_component_data(html_options,
|
|
3
3
|
"toggle-group-part": "item",
|
|
4
4
|
"toggle-group-target": "item",
|
|
5
5
|
value: value,
|
|
@@ -6,9 +6,17 @@
|
|
|
6
6
|
# Override methods here to integrate with your application's icon system,
|
|
7
7
|
# sidebar state management, and other customizations.
|
|
8
8
|
#
|
|
9
|
+
# Engine helper modules are included below to make their methods available
|
|
10
|
+
# in your views (icon_for, sidebar_open?, toast_flash_messages, etc.).
|
|
11
|
+
#
|
|
9
12
|
# Documentation: https://github.com/maquina-app/maquina_components
|
|
10
13
|
#
|
|
11
14
|
module MaquinaComponentsHelper
|
|
15
|
+
include MaquinaComponents::ComponentsHelper
|
|
16
|
+
include MaquinaComponents::IconsHelper
|
|
17
|
+
include MaquinaComponents::SidebarHelper
|
|
18
|
+
include MaquinaComponents::ToastHelper
|
|
19
|
+
|
|
12
20
|
# Icon Override
|
|
13
21
|
#
|
|
14
22
|
# Override this method to use your own icon system (Heroicons, Lucide, etc.)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/generators/base"
|
|
4
|
+
|
|
5
|
+
module MaquinaComponents
|
|
6
|
+
module Generators
|
|
7
|
+
class ScaffoldTemplatesGenerator < Rails::Generators::Base
|
|
8
|
+
source_root File.expand_path("templates", __dir__)
|
|
9
|
+
|
|
10
|
+
desc "Copy maquina_components scaffold templates to your application"
|
|
11
|
+
|
|
12
|
+
TEMPLATE_FILES = %w[
|
|
13
|
+
_form.html.erb.tt
|
|
14
|
+
edit.html.erb.tt
|
|
15
|
+
index.html.erb.tt
|
|
16
|
+
new.html.erb.tt
|
|
17
|
+
partial.html.erb.tt
|
|
18
|
+
show.html.erb.tt
|
|
19
|
+
].freeze
|
|
20
|
+
|
|
21
|
+
def copy_templates
|
|
22
|
+
TEMPLATE_FILES.each do |filename|
|
|
23
|
+
copy_file filename, "lib/templates/erb/scaffold/#{filename}"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def show_post_install_message
|
|
28
|
+
say ""
|
|
29
|
+
say "Scaffold templates installed!", :green
|
|
30
|
+
say ""
|
|
31
|
+
say "Rails will now use maquina_components when you run:"
|
|
32
|
+
say " rails generate scaffold ModelName field:type"
|
|
33
|
+
say ""
|
|
34
|
+
say "Templates are in lib/templates/erb/scaffold/"
|
|
35
|
+
say "Feel free to customize them for your application."
|
|
36
|
+
say ""
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<%%= form_with(model: <%= model_resource_name %>, class: "space-y-4") do |form| %>
|
|
2
|
+
<%% if <%= singular_table_name %>.errors.any? %>
|
|
3
|
+
<%%= render "components/alert", variant: :destructive do %>
|
|
4
|
+
<%%= render "components/alert/title", text: "<%%= pluralize(<%= singular_table_name %>.errors.count, 'error') %> prohibited this <%= singular_table_name %> from being saved:" %>
|
|
5
|
+
<%%= render "components/alert/description" do %>
|
|
6
|
+
<ul class="list-disc list-inside mt-2">
|
|
7
|
+
<%% <%= singular_table_name %>.errors.each do |error| %>
|
|
8
|
+
<li><%%= error.full_message %></li>
|
|
9
|
+
<%% end %>
|
|
10
|
+
</ul>
|
|
11
|
+
<%% end %>
|
|
12
|
+
<%% end %>
|
|
13
|
+
<%% end %>
|
|
14
|
+
|
|
15
|
+
<% attributes.each do |attribute| -%>
|
|
16
|
+
<div class="space-y-2">
|
|
17
|
+
<% if attribute.password_digest? -%>
|
|
18
|
+
<%%= form.label :password %>
|
|
19
|
+
<%%= form.password_field :password, data: { component: "input" } %>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<div class="space-y-2">
|
|
23
|
+
<%%= form.label :password_confirmation %>
|
|
24
|
+
<%%= form.password_field :password_confirmation, data: { component: "input" } %>
|
|
25
|
+
<% elsif attribute.attachments? -%>
|
|
26
|
+
<%%= form.label :<%= attribute.column_name %> %>
|
|
27
|
+
<%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, multiple: true, data: { component: "input" } %>
|
|
28
|
+
<% elsif attribute.field_type == :text_area -%>
|
|
29
|
+
<%%= form.label :<%= attribute.column_name %> %>
|
|
30
|
+
<%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, data: { component: "textarea" } %>
|
|
31
|
+
<% elsif attribute.field_type == :check_box -%>
|
|
32
|
+
<div class="flex items-center gap-2">
|
|
33
|
+
<%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, data: { component: "checkbox" } %>
|
|
34
|
+
<%%= form.label :<%= attribute.column_name %> %>
|
|
35
|
+
</div>
|
|
36
|
+
<% elsif attribute.field_type == :select -%>
|
|
37
|
+
<%%= form.label :<%= attribute.column_name %> %>
|
|
38
|
+
<%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, [], {}, data: { component: "select" } %>
|
|
39
|
+
<% else -%>
|
|
40
|
+
<%%= form.label :<%= attribute.column_name %> %>
|
|
41
|
+
<%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, data: { component: "input" } %>
|
|
42
|
+
<% end -%>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<% end -%>
|
|
46
|
+
<div class="flex items-center gap-4 pt-4">
|
|
47
|
+
<%%= form.submit data: { component: "button", variant: "primary" } %>
|
|
48
|
+
</div>
|
|
49
|
+
<%% end %>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<%% content_for :title, "Editing <%= human_name.downcase %>" %>
|
|
2
|
+
|
|
3
|
+
<%% content_for :breadcrumbs do %>
|
|
4
|
+
<%%= render "components/breadcrumbs" do %>
|
|
5
|
+
<%%= render "components/breadcrumbs/list" do %>
|
|
6
|
+
<%%= render "components/breadcrumbs/item" do %>
|
|
7
|
+
<%%= render "components/breadcrumbs/link", href: <%= index_helper(type: :path) %>, text: "<%= human_name.pluralize %>" %>
|
|
8
|
+
<%% end %>
|
|
9
|
+
<%%= render "components/breadcrumbs/item" do %>
|
|
10
|
+
<%%= render "components/breadcrumbs/link", href: <%= model_resource_name(prefix: "@") %>, text: "<%= human_name %>" %>
|
|
11
|
+
<%% end %>
|
|
12
|
+
<%%= render "components/breadcrumbs/item" do %>
|
|
13
|
+
<%%= render "components/breadcrumbs/page", text: "Edit" %>
|
|
14
|
+
<%% end %>
|
|
15
|
+
<%% end %>
|
|
16
|
+
<%% end %>
|
|
17
|
+
<%% end %>
|
|
18
|
+
|
|
19
|
+
<div class="space-y-6">
|
|
20
|
+
<%%= render "components/card" do %>
|
|
21
|
+
<%%= render "components/card/header" do %>
|
|
22
|
+
<%%= render "components/card/title", text: "Editing <%= human_name.downcase %>" %>
|
|
23
|
+
<%% end %>
|
|
24
|
+
|
|
25
|
+
<%%= render "components/card/content" do %>
|
|
26
|
+
<%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %>
|
|
27
|
+
<%% end %>
|
|
28
|
+
<%% end %>
|
|
29
|
+
</div>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<%% content_for :title, "<%= human_name.pluralize %>" %>
|
|
2
|
+
|
|
3
|
+
<div class="space-y-6">
|
|
4
|
+
<%%= render "components/card" do %>
|
|
5
|
+
<%%= render "components/card/header", layout: :row do %>
|
|
6
|
+
<div>
|
|
7
|
+
<%%= render "components/card/title", text: "<%= human_name.pluralize %>" %>
|
|
8
|
+
<%%= render "components/card/description", text: "<%%= @<%= plural_table_name %>.size %> record(s)" %>
|
|
9
|
+
</div>
|
|
10
|
+
<%%= render "components/card/action" do %>
|
|
11
|
+
<%%= link_to "New <%= human_name.downcase %>", <%= new_helper(type: :path) %>, data: { component: "button", variant: "primary", size: "sm" } %>
|
|
12
|
+
<%% end %>
|
|
13
|
+
<%% end %>
|
|
14
|
+
|
|
15
|
+
<%%= render "components/card/content" do %>
|
|
16
|
+
<%% if @<%= plural_table_name %>.any? %>
|
|
17
|
+
<%%= render "components/table" do %>
|
|
18
|
+
<%%= render "components/table/header" do %>
|
|
19
|
+
<%%= render "components/table/row" do %>
|
|
20
|
+
<% attributes.reject(&:password_digest?).each do |attribute| -%>
|
|
21
|
+
<%%= render "components/table/head" do %><%= attribute.human_name %><%% end %>
|
|
22
|
+
<% end -%>
|
|
23
|
+
<%%= render "components/table/head" do %><%% end %>
|
|
24
|
+
<%% end %>
|
|
25
|
+
<%% end %>
|
|
26
|
+
<%%= render "components/table/body" do %>
|
|
27
|
+
<%% @<%= plural_table_name %>.each do |<%= singular_table_name %>| %>
|
|
28
|
+
<%%= render "components/table/row" do %>
|
|
29
|
+
<% attributes.reject(&:password_digest?).each do |attribute| -%>
|
|
30
|
+
<% if attribute.attachment? -%>
|
|
31
|
+
<%%= render "components/table/cell" do %><%%= link_to <%= singular_table_name %>.<%= attribute.column_name %>.filename, <%= singular_table_name %>.<%= attribute.column_name %> if <%= singular_table_name %>.<%= attribute.column_name %>.attached? %><%% end %>
|
|
32
|
+
<% elsif attribute.attachments? -%>
|
|
33
|
+
<%%= render "components/table/cell" do %><%%= <%= singular_table_name %>.<%= attribute.column_name %>.count %> file(s)<%% end %>
|
|
34
|
+
<% else -%>
|
|
35
|
+
<%%= render "components/table/cell" do %><%%= <%= singular_table_name %>.<%= attribute.column_name %> %><%% end %>
|
|
36
|
+
<% end -%>
|
|
37
|
+
<% end -%>
|
|
38
|
+
<%%= render "components/table/cell" do %>
|
|
39
|
+
<%%= link_to "Show this <%= human_name.downcase %>", <%= model_resource_name(singular_table_name) %>, data: { component: "button", variant: "ghost", size: "sm" } %>
|
|
40
|
+
<%% end %>
|
|
41
|
+
<%% end %>
|
|
42
|
+
<%% end %>
|
|
43
|
+
<%% end %>
|
|
44
|
+
<%% end %>
|
|
45
|
+
<%% else %>
|
|
46
|
+
<%%= render "components/empty" do %>
|
|
47
|
+
<%%= render "components/empty/header" do %>
|
|
48
|
+
<%%= render "components/empty/title", text: "No <%= human_name.pluralize.downcase %> yet" %>
|
|
49
|
+
<%%= render "components/empty/description", text: "Get started by creating a new <%= human_name.downcase %>." %>
|
|
50
|
+
<%% end %>
|
|
51
|
+
<%%= render "components/empty/content" do %>
|
|
52
|
+
<%%= link_to "New <%= human_name.downcase %>", <%= new_helper(type: :path) %>, data: { component: "button", variant: "primary" } %>
|
|
53
|
+
<%% end %>
|
|
54
|
+
<%% end %>
|
|
55
|
+
<%% end %>
|
|
56
|
+
<%% end %>
|
|
57
|
+
<%% end %>
|
|
58
|
+
</div>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<%% content_for :title, "New <%= human_name.downcase %>" %>
|
|
2
|
+
|
|
3
|
+
<%% content_for :breadcrumbs do %>
|
|
4
|
+
<%%= render "components/breadcrumbs" do %>
|
|
5
|
+
<%%= render "components/breadcrumbs/list" do %>
|
|
6
|
+
<%%= render "components/breadcrumbs/item" do %>
|
|
7
|
+
<%%= render "components/breadcrumbs/link", href: <%= index_helper(type: :path) %>, text: "<%= human_name.pluralize %>" %>
|
|
8
|
+
<%% end %>
|
|
9
|
+
<%%= render "components/breadcrumbs/item" do %>
|
|
10
|
+
<%%= render "components/breadcrumbs/page", text: "New" %>
|
|
11
|
+
<%% end %>
|
|
12
|
+
<%% end %>
|
|
13
|
+
<%% end %>
|
|
14
|
+
<%% end %>
|
|
15
|
+
|
|
16
|
+
<div class="space-y-6">
|
|
17
|
+
<%%= render "components/card" do %>
|
|
18
|
+
<%%= render "components/card/header" do %>
|
|
19
|
+
<%%= render "components/card/title", text: "New <%= human_name.downcase %>" %>
|
|
20
|
+
<%% end %>
|
|
21
|
+
|
|
22
|
+
<%%= render "components/card/content" do %>
|
|
23
|
+
<%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %>
|
|
24
|
+
<%% end %>
|
|
25
|
+
<%% end %>
|
|
26
|
+
</div>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<div id="<%%= dom_id <%= singular_name %> %>">
|
|
2
|
+
<% attributes.reject(&:password_digest?).each do |attribute| -%>
|
|
3
|
+
<div>
|
|
4
|
+
<strong class="text-sm font-medium text-muted-foreground"><%= attribute.human_name %>:</strong>
|
|
5
|
+
<% if attribute.attachment? -%>
|
|
6
|
+
<%%= link_to <%= singular_name %>.<%= attribute.column_name %>.filename, <%= singular_name %>.<%= attribute.column_name %> if <%= singular_name %>.<%= attribute.column_name %>.attached? %>
|
|
7
|
+
<% elsif attribute.attachments? -%>
|
|
8
|
+
<%% <%= singular_name %>.<%= attribute.column_name %>.each do |<%= attribute.singular_name %>| %>
|
|
9
|
+
<div><%%= link_to <%= attribute.singular_name %>.filename, <%= attribute.singular_name %> %></div>
|
|
10
|
+
<%% end %>
|
|
11
|
+
<% else -%>
|
|
12
|
+
<%%= <%= singular_name %>.<%= attribute.column_name %> %>
|
|
13
|
+
<% end -%>
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<% end -%>
|
|
17
|
+
</div>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<%% content_for :title, "<%= human_name %>" %>
|
|
2
|
+
|
|
3
|
+
<%% content_for :breadcrumbs do %>
|
|
4
|
+
<%%= render "components/breadcrumbs" do %>
|
|
5
|
+
<%%= render "components/breadcrumbs/list" do %>
|
|
6
|
+
<%%= render "components/breadcrumbs/item" do %>
|
|
7
|
+
<%%= render "components/breadcrumbs/link", href: <%= index_helper(type: :path) %>, text: "<%= human_name.pluralize %>" %>
|
|
8
|
+
<%% end %>
|
|
9
|
+
<%%= render "components/breadcrumbs/item" do %>
|
|
10
|
+
<%%= render "components/breadcrumbs/page", text: "<%= human_name %>" %>
|
|
11
|
+
<%% end %>
|
|
12
|
+
<%% end %>
|
|
13
|
+
<%% end %>
|
|
14
|
+
<%% end %>
|
|
15
|
+
|
|
16
|
+
<div class="space-y-6">
|
|
17
|
+
<%%= render "components/card" do %>
|
|
18
|
+
<%%= render "components/card/header", layout: :row do %>
|
|
19
|
+
<div>
|
|
20
|
+
<%%= render "components/card/title", text: "<%= human_name %>" %>
|
|
21
|
+
</div>
|
|
22
|
+
<%%= render "components/card/action" do %>
|
|
23
|
+
<%%= link_to "Edit this <%= human_name.downcase %>", <%= edit_helper(type: :path) %>, data: { component: "button", variant: "outline", size: "sm" } %>
|
|
24
|
+
<%% end %>
|
|
25
|
+
<%% end %>
|
|
26
|
+
|
|
27
|
+
<%%= render "components/card/content" do %>
|
|
28
|
+
<dl class="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
|
29
|
+
<% attributes.reject(&:password_digest?).each do |attribute| -%>
|
|
30
|
+
<div>
|
|
31
|
+
<dt class="text-sm font-medium text-muted-foreground"><%= attribute.human_name %></dt>
|
|
32
|
+
<% if attribute.attachment? -%>
|
|
33
|
+
<dd class="mt-1"><%%= link_to @<%= singular_table_name %>.<%= attribute.column_name %>.filename, @<%= singular_table_name %>.<%= attribute.column_name %> if @<%= singular_table_name %>.<%= attribute.column_name %>.attached? %></dd>
|
|
34
|
+
<% elsif attribute.attachments? -%>
|
|
35
|
+
<dd class="mt-1">
|
|
36
|
+
<%% @<%= singular_table_name %>.<%= attribute.column_name %>.each do |<%= attribute.singular_name %>| %>
|
|
37
|
+
<div><%%= link_to <%= attribute.singular_name %>.filename, <%= attribute.singular_name %> %></div>
|
|
38
|
+
<%% end %>
|
|
39
|
+
</dd>
|
|
40
|
+
<% else -%>
|
|
41
|
+
<dd class="mt-1"><%%= @<%= singular_table_name %>.<%= attribute.column_name %> %></dd>
|
|
42
|
+
<% end -%>
|
|
43
|
+
</div>
|
|
44
|
+
<% end -%>
|
|
45
|
+
</dl>
|
|
46
|
+
<%% end %>
|
|
47
|
+
|
|
48
|
+
<%%= render "components/card/footer" do %>
|
|
49
|
+
<%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %>, data: { component: "button", variant: "ghost" } %>
|
|
50
|
+
<%%= button_to "Destroy this <%= human_name.downcase %>", <%= model_resource_name(prefix: "@") %>, method: :delete, data: { component: "button", variant: "destructive" } %>
|
|
51
|
+
<%% end %>
|
|
52
|
+
<%% end %>
|
|
53
|
+
</div>
|
data/lib/maquina-components.rb
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
module MaquinaComponents
|
|
2
2
|
class Engine < ::Rails::Engine
|
|
3
3
|
initializer "maquina-components.importmap", before: "importmap" do |app|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
# Hosts bundling JS without importmap-rails (esbuild, vite, bun)
|
|
5
|
+
# have no config.importmap; skip so the engine doesn't break boot.
|
|
6
|
+
if app.config.respond_to?(:importmap)
|
|
7
|
+
app.config.importmap.paths << root.join("config/importmap.rb")
|
|
8
|
+
app.config.importmap.cache_sweepers << root.join("app/javascript")
|
|
9
|
+
end
|
|
6
10
|
end
|
|
7
11
|
|
|
8
|
-
initializer "
|
|
12
|
+
initializer "maquina-components.assets" do |app|
|
|
9
13
|
if app.config.respond_to?(:assets)
|
|
10
14
|
app.config.assets.paths << Engine.root.join("app/javascript")
|
|
11
15
|
end
|