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.
Files changed (198) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +257 -212
  3. data/Rakefile +11 -2
  4. data/app/components/better_ui/action_messages_component/action_messages_component.html.erb +48 -0
  5. data/app/components/better_ui/action_messages_component.rb +544 -0
  6. data/app/components/better_ui/application_component.rb +66 -0
  7. data/app/components/better_ui/button_component/button_component.html.erb +31 -0
  8. data/app/components/better_ui/button_component.rb +307 -0
  9. data/app/components/better_ui/card_component/card_component.html.erb +17 -0
  10. data/app/components/better_ui/card_component.rb +460 -0
  11. data/app/components/better_ui/drawer/header_component/header_component.html.erb +24 -0
  12. data/app/components/better_ui/drawer/header_component.rb +238 -0
  13. data/app/components/better_ui/drawer/layout_component/layout_component.html.erb +44 -0
  14. data/app/components/better_ui/drawer/layout_component.rb +270 -0
  15. data/app/components/better_ui/drawer/nav_group_component/nav_group_component.html.erb +10 -0
  16. data/app/components/better_ui/drawer/nav_group_component.rb +155 -0
  17. data/app/components/better_ui/drawer/nav_item_component/nav_item_component.html.erb +13 -0
  18. data/app/components/better_ui/drawer/nav_item_component.rb +225 -0
  19. data/app/components/better_ui/drawer/sidebar_component/sidebar_component.html.erb +17 -0
  20. data/app/components/better_ui/drawer/sidebar_component.rb +263 -0
  21. data/app/components/better_ui/forms/base_component.rb +450 -0
  22. data/app/components/better_ui/forms/checkbox_component/checkbox_component.html.erb +28 -0
  23. data/app/components/better_ui/forms/checkbox_component.rb +419 -0
  24. data/app/components/better_ui/forms/checkbox_group_component/checkbox_group_component.html.erb +40 -0
  25. data/app/components/better_ui/forms/checkbox_group_component.rb +363 -0
  26. data/app/components/better_ui/forms/number_input_component/number_input_component.html.erb +40 -0
  27. data/app/components/better_ui/forms/number_input_component.rb +320 -0
  28. data/app/components/better_ui/forms/password_input_component/password_input_component.html.erb +71 -0
  29. data/app/components/better_ui/forms/password_input_component.rb +206 -0
  30. data/app/components/better_ui/forms/text_input_component/text_input_component.html.erb +40 -0
  31. data/app/components/better_ui/forms/text_input_component.rb +258 -0
  32. data/app/components/better_ui/forms/textarea_component/textarea_component.html.erb +40 -0
  33. data/app/components/better_ui/forms/textarea_component.rb +329 -0
  34. data/app/form_builders/better_ui/ui_form_builder.rb +467 -0
  35. data/app/helpers/better_ui/application_helper.rb +325 -58
  36. data/app/views/layouts/better_ui/application.html.erb +1 -1
  37. data/config/routes.rb +1 -0
  38. data/lib/better_ui/engine.rb +34 -5
  39. data/lib/better_ui/version.rb +1 -1
  40. data/lib/better_ui.rb +32 -5
  41. data/lib/generators/better_ui/install/USAGE +44 -0
  42. data/lib/generators/better_ui/install/install_generator.rb +87 -0
  43. data/lib/generators/better_ui/install/templates/better_ui_theme.css.tt +280 -0
  44. data/lib/tasks/better_ui_tasks.rake +39 -4
  45. metadata +52 -200
  46. data/app/components/better_ui/application/card/component.html.erb +0 -20
  47. data/app/components/better_ui/application/card/component.rb +0 -214
  48. data/app/components/better_ui/application/main/component.html.erb +0 -9
  49. data/app/components/better_ui/application/main/component.rb +0 -123
  50. data/app/components/better_ui/application/navbar/component.html.erb +0 -92
  51. data/app/components/better_ui/application/navbar/component.rb +0 -136
  52. data/app/components/better_ui/application/sidebar/component.html.erb +0 -249
  53. data/app/components/better_ui/application/sidebar/component.rb +0 -187
  54. data/app/components/better_ui/general/accordion/component.html.erb +0 -5
  55. data/app/components/better_ui/general/accordion/component.rb +0 -92
  56. data/app/components/better_ui/general/accordion/item_component.html.erb +0 -12
  57. data/app/components/better_ui/general/accordion/item_component.rb +0 -176
  58. data/app/components/better_ui/general/alert/component.html.erb +0 -32
  59. data/app/components/better_ui/general/alert/component.rb +0 -242
  60. data/app/components/better_ui/general/avatar/component.html.erb +0 -20
  61. data/app/components/better_ui/general/avatar/component.rb +0 -301
  62. data/app/components/better_ui/general/badge/component.html.erb +0 -23
  63. data/app/components/better_ui/general/badge/component.rb +0 -248
  64. data/app/components/better_ui/general/breadcrumb/component.html.erb +0 -15
  65. data/app/components/better_ui/general/breadcrumb/component.rb +0 -187
  66. data/app/components/better_ui/general/button/component.html.erb +0 -34
  67. data/app/components/better_ui/general/button/component.rb +0 -214
  68. data/app/components/better_ui/general/divider/component.html.erb +0 -10
  69. data/app/components/better_ui/general/divider/component.rb +0 -226
  70. data/app/components/better_ui/general/dropdown/component.html.erb +0 -28
  71. data/app/components/better_ui/general/dropdown/component.rb +0 -192
  72. data/app/components/better_ui/general/dropdown/divider_component.html.erb +0 -1
  73. data/app/components/better_ui/general/dropdown/divider_component.rb +0 -41
  74. data/app/components/better_ui/general/dropdown/item_component.html.erb +0 -6
  75. data/app/components/better_ui/general/dropdown/item_component.rb +0 -119
  76. data/app/components/better_ui/general/field/component.html.erb +0 -27
  77. data/app/components/better_ui/general/field/component.rb +0 -37
  78. data/app/components/better_ui/general/grid/cell_component.html.erb +0 -3
  79. data/app/components/better_ui/general/grid/cell_component.rb +0 -390
  80. data/app/components/better_ui/general/grid/component.html.erb +0 -3
  81. data/app/components/better_ui/general/grid/component.rb +0 -301
  82. data/app/components/better_ui/general/heading/component.html.erb +0 -22
  83. data/app/components/better_ui/general/heading/component.rb +0 -257
  84. data/app/components/better_ui/general/icon/component.html.erb +0 -7
  85. data/app/components/better_ui/general/icon/component.rb +0 -240
  86. data/app/components/better_ui/general/input/checkbox/component.html.erb +0 -5
  87. data/app/components/better_ui/general/input/checkbox/component.rb +0 -238
  88. data/app/components/better_ui/general/input/datetime/component.html.erb +0 -5
  89. data/app/components/better_ui/general/input/datetime/component.rb +0 -223
  90. data/app/components/better_ui/general/input/pin/component.html.erb +0 -1
  91. data/app/components/better_ui/general/input/pin/component.rb +0 -201
  92. data/app/components/better_ui/general/input/radio/component.html.erb +0 -5
  93. data/app/components/better_ui/general/input/radio/component.rb +0 -230
  94. data/app/components/better_ui/general/input/rating/component.html.erb +0 -4
  95. data/app/components/better_ui/general/input/rating/component.rb +0 -272
  96. data/app/components/better_ui/general/input/select/component.html.erb +0 -78
  97. data/app/components/better_ui/general/input/select/component.rb +0 -249
  98. data/app/components/better_ui/general/input/select/select_component.html.erb +0 -5
  99. data/app/components/better_ui/general/input/select/select_component.rb +0 -37
  100. data/app/components/better_ui/general/input/text/component.html.erb +0 -5
  101. data/app/components/better_ui/general/input/text/component.rb +0 -171
  102. data/app/components/better_ui/general/input/textarea/component.html.erb +0 -5
  103. data/app/components/better_ui/general/input/textarea/component.rb +0 -166
  104. data/app/components/better_ui/general/input/toggle/component.html.erb +0 -5
  105. data/app/components/better_ui/general/input/toggle/component.rb +0 -242
  106. data/app/components/better_ui/general/link/component.html.erb +0 -18
  107. data/app/components/better_ui/general/link/component.rb +0 -258
  108. data/app/components/better_ui/general/modal/component.html.erb +0 -5
  109. data/app/components/better_ui/general/modal/component.rb +0 -47
  110. data/app/components/better_ui/general/modal/modal_component.html.erb +0 -52
  111. data/app/components/better_ui/general/modal/modal_component.rb +0 -160
  112. data/app/components/better_ui/general/pagination/component.html.erb +0 -85
  113. data/app/components/better_ui/general/pagination/component.rb +0 -216
  114. data/app/components/better_ui/general/panel/component.html.erb +0 -28
  115. data/app/components/better_ui/general/panel/component.rb +0 -249
  116. data/app/components/better_ui/general/progress/component.html.erb +0 -11
  117. data/app/components/better_ui/general/progress/component.rb +0 -160
  118. data/app/components/better_ui/general/spinner/component.html.erb +0 -35
  119. data/app/components/better_ui/general/spinner/component.rb +0 -93
  120. data/app/components/better_ui/general/table/component.html.erb +0 -5
  121. data/app/components/better_ui/general/table/component.rb +0 -217
  122. data/app/components/better_ui/general/table/tbody_component.html.erb +0 -3
  123. data/app/components/better_ui/general/table/tbody_component.rb +0 -30
  124. data/app/components/better_ui/general/table/td_component.html.erb +0 -3
  125. data/app/components/better_ui/general/table/td_component.rb +0 -44
  126. data/app/components/better_ui/general/table/tfoot_component.html.erb +0 -3
  127. data/app/components/better_ui/general/table/tfoot_component.rb +0 -28
  128. data/app/components/better_ui/general/table/th_component.html.erb +0 -6
  129. data/app/components/better_ui/general/table/th_component.rb +0 -51
  130. data/app/components/better_ui/general/table/thead_component.html.erb +0 -3
  131. data/app/components/better_ui/general/table/thead_component.rb +0 -28
  132. data/app/components/better_ui/general/table/tr_component.html.erb +0 -3
  133. data/app/components/better_ui/general/table/tr_component.rb +0 -30
  134. data/app/components/better_ui/general/tabs/component.html.erb +0 -11
  135. data/app/components/better_ui/general/tabs/component.rb +0 -120
  136. data/app/components/better_ui/general/tabs/panel_component.html.erb +0 -3
  137. data/app/components/better_ui/general/tabs/panel_component.rb +0 -37
  138. data/app/components/better_ui/general/tabs/tab_component.html.erb +0 -13
  139. data/app/components/better_ui/general/tabs/tab_component.rb +0 -111
  140. data/app/components/better_ui/general/tag/component.html.erb +0 -3
  141. data/app/components/better_ui/general/tag/component.rb +0 -104
  142. data/app/components/better_ui/general/text/component.html.erb +0 -1
  143. data/app/components/better_ui/general/text/component.rb +0 -194
  144. data/app/components/better_ui/general/tooltip/component.html.erb +0 -7
  145. data/app/components/better_ui/general/tooltip/component.rb +0 -239
  146. data/app/helpers/better_ui/application/components/card/card_helper.rb +0 -96
  147. data/app/helpers/better_ui/application/components/card.rb +0 -11
  148. data/app/helpers/better_ui/application/components/main/main_helper.rb +0 -64
  149. data/app/helpers/better_ui/application/components/navbar/navbar_helper.rb +0 -77
  150. data/app/helpers/better_ui/application/components/sidebar/sidebar_helper.rb +0 -51
  151. data/app/helpers/better_ui/general/components/accordion/accordion_helper.rb +0 -73
  152. data/app/helpers/better_ui/general/components/alert/alert_helper.rb +0 -57
  153. data/app/helpers/better_ui/general/components/avatar/avatar_helper.rb +0 -29
  154. data/app/helpers/better_ui/general/components/badge/badge_helper.rb +0 -53
  155. data/app/helpers/better_ui/general/components/breadcrumb/breadcrumb_helper.rb +0 -37
  156. data/app/helpers/better_ui/general/components/button/button_helper.rb +0 -65
  157. data/app/helpers/better_ui/general/components/container/container_helper.rb +0 -60
  158. data/app/helpers/better_ui/general/components/divider/divider_helper.rb +0 -63
  159. data/app/helpers/better_ui/general/components/dropdown/divider_helper.rb +0 -32
  160. data/app/helpers/better_ui/general/components/dropdown/dropdown_helper.rb +0 -88
  161. data/app/helpers/better_ui/general/components/dropdown/item_helper.rb +0 -68
  162. data/app/helpers/better_ui/general/components/field/field_helper.rb +0 -26
  163. data/app/helpers/better_ui/general/components/grid/grid_helper.rb +0 -145
  164. data/app/helpers/better_ui/general/components/heading/heading_helper.rb +0 -72
  165. data/app/helpers/better_ui/general/components/icon/icon_helper.rb +0 -16
  166. data/app/helpers/better_ui/general/components/input/checkbox/checkbox_helper.rb +0 -81
  167. data/app/helpers/better_ui/general/components/input/datetime/datetime_helper.rb +0 -91
  168. data/app/helpers/better_ui/general/components/input/pin/pin_helper.rb +0 -76
  169. data/app/helpers/better_ui/general/components/input/radio/radio_helper.rb +0 -79
  170. data/app/helpers/better_ui/general/components/input/radio_group/radio_group_helper.rb +0 -124
  171. data/app/helpers/better_ui/general/components/input/rating/rating_helper.rb +0 -70
  172. data/app/helpers/better_ui/general/components/input/select/select_helper.rb +0 -86
  173. data/app/helpers/better_ui/general/components/input/text/text_helper.rb +0 -138
  174. data/app/helpers/better_ui/general/components/input/textarea/textarea_helper.rb +0 -73
  175. data/app/helpers/better_ui/general/components/input/toggle/toggle_helper.rb +0 -77
  176. data/app/helpers/better_ui/general/components/link/link_helper.rb +0 -89
  177. data/app/helpers/better_ui/general/components/modal/modal_helper.rb +0 -85
  178. data/app/helpers/better_ui/general/components/pagination/pagination_helper.rb +0 -82
  179. data/app/helpers/better_ui/general/components/panel/panel_helper.rb +0 -83
  180. data/app/helpers/better_ui/general/components/progress/progress_helper.rb +0 -53
  181. data/app/helpers/better_ui/general/components/spinner/spinner_helper.rb +0 -19
  182. data/app/helpers/better_ui/general/components/table/table_helper.rb +0 -53
  183. data/app/helpers/better_ui/general/components/table/tbody_helper.rb +0 -13
  184. data/app/helpers/better_ui/general/components/table/td_helper.rb +0 -19
  185. data/app/helpers/better_ui/general/components/table/tfoot_helper.rb +0 -13
  186. data/app/helpers/better_ui/general/components/table/th_helper.rb +0 -19
  187. data/app/helpers/better_ui/general/components/table/thead_helper.rb +0 -13
  188. data/app/helpers/better_ui/general/components/table/tr_helper.rb +0 -13
  189. data/app/helpers/better_ui/general/components/tabs/panel_helper.rb +0 -62
  190. data/app/helpers/better_ui/general/components/tabs/tab_helper.rb +0 -55
  191. data/app/helpers/better_ui/general/components/tabs/tabs_helper.rb +0 -95
  192. data/app/helpers/better_ui/general/components/tag/tag_helper.rb +0 -26
  193. data/app/helpers/better_ui/general/components/text/text_helper.rb +0 -83
  194. data/app/helpers/better_ui/general/components/tooltip/tooltip_helper.rb +0 -60
  195. data/app/jobs/better_ui/application_job.rb +0 -4
  196. data/app/mailers/better_ui/application_mailer.rb +0 -6
  197. data/config/initializers/lookbook.rb +0 -23
  198. 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,5 +0,0 @@
1
- <% if @form %>
2
- <%= @form.text_field(@name, **form_input_attributes) %>
3
- <% else %>
4
- <%= tag.input(**input_attributes) %>
5
- <% 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,5 +0,0 @@
1
- <% if @form %>
2
- <%= @form.text_area(@name, **form_textarea_attributes) %>
3
- <% else %>
4
- <%= tag.textarea(**textarea_attributes) %>
5
- <% 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
@@ -1,5 +0,0 @@
1
- <% if @label %>
2
- <%= render_toggle_with_label %>
3
- <% else %>
4
- <%= render_toggle_switch %>
5
- <% end %>