ruby_ui 1.0.0.beta1

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 (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 CardContent < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "p-6 pt-0"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class CardDescription < Base
5
+ def view_template(&)
6
+ p(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "text-sm text-muted-foreground"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class CardFooter < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "items-center p-6 pt-0"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class CardHeader < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "flex flex-col space-y-1.5 p-6"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class CardTitle < Base
5
+ def view_template(&)
6
+ h3(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "font-semibold leading-none tracking-tight"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class Chart < Base
5
+ def initialize(options: {}, **attrs)
6
+ @options = options.to_json
7
+ super(**attrs)
8
+ end
9
+
10
+ def view_template(&)
11
+ canvas(**attrs, &)
12
+ end
13
+
14
+ private
15
+
16
+ def default_attrs
17
+ {
18
+ data_controller: "ruby-ui--chart",
19
+ data_ruby_ui__chart_options_value: @options
20
+ }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class Checkbox < Base
5
+ def view_template
6
+ input(**attrs)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ type: "checkbox",
14
+ data: {
15
+ ruby_ui__form_field_target: "input",
16
+ ruby_ui__checkbox_group_target: "checkbox",
17
+ action: "change->ruby-ui--checkbox-group#onChange change->ruby-ui--form-field#onInput invalid->ruby-ui--form-field#onInvalid"
18
+ },
19
+ class: "peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 accent-primary"
20
+ }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class CheckboxGroup < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ role: "group",
14
+ data: {
15
+ controller: "ruby-ui--checkbox-group"
16
+ }
17
+ }
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class Clipboard < Base
5
+ def initialize(options: {}, success: "Copied!", error: "Copy Failed!", **attrs)
6
+ @options = options
7
+ @success = success
8
+ @error = error
9
+ super(**attrs)
10
+ end
11
+
12
+ def view_template(&block)
13
+ div(**attrs) do
14
+ div(&block)
15
+ success_popover
16
+ error_popover
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def success_popover
23
+ ClipboardPopover(type: :success) { @success }
24
+ end
25
+
26
+ def error_popover
27
+ ClipboardPopover(type: :error) { @error }
28
+ end
29
+
30
+ def default_attrs
31
+ {
32
+ data: {
33
+ controller: "ruby-ui--clipboard",
34
+ action: "click@window->ruby-ui--clipboard#onClickOutside",
35
+ ruby_ui__clipboard_success_value: @success,
36
+ ruby_ui__clipboard_error_value: @error,
37
+ ruby_ui__clipboard_options_value: @options.to_json
38
+ }
39
+ }
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class ClipboardPopover < Base
5
+ def initialize(type:, **attrs)
6
+ @type = type
7
+ super(**attrs)
8
+ end
9
+
10
+ def view_template(&block)
11
+ div(
12
+ class: "hidden",
13
+ style: "width: max-content; position: absolute; top: 0; left: 0;",
14
+ data: {ruby_ui__clipboard_target: clipboard_target}
15
+ ) do
16
+ div(**attrs, &block)
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def clipboard_target
23
+ case @type
24
+ when :success
25
+ "successPopover"
26
+ when :error
27
+ "errorPopover"
28
+ end
29
+ end
30
+
31
+ def default_attrs
32
+ {
33
+ data: {
34
+ state: :open
35
+ },
36
+ class: "z-50 rounded-md text-sm border bg-background px-2 py-0.5 text-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2"
37
+ }
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class ClipboardSource < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ data: {
14
+ ruby_ui__clipboard_target: "source"
15
+ }
16
+ }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class ClipboardTrigger < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ data: {
14
+ ruby_ui__clipboard_target: "trigger",
15
+ action: "click->ruby-ui--clipboard#copy"
16
+ }
17
+ }
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rouge"
4
+
5
+ module RubyUI
6
+ class Codeblock < Base
7
+ FORMATTER = ::Rouge::Formatters::HTML.new
8
+ ROUGE_CSS = Rouge::Themes::Github.mode(:dark).render(scope: ".highlight") # See themes here: https://rouge-ruby.github.io/docs/Rouge/CSSTheme.html
9
+
10
+ def initialize(code, syntax:, clipboard: true, clipboard_success: "Copied!", clipboard_error: "Copy failed!", **attrs)
11
+ @code = code
12
+ @syntax = syntax.to_sym
13
+ @clipboard = clipboard
14
+ @clipboard_success = clipboard_success
15
+ @clipboard_error = clipboard_error
16
+
17
+ if @syntax == :ruby || @syntax == :html
18
+ @code = @code.gsub(/(?:^|\G) {2}/m, " ")
19
+ end
20
+
21
+ super(**attrs)
22
+ end
23
+
24
+ def view_template
25
+ style { ROUGE_CSS } # For faster load times, move this to the head of your document. (Also move ROUGE_CSS value to head of document)
26
+ if @clipboard
27
+ with_clipboard
28
+ else
29
+ codeblock
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def default_attrs
36
+ {
37
+ style: {tab_size: 2},
38
+ class: "highlight text-sm max-h-[350px] after:content-none flex font-mono overflow-auto overflow-x rounded-md border !bg-stone-900 [&_pre]:p-4"
39
+ }
40
+ end
41
+
42
+ def with_clipboard
43
+ RubyUI.Clipboard(success: @clipboard_success, error: @clipboard_error, class: "relative") do
44
+ RubyUI.ClipboardSource do
45
+ codeblock
46
+ end
47
+ div(class: "absolute top-2 right-2") do
48
+ RubyUI.ClipboardTrigger do
49
+ RubyUI.Button(variant: :ghost, size: :sm, icon: true, class: "text-white hover:text-white hover:bg-white/20") { clipboard_icon }
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ def codeblock
56
+ div(**attrs) do
57
+ div(class: "after:content-none") do
58
+ pre { raw(safe(FORMATTER.format(lexer.lex(@code)))) }
59
+ end
60
+ end
61
+ end
62
+
63
+ def lexer
64
+ Rouge::Lexer.find(@syntax)
65
+ end
66
+
67
+ def clipboard_icon
68
+ svg(
69
+ xmlns: "http://www.w3.org/2000/svg",
70
+ fill: "none",
71
+ viewbox: "0 0 24 24",
72
+ stroke_width: "1.5",
73
+ stroke: "currentColor",
74
+ class: "w-4 h-4"
75
+ ) do |s|
76
+ s.path(
77
+ stroke_linecap: "round",
78
+ stroke_linejoin: "round",
79
+ d:
80
+ "M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"
81
+ )
82
+ end
83
+ end
84
+
85
+ def check_icon
86
+ svg(
87
+ xmlns: "http://www.w3.org/2000/svg",
88
+ fill: "none",
89
+ viewbox: "0 0 24 24",
90
+ stroke_width: "1.5",
91
+ stroke: "currentColor",
92
+ class: "w-4 h-4"
93
+ ) do |s|
94
+ s.path(
95
+ stroke_linecap: "round",
96
+ stroke_linejoin: "round",
97
+ d: "M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
98
+ )
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class Collapsible < Base
5
+ def initialize(open: false, **attrs)
6
+ @open = open
7
+ super(**attrs)
8
+ end
9
+
10
+ def view_template(&)
11
+ div(**attrs, &)
12
+ end
13
+
14
+ private
15
+
16
+ def default_attrs
17
+ {
18
+ data: {
19
+ controller: "ruby-ui--collapsible",
20
+ ruby_ui__collapsible_open_value: @open
21
+ }
22
+ }
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class CollapsibleContent < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ data: {ruby_ui__collapsible_target: "content"},
14
+ class: "overflow-y-hidden"
15
+ }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class CollapsibleTrigger < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ data: {
14
+ action: "click->ruby-ui--collapsible#toggle"
15
+ }
16
+ }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class Combobox < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ data: {
14
+ controller: "ruby-ui--combobox",
15
+ ruby_ui__combobox_open_value: "false",
16
+ action: "click@window->ruby-ui--combobox#onClickOutside",
17
+ ruby_ui__combobox_ruby_ui__combobox_content_outlet: ".combobox-content",
18
+ ruby_ui__combobox_ruby_ui__combobox_item_outlet: ".combobox-item"
19
+ },
20
+ class: "group/combobox w-full relative"
21
+ }
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class ComboboxContent < Base
5
+ def initialize(**attrs)
6
+ @id = "content#{SecureRandom.hex(4)}"
7
+ super
8
+ end
9
+
10
+ def view_template(&)
11
+ div(**attrs) do
12
+ div(class: "min-w-max max-h-[300px] overflow-y-auto overflow-x-hidden rounded-md border bg-popover text-popover-foreground shadow-md outline-none animate-out group-data-[ruby-ui--combobox-open-value=true]/combobox:animate-in fade-out-0 group-data-[ruby-ui--combobox-open-value=true]/combobox:fade-in-0 zoom-out-95 group-data-[ruby-ui--combobox-open-value=true]/combobox:zoom-in-95 slide-in-from-top-2", &)
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def default_attrs
19
+ {
20
+ id: @id,
21
+ role: "listbox",
22
+ data: {
23
+ controller: "ruby-ui--combobox-content",
24
+ ruby_ui__combobox_target: "content",
25
+ action: "keydown.enter->ruby-ui--combobox#onKeyEnter keydown.esc->ruby-ui--combobox#onEscKey keydown.down->ruby-ui--combobox#onKeyDown keydown.up->ruby-ui--combobox#onKeyUp"
26
+ },
27
+ class: "combobox-content hidden w-full absolute top-0 left-0 z-50"
28
+ }
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class ComboboxEmpty < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ role: "presentation",
14
+ class: "hidden py-6 text-center text-sm",
15
+ data: {
16
+ ruby_ui__combobox_content_target: "empty"
17
+ }
18
+ }
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class ComboboxGroup < Base
5
+ def initialize(heading: nil, **attrs)
6
+ @heading = heading
7
+ super(**attrs)
8
+ end
9
+
10
+ def view_template(&block)
11
+ div(**attrs) do
12
+ render_header if @heading
13
+ render_items(&block)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def render_header
20
+ div(group_heading: @heading, class: "px-2 py-1.5 text-xs font-medium text-muted-foreground") { @heading }
21
+ end
22
+
23
+ def render_items(&)
24
+ div(group_items: "", role: "group", &)
25
+ end
26
+
27
+ def default_attrs
28
+ {
29
+ class: "overflow-hidden p-1 text-foreground",
30
+ role: "presentation",
31
+ data: {
32
+ value: @heading,
33
+ ruby_ui__combobox_content_target: "group"
34
+ }
35
+ }
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class ComboboxInput < Base
5
+ def view_template
6
+ input(**attrs)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "hidden",
14
+ data: {
15
+ ruby_ui__combobox_target: "input",
16
+ ruby_ui__form_field_target: "input",
17
+ action: "change->ruby-ui--form-field#onChange invalid->ruby-ui--form-field#onInvalid"
18
+ }
19
+ }
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class ComboboxItem < Base
5
+ def initialize(value: nil, **attrs)
6
+ @value = value
7
+ super(**attrs)
8
+ end
9
+
10
+ def view_template(&block)
11
+ div(**attrs) do
12
+ div(class: "invisible group-aria-selected:visible") { icon }
13
+ block.call
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def icon
20
+ svg(
21
+ xmlns: "http://www.w3.org/2000/svg",
22
+ viewbox: "0 0 24 24",
23
+ fill: "none",
24
+ stroke: "currentColor",
25
+ class: "mr-2 h-4 w-4",
26
+ stroke_width: "2",
27
+ stroke_linecap: "round",
28
+ stroke_linejoin: "round"
29
+ ) do |s|
30
+ s.path(
31
+ d: "M20 6 9 17l-5-5"
32
+ )
33
+ end
34
+ end
35
+
36
+ def default_attrs
37
+ {
38
+ role: "option",
39
+ tabindex: "0",
40
+ class:
41
+ "combobox-item group relative flex cursor-pointer select-none items-center gap-x-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground aria-[current]:bg-accent aria-[current]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
42
+ data: {
43
+ value: @value,
44
+ ruby_ui__combobox_target: "item",
45
+ ruby_ui__combobox_content_target: "item",
46
+ controller: "ruby-ui--combobox-item",
47
+ action: "click->ruby-ui--combobox#onItemSelected"
48
+ },
49
+ aria_selected: "false"
50
+ }
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class ComboboxList < Base
5
+ def initialize(**attrs)
6
+ @id = "list#{SecureRandom.hex(4)}"
7
+ super
8
+ end
9
+
10
+ def view_template(&)
11
+ div(**attrs, &)
12
+ end
13
+
14
+ private
15
+
16
+ def default_attrs
17
+ {
18
+ id: @id,
19
+ data: {
20
+ ruby_ui__combobox_target: "list"
21
+ },
22
+ role: "listbox",
23
+ tabindex: "-1"
24
+ }
25
+ end
26
+ end
27
+ end