better_ui 0.4.0 → 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 +141 -189
- data/app/assets/stylesheets/better_ui/_base.scss +9 -0
- data/app/assets/stylesheets/better_ui/_components.scss +2 -0
- data/app/assets/stylesheets/better_ui/_utilities.scss +14 -0
- data/app/assets/stylesheets/better_ui/application.css +3 -1
- data/app/assets/stylesheets/better_ui/components/_avatar.scss +200 -0
- data/app/assets/stylesheets/better_ui/components/_badge.scss +154 -0
- data/app/assets/stylesheets/better_ui/components/_breadcrumb.scss +106 -0
- data/app/assets/stylesheets/better_ui/components/_button.scss +105 -0
- data/app/assets/stylesheets/better_ui/components/_card.scss +60 -0
- data/app/assets/stylesheets/better_ui/components/_heading.scss +81 -0
- data/app/assets/stylesheets/better_ui/components/_icon.scss +134 -0
- data/app/assets/stylesheets/better_ui/components/_index.scss +17 -0
- data/app/assets/stylesheets/better_ui/components/_link.scss +100 -0
- data/app/assets/stylesheets/better_ui/components/_panel.scss +104 -0
- data/app/assets/stylesheets/better_ui/components/_spinner.scss +129 -0
- data/app/assets/stylesheets/better_ui/components/_table.scss +156 -0
- data/app/assets/stylesheets/better_ui/components/_variables.scss +1 -0
- data/app/assets/stylesheets/better_ui.scss +4 -0
- data/app/components/better_ui/application/alert_component.html.erb +1 -1
- data/app/components/better_ui/application/alert_component.rb +95 -89
- data/app/components/better_ui/application/card_component.html.erb +24 -0
- data/app/components/better_ui/application/card_component.rb +53 -0
- data/app/components/better_ui/application/card_container_component.html.erb +8 -0
- data/app/components/better_ui/application/card_container_component.rb +14 -0
- data/app/components/better_ui/application/toast_component.rb +92 -57
- data/app/components/better_ui/general/avatar_component.html.erb +19 -0
- data/app/components/better_ui/general/avatar_component.rb +171 -0
- data/app/components/better_ui/general/badge_component.html.erb +19 -0
- data/app/components/better_ui/general/badge_component.rb +135 -0
- data/app/components/better_ui/general/breadcrumb_component.html.erb +7 -31
- data/app/components/better_ui/general/breadcrumb_component.rb +64 -66
- data/app/components/better_ui/general/button_component.html.erb +6 -6
- data/app/components/better_ui/general/button_component.rb +62 -95
- data/app/components/better_ui/general/heading_component.html.erb +1 -25
- data/app/components/better_ui/general/heading_component.rb +20 -113
- data/app/components/better_ui/general/icon_component.rb +37 -61
- data/app/components/better_ui/general/link_component.html.erb +17 -0
- data/app/components/better_ui/general/link_component.rb +132 -0
- data/app/components/better_ui/general/panel_component.rb +51 -56
- data/app/components/better_ui/general/spinner_component.html.erb +15 -0
- data/app/components/better_ui/general/spinner_component.rb +79 -0
- data/app/components/better_ui/general/table_component.html.erb +56 -20
- data/app/components/better_ui/general/table_component.rb +89 -87
- data/app/helpers/better_ui/general/components/avatar_helper.rb +17 -0
- data/app/helpers/better_ui/general/components/badge_helper.rb +17 -0
- data/app/helpers/better_ui/general/components/breadcrumb_helper.rb +17 -0
- data/app/helpers/better_ui/general/components/button_helper.rb +17 -0
- data/app/helpers/better_ui/general/components/heading_helper.rb +17 -0
- data/app/helpers/better_ui/general/components/icon_helper.rb +17 -0
- data/app/helpers/better_ui/general/components/link_helper.rb +17 -0
- data/app/helpers/better_ui/general/components/panel_helper.rb +16 -0
- data/app/helpers/better_ui/general/components/spinner_helper.rb +17 -0
- data/app/helpers/better_ui/general/components/table_helper.rb +17 -0
- data/app/helpers/better_ui/general_helper.rb +15 -0
- data/app/helpers/better_ui_helper.rb +12 -0
- data/app/views/components/better_ui/general/table/_custom_body_row.html.erb +17 -0
- data/app/views/components/better_ui/general/table/_custom_footer_rows.html.erb +17 -0
- data/app/views/components/better_ui/general/table/_custom_header_rows.html.erb +12 -0
- data/config/routes.rb +2 -13
- data/lib/better_ui/engine.rb +66 -16
- data/lib/better_ui/version.rb +1 -1
- data/lib/better_ui.rb +12 -0
- data/lib/generators/better_ui/install_generator.rb +103 -0
- data/lib/generators/better_ui/stylesheet_generator.rb +159 -0
- data/lib/generators/better_ui/templates/README +125 -0
- data/lib/generators/better_ui/templates/components/_avatar.scss +200 -0
- data/lib/generators/better_ui/templates/components/_badge.scss +154 -0
- data/lib/generators/better_ui/templates/components/_breadcrumb.scss +106 -0
- data/lib/generators/better_ui/templates/components/_button.scss +109 -0
- data/lib/generators/better_ui/templates/components/_card.scss +60 -0
- data/lib/generators/better_ui/templates/components/_heading.scss +81 -0
- data/lib/generators/better_ui/templates/components/_icon.scss +134 -0
- data/lib/generators/better_ui/templates/components/_index.scss +17 -0
- data/lib/generators/better_ui/templates/components/_link.scss +100 -0
- data/lib/generators/better_ui/templates/components/_panel.scss +104 -0
- data/lib/generators/better_ui/templates/components/_spinner.scss +129 -0
- data/lib/generators/better_ui/templates/components/_table.scss +156 -0
- data/lib/generators/better_ui/templates/components/_variables.scss +0 -0
- data/lib/generators/better_ui/templates/components_stylesheet.scss +35 -0
- data/lib/generators/better_ui/templates/index.scss +18 -0
- data/lib/generators/better_ui/templates/initializer.rb +41 -0
- metadata +120 -49
- data/app/assets/javascripts/better_ui/controllers/navbar_controller.js +0 -138
- data/app/assets/javascripts/better_ui/controllers/sidebar_controller.js +0 -211
- data/app/assets/javascripts/better_ui/controllers/toast_controller.js +0 -161
- data/app/assets/javascripts/better_ui/index.js +0 -159
- data/app/assets/javascripts/better_ui/toast_manager.js +0 -77
- data/app/components/better_ui/theme_helper.rb +0 -169
- data/app/controllers/better_ui/docs_controller.rb +0 -34
- data/app/helpers/better_ui_application_helper.rb +0 -99
@@ -0,0 +1,132 @@
|
|
1
|
+
module BetterUi
|
2
|
+
module General
|
3
|
+
class LinkComponent < ViewComponent::Base
|
4
|
+
attr_reader :label, :href, :theme, :icon, :classes, :active, :data, :method, :target
|
5
|
+
|
6
|
+
# Temi di colore disponibili
|
7
|
+
LINK_THEME = {
|
8
|
+
default: {
|
9
|
+
link: "bui-link--default",
|
10
|
+
active: "bui-link--active bui-link--default",
|
11
|
+
text: "bui-link--text bui-link--default"
|
12
|
+
},
|
13
|
+
white: {
|
14
|
+
link: "bui-link--white",
|
15
|
+
active: "bui-link--active bui-link--white",
|
16
|
+
text: "bui-link--text bui-link--white"
|
17
|
+
},
|
18
|
+
red: {
|
19
|
+
link: "bui-link--red",
|
20
|
+
active: "bui-link--active bui-link--red",
|
21
|
+
text: "bui-link--text bui-link--red"
|
22
|
+
},
|
23
|
+
rose: {
|
24
|
+
link: "bui-link--rose",
|
25
|
+
active: "bui-link--active bui-link--rose",
|
26
|
+
text: "bui-link--text bui-link--rose"
|
27
|
+
},
|
28
|
+
orange: {
|
29
|
+
link: "bui-link--orange",
|
30
|
+
active: "bui-link--active bui-link--orange",
|
31
|
+
text: "bui-link--text bui-link--orange"
|
32
|
+
},
|
33
|
+
green: {
|
34
|
+
link: "bui-link--green",
|
35
|
+
active: "bui-link--active bui-link--green",
|
36
|
+
text: "bui-link--text bui-link--green"
|
37
|
+
},
|
38
|
+
blue: {
|
39
|
+
link: "bui-link--blue",
|
40
|
+
active: "bui-link--active bui-link--blue",
|
41
|
+
text: "bui-link--text bui-link--blue"
|
42
|
+
},
|
43
|
+
yellow: {
|
44
|
+
link: "bui-link--yellow",
|
45
|
+
active: "bui-link--active bui-link--yellow",
|
46
|
+
text: "bui-link--text bui-link--yellow"
|
47
|
+
},
|
48
|
+
violet: {
|
49
|
+
link: "bui-link--violet",
|
50
|
+
active: "bui-link--active bui-link--violet",
|
51
|
+
text: "bui-link--text bui-link--violet"
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
# Inizializzazione del componente
|
56
|
+
def initialize(
|
57
|
+
label:,
|
58
|
+
href: nil,
|
59
|
+
theme: :default,
|
60
|
+
icon: nil,
|
61
|
+
classes: nil,
|
62
|
+
active: false,
|
63
|
+
data: {},
|
64
|
+
method: nil,
|
65
|
+
target: nil
|
66
|
+
)
|
67
|
+
@label = label
|
68
|
+
@href = href
|
69
|
+
@theme = theme.to_sym
|
70
|
+
@icon = icon
|
71
|
+
@classes = classes
|
72
|
+
@active = active
|
73
|
+
@data = data || {}
|
74
|
+
@method = method
|
75
|
+
@target = target
|
76
|
+
end
|
77
|
+
|
78
|
+
# Determina se è un link attivo/corrente
|
79
|
+
def active?
|
80
|
+
@active
|
81
|
+
end
|
82
|
+
|
83
|
+
# Determina se è un link o solo testo
|
84
|
+
def link?
|
85
|
+
@href.present?
|
86
|
+
end
|
87
|
+
|
88
|
+
# Genera le classi per il componente
|
89
|
+
def component_classes
|
90
|
+
theme_classes = LINK_THEME.fetch(@theme, LINK_THEME[:default])
|
91
|
+
|
92
|
+
base_classes = ["bui-link"]
|
93
|
+
|
94
|
+
if active?
|
95
|
+
base_classes << theme_classes[:active]
|
96
|
+
elsif link?
|
97
|
+
base_classes << theme_classes[:link]
|
98
|
+
else
|
99
|
+
base_classes << theme_classes[:text]
|
100
|
+
end
|
101
|
+
|
102
|
+
base_classes << @classes if @classes.present?
|
103
|
+
|
104
|
+
base_classes.compact.join(" ")
|
105
|
+
end
|
106
|
+
|
107
|
+
# Restituisce gli attributi per il link
|
108
|
+
def link_attributes
|
109
|
+
attrs = {
|
110
|
+
class: component_classes
|
111
|
+
}
|
112
|
+
|
113
|
+
attrs[:data] = @data.merge(turbo_method: @method) if @method.present?
|
114
|
+
attrs[:data] = @data if @data.present? && !@method.present?
|
115
|
+
attrs[:target] = @target if @target.present?
|
116
|
+
|
117
|
+
attrs
|
118
|
+
end
|
119
|
+
|
120
|
+
# Renderizza l'icona
|
121
|
+
def render_icon
|
122
|
+
return nil unless @icon.present?
|
123
|
+
|
124
|
+
if @icon.is_a?(String)
|
125
|
+
render BetterUi::General::IconComponent.new(name: @icon)
|
126
|
+
else
|
127
|
+
@icon # Assumiamo che sia già un componente renderizzato
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -1,92 +1,87 @@
|
|
1
1
|
module BetterUi
|
2
2
|
module General
|
3
3
|
class PanelComponent < ViewComponent::Base
|
4
|
-
attr_reader :header, :footer, :body, :title, :padding, :variant
|
4
|
+
attr_reader :header, :footer, :body, :title, :padding, :variant, :rounded
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
# Opzioni di padding disponibili
|
7
|
+
PANEL_PADDING = {
|
8
|
+
none: 'bui-panel--padding-none',
|
9
|
+
small: 'bui-panel--padding-small',
|
10
|
+
medium: 'bui-panel--padding-medium',
|
11
|
+
large: 'bui-panel--padding-large'
|
11
12
|
}.freeze
|
12
13
|
|
13
|
-
|
14
|
+
# Temi di colore per il panel
|
15
|
+
PANEL_THEME = {
|
16
|
+
default: 'bui-panel--default',
|
17
|
+
white: 'bui-panel--white',
|
18
|
+
red: 'bui-panel--red',
|
19
|
+
rose: 'bui-panel--rose',
|
20
|
+
orange: 'bui-panel--orange',
|
21
|
+
green: 'bui-panel--green',
|
22
|
+
blue: 'bui-panel--blue',
|
23
|
+
yellow: 'bui-panel--yellow',
|
24
|
+
violet: 'bui-panel--violet'
|
25
|
+
}.freeze
|
26
|
+
|
27
|
+
# Opzioni di bordi arrotondati standardizzati
|
28
|
+
PANEL_RADIUS = {
|
29
|
+
none: 'bui-panel--radius-none',
|
30
|
+
small: 'bui-panel--radius-small',
|
31
|
+
medium: 'bui-panel--radius-medium',
|
32
|
+
large: 'bui-panel--radius-large',
|
33
|
+
full: 'bui-panel--radius-full'
|
34
|
+
}.freeze
|
35
|
+
|
36
|
+
def initialize(title: nil, body: nil, header: nil, footer: nil, padding: :medium, variant: :default, rounded: :small)
|
14
37
|
@title = title
|
15
38
|
@body = body
|
16
39
|
@header = header
|
17
40
|
@footer = footer
|
18
41
|
@padding = padding.to_sym
|
19
42
|
@variant = variant.to_sym
|
43
|
+
@rounded = rounded.to_sym
|
20
44
|
end
|
21
45
|
|
22
46
|
def panel_classes
|
23
|
-
|
47
|
+
[
|
48
|
+
'bui-panel',
|
49
|
+
get_theme_class,
|
50
|
+
get_border_radius_class
|
51
|
+
].compact.join(' ')
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_border_radius_class
|
55
|
+
PANEL_RADIUS[@rounded] || PANEL_RADIUS[:small]
|
56
|
+
end
|
57
|
+
|
58
|
+
def get_theme_class
|
59
|
+
PANEL_THEME[@variant] || PANEL_THEME[:default]
|
24
60
|
end
|
25
61
|
|
26
62
|
def header_classes
|
27
63
|
[
|
28
|
-
'
|
29
|
-
|
30
|
-
header_color_classes,
|
31
|
-
PADDING_OPTIONS.fetch(@padding, PADDING_OPTIONS[:medium])
|
64
|
+
'bui-panel__header',
|
65
|
+
PANEL_PADDING.fetch(@padding, PANEL_PADDING[:medium])
|
32
66
|
].compact.join(' ')
|
33
67
|
end
|
34
68
|
|
35
69
|
def body_classes
|
36
70
|
[
|
37
|
-
'
|
38
|
-
|
39
|
-
'overflow-x-auto break-words',
|
40
|
-
PADDING_OPTIONS.fetch(@padding, PADDING_OPTIONS[:medium])
|
71
|
+
'bui-panel__body',
|
72
|
+
PANEL_PADDING.fetch(@padding, PANEL_PADDING[:medium])
|
41
73
|
].compact.join(' ')
|
42
74
|
end
|
43
75
|
|
44
76
|
def footer_classes
|
45
77
|
[
|
46
|
-
'
|
47
|
-
|
48
|
-
footer_color_classes,
|
49
|
-
'overflow-x-auto break-words',
|
50
|
-
PADDING_OPTIONS.fetch(@padding, PADDING_OPTIONS[:medium])
|
78
|
+
'bui-panel__footer',
|
79
|
+
PANEL_PADDING.fetch(@padding, PANEL_PADDING[:medium])
|
51
80
|
].compact.join(' ')
|
52
81
|
end
|
53
82
|
|
54
83
|
def title_classes
|
55
|
-
'
|
56
|
-
end
|
57
|
-
|
58
|
-
def header_color_classes
|
59
|
-
case @variant
|
60
|
-
when :primary
|
61
|
-
'bg-orange-50 text-orange-700'
|
62
|
-
when :success
|
63
|
-
'bg-green-50 text-green-700'
|
64
|
-
when :warning
|
65
|
-
'bg-amber-50 text-amber-700'
|
66
|
-
when :danger
|
67
|
-
'bg-red-50 text-red-700'
|
68
|
-
when :info
|
69
|
-
'bg-blue-50 text-blue-700'
|
70
|
-
else
|
71
|
-
'bg-gray-50 text-gray-700'
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def footer_color_classes
|
76
|
-
case @variant
|
77
|
-
when :primary
|
78
|
-
'bg-orange-50 text-orange-600'
|
79
|
-
when :success
|
80
|
-
'bg-green-50 text-green-600'
|
81
|
-
when :warning
|
82
|
-
'bg-amber-50 text-amber-600'
|
83
|
-
when :danger
|
84
|
-
'bg-red-50 text-red-600'
|
85
|
-
when :info
|
86
|
-
'bg-blue-50 text-blue-600'
|
87
|
-
else
|
88
|
-
'bg-gray-50 text-gray-600'
|
89
|
-
end
|
84
|
+
'bui-panel__title'
|
90
85
|
end
|
91
86
|
|
92
87
|
def render?
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<div <%= spinner_attributes.to_s.html_safe %>>
|
2
|
+
<div class="bui-spinner__animation"></div>
|
3
|
+
|
4
|
+
<% if @label.present? %>
|
5
|
+
<div class="bui-spinner__label">
|
6
|
+
<%= @label %>
|
7
|
+
</div>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<% if content.present? %>
|
11
|
+
<div class="bui-spinner__content">
|
12
|
+
<%= content %>
|
13
|
+
</div>
|
14
|
+
<% end %>
|
15
|
+
</div>
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module BetterUi
|
2
|
+
module General
|
3
|
+
class SpinnerComponent < ViewComponent::Base
|
4
|
+
attr_reader :size, :theme, :fullscreen, :label, :classes, :id
|
5
|
+
|
6
|
+
# Temi di colore disponibili
|
7
|
+
SPINNER_THEME = {
|
8
|
+
default: "bui-spinner--default",
|
9
|
+
white: "bui-spinner--white",
|
10
|
+
red: "bui-spinner--red",
|
11
|
+
rose: "bui-spinner--rose",
|
12
|
+
orange: "bui-spinner--orange",
|
13
|
+
green: "bui-spinner--green",
|
14
|
+
blue: "bui-spinner--blue",
|
15
|
+
yellow: "bui-spinner--yellow",
|
16
|
+
violet: "bui-spinner--violet"
|
17
|
+
}
|
18
|
+
|
19
|
+
# Dimensioni disponibili
|
20
|
+
SPINNER_SIZES = {
|
21
|
+
small: "bui-spinner--small",
|
22
|
+
medium: "bui-spinner--medium",
|
23
|
+
large: "bui-spinner--large"
|
24
|
+
}
|
25
|
+
|
26
|
+
# Stati e comportamenti dello spinner
|
27
|
+
SPINNER_STATES = {
|
28
|
+
fullscreen: "bui-spinner--fullscreen"
|
29
|
+
}
|
30
|
+
|
31
|
+
# Inizializzazione del componente
|
32
|
+
def initialize(
|
33
|
+
size: :medium,
|
34
|
+
theme: :default,
|
35
|
+
fullscreen: false,
|
36
|
+
label: nil,
|
37
|
+
classes: nil,
|
38
|
+
id: nil
|
39
|
+
)
|
40
|
+
@size = size.to_sym
|
41
|
+
@theme = theme.to_sym
|
42
|
+
@fullscreen = fullscreen
|
43
|
+
@label = label
|
44
|
+
@classes = classes
|
45
|
+
@id = id
|
46
|
+
end
|
47
|
+
|
48
|
+
# Combina tutte le classi
|
49
|
+
def combined_classes
|
50
|
+
[
|
51
|
+
"bui-spinner", # Classe base per tutti gli spinner
|
52
|
+
get_spinner_theme_class,
|
53
|
+
get_spinner_size_class,
|
54
|
+
@fullscreen ? SPINNER_STATES[:fullscreen] : "",
|
55
|
+
@classes
|
56
|
+
].compact.join(" ")
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_spinner_theme_class
|
60
|
+
SPINNER_THEME[@theme] || SPINNER_THEME[:default]
|
61
|
+
end
|
62
|
+
|
63
|
+
def get_spinner_size_class
|
64
|
+
SPINNER_SIZES[@size] || SPINNER_SIZES[:medium]
|
65
|
+
end
|
66
|
+
|
67
|
+
# Restituisce gli attributi per lo spinner
|
68
|
+
def spinner_attributes
|
69
|
+
attrs = {
|
70
|
+
class: combined_classes,
|
71
|
+
id: @id,
|
72
|
+
role: "status"
|
73
|
+
}
|
74
|
+
|
75
|
+
attrs
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -7,31 +7,67 @@
|
|
7
7
|
<% end %>
|
8
8
|
|
9
9
|
<thead class="<%= thead_classes %>">
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
10
|
+
<% if header_rows_partial.present? %>
|
11
|
+
<%= render partial: header_rows_partial, locals: {
|
12
|
+
component: self,
|
13
|
+
headers: headers_for_display
|
14
|
+
} %>
|
15
|
+
<% else %>
|
16
|
+
<tr>
|
17
|
+
<% headers_for_display.each do |header| %>
|
18
|
+
<th scope="col" class="<%= th_classes %>">
|
19
|
+
<%= header.to_s.humanize %>
|
20
|
+
</th>
|
21
|
+
<% end %>
|
22
|
+
</tr>
|
23
|
+
<% end %>
|
17
24
|
</thead>
|
18
25
|
|
19
26
|
<tbody class="<%= tbody_classes %>">
|
20
27
|
<% data.each_with_index do |row, index| %>
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
28
|
+
<% if body_row_partial.present? %>
|
29
|
+
<%= render partial: body_row_partial, locals: {
|
30
|
+
component: self,
|
31
|
+
row: row,
|
32
|
+
index: index,
|
33
|
+
headers: headers_for_display
|
34
|
+
} %>
|
35
|
+
<% else %>
|
36
|
+
<tr class="<%= tr_classes(index) %>">
|
37
|
+
<% headers_for_display.each do |header| %>
|
38
|
+
<td class="<%= td_classes %>">
|
39
|
+
<% if row.is_a?(Hash) %>
|
40
|
+
<%= row[header.to_s] || row[header.to_sym] %>
|
41
|
+
<% elsif row.respond_to?(header.to_sym) %>
|
42
|
+
<%= row.send(header.to_sym) %>
|
43
|
+
<% else %>
|
44
|
+
—
|
45
|
+
<% end %>
|
46
|
+
</td>
|
47
|
+
<% end %>
|
48
|
+
</tr>
|
49
|
+
<% end %>
|
34
50
|
<% end %>
|
35
51
|
</tbody>
|
52
|
+
|
53
|
+
<% if footer.present? %>
|
54
|
+
<tfoot class="<%= tfoot_classes %>">
|
55
|
+
<% if footer_rows_partial.present? %>
|
56
|
+
<%= render partial: footer_rows_partial, locals: {
|
57
|
+
component: self,
|
58
|
+
footer: footer,
|
59
|
+
headers: headers_for_display
|
60
|
+
} %>
|
61
|
+
<% else %>
|
62
|
+
<tr>
|
63
|
+
<% footer.each_with_index do |value, index| %>
|
64
|
+
<td class="<%= tf_classes %>">
|
65
|
+
<%= value || "—" %>
|
66
|
+
</td>
|
67
|
+
<% end %>
|
68
|
+
</tr>
|
69
|
+
<% end %>
|
70
|
+
</tfoot>
|
71
|
+
<% end %>
|
36
72
|
</table>
|
37
73
|
</div>
|
@@ -1,137 +1,139 @@
|
|
1
1
|
module BetterUi
|
2
2
|
module General
|
3
3
|
class TableComponent < ViewComponent::Base
|
4
|
-
attr_reader :data, :headers, :caption, :striped, :hoverable, :bordered, :compact, :classes, :variant
|
4
|
+
attr_reader :data, :headers, :caption, :striped, :hoverable, :bordered, :compact, :classes, :variant, :rounded, :footer,
|
5
|
+
:header_rows_partial, :body_row_partial, :footer_rows_partial
|
5
6
|
|
6
|
-
|
7
|
+
# Costanti per configurazione stili
|
8
|
+
TABLE_THEMES = {
|
9
|
+
default: "bui-table--default",
|
10
|
+
white: "bui-table--white",
|
11
|
+
red: "bui-table--red",
|
12
|
+
rose: "bui-table--rose",
|
13
|
+
orange: "bui-table--orange",
|
14
|
+
green: "bui-table--green",
|
15
|
+
blue: "bui-table--blue",
|
16
|
+
yellow: "bui-table--yellow",
|
17
|
+
violet: "bui-table--violet"
|
18
|
+
}.freeze
|
19
|
+
|
20
|
+
# Opzioni di bordi arrotondati standardizzati
|
21
|
+
TABLE_RADIUS = {
|
22
|
+
none: "bui-table--radius-none",
|
23
|
+
small: "bui-table--radius-small",
|
24
|
+
medium: "bui-table--radius-medium",
|
25
|
+
large: "bui-table--radius-large",
|
26
|
+
full: "bui-table--radius-full"
|
27
|
+
}.freeze
|
28
|
+
|
29
|
+
def initialize(data:, headers: nil, caption: nil, striped: false, hoverable: false, bordered: true, compact: false, classes: nil, variant: :default, rounded: :small, footer: nil, header_rows_partial: nil, body_row_partial: nil, footer_rows_partial: nil)
|
7
30
|
@data = data || []
|
8
31
|
@headers = headers
|
9
32
|
@caption = caption
|
10
|
-
@striped = striped
|
11
|
-
@hoverable = hoverable
|
12
|
-
@bordered = bordered
|
13
|
-
@compact = compact
|
33
|
+
@striped = !!striped
|
34
|
+
@hoverable = !!hoverable
|
35
|
+
@bordered = !!bordered
|
36
|
+
@compact = !!compact
|
14
37
|
@classes = classes
|
15
|
-
@variant = variant.to_sym
|
38
|
+
@variant = (TABLE_THEMES.key?(variant.to_sym) ? variant.to_sym : :default)
|
39
|
+
@rounded = (TABLE_RADIUS.key?(rounded.to_sym) ? rounded.to_sym : :small)
|
40
|
+
@footer = footer.is_a?(Array) ? footer : nil # Valida che sia un array
|
41
|
+
@header_rows_partial = header_rows_partial
|
42
|
+
@body_row_partial = body_row_partial
|
43
|
+
@footer_rows_partial = footer_rows_partial
|
16
44
|
end
|
17
45
|
|
18
46
|
def table_classes
|
19
|
-
|
47
|
+
[
|
48
|
+
"bui-table",
|
49
|
+
get_theme_class,
|
50
|
+
@bordered ? "bui-table--bordered" : nil,
|
51
|
+
@striped ? "bui-table--striped" : nil,
|
52
|
+
@hoverable ? "bui-table--hoverable" : nil,
|
53
|
+
@compact ? "bui-table--compact" : nil,
|
54
|
+
@classes
|
55
|
+
].compact.join(" ")
|
20
56
|
end
|
21
57
|
|
22
58
|
def table_container_classes
|
23
59
|
[
|
24
|
-
|
25
|
-
|
26
|
-
].compact.join(
|
60
|
+
"bui-table__container",
|
61
|
+
get_border_radius_class
|
62
|
+
].compact.join(" ")
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_border_radius_class
|
66
|
+
TABLE_RADIUS[@rounded] || TABLE_RADIUS[:small]
|
67
|
+
end
|
68
|
+
|
69
|
+
def get_theme_class
|
70
|
+
TABLE_THEMES[@variant] || TABLE_THEMES[:default]
|
27
71
|
end
|
28
72
|
|
29
73
|
def caption_classes
|
30
|
-
|
31
|
-
'px-4 py-2',
|
32
|
-
'text-sm font-medium text-left',
|
33
|
-
caption_color_classes,
|
34
|
-
@bordered ? "border-b #{get_border_color}" : nil
|
35
|
-
].compact.join(' ')
|
74
|
+
"bui-table__caption"
|
36
75
|
end
|
37
76
|
|
38
77
|
def thead_classes
|
39
|
-
|
78
|
+
"bui-table__header"
|
40
79
|
end
|
41
80
|
|
42
81
|
def tbody_classes
|
43
|
-
|
82
|
+
"bui-table__body"
|
83
|
+
end
|
84
|
+
|
85
|
+
def tfoot_classes
|
86
|
+
"bui-table__footer"
|
44
87
|
end
|
45
88
|
|
46
89
|
def tr_classes(index)
|
47
|
-
|
48
|
-
@hoverable ? ThemeHelper::LAYOUT_STYLES[:table][:row][:hover] : nil,
|
49
|
-
@striped ? nil : (index.odd? ? 'bg-gray-50' : nil)
|
50
|
-
].compact.join(' ')
|
90
|
+
"bui-table__row"
|
51
91
|
end
|
52
92
|
|
53
93
|
def th_classes
|
54
94
|
[
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
@bordered ? "border #{get_border_color}" : nil
|
59
|
-
].compact.join(' ')
|
95
|
+
"bui-table__cell",
|
96
|
+
"bui-table__cell--header"
|
97
|
+
].compact.join(" ")
|
60
98
|
end
|
61
99
|
|
62
100
|
def td_classes
|
63
|
-
|
64
|
-
@compact ? 'px-2 py-1' : 'px-4 py-3',
|
65
|
-
@bordered ? "border #{get_border_color}" : nil,
|
66
|
-
'text-sm'
|
67
|
-
].compact.join(' ')
|
101
|
+
"bui-table__cell"
|
68
102
|
end
|
69
103
|
|
70
|
-
def
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
'border-green-200'
|
76
|
-
when :warning
|
77
|
-
'border-amber-200'
|
78
|
-
when :danger
|
79
|
-
'border-red-200'
|
80
|
-
when :info
|
81
|
-
'border-blue-200'
|
82
|
-
else
|
83
|
-
'border-gray-200'
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def caption_color_classes
|
88
|
-
case @variant
|
89
|
-
when :primary
|
90
|
-
'bg-orange-50 text-orange-700'
|
91
|
-
when :success
|
92
|
-
'bg-green-50 text-green-700'
|
93
|
-
when :warning
|
94
|
-
'bg-amber-50 text-amber-700'
|
95
|
-
when :danger
|
96
|
-
'bg-red-50 text-red-700'
|
97
|
-
when :info
|
98
|
-
'bg-blue-50 text-blue-700'
|
99
|
-
else
|
100
|
-
'bg-gray-50 text-gray-700'
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
def th_color_classes
|
105
|
-
case @variant
|
106
|
-
when :primary
|
107
|
-
'text-orange-700'
|
108
|
-
when :success
|
109
|
-
'text-green-700'
|
110
|
-
when :warning
|
111
|
-
'text-amber-700'
|
112
|
-
when :danger
|
113
|
-
'text-red-700'
|
114
|
-
when :info
|
115
|
-
'text-blue-700'
|
116
|
-
else
|
117
|
-
'text-gray-700'
|
118
|
-
end
|
104
|
+
def tf_classes
|
105
|
+
[
|
106
|
+
"bui-table__cell",
|
107
|
+
"bui-table__cell--footer"
|
108
|
+
].compact.join(" ")
|
119
109
|
end
|
120
110
|
|
121
111
|
def headers_for_display
|
122
112
|
return @headers if @headers.present?
|
123
113
|
return [] if @data.empty?
|
124
114
|
|
125
|
-
|
126
|
-
|
127
|
-
if first_item.is_a?(Hash)
|
115
|
+
case first_item = @data.first
|
116
|
+
when Hash
|
128
117
|
first_item.keys
|
129
|
-
|
130
|
-
first_item.attributes.keys - [
|
118
|
+
when -> (item) { item.respond_to?(:attributes) }
|
119
|
+
first_item.attributes.keys - %w[id created_at updated_at]
|
131
120
|
else
|
132
121
|
[]
|
133
122
|
end
|
134
123
|
end
|
124
|
+
|
125
|
+
# Ottiene il valore di una cella in modo consistente
|
126
|
+
def get_cell_value(row, header)
|
127
|
+
if row.is_a?(Hash)
|
128
|
+
row[header.to_s] || row[header.to_sym] || "—"
|
129
|
+
elsif row.respond_to?(header.to_sym)
|
130
|
+
row.send(header.to_sym)
|
131
|
+
elsif row.is_a?(Array) && headers_for_display.index(header)
|
132
|
+
row[headers_for_display.index(header)] || "—"
|
133
|
+
else
|
134
|
+
"—"
|
135
|
+
end
|
136
|
+
end
|
135
137
|
|
136
138
|
def render?
|
137
139
|
@data.present?
|