better_ui 0.1.0 → 0.2.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/MIT-LICENSE +1 -1
- data/README.md +225 -119
- data/app/assets/stylesheets/better_ui/application.css +0 -356
- data/app/components/better_ui/application/card/component.html.erb +20 -0
- data/app/components/better_ui/application/card/component.rb +214 -0
- data/app/components/better_ui/application/main/component.html.erb +9 -0
- data/app/components/better_ui/application/main/component.rb +123 -0
- data/app/components/better_ui/application/navbar/component.html.erb +92 -0
- data/app/components/better_ui/application/navbar/component.rb +136 -0
- data/app/components/better_ui/application/sidebar/component.html.erb +190 -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 +187 -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/divider/component.html.erb +10 -0
- data/app/components/better_ui/general/divider/component.rb +226 -0
- data/app/components/better_ui/general/dropdown/component.html.erb +14 -0
- data/app/components/better_ui/general/dropdown/component.rb +219 -0
- data/app/components/better_ui/general/dropdown/divider_component.html.erb +1 -0
- data/app/components/better_ui/general/dropdown/divider_component.rb +41 -0
- data/app/components/better_ui/general/dropdown/item_component.html.erb +6 -0
- data/app/components/better_ui/general/dropdown/item_component.rb +118 -0
- data/app/components/better_ui/general/field/component.html.erb +27 -0
- data/app/components/better_ui/general/field/component.rb +37 -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 +7 -0
- data/app/components/better_ui/general/icon/component.rb +239 -0
- data/app/components/better_ui/general/input/checkbox/component.html.erb +5 -0
- data/app/components/better_ui/general/input/checkbox/component.rb +238 -0
- data/app/components/better_ui/general/input/datetime/component.html.erb +5 -0
- data/app/components/better_ui/general/input/datetime/component.rb +223 -0
- data/app/components/better_ui/general/input/radio/component.html.erb +5 -0
- data/app/components/better_ui/general/input/radio/component.rb +230 -0
- data/app/components/better_ui/general/input/select/component.html.erb +16 -0
- data/app/components/better_ui/general/input/select/component.rb +184 -0
- data/app/components/better_ui/general/input/select/select_component.html.erb +5 -0
- data/app/components/better_ui/general/input/select/select_component.rb +37 -0
- data/app/components/better_ui/general/input/text/component.html.erb +5 -0
- data/app/components/better_ui/general/input/text/component.rb +171 -0
- data/app/components/better_ui/general/input/textarea/component.html.erb +5 -0
- data/app/components/better_ui/general/input/textarea/component.rb +166 -0
- data/app/components/better_ui/general/link/component.html.erb +18 -0
- data/app/components/better_ui/general/link/component.rb +258 -0
- data/app/components/better_ui/general/modal/component.html.erb +42 -0
- data/app/components/better_ui/general/modal/component.rb +165 -0
- data/app/components/better_ui/general/pagination/component.html.erb +85 -0
- data/app/components/better_ui/general/pagination/component.rb +216 -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/tabs/component.html.erb +3 -0
- data/app/components/better_ui/general/tabs/component.rb +102 -0
- data/app/components/better_ui/general/tabs/panel_component.html.erb +3 -0
- data/app/components/better_ui/general/tabs/panel_component.rb +37 -0
- data/app/components/better_ui/general/tabs/tab_component.html.erb +13 -0
- data/app/components/better_ui/general/tabs/tab_component.rb +111 -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/helpers/better_ui/application/components/card/card_helper.rb +96 -0
- data/app/helpers/better_ui/application/components/card.rb +11 -0
- data/app/helpers/better_ui/application/components/main/main_helper.rb +64 -0
- data/app/helpers/better_ui/application/components/navbar/navbar_helper.rb +77 -0
- data/app/helpers/better_ui/application/components/sidebar/sidebar_helper.rb +51 -0
- data/app/helpers/better_ui/application_helper.rb +51 -179
- data/app/helpers/better_ui/general/components/alert/alert_helper.rb +57 -0
- data/app/helpers/better_ui/general/components/avatar/avatar_helper.rb +29 -0
- data/app/helpers/better_ui/general/components/badge/badge_helper.rb +53 -0
- data/app/helpers/better_ui/general/components/breadcrumb/breadcrumb_helper.rb +37 -0
- data/app/helpers/better_ui/general/components/button/button_helper.rb +65 -0
- data/app/helpers/better_ui/general/components/container/container_helper.rb +60 -0
- data/app/helpers/better_ui/general/components/divider/divider_helper.rb +63 -0
- data/app/helpers/better_ui/general/components/dropdown/divider_helper.rb +32 -0
- data/app/helpers/better_ui/general/components/dropdown/dropdown_helper.rb +79 -0
- data/app/helpers/better_ui/general/components/dropdown/item_helper.rb +62 -0
- data/app/helpers/better_ui/general/components/field/field_helper.rb +26 -0
- data/app/helpers/better_ui/general/components/heading/heading_helper.rb +72 -0
- data/app/helpers/better_ui/general/components/icon/icon_helper.rb +16 -0
- data/app/helpers/better_ui/general/components/input/checkbox/checkbox_helper.rb +81 -0
- data/app/helpers/better_ui/general/components/input/datetime/datetime_helper.rb +91 -0
- data/app/helpers/better_ui/general/components/input/radio/radio_helper.rb +79 -0
- data/app/helpers/better_ui/general/components/input/radio_group/radio_group_helper.rb +124 -0
- data/app/helpers/better_ui/general/components/input/select/select_helper.rb +70 -0
- data/app/helpers/better_ui/general/components/input/text/text_helper.rb +138 -0
- data/app/helpers/better_ui/general/components/input/textarea/textarea_helper.rb +73 -0
- data/app/helpers/better_ui/general/components/link/link_helper.rb +89 -0
- data/app/helpers/better_ui/general/components/modal/modal_helper.rb +95 -0
- data/app/helpers/better_ui/general/components/pagination/pagination_helper.rb +82 -0
- data/app/helpers/better_ui/general/components/panel/panel_helper.rb +83 -0
- data/app/helpers/better_ui/general/components/progress/progress_helper.rb +53 -0
- data/app/helpers/better_ui/general/components/spinner/spinner_helper.rb +19 -0
- data/app/helpers/better_ui/general/components/table/table_helper.rb +53 -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/tabs/panel_helper.rb +62 -0
- data/app/helpers/better_ui/general/components/tabs/tab_helper.rb +55 -0
- data/app/helpers/better_ui/general/components/tabs/tabs_helper.rb +62 -0
- data/app/helpers/better_ui/general/components/tag/tag_helper.rb +26 -0
- data/app/helpers/better_ui/general/components/tooltip/tooltip_helper.rb +60 -0
- data/app/views/layouts/better_ui/application.html.erb +6 -124
- data/config/initializers/lookbook.rb +23 -0
- data/config/routes.rb +0 -8
- data/lib/better_ui/engine.rb +5 -19
- data/lib/better_ui/railtie.rb +20 -0
- data/lib/better_ui/version.rb +1 -1
- data/lib/better_ui.rb +4 -20
- metadata +155 -28
- data/app/controllers/better_ui/docs_controller.rb +0 -41
- data/app/views/better_ui/docs/component.html.erb +0 -365
- data/app/views/better_ui/docs/index.html.erb +0 -100
- data/app/views/better_ui/docs/show.html.erb +0 -60
@@ -0,0 +1,258 @@
|
|
1
|
+
module BetterUi
|
2
|
+
module General
|
3
|
+
module Link
|
4
|
+
class Component < ViewComponent::Base
|
5
|
+
attr_reader :label, :href, :theme, :orientation, :style, :size, :icon, :active, :disabled, :data, :method, :target
|
6
|
+
|
7
|
+
# Classi base sempre presenti
|
8
|
+
LINK_BASE_CLASSES = "transition-colors duration-200 no-underline"
|
9
|
+
|
10
|
+
# Temi con classi Tailwind dirette - LOGICA CORRETTA
|
11
|
+
LINK_THEME_CLASSES = {
|
12
|
+
default: "text-white hover:text-gray-300", # Bianco per sfondi scuri
|
13
|
+
white: "text-gray-900 hover:text-gray-700", # Nero per sfondi chiari
|
14
|
+
red: "text-red-500 hover:text-red-600",
|
15
|
+
rose: "text-rose-500 hover:text-rose-600",
|
16
|
+
orange: "text-orange-500 hover:text-orange-600",
|
17
|
+
green: "text-green-500 hover:text-green-600",
|
18
|
+
blue: "text-blue-500 hover:text-blue-600",
|
19
|
+
yellow: "text-yellow-600 hover:text-yellow-700",
|
20
|
+
violet: "text-violet-500 hover:text-violet-600"
|
21
|
+
}
|
22
|
+
|
23
|
+
# Orientamenti con classi Tailwind dirette
|
24
|
+
LINK_ORIENTATION_CLASSES = {
|
25
|
+
horizontal: "inline-flex items-center",
|
26
|
+
vertical: "flex flex-col items-center"
|
27
|
+
}
|
28
|
+
|
29
|
+
# Stili con classi Tailwind dirette
|
30
|
+
LINK_STYLE_CLASSES = {
|
31
|
+
default: "",
|
32
|
+
underline: "underline",
|
33
|
+
bold: "font-bold",
|
34
|
+
text: "no-underline"
|
35
|
+
}
|
36
|
+
|
37
|
+
# Dimensioni con classi Tailwind dirette
|
38
|
+
LINK_SIZE_CLASSES = {
|
39
|
+
extra_small: "text-[0.65rem]",
|
40
|
+
small: "text-sm",
|
41
|
+
medium: "text-base",
|
42
|
+
large: "text-lg"
|
43
|
+
}
|
44
|
+
|
45
|
+
# Stati con classi Tailwind dirette
|
46
|
+
LINK_STATE_CLASSES = {
|
47
|
+
normal: "",
|
48
|
+
active: "font-semibold",
|
49
|
+
disabled: "opacity-50 cursor-not-allowed pointer-events-none"
|
50
|
+
}
|
51
|
+
|
52
|
+
# @param label [String] testo del link
|
53
|
+
# @param href [String] URL di destinazione (nil per semplice testo)
|
54
|
+
# @param theme [Symbol] tema del colore (:default, :white, etc.)
|
55
|
+
# @param orientation [Symbol] orientamento (:horizontal, :vertical)
|
56
|
+
# @param style [Symbol] stile (:default, :underline, :bold, :text)
|
57
|
+
# @param size [Symbol] dimensione (:extra_small, :small, :medium, :large)
|
58
|
+
# @param icon [String] icona opzionale
|
59
|
+
# @param active [Boolean] stato attivo del link
|
60
|
+
# @param disabled [Boolean] stato disabilitato del link
|
61
|
+
# @param data [Hash] attributi data
|
62
|
+
# @param method [Symbol] metodo HTTP (per Turbo)
|
63
|
+
# @param target [String] target del link
|
64
|
+
# @param html_options [Hash] opzioni HTML aggiuntive
|
65
|
+
def initialize(
|
66
|
+
label:,
|
67
|
+
href: nil,
|
68
|
+
theme: :white,
|
69
|
+
orientation: :horizontal,
|
70
|
+
style: :default,
|
71
|
+
size: :medium,
|
72
|
+
icon: nil,
|
73
|
+
active: false,
|
74
|
+
disabled: false,
|
75
|
+
data: {},
|
76
|
+
method: nil,
|
77
|
+
target: nil,
|
78
|
+
**html_options
|
79
|
+
)
|
80
|
+
@label = label
|
81
|
+
@href = href
|
82
|
+
@theme = theme.to_sym
|
83
|
+
@orientation = orientation.to_sym
|
84
|
+
@style = style.to_sym
|
85
|
+
@size = size.to_sym
|
86
|
+
@icon = icon
|
87
|
+
@active = active
|
88
|
+
@disabled = disabled
|
89
|
+
@data = data || {}
|
90
|
+
@method = method
|
91
|
+
@target = target
|
92
|
+
@html_options = html_options
|
93
|
+
|
94
|
+
validate_params
|
95
|
+
end
|
96
|
+
|
97
|
+
# Determina se è un link attivo/corrente
|
98
|
+
def active?
|
99
|
+
@active
|
100
|
+
end
|
101
|
+
|
102
|
+
# Determina se è disabilitato
|
103
|
+
def disabled?
|
104
|
+
@disabled
|
105
|
+
end
|
106
|
+
|
107
|
+
# Determina se è un link o solo testo
|
108
|
+
def link?
|
109
|
+
@href.present? && !@disabled
|
110
|
+
end
|
111
|
+
|
112
|
+
# Combina tutte le classi CSS
|
113
|
+
def combined_classes
|
114
|
+
[
|
115
|
+
LINK_BASE_CLASSES,
|
116
|
+
get_theme_class,
|
117
|
+
get_orientation_class,
|
118
|
+
get_style_class,
|
119
|
+
get_size_class,
|
120
|
+
get_state_class,
|
121
|
+
@html_options[:class]
|
122
|
+
].compact.join(" ")
|
123
|
+
end
|
124
|
+
|
125
|
+
# Classi per l'icona con dimensionamento proporzionale
|
126
|
+
def icon_classes
|
127
|
+
return "" unless @icon.present?
|
128
|
+
|
129
|
+
# Definisce spacing e dimensioni icona basate su size
|
130
|
+
base_spacing = case @orientation
|
131
|
+
when :horizontal
|
132
|
+
"mr-2"
|
133
|
+
when :vertical
|
134
|
+
"mb-1"
|
135
|
+
else
|
136
|
+
"mr-2"
|
137
|
+
end
|
138
|
+
|
139
|
+
icon_size = case @size
|
140
|
+
when :extra_small
|
141
|
+
"w-3 h-3"
|
142
|
+
when :small
|
143
|
+
"w-4 h-4"
|
144
|
+
when :medium
|
145
|
+
"w-5 h-5"
|
146
|
+
when :large
|
147
|
+
"w-6 h-6"
|
148
|
+
else
|
149
|
+
"w-5 h-5"
|
150
|
+
end
|
151
|
+
|
152
|
+
"#{base_spacing} #{icon_size} inline-block"
|
153
|
+
end
|
154
|
+
|
155
|
+
# Classi per il testo
|
156
|
+
def text_classes
|
157
|
+
"inline-block"
|
158
|
+
end
|
159
|
+
|
160
|
+
# Restituisce gli attributi per il link/span
|
161
|
+
def element_attributes
|
162
|
+
attrs = @html_options.except(:class)
|
163
|
+
attrs[:class] = combined_classes
|
164
|
+
|
165
|
+
if link?
|
166
|
+
# Attributi specifici per i link
|
167
|
+
if @method.present?
|
168
|
+
attrs[:data] = @data.merge(turbo_method: @method)
|
169
|
+
elsif @data.present?
|
170
|
+
attrs[:data] = @data
|
171
|
+
end
|
172
|
+
|
173
|
+
attrs[:target] = @target if @target.present?
|
174
|
+
attrs[:aria] ||= {}
|
175
|
+
attrs[:aria][:current] = "page" if active?
|
176
|
+
else
|
177
|
+
# Attributi per span (testo semplice o disabilitato)
|
178
|
+
attrs[:aria] ||= {}
|
179
|
+
attrs[:aria][:disabled] = true if disabled?
|
180
|
+
end
|
181
|
+
|
182
|
+
attrs
|
183
|
+
end
|
184
|
+
|
185
|
+
# Determina se mostrare l'icona
|
186
|
+
def show_icon?
|
187
|
+
@icon.present?
|
188
|
+
end
|
189
|
+
|
190
|
+
# Renderizza l'icona
|
191
|
+
def render_icon
|
192
|
+
return nil unless show_icon?
|
193
|
+
|
194
|
+
if @icon.is_a?(String)
|
195
|
+
render BetterUi::General::IconComponent.new(name: @icon)
|
196
|
+
else
|
197
|
+
@icon # Assumiamo che sia già un componente renderizzato
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
private
|
202
|
+
|
203
|
+
def get_theme_class
|
204
|
+
LINK_THEME_CLASSES[@theme] || LINK_THEME_CLASSES[:white]
|
205
|
+
end
|
206
|
+
|
207
|
+
def get_orientation_class
|
208
|
+
LINK_ORIENTATION_CLASSES[@orientation] || LINK_ORIENTATION_CLASSES[:horizontal]
|
209
|
+
end
|
210
|
+
|
211
|
+
def get_style_class
|
212
|
+
LINK_STYLE_CLASSES[@style] || LINK_STYLE_CLASSES[:default]
|
213
|
+
end
|
214
|
+
|
215
|
+
def get_size_class
|
216
|
+
LINK_SIZE_CLASSES[@size] || LINK_SIZE_CLASSES[:medium]
|
217
|
+
end
|
218
|
+
|
219
|
+
def get_state_class
|
220
|
+
return LINK_STATE_CLASSES[:disabled] if disabled?
|
221
|
+
return LINK_STATE_CLASSES[:active] if active?
|
222
|
+
LINK_STATE_CLASSES[:normal]
|
223
|
+
end
|
224
|
+
|
225
|
+
def validate_params
|
226
|
+
validate_theme
|
227
|
+
validate_orientation
|
228
|
+
validate_style
|
229
|
+
validate_size
|
230
|
+
end
|
231
|
+
|
232
|
+
def validate_theme
|
233
|
+
unless LINK_THEME_CLASSES.keys.include?(@theme)
|
234
|
+
raise ArgumentError, "Il tema deve essere uno tra: #{LINK_THEME_CLASSES.keys.join(', ')}"
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
def validate_orientation
|
239
|
+
unless LINK_ORIENTATION_CLASSES.keys.include?(@orientation)
|
240
|
+
raise ArgumentError, "L'orientamento deve essere uno tra: #{LINK_ORIENTATION_CLASSES.keys.join(', ')}"
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
def validate_style
|
245
|
+
unless LINK_STYLE_CLASSES.keys.include?(@style)
|
246
|
+
raise ArgumentError, "Lo stile deve essere uno tra: #{LINK_STYLE_CLASSES.keys.join(', ')}"
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
def validate_size
|
251
|
+
unless LINK_SIZE_CLASSES.keys.include?(@size)
|
252
|
+
raise ArgumentError, "La dimensione deve essere una tra: #{LINK_SIZE_CLASSES.keys.join(', ')}"
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
<%# Template per il modal %>
|
2
|
+
<% if @backdrop %>
|
3
|
+
<%= tag.div **backdrop_attributes do %>
|
4
|
+
<%= tag.div **container_attributes do %>
|
5
|
+
<%# Header del modal %>
|
6
|
+
<%= tag.div **header_attributes do %>
|
7
|
+
<h3 class="text-lg font-semibold" id="modal-title"><%= @title %></h3>
|
8
|
+
<% if @closable %>
|
9
|
+
<button type="button" class="text-gray-400 hover:text-gray-600 focus:outline-none focus:text-gray-600 transition-colors duration-200" aria-label="Chiudi modal">
|
10
|
+
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
11
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
12
|
+
</svg>
|
13
|
+
</button>
|
14
|
+
<% end %>
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
<%# Body del modal %>
|
18
|
+
<div class="p-6">
|
19
|
+
<%= content %>
|
20
|
+
</div>
|
21
|
+
<% end %>
|
22
|
+
<% end %>
|
23
|
+
<% else %>
|
24
|
+
<%= tag.div **container_attributes do %>
|
25
|
+
<%# Header del modal %>
|
26
|
+
<%= tag.div **header_attributes do %>
|
27
|
+
<h3 class="text-lg font-semibold" id="modal-title"><%= @title %></h3>
|
28
|
+
<% if @closable %>
|
29
|
+
<button type="button" class="text-gray-400 hover:text-gray-600 focus:outline-none focus:text-gray-600 transition-colors duration-200" aria-label="Chiudi modal">
|
30
|
+
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
31
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
32
|
+
</svg>
|
33
|
+
</button>
|
34
|
+
<% end %>
|
35
|
+
<% end %>
|
36
|
+
|
37
|
+
<%# Body del modal %>
|
38
|
+
<div class="p-6">
|
39
|
+
<%= content %>
|
40
|
+
</div>
|
41
|
+
<% end %>
|
42
|
+
<% end %>
|
@@ -0,0 +1,165 @@
|
|
1
|
+
module BetterUi
|
2
|
+
module General
|
3
|
+
module Modal
|
4
|
+
class Component < ViewComponent::Base
|
5
|
+
attr_reader :title, :theme, :size, :backdrop, :closable, :classes, :html_options
|
6
|
+
|
7
|
+
# Classi base sempre presenti per il backdrop
|
8
|
+
MODAL_BACKDROP_CLASSES = "fixed inset-0 z-50 flex items-center justify-center p-4 bg-black bg-opacity-50"
|
9
|
+
|
10
|
+
# Classi base per il contenitore del modal
|
11
|
+
MODAL_CONTAINER_CLASSES = "relative bg-white shadow-xl w-full"
|
12
|
+
|
13
|
+
# Temi dell'header del modal con classi Tailwind dirette
|
14
|
+
MODAL_THEME = {
|
15
|
+
default: "bg-gray-50 border-b border-gray-200 text-gray-900",
|
16
|
+
white: "bg-white border-b border-gray-200 text-gray-900",
|
17
|
+
red: "bg-red-50 border-b border-red-200 text-red-900",
|
18
|
+
rose: "bg-rose-50 border-b border-rose-200 text-rose-900",
|
19
|
+
orange: "bg-orange-50 border-b border-orange-200 text-orange-900",
|
20
|
+
green: "bg-green-50 border-b border-green-200 text-green-900",
|
21
|
+
blue: "bg-blue-50 border-b border-blue-200 text-blue-900",
|
22
|
+
yellow: "bg-yellow-50 border-b border-yellow-200 text-yellow-900",
|
23
|
+
violet: "bg-violet-50 border-b border-violet-200 text-violet-900"
|
24
|
+
}
|
25
|
+
|
26
|
+
# Dimensioni con classi Tailwind dirette
|
27
|
+
MODAL_SIZES = {
|
28
|
+
small: "max-w-sm",
|
29
|
+
medium: "max-w-md",
|
30
|
+
large: "max-w-2xl"
|
31
|
+
}
|
32
|
+
|
33
|
+
# Border radius con classi Tailwind dirette
|
34
|
+
MODAL_ROUNDED = {
|
35
|
+
none: "rounded-none",
|
36
|
+
small: "rounded-md",
|
37
|
+
medium: "rounded-lg",
|
38
|
+
large: "rounded-xl",
|
39
|
+
full: "rounded-full"
|
40
|
+
}
|
41
|
+
|
42
|
+
# Inizializzazione del componente
|
43
|
+
def initialize(
|
44
|
+
title:,
|
45
|
+
theme: :default,
|
46
|
+
size: :medium,
|
47
|
+
rounded: :medium,
|
48
|
+
backdrop: true,
|
49
|
+
closable: true,
|
50
|
+
classes: nil,
|
51
|
+
**html_options
|
52
|
+
)
|
53
|
+
@title = title
|
54
|
+
@theme = theme.to_sym
|
55
|
+
@size = size.to_sym
|
56
|
+
@rounded = rounded.to_sym
|
57
|
+
@backdrop = backdrop
|
58
|
+
@closable = closable
|
59
|
+
@classes = classes
|
60
|
+
@html_options = html_options
|
61
|
+
|
62
|
+
validate_params
|
63
|
+
end
|
64
|
+
|
65
|
+
# Combina tutte le classi per il backdrop
|
66
|
+
def backdrop_classes
|
67
|
+
MODAL_BACKDROP_CLASSES
|
68
|
+
end
|
69
|
+
|
70
|
+
# Combina tutte le classi per il contenitore
|
71
|
+
def container_classes
|
72
|
+
[
|
73
|
+
MODAL_CONTAINER_CLASSES,
|
74
|
+
get_modal_size_classes,
|
75
|
+
get_modal_rounded_classes,
|
76
|
+
@classes,
|
77
|
+
@html_options[:class]
|
78
|
+
].compact.join(" ")
|
79
|
+
end
|
80
|
+
|
81
|
+
# Combina tutte le classi per l'header
|
82
|
+
def header_classes
|
83
|
+
[
|
84
|
+
"flex items-center justify-between p-6",
|
85
|
+
get_modal_theme_classes
|
86
|
+
].compact.join(" ")
|
87
|
+
end
|
88
|
+
|
89
|
+
def get_modal_theme_classes
|
90
|
+
MODAL_THEME[@theme] || MODAL_THEME[:default]
|
91
|
+
end
|
92
|
+
|
93
|
+
def get_modal_size_classes
|
94
|
+
MODAL_SIZES[@size] || MODAL_SIZES[:medium]
|
95
|
+
end
|
96
|
+
|
97
|
+
def get_modal_rounded_classes
|
98
|
+
MODAL_ROUNDED[@rounded] || MODAL_ROUNDED[:medium]
|
99
|
+
end
|
100
|
+
|
101
|
+
# Restituisce gli attributi per il backdrop
|
102
|
+
def backdrop_attributes
|
103
|
+
attrs = {
|
104
|
+
class: backdrop_classes
|
105
|
+
}
|
106
|
+
|
107
|
+
# Aggiungi altri attributi HTML se presenti
|
108
|
+
@html_options.except(:class).each do |key, value|
|
109
|
+
attrs[key] = value
|
110
|
+
end
|
111
|
+
|
112
|
+
attrs
|
113
|
+
end
|
114
|
+
|
115
|
+
# Restituisce gli attributi per il contenitore
|
116
|
+
def container_attributes
|
117
|
+
{
|
118
|
+
class: container_classes,
|
119
|
+
role: "dialog",
|
120
|
+
"aria-modal": "true",
|
121
|
+
"aria-labelledby": "modal-title"
|
122
|
+
}
|
123
|
+
end
|
124
|
+
|
125
|
+
# Restituisce gli attributi per l'header
|
126
|
+
def header_attributes
|
127
|
+
{
|
128
|
+
class: header_classes
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
132
|
+
# Verifica se rendere il componente
|
133
|
+
def render?
|
134
|
+
@title.present?
|
135
|
+
end
|
136
|
+
|
137
|
+
private
|
138
|
+
|
139
|
+
def validate_params
|
140
|
+
validate_theme
|
141
|
+
validate_size
|
142
|
+
validate_rounded
|
143
|
+
end
|
144
|
+
|
145
|
+
def validate_theme
|
146
|
+
unless MODAL_THEME.keys.include?(@theme)
|
147
|
+
raise ArgumentError, "Il tema deve essere uno tra: #{MODAL_THEME.keys.join(', ')}"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def validate_size
|
152
|
+
unless MODAL_SIZES.keys.include?(@size)
|
153
|
+
raise ArgumentError, "La dimensione deve essere una tra: #{MODAL_SIZES.keys.join(', ')}"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def validate_rounded
|
158
|
+
unless MODAL_ROUNDED.keys.include?(@rounded)
|
159
|
+
raise ArgumentError, "Il border radius deve essere uno tra: #{MODAL_ROUNDED.keys.join(', ')}"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
<% if should_show_pagination? %>
|
2
|
+
<nav aria-label="Pagination" class="flex items-center justify-between">
|
3
|
+
|
4
|
+
<!-- Info testo opzionale -->
|
5
|
+
<% if show_info %>
|
6
|
+
<div class="hidden sm:block">
|
7
|
+
<p class="text-sm text-gray-700"><%= info_text %></p>
|
8
|
+
</div>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<!-- Controlli paginazione -->
|
12
|
+
<div class="<%= container_classes %>">
|
13
|
+
|
14
|
+
<!-- Pulsante Previous -->
|
15
|
+
<% if previous_page %>
|
16
|
+
<a href="<%= build_url(previous_page) %>"
|
17
|
+
class="<%= page_link_classes(previous_page) %> rounded-l-md"
|
18
|
+
aria-label="Pagina precedente">
|
19
|
+
<span class="sr-only">Precedente</span>
|
20
|
+
<%= bui_icon(name: "chevron-left", size: :medium) %>
|
21
|
+
</a>
|
22
|
+
<% else %>
|
23
|
+
<span class="<%= disabled_classes %> rounded-l-md" aria-label="Pagina precedente">
|
24
|
+
<span class="sr-only">Precedente</span>
|
25
|
+
<%= bui_icon(name: "chevron-left", size: :medium) %>
|
26
|
+
</span>
|
27
|
+
<% end %>
|
28
|
+
|
29
|
+
<!-- Prima pagina se necessaria -->
|
30
|
+
<% if show_left_ellipsis? %>
|
31
|
+
<a href="<%= build_url(1) %>" class="<%= page_link_classes(1) %>">1</a>
|
32
|
+
<span class="<%= disabled_classes %>">...</span>
|
33
|
+
<% end %>
|
34
|
+
|
35
|
+
<!-- Range pagine -->
|
36
|
+
<% page_range.each do |page_num| %>
|
37
|
+
<% if page_num == current_page %>
|
38
|
+
<span aria-current="page" class="<%= page_link_classes(page_num) %>">
|
39
|
+
<%= page_num %>
|
40
|
+
</span>
|
41
|
+
<% else %>
|
42
|
+
<a href="<%= build_url(page_num) %>"
|
43
|
+
class="<%= page_link_classes(page_num) %>"
|
44
|
+
aria-label="Vai alla pagina <%= page_num %>">
|
45
|
+
<%= page_num %>
|
46
|
+
</a>
|
47
|
+
<% end %>
|
48
|
+
<% end %>
|
49
|
+
|
50
|
+
<!-- Ultima pagina se necessaria -->
|
51
|
+
<% if show_right_ellipsis? %>
|
52
|
+
<span class="<%= disabled_classes %>">...</span>
|
53
|
+
<a href="<%= build_url(total_pages) %>" class="<%= page_link_classes(total_pages) %>">
|
54
|
+
<%= total_pages %>
|
55
|
+
</a>
|
56
|
+
<% end %>
|
57
|
+
|
58
|
+
<!-- Pulsante Next -->
|
59
|
+
<% if next_page %>
|
60
|
+
<a href="<%= build_url(next_page) %>"
|
61
|
+
class="<%= page_link_classes(next_page) %> rounded-r-md"
|
62
|
+
aria-label="Pagina successiva">
|
63
|
+
<span class="sr-only">Successiva</span>
|
64
|
+
<%= bui_icon(name: "chevron-right", size: :medium) %>
|
65
|
+
</a>
|
66
|
+
<% else %>
|
67
|
+
<span class="<%= disabled_classes %> rounded-r-md" aria-label="Pagina successiva">
|
68
|
+
<span class="sr-only">Successiva</span>
|
69
|
+
<%= bui_icon(name: "chevron-right", size: :medium) %>
|
70
|
+
</span>
|
71
|
+
<% end %>
|
72
|
+
|
73
|
+
</div>
|
74
|
+
|
75
|
+
<!-- Info mobile -->
|
76
|
+
<% if show_info %>
|
77
|
+
<div class="flex flex-1 justify-between sm:hidden">
|
78
|
+
<span class="text-sm text-gray-700">
|
79
|
+
Pagina <%= current_page %> di <%= total_pages %>
|
80
|
+
</span>
|
81
|
+
</div>
|
82
|
+
<% end %>
|
83
|
+
|
84
|
+
</nav>
|
85
|
+
<% end %>
|