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
@@ -1,15 +1,85 @@
1
1
  #
2
- # The Table component is used to render HTML tables with rows, columns, and headers.
2
+ # The Table component creates structured data tables with support for headers,
3
+ # multiple sections, and complex layouts. It provides a clean, semantic way to
4
+ # display tabular data while maintaining proper HTML structure.
5
+ #
6
+ # @slot head A header section containing column titles.
7
+ # @slot body A body section containing rows of data.
8
+ # @slot row+ Individual rows that can be added directly to the table.
9
+ # @slot section+ Multiple sections, each with its own header and body, for
10
+ # complex table layouts.
11
+ #
12
+ # @loco_example Basic Usage
13
+ # = daisy_table do |table|
14
+ # - table.with_head do |head|
15
+ # - head.with_column { "Name" }
16
+ # - head.with_column { "Role" }
17
+ # - head.with_column { "Department" }
18
+ #
19
+ # - table.with_row do |row|
20
+ # - row.with_column { "John Smith" }
21
+ # - row.with_column { "Developer" }
22
+ # - row.with_column { "Engineering" }
23
+ #
24
+ # - table.with_row do |row|
25
+ # - row.with_column { "Jane Doe" }
26
+ # - row.with_column { "Designer" }
27
+ # - row.with_column { "Product" }
28
+ #
29
+ # @loco_example With Body Container
30
+ # = daisy_table do |table|
31
+ # - table.with_head do |head|
32
+ # - head.with_column { "Product" }
33
+ # - head.with_column { "Price" }
34
+ #
35
+ # - table.with_body do |body|
36
+ # - body.with_row do |row|
37
+ # - row.with_column { "Basic Plan" }
38
+ # - row.with_column { "$10/mo" }
39
+ # - body.with_row do |row|
40
+ # - row.with_column { "Pro Plan" }
41
+ # - row.with_column { "$20/mo" }
42
+ #
43
+ # @loco_example With Multiple Sections
44
+ # = daisy_table do |table|
45
+ # - table.with_section do |section|
46
+ # - section.with_head do |head|
47
+ # - head.with_column { "Active Users" }
48
+ # - head.with_column { "Status" }
49
+ #
50
+ # - section.with_body do |body|
51
+ # - body.with_row do |row|
52
+ # - row.with_column { "Alice" }
53
+ # - row.with_column { "Online" }
54
+ #
55
+ # - table.with_section do |section|
56
+ # - section.with_head do |head|
57
+ # - head.with_column { "Inactive Users" }
58
+ # - head.with_column { "Last Seen" }
59
+ #
60
+ # - section.with_body do |body|
61
+ # - body.with_row do |row|
62
+ # - row.with_column { "Bob" }
63
+ # - row.with_column { "2 days ago" }
3
64
  #
4
- # @!parse class Daisy::DataDisplay::TableComponent < LocoMotion::BaseComponent; end
5
65
  class Daisy::DataDisplay::TableComponent < LocoMotion::BaseComponent
6
66
 
67
+ #
68
+ # A component for rendering individual header cells (`<th>`) within a table
69
+ # header row.
70
+ #
7
71
  class HeadColumnComponent < LocoMotion::BasicComponent
8
72
  def before_render
9
73
  set_tag_name :component, :th
10
74
  end
11
75
  end
12
76
 
77
+ #
78
+ # A component for rendering the table header (`<thead>`) section. Contains
79
+ # header columns that define the structure of the table.
80
+ #
81
+ # @slot column+ Individual header cells within the header row.
82
+ #
13
83
  class HeadComponent < LocoMotion::BasicComponent
14
84
  renders_many :columns, HeadColumnComponent
15
85
 
@@ -28,12 +98,20 @@ class Daisy::DataDisplay::TableComponent < LocoMotion::BaseComponent
28
98
  end
29
99
  end
30
100
 
101
+ #
102
+ # A component for rendering individual data cells (`<td>`) within a table row.
103
+ #
31
104
  class BodyColumnComponent < LocoMotion::BasicComponent
32
105
  def before_render
33
106
  set_tag_name :component, :td
34
107
  end
35
108
  end
36
109
 
110
+ #
111
+ # A component for rendering table rows (`<tr>`) containing data cells.
112
+ #
113
+ # @slot column+ Individual data cells within the row.
114
+ #
37
115
  class BodyRowComponent < LocoMotion::BasicComponent
38
116
  renders_many :columns, BodyColumnComponent
39
117
 
@@ -50,6 +128,12 @@ class Daisy::DataDisplay::TableComponent < LocoMotion::BaseComponent
50
128
  end
51
129
  end
52
130
 
131
+ #
132
+ # A component for rendering the table body (`<tbody>`) section. Contains rows
133
+ # of data.
134
+ #
135
+ # @slot row+ Individual rows of data within the body.
136
+ #
53
137
  class BodyComponent < LocoMotion::BasicComponent
54
138
  renders_many :rows, BodyRowComponent
55
139
 
@@ -59,15 +143,21 @@ class Daisy::DataDisplay::TableComponent < LocoMotion::BaseComponent
59
143
 
60
144
  def call
61
145
  part(:component) do
62
- content_tag(:tr) do
63
- rows.each do |row|
64
- concat(row)
65
- end
146
+ rows.each do |row|
147
+ concat(row)
66
148
  end
67
149
  end
68
150
  end
69
151
  end
70
152
 
153
+ #
154
+ # A component for grouping related table content into sections. Each section
155
+ # can have its own header and body, allowing for complex table layouts.
156
+ #
157
+ # @slot head A header section for this group of data.
158
+ # @slot body A body section for this group of data.
159
+ # @slot row+ Individual rows that can be added directly to this section.
160
+ #
71
161
  class SectionComponent < LocoMotion::BasicComponent
72
162
  renders_one :head, HeadComponent
73
163
  renders_one :body, BodyComponent
@@ -78,7 +168,7 @@ class Daisy::DataDisplay::TableComponent < LocoMotion::BaseComponent
78
168
  end
79
169
 
80
170
  def call
81
- # Sections can't be rendered inside a <table> tag, so we don't render the
171
+ # Sections can't be rendered inside a `<table>` tag, so we don't render the
82
172
  # typical `part(:component)` here.
83
173
  concat(head) if head?
84
174
 
@@ -103,33 +193,8 @@ class Daisy::DataDisplay::TableComponent < LocoMotion::BaseComponent
103
193
 
104
194
  #
105
195
  # Instantiate a new Table component. This component takes no content, but
106
- # requires you to utilize the optional <code>head</code> slot, and one of the
107
- # <code>body</code> or <code>rows</code> slots.
108
- #
109
- # @example
110
- # = daisy_table do |table|
111
- # - table.head do |head|
112
- # - head.with_column do
113
- # Column 1
114
- # - head.with_column do
115
- # Column 2
116
- #
117
- # - table.with_row do |row|
118
- # - row.with_column do
119
- # Row 1 - Column 1
120
- # - row.with_column do
121
- # Row 1 - Column 2
122
- # - table.with_row do |row|
123
- # - row.with_column do
124
- # Row 2 - Column 1
125
- # - row.with_column do
126
- # Row 2 - Column 2
127
- #
128
- # For more complex tables, you can use the <code>section</code> slot which
129
- # takes a <code>head</code> and <code>body</code> slot allowing you to build a
130
- # table with multiple headers and bodies.
131
- #
132
- # Please see the demo for more examples of usage.
196
+ # requires you to utilize the optional `head` slot, and one of the `body` or
197
+ # `rows` slots.
133
198
  #
134
199
  def initialize(*args, **kws, &block)
135
200
  super
@@ -1,3 +1,48 @@
1
+ #
2
+ # The Timeline component displays a list of events in chronological order,
3
+ # either vertically or horizontally. It's perfect for showing history,
4
+ # progress, or any sequence of events that should be displayed in order.
5
+ #
6
+ # @slot event+ Individual events in the timeline. Each event can have start,
7
+ # middle, and end sections.
8
+ #
9
+ # @loco_example Basic Vertical Timeline
10
+ # = daisy_timeline do |timeline|
11
+ # - timeline.with_event(start: "2023", end: "Launched product") do |event|
12
+ # - event.with_middle { "🚀" }
13
+ #
14
+ # - timeline.with_event(start: "2024", end: "1M users") do |event|
15
+ # - event.with_middle { "🎉" }
16
+ #
17
+ # @loco_example Horizontal Timeline
18
+ # = daisy_timeline(css: "timeline-horizontal") do |timeline|
19
+ # - timeline.with_event(start: "Q1", end: "Planning") do |event|
20
+ # - event.with_middle { "📋" }
21
+ #
22
+ # - timeline.with_event(start: "Q2", end: "Development") do |event|
23
+ # - event.with_middle { "💻" }
24
+ #
25
+ # - timeline.with_event(start: "Q3", end: "Testing") do |event|
26
+ # - event.with_middle { "🧪" }
27
+ #
28
+ # - timeline.with_event(start: "Q4", end: "Launch") do |event|
29
+ # - event.with_middle { "🚀" }
30
+ #
31
+ # @loco_example Custom Content (Vertical)
32
+ # = daisy_timeline do |timeline|
33
+ # - timeline.with_event do |event|
34
+ # - event.with_start do
35
+ # .font-bold Jan 2024
36
+ # %div{ class: "text-sm text-base-content/70" } Q1
37
+ #
38
+ # - event.with_middle do
39
+ # .bg-primary.text-primary-content.p-2.rounded-full
40
+ # = heroicon_tag "star"
41
+ #
42
+ # - event.with_end do
43
+ # %h3.font-bold Milestone Reached
44
+ # %div{ class: "text-base-content/70" } Exceeded quarterly goals
45
+ #
1
46
  class Daisy::DataDisplay::TimelineComponent < LocoMotion::BaseComponent
2
47
  renders_many :events, Daisy::DataDisplay::TimelineEventComponent
3
48
 
@@ -1,3 +1,27 @@
1
+ #
2
+ # A component for rendering individual events within a timeline. Each event can
3
+ # have three sections: start (typically a date or time), middle (an icon or
4
+ # marker), and end (the event description).
5
+ #
6
+ # @part start The container for the start content (e.g., date/time).
7
+ # @part middle The container for the middle content.
8
+ # @part middle_icon Container for a simple icon when not using custom middle
9
+ # content.
10
+ # @part end The container for the end content (e.g., description).
11
+ # @part separator The line connecting this event to the next one.
12
+ #
13
+ # @slot start Custom content for the start section. You can also provide
14
+ # simple text via the start option.
15
+ #
16
+ # @slot middle Custom content for the middle section. You can also provide
17
+ # simple text via the middle option, or an icon via the middle_icon option.
18
+ #
19
+ # @slot end Custom content for the end section. You can also provide simple
20
+ # text via the end option.
21
+ #
22
+ # @note The middle and middle_icon options are mutually exclusive. If both are
23
+ # provided, middle takes precedence.
24
+ #
1
25
  class Daisy::DataDisplay::TimelineEventComponent < LocoMotion::BaseComponent
2
26
  renders_one :start, LocoMotion::BasicComponent.build(css: "timeline-start")
3
27
  renders_one :middle, LocoMotion::BasicComponent.build(css: "timeline-middle")
@@ -6,7 +30,21 @@ class Daisy::DataDisplay::TimelineEventComponent < LocoMotion::BaseComponent
6
30
  define_parts :start, :middle, :middle_icon, :end, :separator
7
31
 
8
32
  #
9
- # middle and middle_icon are mutually exclusive, middle takes presedence
33
+ # Creates a new timeline event component.
34
+ #
35
+ # @param kws [Hash] The keyword arguments for the component.
36
+ #
37
+ # @option kws [String] :start Text to display in the start section. You can
38
+ # also provide custom content using the start slot.
39
+ #
40
+ # @option kws [String] :middle Text to display in the middle section. You
41
+ # can also provide custom content using the middle slot.
42
+ #
43
+ # @option kws [String] :middle_icon Name of a heroicon to display in the
44
+ # middle section. Ignored if middle is provided.
45
+ #
46
+ # @option kws [String] :end Text to display in the end section. You can
47
+ # also provide custom content using the end slot.
10
48
  #
11
49
  def initialize(*args, **kws, &block)
12
50
  super(*args, **kws, &block)
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # The Checkbox component renders a DaisyUI styled checkbox input.
5
+ # It can be used standalone or with a form builder, and supports various styling
6
+ # options including toggle mode for switch-like appearance.
7
+ #
8
+ # @loco_example Basic Usage
9
+ # = daisy_checkbox(name: "accept", id: "accept")
10
+ #
11
+ # @loco_example Checked Checkbox
12
+ # = daisy_checkbox(name: "accept", id: "accept", checked: true)
13
+ #
14
+ # @loco_example Toggle Checkbox
15
+ # = daisy_checkbox(name: "accept", id: "accept", toggle: true)
16
+ #
17
+ # @loco_example Disabled Checkbox
18
+ # = daisy_checkbox(name: "accept", id: "accept", disabled: true)
19
+ #
20
+ class Daisy::DataInput::CheckboxComponent < LocoMotion::BaseComponent
21
+ attr_reader :name, :id, :value, :checked, :toggle, :disabled, :required
22
+
23
+ #
24
+ # Instantiate a new Checkbox component.
25
+ #
26
+ # @param kws [Hash] The keyword arguments for the component.
27
+ #
28
+ # @option kws name [String] The name attribute for the checkbox input.
29
+ #
30
+ # @option kws id [String] The ID attribute for the checkbox input.
31
+ #
32
+ # @option kws value [String] The value attribute for the checkbox input.
33
+ # Defaults to "1".
34
+ #
35
+ # @option kws checked [Boolean] Whether the checkbox is checked. Defaults to
36
+ # false.
37
+ #
38
+ # @option kws toggle [Boolean] Whether the checkbox should be styled as a
39
+ # toggle switch. Defaults to false.
40
+ #
41
+ # @option kws disabled [Boolean] Whether the checkbox is disabled. Defaults to
42
+ # false.
43
+ #
44
+ # @option kws required [Boolean] Whether the checkbox is required for form
45
+ # validation. Defaults to false.
46
+ #
47
+ def initialize(**kws)
48
+ super
49
+
50
+ @name = config_option(:name)
51
+ @id = config_option(:id)
52
+ @value = config_option(:value, "1")
53
+ @checked = config_option(:checked, false)
54
+ @toggle = config_option(:toggle, false)
55
+ @disabled = config_option(:disabled, false)
56
+ @required = config_option(:required, false)
57
+ end
58
+
59
+ #
60
+ # Calls the {setup_component} method before rendering the component.
61
+ #
62
+ def before_render
63
+ setup_component
64
+ end
65
+
66
+ #
67
+ # Sets up the component by configuring the tag name, CSS classes, and HTML
68
+ # attributes.
69
+ #
70
+ def setup_component
71
+ set_tag_name(:component, :input)
72
+
73
+ add_css(:component, @toggle ? "toggle" : "checkbox")
74
+
75
+ add_html(:component, {
76
+ type: "checkbox",
77
+ name: @name,
78
+ id: @id,
79
+ value: @value,
80
+ checked: @checked,
81
+ disabled: @disabled,
82
+ required: @required
83
+ })
84
+ end
85
+
86
+ #
87
+ # Renders the component inline with no additional whitespace.
88
+ #
89
+ def call
90
+ part(:component)
91
+ end
92
+ end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # The FileInput component renders a DaisyUI styled file input.
5
+ # It can be used standalone or with a form builder, and supports
6
+ # various styling options including different sizes and variants.
7
+ #
8
+ # @loco_example Basic Usage
9
+ # = daisy_file_input(name: "document", id: "document")
10
+ #
11
+ # @loco_example With Accept Attribute
12
+ # = daisy_file_input(name: "image", id: "image", accept: "image/*")
13
+ #
14
+ # @loco_example With Multiple Files
15
+ # = daisy_file_input(name: "documents[]", id: "documents", multiple: true)
16
+ #
17
+ # @loco_example Disabled File Input
18
+ # = daisy_file_input(name: "document", id: "document", disabled: true)
19
+ #
20
+ class Daisy::DataInput::FileInputComponent < LocoMotion::BaseComponent
21
+ attr_reader :name, :id, :accept, :multiple, :disabled, :required
22
+
23
+ #
24
+ # Instantiate a new FileInput component.
25
+ #
26
+ # @param kws [Hash] The keyword arguments for the component.
27
+ #
28
+ # @option kws name [String] The name attribute for the file input.
29
+ #
30
+ # @option kws id [String] The ID attribute for the file input.
31
+ #
32
+ # @option kws accept [String] The accept attribute for the file input,
33
+ # specifying allowed file types.
34
+ #
35
+ # @option kws multiple [Boolean] Whether the file input allows multiple file
36
+ # selection. Defaults to false.
37
+ #
38
+ # @option kws disabled [Boolean] Whether the file input is disabled. Defaults to
39
+ # false.
40
+ #
41
+ # @option kws required [Boolean] Whether the file 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
+ @accept = config_option(:accept, nil)
50
+ @multiple = config_option(:multiple, false)
51
+ @disabled = config_option(:disabled, false)
52
+ @required = config_option(:required, false)
53
+ end
54
+
55
+ #
56
+ # Calls the {setup_component} method before rendering the component.
57
+ #
58
+ def before_render
59
+ setup_component
60
+ end
61
+
62
+ #
63
+ # Sets up the component by configuring the tag name, CSS classes, and HTML
64
+ # attributes. Sets the tag to input with type 'file' and adds the 'file-input'
65
+ # CSS class.
66
+ #
67
+ # This configures the name, id, accept attribute, multiple state, disabled state,
68
+ # and required state of the file input.
69
+ #
70
+ def setup_component
71
+ set_tag_name(:component, :input)
72
+
73
+ add_css(:component, "file-input")
74
+
75
+ add_html(:component, {
76
+ type: "file",
77
+ name: @name,
78
+ id: @id,
79
+ accept: @accept,
80
+ multiple: @multiple,
81
+ disabled: @disabled,
82
+ required: @required
83
+ })
84
+ end
85
+
86
+ #
87
+ # Renders the component inline with no additional whitespace.
88
+ #
89
+ def call
90
+ part(:component)
91
+ end
92
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # The Label component renders a DaisyUI styled label for form inputs.
5
+ # It can be used with any form input component and provides visual styling
6
+ # consistent with other Daisy UI elements.
7
+ #
8
+ # @loco_example Basic Usage
9
+ # = daisy_label(for: "input_id") do
10
+ # My Label
11
+ #
12
+ # @loco_example With Label Title
13
+ # = daisy_label(for: "input_id", title: "My Label")
14
+ #
15
+ # @loco_example Required Label
16
+ # = daisy_label(for: "input_id", required: true) do
17
+ # My Required Label
18
+ #
19
+ class Daisy::DataInput::LabelComponent < LocoMotion::BaseComponent
20
+ attr_reader :for, :title, :required
21
+
22
+ #
23
+ # Instantiate a new Label component.
24
+ #
25
+ # @param kws [Hash] The keyword arguments for the component.
26
+ #
27
+ # @option kws for [String] The ID of the input element this label is for.
28
+ # This connects the label to its associated form control for accessibility.
29
+ #
30
+ # @option kws title [String] The text content of the label. If not provided,
31
+ # the content block will be used. If a content block is provided, it will
32
+ # take precedence over the title option.
33
+ #
34
+ # @option kws required [Boolean] Whether the label is for a required input.
35
+ # Defaults to false.
36
+ #
37
+ def initialize(**kws)
38
+ super
39
+
40
+ @for = config_option(:for)
41
+ @title = config_option(:title)
42
+ @required = config_option(:required, false)
43
+ end
44
+
45
+ #
46
+ # Calls the {setup_component} method before rendering the component.
47
+ #
48
+ def before_render
49
+ setup_component
50
+ end
51
+
52
+ #
53
+ # Sets up the component by configuring the tag name, CSS classes, and HTML
54
+ # attributes. Sets the tag to 'label' and adds the 'label' CSS class.
55
+ #
56
+ # This configures the 'for' attribute to connect the label to its input and
57
+ # adds appropriate styling for required inputs when needed.
58
+ #
59
+ def setup_component
60
+ set_tag_name(:component, :label)
61
+
62
+ add_css(:component, "label")
63
+
64
+ add_html(:component, {
65
+ for: @for
66
+ })
67
+ end
68
+
69
+ #
70
+ # Renders the component with its content.
71
+ #
72
+ def call
73
+ part(:component) do
74
+ if content?
75
+ content
76
+ elsif @title
77
+ content_tag(:span, @title, class: "label-text")
78
+ else
79
+ # Fallback to empty content
80
+ ""
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # The Radio Button component renders a DaisyUI styled radio button input.
5
+ # It can be used standalone or with a form builder, and is ideal for creating
6
+ # option groups where users must select exactly one choice.
7
+ #
8
+ # @loco_example Basic Usage
9
+ # = daisy_radio(name: "option", id: "option1", value: "1")
10
+ #
11
+ # @loco_example Checked Radio Button
12
+ # = daisy_radio(name: "option", id: "option2", value: "2", checked: true)
13
+ #
14
+ # @loco_example Disabled Radio Button
15
+ # = daisy_radio(name: "option", id: "option3", value: "3", disabled: true)
16
+ #
17
+ class Daisy::DataInput::RadioButtonComponent < LocoMotion::BaseComponent
18
+ attr_reader :name, :id, :value, :checked, :disabled, :required
19
+
20
+ #
21
+ # Instantiate a new Radio Button component.
22
+ #
23
+ # @param kws [Hash] The keyword arguments for the component.
24
+ #
25
+ # @option kws name [String] The name attribute for the radio button input.
26
+ #
27
+ # @option kws id [String] The ID attribute for the radio button input.
28
+ #
29
+ # @option kws value [String] The value attribute for the radio button input.
30
+ #
31
+ # @option kws checked [Boolean] Whether the radio button is checked. Defaults to
32
+ # false.
33
+ #
34
+ # @option kws disabled [Boolean] Whether the radio button is disabled. Defaults to
35
+ # false.
36
+ #
37
+ # @option kws required [Boolean] Whether the radio button is required for form
38
+ # validation. Defaults to false.
39
+ #
40
+ def initialize(**kws)
41
+ super
42
+
43
+ @name = config_option(:name)
44
+ @id = config_option(:id)
45
+ @value = config_option(:value)
46
+ @checked = config_option(:checked, false)
47
+ @disabled = config_option(:disabled, false)
48
+ @required = config_option(:required, false)
49
+ end
50
+
51
+ #
52
+ # Calls the {setup_component} method before rendering the component.
53
+ #
54
+ def before_render
55
+ setup_component
56
+ end
57
+
58
+ #
59
+ # Sets up the component by configuring the tag name, CSS classes, and HTML
60
+ # attributes. Sets the tag to input with type 'radio' and adds the 'radio' CSS class.
61
+ #
62
+ # This configures the name, id, value, disabled state, required state, and
63
+ # checked state of the radio button.
64
+ #
65
+ def setup_component
66
+ set_tag_name(:component, :input)
67
+
68
+ add_css(:component, "radio")
69
+
70
+ add_html(:component, {
71
+ type: "radio",
72
+ name: @name,
73
+ id: @id,
74
+ value: @value,
75
+ checked: @checked,
76
+ disabled: @disabled,
77
+ required: @required
78
+ })
79
+ end
80
+
81
+ #
82
+ # Renders the component inline with no additional whitespace.
83
+ #
84
+ def call
85
+ part(:component)
86
+ end
87
+ end