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.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +62 -14
  3. data/app/components/daisy/actions/button_component.html.haml +2 -2
  4. data/app/components/daisy/actions/button_component.rb +98 -59
  5. data/app/components/daisy/actions/dropdown_component.html.haml +1 -2
  6. data/app/components/daisy/actions/dropdown_component.rb +7 -10
  7. data/app/components/daisy/actions/modal_component.html.haml +10 -8
  8. data/app/components/daisy/actions/modal_component.rb +6 -6
  9. data/app/components/daisy/actions/swap_component.rb +13 -9
  10. data/app/components/daisy/actions/theme_controller.js +113 -0
  11. data/app/components/daisy/actions/theme_controller_component.rb +58 -17
  12. data/app/components/daisy/actions/theme_preview_component.html.haml +5 -0
  13. data/app/components/daisy/actions/theme_preview_component.rb +68 -0
  14. data/app/components/daisy/data_display/accordion_component.html.haml +0 -1
  15. data/app/components/daisy/data_display/accordion_component.rb +10 -3
  16. data/app/components/daisy/data_display/avatar_component.html.haml +1 -1
  17. data/app/components/daisy/data_display/avatar_component.rb +17 -7
  18. data/app/components/daisy/data_display/badge_component.rb +122 -4
  19. data/app/components/daisy/data_display/card_component.html.haml +1 -1
  20. data/app/components/daisy/data_display/card_component.rb +20 -6
  21. data/app/components/daisy/data_display/chat_component.rb +2 -2
  22. data/app/components/daisy/data_display/collapse_component.rb +9 -5
  23. data/app/components/daisy/data_display/countdown_component.rb +15 -5
  24. data/app/components/daisy/data_display/figure_component.rb +8 -3
  25. data/app/components/daisy/data_display/kbd_component.rb +13 -4
  26. data/app/components/daisy/data_display/list_component.html.haml +5 -0
  27. data/app/components/daisy/data_display/list_component.rb +82 -0
  28. data/app/components/daisy/data_display/list_item_component.rb +39 -0
  29. data/app/components/daisy/data_display/stat_component.html.haml +5 -6
  30. data/app/components/daisy/data_display/stat_component.rb +21 -8
  31. data/app/components/daisy/data_display/status_component.rb +47 -0
  32. data/app/components/daisy/data_display/timeline_component.rb +1 -1
  33. data/app/components/daisy/data_input/cally_component.html.haml +14 -0
  34. data/app/components/daisy/data_input/cally_component.rb +182 -0
  35. data/app/components/daisy/data_input/cally_input_component.html.haml +5 -0
  36. data/app/components/daisy/data_input/cally_input_component.rb +165 -0
  37. data/app/components/daisy/data_input/cally_input_controller.js +235 -0
  38. data/app/components/daisy/data_input/checkbox_component.html.haml +20 -0
  39. data/app/components/daisy/data_input/checkbox_component.rb +106 -0
  40. data/app/components/daisy/data_input/fieldset_component.html.haml +8 -0
  41. data/app/components/daisy/data_input/fieldset_component.rb +57 -0
  42. data/app/components/daisy/data_input/file_input_component.rb +98 -0
  43. data/app/components/daisy/data_input/filter_component.html.haml +3 -0
  44. data/app/components/daisy/data_input/filter_component.rb +221 -0
  45. data/app/components/daisy/data_input/label_component.rb +84 -0
  46. data/app/components/daisy/data_input/radio_button_component.rb +87 -0
  47. data/app/components/daisy/data_input/range_component.rb +95 -0
  48. data/app/components/daisy/data_input/rating_component.html.haml +11 -0
  49. data/app/components/daisy/data_input/rating_component.rb +139 -0
  50. data/app/components/daisy/data_input/select_component.html.haml +27 -0
  51. data/app/components/daisy/data_input/select_component.rb +320 -0
  52. data/app/components/daisy/data_input/text_area_component.rb +127 -0
  53. data/app/components/daisy/data_input/text_input_component.html.haml +27 -0
  54. data/app/components/daisy/data_input/text_input_component.rb +142 -0
  55. data/app/components/daisy/data_input/toggle_component.rb +48 -0
  56. data/app/components/daisy/feedback/alert_component.html.haml +1 -1
  57. data/app/components/daisy/feedback/alert_component.rb +86 -2
  58. data/app/components/daisy/feedback/loading_component.rb +10 -3
  59. data/app/components/daisy/feedback/skeleton_component.rb +1 -1
  60. data/app/components/daisy/layout/divider_component.rb +4 -2
  61. data/app/components/daisy/layout/drawer_component.html.haml +0 -1
  62. data/app/components/daisy/layout/footer_component.rb +6 -6
  63. data/app/components/daisy/mockup/device_component.rb +15 -18
  64. data/app/components/daisy/navigation/breadcrumbs_component.html.haml +0 -1
  65. data/app/components/daisy/navigation/breadcrumbs_component.rb +84 -9
  66. data/app/components/daisy/navigation/dock_component.rb +146 -0
  67. data/app/components/daisy/navigation/link_component.rb +18 -9
  68. data/app/components/daisy/navigation/menu_component.rb +15 -9
  69. data/app/components/daisy/navigation/navbar_component.html.haml +1 -1
  70. data/app/components/daisy/navigation/navbar_component.rb +2 -13
  71. data/app/components/daisy/navigation/steps_component.rb +6 -6
  72. data/app/components/daisy/navigation/tabs_component.html.haml +0 -1
  73. data/app/components/daisy/navigation/tabs_component.rb +26 -16
  74. data/app/components/hero/icon_component.rb +15 -5
  75. data/app/helpers/daisy/form_builder_helper.rb +186 -0
  76. data/app/views/examples/daisy/data_input/filters.html.haml +62 -0
  77. data/lib/daisy.rb +5 -0
  78. data/lib/hero.rb +1 -1
  79. data/lib/loco_motion/base_component.rb +53 -3
  80. data/lib/loco_motion/component_config.rb +1 -0
  81. data/lib/loco_motion/concerns/iconable_component.rb +134 -0
  82. data/lib/loco_motion/concerns/labelable_component.rb +142 -0
  83. data/lib/loco_motion/concerns/linkable_component.rb +40 -0
  84. data/lib/loco_motion/concerns/tippable_component.rb +25 -10
  85. data/lib/loco_motion/engine.rb +6 -0
  86. data/lib/loco_motion/helpers.rb +38 -17
  87. data/lib/loco_motion/patches/view_component/slot_loco_parent_patch.rb +37 -0
  88. data/lib/loco_motion/patches/view_component/slotable_default_patch.rb +21 -0
  89. data/lib/loco_motion/version.rb +1 -1
  90. data/lib/loco_motion.rb +12 -2
  91. metadata +93 -21
  92. data/app/components/daisy/actions/theme_controller_component.html.haml +0 -5
  93. data/app/components/daisy/layout/artboard_component.rb +0 -59
  94. data/app/components/daisy/navigation/bottom_nav_component.rb +0 -138
@@ -27,9 +27,9 @@
27
27
  # %p
28
28
  # Press
29
29
  # = daisy_kbd("Alt")
30
- # +
30
+ # +
31
31
  # = daisy_kbd("Shift")
32
- # +
32
+ # +
33
33
  # = daisy_kbd("M")
34
34
  # to open the menu.
35
35
  #
@@ -42,10 +42,12 @@
42
42
  # to confirm.
43
43
  #
44
44
  class Daisy::DataDisplay::KbdComponent < LocoMotion::BaseComponent
45
- prepend LocoMotion::Concerns::TippableComponent
45
+ include LocoMotion::Concerns::TippableComponent
46
46
 
47
47
  set_component_name :kbd
48
48
 
49
+ attr_reader :simple_title
50
+
49
51
  #
50
52
  # Creates a new kbd component.
51
53
  #
@@ -53,13 +55,20 @@ class Daisy::DataDisplay::KbdComponent < LocoMotion::BaseComponent
53
55
  #
54
56
  # @param kws [Hash] The keyword arguments for the component.
55
57
  #
58
+ # @option kws [String] :tip The tooltip text to display when hovering over
59
+ # the component.
60
+ #
56
61
  def initialize(*args, **kws, &block)
57
62
  super
58
63
 
64
+ @simple_title = args[0]
65
+
59
66
  set_tag_name(:component, :span)
60
67
  end
61
68
 
62
69
  def before_render
70
+ super
71
+
63
72
  setup_component
64
73
  end
65
74
 
@@ -71,7 +80,7 @@ class Daisy::DataDisplay::KbdComponent < LocoMotion::BaseComponent
71
80
  # additional whitespace gets added to the output.
72
81
  #
73
82
  def call
74
- part(:component) { content }
83
+ part(:component) { content || simple_title }
75
84
  end
76
85
 
77
86
  private
@@ -0,0 +1,5 @@
1
+ = part :component do
2
+ = header if header?
3
+ - items.each do |item|
4
+ = item
5
+ = content
@@ -0,0 +1,82 @@
1
+ #
2
+ # The List component is a vertical layout to display information in rows. It can
3
+ # contain various content types including text, images, and actions arranged in a
4
+ # consistent format.
5
+ #
6
+ # The List component is useful for displaying structured data like user profiles,
7
+ # media libraries, or content collections with a consistent layout.
8
+ #
9
+ # @part component The main list container (ul element)
10
+ # @part header The optional header container for the list
11
+ #
12
+ # @slot item+ {Daisy::DataDisplay::ListItemComponent} Individual list items or
13
+ # rows in the list
14
+ #
15
+ # @loco_example Basic Usage
16
+ # = daisy_list do |list|
17
+ # - list.with_item { "Item 1" }
18
+ # - list.with_item { "Item 2" }
19
+ # - list.with_item { "Item 3" }
20
+ #
21
+ # @loco_example With Header
22
+ # = daisy_list(header: "Featured Items") do |list|
23
+ # - list.with_item { "Featured Item 1" }
24
+ # - list.with_item { "Featured Item 2" }
25
+ # - list.with_item { "Featured Item 3" }
26
+ #
27
+ # @loco_example With Rich Content
28
+ # = daisy_list(header: "Most played songs", css: "bg-base-100 rounded-box shadow-md") do |list|
29
+ # - list.with_item do |item|
30
+ # .flex.items-center.gap-2
31
+ # = image_tag("album_cover.jpg", class: "size-10 rounded-box")
32
+ # .flex.flex-col
33
+ # .font-medium Song Title
34
+ # .text-xs.opacity-60 Artist Name
35
+ # = daisy_button(icon: "play", css: "btn-ghost btn-square")
36
+ #
37
+ # @loco_example With Dividers
38
+ # = daisy_list(css: "divide-y") do |list|
39
+ # - list.with_item { "Item with divider below" }
40
+ # - list.with_item { "Another divided item" }
41
+ # - list.with_item { "Last item" }
42
+ #
43
+ # @!parse class Daisy::DataDisplay::ListComponent < LocoMotion::BaseComponent; end
44
+ class Daisy::DataDisplay::ListComponent < LocoMotion::BaseComponent
45
+ renders_many :items, "Daisy::DataDisplay::ListItemComponent"
46
+ renders_one :header, LocoMotion::BasicComponent.build(tag_name: :li)
47
+
48
+ set_component_name :list
49
+
50
+ # @return [String] Optional header text for the list
51
+ attr_reader :simple_header, :header_css, :header_html
52
+
53
+ #
54
+ # Create a new List component.
55
+ #
56
+ # @param kwargs [Hash] The keyword arguments for the component.
57
+ #
58
+ # @option kwargs [String] :header Optional header text to display at the top
59
+ # of the list.
60
+ #
61
+ # @option kwargs [String] :css Additional CSS classes to apply to the list.
62
+ # Common options include:
63
+ # - `bg-base-100` for background color
64
+ # - `rounded-box` for rounded corners
65
+ # - `shadow-md` for drop shadow
66
+ # - `divide-y` for dividers between items
67
+ #
68
+ def initialize(**kws, &block)
69
+ super
70
+
71
+ @simple_header = config_option(:header)
72
+ @header_css = config_option(:header_css)
73
+ @header_html = config_option(:header_html)
74
+ end
75
+
76
+ def before_render
77
+ add_css(:component, "list")
78
+ set_tag_name(:component, :ul)
79
+
80
+ with_header(tag_name: :li, css: header_css, html: header_html) { simple_header } if simple_header && !header?
81
+ end
82
+ end
@@ -0,0 +1,39 @@
1
+ #
2
+ # The ListItem component represents an individual row within a List component.
3
+ # It provides a consistent layout for displaying content in a list format.
4
+ #
5
+ # @part image Optional image container for the item
6
+ #
7
+ # @loco_example Basic Usage
8
+ # = daisy_list do |list|
9
+ # - list.with_item { "Simple list item" }
10
+ #
11
+ # @loco_example With Image
12
+ # = daisy_list do |list|
13
+ # - list.with_item do
14
+ # = image_tag(src: "profile.jpg", class: "rounded-full size-8")
15
+ # User Profile
16
+ #
17
+ # @!parse class Daisy::DataDisplay::ListItemComponent < LocoMotion::BaseComponent; end
18
+ class Daisy::DataDisplay::ListItemComponent < LocoMotion::BaseComponent
19
+ #
20
+ # Create a new ListItem component.
21
+ #
22
+ # @param kwargs [Hash] The keyword arguments for the component.
23
+ #
24
+ # @option kwargs [String] :css Additional CSS classes to apply to the list item.
25
+ #
26
+ def initialize(**kwargs, &block)
27
+ super
28
+ end
29
+
30
+ # Called before rendering to setup the component CSS and structure
31
+ def before_render
32
+ set_tag_name(:component, :li)
33
+ add_css(:component, "list-row")
34
+ end
35
+
36
+ def call
37
+ part(:component) { content }
38
+ end
39
+ end
@@ -4,17 +4,17 @@
4
4
  = part(:figure) do
5
5
  - if figure?
6
6
  = figure
7
- - if @icon.present?
8
- = heroicon_tag(@icon, class: "inline-block h-8 w-8 stroke-current")
7
+
8
+ = render_icon
9
+
9
10
  - if @src.present?
10
11
  = daisy_avatar(src: @src)
11
-
12
12
 
13
13
  - if title?
14
14
  = title
15
15
  - elsif @simple_title.present?
16
16
  = part(:title) do
17
- = @simple_title
17
+ = @simple_title
18
18
 
19
19
  = part(:value) do
20
20
  = content
@@ -23,5 +23,4 @@
23
23
  = description
24
24
  - elsif @simple_description.present?
25
25
  = part(:description) do
26
- = @simple_description
27
-
26
+ = @simple_description
@@ -3,6 +3,9 @@
3
3
  # description, and figure. It's perfect for dashboards, summaries, or any
4
4
  # situation where you need to highlight important numbers or metrics.
5
5
  #
6
+ # @note Stats have a transparent background by default. Use `bg-base-100` if you
7
+ # need a background color.
8
+ #
6
9
  # Includes the {LocoMotion::Concerns::TippableComponent} module to enable easy
7
10
  # tooltip addition.
8
11
  #
@@ -21,27 +24,29 @@
21
24
  # image via the src option or an icon via the icon option.
22
25
  #
23
26
  # @loco_example Basic Usage
24
- # = daisy_stat(title: "Downloads", value: "31K", css: "bg-base-200")
27
+ # = daisy_stat(title: "Downloads", value: "31K")
25
28
  #
26
29
  # @loco_example With Description
27
- # = daisy_stat(title: "New Users", value: "2.6K", description: "↗︎ 400 (22%)", css: "bg-base-200")
30
+ # = daisy_stat(title: "New Users", value: "2.6K", description: "↗︎ 400 (22%)")
28
31
  #
29
32
  # @loco_example With Icon
30
- # = daisy_stat(title: "Page Views", value: "89,400", icon: "eye", css: "bg-base-200") do |stat|
33
+ # = daisy_stat(title: "Page Views", value: "89,400", icon: "eye") do |stat|
31
34
  # = stat.with_description do
32
35
  # .flex.items-center.gap-1
33
- # = heroicon_tag "arrow-up", class: "size-4 text-success"
36
+ # = heroicon "arrow-up", class: "size-4 text-success"
34
37
  # %span.text-success 14%
35
38
  # from last month
36
39
  #
37
40
  # @loco_example With Custom Figure
38
- # = daisy_stat(title: "Success Rate", value: "98%", css: "bg-base-200") do |stat|
41
+ # = daisy_stat(title: "Success Rate", value: "98%") do |stat|
39
42
  # = stat.with_figure do
40
43
  # .text-success
41
- # = heroicon_tag "check-circle", class: "size-10"
44
+ # = heroicon "check-circle", class: "size-10"
42
45
  #
43
46
  class Daisy::DataDisplay::StatComponent < LocoMotion::BaseComponent
44
- prepend LocoMotion::Concerns::TippableComponent
47
+ include LocoMotion::Concerns::IconableComponent
48
+ include LocoMotion::Concerns::LinkableComponent
49
+ include LocoMotion::Concerns::TippableComponent
45
50
 
46
51
  set_component_name :stat
47
52
 
@@ -76,17 +81,25 @@ class Daisy::DataDisplay::StatComponent < LocoMotion::BaseComponent
76
81
  # @option kws [String] :icon Name of a heroicon to display in the figure
77
82
  # section.
78
83
  #
84
+ # @option kws [String] :tip The tooltip text to display when hovering over
85
+ # the component.
86
+ #
79
87
  def initialize(*args, **kws, &block)
80
88
  super
81
89
 
82
90
  @simple_title = config_option(:title)
83
91
  @simple_description = config_option(:description)
84
92
  @src = config_option(:src)
85
- @icon = config_option(:icon)
86
93
  end
87
94
 
88
95
  def before_render
89
96
  setup_component
97
+
98
+ super
99
+ end
100
+
101
+ def default_icon_size
102
+ "where:size-8"
90
103
  end
91
104
 
92
105
  private
@@ -0,0 +1,47 @@
1
+ #
2
+ # The StatusComponent displays a small icon to visually show the current status of an element,
3
+ # such as online, offline, error, etc. It follows the DaisyUI status component pattern.
4
+ #
5
+ # @loco_example Basic Status
6
+ # = daisy_status()
7
+ #
8
+ # @loco_example Status with Size
9
+ # = daisy_status(css: "status-xs")
10
+ # = daisy_status(css: "status-sm")
11
+ # = daisy_status(css: "status-md")
12
+ # = daisy_status(css: "status-lg")
13
+ # = daisy_status(css: "status-xl")
14
+ #
15
+ # @loco_example Status with Color
16
+ # = daisy_status(css: "status-primary")
17
+ # = daisy_status(css: "status-secondary")
18
+ # = daisy_status(css: "status-accent")
19
+ # = daisy_status(css: "status-info")
20
+ # = daisy_status(css: "status-success")
21
+ # = daisy_status(css: "status-warning")
22
+ # = daisy_status(css: "status-error")
23
+ #
24
+ # @loco_example Status with Accessibility
25
+ # = daisy_status(css: "status-success", html: { aria: { label: "Status: Online" } })
26
+ class Daisy::DataDisplay::StatusComponent < LocoMotion::BaseComponent
27
+ include LocoMotion::Concerns::TippableComponent
28
+
29
+ def initialize(**kws)
30
+ super(**kws)
31
+ end
32
+
33
+ def before_render
34
+ setup_component
35
+ super # Call super after setup
36
+ end
37
+
38
+ def call
39
+ part(:component)
40
+ end
41
+
42
+ private
43
+
44
+ def setup_component
45
+ add_css(:component, "status")
46
+ end
47
+ end
@@ -37,7 +37,7 @@
37
37
  #
38
38
  # - event.with_middle do
39
39
  # .bg-primary.text-primary-content.p-2.rounded-full
40
- # = heroicon_tag "star"
40
+ # = heroicon "star"
41
41
  #
42
42
  # - event.with_end do
43
43
  # %h3.font-bold Milestone Reached
@@ -0,0 +1,14 @@
1
+ = part(:component) do
2
+ = previous_icon if previous_icon?
3
+ = next_icon if next_icon?
4
+
5
+ - if @month_count
6
+ = part(:months) do
7
+ - @month_count.times do |index|
8
+ = render(MonthComponent.new(**month_options(index)))
9
+
10
+ - elsif months?
11
+ = months
12
+
13
+ - else
14
+ = content
@@ -0,0 +1,182 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Daisy
4
+ module DataInput
5
+ # The Cally component provides a customizable calendar interface for date selection.
6
+ # It supports both single date and date range selection, with configurable display
7
+ # options including the number of months to show and navigation controls.
8
+ #
9
+ # @part component The root calendar element that contains all other parts.
10
+ # @part months The container element that holds the individual month components.
11
+ #
12
+ # @slot previous_icon [PreviousIcon] The icon used for navigating to the
13
+ # previous month. Defaults to a chevron-left icon.
14
+ # @see #default_previous_icon
15
+ # @slot next_icon [NextIcon] The icon used for navigating to the next month.
16
+ # Defaults to a chevron-right icon.
17
+ # @see #default_next_icon
18
+ # @slot months+ [MonthComponent] The month components to display in the calendar.
19
+ # Multiple months can be displayed side by side.
20
+ # @see #month_options
21
+ #
22
+ # @loco_example Basic calendar with default options
23
+ # = daisy_cally
24
+ #
25
+ # @loco_example Calendar with range selection enabled
26
+ # = daisy_cally(modifier: :range)
27
+ #
28
+ # @loco_example Calendar showing multiple months with custom value
29
+ # = daisy_cally(months: 2, value: Date.today)
30
+ #
31
+ # @loco_example Calendar with min/max date constraints
32
+ # = daisy_cally(min: 1.month.ago, max: 1.month.from_now)
33
+ class CallyComponent < LocoMotion::BaseComponent
34
+ include ViewComponent::SlotableDefault
35
+
36
+ # A component for the previous navigation icon in the calendar header.
37
+ #
38
+ # @note This is used internally by CallyComponent
39
+ class PreviousIcon < Hero::IconComponent
40
+ def before_render
41
+ super
42
+
43
+ add_html(:component, { slot: "previous" })
44
+ end
45
+ end
46
+
47
+ # A component for the next navigation icon in the calendar header.
48
+ #
49
+ # @note This is used internally by CallyComponent
50
+ class NextIcon < Hero::IconComponent
51
+ def before_render
52
+ super
53
+
54
+ add_html(:component, { slot: "next" })
55
+ end
56
+ end
57
+
58
+ # A component representing a single month in the calendar.
59
+ #
60
+ # @note This is used internally by CallyComponent
61
+ class MonthComponent < LocoMotion::BaseComponent
62
+ # @param offset [Integer, nil] The offset of this month from the start date
63
+ def initialize(**kws)
64
+ super
65
+
66
+ @offset = config_option(:offset)
67
+ end
68
+
69
+ def before_render
70
+ super
71
+
72
+ set_tag_name(:component, "calendar-month")
73
+ add_html(:component, { offset: @offset }) if @offset
74
+ end
75
+
76
+ def call
77
+ part(:component)
78
+ end
79
+ end
80
+
81
+ define_modifiers :range
82
+
83
+ renders_one :previous_icon, PreviousIcon
84
+ renders_one :next_icon, NextIcon
85
+ renders_many :months, MonthComponent
86
+
87
+ define_parts :months
88
+
89
+ # Initializes a new CallyComponent.
90
+ #
91
+ # The Cally component provides a customizable calendar interface for date
92
+ # selection. It supports single date selection by default and can be
93
+ # configured for date range selection. The component automatically
94
+ # handles navigation between months and can display multiple months.
95
+ #
96
+ # @param change [String] ID of an input to update with the selected date.
97
+ # Mutually exclusive with `update`.
98
+ # @param update [String] ID of an element to update with the selected
99
+ # date. Mutually exclusive with `change`.
100
+ # @param id [String] The ID of the calendar element
101
+ # @param value [String, Date] The currently selected date or range
102
+ # @param min [String, Date] The minimum selectable date
103
+ # @param max [String, Date] The maximum selectable date
104
+ # @param today [String, Date] The date to consider as 'today'
105
+ # @param months [Integer] Number of months to display (default: 1)
106
+ def initialize(**kws)
107
+ super
108
+
109
+ # If we don't have any modifiers, assume we want a single month for a date select
110
+ @month_count = config_option(:months, modifiers.blank? ? 1 : nil)
111
+ @change = config_option(:change)
112
+ @update = config_option(:update)
113
+
114
+ @id = config_option(:id)
115
+ @value = config_option(:value)
116
+ @min = config_option(:min)
117
+ @max = config_option(:max)
118
+ @today = config_option(:today)
119
+ end
120
+
121
+ # Configures the calendar component before rendering.
122
+ #
123
+ # Sets up the appropriate tag name based on whether range selection is
124
+ # enabled, adds CSS classes, and configures HTML attributes for the
125
+ # calendar component.
126
+ def before_render
127
+ super
128
+
129
+ if modifiers.include?(:range)
130
+ set_tag_name(:component, "calendar-range")
131
+ else
132
+ set_tag_name(:component, "calendar-date")
133
+ end
134
+
135
+ add_css(:component, "cally")
136
+ add_html(:component, { months: @month_count }) if @month_count
137
+
138
+ add_html(:component, {
139
+ id: @id,
140
+ value: @value,
141
+ min: @min,
142
+ max: @max,
143
+ today: @today
144
+ })
145
+
146
+ if @change
147
+ add_html(:component, { onchange: "document.getElementById('#{@change}').value = this.value" })
148
+ end
149
+
150
+ if @update
151
+ add_html(:component, { onchange: "document.getElementById('#{@update}').innerHTML = this.value" })
152
+ end
153
+ end
154
+
155
+ # Generates options for a month component at the given index.
156
+ #
157
+ # @param index [Integer] The 0-based index of the month
158
+ # @return [Hash] Options hash for the month component
159
+ def month_options(index)
160
+ options = {}
161
+
162
+ options[:offset] = index if index > 0
163
+
164
+ options
165
+ end
166
+
167
+ # Provides a default previous icon if none is specified.
168
+ #
169
+ # @return [PreviousIcon] A chevron-left icon
170
+ def default_previous_icon
171
+ PreviousIcon.new(icon: "chevron-left")
172
+ end
173
+
174
+ # Provides a default next icon if none is specified.
175
+ #
176
+ # @return [NextIcon] A chevron-right icon
177
+ def default_next_icon
178
+ NextIcon.new(icon: "chevron-right")
179
+ end
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,5 @@
1
+ = part(:component) do
2
+ = input
3
+
4
+ = part(:popover) do
5
+ = calendar