ruby_ui 1.0.0.pre.alpha.4 → 1.0.0.rc1

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 (227) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +21 -0
  3. data/README.md +85 -0
  4. data/lib/generators/ruby_ui/component_generator.rb +94 -0
  5. data/lib/generators/ruby_ui/dependencies.yml +74 -0
  6. data/lib/generators/ruby_ui/install/install_generator.rb +89 -0
  7. data/lib/generators/ruby_ui/install/templates/ruby_ui.rb.erb +18 -0
  8. data/lib/generators/ruby_ui/install/templates/tailwind.css.erb +156 -0
  9. data/lib/generators/ruby_ui/javascript_utils.rb +57 -0
  10. data/lib/{rbui → ruby_ui}/accordion/accordion.rb +1 -1
  11. data/lib/{rbui → ruby_ui}/accordion/accordion_content.rb +2 -2
  12. data/lib/ruby_ui/accordion/accordion_controller.js +97 -0
  13. data/lib/{rbui → ruby_ui}/accordion/accordion_default_content.rb +1 -1
  14. data/lib/{rbui → ruby_ui}/accordion/accordion_default_trigger.rb +3 -3
  15. data/lib/{rbui → ruby_ui}/accordion/accordion_icon.rb +2 -2
  16. data/lib/{rbui → ruby_ui}/accordion/accordion_item.rb +4 -4
  17. data/lib/{rbui → ruby_ui}/accordion/accordion_trigger.rb +3 -2
  18. data/lib/{rbui → ruby_ui}/alert/alert.rb +3 -3
  19. data/lib/{rbui → ruby_ui}/alert/alert_description.rb +1 -1
  20. data/lib/{rbui → ruby_ui}/alert/alert_title.rb +1 -1
  21. data/lib/{rbui → ruby_ui}/alert_dialog/alert_dialog.rb +3 -3
  22. data/lib/{rbui → ruby_ui}/alert_dialog/alert_dialog_action.rb +2 -2
  23. data/lib/{rbui → ruby_ui}/alert_dialog/alert_dialog_cancel.rb +3 -3
  24. data/lib/{rbui → ruby_ui}/alert_dialog/alert_dialog_content.rb +5 -5
  25. data/lib/ruby_ui/alert_dialog/alert_dialog_controller.js +31 -0
  26. data/lib/{rbui → ruby_ui}/alert_dialog/alert_dialog_description.rb +1 -1
  27. data/lib/{rbui → ruby_ui}/alert_dialog/alert_dialog_footer.rb +2 -2
  28. data/lib/{rbui → ruby_ui}/alert_dialog/alert_dialog_header.rb +2 -2
  29. data/lib/{rbui → ruby_ui}/alert_dialog/alert_dialog_title.rb +1 -1
  30. data/lib/{rbui → ruby_ui}/alert_dialog/alert_dialog_trigger.rb +2 -2
  31. data/lib/{rbui → ruby_ui}/aspect_ratio/aspect_ratio.rb +1 -1
  32. data/lib/{rbui → ruby_ui}/avatar/avatar.rb +2 -2
  33. data/lib/{rbui → ruby_ui}/avatar/avatar_fallback.rb +1 -1
  34. data/lib/{rbui → ruby_ui}/avatar/avatar_image.rb +1 -1
  35. data/lib/{rbui → ruby_ui}/badge/badge.rb +2 -2
  36. data/lib/{rbui → ruby_ui}/base.rb +1 -8
  37. data/lib/ruby_ui/breadcrumb/breadcrumb.rb +17 -0
  38. data/lib/ruby_ui/breadcrumb/breadcrumb_ellipsis.rb +39 -0
  39. data/lib/{rbui/typography/typography_list_item.rb → ruby_ui/breadcrumb/breadcrumb_item.rb} +3 -3
  40. data/lib/ruby_ui/breadcrumb/breadcrumb_link.rb +22 -0
  41. data/lib/ruby_ui/breadcrumb/breadcrumb_list.rb +17 -0
  42. data/lib/ruby_ui/breadcrumb/breadcrumb_page.rb +19 -0
  43. data/lib/ruby_ui/breadcrumb/breadcrumb_separator.rb +38 -0
  44. data/lib/{rbui → ruby_ui}/button/button.rb +13 -13
  45. data/lib/ruby_ui/calendar/calendar.rb +39 -0
  46. data/lib/{rbui → ruby_ui}/calendar/calendar_body.rb +2 -2
  47. data/lib/ruby_ui/calendar/calendar_controller.js +249 -0
  48. data/lib/{rbui → ruby_ui}/calendar/calendar_days.rb +14 -14
  49. data/lib/{rbui → ruby_ui}/calendar/calendar_header.rb +1 -1
  50. data/lib/ruby_ui/calendar/calendar_input_controller.js +8 -0
  51. data/lib/{rbui → ruby_ui}/calendar/calendar_next.rb +2 -2
  52. data/lib/{rbui → ruby_ui}/calendar/calendar_prev.rb +2 -2
  53. data/lib/{rbui → ruby_ui}/calendar/calendar_title.rb +2 -2
  54. data/lib/{rbui → ruby_ui}/calendar/calendar_weekdays.rb +2 -2
  55. data/lib/{rbui → ruby_ui}/card/card.rb +1 -1
  56. data/lib/{rbui → ruby_ui}/card/card_content.rb +1 -1
  57. data/lib/{rbui → ruby_ui}/card/card_description.rb +1 -1
  58. data/lib/{rbui → ruby_ui}/card/card_footer.rb +1 -1
  59. data/lib/{rbui → ruby_ui}/card/card_header.rb +1 -1
  60. data/lib/{rbui → ruby_ui}/card/card_title.rb +1 -1
  61. data/lib/ruby_ui/carousel/carousel.rb +44 -0
  62. data/lib/ruby_ui/carousel/carousel_content.rb +23 -0
  63. data/lib/ruby_ui/carousel/carousel_controller.js +60 -0
  64. data/lib/ruby_ui/carousel/carousel_item.rb +23 -0
  65. data/lib/ruby_ui/carousel/carousel_next.rb +48 -0
  66. data/lib/ruby_ui/carousel/carousel_previous.rb +49 -0
  67. data/lib/{rbui → ruby_ui}/chart/chart.rb +3 -3
  68. data/lib/ruby_ui/chart/chart_controller.js +103 -0
  69. data/lib/{rbui → ruby_ui}/checkbox/checkbox.rb +4 -4
  70. data/lib/{rbui → ruby_ui}/checkbox/checkbox_group.rb +2 -2
  71. data/lib/ruby_ui/checkbox/checkbox_group_controller.js +21 -0
  72. data/lib/{rbui → ruby_ui}/clipboard/clipboard.rb +6 -6
  73. data/lib/ruby_ui/clipboard/clipboard_controller.js +54 -0
  74. data/lib/{rbui → ruby_ui}/clipboard/clipboard_popover.rb +2 -2
  75. data/lib/{rbui → ruby_ui}/clipboard/clipboard_source.rb +2 -2
  76. data/lib/{rbui → ruby_ui}/clipboard/clipboard_trigger.rb +3 -3
  77. data/lib/{rbui → ruby_ui}/codeblock/codeblock.rb +7 -10
  78. data/lib/{rbui → ruby_ui}/collapsible/collapsible.rb +3 -3
  79. data/lib/{rbui → ruby_ui}/collapsible/collapsible_content.rb +2 -2
  80. data/lib/ruby_ui/collapsible/collapsible_controller.js +47 -0
  81. data/lib/{rbui → ruby_ui}/collapsible/collapsible_trigger.rb +2 -2
  82. data/lib/ruby_ui/combobox/combobox.rb +26 -0
  83. data/lib/ruby_ui/combobox/combobox_checkbox.rb +25 -0
  84. data/lib/ruby_ui/combobox/combobox_controller.js +176 -0
  85. data/lib/{rbui/combobox/combobox_empty.rb → ruby_ui/combobox/combobox_empty_state.rb} +3 -3
  86. data/lib/ruby_ui/combobox/combobox_item.rb +25 -0
  87. data/lib/ruby_ui/combobox/combobox_list.rb +18 -0
  88. data/lib/ruby_ui/combobox/combobox_list_group.rb +20 -0
  89. data/lib/ruby_ui/combobox/combobox_popover.rb +30 -0
  90. data/lib/ruby_ui/combobox/combobox_radio.rb +26 -0
  91. data/lib/{rbui → ruby_ui}/combobox/combobox_search_input.rb +22 -25
  92. data/lib/ruby_ui/combobox/combobox_toggle_all_checkbox.rb +25 -0
  93. data/lib/{rbui → ruby_ui}/combobox/combobox_trigger.rb +26 -21
  94. data/lib/{rbui → ruby_ui}/command/command.rb +1 -1
  95. data/lib/ruby_ui/command/command_controller.js +136 -0
  96. data/lib/{rbui → ruby_ui}/command/command_dialog.rb +2 -2
  97. data/lib/{rbui → ruby_ui}/command/command_dialog_content.rb +6 -6
  98. data/lib/{rbui → ruby_ui}/command/command_dialog_trigger.rb +3 -3
  99. data/lib/{rbui → ruby_ui}/command/command_empty.rb +2 -2
  100. data/lib/{rbui → ruby_ui}/command/command_group.rb +2 -2
  101. data/lib/{rbui → ruby_ui}/command/command_input.rb +3 -3
  102. data/lib/{rbui → ruby_ui}/command/command_item.rb +2 -2
  103. data/lib/{rbui → ruby_ui}/command/command_list.rb +1 -1
  104. data/lib/{rbui → ruby_ui}/context_menu/context_menu.rb +2 -2
  105. data/lib/{rbui → ruby_ui}/context_menu/context_menu_content.rb +2 -2
  106. data/lib/ruby_ui/context_menu/context_menu_controller.js +144 -0
  107. data/lib/{rbui → ruby_ui}/context_menu/context_menu_item.rb +3 -3
  108. data/lib/{rbui → ruby_ui}/context_menu/context_menu_label.rb +2 -2
  109. data/lib/{rbui → ruby_ui}/context_menu/context_menu_separator.rb +1 -1
  110. data/lib/{rbui → ruby_ui}/context_menu/context_menu_trigger.rb +3 -3
  111. data/lib/{rbui → ruby_ui}/dialog/dialog.rb +3 -3
  112. data/lib/{rbui → ruby_ui}/dialog/dialog_content.rb +9 -9
  113. data/lib/ruby_ui/dialog/dialog_controller.js +32 -0
  114. data/lib/{rbui → ruby_ui}/dialog/dialog_description.rb +1 -1
  115. data/lib/{rbui → ruby_ui}/dialog/dialog_footer.rb +2 -2
  116. data/lib/{rbui → ruby_ui}/dialog/dialog_header.rb +2 -2
  117. data/lib/{rbui → ruby_ui}/dialog/dialog_middle.rb +1 -1
  118. data/lib/{rbui → ruby_ui}/dialog/dialog_title.rb +1 -1
  119. data/lib/{rbui → ruby_ui}/dialog/dialog_trigger.rb +2 -2
  120. data/lib/{rbui → ruby_ui}/dropdown_menu/dropdown_menu.rb +4 -4
  121. data/lib/{rbui → ruby_ui}/dropdown_menu/dropdown_menu_content.rb +2 -2
  122. data/lib/ruby_ui/dropdown_menu/dropdown_menu_controller.js +120 -0
  123. data/lib/{rbui → ruby_ui}/dropdown_menu/dropdown_menu_item.rb +3 -3
  124. data/lib/{rbui → ruby_ui}/dropdown_menu/dropdown_menu_label.rb +1 -1
  125. data/lib/{rbui → ruby_ui}/dropdown_menu/dropdown_menu_separator.rb +1 -1
  126. data/lib/{rbui → ruby_ui}/dropdown_menu/dropdown_menu_trigger.rb +2 -2
  127. data/lib/{rbui → ruby_ui}/form/form.rb +1 -1
  128. data/lib/{rbui → ruby_ui}/form/form_field.rb +2 -2
  129. data/lib/ruby_ui/form/form_field_controller.js +61 -0
  130. data/lib/{rbui → ruby_ui}/form/form_field_error.rb +2 -2
  131. data/lib/{rbui → ruby_ui}/form/form_field_hint.rb +1 -1
  132. data/lib/{rbui → ruby_ui}/form/form_field_label.rb +1 -1
  133. data/lib/{rbui → ruby_ui}/hover_card/hover_card.rb +3 -3
  134. data/lib/{rbui → ruby_ui}/hover_card/hover_card_content.rb +2 -2
  135. data/lib/ruby_ui/hover_card/hover_card_controller.js +144 -0
  136. data/lib/{rbui → ruby_ui}/hover_card/hover_card_trigger.rb +2 -2
  137. data/lib/{rbui → ruby_ui}/input/input.rb +3 -3
  138. data/lib/{rbui → ruby_ui}/link/link.rb +13 -13
  139. data/lib/ruby_ui/masked_input/masked_input.rb +15 -0
  140. data/lib/ruby_ui/masked_input/masked_input_controller.js +9 -0
  141. data/lib/{rbui → ruby_ui}/pagination/pagination.rb +1 -1
  142. data/lib/{rbui → ruby_ui}/pagination/pagination_content.rb +1 -1
  143. data/lib/{rbui → ruby_ui}/pagination/pagination_ellipsis.rb +1 -1
  144. data/lib/{rbui → ruby_ui}/pagination/pagination_item.rb +4 -4
  145. data/lib/{rbui → ruby_ui}/popover/popover.rb +4 -4
  146. data/lib/{rbui → ruby_ui}/popover/popover_content.rb +2 -2
  147. data/lib/ruby_ui/popover/popover_controller.js +107 -0
  148. data/lib/{rbui → ruby_ui}/popover/popover_trigger.rb +2 -2
  149. data/lib/ruby_ui/progress/progress.rb +37 -0
  150. data/lib/ruby_ui/radio_button/radio_button.rb +25 -0
  151. data/lib/{rbui → ruby_ui}/select/select.rb +5 -5
  152. data/lib/{rbui → ruby_ui}/select/select_content.rb +3 -3
  153. data/lib/ruby_ui/select/select_controller.js +171 -0
  154. data/lib/{rbui → ruby_ui}/select/select_group.rb +1 -1
  155. data/lib/{rbui → ruby_ui}/select/select_input.rb +4 -4
  156. data/lib/{rbui → ruby_ui}/select/select_item.rb +4 -4
  157. data/lib/ruby_ui/select/select_item_controller.js +11 -0
  158. data/lib/{rbui → ruby_ui}/select/select_label.rb +1 -1
  159. data/lib/{rbui → ruby_ui}/select/select_trigger.rb +3 -3
  160. data/lib/{rbui → ruby_ui}/select/select_value.rb +3 -3
  161. data/lib/ruby_ui/separator/separator.rb +38 -0
  162. data/lib/{rbui → ruby_ui}/sheet/sheet.rb +2 -2
  163. data/lib/{rbui → ruby_ui}/sheet/sheet_content.rb +8 -8
  164. data/lib/ruby_ui/sheet/sheet_content_controller.js +7 -0
  165. data/lib/ruby_ui/sheet/sheet_controller.js +9 -0
  166. data/lib/{rbui → ruby_ui}/sheet/sheet_description.rb +1 -1
  167. data/lib/{rbui → ruby_ui}/sheet/sheet_footer.rb +1 -1
  168. data/lib/{rbui → ruby_ui}/sheet/sheet_header.rb +1 -1
  169. data/lib/{rbui → ruby_ui}/sheet/sheet_middle.rb +1 -1
  170. data/lib/{rbui → ruby_ui}/sheet/sheet_title.rb +1 -1
  171. data/lib/{rbui → ruby_ui}/sheet/sheet_trigger.rb +2 -2
  172. data/lib/{rbui → ruby_ui}/shortcut_key/shortcut_key.rb +1 -1
  173. data/lib/ruby_ui/skeleton/skeleton.rb +17 -0
  174. data/lib/ruby_ui/switch/switch.rb +24 -0
  175. data/lib/{rbui → ruby_ui}/table/table.rb +1 -1
  176. data/lib/{rbui → ruby_ui}/table/table_body.rb +1 -1
  177. data/lib/{rbui → ruby_ui}/table/table_caption.rb +1 -1
  178. data/lib/{rbui → ruby_ui}/table/table_cell.rb +1 -1
  179. data/lib/{rbui → ruby_ui}/table/table_footer.rb +1 -1
  180. data/lib/{rbui → ruby_ui}/table/table_head.rb +1 -1
  181. data/lib/{rbui → ruby_ui}/table/table_header.rb +1 -1
  182. data/lib/{rbui → ruby_ui}/table/table_row.rb +1 -1
  183. data/lib/{rbui → ruby_ui}/tabs/tabs.rb +3 -3
  184. data/lib/{rbui → ruby_ui}/tabs/tabs_content.rb +2 -2
  185. data/lib/ruby_ui/tabs/tabs_controller.js +45 -0
  186. data/lib/{rbui → ruby_ui}/tabs/tabs_list.rb +1 -1
  187. data/lib/{rbui → ruby_ui}/tabs/tabs_trigger.rb +3 -3
  188. data/lib/{rbui → ruby_ui}/textarea/textarea.rb +3 -3
  189. data/lib/{rbui → ruby_ui}/theme_toggle/theme_toggle.rb +4 -4
  190. data/lib/ruby_ui/theme_toggle/theme_toggle_controller.js +30 -0
  191. data/lib/{rbui → ruby_ui}/tooltip/tooltip.rb +3 -3
  192. data/lib/{rbui → ruby_ui}/tooltip/tooltip_content.rb +3 -3
  193. data/lib/ruby_ui/tooltip/tooltip_controller.js +37 -0
  194. data/lib/{rbui → ruby_ui}/tooltip/tooltip_trigger.rb +2 -2
  195. data/lib/ruby_ui/typography/heading.rb +60 -0
  196. data/lib/{rbui/typography/typography_inline_code.rb → ruby_ui/typography/inline_code.rb} +2 -2
  197. data/lib/{rbui/typography/typography_inline_link.rb → ruby_ui/typography/inline_link.rb} +2 -2
  198. data/lib/ruby_ui/typography/text.rb +53 -0
  199. data/lib/{rbui → ruby_ui}/typography/typography_blockquote.rb +1 -1
  200. data/lib/ruby_ui.rb +5 -1
  201. metadata +208 -173
  202. data/lib/generators/rbui/base_generator.rb +0 -17
  203. data/lib/generators/rbui/component_generator.rb +0 -137
  204. data/lib/generators/rbui/install/install_generator.rb +0 -194
  205. data/lib/rbui/calendar/calendar.rb +0 -39
  206. data/lib/rbui/combobox/combobox.rb +0 -24
  207. data/lib/rbui/combobox/combobox_content.rb +0 -31
  208. data/lib/rbui/combobox/combobox_group.rb +0 -38
  209. data/lib/rbui/combobox/combobox_input.rb +0 -22
  210. data/lib/rbui/combobox/combobox_item.rb +0 -53
  211. data/lib/rbui/combobox/combobox_list.rb +0 -29
  212. data/lib/rbui/combobox/combobox_separator.rb +0 -15
  213. data/lib/rbui/combobox/combobox_value.rb +0 -27
  214. data/lib/rbui/radio_button/radio_button.rb +0 -22
  215. data/lib/rbui/railtie.rb +0 -52
  216. data/lib/rbui/typography/typography_h1.rb +0 -17
  217. data/lib/rbui/typography/typography_h2.rb +0 -17
  218. data/lib/rbui/typography/typography_h3.rb +0 -17
  219. data/lib/rbui/typography/typography_h4.rb +0 -17
  220. data/lib/rbui/typography/typography_large.rb +0 -17
  221. data/lib/rbui/typography/typography_lead.rb +0 -17
  222. data/lib/rbui/typography/typography_list.rb +0 -47
  223. data/lib/rbui/typography/typography_muted.rb +0 -17
  224. data/lib/rbui/typography/typography_p.rb +0 -17
  225. data/lib/rbui/typography/typography_small.rb +0 -17
  226. data/lib/rbui/version.rb +0 -5
  227. data/lib/rbui.rb +0 -57
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RBUI
3
+ module RubyUI
4
4
  class Button < Base
5
5
  def initialize(type: :button, variant: :primary, size: :md, icon: false, **attrs)
6
6
  @type = type
@@ -35,45 +35,45 @@ module RBUI
35
35
  end
36
36
 
37
37
  def primary_classes
38
- tokens(
38
+ [
39
39
  "whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground shadow hover:bg-primary/90",
40
40
  size_classes
41
- )
41
+ ]
42
42
  end
43
43
 
44
44
  def link_classes
45
- tokens(
45
+ [
46
46
  "whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 text-primary underline-offset-4 hover:underline",
47
47
  size_classes
48
- )
48
+ ]
49
49
  end
50
50
 
51
51
  def secondary_classes
52
- tokens(
52
+ [
53
53
  "whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-secondary text-secondary-foreground hover:bg-opacity-80",
54
54
  size_classes
55
- )
55
+ ]
56
56
  end
57
57
 
58
58
  def destructive_classes
59
- tokens(
59
+ [
60
60
  "whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
61
61
  size_classes
62
- )
62
+ ]
63
63
  end
64
64
 
65
65
  def outline_classes
66
- tokens(
66
+ [
67
67
  "whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
68
68
  size_classes
69
- )
69
+ ]
70
70
  end
71
71
 
72
72
  def ghost_classes
73
- tokens(
73
+ [
74
74
  "whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 hover:bg-accent hover:text-accent-foreground",
75
75
  size_classes
76
- )
76
+ ]
77
77
  end
78
78
 
79
79
  def default_classes
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class Calendar < Base
5
+ def initialize(selected_date: nil, input_id: nil, date_format: "yyyy-MM-dd", **attrs)
6
+ @selected_date = selected_date
7
+ @input_id = input_id
8
+ @date_format = date_format
9
+ super(**attrs)
10
+ end
11
+
12
+ def view_template
13
+ div(**attrs) do
14
+ RubyUI.CalendarHeader do
15
+ RubyUI.CalendarTitle
16
+ RubyUI.CalendarPrev
17
+ RubyUI.CalendarNext
18
+ end
19
+ RubyUI.CalendarBody # Where the calendar is rendered (Weekdays and Days)
20
+ RubyUI.CalendarWeekdays # Template for the weekdays
21
+ RubyUI.CalendarDays # Template for the days
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def default_attrs
28
+ {
29
+ class: "p-3 space-y-4",
30
+ data: {
31
+ controller: "ruby-ui--calendar",
32
+ ruby_ui__calendar_selected_date_value: @selected_date&.to_s,
33
+ ruby_ui__calendar_format_value: @date_format,
34
+ ruby_ui__calendar_ruby_ui__calendar_input_outlet: @input_id
35
+ }
36
+ }
37
+ end
38
+ end
39
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RBUI
3
+ module RubyUI
4
4
  class CalendarBody < Base
5
5
  def view_template
6
6
  table(**attrs)
@@ -11,7 +11,7 @@ module RBUI
11
11
  def default_attrs
12
12
  {
13
13
  data: {
14
- rbui__calendar_target: "calendar"
14
+ ruby_ui__calendar_target: "calendar"
15
15
  }
16
16
  }
17
17
  end
@@ -0,0 +1,249 @@
1
+ import { Controller } from "@hotwired/stimulus";
2
+ import Mustache from "mustache";
3
+
4
+ export default class extends Controller {
5
+ static targets = [
6
+ "calendar",
7
+ "title",
8
+ "weekdaysTemplate",
9
+ "selectedDateTemplate",
10
+ "todayDateTemplate",
11
+ "currentMonthDateTemplate",
12
+ "otherMonthDateTemplate",
13
+ ];
14
+ static values = {
15
+ selectedDate: {
16
+ type: String,
17
+ default: null,
18
+ },
19
+ viewDate: {
20
+ type: String,
21
+ default: new Date().toISOString().slice(0, 10),
22
+ },
23
+ format: {
24
+ type: String,
25
+ default: "yyyy-MM-dd", // Default format
26
+ },
27
+ };
28
+ static outlets = ["ruby-ui--calendar-input"];
29
+
30
+ initialize() {
31
+ this.updateCalendar(); // Initial calendar render
32
+ }
33
+
34
+ nextMonth(e) {
35
+ e.preventDefault();
36
+ this.viewDateValue = this.adjustMonth(1);
37
+ }
38
+
39
+ prevMonth(e) {
40
+ e.preventDefault();
41
+ this.viewDateValue = this.adjustMonth(-1);
42
+ }
43
+
44
+ selectDay(e) {
45
+ e.preventDefault();
46
+ // Set the selected date value
47
+ this.selectedDateValue = e.currentTarget.dataset.day;
48
+ }
49
+
50
+ selectedDateValueChanged(value, prevValue) {
51
+ // update the viewDateValue to the first day of month of the selected date (This will trigger updateCalendar() function)
52
+ const newViewDate = new Date(this.selectedDateValue);
53
+ newViewDate.setDate(2); // set the day to the 2nd (to avoid issues with months with different number of days and timezones)
54
+ this.viewDateValue = newViewDate.toISOString().slice(0, 10);
55
+
56
+ // Re-render the calendar
57
+ this.updateCalendar();
58
+
59
+ // update the input value
60
+ this.rubyUiCalendarInputOutlets.forEach((outlet) => {
61
+ const formattedDate = this.formatDate(this.selectedDate());
62
+ outlet.setValue(formattedDate);
63
+ });
64
+ }
65
+
66
+ viewDateValueChanged(value, prevValue) {
67
+ this.updateCalendar();
68
+ }
69
+
70
+ adjustMonth(adjustment) {
71
+ const date = this.viewDate();
72
+ date.setDate(2); // set the day to the 2nd (to avoid issues with months with different number of days and timezones)
73
+ date.setMonth(date.getMonth() + adjustment);
74
+ return date.toISOString().slice(0, 10);
75
+ }
76
+
77
+ updateCalendar() {
78
+ // Update the title with month and year
79
+ this.titleTarget.textContent = this.monthAndYear();
80
+ this.calendarTarget.innerHTML = this.calendarHTML();
81
+ }
82
+
83
+ calendarHTML() {
84
+ return this.weekdaysTemplateTarget.innerHTML + this.calendarDays();
85
+ }
86
+
87
+ calendarDays() {
88
+ return this.getFullWeeksStartAndEndInMonth()
89
+ .map((week) => this.renderWeek(week))
90
+ .join("");
91
+ }
92
+
93
+ renderWeek(week) {
94
+ const days = week
95
+ .map((day) => {
96
+ return this.renderDay(day);
97
+ })
98
+ .join("");
99
+ return `<tr class="flex w-full mt-2">${days}</tr>`;
100
+ }
101
+
102
+ renderDay(day) {
103
+ const today = new Date();
104
+ let dateHTML = "";
105
+ const data = { day: day, dayDate: day.getDate() };
106
+
107
+ if (day.toDateString() === this.selectedDate().toDateString()) {
108
+ // selectedDate
109
+ // Render the selected date template target innerHTML with Mustache
110
+ dateHTML = Mustache.render(
111
+ this.selectedDateTemplateTarget.innerHTML,
112
+ data,
113
+ );
114
+ } else if (day.toDateString() === today.toDateString()) {
115
+ // todayDate
116
+ dateHTML = Mustache.render(this.todayDateTemplateTarget.innerHTML, data);
117
+ } else if (day.getMonth() === this.viewDate().getMonth()) {
118
+ // currentMonthDate
119
+ dateHTML = Mustache.render(
120
+ this.currentMonthDateTemplateTarget.innerHTML,
121
+ data,
122
+ );
123
+ } else {
124
+ // otherMonthDate
125
+ dateHTML = Mustache.render(
126
+ this.otherMonthDateTemplateTarget.innerHTML,
127
+ data,
128
+ );
129
+ }
130
+ return dateHTML;
131
+ }
132
+
133
+ monthAndYear() {
134
+ const month = this.viewDate().toLocaleString("en-US", { month: "long" });
135
+ const year = this.viewDate().getFullYear();
136
+ return `${month} ${year}`;
137
+ }
138
+
139
+ selectedDate() {
140
+ return new Date(this.selectedDateValue);
141
+ }
142
+
143
+ viewDate() {
144
+ return this.viewDateValue
145
+ ? new Date(this.viewDateValue)
146
+ : this.selectedDate();
147
+ }
148
+
149
+ getFullWeeksStartAndEndInMonth() {
150
+ const month = this.viewDate().getMonth();
151
+ const year = this.viewDate().getFullYear();
152
+
153
+ let weeks = [],
154
+ firstDate = new Date(year, month, 1),
155
+ lastDate = new Date(year, month + 1, 0),
156
+ numDays = lastDate.getDate();
157
+
158
+ let start = 1;
159
+ let end;
160
+ if (firstDate.getDay() === 1) {
161
+ end = 7;
162
+ } else if (firstDate.getDay() === 0) {
163
+ let preMonthEndDay = new Date(year, month, 0);
164
+ start = preMonthEndDay.getDate() - 6 + 1;
165
+ end = 1;
166
+ } else {
167
+ let preMonthEndDay = new Date(year, month, 0);
168
+ start = preMonthEndDay.getDate() + 1 - firstDate.getDay() + 1;
169
+ end = 7 - firstDate.getDay() + 1;
170
+ weeks.push({
171
+ start: start,
172
+ end: end,
173
+ });
174
+ start = end + 1;
175
+ end = end + 7;
176
+ }
177
+ while (start <= numDays) {
178
+ weeks.push({
179
+ start: start,
180
+ end: end,
181
+ });
182
+ start = end + 1;
183
+ end = end + 7;
184
+ end = start === 1 && end === 8 ? 1 : end;
185
+ if (end > numDays && start <= numDays) {
186
+ end = end - numDays;
187
+ weeks.push({
188
+ start: start,
189
+ end: end,
190
+ });
191
+ break;
192
+ }
193
+ }
194
+ // *** the magic starts here
195
+ return weeks.map(({ start, end }, index) => {
196
+ const sub = +(start > end && index === 0);
197
+ return Array.from({ length: 7 }, (_, index) => {
198
+ const date = new Date(year, month - sub, start + index);
199
+ return date;
200
+ });
201
+ });
202
+ }
203
+
204
+ formatDate(date) {
205
+ const format = this.formatValue;
206
+ const day = date.getDate();
207
+ const month = date.getMonth() + 1;
208
+ const year = date.getFullYear();
209
+ const hours = date.getHours();
210
+ const minutes = date.getMinutes();
211
+ const seconds = date.getSeconds();
212
+ const dayOfWeek = date.toLocaleString("en-US", { weekday: "long" });
213
+ const monthName = date.toLocaleString("en-US", { month: "long" });
214
+ const daySuffix = this.getDaySuffix(day);
215
+
216
+ const map = {
217
+ yyyy: year,
218
+ MM: ("0" + month).slice(-2),
219
+ dd: ("0" + day).slice(-2),
220
+ HH: ("0" + hours).slice(-2),
221
+ mm: ("0" + minutes).slice(-2),
222
+ ss: ("0" + seconds).slice(-2),
223
+ EEEE: dayOfWeek,
224
+ MMMM: monthName,
225
+ do: day + daySuffix,
226
+ PPPP: `${dayOfWeek}, ${monthName} ${day}${daySuffix}, ${year}`,
227
+ };
228
+
229
+ const formattedDate = format.replace(
230
+ /yyyy|MM|dd|HH|mm|ss|EEEE|MMMM|do|PPPP/g,
231
+ (matched) => map[matched],
232
+ );
233
+ return formattedDate;
234
+ }
235
+
236
+ getDaySuffix(day) {
237
+ if (day > 3 && day < 21) return "th";
238
+ switch (day % 10) {
239
+ case 1:
240
+ return "st";
241
+ case 2:
242
+ return "nd";
243
+ case 3:
244
+ return "rd";
245
+ default:
246
+ return "th";
247
+ }
248
+ }
249
+ }
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RBUI
3
+ module RubyUI
4
4
  class CalendarDays < Base
5
5
  BASE_CLASS = "inline-flex items-center justify-center rounded-md text-sm ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 h-8 w-8 p-0 font-normal aria-selected:opacity-100"
6
6
 
@@ -17,13 +17,13 @@ module RBUI
17
17
  date_template("selectedDateTemplate") do
18
18
  button(
19
19
  data_day: "{{day}}",
20
- data_action: "click->rbui--calendar#selectDay",
20
+ data_action: "click->ruby-ui--calendar#selectDay",
21
21
  name: "day",
22
22
  class:
23
- tokens(
23
+ [
24
24
  BASE_CLASS,
25
25
  "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground"
26
- ),
26
+ ],
27
27
  role: "gridcell",
28
28
  tabindex: "0",
29
29
  type: "button",
@@ -36,13 +36,13 @@ module RBUI
36
36
  date_template("todayDateTemplate") do
37
37
  button(
38
38
  data_day: "{{day}}",
39
- data_action: "click->rbui--calendar#selectDay",
39
+ data_action: "click->ruby-ui--calendar#selectDay",
40
40
  name: "day",
41
41
  class:
42
- tokens(
42
+ [
43
43
  BASE_CLASS,
44
44
  "bg-accent text-accent-foreground hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground"
45
- ),
45
+ ],
46
46
  role: "gridcell",
47
47
  tabindex: "-1",
48
48
  type: "button"
@@ -54,13 +54,13 @@ module RBUI
54
54
  date_template("currentMonthDateTemplate") do
55
55
  button(
56
56
  data_day: "{{day}}",
57
- data_action: "click->rbui--calendar#selectDay",
57
+ data_action: "click->ruby-ui--calendar#selectDay",
58
58
  name: "day",
59
59
  class:
60
- tokens(
60
+ [
61
61
  BASE_CLASS,
62
62
  "bg-background text-foreground hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground"
63
- ),
63
+ ],
64
64
  role: "gridcell",
65
65
  tabindex: "-1",
66
66
  type: "button"
@@ -72,13 +72,13 @@ module RBUI
72
72
  date_template("otherMonthDateTemplate") do
73
73
  button(
74
74
  data_day: "{{day}}",
75
- data_action: " click->rbui--calendar#selectDay",
75
+ data_action: " click->ruby-ui--calendar#selectDay",
76
76
  name: "day",
77
77
  class:
78
- tokens(
78
+ [
79
79
  BASE_CLASS,
80
80
  "bg-background text-muted-foreground hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground"
81
- ),
81
+ ],
82
82
  role: "gridcell",
83
83
  tabindex: "-1",
84
84
  type: "button"
@@ -87,7 +87,7 @@ module RBUI
87
87
  end
88
88
 
89
89
  def date_template(target, &block)
90
- template_tag(data: {rbui__calendar_target: target}) do
90
+ template(data: {ruby_ui__calendar_target: target}) do
91
91
  td(
92
92
  class:
93
93
  "relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-accent [&:has([aria-selected])]:rounded-md",
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RBUI
3
+ module RubyUI
4
4
  class CalendarHeader < Base
5
5
  def view_template(&)
6
6
  div(**attrs, &)
@@ -0,0 +1,8 @@
1
+ import { Controller } from "@hotwired/stimulus"
2
+
3
+ // Connects to data-controller="input"
4
+ export default class extends Controller {
5
+ setValue(value) {
6
+ this.element.value = value
7
+ }
8
+ }
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RBUI
3
+ module RubyUI
4
4
  class CalendarNext < Base
5
5
  def view_template(&block)
6
6
  button(**attrs) do
@@ -36,7 +36,7 @@ module RBUI
36
36
  class:
37
37
  "inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input hover:bg-accent hover:text-accent-foreground h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 absolute right-1",
38
38
  type: "button",
39
- data_action: "click->rbui--calendar#nextMonth"
39
+ data_action: "click->ruby-ui--calendar#nextMonth"
40
40
  }
41
41
  end
42
42
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RBUI
3
+ module RubyUI
4
4
  class CalendarPrev < Base
5
5
  def view_template(&block)
6
6
  button(**attrs) do
@@ -36,7 +36,7 @@ module RBUI
36
36
  class:
37
37
  "rdp-button_reset rdp-button inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input hover:bg-accent hover:text-accent-foreground h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 absolute left-1",
38
38
  type: "button",
39
- data_action: "click->rbui--calendar#prevMonth"
39
+ data_action: "click->ruby-ui--calendar#prevMonth"
40
40
  }
41
41
  end
42
42
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RBUI
3
+ module RubyUI
4
4
  class CalendarTitle < Base
5
5
  def initialize(default: "Month Year", **attrs)
6
6
  @default = default
@@ -19,7 +19,7 @@ module RBUI
19
19
  aria_live: "polite",
20
20
  role: "presentation",
21
21
  data: {
22
- rbui__calendar_target: "title"
22
+ ruby_ui__calendar_target: "title"
23
23
  }
24
24
  }
25
25
  end
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RBUI
3
+ module RubyUI
4
4
  class CalendarWeekdays < Base
5
5
  DAYS = %w[Monday Tuesday Wednesday Thursday Friday Saturday Sunday].freeze
6
6
 
7
7
  def view_template
8
- template_tag(data: {rbui__calendar_target: "weekdaysTemplate"}) do
8
+ template(data: {ruby_ui__calendar_target: "weekdaysTemplate"}) do
9
9
  thead(**attrs) do
10
10
  tr(class: "flex") do
11
11
  DAYS.each do |day|
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RBUI
3
+ module RubyUI
4
4
  class Card < Base
5
5
  def view_template(&)
6
6
  div(**attrs, &)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RBUI
3
+ module RubyUI
4
4
  class CardContent < Base
5
5
  def view_template(&)
6
6
  div(**attrs, &)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RBUI
3
+ module RubyUI
4
4
  class CardDescription < Base
5
5
  def view_template(&)
6
6
  p(**attrs, &)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RBUI
3
+ module RubyUI
4
4
  class CardFooter < Base
5
5
  def view_template(&)
6
6
  div(**attrs, &)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RBUI
3
+ module RubyUI
4
4
  class CardHeader < Base
5
5
  def view_template(&)
6
6
  div(**attrs, &)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RBUI
3
+ module RubyUI
4
4
  class CardTitle < Base
5
5
  def view_template(&)
6
6
  h3(**attrs, &)
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class Carousel < Base
5
+ def initialize(orientation: :horizontal, options: {}, **user_attrs)
6
+ @orientation = orientation
7
+ @options = options
8
+
9
+ super(**user_attrs)
10
+ end
11
+
12
+ def view_template(&)
13
+ div(**attrs, &)
14
+ end
15
+
16
+ private
17
+
18
+ def default_attrs
19
+ {
20
+ class: ["relative group", orientation_classes],
21
+ role: "region",
22
+ aria_roledescription: "carousel",
23
+ data: {
24
+ controller: "ruby-ui--carousel",
25
+ ruby_ui__carousel_options_value: default_options.merge(@options).to_json,
26
+ action: %w[
27
+ keydown.right->ruby-ui--carousel#scrollNext:prevent
28
+ keydown.left->ruby-ui--carousel#scrollPrev:prevent
29
+ ]
30
+ }
31
+ }
32
+ end
33
+
34
+ def default_options
35
+ {
36
+ axis: (@orientation == :horizontal) ? "x" : "y"
37
+ }
38
+ end
39
+
40
+ def orientation_classes
41
+ (@orientation == :horizontal) ? "is-horizontal" : "is-vertical"
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class CarouselContent < Base
5
+ def view_template(&)
6
+ div(class: "overflow-hidden", data: {ruby_ui__carousel_target: "viewport"}) do
7
+ div(**attrs, &)
8
+ end
9
+ end
10
+
11
+ private
12
+
13
+ def default_attrs
14
+ {
15
+ class: [
16
+ "flex",
17
+ "group-[.is-horizontal]:-ml-4",
18
+ "group-[.is-vertical]:-mt-4 group-[.is-vertical]:flex-col"
19
+ ]
20
+ }
21
+ end
22
+ end
23
+ end