better_ui_tmp 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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +211 -0
- data/Rakefile +8 -0
- data/app/assets/builds/application.js +1 -0
- data/app/assets/builds/better_ui.css +1 -0
- data/app/assets/stylesheets/better_ui.scss +3 -0
- data/app/components/better_ui/application/main/component.html.erb +5 -0
- data/app/components/better_ui/application/main/component.rb +99 -0
- data/app/components/better_ui/application/navbar/component.html.erb +219 -0
- data/app/components/better_ui/application/navbar/component.rb +148 -0
- data/app/components/better_ui/application/sidebar/component.html.erb +184 -0
- data/app/components/better_ui/application/sidebar/component.rb +129 -0
- data/app/components/better_ui/general/alert/component.html.erb +32 -0
- data/app/components/better_ui/general/alert/component.rb +242 -0
- data/app/components/better_ui/general/avatar/component.html.erb +20 -0
- data/app/components/better_ui/general/avatar/component.rb +301 -0
- data/app/components/better_ui/general/badge/component.html.erb +23 -0
- data/app/components/better_ui/general/badge/component.rb +248 -0
- data/app/components/better_ui/general/breadcrumb/component.html.erb +15 -0
- data/app/components/better_ui/general/breadcrumb/component.rb +186 -0
- data/app/components/better_ui/general/button/component.html.erb +34 -0
- data/app/components/better_ui/general/button/component.rb +214 -0
- data/app/components/better_ui/general/card/component.html.erb +21 -0
- data/app/components/better_ui/general/card/component.rb +37 -0
- data/app/components/better_ui/general/container/component.html.erb +8 -0
- data/app/components/better_ui/general/container/component.rb +158 -0
- data/app/components/better_ui/general/divider/component.html.erb +10 -0
- data/app/components/better_ui/general/divider/component.rb +226 -0
- data/app/components/better_ui/general/heading/component.html.erb +22 -0
- data/app/components/better_ui/general/heading/component.rb +257 -0
- data/app/components/better_ui/general/icon/component.html.erb +1 -0
- data/app/components/better_ui/general/icon/component.rb +222 -0
- data/app/components/better_ui/general/link/component.html.erb +18 -0
- data/app/components/better_ui/general/link/component.rb +255 -0
- data/app/components/better_ui/general/panel/component.html.erb +28 -0
- data/app/components/better_ui/general/panel/component.rb +249 -0
- data/app/components/better_ui/general/progress/component.html.erb +11 -0
- data/app/components/better_ui/general/progress/component.rb +160 -0
- data/app/components/better_ui/general/spinner/component.html.erb +35 -0
- data/app/components/better_ui/general/spinner/component.rb +93 -0
- data/app/components/better_ui/general/table/component.html.erb +5 -0
- data/app/components/better_ui/general/table/component.rb +217 -0
- data/app/components/better_ui/general/table/tbody_component.html.erb +3 -0
- data/app/components/better_ui/general/table/tbody_component.rb +30 -0
- data/app/components/better_ui/general/table/td_component.html.erb +3 -0
- data/app/components/better_ui/general/table/td_component.rb +44 -0
- data/app/components/better_ui/general/table/tfoot_component.html.erb +3 -0
- data/app/components/better_ui/general/table/tfoot_component.rb +28 -0
- data/app/components/better_ui/general/table/th_component.html.erb +6 -0
- data/app/components/better_ui/general/table/th_component.rb +51 -0
- data/app/components/better_ui/general/table/thead_component.html.erb +3 -0
- data/app/components/better_ui/general/table/thead_component.rb +28 -0
- data/app/components/better_ui/general/table/tr_component.html.erb +3 -0
- data/app/components/better_ui/general/table/tr_component.rb +30 -0
- data/app/components/better_ui/general/tag/component.html.erb +3 -0
- data/app/components/better_ui/general/tag/component.rb +104 -0
- data/app/components/better_ui/general/tooltip/component.html.erb +7 -0
- data/app/components/better_ui/general/tooltip/component.rb +239 -0
- data/app/controllers/better_ui/application_controller.rb +5 -0
- data/app/helpers/better_ui/application/components/main/main_helper.rb +42 -0
- data/app/helpers/better_ui/application/components/main.rb +13 -0
- data/app/helpers/better_ui/application/components/navbar/navbar_helper.rb +51 -0
- data/app/helpers/better_ui/application/components/navbar.rb +13 -0
- data/app/helpers/better_ui/application/components/sidebar/sidebar_helper.rb +51 -0
- data/app/helpers/better_ui/application/components/sidebar.rb +13 -0
- data/app/helpers/better_ui/application_helper.rb +10 -0
- data/app/helpers/better_ui/form_helper.rb +5 -0
- data/app/helpers/better_ui/general/components/alert/alert_helper.rb +29 -0
- data/app/helpers/better_ui/general/components/alert.rb +13 -0
- data/app/helpers/better_ui/general/components/avatar/avatar_helper.rb +29 -0
- data/app/helpers/better_ui/general/components/avatar.rb +13 -0
- data/app/helpers/better_ui/general/components/badge/badge_helper.rb +53 -0
- data/app/helpers/better_ui/general/components/badge.rb +13 -0
- data/app/helpers/better_ui/general/components/breadcrumb/breadcrumb_helper.rb +37 -0
- data/app/helpers/better_ui/general/components/breadcrumb.rb +13 -0
- data/app/helpers/better_ui/general/components/button/button_helper.rb +65 -0
- data/app/helpers/better_ui/general/components/button.rb +13 -0
- data/app/helpers/better_ui/general/components/card/card_helper.rb +37 -0
- data/app/helpers/better_ui/general/components/card.rb +13 -0
- data/app/helpers/better_ui/general/components/container/container_helper.rb +60 -0
- data/app/helpers/better_ui/general/components/container.rb +13 -0
- data/app/helpers/better_ui/general/components/divider/divider_helper.rb +63 -0
- data/app/helpers/better_ui/general/components/divider.rb +13 -0
- data/app/helpers/better_ui/general/components/heading/heading_helper.rb +72 -0
- data/app/helpers/better_ui/general/components/heading.rb +13 -0
- data/app/helpers/better_ui/general/components/icon/icon_helper.rb +16 -0
- data/app/helpers/better_ui/general/components/icon.rb +13 -0
- data/app/helpers/better_ui/general/components/link/link_helper.rb +89 -0
- data/app/helpers/better_ui/general/components/link.rb +13 -0
- data/app/helpers/better_ui/general/components/panel/panel_helper.rb +83 -0
- data/app/helpers/better_ui/general/components/panel.rb +13 -0
- data/app/helpers/better_ui/general/components/progress/progress_helper.rb +53 -0
- data/app/helpers/better_ui/general/components/progress.rb +11 -0
- data/app/helpers/better_ui/general/components/spinner/spinner_helper.rb +17 -0
- data/app/helpers/better_ui/general/components/spinner.rb +10 -0
- data/app/helpers/better_ui/general/components/table/table_helper.rb +13 -0
- data/app/helpers/better_ui/general/components/table/tbody_helper.rb +13 -0
- data/app/helpers/better_ui/general/components/table/td_helper.rb +19 -0
- data/app/helpers/better_ui/general/components/table/tfoot_helper.rb +13 -0
- data/app/helpers/better_ui/general/components/table/th_helper.rb +19 -0
- data/app/helpers/better_ui/general/components/table/thead_helper.rb +13 -0
- data/app/helpers/better_ui/general/components/table/tr_helper.rb +13 -0
- data/app/helpers/better_ui/general/components/table.rb +25 -0
- data/app/helpers/better_ui/general/components/tag/tag_helper.rb +26 -0
- data/app/helpers/better_ui/general/components/tag.rb +15 -0
- data/app/helpers/better_ui/general/components/tooltip/tooltip_helper.rb +60 -0
- data/app/helpers/better_ui/general/components/tooltip.rb +13 -0
- data/app/helpers/better_ui/general_helper.rb +24 -0
- data/app/helpers/better_ui_helper.rb +16 -0
- data/app/javascript/application.js +1 -0
- data/app/jobs/better_ui/application_job.rb +4 -0
- data/app/mailers/better_ui/application_mailer.rb +6 -0
- data/app/models/better_ui/application_record.rb +5 -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/app/views/layouts/component_preview.html.erb +32 -0
- data/config/initializers/lookbook.rb +23 -0
- data/config/routes.rb +3 -0
- data/lib/better_ui/engine.rb +109 -0
- data/lib/better_ui/version.rb +3 -0
- data/lib/better_ui.rb +37 -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/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
- data/lib/tasks/better_ui_tasks.rake +4 -0
- metadata +260 -0
@@ -0,0 +1,257 @@
|
|
1
|
+
module BetterUi
|
2
|
+
module General
|
3
|
+
module Heading
|
4
|
+
class Component < ViewComponent::Base
|
5
|
+
attr_reader :level, :theme, :align, :size, :style, :icon, :subtitle, :with_divider
|
6
|
+
|
7
|
+
# Classi base sempre presenti
|
8
|
+
HEADING_BASE_CLASSES = "font-bold leading-tight"
|
9
|
+
|
10
|
+
# Temi con classi Tailwind dirette - LOGICA CORRETTA
|
11
|
+
HEADING_THEME_CLASSES = {
|
12
|
+
default: "text-white", # Testo bianco (per sfondi scuri)
|
13
|
+
white: "text-gray-900", # Testo nero (per sfondi chiari)
|
14
|
+
red: "text-red-500",
|
15
|
+
rose: "text-rose-500",
|
16
|
+
orange: "text-orange-500",
|
17
|
+
green: "text-green-500",
|
18
|
+
blue: "text-blue-500",
|
19
|
+
yellow: "text-yellow-600",
|
20
|
+
violet: "text-violet-500",
|
21
|
+
purple: "text-purple-500"
|
22
|
+
}
|
23
|
+
|
24
|
+
# Allineamenti con classi Tailwind dirette
|
25
|
+
HEADING_ALIGN_CLASSES = {
|
26
|
+
left: "text-left",
|
27
|
+
center: "text-center",
|
28
|
+
right: "text-right"
|
29
|
+
}
|
30
|
+
|
31
|
+
# Dimensioni base (verranno combinate con level)
|
32
|
+
HEADING_SIZE_CLASSES = {
|
33
|
+
small: {
|
34
|
+
1 => "text-2xl sm:text-3xl",
|
35
|
+
2 => "text-xl sm:text-2xl",
|
36
|
+
3 => "text-lg sm:text-xl",
|
37
|
+
4 => "text-base sm:text-lg",
|
38
|
+
5 => "text-sm sm:text-base",
|
39
|
+
6 => "text-xs sm:text-sm"
|
40
|
+
},
|
41
|
+
medium: {
|
42
|
+
1 => "text-3xl sm:text-4xl",
|
43
|
+
2 => "text-2xl sm:text-3xl",
|
44
|
+
3 => "text-xl sm:text-2xl",
|
45
|
+
4 => "text-lg sm:text-xl",
|
46
|
+
5 => "text-base sm:text-lg",
|
47
|
+
6 => "text-sm sm:text-base"
|
48
|
+
},
|
49
|
+
large: {
|
50
|
+
1 => "text-4xl sm:text-5xl",
|
51
|
+
2 => "text-3xl sm:text-4xl",
|
52
|
+
3 => "text-2xl sm:text-3xl",
|
53
|
+
4 => "text-xl sm:text-2xl",
|
54
|
+
5 => "text-lg sm:text-xl",
|
55
|
+
6 => "text-base sm:text-lg"
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
# Stili con classi Tailwind dirette
|
60
|
+
HEADING_STYLE_CLASSES = {
|
61
|
+
normal: "",
|
62
|
+
bold: "font-extrabold",
|
63
|
+
italic: "italic",
|
64
|
+
underline: "underline"
|
65
|
+
}
|
66
|
+
|
67
|
+
# Temi per subtitle - LOGICA CORRETTA
|
68
|
+
HEADING_SUBTITLE_THEME_CLASSES = {
|
69
|
+
default: "text-gray-300", # Testo grigio chiaro (per sfondi scuri)
|
70
|
+
white: "text-gray-600", # Testo grigio scuro (per sfondi chiari)
|
71
|
+
red: "text-red-400",
|
72
|
+
rose: "text-rose-400",
|
73
|
+
orange: "text-orange-400",
|
74
|
+
green: "text-green-400",
|
75
|
+
blue: "text-blue-400",
|
76
|
+
yellow: "text-yellow-500",
|
77
|
+
violet: "text-violet-400"
|
78
|
+
}
|
79
|
+
|
80
|
+
# Temi per divider - LOGICA CORRETTA
|
81
|
+
HEADING_DIVIDER_THEME_CLASSES = {
|
82
|
+
default: "border-gray-700", # Bordo grigio scuro (per sfondi scuri)
|
83
|
+
white: "border-gray-200", # Bordo grigio chiaro (per sfondi chiari)
|
84
|
+
red: "border-red-200",
|
85
|
+
rose: "border-rose-200",
|
86
|
+
orange: "border-orange-200",
|
87
|
+
green: "border-green-200",
|
88
|
+
blue: "border-blue-200",
|
89
|
+
yellow: "border-yellow-200",
|
90
|
+
violet: "border-violet-200"
|
91
|
+
}
|
92
|
+
|
93
|
+
# @param level [Integer] livello del heading (1-6)
|
94
|
+
# @param theme [Symbol] tema del colore (:default, :white, etc.)
|
95
|
+
# @param align [Symbol] allineamento (:left, :center, :right)
|
96
|
+
# @param size [Symbol] dimensione (:small, :medium, :large)
|
97
|
+
# @param style [Symbol] stile (:normal, :bold, :italic, :underline)
|
98
|
+
# @param icon [String] icona opzionale
|
99
|
+
# @param subtitle [String] sottotitolo opzionale
|
100
|
+
# @param with_divider [Boolean] mostra linea divisoria
|
101
|
+
# @param html_options [Hash] opzioni HTML per il container
|
102
|
+
def initialize(
|
103
|
+
level: 2,
|
104
|
+
theme: :white,
|
105
|
+
align: :left,
|
106
|
+
size: :medium,
|
107
|
+
style: :normal,
|
108
|
+
icon: nil,
|
109
|
+
subtitle: nil,
|
110
|
+
with_divider: false,
|
111
|
+
**html_options
|
112
|
+
)
|
113
|
+
@level = level.to_i.clamp(1, 6)
|
114
|
+
@theme = theme.to_sym
|
115
|
+
@align = align.to_sym
|
116
|
+
@size = size.to_sym
|
117
|
+
@style = style.to_sym
|
118
|
+
@icon = icon
|
119
|
+
@subtitle = subtitle
|
120
|
+
@with_divider = with_divider
|
121
|
+
@html_options = html_options
|
122
|
+
|
123
|
+
validate_params
|
124
|
+
end
|
125
|
+
|
126
|
+
# Combina tutte le classi per il heading
|
127
|
+
def heading_classes
|
128
|
+
[
|
129
|
+
HEADING_BASE_CLASSES,
|
130
|
+
get_theme_class,
|
131
|
+
get_align_class,
|
132
|
+
get_size_class,
|
133
|
+
get_style_class,
|
134
|
+
@html_options[:class]
|
135
|
+
].compact.join(" ")
|
136
|
+
end
|
137
|
+
|
138
|
+
# Classi per il container principale
|
139
|
+
def container_classes
|
140
|
+
"mb-4"
|
141
|
+
end
|
142
|
+
|
143
|
+
# Classi per il subtitle
|
144
|
+
def subtitle_classes
|
145
|
+
return "" unless @subtitle.present?
|
146
|
+
|
147
|
+
[
|
148
|
+
"mt-1 text-sm",
|
149
|
+
get_subtitle_theme_class,
|
150
|
+
get_align_class
|
151
|
+
].compact.join(" ")
|
152
|
+
end
|
153
|
+
|
154
|
+
# Classi per il divider
|
155
|
+
def divider_classes
|
156
|
+
return "" unless @with_divider
|
157
|
+
|
158
|
+
[
|
159
|
+
"mt-2 border-t",
|
160
|
+
get_divider_theme_class
|
161
|
+
].compact.join(" ")
|
162
|
+
end
|
163
|
+
|
164
|
+
# Classi per l'icona
|
165
|
+
def icon_classes
|
166
|
+
return "" unless @icon.present?
|
167
|
+
"mr-2 inline-block"
|
168
|
+
end
|
169
|
+
|
170
|
+
# Restituisce gli attributi HTML per il heading
|
171
|
+
def heading_attributes
|
172
|
+
attrs = @html_options.except(:class)
|
173
|
+
attrs[:class] = heading_classes
|
174
|
+
attrs
|
175
|
+
end
|
176
|
+
|
177
|
+
# Tag del heading basato sul level
|
178
|
+
def heading_tag
|
179
|
+
"h#{@level}"
|
180
|
+
end
|
181
|
+
|
182
|
+
# Determina se mostrare l'icona
|
183
|
+
def show_icon?
|
184
|
+
@icon.present?
|
185
|
+
end
|
186
|
+
|
187
|
+
# Determina se mostrare il subtitle
|
188
|
+
def show_subtitle?
|
189
|
+
@subtitle.present?
|
190
|
+
end
|
191
|
+
|
192
|
+
# Determina se mostrare il divider
|
193
|
+
def show_divider?
|
194
|
+
@with_divider
|
195
|
+
end
|
196
|
+
|
197
|
+
private
|
198
|
+
|
199
|
+
def get_theme_class
|
200
|
+
HEADING_THEME_CLASSES[@theme] || HEADING_THEME_CLASSES[:white]
|
201
|
+
end
|
202
|
+
|
203
|
+
def get_align_class
|
204
|
+
HEADING_ALIGN_CLASSES[@align] || HEADING_ALIGN_CLASSES[:left]
|
205
|
+
end
|
206
|
+
|
207
|
+
def get_size_class
|
208
|
+
size_map = HEADING_SIZE_CLASSES[@size] || HEADING_SIZE_CLASSES[:medium]
|
209
|
+
size_map[@level] || size_map[2]
|
210
|
+
end
|
211
|
+
|
212
|
+
def get_style_class
|
213
|
+
HEADING_STYLE_CLASSES[@style] || HEADING_STYLE_CLASSES[:normal]
|
214
|
+
end
|
215
|
+
|
216
|
+
def get_subtitle_theme_class
|
217
|
+
HEADING_SUBTITLE_THEME_CLASSES[@theme] || HEADING_SUBTITLE_THEME_CLASSES[:white]
|
218
|
+
end
|
219
|
+
|
220
|
+
def get_divider_theme_class
|
221
|
+
HEADING_DIVIDER_THEME_CLASSES[@theme] || HEADING_DIVIDER_THEME_CLASSES[:white]
|
222
|
+
end
|
223
|
+
|
224
|
+
def validate_params
|
225
|
+
validate_theme
|
226
|
+
validate_align
|
227
|
+
validate_size
|
228
|
+
validate_style
|
229
|
+
end
|
230
|
+
|
231
|
+
def validate_theme
|
232
|
+
unless HEADING_THEME_CLASSES.keys.include?(@theme)
|
233
|
+
raise ArgumentError, "Il tema deve essere uno tra: #{HEADING_THEME_CLASSES.keys.join(', ')}"
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def validate_align
|
238
|
+
unless HEADING_ALIGN_CLASSES.keys.include?(@align)
|
239
|
+
raise ArgumentError, "L'allineamento deve essere uno tra: #{HEADING_ALIGN_CLASSES.keys.join(', ')}"
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def validate_size
|
244
|
+
unless HEADING_SIZE_CLASSES.keys.include?(@size)
|
245
|
+
raise ArgumentError, "La dimensione deve essere una tra: #{HEADING_SIZE_CLASSES.keys.join(', ')}"
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
def validate_style
|
250
|
+
unless HEADING_STYLE_CLASSES.keys.include?(@style)
|
251
|
+
raise ArgumentError, "Lo stile deve essere uno tra: #{HEADING_STYLE_CLASSES.keys.join(', ')}"
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<i class="<%= fa_class_name %> <%= icon_classes %>"></i>
|
@@ -0,0 +1,222 @@
|
|
1
|
+
module BetterUi
|
2
|
+
module General
|
3
|
+
module Icon
|
4
|
+
class Component < ViewComponent::Base
|
5
|
+
# Classi base per l'icona con nomenclatura BEM
|
6
|
+
ICON_BASE_CLASSES = "bui-icon inline-flex items-center justify-center"
|
7
|
+
|
8
|
+
# Dimensioni dell'icona (standardizzate: small, medium, large)
|
9
|
+
ICON_SIZE_CLASSES = {
|
10
|
+
small: "bui-icon--small w-4 h-4 text-sm",
|
11
|
+
medium: "bui-icon--medium w-5 h-5 text-base",
|
12
|
+
large: "bui-icon--large w-6 h-6 text-lg"
|
13
|
+
}.freeze
|
14
|
+
|
15
|
+
# Temi dell'icona con colori coerenti
|
16
|
+
ICON_THEME_CLASSES = {
|
17
|
+
default: "bui-icon--default text-gray-600",
|
18
|
+
white: "bui-icon--white text-white",
|
19
|
+
red: "bui-icon--red text-red-600",
|
20
|
+
rose: "bui-icon--rose text-rose-600",
|
21
|
+
orange: "bui-icon--orange text-orange-600",
|
22
|
+
green: "bui-icon--green text-green-600",
|
23
|
+
blue: "bui-icon--blue text-blue-600",
|
24
|
+
yellow: "bui-icon--yellow text-yellow-600",
|
25
|
+
violet: "bui-icon--violet text-violet-600",
|
26
|
+
purple: "bui-icon--purple text-purple-600"
|
27
|
+
}.freeze
|
28
|
+
|
29
|
+
# Animazioni disponibili
|
30
|
+
ICON_ANIMATION_CLASSES = {
|
31
|
+
spin: "bui-icon--spin animate-spin",
|
32
|
+
pulse: "bui-icon--pulse animate-pulse"
|
33
|
+
}.freeze
|
34
|
+
|
35
|
+
# Trasformazioni disponibili
|
36
|
+
ICON_ROTATION_CLASSES = {
|
37
|
+
90 => "bui-icon--rotate-90 transform rotate-90",
|
38
|
+
180 => "bui-icon--rotate-180 transform rotate-180",
|
39
|
+
270 => "bui-icon--rotate-270 transform rotate-270"
|
40
|
+
}.freeze
|
41
|
+
|
42
|
+
ICON_FLIP_CLASSES = {
|
43
|
+
horizontal: "bui-icon--flip-h transform scale-x-[-1]",
|
44
|
+
vertical: "bui-icon--flip-v transform scale-y-[-1]",
|
45
|
+
both: "bui-icon--flip-both transform scale-[-1]"
|
46
|
+
}.freeze
|
47
|
+
|
48
|
+
# Bordo e larghezza fissa
|
49
|
+
ICON_BORDER_CLASSES = "bui-icon--border border border-current rounded-full p-1"
|
50
|
+
ICON_FIXED_WIDTH_CLASSES = "bui-icon--fixed-width w-5"
|
51
|
+
|
52
|
+
attr_reader :name, :style, :size, :theme, :spin, :pulse, :border, :fixed_width,
|
53
|
+
:rotation, :flip, :classes, :id, :html_options
|
54
|
+
|
55
|
+
# @param name [String] Nome dell'icona (richiesto)
|
56
|
+
# @param style [Symbol] Stile dell'icona (:solid, :regular, :brands)
|
57
|
+
# @param size [Symbol] Dimensione (:small, :medium, :large)
|
58
|
+
# @param theme [Symbol] Tema colore (:default, :white, :red, :rose, :orange, :green, :blue, :yellow, :violet)
|
59
|
+
# @param spin [Boolean] Rotazione continua
|
60
|
+
# @param pulse [Boolean] Animazione pulsazione
|
61
|
+
# @param border [Boolean] Mostra bordo attorno all'icona
|
62
|
+
# @param fixed_width [Boolean] Larghezza fissa per allineamento
|
63
|
+
# @param rotation [Integer] Rotazione in gradi (0, 90, 180, 270)
|
64
|
+
# @param flip [Symbol] Tipo di flip (:horizontal, :vertical, :both)
|
65
|
+
# @param classes [String] Classi CSS aggiuntive
|
66
|
+
# @param id [String] ID HTML
|
67
|
+
# @param html_options [Hash] Attributi HTML aggiuntivi
|
68
|
+
def initialize(
|
69
|
+
name:,
|
70
|
+
style: :solid,
|
71
|
+
size: :medium,
|
72
|
+
theme: :default,
|
73
|
+
spin: false,
|
74
|
+
pulse: false,
|
75
|
+
border: false,
|
76
|
+
fixed_width: false,
|
77
|
+
rotation: nil,
|
78
|
+
flip: nil,
|
79
|
+
classes: nil,
|
80
|
+
id: nil,
|
81
|
+
**html_options
|
82
|
+
)
|
83
|
+
@name = name
|
84
|
+
@style = style.to_sym
|
85
|
+
@size = size.to_sym
|
86
|
+
@theme = theme.to_sym
|
87
|
+
@spin = spin
|
88
|
+
@pulse = pulse
|
89
|
+
@border = border
|
90
|
+
@fixed_width = fixed_width
|
91
|
+
@rotation = rotation&.to_i
|
92
|
+
@flip = flip&.to_sym
|
93
|
+
@classes = classes
|
94
|
+
@id = id
|
95
|
+
@html_options = html_options
|
96
|
+
|
97
|
+
validate_params!
|
98
|
+
end
|
99
|
+
|
100
|
+
# Genera le classi CSS complete per l'icona
|
101
|
+
def icon_classes
|
102
|
+
classes = [
|
103
|
+
ICON_BASE_CLASSES,
|
104
|
+
size_classes,
|
105
|
+
theme_classes,
|
106
|
+
animation_classes,
|
107
|
+
transformation_classes,
|
108
|
+
border_classes,
|
109
|
+
fixed_width_classes,
|
110
|
+
@classes
|
111
|
+
].compact.join(" ")
|
112
|
+
end
|
113
|
+
|
114
|
+
# Attributi HTML per l'elemento icona
|
115
|
+
def icon_attributes
|
116
|
+
{
|
117
|
+
class: icon_classes,
|
118
|
+
id: @id,
|
119
|
+
**@html_options
|
120
|
+
}.compact
|
121
|
+
end
|
122
|
+
|
123
|
+
# Nome completo della classe FontAwesome basato su stile
|
124
|
+
def fa_class_name
|
125
|
+
prefix = case @style
|
126
|
+
when :solid then "fas"
|
127
|
+
when :regular then "far"
|
128
|
+
when :brands then "fab"
|
129
|
+
else "fas"
|
130
|
+
end
|
131
|
+
|
132
|
+
"#{prefix} fa-#{@name}"
|
133
|
+
end
|
134
|
+
|
135
|
+
# Verifica se il componente deve essere renderizzato
|
136
|
+
def render?
|
137
|
+
@name.present?
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
def validate_params!
|
143
|
+
validate_name!
|
144
|
+
validate_style!
|
145
|
+
validate_size!
|
146
|
+
validate_theme!
|
147
|
+
validate_rotation!
|
148
|
+
validate_flip!
|
149
|
+
end
|
150
|
+
|
151
|
+
def validate_name!
|
152
|
+
raise ArgumentError, "Il nome dell'icona è richiesto" if @name.blank?
|
153
|
+
end
|
154
|
+
|
155
|
+
def validate_style!
|
156
|
+
valid_styles = [:solid, :regular, :brands]
|
157
|
+
unless valid_styles.include?(@style)
|
158
|
+
raise ArgumentError, "Lo stile deve essere uno tra: #{valid_styles.join(', ')}"
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def validate_size!
|
163
|
+
unless ICON_SIZE_CLASSES.key?(@size)
|
164
|
+
valid_sizes = ICON_SIZE_CLASSES.keys
|
165
|
+
raise ArgumentError, "La dimensione deve essere una tra: #{valid_sizes.join(', ')}"
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def validate_theme!
|
170
|
+
unless ICON_THEME_CLASSES.key?(@theme)
|
171
|
+
valid_themes = ICON_THEME_CLASSES.keys
|
172
|
+
raise ArgumentError, "Il tema deve essere uno tra: #{valid_themes.join(', ')}"
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def validate_rotation!
|
177
|
+
if @rotation && !ICON_ROTATION_CLASSES.key?(@rotation)
|
178
|
+
valid_rotations = ICON_ROTATION_CLASSES.keys
|
179
|
+
raise ArgumentError, "La rotazione deve essere una tra: #{valid_rotations.join(', ')}"
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def validate_flip!
|
184
|
+
if @flip && !ICON_FLIP_CLASSES.key?(@flip)
|
185
|
+
valid_flips = ICON_FLIP_CLASSES.keys
|
186
|
+
raise ArgumentError, "Il flip deve essere uno tra: #{valid_flips.join(', ')}"
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def size_classes
|
191
|
+
ICON_SIZE_CLASSES[@size]
|
192
|
+
end
|
193
|
+
|
194
|
+
def theme_classes
|
195
|
+
ICON_THEME_CLASSES[@theme]
|
196
|
+
end
|
197
|
+
|
198
|
+
def animation_classes
|
199
|
+
animations = []
|
200
|
+
animations << ICON_ANIMATION_CLASSES[:spin] if @spin
|
201
|
+
animations << ICON_ANIMATION_CLASSES[:pulse] if @pulse
|
202
|
+
animations.join(" ")
|
203
|
+
end
|
204
|
+
|
205
|
+
def transformation_classes
|
206
|
+
transformations = []
|
207
|
+
transformations << ICON_ROTATION_CLASSES[@rotation] if @rotation
|
208
|
+
transformations << ICON_FLIP_CLASSES[@flip] if @flip
|
209
|
+
transformations.join(" ")
|
210
|
+
end
|
211
|
+
|
212
|
+
def border_classes
|
213
|
+
@border ? ICON_BORDER_CLASSES : nil
|
214
|
+
end
|
215
|
+
|
216
|
+
def fixed_width_classes
|
217
|
+
@fixed_width ? ICON_FIXED_WIDTH_CLASSES : nil
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<%# Template per il link %>
|
2
|
+
<% if link? %>
|
3
|
+
<%= link_to @href, **element_attributes do %>
|
4
|
+
<% if show_icon? %>
|
5
|
+
<span class="<%= icon_classes %>"><%= render_icon %></span>
|
6
|
+
<% end %>
|
7
|
+
<span class="<%= text_classes %>"><%= @label %></span>
|
8
|
+
<%= content %>
|
9
|
+
<% end %>
|
10
|
+
<% else %>
|
11
|
+
<%= tag.span(**element_attributes) do %>
|
12
|
+
<% if show_icon? %>
|
13
|
+
<span class="<%= icon_classes %>"><%= render_icon %></span>
|
14
|
+
<% end %>
|
15
|
+
<span class="<%= text_classes %>"><%= @label %></span>
|
16
|
+
<%= content %>
|
17
|
+
<% end %>
|
18
|
+
<% end %>
|