better_ui 0.6.0 → 0.7.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 +257 -212
- data/Rakefile +11 -2
- data/app/components/better_ui/action_messages_component/action_messages_component.html.erb +48 -0
- data/app/components/better_ui/action_messages_component.rb +544 -0
- data/app/components/better_ui/application_component.rb +66 -0
- data/app/components/better_ui/button_component/button_component.html.erb +31 -0
- data/app/components/better_ui/button_component.rb +307 -0
- data/app/components/better_ui/card_component/card_component.html.erb +17 -0
- data/app/components/better_ui/card_component.rb +460 -0
- data/app/components/better_ui/drawer/header_component/header_component.html.erb +24 -0
- data/app/components/better_ui/drawer/header_component.rb +238 -0
- data/app/components/better_ui/drawer/layout_component/layout_component.html.erb +44 -0
- data/app/components/better_ui/drawer/layout_component.rb +270 -0
- data/app/components/better_ui/drawer/nav_group_component/nav_group_component.html.erb +10 -0
- data/app/components/better_ui/drawer/nav_group_component.rb +155 -0
- data/app/components/better_ui/drawer/nav_item_component/nav_item_component.html.erb +13 -0
- data/app/components/better_ui/drawer/nav_item_component.rb +225 -0
- data/app/components/better_ui/drawer/sidebar_component/sidebar_component.html.erb +17 -0
- data/app/components/better_ui/drawer/sidebar_component.rb +263 -0
- data/app/components/better_ui/forms/base_component.rb +450 -0
- data/app/components/better_ui/forms/checkbox_component/checkbox_component.html.erb +28 -0
- data/app/components/better_ui/forms/checkbox_component.rb +419 -0
- data/app/components/better_ui/forms/checkbox_group_component/checkbox_group_component.html.erb +40 -0
- data/app/components/better_ui/forms/checkbox_group_component.rb +363 -0
- data/app/components/better_ui/forms/number_input_component/number_input_component.html.erb +40 -0
- data/app/components/better_ui/forms/number_input_component.rb +320 -0
- data/app/components/better_ui/forms/password_input_component/password_input_component.html.erb +71 -0
- data/app/components/better_ui/forms/password_input_component.rb +206 -0
- data/app/components/better_ui/forms/text_input_component/text_input_component.html.erb +40 -0
- data/app/components/better_ui/forms/text_input_component.rb +258 -0
- data/app/components/better_ui/forms/textarea_component/textarea_component.html.erb +40 -0
- data/app/components/better_ui/forms/textarea_component.rb +329 -0
- data/app/form_builders/better_ui/ui_form_builder.rb +467 -0
- data/app/helpers/better_ui/application_helper.rb +325 -58
- data/app/views/layouts/better_ui/application.html.erb +1 -1
- data/config/routes.rb +1 -0
- data/lib/better_ui/engine.rb +34 -5
- data/lib/better_ui/version.rb +1 -1
- data/lib/better_ui.rb +32 -5
- data/lib/generators/better_ui/install/USAGE +44 -0
- data/lib/generators/better_ui/install/install_generator.rb +87 -0
- data/lib/generators/better_ui/install/templates/better_ui_theme.css.tt +280 -0
- data/lib/tasks/better_ui_tasks.rake +39 -4
- metadata +52 -200
- data/app/components/better_ui/application/card/component.html.erb +0 -20
- data/app/components/better_ui/application/card/component.rb +0 -214
- data/app/components/better_ui/application/main/component.html.erb +0 -9
- data/app/components/better_ui/application/main/component.rb +0 -123
- data/app/components/better_ui/application/navbar/component.html.erb +0 -92
- data/app/components/better_ui/application/navbar/component.rb +0 -136
- data/app/components/better_ui/application/sidebar/component.html.erb +0 -249
- data/app/components/better_ui/application/sidebar/component.rb +0 -187
- data/app/components/better_ui/general/accordion/component.html.erb +0 -5
- data/app/components/better_ui/general/accordion/component.rb +0 -92
- data/app/components/better_ui/general/accordion/item_component.html.erb +0 -12
- data/app/components/better_ui/general/accordion/item_component.rb +0 -176
- data/app/components/better_ui/general/alert/component.html.erb +0 -32
- data/app/components/better_ui/general/alert/component.rb +0 -242
- data/app/components/better_ui/general/avatar/component.html.erb +0 -20
- data/app/components/better_ui/general/avatar/component.rb +0 -301
- data/app/components/better_ui/general/badge/component.html.erb +0 -23
- data/app/components/better_ui/general/badge/component.rb +0 -248
- data/app/components/better_ui/general/breadcrumb/component.html.erb +0 -15
- data/app/components/better_ui/general/breadcrumb/component.rb +0 -187
- data/app/components/better_ui/general/button/component.html.erb +0 -34
- data/app/components/better_ui/general/button/component.rb +0 -214
- data/app/components/better_ui/general/divider/component.html.erb +0 -10
- data/app/components/better_ui/general/divider/component.rb +0 -226
- data/app/components/better_ui/general/dropdown/component.html.erb +0 -28
- data/app/components/better_ui/general/dropdown/component.rb +0 -192
- data/app/components/better_ui/general/dropdown/divider_component.html.erb +0 -1
- data/app/components/better_ui/general/dropdown/divider_component.rb +0 -41
- data/app/components/better_ui/general/dropdown/item_component.html.erb +0 -6
- data/app/components/better_ui/general/dropdown/item_component.rb +0 -119
- data/app/components/better_ui/general/field/component.html.erb +0 -27
- data/app/components/better_ui/general/field/component.rb +0 -37
- data/app/components/better_ui/general/grid/cell_component.html.erb +0 -3
- data/app/components/better_ui/general/grid/cell_component.rb +0 -390
- data/app/components/better_ui/general/grid/component.html.erb +0 -3
- data/app/components/better_ui/general/grid/component.rb +0 -301
- data/app/components/better_ui/general/heading/component.html.erb +0 -22
- data/app/components/better_ui/general/heading/component.rb +0 -257
- data/app/components/better_ui/general/icon/component.html.erb +0 -7
- data/app/components/better_ui/general/icon/component.rb +0 -240
- data/app/components/better_ui/general/input/checkbox/component.html.erb +0 -5
- data/app/components/better_ui/general/input/checkbox/component.rb +0 -238
- data/app/components/better_ui/general/input/datetime/component.html.erb +0 -5
- data/app/components/better_ui/general/input/datetime/component.rb +0 -223
- data/app/components/better_ui/general/input/pin/component.html.erb +0 -1
- data/app/components/better_ui/general/input/pin/component.rb +0 -201
- data/app/components/better_ui/general/input/radio/component.html.erb +0 -5
- data/app/components/better_ui/general/input/radio/component.rb +0 -230
- data/app/components/better_ui/general/input/rating/component.html.erb +0 -4
- data/app/components/better_ui/general/input/rating/component.rb +0 -272
- data/app/components/better_ui/general/input/select/component.html.erb +0 -78
- data/app/components/better_ui/general/input/select/component.rb +0 -249
- data/app/components/better_ui/general/input/select/select_component.html.erb +0 -5
- data/app/components/better_ui/general/input/select/select_component.rb +0 -37
- data/app/components/better_ui/general/input/text/component.html.erb +0 -5
- data/app/components/better_ui/general/input/text/component.rb +0 -171
- data/app/components/better_ui/general/input/textarea/component.html.erb +0 -5
- data/app/components/better_ui/general/input/textarea/component.rb +0 -166
- data/app/components/better_ui/general/input/toggle/component.html.erb +0 -5
- data/app/components/better_ui/general/input/toggle/component.rb +0 -242
- data/app/components/better_ui/general/link/component.html.erb +0 -18
- data/app/components/better_ui/general/link/component.rb +0 -258
- data/app/components/better_ui/general/modal/component.html.erb +0 -5
- data/app/components/better_ui/general/modal/component.rb +0 -47
- data/app/components/better_ui/general/modal/modal_component.html.erb +0 -52
- data/app/components/better_ui/general/modal/modal_component.rb +0 -160
- data/app/components/better_ui/general/pagination/component.html.erb +0 -85
- data/app/components/better_ui/general/pagination/component.rb +0 -216
- data/app/components/better_ui/general/panel/component.html.erb +0 -28
- data/app/components/better_ui/general/panel/component.rb +0 -249
- data/app/components/better_ui/general/progress/component.html.erb +0 -11
- data/app/components/better_ui/general/progress/component.rb +0 -160
- data/app/components/better_ui/general/spinner/component.html.erb +0 -35
- data/app/components/better_ui/general/spinner/component.rb +0 -93
- data/app/components/better_ui/general/table/component.html.erb +0 -5
- data/app/components/better_ui/general/table/component.rb +0 -217
- data/app/components/better_ui/general/table/tbody_component.html.erb +0 -3
- data/app/components/better_ui/general/table/tbody_component.rb +0 -30
- data/app/components/better_ui/general/table/td_component.html.erb +0 -3
- data/app/components/better_ui/general/table/td_component.rb +0 -44
- data/app/components/better_ui/general/table/tfoot_component.html.erb +0 -3
- data/app/components/better_ui/general/table/tfoot_component.rb +0 -28
- data/app/components/better_ui/general/table/th_component.html.erb +0 -6
- data/app/components/better_ui/general/table/th_component.rb +0 -51
- data/app/components/better_ui/general/table/thead_component.html.erb +0 -3
- data/app/components/better_ui/general/table/thead_component.rb +0 -28
- data/app/components/better_ui/general/table/tr_component.html.erb +0 -3
- data/app/components/better_ui/general/table/tr_component.rb +0 -30
- data/app/components/better_ui/general/tabs/component.html.erb +0 -11
- data/app/components/better_ui/general/tabs/component.rb +0 -120
- data/app/components/better_ui/general/tabs/panel_component.html.erb +0 -3
- data/app/components/better_ui/general/tabs/panel_component.rb +0 -37
- data/app/components/better_ui/general/tabs/tab_component.html.erb +0 -13
- data/app/components/better_ui/general/tabs/tab_component.rb +0 -111
- data/app/components/better_ui/general/tag/component.html.erb +0 -3
- data/app/components/better_ui/general/tag/component.rb +0 -104
- data/app/components/better_ui/general/text/component.html.erb +0 -1
- data/app/components/better_ui/general/text/component.rb +0 -194
- data/app/components/better_ui/general/tooltip/component.html.erb +0 -7
- data/app/components/better_ui/general/tooltip/component.rb +0 -239
- data/app/helpers/better_ui/application/components/card/card_helper.rb +0 -96
- data/app/helpers/better_ui/application/components/card.rb +0 -11
- data/app/helpers/better_ui/application/components/main/main_helper.rb +0 -64
- data/app/helpers/better_ui/application/components/navbar/navbar_helper.rb +0 -77
- data/app/helpers/better_ui/application/components/sidebar/sidebar_helper.rb +0 -51
- data/app/helpers/better_ui/general/components/accordion/accordion_helper.rb +0 -73
- data/app/helpers/better_ui/general/components/alert/alert_helper.rb +0 -57
- data/app/helpers/better_ui/general/components/avatar/avatar_helper.rb +0 -29
- data/app/helpers/better_ui/general/components/badge/badge_helper.rb +0 -53
- data/app/helpers/better_ui/general/components/breadcrumb/breadcrumb_helper.rb +0 -37
- data/app/helpers/better_ui/general/components/button/button_helper.rb +0 -65
- data/app/helpers/better_ui/general/components/container/container_helper.rb +0 -60
- data/app/helpers/better_ui/general/components/divider/divider_helper.rb +0 -63
- data/app/helpers/better_ui/general/components/dropdown/divider_helper.rb +0 -32
- data/app/helpers/better_ui/general/components/dropdown/dropdown_helper.rb +0 -88
- data/app/helpers/better_ui/general/components/dropdown/item_helper.rb +0 -68
- data/app/helpers/better_ui/general/components/field/field_helper.rb +0 -26
- data/app/helpers/better_ui/general/components/grid/grid_helper.rb +0 -145
- data/app/helpers/better_ui/general/components/heading/heading_helper.rb +0 -72
- data/app/helpers/better_ui/general/components/icon/icon_helper.rb +0 -16
- data/app/helpers/better_ui/general/components/input/checkbox/checkbox_helper.rb +0 -81
- data/app/helpers/better_ui/general/components/input/datetime/datetime_helper.rb +0 -91
- data/app/helpers/better_ui/general/components/input/pin/pin_helper.rb +0 -76
- data/app/helpers/better_ui/general/components/input/radio/radio_helper.rb +0 -79
- data/app/helpers/better_ui/general/components/input/radio_group/radio_group_helper.rb +0 -124
- data/app/helpers/better_ui/general/components/input/rating/rating_helper.rb +0 -70
- data/app/helpers/better_ui/general/components/input/select/select_helper.rb +0 -86
- data/app/helpers/better_ui/general/components/input/text/text_helper.rb +0 -138
- data/app/helpers/better_ui/general/components/input/textarea/textarea_helper.rb +0 -73
- data/app/helpers/better_ui/general/components/input/toggle/toggle_helper.rb +0 -77
- data/app/helpers/better_ui/general/components/link/link_helper.rb +0 -89
- data/app/helpers/better_ui/general/components/modal/modal_helper.rb +0 -85
- data/app/helpers/better_ui/general/components/pagination/pagination_helper.rb +0 -82
- data/app/helpers/better_ui/general/components/panel/panel_helper.rb +0 -83
- data/app/helpers/better_ui/general/components/progress/progress_helper.rb +0 -53
- data/app/helpers/better_ui/general/components/spinner/spinner_helper.rb +0 -19
- data/app/helpers/better_ui/general/components/table/table_helper.rb +0 -53
- data/app/helpers/better_ui/general/components/table/tbody_helper.rb +0 -13
- data/app/helpers/better_ui/general/components/table/td_helper.rb +0 -19
- data/app/helpers/better_ui/general/components/table/tfoot_helper.rb +0 -13
- data/app/helpers/better_ui/general/components/table/th_helper.rb +0 -19
- data/app/helpers/better_ui/general/components/table/thead_helper.rb +0 -13
- data/app/helpers/better_ui/general/components/table/tr_helper.rb +0 -13
- data/app/helpers/better_ui/general/components/tabs/panel_helper.rb +0 -62
- data/app/helpers/better_ui/general/components/tabs/tab_helper.rb +0 -55
- data/app/helpers/better_ui/general/components/tabs/tabs_helper.rb +0 -95
- data/app/helpers/better_ui/general/components/tag/tag_helper.rb +0 -26
- data/app/helpers/better_ui/general/components/text/text_helper.rb +0 -83
- data/app/helpers/better_ui/general/components/tooltip/tooltip_helper.rb +0 -60
- data/app/jobs/better_ui/application_job.rb +0 -4
- data/app/mailers/better_ui/application_mailer.rb +0 -6
- data/config/initializers/lookbook.rb +0 -23
- data/lib/better_ui/railtie.rb +0 -20
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module BetterUi
|
|
4
|
-
module General
|
|
5
|
-
module Input
|
|
6
|
-
module Select
|
|
7
|
-
class Component < ViewComponent::Base
|
|
8
|
-
# Costanti con classi Tailwind dirette
|
|
9
|
-
SELECT_THEME = {
|
|
10
|
-
default: 'border-gray-300 text-gray-800 focus:border-gray-600 focus:ring-gray-600',
|
|
11
|
-
white: 'border-gray-300 text-gray-900 focus:border-gray-500 focus:ring-gray-500',
|
|
12
|
-
red: 'border-gray-300 text-red-600 focus:border-red-500 focus:ring-red-500',
|
|
13
|
-
rose: 'border-gray-300 text-rose-600 focus:border-rose-500 focus:ring-rose-500',
|
|
14
|
-
orange: 'border-gray-300 text-orange-600 focus:border-orange-500 focus:ring-orange-500',
|
|
15
|
-
green: 'border-gray-300 text-green-600 focus:border-green-500 focus:ring-green-500',
|
|
16
|
-
blue: 'border-gray-300 text-blue-600 focus:border-blue-500 focus:ring-blue-500',
|
|
17
|
-
yellow: 'border-gray-300 text-yellow-600 focus:border-yellow-500 focus:ring-yellow-500',
|
|
18
|
-
violet: 'border-gray-300 text-violet-600 focus:border-violet-500 focus:ring-violet-500'
|
|
19
|
-
}.freeze
|
|
20
|
-
|
|
21
|
-
SELECT_SIZE = {
|
|
22
|
-
small: 'px-2 py-1.5 text-xs',
|
|
23
|
-
medium: 'px-3 py-2 text-sm',
|
|
24
|
-
large: 'px-4 py-3 text-base'
|
|
25
|
-
}.freeze
|
|
26
|
-
|
|
27
|
-
SELECT_ROUNDED = {
|
|
28
|
-
none: 'rounded-none',
|
|
29
|
-
small: 'rounded-sm',
|
|
30
|
-
medium: 'rounded',
|
|
31
|
-
large: 'rounded-lg',
|
|
32
|
-
full: 'rounded-full'
|
|
33
|
-
}.freeze
|
|
34
|
-
|
|
35
|
-
SELECT_BASE_CLASSES = 'block w-full bg-white border-2 shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 transition-colors duration-200'.freeze
|
|
36
|
-
|
|
37
|
-
attr_reader :name, :options, :selected, :required, :disabled, :multiple, :searchable,
|
|
38
|
-
:theme, :size, :rounded, :placeholder, :search_placeholder, :max_height,
|
|
39
|
-
:form, :classes, :html_options
|
|
40
|
-
|
|
41
|
-
# @param name [String] Nome del campo select (obbligatorio)
|
|
42
|
-
# @param options [Array<Hash>] Array di opzioni nel formato [{value: 'value', label: 'label'}, ...]
|
|
43
|
-
# @param selected [String, Array, nil] Valore/i selezionato/i
|
|
44
|
-
# @param required [Boolean] Se il campo è obbligatorio
|
|
45
|
-
# @param disabled [Boolean] Se il campo è disabilitato
|
|
46
|
-
# @param multiple [Boolean] Se multiple opzioni possono essere selezionate
|
|
47
|
-
# @param searchable [Boolean] Se abilitare la ricerca
|
|
48
|
-
# @param theme [Symbol] Tema del componente (:default, :white, :red, :rose, :orange, :green, :blue, :yellow, :violet)
|
|
49
|
-
# @param size [Symbol] Dimensione del componente (:small, :medium, :large)
|
|
50
|
-
# @param rounded [Symbol] Border radius (:none, :small, :medium, :large, :full)
|
|
51
|
-
# @param placeholder [String] Testo placeholder per il trigger
|
|
52
|
-
# @param search_placeholder [String] Testo placeholder per il campo search
|
|
53
|
-
# @param max_height [String] Altezza massima del dropdown (default: "300px")
|
|
54
|
-
# @param form [ActionView::Helpers::FormBuilder, nil] Form builder Rails opzionale
|
|
55
|
-
# @param classes [String] Classi CSS aggiuntive
|
|
56
|
-
# @param html_options [Hash] Attributi HTML aggiuntivi
|
|
57
|
-
def initialize(
|
|
58
|
-
name:,
|
|
59
|
-
options:,
|
|
60
|
-
selected: nil,
|
|
61
|
-
required: false,
|
|
62
|
-
disabled: false,
|
|
63
|
-
multiple: false,
|
|
64
|
-
searchable: true,
|
|
65
|
-
theme: :default,
|
|
66
|
-
size: :medium,
|
|
67
|
-
rounded: :medium,
|
|
68
|
-
placeholder: nil,
|
|
69
|
-
search_placeholder: nil,
|
|
70
|
-
max_height: "300px",
|
|
71
|
-
form: nil,
|
|
72
|
-
classes: '',
|
|
73
|
-
**html_options
|
|
74
|
-
)
|
|
75
|
-
@name = name
|
|
76
|
-
@options = options
|
|
77
|
-
@selected = normalize_selected(selected)
|
|
78
|
-
@required = required
|
|
79
|
-
@disabled = disabled
|
|
80
|
-
@multiple = multiple
|
|
81
|
-
@searchable = searchable
|
|
82
|
-
@theme = theme.to_sym
|
|
83
|
-
@size = size.to_sym
|
|
84
|
-
@rounded = rounded.to_sym
|
|
85
|
-
@placeholder = placeholder || (multiple ? "Seleziona opzioni..." : "Seleziona...")
|
|
86
|
-
@search_placeholder = search_placeholder || "Cerca..."
|
|
87
|
-
@max_height = max_height
|
|
88
|
-
@form = form
|
|
89
|
-
@classes = classes
|
|
90
|
-
@html_options = html_options
|
|
91
|
-
|
|
92
|
-
validate_params
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
private
|
|
96
|
-
|
|
97
|
-
def validate_params
|
|
98
|
-
validate_theme
|
|
99
|
-
validate_size
|
|
100
|
-
validate_rounded
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def validate_theme
|
|
104
|
-
return if SELECT_THEME.key?(@theme)
|
|
105
|
-
|
|
106
|
-
raise ArgumentError, "Invalid theme: #{@theme}. Valid themes are: #{SELECT_THEME.keys.join(', ')}"
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
def validate_size
|
|
110
|
-
return if SELECT_SIZE.key?(@size)
|
|
111
|
-
|
|
112
|
-
raise ArgumentError, "Invalid size: #{@size}. Valid sizes are: #{SELECT_SIZE.keys.join(', ')}"
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def validate_rounded
|
|
116
|
-
return if SELECT_ROUNDED.key?(@rounded)
|
|
117
|
-
|
|
118
|
-
raise ArgumentError, "Invalid rounded: #{@rounded}. Valid rounded options are: #{SELECT_ROUNDED.keys.join(', ')}"
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
def normalize_selected(selected)
|
|
122
|
-
return [] if selected.nil?
|
|
123
|
-
return selected if selected.is_a?(Array)
|
|
124
|
-
[selected]
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
def container_attributes
|
|
128
|
-
{
|
|
129
|
-
'data-controller': 'select',
|
|
130
|
-
'data-select-multiple-value': @multiple,
|
|
131
|
-
'data-select-searchable-value': @searchable,
|
|
132
|
-
'data-select-selected-value': @selected.to_json,
|
|
133
|
-
'data-select-placeholder-value': @placeholder,
|
|
134
|
-
'data-select-search-placeholder-value': @search_placeholder,
|
|
135
|
-
'data-action': 'keydown->select#keydown',
|
|
136
|
-
class: "relative #{@classes}"
|
|
137
|
-
}.merge(@html_options)
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
def trigger_classes
|
|
141
|
-
[
|
|
142
|
-
SELECT_BASE_CLASSES,
|
|
143
|
-
SELECT_THEME[@theme],
|
|
144
|
-
SELECT_SIZE[@size],
|
|
145
|
-
SELECT_ROUNDED[@rounded],
|
|
146
|
-
'cursor-pointer flex items-center justify-between',
|
|
147
|
-
@disabled ? 'opacity-50 cursor-not-allowed' : 'hover:border-gray-400'
|
|
148
|
-
].compact.join(' ')
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
def dropdown_classes
|
|
152
|
-
[
|
|
153
|
-
'absolute z-50 w-full mt-1 bg-white border border-gray-300 shadow-lg',
|
|
154
|
-
@rounded == :none ? 'rounded-none' : 'rounded-md',
|
|
155
|
-
'hidden opacity-0 scale-95 translate-y-1',
|
|
156
|
-
'transition-all duration-150 ease-out'
|
|
157
|
-
].join(' ')
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
def search_input_classes
|
|
161
|
-
[
|
|
162
|
-
'w-full px-3 py-2 text-sm border-0 border-b border-gray-200',
|
|
163
|
-
'focus:outline-none focus:border-gray-400 bg-gray-50'
|
|
164
|
-
].join(' ')
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
def options_container_classes
|
|
168
|
-
[
|
|
169
|
-
'overflow-y-auto',
|
|
170
|
-
"max-h-[#{@max_height}]"
|
|
171
|
-
].join(' ')
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
def option_classes
|
|
175
|
-
[
|
|
176
|
-
'px-3 py-2 cursor-pointer hover:bg-gray-50 flex items-center justify-between',
|
|
177
|
-
'transition-colors duration-150'
|
|
178
|
-
].join(' ')
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
def input_name
|
|
182
|
-
if @form.present?
|
|
183
|
-
@form.field_name(@name)
|
|
184
|
-
else
|
|
185
|
-
@multiple ? "#{@name}[]" : @name
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
def input_id
|
|
190
|
-
if @form.present?
|
|
191
|
-
@form.field_id(@name)
|
|
192
|
-
else
|
|
193
|
-
@name.to_s.gsub(/[\[\]]+/, '_').gsub(/_$/, '')
|
|
194
|
-
end
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
def hidden_input_value
|
|
198
|
-
if @multiple
|
|
199
|
-
@selected.to_json
|
|
200
|
-
else
|
|
201
|
-
@selected.first || ''
|
|
202
|
-
end
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
def trigger_text
|
|
206
|
-
if @selected.empty?
|
|
207
|
-
@placeholder
|
|
208
|
-
elsif @multiple
|
|
209
|
-
case @selected.length
|
|
210
|
-
when 1
|
|
211
|
-
selected_option = @options.find { |opt| opt[:value].to_s == @selected.first.to_s }
|
|
212
|
-
selected_option ? selected_option[:label] : @selected.first
|
|
213
|
-
else
|
|
214
|
-
"#{@selected.length} selezionati"
|
|
215
|
-
end
|
|
216
|
-
else
|
|
217
|
-
selected_option = @options.find { |opt| opt[:value].to_s == @selected.first.to_s }
|
|
218
|
-
selected_option ? selected_option[:label] : @selected.first
|
|
219
|
-
end
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
def trigger_text_classes
|
|
223
|
-
@selected.empty? ? 'text-gray-500' : 'text-gray-900'
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
def selected_option_values
|
|
227
|
-
@selected.map(&:to_s)
|
|
228
|
-
end
|
|
229
|
-
|
|
230
|
-
def option_selected?(option)
|
|
231
|
-
selected_option_values.include?(option[:value].to_s)
|
|
232
|
-
end
|
|
233
|
-
|
|
234
|
-
def badge_container_classes
|
|
235
|
-
'flex flex-wrap gap-1 mt-2'
|
|
236
|
-
end
|
|
237
|
-
|
|
238
|
-
def chevron_icon
|
|
239
|
-
'
|
|
240
|
-
<svg class="w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
241
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
|
|
242
|
-
</svg>
|
|
243
|
-
'.html_safe
|
|
244
|
-
end
|
|
245
|
-
end
|
|
246
|
-
end
|
|
247
|
-
end
|
|
248
|
-
end
|
|
249
|
-
end
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
<select name="<%= name %>" class="<%= classes %>" <%= "required" if required %> <%= "disabled" if disabled %> <%= "multiple" if multiple %> <%= options_html.map { |key, value| "#{key}=\"#{value}\"" }.join(" ") %>>
|
|
2
|
-
<% options.each do |option| %>
|
|
3
|
-
<option value="<%= option[:value] %>" <%= "selected" if option[:value] == selected %>><%= option[:label] %></option>
|
|
4
|
-
<% end %>
|
|
5
|
-
</select>
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module BetterUi
|
|
4
|
-
module General
|
|
5
|
-
module Input
|
|
6
|
-
module Select
|
|
7
|
-
class SelectComponent < ViewComponent::Base
|
|
8
|
-
attr_reader :name, :options, :selected, :required, :disabled, :multiple, :options_html, :classes, :html_options
|
|
9
|
-
|
|
10
|
-
BASE_SELECT_CLASSES = "h-10 px-3 py-2 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm disabled:bg-gray-100 disabled:cursor-not-allowed"
|
|
11
|
-
# @param name [String] Nome del campo
|
|
12
|
-
# @param options [Array] Opzioni del select ([{value => label}, {value => label}, ...])
|
|
13
|
-
# @param selected [String, Array] Valore selezionato
|
|
14
|
-
# @param required [Boolean] Se il campo è obbligatorio
|
|
15
|
-
# @param disabled [Boolean] Se il campo è disabilitato
|
|
16
|
-
# @param multiple [Boolean] Se il select è multiplo
|
|
17
|
-
# @param options_html [Hash] Opzioni HTML aggiuntive per le option
|
|
18
|
-
# @param classes [String] Classi del campo
|
|
19
|
-
# @param html_options [Hash] Opzioni HTML del campo
|
|
20
|
-
def initialize(name:, options:, selected: nil, required: false, disabled: false, multiple: false, options_html: {}, classes: '', **html_options)
|
|
21
|
-
@name = name
|
|
22
|
-
@type = :select
|
|
23
|
-
@required = required
|
|
24
|
-
@disabled = disabled
|
|
25
|
-
@options = options.map { |option| { value: option[:value], label: option[:label] } }
|
|
26
|
-
@selected = selected
|
|
27
|
-
@multiple = multiple
|
|
28
|
-
@options_html = options_html
|
|
29
|
-
@classes = BASE_SELECT_CLASSES + classes
|
|
30
|
-
|
|
31
|
-
puts "Optionssssssssssssssssssssssss: #{selected}"
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module BetterUi
|
|
4
|
-
module General
|
|
5
|
-
module Input
|
|
6
|
-
module Text
|
|
7
|
-
class Component < ViewComponent::Base
|
|
8
|
-
attr_reader :name, :value, :placeholder, :required, :disabled, :classes, :options,
|
|
9
|
-
:theme, :size, :rounded, :form, :type
|
|
10
|
-
|
|
11
|
-
# Temi supportati per il Text Input
|
|
12
|
-
TEXT_INPUT_THEME = {
|
|
13
|
-
default: 'border-gray-300 focus:border-blue-500 focus:ring-blue-500',
|
|
14
|
-
white: 'border-white focus:border-gray-300 focus:ring-gray-300 bg-white',
|
|
15
|
-
red: 'border-red-300 focus:border-red-500 focus:ring-red-500',
|
|
16
|
-
rose: 'border-rose-300 focus:border-rose-500 focus:ring-rose-500',
|
|
17
|
-
orange: 'border-orange-300 focus:border-orange-500 focus:ring-orange-500',
|
|
18
|
-
green: 'border-green-300 focus:border-green-500 focus:ring-green-500',
|
|
19
|
-
blue: 'border-blue-300 focus:border-blue-500 focus:ring-blue-500',
|
|
20
|
-
yellow: 'border-yellow-300 focus:border-yellow-500 focus:ring-yellow-500',
|
|
21
|
-
violet: 'border-violet-300 focus:border-violet-500 focus:ring-violet-500'
|
|
22
|
-
}.freeze
|
|
23
|
-
|
|
24
|
-
# Dimensioni supportate per il Text Input
|
|
25
|
-
TEXT_INPUT_SIZES = {
|
|
26
|
-
small: 'h-8 px-2 py-1 text-xs',
|
|
27
|
-
medium: 'h-10 px-3 py-2 text-sm',
|
|
28
|
-
large: 'h-12 px-4 py-3 text-base'
|
|
29
|
-
}.freeze
|
|
30
|
-
|
|
31
|
-
# Border radius supportati per il Text Input
|
|
32
|
-
TEXT_INPUT_RADIUS = {
|
|
33
|
-
none: 'rounded-none',
|
|
34
|
-
small: 'rounded-sm',
|
|
35
|
-
medium: 'rounded-md',
|
|
36
|
-
large: 'rounded-lg',
|
|
37
|
-
full: 'rounded-full'
|
|
38
|
-
}.freeze
|
|
39
|
-
|
|
40
|
-
# Tipi supportati per il Text Input
|
|
41
|
-
TEXT_INPUT_TYPES = [
|
|
42
|
-
:text, :password, :email, :tel, :url, :number, :search,
|
|
43
|
-
:date, :time, :datetime_local, :month, :week, :color
|
|
44
|
-
].freeze
|
|
45
|
-
|
|
46
|
-
# Classi base per il Text Input
|
|
47
|
-
TEXT_INPUT_BASE_CLASSES = 'block w-full border shadow-sm disabled:bg-gray-100 disabled:cursor-not-allowed focus:outline-none focus:ring-1'
|
|
48
|
-
|
|
49
|
-
# @param name [String] Nome del campo input
|
|
50
|
-
# @param value [String] Valore del campo
|
|
51
|
-
# @param placeholder [String] Placeholder del campo
|
|
52
|
-
# @param required [Boolean] Se il campo è obbligatorio
|
|
53
|
-
# @param disabled [Boolean] Se il campo è disabilitato
|
|
54
|
-
# @param type [Symbol] Tipo del campo input (:text, :password, :email, :tel, :url, :number, :search, :date, :time, :datetime_local, :month, :week, :color)
|
|
55
|
-
# @param theme [Symbol] Tema del componente (:default, :white, :red, :rose, :orange, :green, :blue, :yellow, :violet)
|
|
56
|
-
# @param size [Symbol] Dimensione del componente (:small, :medium, :large)
|
|
57
|
-
# @param rounded [Symbol] Border radius (:none, :small, :medium, :large, :full)
|
|
58
|
-
# @param classes [String] Classi CSS aggiuntive
|
|
59
|
-
# @param form [ActionView::Helpers::FormBuilder] Form builder Rails opzionale
|
|
60
|
-
# @param options [Hash] Opzioni aggiuntive per l'input
|
|
61
|
-
def initialize(name:, value: nil, placeholder: nil, required: false, disabled: false,
|
|
62
|
-
type: :text, theme: :default, size: :medium, rounded: :medium, classes: '', form: nil, **options)
|
|
63
|
-
@name = name
|
|
64
|
-
@value = value
|
|
65
|
-
@placeholder = placeholder
|
|
66
|
-
@required = required
|
|
67
|
-
@disabled = disabled
|
|
68
|
-
@type = type
|
|
69
|
-
@theme = theme
|
|
70
|
-
@size = size
|
|
71
|
-
@rounded = rounded
|
|
72
|
-
@classes = classes
|
|
73
|
-
@form = form
|
|
74
|
-
@options = options
|
|
75
|
-
|
|
76
|
-
validate_params
|
|
77
|
-
super()
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
# Attributi per l'elemento input standalone
|
|
81
|
-
def input_attributes
|
|
82
|
-
{
|
|
83
|
-
type: @type,
|
|
84
|
-
name: @name,
|
|
85
|
-
id: @name,
|
|
86
|
-
value: @value,
|
|
87
|
-
placeholder: @placeholder,
|
|
88
|
-
required: @required,
|
|
89
|
-
disabled: @disabled,
|
|
90
|
-
class: build_classes
|
|
91
|
-
}.merge(@options)
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
# Attributi per l'elemento input con form builder
|
|
95
|
-
def form_input_attributes
|
|
96
|
-
{
|
|
97
|
-
class: build_classes,
|
|
98
|
-
placeholder: @placeholder,
|
|
99
|
-
required: @required,
|
|
100
|
-
disabled: @disabled
|
|
101
|
-
}.merge(@options)
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
private
|
|
105
|
-
|
|
106
|
-
# Costruisce le classi CSS complete
|
|
107
|
-
def build_classes
|
|
108
|
-
[
|
|
109
|
-
TEXT_INPUT_BASE_CLASSES,
|
|
110
|
-
get_theme_classes,
|
|
111
|
-
get_size_classes,
|
|
112
|
-
get_rounded_classes,
|
|
113
|
-
@classes
|
|
114
|
-
].compact.join(' ')
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
# Restituisce le classi del tema
|
|
118
|
-
def get_theme_classes
|
|
119
|
-
TEXT_INPUT_THEME[@theme]
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
# Restituisce le classi della dimensione
|
|
123
|
-
def get_size_classes
|
|
124
|
-
TEXT_INPUT_SIZES[@size]
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
# Restituisce le classi del border radius
|
|
128
|
-
def get_rounded_classes
|
|
129
|
-
TEXT_INPUT_RADIUS[@rounded]
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
# Valida i parametri del componente
|
|
133
|
-
def validate_params
|
|
134
|
-
validate_type
|
|
135
|
-
validate_theme
|
|
136
|
-
validate_size
|
|
137
|
-
validate_rounded
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
# Valida il tema
|
|
141
|
-
def validate_theme
|
|
142
|
-
return if TEXT_INPUT_THEME.key?(@theme)
|
|
143
|
-
|
|
144
|
-
raise ArgumentError, "Tema non valido: #{@theme}. Temi supportati: #{TEXT_INPUT_THEME.keys.join(', ')}"
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
# Valida la dimensione
|
|
148
|
-
def validate_size
|
|
149
|
-
return if TEXT_INPUT_SIZES.key?(@size)
|
|
150
|
-
|
|
151
|
-
raise ArgumentError, "Dimensione non valida: #{@size}. Dimensioni supportate: #{TEXT_INPUT_SIZES.keys.join(', ')}"
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
# Valida il border radius
|
|
155
|
-
def validate_rounded
|
|
156
|
-
return if TEXT_INPUT_RADIUS.key?(@rounded)
|
|
157
|
-
|
|
158
|
-
raise ArgumentError, "Border radius non valido: #{@rounded}. Valori supportati: #{TEXT_INPUT_RADIUS.keys.join(', ')}"
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
# Valida il tipo
|
|
162
|
-
def validate_type
|
|
163
|
-
return if TEXT_INPUT_TYPES.include?(@type)
|
|
164
|
-
|
|
165
|
-
raise ArgumentError, "Tipo non valido: #{@type}. Tipi supportati: #{TEXT_INPUT_TYPES.join(', ')}"
|
|
166
|
-
end
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
end
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module BetterUi
|
|
4
|
-
module General
|
|
5
|
-
module Input
|
|
6
|
-
module Textarea
|
|
7
|
-
class Component < ViewComponent::Base
|
|
8
|
-
attr_reader :name, :value, :placeholder, :required, :disabled, :classes, :options,
|
|
9
|
-
:theme, :size, :rounded, :form, :rows
|
|
10
|
-
|
|
11
|
-
# Temi supportati per il Textarea
|
|
12
|
-
TEXTAREA_THEME = {
|
|
13
|
-
default: 'border-gray-300 focus:border-blue-500 focus:ring-blue-500',
|
|
14
|
-
white: 'border-white focus:border-gray-300 focus:ring-gray-300 bg-white',
|
|
15
|
-
red: 'border-red-300 focus:border-red-500 focus:ring-red-500',
|
|
16
|
-
rose: 'border-rose-300 focus:border-rose-500 focus:ring-rose-500',
|
|
17
|
-
orange: 'border-orange-300 focus:border-orange-500 focus:ring-orange-500',
|
|
18
|
-
green: 'border-green-300 focus:border-green-500 focus:ring-green-500',
|
|
19
|
-
blue: 'border-blue-300 focus:border-blue-500 focus:ring-blue-500',
|
|
20
|
-
yellow: 'border-yellow-300 focus:border-yellow-500 focus:ring-yellow-500',
|
|
21
|
-
violet: 'border-violet-300 focus:border-violet-500 focus:ring-violet-500'
|
|
22
|
-
}.freeze
|
|
23
|
-
|
|
24
|
-
# Dimensioni supportate per il Textarea
|
|
25
|
-
TEXTAREA_SIZES = {
|
|
26
|
-
small: 'px-2 py-1 text-xs',
|
|
27
|
-
medium: 'px-3 py-2 text-sm',
|
|
28
|
-
large: 'px-4 py-3 text-base'
|
|
29
|
-
}.freeze
|
|
30
|
-
|
|
31
|
-
# Border radius supportati per il Textarea
|
|
32
|
-
TEXTAREA_RADIUS = {
|
|
33
|
-
none: 'rounded-none',
|
|
34
|
-
small: 'rounded-sm',
|
|
35
|
-
medium: 'rounded-md',
|
|
36
|
-
large: 'rounded-lg',
|
|
37
|
-
full: 'rounded-2xl'
|
|
38
|
-
}.freeze
|
|
39
|
-
|
|
40
|
-
# Classi base per il Textarea
|
|
41
|
-
TEXTAREA_BASE_CLASSES = 'block w-full border shadow-sm disabled:bg-gray-100 disabled:cursor-not-allowed focus:outline-none focus:ring-1 resize-y'
|
|
42
|
-
|
|
43
|
-
# @param name [String] Nome del campo textarea
|
|
44
|
-
# @param value [String] Valore del campo
|
|
45
|
-
# @param placeholder [String] Placeholder del campo
|
|
46
|
-
# @param required [Boolean] Se il campo è obbligatorio
|
|
47
|
-
# @param disabled [Boolean] Se il campo è disabilitato
|
|
48
|
-
# @param rows [Integer] Numero di righe per la textarea
|
|
49
|
-
# @param theme [Symbol] Tema del componente (:default, :white, :red, :rose, :orange, :green, :blue, :yellow, :violet)
|
|
50
|
-
# @param size [Symbol] Dimensione del componente (:small, :medium, :large)
|
|
51
|
-
# @param rounded [Symbol] Border radius (:none, :small, :medium, :large, :full)
|
|
52
|
-
# @param classes [String] Classi CSS aggiuntive
|
|
53
|
-
# @param form [ActionView::Helpers::FormBuilder] Form builder Rails opzionale
|
|
54
|
-
# @param options [Hash] Opzioni aggiuntive per la textarea
|
|
55
|
-
def initialize(name:, value: nil, placeholder: nil, required: false, disabled: false,
|
|
56
|
-
rows: 3, theme: :default, size: :medium, rounded: :medium, classes: '', form: nil, **options)
|
|
57
|
-
@name = name
|
|
58
|
-
@value = value
|
|
59
|
-
@placeholder = placeholder
|
|
60
|
-
@required = required
|
|
61
|
-
@disabled = disabled
|
|
62
|
-
@rows = rows
|
|
63
|
-
@theme = theme
|
|
64
|
-
@size = size
|
|
65
|
-
@rounded = rounded
|
|
66
|
-
@classes = classes
|
|
67
|
-
@form = form
|
|
68
|
-
@options = options
|
|
69
|
-
|
|
70
|
-
validate_params
|
|
71
|
-
super()
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# Attributi per l'elemento textarea standalone
|
|
75
|
-
def textarea_attributes
|
|
76
|
-
{
|
|
77
|
-
name: @name,
|
|
78
|
-
id: @name,
|
|
79
|
-
value: @value,
|
|
80
|
-
placeholder: @placeholder,
|
|
81
|
-
required: @required,
|
|
82
|
-
disabled: @disabled,
|
|
83
|
-
rows: @rows,
|
|
84
|
-
class: build_classes
|
|
85
|
-
}.merge(@options)
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
# Attributi per l'elemento textarea con form builder
|
|
89
|
-
def form_textarea_attributes
|
|
90
|
-
{
|
|
91
|
-
class: build_classes,
|
|
92
|
-
placeholder: @placeholder,
|
|
93
|
-
required: @required,
|
|
94
|
-
disabled: @disabled,
|
|
95
|
-
rows: @rows
|
|
96
|
-
}.merge(@options)
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
private
|
|
100
|
-
|
|
101
|
-
# Costruisce le classi CSS complete
|
|
102
|
-
def build_classes
|
|
103
|
-
[
|
|
104
|
-
TEXTAREA_BASE_CLASSES,
|
|
105
|
-
get_theme_classes,
|
|
106
|
-
get_size_classes,
|
|
107
|
-
get_rounded_classes,
|
|
108
|
-
@classes
|
|
109
|
-
].compact.join(' ')
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
# Restituisce le classi del tema
|
|
113
|
-
def get_theme_classes
|
|
114
|
-
TEXTAREA_THEME[@theme]
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
# Restituisce le classi della dimensione
|
|
118
|
-
def get_size_classes
|
|
119
|
-
TEXTAREA_SIZES[@size]
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
# Restituisce le classi del border radius
|
|
123
|
-
def get_rounded_classes
|
|
124
|
-
TEXTAREA_RADIUS[@rounded]
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
# Valida i parametri del componente
|
|
128
|
-
def validate_params
|
|
129
|
-
validate_theme
|
|
130
|
-
validate_size
|
|
131
|
-
validate_rounded
|
|
132
|
-
validate_rows
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
# Valida il tema
|
|
136
|
-
def validate_theme
|
|
137
|
-
return if TEXTAREA_THEME.key?(@theme)
|
|
138
|
-
|
|
139
|
-
raise ArgumentError, "Tema non valido: #{@theme}. Temi supportati: #{TEXTAREA_THEME.keys.join(', ')}"
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
# Valida la dimensione
|
|
143
|
-
def validate_size
|
|
144
|
-
return if TEXTAREA_SIZES.key?(@size)
|
|
145
|
-
|
|
146
|
-
raise ArgumentError, "Dimensione non valida: #{@size}. Dimensioni supportate: #{TEXTAREA_SIZES.keys.join(', ')}"
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
# Valida il border radius
|
|
150
|
-
def validate_rounded
|
|
151
|
-
return if TEXTAREA_RADIUS.key?(@rounded)
|
|
152
|
-
|
|
153
|
-
raise ArgumentError, "Border radius non valido: #{@rounded}. Valori supportati: #{TEXTAREA_RADIUS.keys.join(', ')}"
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
# Valida il numero di righe
|
|
157
|
-
def validate_rows
|
|
158
|
-
return if @rows.is_a?(Integer) && @rows.positive?
|
|
159
|
-
|
|
160
|
-
raise ArgumentError, "Il numero di righe deve essere un intero positivo: #{@rows}"
|
|
161
|
-
end
|
|
162
|
-
end
|
|
163
|
-
end
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
|
-
end
|