maquina-components 0.2.0 → 0.3.1

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +77 -0
  3. data/app/assets/stylesheets/calendar.css +222 -0
  4. data/app/assets/stylesheets/combobox.css +218 -0
  5. data/app/assets/stylesheets/date_picker.css +172 -0
  6. data/app/assets/stylesheets/toast.css +433 -0
  7. data/app/assets/tailwind/maquina_components_engine/engine.css +16 -14
  8. data/app/helpers/maquina_components/calendar_helper.rb +196 -0
  9. data/app/helpers/maquina_components/combobox_helper.rb +300 -0
  10. data/app/helpers/maquina_components/icons_helper.rb +220 -0
  11. data/app/helpers/maquina_components/table_helper.rb +9 -10
  12. data/app/helpers/maquina_components/toast_helper.rb +115 -0
  13. data/app/javascript/controllers/calendar_controller.js +394 -0
  14. data/app/javascript/controllers/combobox_controller.js +325 -0
  15. data/app/javascript/controllers/date_picker_controller.js +261 -0
  16. data/app/javascript/controllers/toast_controller.js +115 -0
  17. data/app/javascript/controllers/toaster_controller.js +226 -0
  18. data/app/views/components/_calendar.html.erb +121 -0
  19. data/app/views/components/_combobox.html.erb +13 -0
  20. data/app/views/components/_date_picker.html.erb +102 -0
  21. data/app/views/components/_toast.html.erb +53 -0
  22. data/app/views/components/_toaster.html.erb +17 -0
  23. data/app/views/components/calendar/_header.html.erb +22 -0
  24. data/app/views/components/calendar/_week.html.erb +53 -0
  25. data/app/views/components/combobox/_content.html.erb +17 -0
  26. data/app/views/components/combobox/_empty.html.erb +9 -0
  27. data/app/views/components/combobox/_group.html.erb +8 -0
  28. data/app/views/components/combobox/_input.html.erb +18 -0
  29. data/app/views/components/combobox/_label.html.erb +8 -0
  30. data/app/views/components/combobox/_list.html.erb +8 -0
  31. data/app/views/components/combobox/_option.html.erb +24 -0
  32. data/app/views/components/combobox/_separator.html.erb +6 -0
  33. data/app/views/components/combobox/_trigger.html.erb +22 -0
  34. data/app/views/components/toast/_action.html.erb +14 -0
  35. data/app/views/components/toast/_description.html.erb +8 -0
  36. data/app/views/components/toast/_title.html.erb +8 -0
  37. data/lib/maquina_components/version.rb +1 -1
  38. metadata +33 -2
@@ -0,0 +1,121 @@
1
+ <%# locals: (selected: nil, selected_end: nil, month: nil, year: nil, mode: :single, min_date: nil, max_date: nil, disabled_dates: [], show_outside_days: true, week_starts_on: :sunday, cell_size: nil, input_name: nil, input_name_end: nil, css_classes: "", **html_options) %>
2
+ <%
3
+ # Parse selected dates
4
+ selected_date = case selected
5
+ when String then Date.parse(selected) rescue nil
6
+ when Date, Time, DateTime then selected.to_date
7
+ else nil
8
+ end
9
+
10
+ selected_end_date = case selected_end
11
+ when String then Date.parse(selected_end) rescue nil
12
+ when Date, Time, DateTime then selected_end.to_date
13
+ else nil
14
+ end
15
+
16
+ # Parse min/max dates
17
+ min_date_parsed = case min_date
18
+ when String then Date.parse(min_date) rescue nil
19
+ when Date, Time, DateTime then min_date.to_date
20
+ else nil
21
+ end
22
+
23
+ max_date_parsed = case max_date
24
+ when String then Date.parse(max_date) rescue nil
25
+ when Date, Time, DateTime then max_date.to_date
26
+ else nil
27
+ end
28
+
29
+ # Determine display month/year
30
+ display_date = selected_date || Date.current
31
+ display_month = month || display_date.month
32
+ display_year = year || display_date.year
33
+
34
+ # Build the calendar data
35
+ first_of_month = Date.new(display_year, display_month, 1)
36
+ last_of_month = first_of_month.end_of_month
37
+
38
+ # Calculate start of calendar grid
39
+ week_start = week_starts_on == :monday ? 1 : 0
40
+ days_before = (first_of_month.wday - week_start) % 7
41
+ calendar_start = first_of_month - days_before.days
42
+
43
+ # Calculate end of calendar grid (6 weeks max)
44
+ total_days = days_before + last_of_month.day
45
+ weeks_needed = (total_days / 7.0).ceil
46
+ weeks_needed = [weeks_needed, 6].min
47
+ calendar_end = calendar_start + (weeks_needed * 7 - 1).days
48
+
49
+ # Build weeks array
50
+ weeks = (calendar_start..calendar_end).each_slice(7).to_a
51
+
52
+ # Weekday names
53
+ weekday_names = week_starts_on == :monday ?
54
+ %w[Mo Tu We Th Fr Sa Su] :
55
+ %w[Su Mo Tu We Th Fr Sa]
56
+
57
+ merged_data = (html_options.delete(:data) || {}).merge(
58
+ controller: "calendar",
59
+ component: "calendar",
60
+ "calendar-mode-value": mode,
61
+ "calendar-month-value": display_month,
62
+ "calendar-year-value": display_year,
63
+ "calendar-selected-value": selected_date&.iso8601,
64
+ "calendar-selected-end-value": selected_end_date&.iso8601,
65
+ "calendar-min-date-value": min_date_parsed&.iso8601,
66
+ "calendar-max-date-value": max_date_parsed&.iso8601,
67
+ "calendar-week-starts-on-value": week_starts_on
68
+ )
69
+
70
+ style_attr = cell_size ? "--cell-size: #{cell_size};" : nil
71
+ %>
72
+
73
+ <%= content_tag :div,
74
+ class: css_classes.presence,
75
+ data: merged_data,
76
+ style: style_attr,
77
+ **html_options do %>
78
+
79
+ <%# Hidden inputs for form integration %>
80
+ <% if input_name %>
81
+ <input type="hidden"
82
+ name="<%= input_name %>"
83
+ value="<%= selected_date&.iso8601 %>"
84
+ data-calendar-target="input">
85
+ <% end %>
86
+ <% if input_name_end && mode == :range %>
87
+ <input type="hidden"
88
+ name="<%= input_name_end %>"
89
+ value="<%= selected_end_date&.iso8601 %>"
90
+ data-calendar-target="inputEnd">
91
+ <% end %>
92
+
93
+ <%# Header with navigation %>
94
+ <%= render "components/calendar/header",
95
+ month: display_month,
96
+ year: display_year,
97
+ month_name: I18n.l(first_of_month, format: "%B %Y") %>
98
+
99
+ <%# Weekday headers %>
100
+ <div data-calendar-part="weekdays">
101
+ <% weekday_names.each do |day_name| %>
102
+ <div data-calendar-part="weekday"><%= day_name %></div>
103
+ <% end %>
104
+ </div>
105
+
106
+ <%# Calendar grid %>
107
+ <div data-calendar-part="grid" role="grid" aria-label="Calendar">
108
+ <% weeks.each do |week_days| %>
109
+ <%= render "components/calendar/week",
110
+ days: week_days,
111
+ display_month: display_month,
112
+ selected_date: selected_date,
113
+ selected_end_date: selected_end_date,
114
+ mode: mode,
115
+ min_date: min_date_parsed,
116
+ max_date: max_date_parsed,
117
+ disabled_dates: disabled_dates,
118
+ show_outside_days: show_outside_days %>
119
+ <% end %>
120
+ </div>
121
+ <% end %>
@@ -0,0 +1,13 @@
1
+ <%# locals: (id: nil, name: nil, value: nil, placeholder: "Select...", css_classes: "", **html_options) %>
2
+ <% combobox_id = id || "combobox-#{SecureRandom.hex(4)}" %>
3
+ <% merged_data = (html_options.delete(:data) || {}).merge(
4
+ component: :combobox,
5
+ controller: "combobox",
6
+ combobox_value_value: value,
7
+ combobox_name_value: name,
8
+ combobox_placeholder_value: placeholder
9
+ ) %>
10
+
11
+ <%= content_tag :div, class: css_classes.presence, data: merged_data, **html_options do %>
12
+ <%= yield combobox_id %>
13
+ <% end %>
@@ -0,0 +1,102 @@
1
+ <%# locals: (selected: nil, selected_end: nil, mode: :single, min_date: nil, max_date: nil, disabled_dates: [], show_outside_days: true, week_starts_on: :sunday, placeholder: nil, input_name: nil, input_name_end: nil, id: nil, disabled: false, required: false, css_classes: "", **html_options) %>
2
+ <%
3
+ # Generate unique ID for popover targeting
4
+ component_id = id || "date-picker-#{SecureRandom.hex(4)}"
5
+ popover_id = "#{component_id}-popover"
6
+
7
+ # Parse selected dates for display
8
+ selected_date = case selected
9
+ when String then Date.parse(selected) rescue nil
10
+ when Date, Time, DateTime then selected.to_date
11
+ else nil
12
+ end
13
+
14
+ selected_end_date = case selected_end
15
+ when String then Date.parse(selected_end) rescue nil
16
+ when Date, Time, DateTime then selected_end.to_date
17
+ else nil
18
+ end
19
+
20
+ # Format display value
21
+ display_value = if mode == :range && selected_date && selected_end_date
22
+ "#{I18n.l(selected_date, format: :short)} - #{I18n.l(selected_end_date, format: :short)}"
23
+ elsif mode == :range && selected_date
24
+ "#{I18n.l(selected_date, format: :short)} - ..."
25
+ elsif selected_date
26
+ I18n.l(selected_date, format: :long)
27
+ end
28
+
29
+ default_placeholder = mode == :range ? "Select date range" : "Select date"
30
+
31
+ merged_data = (html_options.delete(:data) || {}).merge(
32
+ controller: "date-picker",
33
+ component: "date-picker",
34
+ "date-picker-mode-value": mode,
35
+ "date-picker-selected-value": selected_date&.iso8601,
36
+ "date-picker-selected-end-value": selected_end_date&.iso8601
37
+ )
38
+ %>
39
+
40
+ <div id="<%= component_id %>"
41
+ class="<%= css_classes.presence %>"
42
+ data-controller="date-picker"
43
+ data-component="date-picker"
44
+ data-date-picker-mode-value="<%= mode %>"
45
+ data-date-picker-selected-value="<%= selected_date&.iso8601 %>"
46
+ data-date-picker-selected-end-value="<%= selected_end_date&.iso8601 %>">
47
+
48
+ <%# Hidden inputs for form submission %>
49
+ <% if input_name %>
50
+ <input type="hidden"
51
+ name="<%= input_name %>"
52
+ value="<%= selected_date&.iso8601 %>"
53
+ data-date-picker-target="input"
54
+ <%= "required" if required %>>
55
+ <% end %>
56
+ <% if input_name_end && mode == :range %>
57
+ <input type="hidden"
58
+ name="<%= input_name_end %>"
59
+ value="<%= selected_end_date&.iso8601 %>"
60
+ data-date-picker-target="inputEnd">
61
+ <% end %>
62
+
63
+ <%# Trigger button %>
64
+ <button type="button"
65
+ popovertarget="<%= popover_id %>"
66
+ data-date-picker-target="trigger"
67
+ data-date-picker-part="trigger"
68
+ <%= "disabled" if disabled %>
69
+ aria-haspopup="dialog"
70
+ aria-expanded="false">
71
+ <%= icon_for :calendar, class: "size-4" %>
72
+ <span data-date-picker-target="display">
73
+ <%= display_value || placeholder || default_placeholder %>
74
+ </span>
75
+ <% unless display_value %>
76
+ <span data-date-picker-part="placeholder-indicator"></span>
77
+ <% end %>
78
+ </button>
79
+
80
+ <%# Popover with Calendar %>
81
+ <div id="<%= popover_id %>"
82
+ popover
83
+ data-date-picker-target="popover"
84
+ data-date-picker-part="popover"
85
+ role="dialog"
86
+ aria-modal="true"
87
+ aria-label="<%= mode == :range ? 'Date range picker' : 'Date picker' %>">
88
+ <%= render "components/calendar",
89
+ selected: selected_date,
90
+ selected_end: selected_end_date,
91
+ mode: mode,
92
+ min_date: min_date,
93
+ max_date: max_date,
94
+ disabled_dates: disabled_dates,
95
+ show_outside_days: show_outside_days,
96
+ week_starts_on: week_starts_on,
97
+ data: {
98
+ "date-picker-target": "calendar",
99
+ action: "calendar:change->date-picker#handleChange calendar:navigate->date-picker#handleNavigate"
100
+ } %>
101
+ </div>
102
+ </div>
@@ -0,0 +1,53 @@
1
+ <%# locals: (variant: :default, title: nil, description: nil, icon: nil, duration: 5000, dismissible: true, css_classes: "", **html_options) %>
2
+ <%
3
+ # Auto-select icon based on variant if not provided
4
+ default_icons = {
5
+ default: nil,
6
+ success: :circle_check,
7
+ info: :info,
8
+ warning: :triangle_alert,
9
+ error: :circle_x
10
+ }
11
+ toast_icon = icon || default_icons[variant]
12
+ %>
13
+ <% merged_data = (html_options.delete(:data) || {}).merge(
14
+ component: :toast,
15
+ controller: "toast",
16
+ variant: variant,
17
+ toast_duration_value: duration,
18
+ toast_dismissible_value: dismissible,
19
+ state: "entering"
20
+ ) %>
21
+
22
+ <%= content_tag :div,
23
+ role: "alert",
24
+ class: css_classes.presence,
25
+ data: merged_data,
26
+ **html_options do %>
27
+ <% if toast_icon %>
28
+ <div data-toast-part="icon">
29
+ <%= icon_for toast_icon, class: "size-5" %>
30
+ </div>
31
+ <% end %>
32
+
33
+ <div data-toast-part="content">
34
+ <% if title.present? %>
35
+ <%= render "components/toast/title", text: title %>
36
+ <% end %>
37
+
38
+ <% if description.present? %>
39
+ <%= render "components/toast/description", text: description %>
40
+ <% end %>
41
+
42
+ <%= yield if block_given? %>
43
+ </div>
44
+
45
+ <% if dismissible %>
46
+ <button type="button"
47
+ data-toast-part="close"
48
+ data-action="toast#dismiss"
49
+ aria-label="Dismiss notification">
50
+ <%= icon_for :x, class: "size-4" %>
51
+ </button>
52
+ <% end %>
53
+ <% end %>
@@ -0,0 +1,17 @@
1
+ <%# locals: (position: :bottom_right, css_classes: "", **html_options) %>
2
+ <% merged_data = (html_options.delete(:data) || {}).merge(
3
+ component: :toaster,
4
+ controller: "toaster",
5
+ position: position.to_s.dasherize,
6
+ toaster_target: "container"
7
+ ) %>
8
+
9
+ <%= content_tag :div,
10
+ id: "toaster",
11
+ role: "region",
12
+ aria: { label: "Notifications", live: "polite" },
13
+ class: css_classes.presence,
14
+ data: merged_data,
15
+ **html_options do %>
16
+ <%= yield if block_given? %>
17
+ <% end %>
@@ -0,0 +1,22 @@
1
+ <%# locals: (month:, year:, month_name:, css_classes: "", **html_options) %>
2
+ <% merged_data = (html_options.delete(:data) || {}).merge("calendar-part": "header") %>
3
+
4
+ <%= content_tag :div, class: css_classes.presence, data: merged_data, **html_options do %>
5
+ <button type="button"
6
+ data-action="click->calendar#previousMonth"
7
+ data-calendar-target="prevButton"
8
+ aria-label="Previous month">
9
+ <%= icon_for :chevron_left, class: "size-4" %>
10
+ </button>
11
+
12
+ <div data-calendar-part="caption">
13
+ <%= month_name %>
14
+ </div>
15
+
16
+ <button type="button"
17
+ data-action="click->calendar#nextMonth"
18
+ data-calendar-target="nextButton"
19
+ aria-label="Next month">
20
+ <%= icon_for :chevron_right, class: "size-4" %>
21
+ </button>
22
+ <% end %>
@@ -0,0 +1,53 @@
1
+ <%# locals: (days:, display_month:, selected_date: nil, selected_end_date: nil, mode: :single, min_date: nil, max_date: nil, disabled_dates: [], show_outside_days: true, css_classes: "", **html_options) %>
2
+ <% merged_data = (html_options.delete(:data) || {}).merge("calendar-part": "week") %>
3
+
4
+ <%= content_tag :div, role: "row", class: css_classes.presence, data: merged_data, **html_options do %>
5
+ <% days.each do |day| %>
6
+ <%
7
+ is_outside = day.month != display_month
8
+ is_today = day == Date.current
9
+ is_selected = selected_date && day == selected_date
10
+ is_range_end = selected_end_date && day == selected_end_date
11
+ is_range_middle = selected_date && selected_end_date &&
12
+ day > selected_date && day < selected_end_date
13
+ is_disabled = (min_date && day < min_date) ||
14
+ (max_date && day > max_date) ||
15
+ disabled_dates.include?(day)
16
+
17
+ day_state = if is_selected && mode == :range && selected_end_date
18
+ "range-start"
19
+ elsif is_range_end
20
+ "range-end"
21
+ elsif is_range_middle
22
+ "range-middle"
23
+ elsif is_selected
24
+ "selected"
25
+ end
26
+
27
+ # Skip rendering if outside day and not showing them
28
+ next if is_outside && !show_outside_days
29
+
30
+ day_data = {
31
+ "calendar-part": "day",
32
+ "calendar-target": "day",
33
+ date: day.iso8601,
34
+ state: day_state.presence,
35
+ outside: (is_outside ? true : nil),
36
+ today: (is_today ? true : nil),
37
+ action: "click->calendar#selectDay keydown->calendar#handleKeydown"
38
+ }.compact
39
+ %>
40
+ <button type="button"
41
+ data-calendar-part="day"
42
+ data-calendar-target="day"
43
+ data-date="<%= day.iso8601 %>"
44
+ <%= "data-state=\"#{day_state}\"" if day_state %>
45
+ <%= "data-outside" if is_outside %>
46
+ <%= "data-today" if is_today %>
47
+ data-action="click->calendar#selectDay keydown->calendar#handleKeydown"
48
+ <%= "disabled" if is_disabled %>
49
+ tabindex="<%= is_today ? '0' : '-1' %>"
50
+ <%= "aria-selected=\"true\"" if day_state&.include?("selected") || day_state == "range-start" || day_state == "range-end" %>
51
+ <%= "aria-current=\"date\"" if is_today %>><%= day.day %></button>
52
+ <% end %>
53
+ <% end %>
@@ -0,0 +1,17 @@
1
+ <%# locals: (id:, align: :start, width: :default, css_classes: "", **html_options) %>
2
+ <% merged_data = (html_options.delete(:data) || {}).merge(
3
+ combobox_part: "content",
4
+ combobox_target: "content",
5
+ align: align,
6
+ width: width
7
+ ) %>
8
+
9
+ <%= content_tag :div,
10
+ id: id,
11
+ popover: "auto",
12
+ role: "listbox",
13
+ class: css_classes.presence,
14
+ data: merged_data,
15
+ **html_options do %>
16
+ <%= yield %>
17
+ <% end %>
@@ -0,0 +1,9 @@
1
+ <%# locals: (text: "No results found.", css_classes: "", **html_options) %>
2
+ <% merged_data = (html_options.delete(:data) || {}).merge(
3
+ combobox_part: "empty",
4
+ combobox_target: "empty"
5
+ ) %>
6
+
7
+ <%= content_tag :div, class: css_classes.presence, data: merged_data, hidden: true, **html_options do %>
8
+ <%= text %>
9
+ <% end %>
@@ -0,0 +1,8 @@
1
+ <%# locals: (css_classes: "", **html_options) %>
2
+ <% merged_data = (html_options.delete(:data) || {}).merge(
3
+ combobox_part: "group"
4
+ ) %>
5
+
6
+ <%= content_tag :div, role: "group", class: css_classes.presence, data: merged_data, **html_options do %>
7
+ <%= yield %>
8
+ <% end %>
@@ -0,0 +1,18 @@
1
+ <%# locals: (placeholder: "Search...", css_classes: "", **html_options) %>
2
+ <% merged_data = (html_options.delete(:data) || {}).merge(
3
+ combobox_part: "input",
4
+ combobox_target: "input",
5
+ action: "input->combobox#filter"
6
+ ) %>
7
+
8
+ <div data-combobox-part="input-wrapper">
9
+ <%= icon_for :search, class: "size-4 shrink-0 opacity-50" %>
10
+ <%= tag.input type: "text",
11
+ placeholder: placeholder,
12
+ autocomplete: "off",
13
+ autocorrect: "off",
14
+ spellcheck: false,
15
+ class: css_classes.presence,
16
+ data: merged_data,
17
+ **html_options %>
18
+ </div>
@@ -0,0 +1,8 @@
1
+ <%# locals: (text: nil, css_classes: "", **html_options) %>
2
+ <% merged_data = (html_options.delete(:data) || {}).merge(
3
+ combobox_part: "label"
4
+ ) %>
5
+
6
+ <%= content_tag :div, class: css_classes.presence, data: merged_data, **html_options do %>
7
+ <%= text || yield %>
8
+ <% end %>
@@ -0,0 +1,8 @@
1
+ <%# locals: (css_classes: "", **html_options) %>
2
+ <% merged_data = (html_options.delete(:data) || {}).merge(
3
+ combobox_part: "list"
4
+ ) %>
5
+
6
+ <%= content_tag :div, class: css_classes.presence, data: merged_data, **html_options do %>
7
+ <%= yield %>
8
+ <% end %>
@@ -0,0 +1,24 @@
1
+ <%# locals: (value:, selected: false, disabled: false, css_classes: "", **html_options) %>
2
+ <% merged_data = (html_options.delete(:data) || {}).merge(
3
+ combobox_part: "option",
4
+ combobox_target: "option",
5
+ value: value,
6
+ selected: selected,
7
+ action: "click->combobox#select"
8
+ ) %>
9
+
10
+ <% aria_attrs = { selected: selected } %>
11
+ <% aria_attrs[:disabled] = true if disabled %>
12
+
13
+ <%= content_tag :div,
14
+ role: "option",
15
+ tabindex: "-1",
16
+ aria: aria_attrs,
17
+ class: css_classes.presence,
18
+ data: merged_data,
19
+ **html_options do %>
20
+ <span data-combobox-part="check" class="<%= 'invisible' unless selected %>">
21
+ <%= icon_for :check, class: "size-4" %>
22
+ </span>
23
+ <%= yield %>
24
+ <% end %>
@@ -0,0 +1,6 @@
1
+ <%# locals: (css_classes: "", **html_options) %>
2
+ <% merged_data = (html_options.delete(:data) || {}).merge(
3
+ combobox_part: "separator"
4
+ ) %>
5
+
6
+ <%= tag.div role: "separator", class: css_classes.presence, data: merged_data, **html_options %>
@@ -0,0 +1,22 @@
1
+ <%# locals: (for_id:, placeholder: "Select...", variant: :outline, size: :default, css_classes: "", **html_options) %>
2
+ <% merged_data = (html_options.delete(:data) || {}).merge(
3
+ component: :button,
4
+ variant: variant,
5
+ size: size,
6
+ combobox_part: "trigger",
7
+ combobox_target: "trigger",
8
+ action: "combobox#toggle"
9
+ ) %>
10
+
11
+ <%= content_tag :button,
12
+ type: "button",
13
+ popovertarget: for_id,
14
+ popovertargetaction: "toggle",
15
+ role: "combobox",
16
+ aria: { expanded: false, haspopup: "listbox", controls: for_id },
17
+ class: css_classes.presence,
18
+ data: merged_data,
19
+ **html_options do %>
20
+ <span data-combobox-target="label"><%= placeholder %></span>
21
+ <%= icon_for :chevrons_up_down, class: "size-4 shrink-0 opacity-50" %>
22
+ <% end %>
@@ -0,0 +1,14 @@
1
+ <%# locals: (label:, href: nil, method: nil, css_classes: "", **html_options) %>
2
+ <% merged_data = (html_options.delete(:data) || {}).merge(
3
+ toast_part: "action"
4
+ ) %>
5
+
6
+ <% merged_data["turbo-method"] = method if method.present? %>
7
+
8
+ <% if href.present? %>
9
+ <%= link_to label, href, class: css_classes.presence, data: merged_data, **html_options %>
10
+ <% else %>
11
+ <%= content_tag :button, type: "button", class: css_classes.presence, data: merged_data, **html_options do %>
12
+ <%= label %>
13
+ <% end %>
14
+ <% end %>
@@ -0,0 +1,8 @@
1
+ <%# locals: (text: nil, css_classes: "", **html_options) %>
2
+ <% merged_data = (html_options.delete(:data) || {}).merge(
3
+ toast_part: "description"
4
+ ) %>
5
+
6
+ <%= content_tag :div, class: css_classes.presence, data: merged_data, **html_options do %>
7
+ <%= text || yield %>
8
+ <% end %>
@@ -0,0 +1,8 @@
1
+ <%# locals: (text: nil, css_classes: "", **html_options) %>
2
+ <% merged_data = (html_options.delete(:data) || {}).merge(
3
+ toast_part: "title"
4
+ ) %>
5
+
6
+ <%= content_tag :div, class: css_classes.presence, data: merged_data, **html_options do %>
7
+ <%= text || yield %>
8
+ <% end %>
@@ -1,3 +1,3 @@
1
1
  module MaquinaComponents
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.1"
3
3
  end