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,16 @@
|
|
1
|
+
<select <%= tag.attributes(select_attributes).html_safe %>>
|
2
|
+
<% if @placeholder.present? && !@multiple %>
|
3
|
+
<option value="" disabled <%= "selected" if @selected.nil? %>><%= @placeholder %></option>
|
4
|
+
<% end %>
|
5
|
+
<% @options.each do |option| %>
|
6
|
+
<option
|
7
|
+
value="<%= option[:value] %>"
|
8
|
+
<%= "selected" if selected?(option) %>
|
9
|
+
<%= "disabled" if option[:disabled] %>
|
10
|
+
<%= option[:html]&.map { |k, v| "#{k}=\"#{v}\"" }&.join(' ').to_s.html_safe %>
|
11
|
+
>
|
12
|
+
<%= option[:label] %>
|
13
|
+
</option>
|
14
|
+
<% end %>
|
15
|
+
<%= content %>
|
16
|
+
</select>
|
@@ -0,0 +1,184 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BetterUi
|
4
|
+
module General
|
5
|
+
module Input
|
6
|
+
module Select
|
7
|
+
class Component < ViewComponent::Base
|
8
|
+
attr_reader :name, :options, :selected, :required, :disabled, :multiple,
|
9
|
+
:theme, :size, :rounded, :placeholder, :form, :options_html,
|
10
|
+
:classes, :html_options
|
11
|
+
|
12
|
+
# Classi base sempre presenti
|
13
|
+
SELECT_BASE_CLASSES = "block w-full border shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-0"
|
14
|
+
|
15
|
+
# Temi di select con classi Tailwind
|
16
|
+
SELECT_THEME = {
|
17
|
+
default: "bg-white border-gray-300 focus:border-blue-500 focus:ring-blue-500",
|
18
|
+
white: "bg-white border-gray-300 focus:border-blue-500 focus:ring-blue-500",
|
19
|
+
red: "bg-white border-red-300 focus:border-red-500 focus:ring-red-500",
|
20
|
+
rose: "bg-white border-rose-300 focus:border-rose-500 focus:ring-rose-500",
|
21
|
+
orange: "bg-white border-orange-300 focus:border-orange-500 focus:ring-orange-500",
|
22
|
+
green: "bg-white border-green-300 focus:border-green-500 focus:ring-green-500",
|
23
|
+
blue: "bg-white border-blue-300 focus:border-blue-500 focus:ring-blue-500",
|
24
|
+
yellow: "bg-white border-yellow-300 focus:border-yellow-500 focus:ring-yellow-500",
|
25
|
+
violet: "bg-white border-violet-300 focus:border-violet-500 focus:ring-violet-500"
|
26
|
+
}.freeze
|
27
|
+
|
28
|
+
# Dimensioni con classi Tailwind
|
29
|
+
SELECT_SIZE = {
|
30
|
+
small: "px-2 py-1.5 text-xs",
|
31
|
+
medium: "px-3 py-2 text-sm",
|
32
|
+
large: "px-4 py-3 text-base"
|
33
|
+
}.freeze
|
34
|
+
|
35
|
+
# Border radius con classi Tailwind
|
36
|
+
SELECT_ROUNDED = {
|
37
|
+
none: "rounded-none",
|
38
|
+
small: "rounded-sm",
|
39
|
+
medium: "rounded-md",
|
40
|
+
large: "rounded-lg",
|
41
|
+
full: "rounded-full"
|
42
|
+
}.freeze
|
43
|
+
|
44
|
+
# Stati del select
|
45
|
+
SELECT_STATE = {
|
46
|
+
disabled: "bg-gray-100 cursor-not-allowed opacity-75"
|
47
|
+
}.freeze
|
48
|
+
|
49
|
+
# @param name [String] Name of the select field (required)
|
50
|
+
# @param options [Array<Hash>] Array of options for the select in format [{value: 'value', label: 'label'}, ...]
|
51
|
+
# @param selected [String, Array, nil] Selected value or values
|
52
|
+
# @param required [Boolean] Whether the field is required
|
53
|
+
# @param disabled [Boolean] Whether the field is disabled
|
54
|
+
# @param multiple [Boolean] Whether multiple options can be selected
|
55
|
+
# @param theme [Symbol] Component theme (:default, :white, :red, :rose, :orange, :green, :blue, :yellow, :violet)
|
56
|
+
# @param size [Symbol] Component size (:small, :medium, :large)
|
57
|
+
# @param rounded [Symbol] Border radius (:none, :small, :medium, :large, :full)
|
58
|
+
# @param placeholder [String, nil] Placeholder text for the field (creates an initial disabled option)
|
59
|
+
# @param form [ActionView::Helpers::FormBuilder, nil] Optional Rails form builder
|
60
|
+
# @param options_html [Hash] Additional HTML attributes for option tags
|
61
|
+
# @param classes [String] Additional CSS classes
|
62
|
+
# @param html_options [Hash] Additional HTML attributes for the select tag
|
63
|
+
def initialize(
|
64
|
+
name:,
|
65
|
+
options:,
|
66
|
+
selected: nil,
|
67
|
+
required: false,
|
68
|
+
disabled: false,
|
69
|
+
multiple: false,
|
70
|
+
theme: :default,
|
71
|
+
size: :medium,
|
72
|
+
rounded: :medium,
|
73
|
+
placeholder: nil,
|
74
|
+
form: nil,
|
75
|
+
options_html: {},
|
76
|
+
classes: '',
|
77
|
+
**html_options
|
78
|
+
)
|
79
|
+
@name = name
|
80
|
+
@options = options
|
81
|
+
@selected = selected
|
82
|
+
@required = required
|
83
|
+
@disabled = disabled
|
84
|
+
@multiple = multiple
|
85
|
+
@theme = theme.to_sym
|
86
|
+
@size = size.to_sym
|
87
|
+
@rounded = rounded.to_sym
|
88
|
+
@placeholder = placeholder
|
89
|
+
@form = form
|
90
|
+
@options_html = options_html
|
91
|
+
@classes = classes
|
92
|
+
@html_options = html_options
|
93
|
+
|
94
|
+
validate_params
|
95
|
+
end
|
96
|
+
|
97
|
+
def combined_classes
|
98
|
+
[
|
99
|
+
SELECT_BASE_CLASSES,
|
100
|
+
SELECT_THEME[@theme],
|
101
|
+
SELECT_SIZE[@size],
|
102
|
+
SELECT_ROUNDED[@rounded],
|
103
|
+
@disabled ? SELECT_STATE[:disabled] : nil,
|
104
|
+
@classes
|
105
|
+
].compact.join(' ')
|
106
|
+
end
|
107
|
+
|
108
|
+
def select_attributes
|
109
|
+
attrs = {
|
110
|
+
name: form_field_name,
|
111
|
+
id: @html_options[:id] || form_field_id,
|
112
|
+
class: combined_classes
|
113
|
+
}
|
114
|
+
|
115
|
+
# Aggiungi attributi booleani solo se true
|
116
|
+
attrs[:required] = @required if @required
|
117
|
+
attrs[:disabled] = @disabled if @disabled
|
118
|
+
attrs[:multiple] = @multiple if @multiple
|
119
|
+
|
120
|
+
# Aggiungi altri attributi HTML
|
121
|
+
@html_options.except(:id, :class).each do |key, value|
|
122
|
+
attrs[key] = value unless value.nil?
|
123
|
+
end
|
124
|
+
|
125
|
+
# Rimuovi attributi con valori nil o false
|
126
|
+
attrs.compact
|
127
|
+
end
|
128
|
+
|
129
|
+
def form_field_name
|
130
|
+
if @form.present?
|
131
|
+
@form.field_name(@name)
|
132
|
+
else
|
133
|
+
@name
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def form_field_id
|
138
|
+
if @form.present?
|
139
|
+
@form.field_id(@name)
|
140
|
+
else
|
141
|
+
@name.to_s.gsub(/[\[\]]+/, '_').gsub(/_$/, '')
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def selected?(option)
|
146
|
+
return false if @selected.nil?
|
147
|
+
|
148
|
+
if @selected.is_a?(Array)
|
149
|
+
@selected.include?(option[:value])
|
150
|
+
else
|
151
|
+
option[:value].to_s == @selected.to_s
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
private
|
156
|
+
|
157
|
+
def validate_params
|
158
|
+
validate_theme
|
159
|
+
validate_size
|
160
|
+
validate_rounded
|
161
|
+
end
|
162
|
+
|
163
|
+
def validate_theme
|
164
|
+
unless SELECT_THEME.keys.include?(@theme)
|
165
|
+
raise ArgumentError, "Invalid theme: #{@theme}. Valid themes are: #{SELECT_THEME.keys.join(', ')}"
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def validate_size
|
170
|
+
unless SELECT_SIZE.keys.include?(@size)
|
171
|
+
raise ArgumentError, "Invalid size: #{@size}. Valid sizes are: #{SELECT_SIZE.keys.join(', ')}"
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def validate_rounded
|
176
|
+
unless SELECT_ROUNDED.keys.include?(@rounded)
|
177
|
+
raise ArgumentError, "Invalid rounded: #{@rounded}. Valid rounded options are: #{SELECT_ROUNDED.keys.join(', ')}"
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,5 @@
|
|
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>
|
@@ -0,0 +1,37 @@
|
|
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
|
@@ -0,0 +1,171 @@
|
|
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
|
@@ -0,0 +1,166 @@
|
|
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
|
@@ -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 %>
|