loco_motion-rails 0.0.8 → 0.5.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 +62 -14
- data/app/components/daisy/actions/button_component.html.haml +2 -2
- data/app/components/daisy/actions/button_component.rb +98 -59
- data/app/components/daisy/actions/dropdown_component.html.haml +1 -2
- data/app/components/daisy/actions/dropdown_component.rb +7 -10
- data/app/components/daisy/actions/modal_component.html.haml +10 -8
- data/app/components/daisy/actions/modal_component.rb +6 -6
- data/app/components/daisy/actions/swap_component.rb +13 -9
- data/app/components/daisy/actions/theme_controller.js +113 -0
- data/app/components/daisy/actions/theme_controller_component.rb +58 -17
- data/app/components/daisy/actions/theme_preview_component.html.haml +5 -0
- data/app/components/daisy/actions/theme_preview_component.rb +68 -0
- data/app/components/daisy/data_display/accordion_component.html.haml +0 -1
- data/app/components/daisy/data_display/accordion_component.rb +10 -3
- data/app/components/daisy/data_display/avatar_component.html.haml +1 -1
- data/app/components/daisy/data_display/avatar_component.rb +17 -7
- data/app/components/daisy/data_display/badge_component.rb +122 -4
- data/app/components/daisy/data_display/card_component.html.haml +1 -1
- data/app/components/daisy/data_display/card_component.rb +20 -6
- data/app/components/daisy/data_display/chat_component.rb +2 -2
- data/app/components/daisy/data_display/collapse_component.rb +9 -5
- data/app/components/daisy/data_display/countdown_component.rb +15 -5
- data/app/components/daisy/data_display/figure_component.rb +8 -3
- data/app/components/daisy/data_display/kbd_component.rb +13 -4
- data/app/components/daisy/data_display/list_component.html.haml +5 -0
- data/app/components/daisy/data_display/list_component.rb +82 -0
- data/app/components/daisy/data_display/list_item_component.rb +39 -0
- data/app/components/daisy/data_display/stat_component.html.haml +5 -6
- data/app/components/daisy/data_display/stat_component.rb +21 -8
- data/app/components/daisy/data_display/status_component.rb +47 -0
- data/app/components/daisy/data_display/timeline_component.rb +1 -1
- data/app/components/daisy/data_input/cally_component.html.haml +14 -0
- data/app/components/daisy/data_input/cally_component.rb +182 -0
- data/app/components/daisy/data_input/cally_input_component.html.haml +5 -0
- data/app/components/daisy/data_input/cally_input_component.rb +165 -0
- data/app/components/daisy/data_input/cally_input_controller.js +235 -0
- data/app/components/daisy/data_input/checkbox_component.html.haml +20 -0
- data/app/components/daisy/data_input/checkbox_component.rb +106 -0
- data/app/components/daisy/data_input/fieldset_component.html.haml +8 -0
- data/app/components/daisy/data_input/fieldset_component.rb +57 -0
- data/app/components/daisy/data_input/file_input_component.rb +98 -0
- data/app/components/daisy/data_input/filter_component.html.haml +3 -0
- data/app/components/daisy/data_input/filter_component.rb +221 -0
- data/app/components/daisy/data_input/label_component.rb +84 -0
- data/app/components/daisy/data_input/radio_button_component.rb +87 -0
- data/app/components/daisy/data_input/range_component.rb +95 -0
- data/app/components/daisy/data_input/rating_component.html.haml +11 -0
- data/app/components/daisy/data_input/rating_component.rb +139 -0
- data/app/components/daisy/data_input/select_component.html.haml +27 -0
- data/app/components/daisy/data_input/select_component.rb +320 -0
- data/app/components/daisy/data_input/text_area_component.rb +127 -0
- data/app/components/daisy/data_input/text_input_component.html.haml +27 -0
- data/app/components/daisy/data_input/text_input_component.rb +142 -0
- data/app/components/daisy/data_input/toggle_component.rb +48 -0
- data/app/components/daisy/feedback/alert_component.html.haml +1 -1
- data/app/components/daisy/feedback/alert_component.rb +86 -2
- data/app/components/daisy/feedback/loading_component.rb +10 -3
- data/app/components/daisy/feedback/skeleton_component.rb +1 -1
- data/app/components/daisy/layout/divider_component.rb +4 -2
- data/app/components/daisy/layout/drawer_component.html.haml +0 -1
- data/app/components/daisy/layout/footer_component.rb +6 -6
- data/app/components/daisy/mockup/device_component.rb +15 -18
- data/app/components/daisy/navigation/breadcrumbs_component.html.haml +0 -1
- data/app/components/daisy/navigation/breadcrumbs_component.rb +84 -9
- data/app/components/daisy/navigation/dock_component.rb +146 -0
- data/app/components/daisy/navigation/link_component.rb +18 -9
- data/app/components/daisy/navigation/menu_component.rb +15 -9
- data/app/components/daisy/navigation/navbar_component.html.haml +1 -1
- data/app/components/daisy/navigation/navbar_component.rb +2 -13
- data/app/components/daisy/navigation/steps_component.rb +6 -6
- data/app/components/daisy/navigation/tabs_component.html.haml +0 -1
- data/app/components/daisy/navigation/tabs_component.rb +26 -16
- data/app/components/hero/icon_component.rb +15 -5
- data/app/helpers/daisy/form_builder_helper.rb +186 -0
- data/app/views/examples/daisy/data_input/filters.html.haml +62 -0
- data/lib/daisy.rb +5 -0
- data/lib/hero.rb +1 -1
- data/lib/loco_motion/base_component.rb +53 -3
- data/lib/loco_motion/component_config.rb +1 -0
- data/lib/loco_motion/concerns/iconable_component.rb +134 -0
- data/lib/loco_motion/concerns/labelable_component.rb +142 -0
- data/lib/loco_motion/concerns/linkable_component.rb +40 -0
- data/lib/loco_motion/concerns/tippable_component.rb +25 -10
- data/lib/loco_motion/engine.rb +6 -0
- data/lib/loco_motion/helpers.rb +38 -17
- data/lib/loco_motion/patches/view_component/slot_loco_parent_patch.rb +37 -0
- data/lib/loco_motion/patches/view_component/slotable_default_patch.rb +21 -0
- data/lib/loco_motion/version.rb +1 -1
- data/lib/loco_motion.rb +12 -2
- metadata +93 -21
- data/app/components/daisy/actions/theme_controller_component.html.haml +0 -5
- data/app/components/daisy/layout/artboard_component.rb +0 -59
- data/app/components/daisy/navigation/bottom_nav_component.rb +0 -138
@@ -0,0 +1,320 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# The Select component provides a styled dropdown select input for forms.
|
5
|
+
# It supports various styling options, including sizes, colors, and variants.
|
6
|
+
# Additionally, it supports labelable functionality with start, end, and
|
7
|
+
# floating labels.
|
8
|
+
#
|
9
|
+
# @note Select inputs have a border by default and a width of 20rem. Use
|
10
|
+
# `select-ghost` to remove the border.
|
11
|
+
#
|
12
|
+
# @part placeholder The placeholder option element that is shown when no option
|
13
|
+
# is selected.
|
14
|
+
# @part label_wrapper The wrapper element for labels (when using
|
15
|
+
# start/end/floating labels).
|
16
|
+
# @part start The element that contains the start label (appears before the
|
17
|
+
# select).
|
18
|
+
# @part end The element that contains the end label (appears after the select).
|
19
|
+
# @part floating The element that contains the floating label (appears floating
|
20
|
+
# above the select).
|
21
|
+
#
|
22
|
+
# @slot options+ Custom options to be rendered in the select.
|
23
|
+
# @slot start Custom content for the start label.
|
24
|
+
# @slot end Custom content for the end label.
|
25
|
+
# @slot floating Custom content for the floating label.
|
26
|
+
#
|
27
|
+
# @loco_example Using simple strings for options
|
28
|
+
# = daisy_select(name: "size", css: "select-sm", options: ["Small", "Medium", "Large"])
|
29
|
+
#
|
30
|
+
# @loco_example Using a block to define options
|
31
|
+
# = daisy_select(name: "color", css: "select-primary") do |select|
|
32
|
+
# - select.with_option(value: "red", label: "Red")
|
33
|
+
# - select.with_option(value: "green", label: "Green")
|
34
|
+
# - select.with_option(value: "blue", label: "Blue")
|
35
|
+
#
|
36
|
+
# @loco_example With a start label
|
37
|
+
# = daisy_select(name: "color", start: "Select a color", options: ["Red", "Green", "Blue"])
|
38
|
+
#
|
39
|
+
# @loco_example With a floating label
|
40
|
+
# = daisy_select(name: "color", floating: "Color", options: ["Red", "Green", "Blue"])
|
41
|
+
#
|
42
|
+
class Daisy::DataInput::SelectComponent < LocoMotion::BaseComponent
|
43
|
+
include LocoMotion::Concerns::LabelableComponent
|
44
|
+
|
45
|
+
class SelectOptionComponent < LocoMotion::BasicComponent
|
46
|
+
attr_reader :value, :label, :selected, :disabled
|
47
|
+
|
48
|
+
#
|
49
|
+
# Initialize a new select option component.
|
50
|
+
#
|
51
|
+
# @param value [String, Symbol, Integer] The value of the option.
|
52
|
+
#
|
53
|
+
# @param label [String] The label to display for the option.
|
54
|
+
#
|
55
|
+
# @param selected [Boolean] Whether the option is selected. Defaults to false.
|
56
|
+
#
|
57
|
+
# @param disabled [Boolean] Whether the option is disabled. Defaults to false.
|
58
|
+
#
|
59
|
+
# @param css [String] CSS classes to apply to the option.
|
60
|
+
#
|
61
|
+
# @param html [Hash] HTML attributes to apply to the option.
|
62
|
+
#
|
63
|
+
def initialize(value:, label:, selected: false, disabled: false, css: "", html: {}, **kws)
|
64
|
+
@value = value
|
65
|
+
@label = label
|
66
|
+
@selected = selected
|
67
|
+
@disabled = disabled
|
68
|
+
@css = css
|
69
|
+
@html = html
|
70
|
+
super(**kws)
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# Renders the option element with the appropriate attributes.
|
75
|
+
#
|
76
|
+
# @return [String] The rendered HTML for the option element.
|
77
|
+
#
|
78
|
+
def call
|
79
|
+
content_tag(:option, label, {
|
80
|
+
value: value,
|
81
|
+
selected: selected,
|
82
|
+
disabled: disabled,
|
83
|
+
class: @css
|
84
|
+
}.merge(@html))
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
renders_many :options, SelectOptionComponent
|
89
|
+
|
90
|
+
define_part :placeholder
|
91
|
+
|
92
|
+
attr_reader :name, :id, :value, :include_blank, :disabled, :required, :options_css, :options_html
|
93
|
+
|
94
|
+
#
|
95
|
+
# Initialize a new select component.
|
96
|
+
#
|
97
|
+
# @param kws [Hash] The keyword arguments for the component.
|
98
|
+
#
|
99
|
+
# @option kws name [String] The name attribute for the select input.
|
100
|
+
#
|
101
|
+
# @option kws id [String] The id attribute for the select input.
|
102
|
+
#
|
103
|
+
# @option kws value [String, Symbol, Integer] The current value of the select input.
|
104
|
+
# Determines which option is selected on initial render.
|
105
|
+
#
|
106
|
+
# @option kws include_blank [Boolean] Whether to include a blank option at the
|
107
|
+
# top of the list.
|
108
|
+
#
|
109
|
+
# @option kws disabled [Boolean] Whether the select input is disabled. Defaults to
|
110
|
+
# false.
|
111
|
+
#
|
112
|
+
# @option kws required [Boolean] Whether the select input is required for form
|
113
|
+
# validation. Defaults to false.
|
114
|
+
#
|
115
|
+
# @option kws options [Array] An array of options to display in the select input.
|
116
|
+
# Can be an array of strings or hashes with :value and :label keys.
|
117
|
+
#
|
118
|
+
# @option kws options_css [String] CSS classes to apply to each option.
|
119
|
+
#
|
120
|
+
# @option kws options_html [Hash] HTML attributes to apply to each option.
|
121
|
+
#
|
122
|
+
# @option kws option_label [Symbol] The key to use for the option label.
|
123
|
+
#
|
124
|
+
# @option kws option_value [Symbol] The key to use for the option value.
|
125
|
+
#
|
126
|
+
def initialize(**kws)
|
127
|
+
super(**kws)
|
128
|
+
|
129
|
+
@name = config_option(:name)
|
130
|
+
@id = config_option(:id)
|
131
|
+
@value = config_option(:value)
|
132
|
+
@include_blank = config_option(:include_blank, false)
|
133
|
+
@disabled = config_option(:disabled, false)
|
134
|
+
@required = config_option(:required, false)
|
135
|
+
@options_list = config_option(:options)
|
136
|
+
@options_css = config_option(:options_css, "")
|
137
|
+
@options_html = config_option(:options_html, {})
|
138
|
+
@option_label = config_option(:option_label, :label)
|
139
|
+
@option_value = config_option(:option_value, :value)
|
140
|
+
end
|
141
|
+
|
142
|
+
#
|
143
|
+
# Sets up the component before rendering.
|
144
|
+
#
|
145
|
+
def before_render
|
146
|
+
super
|
147
|
+
|
148
|
+
setup_component
|
149
|
+
setup_placeholder
|
150
|
+
end
|
151
|
+
|
152
|
+
#
|
153
|
+
# Sets up the component by configuring the tag name, CSS classes, and HTML attributes.
|
154
|
+
# Sets the tag to 'select' and adds the 'select' CSS class.
|
155
|
+
# Also adds Stimulus controller data attributes.
|
156
|
+
#
|
157
|
+
def setup_component
|
158
|
+
set_tag_name(:component, :select)
|
159
|
+
|
160
|
+
if has_floating_label?
|
161
|
+
add_css(:label_wrapper, "floating-label")
|
162
|
+
add_css(:component, "select")
|
163
|
+
elsif has_start_label? || has_end_label?
|
164
|
+
add_stimulus_controller(:label_wrapper, "select")
|
165
|
+
|
166
|
+
add_css(:label_wrapper, "select")
|
167
|
+
add_css(:start, "label")
|
168
|
+
add_css(:end, "label")
|
169
|
+
else
|
170
|
+
add_css(:component, "select")
|
171
|
+
end
|
172
|
+
|
173
|
+
# Add HTML attributes for the select element
|
174
|
+
add_html(:component,
|
175
|
+
name: @name,
|
176
|
+
id: @id,
|
177
|
+
disabled: @disabled,
|
178
|
+
required: @required
|
179
|
+
)
|
180
|
+
end
|
181
|
+
|
182
|
+
#
|
183
|
+
# Sets up the placeholder option that appears when no option is selected.
|
184
|
+
# Adds a disabled option with an empty value.
|
185
|
+
#
|
186
|
+
def setup_placeholder
|
187
|
+
set_tag_name(:placeholder, :option)
|
188
|
+
add_html(:placeholder, value: "", disabled: true, selected: @value.blank?)
|
189
|
+
end
|
190
|
+
|
191
|
+
#
|
192
|
+
# Converts the options array into SelectOptionComponent instances.
|
193
|
+
# Handles both hash options (with value/label keys) and simple string options.
|
194
|
+
#
|
195
|
+
# @return [Array<SelectOptionComponent>] Array of option components or empty array if @options_list is nil.
|
196
|
+
#
|
197
|
+
def default_options
|
198
|
+
return [] unless @options_list
|
199
|
+
|
200
|
+
options_list.map do |option|
|
201
|
+
value = extract_option_value(option)
|
202
|
+
label = extract_option_label(option, value)
|
203
|
+
|
204
|
+
Daisy::DataInput::SelectComponent::SelectOptionComponent.new(
|
205
|
+
value: value,
|
206
|
+
label: label,
|
207
|
+
selected: value.to_s == @value.to_s,
|
208
|
+
css: @options_css,
|
209
|
+
html: @options_html
|
210
|
+
)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
private
|
215
|
+
|
216
|
+
# Extracts the value from an option using the configured @option_value key or method.
|
217
|
+
#
|
218
|
+
# @param option [Object] The option to extract the value from
|
219
|
+
# @return [Object] The extracted value
|
220
|
+
#
|
221
|
+
def extract_option_value(option)
|
222
|
+
if option.is_a?(Hash)
|
223
|
+
option[@option_value]
|
224
|
+
elsif option.respond_to?(@option_value)
|
225
|
+
option.public_send(@option_value)
|
226
|
+
else
|
227
|
+
option
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
# Extracts the label from an option using the configured @option_label key or method.
|
232
|
+
# Falls back to the value if no label can be extracted.
|
233
|
+
#
|
234
|
+
# @param option [Object] The option to extract the label from
|
235
|
+
# @param value [Object] The extracted value to use as fallback
|
236
|
+
# @return [String] The extracted label or string representation of the value
|
237
|
+
#
|
238
|
+
def extract_option_label(option, value)
|
239
|
+
if option.is_a?(Hash)
|
240
|
+
option[@option_label] || value.to_s
|
241
|
+
elsif option.respond_to?(@option_label)
|
242
|
+
option.public_send(@option_label)
|
243
|
+
else
|
244
|
+
value.to_s
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
# Alias for include_blank to match Ruby convention for boolean methods
|
249
|
+
def include_blank?
|
250
|
+
@include_blank
|
251
|
+
end
|
252
|
+
|
253
|
+
#
|
254
|
+
# Renders the select options based on the configuration.
|
255
|
+
# This method is used by the template to render options consistently.
|
256
|
+
#
|
257
|
+
# @return [String] The HTML for all options in the select.
|
258
|
+
#
|
259
|
+
def render_select_options
|
260
|
+
result = ""
|
261
|
+
|
262
|
+
# Add blank option if configured
|
263
|
+
if include_blank?
|
264
|
+
result += content_tag(:option, "", value: "")
|
265
|
+
end
|
266
|
+
|
267
|
+
# Add options from the block or default options
|
268
|
+
if options?
|
269
|
+
options.each do |option|
|
270
|
+
result += option.call
|
271
|
+
end
|
272
|
+
elsif default_options.present?
|
273
|
+
default_options.each do |option|
|
274
|
+
result += render(option)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
result.html_safe
|
279
|
+
end
|
280
|
+
|
281
|
+
#
|
282
|
+
# Renders the component part with placeholder, options and content.
|
283
|
+
# This method is used by the template to render the select component consistently.
|
284
|
+
#
|
285
|
+
# @return [String] The HTML for the select component.
|
286
|
+
#
|
287
|
+
def render_component
|
288
|
+
part(:component) do
|
289
|
+
result = ""
|
290
|
+
|
291
|
+
# Add placeholder if provided
|
292
|
+
if @placeholder
|
293
|
+
result += part(:placeholder) do
|
294
|
+
@placeholder
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
# Add options
|
299
|
+
result += render_select_options
|
300
|
+
|
301
|
+
# Add content if present
|
302
|
+
if content?
|
303
|
+
result += (content || "")
|
304
|
+
end
|
305
|
+
|
306
|
+
result.html_safe
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
private
|
311
|
+
|
312
|
+
#
|
313
|
+
# Ensures the options list is always an array, even if a single option is provided.
|
314
|
+
#
|
315
|
+
# @return [Array] The list of options as an array.
|
316
|
+
#
|
317
|
+
def options_list
|
318
|
+
@options_list.is_a?(Array) ? @options_list : [@options_list]
|
319
|
+
end
|
320
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# The TextArea component renders a DaisyUI styled textarea field.
|
5
|
+
# It can be used standalone or with a form builder, and supports
|
6
|
+
# various styling options and states.
|
7
|
+
#
|
8
|
+
# @note Text areas have a border by default. Use `textarea-ghost` to remove the
|
9
|
+
# border.
|
10
|
+
#
|
11
|
+
# @part component The main textarea element that users can type into.
|
12
|
+
#
|
13
|
+
# @loco_example Basic Usage
|
14
|
+
# = daisy_text_area(name: "message", id: "message")
|
15
|
+
#
|
16
|
+
# @loco_example With Placeholder
|
17
|
+
# = daisy_text_area(name: "message", placeholder: "Enter your message here...")
|
18
|
+
#
|
19
|
+
# @loco_example With Initial Value
|
20
|
+
# = daisy_text_area(name: "message", value: "Initial text content")
|
21
|
+
#
|
22
|
+
# @loco_example With Specified Rows
|
23
|
+
# = daisy_text_area(name: "message", rows: 6)
|
24
|
+
#
|
25
|
+
# @loco_example Borderless Style
|
26
|
+
# = daisy_text_area(name: "message", css: "textarea-ghost")
|
27
|
+
#
|
28
|
+
# @loco_example Different Colors
|
29
|
+
# .flex.flex-col.gap-4
|
30
|
+
# = daisy_text_area(name: "primary", placeholder: "Primary", css: "textarea-primary")
|
31
|
+
# = daisy_text_area(name: "secondary", placeholder: "Secondary", css: "textarea-secondary")
|
32
|
+
# = daisy_text_area(name: "accent", placeholder: "Accent", css: "textarea-accent")
|
33
|
+
#
|
34
|
+
# @loco_example Disabled TextArea
|
35
|
+
# = daisy_text_area(name: "message", disabled: true)
|
36
|
+
#
|
37
|
+
# @loco_example Required TextArea
|
38
|
+
# = daisy_text_area(name: "message", required: true)
|
39
|
+
#
|
40
|
+
# @loco_example Readonly TextArea
|
41
|
+
# = daisy_text_area(name: "message", readonly: true, value: "This content cannot be edited.")
|
42
|
+
#
|
43
|
+
class Daisy::DataInput::TextAreaComponent < LocoMotion::BaseComponent
|
44
|
+
attr_reader :name, :id, :value, :placeholder, :rows, :cols, :disabled, :required, :readonly
|
45
|
+
|
46
|
+
#
|
47
|
+
# Instantiate a new TextArea component.
|
48
|
+
#
|
49
|
+
# @param kws [Hash] The keyword arguments for the component.
|
50
|
+
#
|
51
|
+
# @option kws name [String] The name attribute for the textarea.
|
52
|
+
#
|
53
|
+
# @option kws id [String] The ID attribute for the textarea.
|
54
|
+
#
|
55
|
+
# @option kws value [String] The initial value of the textarea.
|
56
|
+
#
|
57
|
+
# @option kws placeholder [String] Placeholder text for the textarea.
|
58
|
+
#
|
59
|
+
# @option kws rows [Integer] The number of visible text lines. Defaults to 4.
|
60
|
+
#
|
61
|
+
# @option kws cols [Integer] The visible width of the textarea. Defaults to nil.
|
62
|
+
#
|
63
|
+
# @option kws disabled [Boolean] Whether the textarea is disabled. Defaults to
|
64
|
+
# false.
|
65
|
+
#
|
66
|
+
# @option kws required [Boolean] Whether the textarea is required for form
|
67
|
+
# validation. Defaults to false.
|
68
|
+
#
|
69
|
+
# @option kws readonly [Boolean] Whether the textarea is read-only. Defaults to
|
70
|
+
# false.
|
71
|
+
#
|
72
|
+
def initialize(**kws)
|
73
|
+
super
|
74
|
+
|
75
|
+
@name = config_option(:name)
|
76
|
+
@id = config_option(:id)
|
77
|
+
@value = config_option(:value, nil)
|
78
|
+
@placeholder = config_option(:placeholder, nil)
|
79
|
+
@rows = config_option(:rows, 4)
|
80
|
+
@cols = config_option(:cols, nil)
|
81
|
+
@disabled = config_option(:disabled, false)
|
82
|
+
@required = config_option(:required, false)
|
83
|
+
@readonly = config_option(:readonly, false)
|
84
|
+
end
|
85
|
+
|
86
|
+
#
|
87
|
+
# Calls the {setup_component} method before rendering the component.
|
88
|
+
#
|
89
|
+
def before_render
|
90
|
+
setup_component
|
91
|
+
end
|
92
|
+
|
93
|
+
#
|
94
|
+
# Sets up the component by configuring the tag name, CSS classes, and HTML
|
95
|
+
# attributes. Sets the tag to textarea and adds the 'textarea' CSS class.
|
96
|
+
#
|
97
|
+
# This configures various attributes of the textarea including name, id, value,
|
98
|
+
# placeholder, rows, cols, and states like disabled, required, and readonly.
|
99
|
+
#
|
100
|
+
def setup_component
|
101
|
+
set_tag_name(:component, :textarea)
|
102
|
+
|
103
|
+
add_css(:component, "textarea")
|
104
|
+
|
105
|
+
add_html(:component, {
|
106
|
+
name: @name,
|
107
|
+
id: @id,
|
108
|
+
placeholder: @placeholder,
|
109
|
+
rows: @rows,
|
110
|
+
cols: @cols,
|
111
|
+
disabled: @disabled,
|
112
|
+
required: @required,
|
113
|
+
readonly: @readonly
|
114
|
+
})
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
# Renders the component with its value as content.
|
119
|
+
#
|
120
|
+
def call
|
121
|
+
if @value
|
122
|
+
part(:component) { @value }
|
123
|
+
else
|
124
|
+
part(:component)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
- if has_any_label?
|
2
|
+
= part(:label_wrapper) do
|
3
|
+
- if has_start_label?
|
4
|
+
- if start?
|
5
|
+
= start
|
6
|
+
- else
|
7
|
+
= part(:start) do
|
8
|
+
= @start
|
9
|
+
|
10
|
+
- if has_floating_label?
|
11
|
+
- if floating?
|
12
|
+
= floating
|
13
|
+
- else
|
14
|
+
= part(:floating) do
|
15
|
+
= @floating
|
16
|
+
|
17
|
+
= part(:component)
|
18
|
+
|
19
|
+
- if has_end_label?
|
20
|
+
- if end?
|
21
|
+
= self.send(:end)
|
22
|
+
- else
|
23
|
+
= part(:end) do
|
24
|
+
= @end
|
25
|
+
|
26
|
+
- else
|
27
|
+
= part(:component)
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# The TextInput component renders a DaisyUI styled text input field.
|
5
|
+
# It can be used standalone or with a form builder, and supports
|
6
|
+
# various styling options including different types, sizes and variants.
|
7
|
+
#
|
8
|
+
# @note Input fields have a border by default and a width of 20rem. Use
|
9
|
+
# `input-ghost` to remove the border.
|
10
|
+
#
|
11
|
+
# @part label_wrapper The wrapper element for labels (when using
|
12
|
+
# start/end/floating labels).
|
13
|
+
# @part start The element that contains the start label (appears before the
|
14
|
+
# input).
|
15
|
+
# @part end The element that contains the end label (appears after the input).
|
16
|
+
# @part floating The element that contains the floating label (appears floating
|
17
|
+
# above the input).
|
18
|
+
#
|
19
|
+
# @slot start Content to display before the input field.
|
20
|
+
# @slot end Content to display after the input field.
|
21
|
+
# @slot floating Custom content for the floating label.
|
22
|
+
#
|
23
|
+
# @loco_example Basic Usage
|
24
|
+
# = daisy_text_input(name: "username", id: "username")
|
25
|
+
#
|
26
|
+
# @loco_example With Placeholder
|
27
|
+
# = daisy_text_input(name: "email", id: "email", placeholder: "Enter your email")
|
28
|
+
#
|
29
|
+
# @loco_example Ghost Style (No Border)
|
30
|
+
# = daisy_text_input(name: "search", id: "search", css: "input-ghost")
|
31
|
+
#
|
32
|
+
# @loco_example Different Types
|
33
|
+
# = daisy_text_input(name: "password", id: "password", type: "password")
|
34
|
+
# = daisy_text_input(name: "email", id: "email", type: "email")
|
35
|
+
#
|
36
|
+
# @loco_example With Start Label
|
37
|
+
# = daisy_text_input(name: "username", id: "username", start: "Username:")
|
38
|
+
#
|
39
|
+
# @loco_example With End Label
|
40
|
+
# = daisy_text_input(name: "email", id: "email", end: "@example.com")
|
41
|
+
#
|
42
|
+
# @loco_example With Floating Label
|
43
|
+
# = daisy_text_input(name: "username", id: "username", floating: "Username")
|
44
|
+
#
|
45
|
+
# @loco_example With Icons
|
46
|
+
# = daisy_text_input(name: "search", placeholder: "Search...") do |text_input|
|
47
|
+
# - text_input.with_start do
|
48
|
+
# = hero_icon("magnifying-glass", size: 5, css: "text-gray-400")
|
49
|
+
#
|
50
|
+
# @loco_example With Start and End Content
|
51
|
+
# = daisy_text_input(name: "email", placeholder: "Email address") do |text_input|
|
52
|
+
# - text_input.with_start do
|
53
|
+
# = hero_icon("envelope", size: 5, css: "text-gray-400")
|
54
|
+
# - text_input.with_end do
|
55
|
+
# = daisy_button(title: "Verify", css: "h-full rounded-l-none")
|
56
|
+
#
|
57
|
+
# @loco_example Disabled Text Input
|
58
|
+
# = daisy_text_input(name: "username", id: "username", disabled: true)
|
59
|
+
#
|
60
|
+
class Daisy::DataInput::TextInputComponent < LocoMotion::BaseComponent
|
61
|
+
include LocoMotion::Concerns::LabelableComponent
|
62
|
+
|
63
|
+
attr_reader :name, :id, :value, :type, :disabled, :required, :readonly
|
64
|
+
|
65
|
+
#
|
66
|
+
# Instantiate a new TextInput component.
|
67
|
+
#
|
68
|
+
# @param kws [Hash] The keyword arguments for the component.
|
69
|
+
#
|
70
|
+
# @option kws name [String] The name attribute for the text input.
|
71
|
+
#
|
72
|
+
# @option kws id [String] The ID attribute for the text input.
|
73
|
+
#
|
74
|
+
# @option kws value [String] The initial value of the text input.
|
75
|
+
#
|
76
|
+
# @option kws type [String] The type of input (text, password, email, etc.).
|
77
|
+
# Defaults to "text".
|
78
|
+
#
|
79
|
+
# @option kws disabled [Boolean] Whether the text input is disabled. Defaults to
|
80
|
+
# false.
|
81
|
+
#
|
82
|
+
# @option kws required [Boolean] Whether the text input is required for form
|
83
|
+
# validation. Defaults to false.
|
84
|
+
#
|
85
|
+
# @option kws readonly [Boolean] Whether the text input is read-only. Defaults to
|
86
|
+
# false.
|
87
|
+
#
|
88
|
+
def initialize(**kws)
|
89
|
+
super
|
90
|
+
|
91
|
+
@name = config_option(:name)
|
92
|
+
@id = config_option(:id)
|
93
|
+
@value = config_option(:value, nil)
|
94
|
+
@type = config_option(:type, "text")
|
95
|
+
@disabled = config_option(:disabled, false)
|
96
|
+
@required = config_option(:required, false)
|
97
|
+
@readonly = config_option(:readonly, false)
|
98
|
+
@change = config_option(:change)
|
99
|
+
end
|
100
|
+
|
101
|
+
#
|
102
|
+
# Calls the {setup_component} method before rendering the component.
|
103
|
+
#
|
104
|
+
def before_render
|
105
|
+
super
|
106
|
+
|
107
|
+
setup_component
|
108
|
+
end
|
109
|
+
|
110
|
+
#
|
111
|
+
# Sets up the component by configuring the tag name, CSS classes, and HTML
|
112
|
+
# attributes. Sets the tag to input with appropriate type and adds the 'input'
|
113
|
+
# CSS class.
|
114
|
+
#
|
115
|
+
# This configures various attributes of the text input including name, id, value,
|
116
|
+
# placeholder, type, and states like disabled, required, and readonly.
|
117
|
+
#
|
118
|
+
def setup_component
|
119
|
+
set_tag_name(:component, :input)
|
120
|
+
|
121
|
+
if has_floating_label?
|
122
|
+
add_css(:label_wrapper, "floating-label input")
|
123
|
+
elsif has_start_label? || has_end_label?
|
124
|
+
add_css(:label_wrapper, "input")
|
125
|
+
else
|
126
|
+
add_css(:component, "input")
|
127
|
+
end
|
128
|
+
|
129
|
+
add_html(:component, {
|
130
|
+
type: @type,
|
131
|
+
name: @name,
|
132
|
+
id: @id,
|
133
|
+
value: @value,
|
134
|
+
placeholder: @placeholder,
|
135
|
+
disabled: @disabled,
|
136
|
+
required: @required,
|
137
|
+
readonly: @readonly
|
138
|
+
})
|
139
|
+
|
140
|
+
add_html(:component, { onchange: "document.getElementById('#{@change}').value = this.value" }) if @change
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# The Toggle component renders a DaisyUI styled toggle switch.
|
5
|
+
# It can be used standalone or with a form builder, and provides a visual way
|
6
|
+
# to toggle between two states (on/off).
|
7
|
+
#
|
8
|
+
# @part label_wrapper The wrapper element for labels (when using
|
9
|
+
# start/end/floating labels).
|
10
|
+
# @part start The element that contains the start label (appears before the
|
11
|
+
# toggle).
|
12
|
+
# @part end The element that contains the end label (appears after the toggle).
|
13
|
+
#
|
14
|
+
# @slot start Custom content for the start label.
|
15
|
+
# @slot end Custom content for the end label.
|
16
|
+
#
|
17
|
+
# @loco_example Basic Usage
|
18
|
+
# = daisy_toggle(name: "notifications", id: "notifications")
|
19
|
+
#
|
20
|
+
# @loco_example Checked Toggle
|
21
|
+
# = daisy_toggle(name: "notifications", id: "notifications", checked: true)
|
22
|
+
#
|
23
|
+
# @loco_example Colored Toggle
|
24
|
+
# = daisy_toggle(name: "theme", id: "theme", css: "toggle-primary", checked: true)
|
25
|
+
#
|
26
|
+
# @loco_example Disabled Toggle
|
27
|
+
# = daisy_toggle(name: "disabled", id: "disabled", disabled: true)
|
28
|
+
#
|
29
|
+
# @loco_example With End Label (common for toggles)
|
30
|
+
# = daisy_toggle(name: "notifications", id: "notifications", end: "Enable notifications")
|
31
|
+
#
|
32
|
+
class Daisy::DataInput::ToggleComponent < Daisy::DataInput::CheckboxComponent
|
33
|
+
#
|
34
|
+
# Instantiate a new Toggle component.
|
35
|
+
#
|
36
|
+
# This component accepts the same options as {Daisy::DataInput::CheckboxComponent},
|
37
|
+
# but always sets `toggle: true` to render the checkbox as a toggle switch.
|
38
|
+
#
|
39
|
+
# @param kws [Hash] The keyword arguments for the component. See
|
40
|
+
# {Daisy::DataInput::CheckboxComponent#initialize} for available options.
|
41
|
+
#
|
42
|
+
def initialize(**kws)
|
43
|
+
# Always force toggle to be true
|
44
|
+
kws[:toggle] = true
|
45
|
+
|
46
|
+
super(**kws)
|
47
|
+
end
|
48
|
+
end
|