loco_motion-rails 0.0.7 → 0.4.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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +101 -14
  3. data/app/components/daisy/actions/button_component.rb +109 -8
  4. data/app/components/daisy/actions/dropdown_component.html.haml +5 -5
  5. data/app/components/daisy/actions/dropdown_component.rb +94 -25
  6. data/app/components/daisy/actions/modal_component.html.haml +3 -2
  7. data/app/components/daisy/actions/modal_component.rb +94 -45
  8. data/app/components/daisy/actions/swap_component.rb +114 -5
  9. data/app/components/daisy/actions/theme_controller_component.html.haml +1 -1
  10. data/app/components/daisy/actions/theme_controller_component.rb +36 -1
  11. data/app/components/daisy/data_display/accordion_component.rb +79 -3
  12. data/app/components/daisy/data_display/avatar_component.rb +36 -16
  13. data/app/components/daisy/data_display/badge_component.rb +35 -5
  14. data/app/components/daisy/data_display/card_component.html.haml +5 -13
  15. data/app/components/daisy/data_display/card_component.rb +74 -39
  16. data/app/components/daisy/data_display/carousel_component.rb +38 -0
  17. data/app/components/daisy/data_display/chat_component.rb +40 -10
  18. data/app/components/daisy/data_display/collapse_component.rb +58 -1
  19. data/app/components/daisy/data_display/countdown_component.rb +49 -0
  20. data/app/components/daisy/data_display/diff_component.rb +37 -0
  21. data/app/components/daisy/data_display/figure_component.rb +49 -0
  22. data/app/components/daisy/data_display/kbd_component.rb +50 -2
  23. data/app/components/daisy/data_display/stat_component.rb +64 -6
  24. data/app/components/daisy/data_display/table_component.rb +99 -34
  25. data/app/components/daisy/data_display/timeline_component.rb +45 -0
  26. data/app/components/daisy/data_display/timeline_event_component.rb +39 -1
  27. data/app/components/daisy/data_input/checkbox_component.rb +92 -0
  28. data/app/components/daisy/data_input/file_input_component.rb +92 -0
  29. data/app/components/daisy/data_input/label_component.rb +84 -0
  30. data/app/components/daisy/data_input/radio_button_component.rb +87 -0
  31. data/app/components/daisy/data_input/range_component.rb +95 -0
  32. data/app/components/daisy/data_input/rating_component.html.haml +13 -0
  33. data/app/components/daisy/data_input/rating_component.rb +138 -0
  34. data/app/components/daisy/data_input/select_component.html.haml +15 -0
  35. data/app/components/daisy/data_input/select_component.rb +178 -0
  36. data/app/components/daisy/data_input/text_area_component.rb +124 -0
  37. data/app/components/daisy/data_input/text_input_component.html.haml +6 -0
  38. data/app/components/daisy/data_input/text_input_component.rb +140 -0
  39. data/app/components/daisy/data_input/toggle_component.rb +36 -0
  40. data/app/components/daisy/feedback/alert_component.rb +46 -1
  41. data/app/components/daisy/feedback/loading_component.rb +39 -0
  42. data/app/components/daisy/feedback/progress_component.rb +39 -1
  43. data/app/components/daisy/feedback/radial_progress_component.rb +44 -1
  44. data/app/components/daisy/feedback/skeleton_component.rb +44 -0
  45. data/app/components/daisy/feedback/toast_component.rb +36 -0
  46. data/app/components/daisy/feedback/tooltip_component.rb +46 -10
  47. data/app/components/daisy/layout/artboard_component.rb +48 -0
  48. data/app/components/daisy/layout/divider_component.rb +50 -10
  49. data/app/components/daisy/layout/drawer_component.rb +62 -17
  50. data/app/components/daisy/layout/footer_component.rb +51 -11
  51. data/app/components/daisy/layout/hero_component.rb +67 -5
  52. data/app/components/daisy/layout/indicator_component.rb +55 -8
  53. data/app/components/daisy/layout/join_component.rb +71 -0
  54. data/app/components/daisy/layout/stack_component.rb +59 -0
  55. data/app/components/daisy/mockup/browser_component.rb +78 -0
  56. data/app/components/daisy/mockup/code_component.rb +144 -0
  57. data/app/components/daisy/mockup/device_component.rb +81 -0
  58. data/app/components/daisy/mockup/frame_component.rb +62 -0
  59. data/app/components/daisy/navigation/bottom_nav_component.rb +81 -2
  60. data/app/components/daisy/navigation/breadcrumbs_component.rb +40 -3
  61. data/app/components/daisy/navigation/link_component.rb +31 -6
  62. data/app/components/daisy/navigation/menu_component.rb +52 -20
  63. data/app/components/daisy/navigation/navbar_component.html.haml +1 -1
  64. data/app/components/daisy/navigation/navbar_component.rb +63 -2
  65. data/app/components/daisy/navigation/steps_component.rb +76 -0
  66. data/app/components/daisy/navigation/tabs_component.rb +110 -7
  67. data/app/components/hero/icon_component.rb +40 -0
  68. data/app/helpers/daisy/form_builder_helper.rb +159 -0
  69. data/lib/daisy.rb +10 -0
  70. data/lib/loco_motion/base_component.rb +9 -2
  71. data/lib/loco_motion/engine.rb +6 -0
  72. data/lib/loco_motion/helpers.rb +19 -0
  73. data/lib/loco_motion/version.rb +5 -0
  74. metadata +51 -5
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # The Range component renders a DaisyUI styled range input slider.
5
+ # It can be used standalone or with a form builder, and supports customization
6
+ # of min/max values, step increments, and color variants.
7
+ #
8
+ # @loco_example Basic Usage
9
+ # = daisy_range(name: "volume", id: "volume", min: 0, max: 100, value: 50)
10
+ #
11
+ # @loco_example Range with Steps
12
+ # = daisy_range(name: "step_range", id: "step_range", min: 0, max: 100, step: 25)
13
+ #
14
+ # @loco_example Range with Different Colors
15
+ # = daisy_range(name: "primary_range", id: "primary_range", css: "range-primary")
16
+ # = daisy_range(name: "error_range", id: "error_range", css: "range-error")
17
+ #
18
+ class Daisy::DataInput::RangeComponent < LocoMotion::BaseComponent
19
+ attr_reader :name, :id, :min, :max, :step, :value, :disabled, :required
20
+
21
+ #
22
+ # Instantiate a new Range component.
23
+ #
24
+ # @param kws [Hash] The keyword arguments for the component.
25
+ #
26
+ # @option kws name [String] The name attribute for the range input.
27
+ #
28
+ # @option kws id [String] The ID attribute for the range input.
29
+ #
30
+ # @option kws min [Integer] The minimum value (default: 0).
31
+ #
32
+ # @option kws max [Integer] The maximum value (default: 100).
33
+ #
34
+ # @option kws step [Integer] The step increment (default: 1).
35
+ #
36
+ # @option kws value [Integer] The current value (default: min).
37
+ #
38
+ # @option kws disabled [Boolean] Whether the range input is disabled. Defaults to
39
+ # false.
40
+ #
41
+ # @option kws required [Boolean] Whether the range input is required for form
42
+ # validation. Defaults to false.
43
+ #
44
+ def initialize(**kws)
45
+ super
46
+
47
+ @name = config_option(:name)
48
+ @id = config_option(:id)
49
+ @min = config_option(:min, 0)
50
+ @max = config_option(:max, 100)
51
+ @step = config_option(:step, 1)
52
+ @value = config_option(:value, @min)
53
+ @disabled = config_option(:disabled, false)
54
+ @required = config_option(:required, false)
55
+ end
56
+
57
+ #
58
+ # Calls the {setup_component} method before rendering the component.
59
+ #
60
+ def before_render
61
+ setup_component
62
+ end
63
+
64
+ #
65
+ # Sets up the component by configuring the tag name, CSS classes, and HTML
66
+ # attributes. Sets the tag to input with type 'range' and adds the 'range' CSS class.
67
+ #
68
+ # This configures the min, max, step values along with name, id, value, disabled state,
69
+ # and required state of the range input.
70
+ #
71
+ def setup_component
72
+ set_tag_name(:component, :input)
73
+
74
+ add_css(:component, "range")
75
+
76
+ add_html(:component, {
77
+ type: "range",
78
+ name: @name,
79
+ id: @id,
80
+ min: @min,
81
+ max: @max,
82
+ step: @step,
83
+ value: @value,
84
+ disabled: @disabled,
85
+ required: @required
86
+ })
87
+ end
88
+
89
+ #
90
+ # Renders the component inline with no additional whitespace.
91
+ #
92
+ def call
93
+ part(:component)
94
+ end
95
+ end
@@ -0,0 +1,13 @@
1
+ = part(:component) do
2
+ = part(:hidden_input)
3
+
4
+ - if items?
5
+ - items.each do |item|
6
+ - item.set_loco_parent(component_ref)
7
+ = item
8
+ - elsif content?
9
+ = content
10
+ - elsif star_items.present?
11
+ - star_items.each do |item|
12
+ - item.set_loco_parent(component_ref)
13
+ = render(item)
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # The Rating component renders a DaisyUI styled rating input using radio buttons.
5
+ # It can be used standalone or with a form builder, allowing users to select a
6
+ # rating from 1 to a configurable maximum value. Supports customization of size,
7
+ # colors, and initial value.
8
+ #
9
+ # @loco_example Basic Usage
10
+ # = daisy_rating(name: "product_rating", id: "product_rating")
11
+ #
12
+ # @loco_example Disabled Rating
13
+ # = daisy_rating(name: "disabled_rating", value: 3, disabled: true)
14
+ #
15
+ # @loco_example Rating with Different Colors
16
+ # = daisy_rating(name: "primary_rating", css: "[&>input]:bg-primary")
17
+ # = daisy_rating(name: "warning_rating", css: "[&>input]:bg-warning")
18
+ #
19
+ # @loco_example Rating with Different Sizes
20
+ # = daisy_rating(name: "small_rating", css: "rating-sm")
21
+ # = daisy_rating(name: "large_rating", css: "rating-lg")
22
+ #
23
+ class Daisy::DataInput::RatingComponent < LocoMotion::BaseComponent
24
+ #
25
+ # Inner component for rendering individual rating items as radio inputs.
26
+ #
27
+ class RatingItemComponent < LocoMotion::BasicComponent
28
+ #
29
+ # Sets up the component before rendering.
30
+ #
31
+ def before_render
32
+ set_tag_name(:component, :input)
33
+ add_html(:component, { name: loco_parent&.name, type: "radio" })
34
+ end
35
+
36
+ #
37
+ # Renders the component with the appropriate attributes.
38
+ # Takes the name from the parent component and sets the type to radio.
39
+ #
40
+ # @return [String] The rendered HTML for the rating item.
41
+ #
42
+ def call
43
+ part(:component)
44
+ end
45
+ end
46
+
47
+ define_part :hidden_input
48
+
49
+ renders_many :items, RatingItemComponent
50
+
51
+ attr_reader :name, :value, :max, :disabled, :required, :id, :inputs_css, :inputs_html
52
+
53
+ #
54
+ # Instantiate a new Rating component.
55
+ #
56
+ # @param kws [Hash] The keyword arguments for the component.
57
+ #
58
+ # @option kws name [String] The name attribute for the radio inputs.
59
+ #
60
+ # @option kws value [Integer] The current rating value.
61
+ #
62
+ # @option kws max [Integer] The maximum rating value (default: 5).
63
+ #
64
+ # @option kws disabled [Boolean] Whether the rating is disabled. Defaults to
65
+ # false. When disabled, users cannot interact with the rating control.
66
+ #
67
+ # @option kws required [Boolean] Whether the rating input is required for form
68
+ # validation. Defaults to false.
69
+ #
70
+ # @option kws id [String] The ID for the first radio input.
71
+ #
72
+ # @option kws inputs_css [String] CSS classes to apply to each rating input.
73
+ #
74
+ # @option kws inputs_html [Hash] HTML attributes to apply to each rating input.
75
+ #
76
+ def initialize(**kws)
77
+ super
78
+
79
+ @name = config_option(:name)
80
+ @value = config_option(:value)
81
+ @max = config_option(:max, 5)
82
+ @disabled = config_option(:disabled, false)
83
+ @required = config_option(:required, false)
84
+ @id = config_option(:id)
85
+ @inputs_css = config_option(:inputs_css)
86
+ @inputs_html = config_option(:inputs_html, {})
87
+ end
88
+
89
+ #
90
+ # Calls the {setup_component} and {setup_hidden_input} methods before rendering
91
+ # the component. This prepares the rating container and creates a hidden input
92
+ # if needed.
93
+ #
94
+ def before_render
95
+ setup_component
96
+ setup_hidden_input
97
+ end
98
+
99
+ #
100
+ # Sets up the component by configuring the tag name and CSS classes.
101
+ #
102
+ def setup_component
103
+ set_tag_name(:component, :div)
104
+ add_css(:component, "rating")
105
+ add_html(:component, id: @id) if @id
106
+ end
107
+
108
+ #
109
+ # Sets up a hidden input so that the rating can start empty.
110
+ #
111
+ def setup_hidden_input
112
+ set_tag_name(:hidden_input, :input)
113
+ add_css(:hidden_input, "hidden")
114
+ add_html(:hidden_input, { type: "radio", name: @name, value: nil, checked: @value.blank? })
115
+ end
116
+
117
+ #
118
+ # Declares some default items to use if no custom items are provided.
119
+ #
120
+ def star_items
121
+ (1..@max).map do |rating|
122
+ input_attrs = {
123
+ css: ["[:where(&)]:mask [:where(&)]:mask-star", @inputs_css].compact.join(" "),
124
+ html: {
125
+ name: @name,
126
+ value: rating,
127
+ checked: @value == rating,
128
+ required: @required && rating == 1,
129
+ disabled: @disabled,
130
+ "aria-label": "#{rating} star",
131
+ **@inputs_html
132
+ }
133
+ }
134
+
135
+ RatingItemComponent.new(**input_attrs)
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,15 @@
1
+ = part(:component) do
2
+ - if @placeholder_text
3
+ = part(:placeholder) do
4
+ = @placeholder_text
5
+
6
+ - if options?
7
+ - options.each do |option|
8
+ - option.set_loco_parent(component_ref)
9
+ = option.call
10
+ - elsif default_options.present?
11
+ - default_options.each do |option|
12
+ - option.set_loco_parent(component_ref)
13
+ = render(option)
14
+ - elsif content?
15
+ = content
@@ -0,0 +1,178 @@
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, bordered and ghost variants.
6
+ #
7
+ # @part placeholder The placeholder option element that is shown when no option is selected.
8
+ #
9
+ # @slot options+ Custom options to be rendered in the select.
10
+ #
11
+ # @loco_example Using simple strings for options
12
+ # = daisy_select(name: "size", css: "select-sm select-bordered", options: ["Small", "Medium", "Large"])
13
+ #
14
+ # @loco_example Using a block to define options
15
+ # = daisy_select(name: "color", css: "select-primary") do |select|
16
+ # - select.with_option(value: "red", label: "Red")
17
+ # - select.with_option(value: "green", label: "Green")
18
+ # - select.with_option(value: "blue", label: "Blue")
19
+ class Daisy::DataInput::SelectComponent < LocoMotion::BaseComponent
20
+ class SelectOptionComponent < LocoMotion::BasicComponent
21
+ attr_reader :value, :label, :selected, :disabled
22
+
23
+ #
24
+ # Initialize a new select option component.
25
+ #
26
+ # @param value [String, Symbol, Integer] The value of the option.
27
+ #
28
+ # @param label [String] The label to display for the option.
29
+ #
30
+ # @param selected [Boolean] Whether the option is selected. Defaults to false.
31
+ #
32
+ # @param disabled [Boolean] Whether the option is disabled. Defaults to false.
33
+ #
34
+ # @param css [String] CSS classes to apply to the option.
35
+ #
36
+ # @param html [Hash] HTML attributes to apply to the option.
37
+ #
38
+ def initialize(value:, label:, selected: false, disabled: false, css: "", html: {}, **kws)
39
+ @value = value
40
+ @label = label
41
+ @selected = selected
42
+ @disabled = disabled
43
+ @css = css
44
+ @html = html
45
+ super(**kws)
46
+ end
47
+
48
+ #
49
+ # Renders the option element with the appropriate attributes.
50
+ #
51
+ # @return [String] The rendered HTML for the option element.
52
+ #
53
+ def call
54
+ content_tag(:option, label, {
55
+ value: value,
56
+ selected: selected,
57
+ disabled: disabled,
58
+ class: @css
59
+ }.merge(@html))
60
+ end
61
+ end
62
+
63
+ renders_many :options, SelectOptionComponent
64
+
65
+ define_part :placeholder
66
+
67
+ attr_reader :name, :id, :value, :placeholder_text, :disabled, :required, :options_css, :options_html
68
+
69
+ #
70
+ # Initialize a new select component.
71
+ #
72
+ # @param kws [Hash] The keyword arguments for the component.
73
+ #
74
+ # @option kws name [String] The name attribute for the select input.
75
+ #
76
+ # @option kws id [String] The id attribute for the select input.
77
+ #
78
+ # @option kws value [String, Symbol, Integer] The current value of the select input.
79
+ # Determines which option is selected on initial render.
80
+ #
81
+ # @option kws placeholder [String] Optional placeholder text to display when no
82
+ # option is selected. Appears as a disabled option at the top of the list.
83
+ #
84
+ # @option kws disabled [Boolean] Whether the select input is disabled. Defaults to
85
+ # false.
86
+ #
87
+ # @option kws required [Boolean] Whether the select input is required for form
88
+ # validation. Defaults to false.
89
+ #
90
+ # @option kws options [Array] An array of options to display in the select input.
91
+ # Can be an array of strings or hashes with :value and :label keys.
92
+ #
93
+ # @option kws options_css [String] CSS classes to apply to each option.
94
+ #
95
+ # @option kws options_html [Hash] HTML attributes to apply to each option.
96
+ #
97
+ def initialize(**kws)
98
+ super(**kws)
99
+
100
+ @name = config_option(:name)
101
+ @id = config_option(:id)
102
+ @value = config_option(:value)
103
+ @placeholder_text = config_option(:placeholder)
104
+ @disabled = config_option(:disabled, false)
105
+ @required = config_option(:required, false)
106
+ @options_list = config_option(:options)
107
+ @options_css = config_option(:options_css, "")
108
+ @options_html = config_option(:options_html, {})
109
+ end
110
+
111
+ #
112
+ # Sets up the component before rendering.
113
+ #
114
+ def before_render
115
+ setup_component
116
+ setup_placeholder
117
+ end
118
+
119
+ #
120
+ # Sets up the component by configuring the tag name, CSS classes, and HTML attributes.
121
+ # Sets the tag to 'select' and adds the 'select' CSS class.
122
+ #
123
+ def setup_component
124
+ set_tag_name(:component, :select)
125
+ add_css(:component, "select")
126
+
127
+ # Add HTML attributes for the select element
128
+ add_html(:component,
129
+ name: @name,
130
+ id: @id,
131
+ disabled: @disabled,
132
+ required: @required
133
+ )
134
+ end
135
+
136
+ #
137
+ # Sets up the placeholder option that appears when no option is selected.
138
+ # Adds a disabled option with an empty value.
139
+ #
140
+ def setup_placeholder
141
+ set_tag_name(:placeholder, :option)
142
+ add_html(:placeholder, value: "", disabled: true, selected: @value.blank?)
143
+ end
144
+
145
+ #
146
+ # Converts the options array into SelectOptionComponent instances.
147
+ # Handles both hash options (with value/label keys) and simple string options.
148
+ #
149
+ # @return [Array<SelectOptionComponent>] Array of option components or empty array if @options_list is nil.
150
+ #
151
+ def default_options
152
+ return [] unless @options_list
153
+
154
+ options_list.map do |option|
155
+ value = option.is_a?(Hash) ? option[:value] : option
156
+ label = option.is_a?(Hash) ? option[:label] : option.to_s
157
+
158
+ Daisy::DataInput::SelectComponent::SelectOptionComponent.new(
159
+ value: value,
160
+ label: label,
161
+ selected: value.to_s == @value.to_s,
162
+ css: @options_css,
163
+ html: @options_html
164
+ )
165
+ end
166
+ end
167
+
168
+ private
169
+
170
+ #
171
+ # Ensures the options list is always an array, even if a single option is provided.
172
+ #
173
+ # @return [Array] The list of options as an array.
174
+ #
175
+ def options_list
176
+ @options_list.is_a?(Array) ? @options_list : [@options_list]
177
+ end
178
+ end
@@ -0,0 +1,124 @@
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
+ # @part component The main textarea element that users can type into.
9
+ #
10
+ # @loco_example Basic Usage
11
+ # = daisy_text_area(name: "message", id: "message")
12
+ #
13
+ # @loco_example With Placeholder
14
+ # = daisy_text_area(name: "message", placeholder: "Enter your message here...")
15
+ #
16
+ # @loco_example With Initial Value
17
+ # = daisy_text_area(name: "message", value: "Initial text content")
18
+ #
19
+ # @loco_example With Specified Rows
20
+ # = daisy_text_area(name: "message", rows: 6)
21
+ #
22
+ # @loco_example With Border Style
23
+ # = daisy_text_area(name: "message", css: "textarea-bordered")
24
+ #
25
+ # @loco_example Different Colors
26
+ # .flex.flex-col.gap-4
27
+ # = daisy_text_area(name: "primary", placeholder: "Primary", css: "textarea-primary textarea-bordered")
28
+ # = daisy_text_area(name: "secondary", placeholder: "Secondary", css: "textarea-secondary textarea-bordered")
29
+ # = daisy_text_area(name: "accent", placeholder: "Accent", css: "textarea-accent textarea-bordered")
30
+ #
31
+ # @loco_example Disabled TextArea
32
+ # = daisy_text_area(name: "message", disabled: true, css: "textarea-bordered")
33
+ #
34
+ # @loco_example Required TextArea
35
+ # = daisy_text_area(name: "message", required: true, css: "textarea-bordered")
36
+ #
37
+ # @loco_example Readonly TextArea
38
+ # = daisy_text_area(name: "message", readonly: true, value: "This content cannot be edited.", css: "textarea-bordered")
39
+ #
40
+ class Daisy::DataInput::TextAreaComponent < LocoMotion::BaseComponent
41
+ attr_reader :name, :id, :value, :placeholder, :rows, :cols, :disabled, :required, :readonly
42
+
43
+ #
44
+ # Instantiate a new TextArea component.
45
+ #
46
+ # @param kws [Hash] The keyword arguments for the component.
47
+ #
48
+ # @option kws name [String] The name attribute for the textarea.
49
+ #
50
+ # @option kws id [String] The ID attribute for the textarea.
51
+ #
52
+ # @option kws value [String] The initial value of the textarea.
53
+ #
54
+ # @option kws placeholder [String] Placeholder text for the textarea.
55
+ #
56
+ # @option kws rows [Integer] The number of visible text lines. Defaults to 4.
57
+ #
58
+ # @option kws cols [Integer] The visible width of the textarea. Defaults to nil.
59
+ #
60
+ # @option kws disabled [Boolean] Whether the textarea is disabled. Defaults to
61
+ # false.
62
+ #
63
+ # @option kws required [Boolean] Whether the textarea is required for form
64
+ # validation. Defaults to false.
65
+ #
66
+ # @option kws readonly [Boolean] Whether the textarea is read-only. Defaults to
67
+ # false.
68
+ #
69
+ def initialize(**kws)
70
+ super
71
+
72
+ @name = config_option(:name)
73
+ @id = config_option(:id)
74
+ @value = config_option(:value, nil)
75
+ @placeholder = config_option(:placeholder, nil)
76
+ @rows = config_option(:rows, 4)
77
+ @cols = config_option(:cols, nil)
78
+ @disabled = config_option(:disabled, false)
79
+ @required = config_option(:required, false)
80
+ @readonly = config_option(:readonly, false)
81
+ end
82
+
83
+ #
84
+ # Calls the {setup_component} method before rendering the component.
85
+ #
86
+ def before_render
87
+ setup_component
88
+ end
89
+
90
+ #
91
+ # Sets up the component by configuring the tag name, CSS classes, and HTML
92
+ # attributes. Sets the tag to textarea and adds the 'textarea' CSS class.
93
+ #
94
+ # This configures various attributes of the textarea including name, id, value,
95
+ # placeholder, rows, cols, and states like disabled, required, and readonly.
96
+ #
97
+ def setup_component
98
+ set_tag_name(:component, :textarea)
99
+
100
+ add_css(:component, "textarea")
101
+
102
+ add_html(:component, {
103
+ name: @name,
104
+ id: @id,
105
+ placeholder: @placeholder,
106
+ rows: @rows,
107
+ cols: @cols,
108
+ disabled: @disabled,
109
+ required: @required,
110
+ readonly: @readonly
111
+ })
112
+ end
113
+
114
+ #
115
+ # Renders the component with its value as content.
116
+ #
117
+ def call
118
+ if @value
119
+ part(:component) { @value }
120
+ else
121
+ part(:component)
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,6 @@
1
+ = part(:component) do
2
+ = start if start?
3
+
4
+ = part(:input)
5
+
6
+ = end_content if end?