ruby_ui 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. checksums.yaml +7 -0
  2. data/lib/generators/ruby_ui/component_generator.rb +130 -0
  3. data/lib/generators/ruby_ui/install/install_generator.rb +90 -0
  4. data/lib/generators/ruby_ui/javascript_utils.rb +36 -0
  5. data/lib/ruby_ui/accordion/accordion.rb +17 -0
  6. data/lib/ruby_ui/accordion/accordion_content.rb +21 -0
  7. data/lib/ruby_ui/accordion/accordion_default_content.rb +17 -0
  8. data/lib/ruby_ui/accordion/accordion_default_trigger.rb +19 -0
  9. data/lib/ruby_ui/accordion/accordion_icon.rb +38 -0
  10. data/lib/ruby_ui/accordion/accordion_item.rb +28 -0
  11. data/lib/ruby_ui/accordion/accordion_trigger.rb +17 -0
  12. data/lib/ruby_ui/alert/alert.rb +36 -0
  13. data/lib/ruby_ui/alert/alert_description.rb +17 -0
  14. data/lib/ruby_ui/alert/alert_title.rb +17 -0
  15. data/lib/ruby_ui/alert_dialog/alert_dialog.rb +26 -0
  16. data/lib/ruby_ui/alert_dialog/alert_dialog_action.rb +17 -0
  17. data/lib/ruby_ui/alert_dialog/alert_dialog_cancel.rb +21 -0
  18. data/lib/ruby_ui/alert_dialog/alert_dialog_content.rb +45 -0
  19. data/lib/ruby_ui/alert_dialog/alert_dialog_description.rb +17 -0
  20. data/lib/ruby_ui/alert_dialog/alert_dialog_footer.rb +17 -0
  21. data/lib/ruby_ui/alert_dialog/alert_dialog_header.rb +17 -0
  22. data/lib/ruby_ui/alert_dialog/alert_dialog_title.rb +17 -0
  23. data/lib/ruby_ui/alert_dialog/alert_dialog_trigger.rb +18 -0
  24. data/lib/ruby_ui/aspect_ratio/aspect_ratio.rb +33 -0
  25. data/lib/ruby_ui/avatar/avatar.rb +31 -0
  26. data/lib/ruby_ui/avatar/avatar_fallback.rb +17 -0
  27. data/lib/ruby_ui/avatar/avatar_image.rb +26 -0
  28. data/lib/ruby_ui/badge/badge.rb +60 -0
  29. data/lib/ruby_ui/base.rb +22 -0
  30. data/lib/ruby_ui/button/button.rb +97 -0
  31. data/lib/ruby_ui/calendar/calendar.rb +39 -0
  32. data/lib/ruby_ui/calendar/calendar_body.rb +19 -0
  33. data/lib/ruby_ui/calendar/calendar_days.rb +104 -0
  34. data/lib/ruby_ui/calendar/calendar_header.rb +17 -0
  35. data/lib/ruby_ui/calendar/calendar_next.rb +43 -0
  36. data/lib/ruby_ui/calendar/calendar_prev.rb +43 -0
  37. data/lib/ruby_ui/calendar/calendar_title.rb +27 -0
  38. data/lib/ruby_ui/calendar/calendar_weekdays.rb +33 -0
  39. data/lib/ruby_ui/card/card.rb +17 -0
  40. data/lib/ruby_ui/card/card_content.rb +17 -0
  41. data/lib/ruby_ui/card/card_description.rb +17 -0
  42. data/lib/ruby_ui/card/card_footer.rb +17 -0
  43. data/lib/ruby_ui/card/card_header.rb +17 -0
  44. data/lib/ruby_ui/card/card_title.rb +17 -0
  45. data/lib/ruby_ui/chart/chart.rb +23 -0
  46. data/lib/ruby_ui/checkbox/checkbox.rb +23 -0
  47. data/lib/ruby_ui/checkbox/checkbox_group.rb +20 -0
  48. data/lib/ruby_ui/clipboard/clipboard.rb +42 -0
  49. data/lib/ruby_ui/clipboard/clipboard_popover.rb +40 -0
  50. data/lib/ruby_ui/clipboard/clipboard_source.rb +19 -0
  51. data/lib/ruby_ui/clipboard/clipboard_trigger.rb +20 -0
  52. data/lib/ruby_ui/codeblock/codeblock.rb +102 -0
  53. data/lib/ruby_ui/collapsible/collapsible.rb +25 -0
  54. data/lib/ruby_ui/collapsible/collapsible_content.rb +18 -0
  55. data/lib/ruby_ui/collapsible/collapsible_trigger.rb +19 -0
  56. data/lib/ruby_ui/combobox/combobox.rb +24 -0
  57. data/lib/ruby_ui/combobox/combobox_content.rb +31 -0
  58. data/lib/ruby_ui/combobox/combobox_empty.rb +21 -0
  59. data/lib/ruby_ui/combobox/combobox_group.rb +38 -0
  60. data/lib/ruby_ui/combobox/combobox_input.rb +22 -0
  61. data/lib/ruby_ui/combobox/combobox_item.rb +53 -0
  62. data/lib/ruby_ui/combobox/combobox_list.rb +27 -0
  63. data/lib/ruby_ui/combobox/combobox_search_input.rb +56 -0
  64. data/lib/ruby_ui/combobox/combobox_separator.rb +15 -0
  65. data/lib/ruby_ui/combobox/combobox_trigger.rb +52 -0
  66. data/lib/ruby_ui/combobox/combobox_value.rb +27 -0
  67. data/lib/ruby_ui/command/command.rb +9 -0
  68. data/lib/ruby_ui/command/command_dialog.rb +17 -0
  69. data/lib/ruby_ui/command/command_dialog_content.rb +48 -0
  70. data/lib/ruby_ui/command/command_dialog_trigger.rb +29 -0
  71. data/lib/ruby_ui/command/command_empty.rb +19 -0
  72. data/lib/ruby_ui/command/command_group.rb +40 -0
  73. data/lib/ruby_ui/command/command_input.rb +56 -0
  74. data/lib/ruby_ui/command/command_item.rb +32 -0
  75. data/lib/ruby_ui/command/command_list.rb +17 -0
  76. data/lib/ruby_ui/context_menu/context_menu.rb +26 -0
  77. data/lib/ruby_ui/context_menu/context_menu_content.rb +25 -0
  78. data/lib/ruby_ui/context_menu/context_menu_item.rb +66 -0
  79. data/lib/ruby_ui/context_menu/context_menu_label.rb +24 -0
  80. data/lib/ruby_ui/context_menu/context_menu_separator.rb +19 -0
  81. data/lib/ruby_ui/context_menu/context_menu_trigger.rb +20 -0
  82. data/lib/ruby_ui/dialog/dialog.rb +25 -0
  83. data/lib/ruby_ui/dialog/dialog_content.rb +78 -0
  84. data/lib/ruby_ui/dialog/dialog_description.rb +17 -0
  85. data/lib/ruby_ui/dialog/dialog_footer.rb +17 -0
  86. data/lib/ruby_ui/dialog/dialog_header.rb +17 -0
  87. data/lib/ruby_ui/dialog/dialog_middle.rb +17 -0
  88. data/lib/ruby_ui/dialog/dialog_title.rb +17 -0
  89. data/lib/ruby_ui/dialog/dialog_trigger.rb +20 -0
  90. data/lib/ruby_ui/dropdown_menu/dropdown_menu.rb +26 -0
  91. data/lib/ruby_ui/dropdown_menu/dropdown_menu_content.rb +22 -0
  92. data/lib/ruby_ui/dropdown_menu/dropdown_menu_item.rb +28 -0
  93. data/lib/ruby_ui/dropdown_menu/dropdown_menu_label.rb +17 -0
  94. data/lib/ruby_ui/dropdown_menu/dropdown_menu_separator.rb +19 -0
  95. data/lib/ruby_ui/dropdown_menu/dropdown_menu_trigger.rb +18 -0
  96. data/lib/ruby_ui/form/form.rb +15 -0
  97. data/lib/ruby_ui/form/form_field.rb +20 -0
  98. data/lib/ruby_ui/form/form_field_error.rb +20 -0
  99. data/lib/ruby_ui/form/form_field_hint.rb +15 -0
  100. data/lib/ruby_ui/form/form_field_label.rb +15 -0
  101. data/lib/ruby_ui/hover_card/hover_card.rb +27 -0
  102. data/lib/ruby_ui/hover_card/hover_card_content.rb +22 -0
  103. data/lib/ruby_ui/hover_card/hover_card_trigger.rb +20 -0
  104. data/lib/ruby_ui/input/input.rb +26 -0
  105. data/lib/ruby_ui/link/link.rb +97 -0
  106. data/lib/ruby_ui/masked_input/masked_input.rb +15 -0
  107. data/lib/ruby_ui/pagination/pagination.rb +19 -0
  108. data/lib/ruby_ui/pagination/pagination_content.rb +17 -0
  109. data/lib/ruby_ui/pagination/pagination_ellipsis.rb +42 -0
  110. data/lib/ruby_ui/pagination/pagination_item.rb +28 -0
  111. data/lib/ruby_ui/popover/popover.rb +26 -0
  112. data/lib/ruby_ui/popover/popover_content.rb +27 -0
  113. data/lib/ruby_ui/popover/popover_trigger.rb +20 -0
  114. data/lib/ruby_ui/radio_button/radio_button.rb +22 -0
  115. data/lib/ruby_ui/select/select.rb +23 -0
  116. data/lib/ruby_ui/select/select_content.rb +32 -0
  117. data/lib/ruby_ui/select/select_group.rb +15 -0
  118. data/lib/ruby_ui/select/select_input.rb +22 -0
  119. data/lib/ruby_ui/select/select_item.rb +52 -0
  120. data/lib/ruby_ui/select/select_label.rb +17 -0
  121. data/lib/ruby_ui/select/select_trigger.rb +54 -0
  122. data/lib/ruby_ui/select/select_value.rb +27 -0
  123. data/lib/ruby_ui/sheet/sheet.rb +17 -0
  124. data/lib/ruby_ui/sheet/sheet_content.rb +77 -0
  125. data/lib/ruby_ui/sheet/sheet_description.rb +17 -0
  126. data/lib/ruby_ui/sheet/sheet_footer.rb +17 -0
  127. data/lib/ruby_ui/sheet/sheet_header.rb +17 -0
  128. data/lib/ruby_ui/sheet/sheet_middle.rb +17 -0
  129. data/lib/ruby_ui/sheet/sheet_title.rb +17 -0
  130. data/lib/ruby_ui/sheet/sheet_trigger.rb +17 -0
  131. data/lib/ruby_ui/shortcut_key/shortcut_key.rb +17 -0
  132. data/lib/ruby_ui/table/table.rb +19 -0
  133. data/lib/ruby_ui/table/table_body.rb +17 -0
  134. data/lib/ruby_ui/table/table_caption.rb +17 -0
  135. data/lib/ruby_ui/table/table_cell.rb +17 -0
  136. data/lib/ruby_ui/table/table_footer.rb +17 -0
  137. data/lib/ruby_ui/table/table_head.rb +17 -0
  138. data/lib/ruby_ui/table/table_header.rb +17 -0
  139. data/lib/ruby_ui/table/table_row.rb +17 -0
  140. data/lib/ruby_ui/tabs/tabs.rb +25 -0
  141. data/lib/ruby_ui/tabs/tabs_content.rb +26 -0
  142. data/lib/ruby_ui/tabs/tabs_list.rb +17 -0
  143. data/lib/ruby_ui/tabs/tabs_trigger.rb +28 -0
  144. data/lib/ruby_ui/textarea/textarea.rb +26 -0
  145. data/lib/ruby_ui/theme_toggle/theme_toggle.rb +41 -0
  146. data/lib/ruby_ui/tooltip/tooltip.rb +26 -0
  147. data/lib/ruby_ui/tooltip/tooltip_content.rb +26 -0
  148. data/lib/ruby_ui/tooltip/tooltip_trigger.rb +19 -0
  149. data/lib/ruby_ui/typography/heading.rb +60 -0
  150. data/lib/ruby_ui/typography/inline_code.rb +17 -0
  151. data/lib/ruby_ui/typography/inline_link.rb +22 -0
  152. data/lib/ruby_ui/typography/text.rb +53 -0
  153. data/lib/ruby_ui/typography/typography_blockquote.rb +17 -0
  154. data/lib/ruby_ui.rb +5 -0
  155. metadata +280 -0
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class AlertDialogTitle < Base
5
+ def view_template(&)
6
+ h2(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "text-lg font-semibold"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class AlertDialogTrigger < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ data: {action: "click->ruby-ui--alert-dialog#open"},
14
+ class: "inline-block"
15
+ }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class AspectRatio < Base
5
+ def initialize(aspect_ratio: "16/9", **attrs)
6
+ raise "aspect_ratio must be in the format of a string with a slash in the middle (eg. '16/9', '1/1')" unless aspect_ratio.is_a?(String) && aspect_ratio.include?("/")
7
+
8
+ @aspect_ratio = aspect_ratio
9
+ super(**attrs)
10
+ end
11
+
12
+ def view_template(&block)
13
+ div(
14
+ class: "relative w-full",
15
+ style: "padding-bottom: #{padding_bottom}%;"
16
+ ) do
17
+ div(**attrs, &block)
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def padding_bottom
24
+ @aspect_ratio.split("/").map(&:to_i).reverse.reduce(&:fdiv) * 100
25
+ end
26
+
27
+ def default_attrs
28
+ {
29
+ class: "bg-muted absolute inset-0 [&>img]:object-cover [&>img]:absolute [&>img]:h-full [&>img]:w-full [&>img]:inset-0 [&>img]:text-transparent"
30
+ }
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class Avatar < Base
5
+ SIZES = {
6
+ xs: "h-4 w-4 text-[0.5rem]",
7
+ sm: "h-6 w-6 text-xs",
8
+ md: "h-10 w-10 text-base",
9
+ lg: "h-14 w-14 text-xl",
10
+ xl: "h-20 w-20 text-3xl"
11
+ }
12
+
13
+ def initialize(size: :md, **attrs)
14
+ @size = size
15
+ @size_classes = SIZES[@size]
16
+ super(**attrs)
17
+ end
18
+
19
+ def view_template(&)
20
+ span(**attrs, &)
21
+ end
22
+
23
+ private
24
+
25
+ def default_attrs
26
+ {
27
+ class: ["relative flex shrink-0 overflow-hidden rounded-full", @size_classes]
28
+ }
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class AvatarFallback < Base
5
+ def view_template(&)
6
+ span(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "flex h-full w-full items-center justify-center rounded-full bg-muted"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class AvatarImage < Base
5
+ def initialize(src:, alt: "", **attrs)
6
+ @src = src
7
+ @alt = alt
8
+ super(**attrs)
9
+ end
10
+
11
+ def view_template
12
+ img(**attrs)
13
+ end
14
+
15
+ private
16
+
17
+ def default_attrs
18
+ {
19
+ loading: "lazy",
20
+ class: "aspect-square h-full w-full",
21
+ alt: @alt,
22
+ src: @src
23
+ }
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class Badge < Base
5
+ SIZES = {
6
+ sm: "px-1.5 py-0.5 text-xs",
7
+ md: "px-2 py-1 text-xs",
8
+ lg: "px-3 py-1 text-sm"
9
+ }
10
+
11
+ COLORS = {
12
+ primary: "text-primary bg-primary/5 ring-primary/20",
13
+ secondary: "text-secondary bg-secondary/10 ring-secondary/20",
14
+ outline: "text-foreground bg-background ring-border",
15
+ destructive: "text-destructive bg-destructive/10 ring-destructive/20",
16
+ success: "text-success bg-success/10 ring-success/20",
17
+ warning: "text-warning bg-warning/10 ring-warning/20",
18
+ slate: "text-slate-500 bg-slate-500/10 ring-slate-500/20",
19
+ gray: "text-gray-500 bg-gray-500/10 ring-gray-500/20",
20
+ zinc: "text-zinc-500 bg-zinc-500/10 ring-zinc-500/20",
21
+ neutral: "text-neutral-500 bg-neutral-500/10 ring-neutral-500/20",
22
+ stone: "text-stone-500 bg-stone-500/10 ring-stone-500/20",
23
+ red: "text-red-500 bg-red-500/10 ring-red-500/20",
24
+ orange: "text-orange-500 bg-orange-500/10 ring-orange-500/20",
25
+ amber: "text-amber-500 bg-amber-500/10 ring-amber-500/20",
26
+ yellow: "text-yellow-500 bg-yellow-500/10 ring-yellow-500/20",
27
+ lime: "text-lime-500 bg-lime-500/10 ring-lime-500/20",
28
+ green: "text-green-500 bg-green-500/10 ring-green-500/20",
29
+ emerald: "text-emerald-500 bg-emerald-500/10 ring-emerald-500/20",
30
+ teal: "text-teal-500 bg-teal-500/10 ring-teal-500/20",
31
+ cyan: "text-cyan-500 bg-cyan-500/10 ring-cyan-500/20",
32
+ sky: "text-sky-500 bg-sky-500/10 ring-sky-500/20",
33
+ blue: "text-blue-500 bg-blue-500/10 ring-blue-500/20",
34
+ indigo: "text-indigo-500 bg-indigo-500/10 ring-indigo-500/20",
35
+ violet: "text-violet-500 bg-violet-500/10 ring-violet-500/20",
36
+ purple: "text-purple-500 bg-purple-500/10 ring-purple-500/20",
37
+ fuchsia: "text-fuchsia-500 bg-fuchsia-500/10 ring-fuchsia-500/20",
38
+ pink: "text-pink-500 bg-pink-500/10 ring-pink-500/20",
39
+ rose: "text-rose-500 bg-rose-500/10 ring-rose-500/20"
40
+ }
41
+
42
+ def initialize(variant: :primary, size: :md, **args)
43
+ @variant = variant
44
+ @size = size
45
+ super(**args)
46
+ end
47
+
48
+ def view_template(&)
49
+ span(**attrs, &)
50
+ end
51
+
52
+ private
53
+
54
+ def default_attrs
55
+ {
56
+ class: ["inline-flex items-center rounded-md font-medium ring-1 ring-inset", SIZES[@size], COLORS[@variant]]
57
+ }
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tailwind_merge"
4
+
5
+ module RubyUI
6
+ class Base < Phlex::HTML
7
+ TAILWIND_MERGER = ::TailwindMerge::Merger.new.freeze unless defined?(TAILWIND_MERGER)
8
+
9
+ attr_reader :attrs
10
+
11
+ def initialize(**user_attrs)
12
+ @attrs = mix(default_attrs, user_attrs)
13
+ @attrs[:class] = TAILWIND_MERGER.merge(@attrs[:class]) if @attrs[:class]
14
+ end
15
+
16
+ private
17
+
18
+ def default_attrs
19
+ {}
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class Button < Base
5
+ def initialize(type: :button, variant: :primary, size: :md, icon: false, **attrs)
6
+ @type = type
7
+ @variant = variant.to_sym
8
+ @size = size.to_sym
9
+ @icon = icon
10
+ super(**attrs)
11
+ end
12
+
13
+ def view_template(&)
14
+ button(**attrs, &)
15
+ end
16
+
17
+ private
18
+
19
+ def size_classes
20
+ if @icon
21
+ case @size
22
+ when :sm then "h-6 w-6"
23
+ when :md then "h-9 w-9"
24
+ when :lg then "h-10 w-10"
25
+ when :xl then "h-12 w-12"
26
+ end
27
+ else
28
+ case @size
29
+ when :sm then "px-3 py-1.5 h-8 text-xs"
30
+ when :md then "px-4 py-2 h-9 text-sm"
31
+ when :lg then "px-4 py-2 h-10 text-base"
32
+ when :xl then "px-6 py-3 h-12 text-base"
33
+ end
34
+ end
35
+ end
36
+
37
+ def primary_classes
38
+ [
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
+ size_classes
41
+ ]
42
+ end
43
+
44
+ def link_classes
45
+ [
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
+ size_classes
48
+ ]
49
+ end
50
+
51
+ def secondary_classes
52
+ [
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
+ size_classes
55
+ ]
56
+ end
57
+
58
+ def destructive_classes
59
+ [
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
+ size_classes
62
+ ]
63
+ end
64
+
65
+ def outline_classes
66
+ [
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
+ size_classes
69
+ ]
70
+ end
71
+
72
+ def ghost_classes
73
+ [
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
+ size_classes
76
+ ]
77
+ end
78
+
79
+ def default_classes
80
+ case @variant
81
+ when :primary then primary_classes
82
+ when :link then link_classes
83
+ when :secondary then secondary_classes
84
+ when :destructive then destructive_classes
85
+ when :outline then outline_classes
86
+ when :ghost then ghost_classes
87
+ end
88
+ end
89
+
90
+ def default_attrs
91
+ {
92
+ type: @type,
93
+ class: default_classes
94
+ }
95
+ end
96
+ end
97
+ end
@@ -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
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class CalendarBody < Base
5
+ def view_template
6
+ table(**attrs)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ data: {
14
+ ruby_ui__calendar_target: "calendar"
15
+ }
16
+ }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class CalendarDays < Base
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
+
7
+ def view_template
8
+ render_selected_date_template
9
+ render_today_date_template
10
+ render_current_month_date_template
11
+ render_other_month_date_template
12
+ end
13
+
14
+ private
15
+
16
+ def render_selected_date_template
17
+ date_template("selectedDateTemplate") do
18
+ button(
19
+ data_day: "{{day}}",
20
+ data_action: "click->ruby-ui--calendar#selectDay",
21
+ name: "day",
22
+ class:
23
+ [
24
+ BASE_CLASS,
25
+ "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground"
26
+ ],
27
+ role: "gridcell",
28
+ tabindex: "0",
29
+ type: "button",
30
+ aria_selected: "true"
31
+ ) { "{{dayDate}}" }
32
+ end
33
+ end
34
+
35
+ def render_today_date_template
36
+ date_template("todayDateTemplate") do
37
+ button(
38
+ data_day: "{{day}}",
39
+ data_action: "click->ruby-ui--calendar#selectDay",
40
+ name: "day",
41
+ class:
42
+ [
43
+ BASE_CLASS,
44
+ "bg-accent text-accent-foreground hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground"
45
+ ],
46
+ role: "gridcell",
47
+ tabindex: "-1",
48
+ type: "button"
49
+ ) { "{{dayDate}}" }
50
+ end
51
+ end
52
+
53
+ def render_current_month_date_template
54
+ date_template("currentMonthDateTemplate") do
55
+ button(
56
+ data_day: "{{day}}",
57
+ data_action: "click->ruby-ui--calendar#selectDay",
58
+ name: "day",
59
+ class:
60
+ [
61
+ BASE_CLASS,
62
+ "bg-background text-foreground hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground"
63
+ ],
64
+ role: "gridcell",
65
+ tabindex: "-1",
66
+ type: "button"
67
+ ) { "{{dayDate}}" }
68
+ end
69
+ end
70
+
71
+ def render_other_month_date_template
72
+ date_template("otherMonthDateTemplate") do
73
+ button(
74
+ data_day: "{{day}}",
75
+ data_action: " click->ruby-ui--calendar#selectDay",
76
+ name: "day",
77
+ class:
78
+ [
79
+ BASE_CLASS,
80
+ "bg-background text-muted-foreground hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground"
81
+ ],
82
+ role: "gridcell",
83
+ tabindex: "-1",
84
+ type: "button"
85
+ ) { "{{dayDate}}" }
86
+ end
87
+ end
88
+
89
+ def date_template(target, &block)
90
+ template(data: {ruby_ui__calendar_target: target}) do
91
+ td(
92
+ class:
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",
94
+ role: "presentation",
95
+ &block
96
+ )
97
+ end
98
+ end
99
+
100
+ def default_attrs
101
+ {}
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class CalendarHeader < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "flex justify-center pt-1 relative items-center"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class CalendarNext < Base
5
+ def view_template(&block)
6
+ button(**attrs) do
7
+ icon
8
+ end
9
+ end
10
+
11
+ private
12
+
13
+ def icon
14
+ svg(
15
+ width: "15",
16
+ height: "15",
17
+ viewbox: "0 0 15 15",
18
+ fill: "none",
19
+ xmlns: "http://www.w3.org/2000/svg",
20
+ class: "h-4 w-4"
21
+ ) do |s|
22
+ s.path(
23
+ d:
24
+ "M6.1584 3.13508C6.35985 2.94621 6.67627 2.95642 6.86514 3.15788L10.6151 7.15788C10.7954 7.3502 10.7954 7.64949 10.6151 7.84182L6.86514 11.8418C6.67627 12.0433 6.35985 12.0535 6.1584 11.8646C5.95694 11.6757 5.94673 11.3593 6.1356 11.1579L9.565 7.49985L6.1356 3.84182C5.94673 3.64036 5.95694 3.32394 6.1584 3.13508Z",
25
+ fill: "currentColor",
26
+ fill_rule: "evenodd",
27
+ clip_rule: "evenodd"
28
+ )
29
+ end
30
+ end
31
+
32
+ def default_attrs
33
+ {
34
+ name: "next-month",
35
+ aria_label: "Go to next month",
36
+ class:
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
+ type: "button",
39
+ data_action: "click->ruby-ui--calendar#nextMonth"
40
+ }
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class CalendarPrev < Base
5
+ def view_template(&block)
6
+ button(**attrs) do
7
+ icon
8
+ end
9
+ end
10
+
11
+ private
12
+
13
+ def icon
14
+ svg(
15
+ width: "15",
16
+ height: "15",
17
+ viewbox: "0 0 15 15",
18
+ fill: "none",
19
+ xmlns: "http://www.w3.org/2000/svg",
20
+ class: "h-4 w-4"
21
+ ) do |s|
22
+ s.path(
23
+ d:
24
+ "M8.84182 3.13514C9.04327 3.32401 9.05348 3.64042 8.86462 3.84188L5.43521 7.49991L8.86462 11.1579C9.05348 11.3594 9.04327 11.6758 8.84182 11.8647C8.64036 12.0535 8.32394 12.0433 8.13508 11.8419L4.38508 7.84188C4.20477 7.64955 4.20477 7.35027 4.38508 7.15794L8.13508 3.15794C8.32394 2.95648 8.64036 2.94628 8.84182 3.13514Z",
25
+ fill: "currentColor",
26
+ fill_rule: "evenodd",
27
+ clip_rule: "evenodd"
28
+ )
29
+ end
30
+ end
31
+
32
+ def default_attrs
33
+ {
34
+ name: "previous-month",
35
+ aria_label: "Go to previous month",
36
+ class:
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
+ type: "button",
39
+ data_action: "click->ruby-ui--calendar#prevMonth"
40
+ }
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class CalendarTitle < Base
5
+ def initialize(default: "Month Year", **attrs)
6
+ @default = default
7
+ super(**attrs)
8
+ end
9
+
10
+ def view_template
11
+ div(**attrs) { @default }
12
+ end
13
+
14
+ private
15
+
16
+ def default_attrs
17
+ {
18
+ class: "text-sm font-medium",
19
+ aria_live: "polite",
20
+ role: "presentation",
21
+ data: {
22
+ ruby_ui__calendar_target: "title"
23
+ }
24
+ }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class CalendarWeekdays < Base
5
+ DAYS = %w[Monday Tuesday Wednesday Thursday Friday Saturday Sunday].freeze
6
+
7
+ def view_template
8
+ template(data: {ruby_ui__calendar_target: "weekdaysTemplate"}) do
9
+ thead(**attrs) do
10
+ tr(class: "flex") do
11
+ DAYS.each do |day|
12
+ render_day(day)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def render_day(day)
22
+ th(
23
+ scope: "col",
24
+ class: "text-muted-foreground rounded-md w-8 font-normal text-[0.8rem]",
25
+ aria_label: day
26
+ ) { day[0..1] }
27
+ end
28
+
29
+ def default_attrs
30
+ {}
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class Card < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "rounded-xl border bg-background shadow"
14
+ }
15
+ end
16
+ end
17
+ end