ruby_ui 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/ruby_ui/dependencies.yml +12 -2
  3. data/lib/generators/ruby_ui/javascript_utils.rb +0 -13
  4. data/lib/ruby_ui/accordion/accordion_controller.js +16 -9
  5. data/lib/ruby_ui/bubble/bubble.rb +37 -0
  6. data/lib/ruby_ui/bubble/bubble_content.rb +23 -0
  7. data/lib/ruby_ui/bubble/bubble_docs.rb +167 -0
  8. data/lib/ruby_ui/bubble/bubble_group.rb +18 -0
  9. data/lib/ruby_ui/bubble/bubble_reactions.rb +38 -0
  10. data/lib/ruby_ui/combobox/combobox.rb +3 -1
  11. data/lib/ruby_ui/combobox/combobox_checkbox.rb +8 -1
  12. data/lib/ruby_ui/combobox/combobox_controller.js +3 -2
  13. data/lib/ruby_ui/combobox/combobox_trigger.rb +1 -4
  14. data/lib/ruby_ui/context_menu/context_menu_content.rb +5 -6
  15. data/lib/ruby_ui/context_menu/context_menu_controller.js +87 -75
  16. data/lib/ruby_ui/data_table/data_table_column_toggle.rb +8 -4
  17. data/lib/ruby_ui/data_table/data_table_column_visibility_controller.js +12 -2
  18. data/lib/ruby_ui/dialog/dialog_content.rb +1 -1
  19. data/lib/ruby_ui/dropdown_menu/dropdown_menu.rb +0 -1
  20. data/lib/ruby_ui/dropdown_menu/dropdown_menu_controller.js +5 -1
  21. data/lib/ruby_ui/dropdown_menu/dropdown_menu_docs.rb +1 -1
  22. data/lib/ruby_ui/empty/empty.rb +18 -0
  23. data/lib/ruby_ui/empty/empty_content.rb +18 -0
  24. data/lib/ruby_ui/empty/empty_description.rb +18 -0
  25. data/lib/ruby_ui/empty/empty_docs.rb +69 -0
  26. data/lib/ruby_ui/empty/empty_header.rb +18 -0
  27. data/lib/ruby_ui/empty/empty_media.rb +31 -0
  28. data/lib/ruby_ui/empty/empty_title.rb +18 -0
  29. data/lib/ruby_ui/hover_card/hover_card_content.rb +5 -6
  30. data/lib/ruby_ui/hover_card/hover_card_controller.js +113 -76
  31. data/lib/ruby_ui/input_otp/input_otp.rb +42 -0
  32. data/lib/ruby_ui/input_otp/input_otp_controller.js +128 -0
  33. data/lib/ruby_ui/input_otp/input_otp_docs.rb +213 -0
  34. data/lib/ruby_ui/input_otp/input_otp_group.rb +15 -0
  35. data/lib/ruby_ui/input_otp/input_otp_separator.rb +39 -0
  36. data/lib/ruby_ui/input_otp/input_otp_slot.rb +33 -0
  37. data/lib/ruby_ui/message/message.rb +23 -0
  38. data/lib/ruby_ui/message/message_avatar.rb +18 -0
  39. data/lib/ruby_ui/message/message_content.rb +18 -0
  40. data/lib/ruby_ui/message/message_docs.rb +173 -0
  41. data/lib/ruby_ui/message/message_footer.rb +18 -0
  42. data/lib/ruby_ui/message/message_group.rb +18 -0
  43. data/lib/ruby_ui/message/message_header.rb +18 -0
  44. data/lib/ruby_ui/message_scroller/message_scroller.rb +18 -0
  45. data/lib/ruby_ui/message_scroller/message_scroller_button.rb +56 -0
  46. data/lib/ruby_ui/message_scroller/message_scroller_content.rb +23 -0
  47. data/lib/ruby_ui/message_scroller/message_scroller_controller.js +335 -0
  48. data/lib/ruby_ui/message_scroller/message_scroller_docs.rb +208 -0
  49. data/lib/ruby_ui/message_scroller/message_scroller_item.rb +28 -0
  50. data/lib/ruby_ui/message_scroller/message_scroller_provider.rb +34 -0
  51. data/lib/ruby_ui/message_scroller/message_scroller_viewport.rb +22 -0
  52. data/lib/ruby_ui/native_select/native_select_icon.rb +1 -1
  53. data/lib/ruby_ui/popover/popover_content.rb +2 -1
  54. data/lib/ruby_ui/popover/popover_controller.js +95 -32
  55. data/lib/ruby_ui/toast/toaster_controller.js +24 -8
  56. data/lib/ruby_ui.rb +1 -1
  57. metadata +34 -1
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class InputOtpSlot < Base
5
+ def initialize(index:, **attrs)
6
+ @index = index
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
+ aria_hidden: "true",
19
+ data: {
20
+ ruby_ui__input_otp_target: "slot",
21
+ index: @index
22
+ },
23
+ class: [
24
+ "relative flex h-9 w-9 items-center justify-center border-y border-r border-input text-sm shadow-xs transition-all",
25
+ "first:rounded-l-md first:border-l last:rounded-r-md",
26
+ "data-[active=true]:z-10 data-[active=true]:border-ring data-[active=true]:ring-2 data-[active=true]:ring-ring/50",
27
+ "data-[caret=true]:after:content-[''] data-[caret=true]:after:absolute data-[caret=true]:after:h-4 data-[caret=true]:after:w-px data-[caret=true]:after:animate-caret-blink data-[caret=true]:after:bg-foreground",
28
+ "aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40"
29
+ ]
30
+ }
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class Message < Base
5
+ def initialize(align: :start, **attrs)
6
+ @align = align
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: {slot: "message", align: @align},
19
+ class: "group/message relative flex w-full min-w-0 gap-2 text-sm data-[align=end]:flex-row-reverse"
20
+ }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class MessageAvatar < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ data: {slot: "message-avatar"},
14
+ class: "flex w-fit min-w-8 shrink-0 items-center justify-center self-end overflow-hidden rounded-full bg-muted group-has-data-[slot=message-footer]/message:-translate-y-8"
15
+ }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class MessageContent < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ data: {slot: "message-content"},
14
+ class: "flex w-full min-w-0 flex-col gap-2.5 wrap-break-word group-data-[align=end]/message:[&>[data-slot]]:self-end"
15
+ }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,173 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Views::Docs::Message < Views::Base
4
+ def view_template
5
+ component = "Message"
6
+
7
+ div(class: "max-w-2xl mx-auto w-full py-10 space-y-10") do
8
+ render Docs::Header.new(title: "Message", description: "A chat message layout that pairs an avatar with bubbles, headers, and footers. Built on top of Avatar and Bubble.")
9
+
10
+ Heading(level: 2) { "Usage" }
11
+
12
+ render Docs::VisualCodeExample.new(title: "Conversation", context: self) do
13
+ <<~RUBY
14
+ div(class: "flex flex-col gap-6") do
15
+ Message(align: :end) do
16
+ MessageAvatar do
17
+ Avatar(size: :sm) do
18
+ AvatarImage(src: "https://github.com/joeldrapper.png", alt: "@me")
19
+ AvatarFallback { "ME" }
20
+ end
21
+ end
22
+ MessageContent do
23
+ Bubble do
24
+ BubbleContent { "Deploying to prod real quick." }
25
+ end
26
+ end
27
+ end
28
+
29
+ Message do
30
+ MessageAvatar do
31
+ Avatar(size: :sm) do
32
+ AvatarImage(src: "https://github.com/shadcn.png", alt: "@rabbit")
33
+ AvatarFallback { "R" }
34
+ end
35
+ end
36
+ MessageContent do
37
+ Bubble(variant: :muted) do
38
+ BubbleContent { "It's 4:55 PM. On a Friday." }
39
+ end
40
+ end
41
+ end
42
+
43
+ Message(align: :end) do
44
+ MessageAvatar do
45
+ Avatar(size: :sm) do
46
+ AvatarImage(src: "https://github.com/joeldrapper.png", alt: "@me")
47
+ AvatarFallback { "ME" }
48
+ end
49
+ end
50
+ MessageContent do
51
+ Bubble do
52
+ BubbleContent { "It's a one-line change." }
53
+ end
54
+ MessageFooter { "Delivered" }
55
+ end
56
+ end
57
+
58
+ Message do
59
+ MessageAvatar do
60
+ Avatar(size: :sm) do
61
+ AvatarImage(src: "https://github.com/shadcn.png", alt: "@rabbit")
62
+ AvatarFallback { "R" }
63
+ end
64
+ end
65
+ MessageContent do
66
+ BubbleGroup do
67
+ Bubble(variant: :muted) do
68
+ BubbleContent { "It's always a one-line change 😭." }
69
+ end
70
+ Bubble(variant: :muted) do
71
+ BubbleContent { "Alright, let me take a look." }
72
+ BubbleReactions(role: "img", aria_label: "Reaction: thumbs up") do
73
+ span { "👍" }
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ RUBY
81
+ end
82
+
83
+ Heading(level: 2) { "With header" }
84
+
85
+ render Docs::VisualCodeExample.new(title: "Header and footer", context: self) do
86
+ <<~RUBY
87
+ Message do
88
+ MessageAvatar do
89
+ Avatar(size: :sm) do
90
+ AvatarImage(src: "https://github.com/shadcn.png", alt: "@oliver")
91
+ AvatarFallback { "OL" }
92
+ end
93
+ end
94
+ MessageContent do
95
+ MessageHeader { "Oliver" }
96
+ Bubble(variant: :muted) do
97
+ BubbleContent { "Pushed the fix, can you review?" }
98
+ end
99
+ MessageFooter { "9:41 AM" }
100
+ end
101
+ end
102
+ RUBY
103
+ end
104
+
105
+ Heading(level: 2) { "Alignment" }
106
+
107
+ render Docs::VisualCodeExample.new(title: "Sender and receiver", context: self) do
108
+ <<~RUBY
109
+ div(class: "flex flex-col gap-6") do
110
+ Message do
111
+ MessageAvatar do
112
+ Avatar(size: :sm) do
113
+ AvatarImage(src: "https://github.com/shadcn.png", alt: "@rabbit")
114
+ AvatarFallback { "R" }
115
+ end
116
+ end
117
+ MessageContent do
118
+ Bubble(variant: :muted) { BubbleContent { "Aligned to the start." } }
119
+ end
120
+ end
121
+ Message(align: :end) do
122
+ MessageAvatar do
123
+ Avatar(size: :sm) do
124
+ AvatarImage(src: "https://github.com/joeldrapper.png", alt: "@me")
125
+ AvatarFallback { "ME" }
126
+ end
127
+ end
128
+ MessageContent do
129
+ Bubble { BubbleContent { "Aligned to the end." } }
130
+ end
131
+ end
132
+ end
133
+ RUBY
134
+ end
135
+
136
+ Heading(level: 2) { "Group" }
137
+
138
+ render Docs::VisualCodeExample.new(title: "Message group", context: self) do
139
+ <<~RUBY
140
+ MessageGroup do
141
+ Message do
142
+ MessageAvatar do
143
+ Avatar(size: :sm) do
144
+ AvatarImage(src: "https://github.com/shadcn.png", alt: "@rabbit")
145
+ AvatarFallback { "R" }
146
+ end
147
+ end
148
+ MessageContent do
149
+ Bubble(variant: :muted) { BubbleContent { "First message." } }
150
+ end
151
+ end
152
+ Message do
153
+ MessageAvatar do
154
+ Avatar(size: :sm) do
155
+ AvatarImage(src: "https://github.com/shadcn.png", alt: "@rabbit")
156
+ AvatarFallback { "R" }
157
+ end
158
+ end
159
+ MessageContent do
160
+ Bubble(variant: :muted) { BubbleContent { "Second, tighter spacing." } }
161
+ end
162
+ end
163
+ end
164
+ RUBY
165
+ end
166
+
167
+ render Components::ComponentSetup::Tabs.new(component_name: component)
168
+
169
+ # components
170
+ render Docs::ComponentsTable.new(component_files(component))
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class MessageFooter < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ data: {slot: "message-footer"},
14
+ class: "flex max-w-full min-w-0 items-center px-3 text-xs font-medium text-muted-foreground group-data-[align=end]/message:justify-end group-has-data-[variant=ghost]/message:px-0"
15
+ }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class MessageGroup < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ data: {slot: "message-group"},
14
+ class: "flex min-w-0 flex-col gap-2"
15
+ }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class MessageHeader < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ data: {slot: "message-header"},
14
+ class: "flex max-w-full min-w-0 items-center px-3 text-xs font-medium text-muted-foreground group-has-data-[variant=ghost]/message:px-0"
15
+ }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class MessageScroller < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ data: {slot: "message-scroller"},
14
+ class: "group/message-scroller relative flex size-full min-h-0 flex-col overflow-hidden"
15
+ }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class MessageScrollerButton < Base
5
+ def initialize(direction: :end, **attrs)
6
+ @direction = direction
7
+ super(**attrs)
8
+ end
9
+
10
+ def view_template(&)
11
+ button(**attrs) do
12
+ if block_given?
13
+ yield
14
+ else
15
+ default_icon
16
+ span(class: "sr-only") { (@direction == :start) ? "Scroll to start" : "Scroll to end" }
17
+ end
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def default_attrs
24
+ {
25
+ type: "button",
26
+ tabindex: "-1",
27
+ data: {
28
+ slot: "message-scroller-button",
29
+ direction: @direction,
30
+ active: "false",
31
+ ruby_ui__message_scroller_target: "button",
32
+ action: "click->ruby-ui--message-scroller#jump"
33
+ },
34
+ class: "absolute left-1/2 z-10 -translate-x-1/2 inline-flex size-8 items-center justify-center rounded-full border border-border bg-background text-foreground shadow-sm transition-[translate,scale,opacity] duration-200 hover:bg-muted hover:text-foreground data-[active=false]:pointer-events-none data-[active=false]:scale-95 data-[active=false]:opacity-0 data-[active=true]:scale-100 data-[active=true]:opacity-100 data-[direction=end]:bottom-4 data-[direction=end]:data-[active=false]:translate-y-full data-[direction=start]:top-4 data-[direction=start]:data-[active=false]:-translate-y-full data-[direction=start]:[&_svg]:rotate-180"
35
+ }
36
+ end
37
+
38
+ def default_icon
39
+ svg(
40
+ xmlns: "http://www.w3.org/2000/svg",
41
+ width: "24",
42
+ height: "24",
43
+ viewbox: "0 0 24 24",
44
+ fill: "none",
45
+ stroke: "currentColor",
46
+ stroke_width: "2",
47
+ stroke_linecap: "round",
48
+ stroke_linejoin: "round",
49
+ class: "size-4"
50
+ ) do |s|
51
+ s.path(d: "M12 5v14")
52
+ s.path(d: "m19 12-7 7-7-7")
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class MessageScrollerContent < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ role: "log",
14
+ aria_relevant: "additions text",
15
+ data: {
16
+ slot: "message-scroller-content",
17
+ ruby_ui__message_scroller_target: "content"
18
+ },
19
+ class: "flex h-max min-h-full flex-col gap-8"
20
+ }
21
+ end
22
+ end
23
+ end