better_ui 0.4.0 → 0.5.0
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 +165 -105
- 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 +123 -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 +4 -4
- data/app/components/better_ui/general/button_component.rb +64 -95
- data/app/components/better_ui/general/heading_component.html.erb +3 -3
- data/app/components/better_ui/general/heading_component.rb +76 -70
- data/app/components/better_ui/general/icon_component.html.erb +1 -1
- data/app/components/better_ui/general/icon_component.rb +22 -23
- 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 +62 -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 +106 -80
- data/app/components/better_ui/theme_helper.rb +77 -75
- 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/lib/better_ui/engine.rb +4 -10
- data/lib/better_ui/version.rb +1 -1
- data/lib/better_ui.rb +4 -0
- data/lib/generators/better_ui/stylesheet_generator.rb +96 -0
- data/lib/generators/better_ui/templates/README +56 -0
- data/lib/generators/better_ui/templates/components/_avatar.scss +151 -0
- data/lib/generators/better_ui/templates/components/_badge.scss +142 -0
- data/lib/generators/better_ui/templates/components/_breadcrumb.scss +107 -0
- data/lib/generators/better_ui/templates/components/_button.scss +106 -0
- data/lib/generators/better_ui/templates/components/_card.scss +69 -0
- data/lib/generators/better_ui/templates/components/_heading.scss +180 -0
- data/lib/generators/better_ui/templates/components/_icon.scss +90 -0
- data/lib/generators/better_ui/templates/components/_link.scss +130 -0
- data/lib/generators/better_ui/templates/components/_panel.scss +144 -0
- data/lib/generators/better_ui/templates/components/_spinner.scss +132 -0
- data/lib/generators/better_ui/templates/components/_table.scss +105 -0
- data/lib/generators/better_ui/templates/components/_variables.scss +33 -0
- data/lib/generators/better_ui/templates/components_stylesheet.scss +66 -0
- metadata +51 -22
- data/app/helpers/better_ui_application_helper.rb +0 -99
@@ -1,137 +1,163 @@
|
|
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: { base: "bui-table-default", border: "bui-table-border-default", bg: "bui-table-bg-default", text: "bui-table-text-default" },
|
10
|
+
white: { base: "bui-table-white", border: "bui-table-border-white", bg: "bui-table-bg-white", text: "bui-table-text-white" },
|
11
|
+
red: { base: "bui-table-red", border: "bui-table-border-red", bg: "bui-table-bg-red", text: "bui-table-text-red" },
|
12
|
+
rose: { base: "bui-table-rose", border: "bui-table-border-rose", bg: "bui-table-bg-rose", text: "bui-table-text-rose" },
|
13
|
+
orange: { base: "bui-table-orange", border: "bui-table-border-orange", bg: "bui-table-bg-orange", text: "bui-table-text-orange" },
|
14
|
+
green: { base: "bui-table-green", border: "bui-table-border-green", bg: "bui-table-bg-green", text: "bui-table-text-green" },
|
15
|
+
blue: { base: "bui-table-blue", border: "bui-table-border-blue", bg: "bui-table-bg-blue", text: "bui-table-text-blue" },
|
16
|
+
yellow: { base: "bui-table-yellow", border: "bui-table-border-yellow", bg: "bui-table-bg-yellow", text: "bui-table-text-yellow" },
|
17
|
+
violet: { base: "bui-table-violet", border: "bui-table-border-violet", bg: "bui-table-bg-violet", text: "bui-table-text-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-base",
|
49
|
+
@bordered ? "bui-table-bordered" : nil,
|
50
|
+
@classes
|
51
|
+
].compact.join(" ")
|
20
52
|
end
|
21
53
|
|
22
54
|
def table_container_classes
|
23
55
|
[
|
24
|
-
|
25
|
-
|
26
|
-
].compact.join(
|
56
|
+
"bui-table-container",
|
57
|
+
get_border_radius_class
|
58
|
+
].compact.join(" ")
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_border_radius_class
|
62
|
+
TABLE_RADIUS[@rounded] || TABLE_RADIUS[:small]
|
27
63
|
end
|
28
64
|
|
29
65
|
def caption_classes
|
30
66
|
[
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
@bordered ? "
|
35
|
-
].compact.join(
|
67
|
+
"bui-table-caption",
|
68
|
+
get_theme_bg_color,
|
69
|
+
get_theme_text_class,
|
70
|
+
@bordered ? "bui-table-caption-bordered #{get_theme_border_color}" : nil
|
71
|
+
].compact.join(" ")
|
36
72
|
end
|
37
73
|
|
38
74
|
def thead_classes
|
39
|
-
|
75
|
+
"bui-table-header"
|
40
76
|
end
|
41
77
|
|
42
78
|
def tbody_classes
|
43
|
-
@striped ?
|
79
|
+
@striped ? "bui-table-row-striped" : nil
|
80
|
+
end
|
81
|
+
|
82
|
+
def tfoot_classes
|
83
|
+
"bui-table-footer"
|
44
84
|
end
|
45
85
|
|
46
86
|
def tr_classes(index)
|
47
87
|
[
|
48
|
-
@hoverable ?
|
49
|
-
@striped ? nil : (index.odd? ?
|
50
|
-
].compact.join(
|
88
|
+
@hoverable ? "bui-table-row-hover" : nil,
|
89
|
+
@striped ? nil : (index.odd? ? "bui-table-row-alternate" : nil)
|
90
|
+
].compact.join(" ")
|
51
91
|
end
|
52
92
|
|
53
93
|
def th_classes
|
54
94
|
[
|
55
|
-
@compact ?
|
56
|
-
|
57
|
-
|
58
|
-
@bordered ? "
|
59
|
-
].compact.join(
|
95
|
+
@compact ? "bui-table-cell-compact" : "bui-table-cell",
|
96
|
+
get_theme_bg_color,
|
97
|
+
get_theme_text_class,
|
98
|
+
@bordered ? "bui-table-cell-bordered #{get_theme_border_color}" : nil
|
99
|
+
].compact.join(" ")
|
60
100
|
end
|
61
101
|
|
62
102
|
def td_classes
|
63
103
|
[
|
64
|
-
@compact ?
|
65
|
-
@bordered ? "
|
66
|
-
|
67
|
-
].compact.join(' ')
|
104
|
+
@compact ? "bui-table-cell-compact" : "bui-table-cell",
|
105
|
+
@bordered ? "bui-table-cell-bordered #{get_theme_border_color}" : nil
|
106
|
+
].compact.join(" ")
|
68
107
|
end
|
69
108
|
|
70
|
-
def
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
when :danger
|
79
|
-
'border-red-200'
|
80
|
-
when :info
|
81
|
-
'border-blue-200'
|
82
|
-
else
|
83
|
-
'border-gray-200'
|
84
|
-
end
|
109
|
+
def tf_classes
|
110
|
+
[
|
111
|
+
@compact ? "bui-table-cell-compact" : "bui-table-cell",
|
112
|
+
"bui-table-footer-cell",
|
113
|
+
get_theme_bg_color,
|
114
|
+
get_theme_text_class,
|
115
|
+
@bordered ? "bui-table-cell-bordered #{get_theme_border_color}" : nil
|
116
|
+
].compact.join(" ")
|
85
117
|
end
|
86
118
|
|
87
|
-
def
|
88
|
-
|
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
|
119
|
+
def get_theme_base_class
|
120
|
+
TABLE_THEMES[@variant][:base] || TABLE_THEMES[:default][:base]
|
102
121
|
end
|
103
122
|
|
104
|
-
def
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
when :info
|
115
|
-
'text-blue-700'
|
116
|
-
else
|
117
|
-
'text-gray-700'
|
118
|
-
end
|
123
|
+
def get_theme_border_color
|
124
|
+
TABLE_THEMES[@variant][:border] || TABLE_THEMES[:default][:border]
|
125
|
+
end
|
126
|
+
|
127
|
+
def get_theme_bg_color
|
128
|
+
TABLE_THEMES[@variant][:bg] || TABLE_THEMES[:default][:bg]
|
129
|
+
end
|
130
|
+
|
131
|
+
def get_theme_text_class
|
132
|
+
TABLE_THEMES[@variant][:text] || TABLE_THEMES[:default][:text]
|
119
133
|
end
|
120
134
|
|
121
135
|
def headers_for_display
|
122
136
|
return @headers if @headers.present?
|
123
137
|
return [] if @data.empty?
|
124
138
|
|
125
|
-
|
126
|
-
|
127
|
-
if first_item.is_a?(Hash)
|
139
|
+
case first_item = @data.first
|
140
|
+
when Hash
|
128
141
|
first_item.keys
|
129
|
-
|
130
|
-
first_item.attributes.keys - [
|
142
|
+
when -> (item) { item.respond_to?(:attributes) }
|
143
|
+
first_item.attributes.keys - %w[id created_at updated_at]
|
131
144
|
else
|
132
145
|
[]
|
133
146
|
end
|
134
147
|
end
|
148
|
+
|
149
|
+
# Ottiene il valore di una cella in modo consistente
|
150
|
+
def get_cell_value(row, header)
|
151
|
+
if row.is_a?(Hash)
|
152
|
+
row[header.to_s] || row[header.to_sym] || "—"
|
153
|
+
elsif row.respond_to?(header.to_sym)
|
154
|
+
row.send(header.to_sym)
|
155
|
+
elsif row.is_a?(Array) && headers_for_display.index(header)
|
156
|
+
row[headers_for_display.index(header)] || "—"
|
157
|
+
else
|
158
|
+
"—"
|
159
|
+
end
|
160
|
+
end
|
135
161
|
|
136
162
|
def render?
|
137
163
|
@data.present?
|
@@ -4,72 +4,80 @@ module BetterUi
|
|
4
4
|
module ThemeHelper
|
5
5
|
# Colori principali del tema
|
6
6
|
THEME_COLORS = {
|
7
|
-
#
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
7
|
+
# Varianti cromatiche
|
8
|
+
default: {
|
9
|
+
bg: 'bg-black',
|
10
|
+
text: 'text-white',
|
11
|
+
hover: 'hover:bg-gray-900'
|
12
|
+
},
|
13
|
+
white: {
|
14
|
+
bg: 'bg-white',
|
15
|
+
text: 'text-black',
|
16
|
+
hover: 'hover:bg-gray-100'
|
17
|
+
},
|
18
|
+
red: {
|
19
|
+
bg: 'bg-red-500',
|
20
|
+
text: 'text-white',
|
21
|
+
hover: 'hover:bg-red-600'
|
17
22
|
},
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
text: 'text-gray-800'
|
23
|
+
rose: {
|
24
|
+
bg: 'bg-rose-500',
|
25
|
+
text: 'text-white',
|
26
|
+
hover: 'hover:bg-rose-600'
|
23
27
|
},
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
text: 'text-white'
|
28
|
+
orange: {
|
29
|
+
bg: 'bg-orange-500',
|
30
|
+
text: 'text-white',
|
31
|
+
hover: 'hover:bg-orange-600'
|
29
32
|
},
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
text: 'text-white'
|
33
|
+
green: {
|
34
|
+
bg: 'bg-green-500',
|
35
|
+
text: 'text-white',
|
36
|
+
hover: 'hover:bg-green-600'
|
35
37
|
},
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
text: 'text-white'
|
38
|
+
blue: {
|
39
|
+
bg: 'bg-blue-500',
|
40
|
+
text: 'text-white',
|
41
|
+
hover: 'hover:bg-blue-600'
|
41
42
|
},
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
yellow: {
|
44
|
+
bg: 'bg-yellow-500',
|
45
|
+
text: 'text-black',
|
46
|
+
hover: 'hover:bg-yellow-600'
|
47
|
+
},
|
48
|
+
violet: {
|
49
|
+
bg: 'bg-violet-500',
|
50
|
+
text: 'text-white',
|
51
|
+
hover: 'hover:bg-violet-600'
|
47
52
|
}
|
48
53
|
}
|
49
54
|
|
50
55
|
# Bordi del tema
|
51
56
|
THEME_BORDERS = {
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
57
|
+
default: 'border-gray-900',
|
58
|
+
white: 'border-gray-200',
|
59
|
+
red: 'border-red-600',
|
60
|
+
rose: 'border-rose-600',
|
61
|
+
orange: 'border-orange-600',
|
62
|
+
green: 'border-green-600',
|
63
|
+
blue: 'border-blue-600',
|
64
|
+
yellow: 'border-yellow-600',
|
65
|
+
violet: 'border-violet-600'
|
58
66
|
}
|
59
67
|
|
68
|
+
# NOTA: I valori di border-radius sono ora definiti nelle costanti specifiche di ogni componente
|
69
|
+
# per garantire una nomenclatura standardizzata:
|
70
|
+
# - none: nessun arrotondamento (rounded-none)
|
71
|
+
# - small: arrotondamento piccolo (rounded-md)
|
72
|
+
# - medium: arrotondamento medio (rounded-lg)
|
73
|
+
# - large: arrotondamento grande (rounded-xl)
|
74
|
+
# - full: arrotondamento completo (rounded-full)
|
75
|
+
|
60
76
|
# Effetti hover
|
61
|
-
THEME_HOVER = {
|
62
|
-
primary: 'hover:bg-orange-600',
|
63
|
-
secondary: 'hover:bg-gray-300',
|
64
|
-
success: 'hover:bg-green-600',
|
65
|
-
warning: 'hover:bg-amber-600',
|
66
|
-
danger: 'hover:bg-red-600',
|
67
|
-
info: 'hover:bg-blue-600'
|
68
|
-
}
|
77
|
+
THEME_HOVER = THEME_COLORS.transform_values { |v| v[:hover] }
|
69
78
|
|
70
79
|
# Stili base comuni
|
71
80
|
COMMON_STYLES = {
|
72
|
-
rounded: 'rounded-md',
|
73
81
|
shadow: 'shadow-sm',
|
74
82
|
transitions: 'transition-all duration-200'
|
75
83
|
}
|
@@ -77,13 +85,13 @@ module BetterUi
|
|
77
85
|
# Stili per elementi di layout
|
78
86
|
LAYOUT_STYLES = {
|
79
87
|
panel: {
|
80
|
-
base: '
|
88
|
+
base: 'border shadow-sm',
|
81
89
|
header: 'px-4 py-3 border-b',
|
82
90
|
body: 'p-4',
|
83
91
|
footer: 'px-4 py-3 border-t'
|
84
92
|
},
|
85
93
|
table: {
|
86
|
-
container: 'overflow-hidden
|
94
|
+
container: 'overflow-hidden border shadow-sm',
|
87
95
|
header: 'bg-gray-50 text-left text-xs uppercase tracking-wider text-gray-500 font-medium',
|
88
96
|
row: {
|
89
97
|
base: '',
|
@@ -102,21 +110,14 @@ module BetterUi
|
|
102
110
|
when :button
|
103
111
|
base_classes << 'inline-flex items-center justify-center'
|
104
112
|
base_classes << 'font-medium'
|
105
|
-
base_classes << COMMON_STYLES[:rounded]
|
106
113
|
base_classes << COMMON_STYLES[:transitions]
|
107
114
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
else
|
115
|
-
# Versione piena
|
116
|
-
base_classes << THEME_COLORS.dig(variant.to_sym, :default)&.sub('bg-', '') || "bg-#{variant}-500"
|
117
|
-
base_classes << THEME_COLORS.dig(variant.to_sym, :text) || 'text-white'
|
118
|
-
base_classes << THEME_HOVER[variant.to_sym] || "hover:bg-#{variant}-600"
|
119
|
-
end
|
115
|
+
variant_colors = THEME_COLORS[variant.to_sym] || THEME_COLORS[:default]
|
116
|
+
|
117
|
+
# Versione piena
|
118
|
+
base_classes << variant_colors[:bg]
|
119
|
+
base_classes << variant_colors[:text]
|
120
|
+
base_classes << THEME_HOVER[variant.to_sym] || THEME_HOVER[:default]
|
120
121
|
|
121
122
|
# Dimensione
|
122
123
|
case options[:size]
|
@@ -141,22 +142,23 @@ module BetterUi
|
|
141
142
|
when :panel
|
142
143
|
base_classes << LAYOUT_STYLES[:panel][:base]
|
143
144
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
base_classes << THEME_COLORS.dig(variant.to_sym, :light)&.sub('bg-', '') || "bg-#{variant}-50"
|
150
|
-
base_classes << THEME_BORDERS[variant.to_sym] || "border-#{variant}-200"
|
151
|
-
end
|
145
|
+
variant_colors = THEME_COLORS[variant.to_sym] || THEME_COLORS[:default]
|
146
|
+
|
147
|
+
base_classes << variant_colors[:bg]
|
148
|
+
base_classes << variant_colors[:text]
|
149
|
+
base_classes << THEME_BORDERS[variant.to_sym] || THEME_BORDERS[:default]
|
152
150
|
|
153
151
|
when :table
|
154
|
-
base_classes << 'min-w-full
|
152
|
+
base_classes << 'min-w-full'
|
153
|
+
|
154
|
+
variant_colors = THEME_COLORS[variant.to_sym] || THEME_COLORS[:default]
|
155
|
+
base_classes << variant_colors[:bg]
|
156
|
+
base_classes << variant_colors[:text]
|
155
157
|
|
156
158
|
# Bordi
|
157
159
|
if options[:bordered]
|
158
160
|
base_classes << 'border-collapse'
|
159
|
-
base_classes << (THEME_BORDERS[variant.to_sym] ||
|
161
|
+
base_classes << (THEME_BORDERS[variant.to_sym] || THEME_BORDERS[:default])
|
160
162
|
end
|
161
163
|
|
162
164
|
# Classi personalizzate
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<tr class="<%= component.tr_classes(index) %>">
|
2
|
+
<% headers.each_with_index do |header, cell_index| %>
|
3
|
+
<td class="<%= component.td_classes %>">
|
4
|
+
<% cell_value = component.get_cell_value(row, header) %>
|
5
|
+
<% if cell_index == 0 %>
|
6
|
+
<div class="flex items-center">
|
7
|
+
<div class="w-8 h-8 rounded-full bg-blue-100 mr-2 flex items-center justify-center text-blue-700">
|
8
|
+
<%= cell_value.to_s.first&.upcase || 'N/A' %>
|
9
|
+
</div>
|
10
|
+
<%= cell_value %>
|
11
|
+
</div>
|
12
|
+
<% else %>
|
13
|
+
<%= cell_value %>
|
14
|
+
<% end %>
|
15
|
+
</td>
|
16
|
+
<% end %>
|
17
|
+
</tr>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<tr>
|
2
|
+
<% footer.each_with_index do |value, index| %>
|
3
|
+
<td class="<%= component.tf_classes %>">
|
4
|
+
<% if index == 0 %>
|
5
|
+
<div class="flex items-center">
|
6
|
+
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
7
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 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
|
8
|
+
0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path>
|
9
|
+
</svg>
|
10
|
+
<strong><%= value %></strong>
|
11
|
+
</div>
|
12
|
+
<% else %>
|
13
|
+
<%= value %>
|
14
|
+
<% end %>
|
15
|
+
</td>
|
16
|
+
<% end %>
|
17
|
+
</tr>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<tr>
|
2
|
+
<% headers.each do |header| %>
|
3
|
+
<th class="<%= component.th_classes %>">
|
4
|
+
<div class="flex items-center justify-between">
|
5
|
+
<%= header.to_s.humanize %>
|
6
|
+
<svg class="w-4 h-4 ml-1" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
7
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
|
8
|
+
</svg>
|
9
|
+
</div>
|
10
|
+
</th>
|
11
|
+
<% end %>
|
12
|
+
</tr>
|
data/lib/better_ui/engine.rb
CHANGED
@@ -3,6 +3,9 @@ require 'redcarpet'
|
|
3
3
|
require 'tailwindcss-rails'
|
4
4
|
require 'coderay'
|
5
5
|
require 'font-awesome-sass'
|
6
|
+
require 'lookbook'
|
7
|
+
require 'listen'
|
8
|
+
require 'action_cable'
|
6
9
|
|
7
10
|
module BetterUi
|
8
11
|
class Engine < ::Rails::Engine
|
@@ -35,16 +38,7 @@ module BetterUi
|
|
35
38
|
|
36
39
|
# Configurazione per Lookbook in sviluppo e test
|
37
40
|
initializer 'better_ui.lookbook' do
|
38
|
-
if
|
39
|
-
# Carica esplicitamente le dipendenze per le funzionalità avanzate di Lookbook
|
40
|
-
begin
|
41
|
-
require 'listen'
|
42
|
-
require 'action_cable'
|
43
|
-
rescue LoadError => e
|
44
|
-
# Log che le dipendenze opzionali non sono disponibili
|
45
|
-
puts "NOTA: Alcune funzionalità avanzate di Lookbook potrebbero non essere disponibili: #{e.message}"
|
46
|
-
end
|
47
|
-
|
41
|
+
if Rails.env.development? || Rails.env.test?
|
48
42
|
config.lookbook = Lookbook
|
49
43
|
end
|
50
44
|
end
|
data/lib/better_ui/version.rb
CHANGED
data/lib/better_ui.rb
CHANGED
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BetterUi
|
4
|
+
module Generators
|
5
|
+
class StylesheetGenerator < Rails::Generators::Base
|
6
|
+
source_root File.expand_path('templates', __dir__)
|
7
|
+
|
8
|
+
desc "Genera un foglio di stile SCSS di base per personalizzare i componenti di BetterUi"
|
9
|
+
|
10
|
+
class_option :prefix, type: :string, default: "custom",
|
11
|
+
desc: "Prefisso da utilizzare per il foglio di stile (default: 'custom')"
|
12
|
+
|
13
|
+
def create_stylesheet
|
14
|
+
# Crea il file principale
|
15
|
+
template "components_stylesheet.scss",
|
16
|
+
File.join("app/assets/stylesheets", "#{options[:prefix]}_better_ui_components.scss")
|
17
|
+
|
18
|
+
# Crea la directory dei componenti se non esiste
|
19
|
+
directory = File.join("app/assets/stylesheets", "components")
|
20
|
+
FileUtils.mkdir_p(directory) unless File.directory?(directory)
|
21
|
+
|
22
|
+
# Lista dei file dei componenti
|
23
|
+
component_files = ['_variables.scss', '_button.scss', '_heading.scss', '_breadcrumb.scss',
|
24
|
+
'_link.scss', '_panel.scss', '_icon.scss', '_table.scss', '_badge.scss',
|
25
|
+
'_spinner.scss', '_avatar.scss']
|
26
|
+
|
27
|
+
# Copia i file originali
|
28
|
+
component_files.each do |filename|
|
29
|
+
copy_file "components/#{filename}", File.join(directory, filename)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def create_overrides
|
34
|
+
# Crea la directory dei componenti se non esiste
|
35
|
+
directory = File.join("app/assets/stylesheets", "components")
|
36
|
+
FileUtils.mkdir_p(directory) unless File.directory?(directory)
|
37
|
+
|
38
|
+
# Lista dei file dei componenti
|
39
|
+
component_files = ['_variables.scss', '_button.scss', '_heading.scss', '_breadcrumb.scss',
|
40
|
+
'_link.scss', '_panel.scss', '_icon.scss', '_table.scss', '_badge.scss',
|
41
|
+
'_spinner.scss', '_avatar.scss']
|
42
|
+
|
43
|
+
# Crea i file di override
|
44
|
+
component_files.each do |filename|
|
45
|
+
# Nome del file di override
|
46
|
+
override_filename = filename.sub('.scss', '_overrides.scss')
|
47
|
+
override_path = File.join(directory, override_filename)
|
48
|
+
|
49
|
+
# Crea il file di override solo se non esiste già
|
50
|
+
unless File.exist?(override_path)
|
51
|
+
# Leggi il contenuto del file originale dalla directory templates
|
52
|
+
template_path = File.join(self.class.source_root, "components", filename)
|
53
|
+
|
54
|
+
# Se il file template esiste, crea il file di override
|
55
|
+
if File.exist?(template_path)
|
56
|
+
original_content = File.read(template_path)
|
57
|
+
override_content = generate_empty_override(original_content, filename)
|
58
|
+
create_file override_path, override_content
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def show_readme
|
65
|
+
readme "README" if behavior == :invoke
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
# Genera un file di override vuoto con le stesse classi del file originale
|
71
|
+
def generate_empty_override(content, filename)
|
72
|
+
component_name = filename.sub('_', '').sub('.scss', '')
|
73
|
+
result = "/* ==============================\n"
|
74
|
+
result += " * #{component_name.capitalize} Component Overrides\n"
|
75
|
+
result += " * ==============================\n"
|
76
|
+
result += " * Questo file contiene le classi vuote per sovrascrivere gli stili di default.\n"
|
77
|
+
result += " * Aggiungi qui le tue personalizzazioni.\n"
|
78
|
+
result += " */\n\n"
|
79
|
+
|
80
|
+
# Estrae le classi tramite regex
|
81
|
+
class_matches = content.scan(/\.(bui-[a-zA-Z0-9_-]+)\s*\{/)
|
82
|
+
class_matches.flatten.uniq.each do |css_class|
|
83
|
+
result += ".#{css_class} {\n // Sovrascrivi qui gli stili per .#{css_class}\n}\n\n"
|
84
|
+
end
|
85
|
+
|
86
|
+
# Estrae anche classi annidate usando la sintassi SCSS
|
87
|
+
nested_matches = content.scan(/\.(bui-[a-zA-Z0-9_-]+)\s*{[^{]*\.([\w-]+)\s*{/)
|
88
|
+
nested_matches.each do |parent_class, child_class|
|
89
|
+
result += ".#{parent_class} {\n .#{child_class} {\n // Sovrascrivi qui gli stili annidati\n }\n}\n\n"
|
90
|
+
end
|
91
|
+
|
92
|
+
result
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|