ariadne_view_components 0.0.43-aarch64-linux → 0.0.44-aarch64-linux

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 (102) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/app/components/ariadne/ariadne-form.d.ts +22 -0
  4. data/app/components/ariadne/ariadne-form.js +85 -0
  5. data/app/components/ariadne/ariadne-form.ts +96 -0
  6. data/app/components/ariadne/ariadne.d.ts +2 -0
  7. data/app/components/ariadne/ariadne.js +16 -0
  8. data/app/components/ariadne/ariadne.ts +21 -0
  9. data/app/components/ariadne/avatar_component.rb +81 -0
  10. data/app/components/ariadne/avatar_stack_component/avatar_stack_component.html.erb +12 -0
  11. data/app/components/ariadne/avatar_stack_component.rb +75 -0
  12. data/app/components/ariadne/base_button.rb +70 -0
  13. data/app/components/ariadne/base_component.rb +37 -0
  14. data/app/components/ariadne/blankslate_component/blankslate_component.html.erb +26 -0
  15. data/app/components/ariadne/blankslate_component.rb +148 -0
  16. data/app/components/ariadne/body_component.rb +30 -0
  17. data/app/components/ariadne/button_component/button_component.html.erb +4 -0
  18. data/app/components/ariadne/button_component.rb +165 -0
  19. data/app/components/ariadne/clipboard_copy_component/clipboard-copy-component.d.ts +4 -0
  20. data/app/components/ariadne/clipboard_copy_component/clipboard-copy-component.js +18 -0
  21. data/app/components/ariadne/clipboard_copy_component/clipboard-copy-component.ts +19 -0
  22. data/app/components/ariadne/clipboard_copy_component/clipboard_copy_component.html.erb +9 -0
  23. data/app/components/ariadne/clipboard_copy_component.rb +90 -0
  24. data/app/components/ariadne/comment_component/comment_component.html.erb +37 -0
  25. data/app/components/ariadne/comment_component.rb +71 -0
  26. data/app/components/ariadne/component.rb +127 -0
  27. data/app/components/ariadne/container_component/container_component.html.erb +3 -0
  28. data/app/components/ariadne/container_component.rb +25 -0
  29. data/app/components/ariadne/content.rb +12 -0
  30. data/app/components/ariadne/counter_component.rb +100 -0
  31. data/app/components/ariadne/details_component/details_component.html.erb +4 -0
  32. data/app/components/ariadne/details_component.rb +81 -0
  33. data/app/components/ariadne/dropdown/menu_component.html.erb +20 -0
  34. data/app/components/ariadne/dropdown/menu_component.rb +101 -0
  35. data/app/components/ariadne/dropdown/menu_component.ts +1 -0
  36. data/app/components/ariadne/dropdown_component/dropdown_component.html.erb +8 -0
  37. data/app/components/ariadne/dropdown_component.rb +172 -0
  38. data/app/components/ariadne/flash_component/flash_component.html.erb +31 -0
  39. data/app/components/ariadne/flash_component.rb +128 -0
  40. data/app/components/ariadne/flex_component/flex_component.html.erb +5 -0
  41. data/app/components/ariadne/flex_component.rb +56 -0
  42. data/app/components/ariadne/footer_component/footer_component.html.erb +7 -0
  43. data/app/components/ariadne/footer_component.rb +23 -0
  44. data/app/components/ariadne/grid_component/grid_component.html.erb +26 -0
  45. data/app/components/ariadne/grid_component.rb +67 -0
  46. data/app/components/ariadne/header_component/header_component.html.erb +29 -0
  47. data/app/components/ariadne/header_component.rb +111 -0
  48. data/app/components/ariadne/heading_component.rb +49 -0
  49. data/app/components/ariadne/heroicon_component/heroicon_component.html.erb +4 -0
  50. data/app/components/ariadne/heroicon_component.rb +166 -0
  51. data/app/components/ariadne/image_component.rb +53 -0
  52. data/app/components/ariadne/inline_flex_component/inline_flex_component.html.erb +6 -0
  53. data/app/components/ariadne/inline_flex_component.rb +72 -0
  54. data/app/components/ariadne/link_component.rb +65 -0
  55. data/app/components/ariadne/list_component/list_component.html.erb +6 -0
  56. data/app/components/ariadne/list_component.rb +70 -0
  57. data/app/components/ariadne/narrow_container_component/narrow_container_component.html.erb +3 -0
  58. data/app/components/ariadne/narrow_container_component.rb +30 -0
  59. data/app/components/ariadne/panel_bar_component/panel_bar_component.html.erb +20 -0
  60. data/app/components/ariadne/panel_bar_component.rb +80 -0
  61. data/app/components/ariadne/pill_component/pill_component.html.erb +3 -0
  62. data/app/components/ariadne/pill_component.rb +44 -0
  63. data/app/components/ariadne/rich_text_area_component/rich-text-area-component.d.ts +6 -0
  64. data/app/components/ariadne/rich_text_area_component/rich-text-area-component.js +38 -0
  65. data/app/components/ariadne/rich_text_area_component/rich-text-area-component.ts +47 -0
  66. data/app/components/ariadne/rich_text_area_component/rich_text_area_component.html.erb +6 -0
  67. data/app/components/ariadne/rich_text_area_component.rb +35 -0
  68. data/app/components/ariadne/slideover_component/slideover-component.d.ts +9 -0
  69. data/app/components/ariadne/slideover_component/slideover-component.js +11 -0
  70. data/app/components/ariadne/slideover_component/slideover-component.ts +17 -0
  71. data/app/components/ariadne/slideover_component/slideover_component.html.erb +9 -0
  72. data/app/components/ariadne/slideover_component.rb +66 -0
  73. data/app/components/ariadne/tab_component/tab_component.html.erb +3 -0
  74. data/app/components/ariadne/tab_component.rb +98 -0
  75. data/app/components/ariadne/tab_container_component/tab-container-component.d.ts +1 -0
  76. data/app/components/ariadne/tab_container_component/tab-container-component.js +23 -0
  77. data/app/components/ariadne/tab_container_component/tab-container-component.ts +24 -0
  78. data/app/components/ariadne/tab_container_component.erb +10 -0
  79. data/app/components/ariadne/tab_container_component.rb +68 -0
  80. data/app/components/ariadne/tab_nav_component/tab-nav-component.d.ts +9 -0
  81. data/app/components/ariadne/tab_nav_component/tab-nav-component.js +33 -0
  82. data/app/components/ariadne/tab_nav_component/tab-nav-component.ts +34 -0
  83. data/app/components/ariadne/tab_nav_component/tab_nav_component.html.erb +7 -0
  84. data/app/components/ariadne/tab_nav_component.rb +72 -0
  85. data/app/components/ariadne/table_nav_component/table_nav_component.html.erb +52 -0
  86. data/app/components/ariadne/table_nav_component.rb +338 -0
  87. data/app/components/ariadne/text.rb +25 -0
  88. data/app/components/ariadne/time_ago_component/time-ago-component.d.ts +1 -0
  89. data/app/components/ariadne/time_ago_component/time-ago-component.js +1 -0
  90. data/app/components/ariadne/time_ago_component/time-ago-component.ts +1 -0
  91. data/app/components/ariadne/time_ago_component.rb +56 -0
  92. data/app/components/ariadne/timeline_component/timeline_component.html.erb +19 -0
  93. data/app/components/ariadne/timeline_component.rb +34 -0
  94. data/app/components/ariadne/tooltip_component/tooltip-component.d.ts +24 -0
  95. data/app/components/ariadne/tooltip_component/tooltip-component.js +43 -0
  96. data/app/components/ariadne/tooltip_component/tooltip-component.ts +57 -0
  97. data/app/components/ariadne/tooltip_component/tooltip_component.html.erb +4 -0
  98. data/app/components/ariadne/tooltip_component.rb +108 -0
  99. data/lib/ariadne/view_components/engine.rb +0 -22
  100. data/lib/ariadne/view_components/version.rb +1 -1
  101. data/tailwind.config.js +10 -15
  102. metadata +98 -2
@@ -0,0 +1,338 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ariadne
4
+ # The `TableNavComponent` is used to render a table navigation.
5
+ class TableNavComponent < Ariadne::Component
6
+ DEFAULT_CLASSES = "ariadne-min-w-full ariadne-divide-y ariadne-divide-gray-300"
7
+
8
+ renders_one :header_row, "BaseRowItem::HeaderRowItem"
9
+
10
+ renders_many :rows, "BaseRowItem::RowItem"
11
+
12
+ renders_one :footer, "FooterItem"
13
+
14
+ DEFAULT_TAG = :table
15
+
16
+ # @example Default
17
+ #
18
+ # <%= render(Ariadne::TableNavComponent.new) do |table| %>
19
+ # <%= table.with_header_row do |header_row| %>
20
+ # <% header_row.with_selection_cell do %>
21
+ # Status
22
+ # <% end %>
23
+ # <% header_row.with_main_cell do %>
24
+ # State
25
+ # <% end %>
26
+ # <% header_row.with_action_cell do %>
27
+ # Labels
28
+ # <% end %>
29
+ # <% end %>
30
+ # <%= table.with_row do |row| %>
31
+ # <% row.with_selection_cell do %>
32
+ # "G"
33
+ # <% end %>
34
+ # <% row.with_main_cell do %>
35
+ # "California"
36
+ # <% end %>
37
+ # <% row.with_metadata_cell do %>
38
+ # "Labels"
39
+ # <% end %>
40
+ # <% end %>
41
+ # <%= table.with_row do |row| %>
42
+ # <% row.with_selection_cell do %>
43
+ # "V"
44
+ # <% end %>
45
+ # <% row.with_main_cell do %>
46
+ # "New York"
47
+ # <% end %>
48
+ # <% row.with_metadata_cell do %>
49
+ # "Labels"
50
+ # <% end %>
51
+ # <% end %>
52
+ # <%= table.with_row do |row| %>
53
+ # <% row.with_cell do %>
54
+ # "D"
55
+ # <% end %>
56
+ # <% row.with_selection_cell do %>
57
+ # "Texas"
58
+ # <% end %>
59
+ # <% row.with_metadata_cell do %>
60
+ # "Labels"
61
+ # <% end %>
62
+ # <% end %>
63
+ # <% end %>
64
+ #
65
+ # @param classes [String] <%= link_to_classes_docs %>
66
+ # @param attributes [Hash] <%= link_to_attributes_docs %>
67
+ def initialize(classes: "", attributes: {})
68
+ @tag = DEFAULT_TAG
69
+ @classes = merge_class_names(
70
+ DEFAULT_CLASSES,
71
+ classes,
72
+ )
73
+
74
+ @attributes = attributes
75
+ end
76
+
77
+ def has_header_row?
78
+ header_row.present?
79
+ end
80
+
81
+ def has_footer?
82
+ footer.present?
83
+ end
84
+
85
+ # This component is part of `TableNavComponent` and should not be
86
+ # used as a standalone component.
87
+ class BaseRowItem < Ariadne::TableNavComponent
88
+ BASE_ROW_CLASSES = ""
89
+
90
+ DEFAULT_TAG = :tr
91
+
92
+ BASE_SELECTION_CLASSES = ""
93
+ renders_one :selection_cell, lambda { |classes: "", attributes: {}|
94
+ actual_classes = merge_class_names(BASE_SELECTION_CLASSES, classes)
95
+ if header?
96
+ Ariadne::TableNavComponent::BaseCellItem::HeaderCellItem.new(classes: actual_classes, attributes: attributes)
97
+ else
98
+ Ariadne::TableNavComponent::BaseCellItem::CellItem.new(classes: actual_classes, attributes: attributes)
99
+ end
100
+ }
101
+
102
+ BASE_MAIN_CLASSES = "ariadne-pr-5"
103
+ renders_one :main_cell, lambda { |classes: "", attributes: {}|
104
+ actual_classes = merge_class_names(BASE_MAIN_CLASSES, classes)
105
+ if header?
106
+ Ariadne::TableNavComponent::BaseCellItem::HeaderCellItem.new(classes: actual_classes, attributes: attributes)
107
+ else
108
+ Ariadne::TableNavComponent::BaseCellItem::CellItem.new(classes: actual_classes, attributes: attributes)
109
+ end
110
+ }
111
+
112
+ attr_reader :classes, :attributes
113
+
114
+ def initialize(classes: "", attributes: {})
115
+ @tag = DEFAULT_TAG
116
+ @classes = merge_class_names(BASE_ROW_CLASSES, classes)
117
+
118
+ @attributes = attributes
119
+ end
120
+
121
+ private def linked?
122
+ @href.present?
123
+ end
124
+
125
+ private def header?
126
+ @header.present?
127
+ end
128
+
129
+ def call
130
+ Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes)
131
+ end
132
+
133
+ # This component is part of `TableNavComponent` and should not be
134
+ # used as a standalone component.
135
+ class RowItem < Ariadne::TableNavComponent::BaseRowItem
136
+ DEFAULT_ROW_CLASSES = "ariadne-bg-white"
137
+ DEFAULT_METADATA_CLASSES = ""
138
+ renders_many :metadata_cells, lambda { |classes: "", attributes: {}|
139
+ actual_classes = merge_class_names(DEFAULT_METADATA_CLASSES, classes)
140
+ Ariadne::TableNavComponent::BaseCellItem::CellItem.new(classes: actual_classes, attributes: attributes)
141
+ }
142
+
143
+ attr_reader :href
144
+
145
+ def initialize(classes: "", attributes: {})
146
+ @header = false
147
+
148
+ actual_classes = merge_class_names(DEFAULT_ROW_CLASSES, classes)
149
+
150
+ super(classes: actual_classes, attributes: attributes)
151
+ end
152
+ end
153
+
154
+ # This component is part of `TableNavComponent` and should not be
155
+ # used as a standalone component.
156
+ class HeaderRowItem < Ariadne::TableNavComponent::BaseRowItem
157
+ DEFAULT_HEADER_ROW_CLASSES = "ariadne-bg-gray-50 ariadne-text-left"
158
+
159
+ renders_many :action_cells, lambda { |classes: "", attributes: {}|
160
+ Ariadne::TableNavComponent::BaseCellItem::HeaderCellItem.new(classes: classes, attributes: attributes)
161
+ }
162
+
163
+ def initialize(classes: "", attributes: {})
164
+ @header = true
165
+
166
+ actual_classes = merge_class_names(
167
+ DEFAULT_HEADER_ROW_CLASSES,
168
+ classes,
169
+ )
170
+
171
+ super(classes: actual_classes, attributes: attributes)
172
+ end
173
+ end
174
+ end
175
+
176
+ # This component is part of `TableNavComponent` and should not be
177
+ # used as a standalone component.
178
+ class BaseCellItem < Ariadne::TableNavComponent
179
+ DEFAULT_CELL_CLASSES = "ariadne-py-3.5 ariadne-pl-4 ariadne-pr-3 ariadne-text-left ariadne-text-sm ariadne-text-gray-900"
180
+
181
+ attr_writer :first, :last
182
+
183
+ def initialize(classes: "", attributes: {})
184
+ @classes = merge_class_names(
185
+ DEFAULT_CELL_CLASSES,
186
+ classes,
187
+ )
188
+
189
+ @attributes = attributes
190
+ end
191
+
192
+ def call
193
+ render(Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes)) do
194
+ content
195
+ end
196
+ end
197
+
198
+ # This component is part of `TableNavComponent` and should not be
199
+ # used as a standalone component.
200
+ class HeaderCellItem < Ariadne::TableNavComponent::BaseCellItem
201
+ DEFAULT_HEADER_CELL_CLASSES = "ariadne-py-3.5 ariadne-pl-4 ariadne-pr-3 ariadne-text-left ariadne-text-sm ariadne-font-semibold ariadne-text-gray-900 sm:ariadne-pl-6 md:ariadne-pl-0"
202
+
203
+ DEFAULT_TAG = :th
204
+
205
+ WIDTH_CLASSES = {
206
+ none: "ariadne-flex-none ariadne-w-14 ariadne-px-4",
207
+ default: "ariadne-flex-initial",
208
+ narrow: "ariadne-flex-initial ariadne-w-1/5 ariadne-text-right",
209
+ wide: "ariadne-flex-grow ariadne-w-3/5 sm:ariadne-pl-6",
210
+ }
211
+
212
+ # TODO: add one_of check for width
213
+ def initialize(classes: "", attributes: {})
214
+ @tag = DEFAULT_TAG
215
+ actual_classes = merge_class_names(DEFAULT_HEADER_CELL_CLASSES, classes)
216
+ attributes["scope"] = "col"
217
+ super(classes: actual_classes, attributes: attributes)
218
+ end
219
+ end
220
+
221
+ # This component is part of `TableNavComponent` and should not be
222
+ # used as a standalone component.
223
+ class CellItem < Ariadne::TableNavComponent::BaseCellItem
224
+ DEFAULT_CELL_CLASSES = ""
225
+
226
+ DEFAULT_TAG = :td
227
+
228
+ # TODO: add one_of check for width
229
+ def initialize(classes: "", attributes: {})
230
+ @tag = DEFAULT_TAG
231
+ actual_classes = merge_class_names(DEFAULT_CELL_CLASSES, classes)
232
+ super(classes: actual_classes, attributes: attributes)
233
+ end
234
+ end
235
+ end
236
+
237
+ # This component is part of `TableNavComponent` and should not be
238
+ # used as a standalone component.
239
+ class FooterItem < Ariadne::TableNavComponent
240
+ DEFAULT_FOOTER_CLASSES = "ariadne-border-none ariadne-flex ariadne-items-center ariadne-justify-between ariadne-px-4 ariadne-py-3 sm:ariadne-px-6"
241
+
242
+ DEFAULT_RESULT_CLASSES = "ariadne-text-sm ariadne-text-gray-700"
243
+ renders_one :records_info, lambda { |classes: "", attributes: {}|
244
+ actual_classes = merge_class_names(DEFAULT_RESULT_CLASSES, classes)
245
+ Ariadne::BaseComponent.new(tag: :p, classes: actual_classes, attributes: attributes)
246
+ }
247
+
248
+ renders_one :pagination_bar, "Ariadne::TableNavComponent::PaginationBarItem"
249
+
250
+ attr_reader :classes, :attributes
251
+
252
+ def initialize(classes: "", attributes: {})
253
+ @classes = merge_class_names(
254
+ DEFAULT_FOOTER_CLASSES,
255
+ classes,
256
+ )
257
+
258
+ @attributes = attributes
259
+ end
260
+
261
+ def call
262
+ render(Ariadne::BaseComponent.new(tag: :div, classes: @classes, attributes: @attributes)) do
263
+ records_info.to_s + pagination_bar.to_s
264
+ end
265
+ end
266
+ end
267
+
268
+ # This component is part of `TableNavComponent` and should not be
269
+ # used as a standalone component.
270
+ class PaginationBarItem < Ariadne::FooterComponent
271
+ DEFAULT_PREV_PAGE_CLASSES = "ariadne-relative ariadne-inline-flex ariadne-items-center ariadne-rounded-l-md ariadne-border ariadne-border-gray-300 ariadne-bg-white ariadne-px-2 ariadne-py-2 ariadne-text-sm ariadne-font-medium ariadne-text-gray-500 hover:ariadne-bg-gray-50 focus:ariadne-z-20"
272
+ renders_one :prev_page, lambda { |disabled: false, href:, classes: "", attributes: {}|
273
+ if disabled
274
+ actual_classes = merge_class_names(DEFAULT_PREV_PAGE_CLASSES, "ariadne-bg-gray-50", classes)
275
+
276
+ render(Ariadne::BaseComponent.new(tag: :span, classes: actual_classes, attributes: attributes)) do
277
+ render(Ariadne::HeroiconComponent.new(icon: "chevron-left", size: :sm, variant: :mini, text_attributes: { "aria-hidden": true }, text_classes: "ariadne-sr-only"))
278
+ end
279
+ else
280
+ actual_classes = merge_class_names(DEFAULT_PREV_PAGE_CLASSES, "hover:ariadne-bg-gray-50", classes)
281
+ attributes[:"aria-label"] = "previous"
282
+
283
+ render(Ariadne::LinkComponent.new(href: href, classes: actual_classes, attributes: attributes)) do
284
+ render(Ariadne::HeroiconComponent.new(icon: "chevron-left", size: :sm, variant: :mini, text_attributes: { "aria-hidden": true }, text_classes: "ariadne-sr-only"))
285
+ end
286
+ end
287
+ }
288
+
289
+ DEFAULT_PAGE_CLASSES = "ariadne-relative ariadne-inline-flex ariadne-items-center ariadne-border ariadne-border-gray-300 ariadne-bg-white ariadne-px-4 ariadne-py-2 ariadne-text-sm ariadne-font-medium ariadne-text-gray-500 hover:ariadne-bg-gray-50 focus:ariadne-z-20"
290
+ DEFAULT_CURRENT_PAGE_CLASSES = "ariadne-relative ariadne-z-10 ariadne-inline-flex ariadne-items-center ariadne-border ariadne-border-slate-500 ariadne-bg-slate-50 ariadne-px-4 ariadne-py-2 ariadne-text-sm ariadne-font-medium ariadne-text-slate-600 focus:ariadne-z-20"
291
+ DEFAULT_GAP_CLASSES = " ariadne-relative ariadne-inline-flex ariadne-items-center ariadne-border ariadne-border-gray-300 ariadne-bg-white ariadne-px-4 ariadne-py-2 ariadne-text-sm ariadne-font-medium ariadne-text-gray-700"
292
+ renders_many :items, lambda { |link:, classes: "", attributes: {}|
293
+ page, href = link
294
+ if page.is_a?(Integer)
295
+ actual_classes = merge_class_names(DEFAULT_PAGE_CLASSES, classes)
296
+ render(Ariadne::LinkComponent.new(href: href, classes: actual_classes, attributes: attributes)) { page.to_s }
297
+ elsif page.is_a?(String)
298
+ actual_classes = merge_class_names(DEFAULT_CURRENT_PAGE_CLASSES, classes)
299
+ render(Ariadne::LinkComponent.new(href: href, classes: actual_classes, attributes: attributes)) { page.to_s }
300
+ elsif page == :gap
301
+ actual_classes = merge_class_names(DEFAULT_GAP_CLASSES, classes)
302
+ render(Ariadne::BaseComponent.new(tag: :span, classes: actual_classes, attributes: attributes)) { h(href.to_s) }
303
+ end
304
+ }
305
+
306
+ DEFAULT_NEXT_PAGE_CLASSES = "ariadne-relative ariadne-inline-flex ariadne-items-center ariadne-rounded-r-md ariadne-border ariadne-border-gray-300 ariadne-bg-white ariadne-px-2 ariadne-py-2 ariadne-text-sm ariadne-font-medium ariadne-text-gray-500 hover:ariadne-bg-gray-50 focus:ariadne-z-20"
307
+ renders_one :next_page, lambda { |disabled: false, href:, classes: "", attributes: {}|
308
+ if disabled
309
+ actual_classes = merge_class_names(DEFAULT_NEXT_PAGE_CLASSES, "ariadne-bg-gray-50", classes)
310
+
311
+ render(Ariadne::BaseComponent.new(tag: :span, classes: actual_classes, attributes: attributes)) do
312
+ render(Ariadne::HeroiconComponent.new(icon: "chevron-right", size: :sm, variant: :mini, text_attributes: { "aria-hidden": true }, text_classes: "ariadne-sr-only"))
313
+ end
314
+ else
315
+ actual_classes = merge_class_names(DEFAULT_NEXT_PAGE_CLASSES, "hover:ariadne-bg-gray-50", classes)
316
+ attributes[:"aria-label"] = "next"
317
+
318
+ render(Ariadne::LinkComponent.new(href: href, classes: actual_classes, attributes: attributes)) do
319
+ render(Ariadne::HeroiconComponent.new(icon: "chevron-right", size: :sm, variant: :mini, text_attributes: { "aria-hidden": true }, text_classes: "ariadne-sr-only"))
320
+ end
321
+ end
322
+ }
323
+
324
+ attr_reader :classes, :attributes
325
+
326
+ DEFAULT_PAGINATOR_CLASSES = "ariadne-flex ariadne-items-center ariadne-justify-between ariadne-m-10"
327
+ def initialize(classes: "", attributes: {})
328
+ @classes = merge_class_names(
329
+ DEFAULT_PAGINATOR_CLASSES,
330
+ classes,
331
+ )
332
+
333
+ @attributes = attributes
334
+ @attributes[:"aria-label"] ||= "paginator"
335
+ end
336
+ end
337
+ end
338
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ariadne
4
+ # `Text` is a wrapper component that will apply typography styles to the text inside.
5
+ class Text < Ariadne::Component
6
+ DEFAULT_TAG = :span
7
+
8
+ # @example Default
9
+ # <%= render(Ariadne::Text.new(tag: :p, attributes: { font_weight: :bold })) { "Bold Text" } %>
10
+ # <%= render(Ariadne::Text.new(tag: :p, attributes: { color: :danger })) { "Danger Text" } %>
11
+ #
12
+ # @param tag [Symbol, String] The rendered tag name
13
+ # @param classes [String] <%= link_to_classes_docs %>
14
+ # @param attributes [Hash] <%= link_to_attributes_docs %>
15
+ def initialize(tag: DEFAULT_TAG, classes: "", attributes: {})
16
+ @tag = tag
17
+ @classes = classes
18
+ @attributes = attributes
19
+ end
20
+
21
+ def call
22
+ render(Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes)) { content }
23
+ end
24
+ end
25
+ end
@@ -0,0 +1 @@
1
+ import '@github/time-elements';
@@ -0,0 +1 @@
1
+ import '@github/time-elements';
@@ -0,0 +1 @@
1
+ import '@github/time-elements'
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ariadne
4
+ # Displays a time ariadne-relative to how long ago it was. This component requires JavaScript.
5
+ class TimeAgoComponent < Ariadne::Component
6
+ DEFAULT_TAG = :"time-ago"
7
+ TAG_OPTIONS = [DEFAULT_TAG].freeze
8
+
9
+ DEFAULT_CLASSES = "ariadne-whitespace-nowrap"
10
+
11
+ # @example Default
12
+ #
13
+ # <%= render(Ariadne::TimeAgoComponent.new(time: Time.now)) %>
14
+ #
15
+ # @param tag [Symbol, String] The rendered tag name.
16
+ # @param time [Time] The time to be formatted
17
+ # @param micro [Boolean] If true then the text will be formatted in "micro" mode, using as few characters as possible
18
+ # @param classes [String] <%%= link_to_classes_docs %>
19
+ # @param attributes [Hash] <%= link_to_attributes_docs %>
20
+ def initialize(tag: DEFAULT_TAG, time:, micro: false, classes: "", attributes: {})
21
+ @tag = check_incoming_tag(DEFAULT_TAG, tag)
22
+ @classes = merge_class_names(
23
+ DEFAULT_CLASSES,
24
+ classes,
25
+ )
26
+
27
+ @time = time
28
+ @micro = micro
29
+ @attributes = attributes
30
+ @attributes[:datetime] = @time.utc.iso8601
31
+ @attributes[:format] = "micro" if @micro
32
+ end
33
+
34
+ def call
35
+ render(Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes)) { time_in_words }
36
+ end
37
+
38
+ private def time_in_words
39
+ return @time.in_time_zone.strftime("%b %-d, %Y") unless @micro
40
+
41
+ seconds_ago = Time.current - @time
42
+
43
+ if seconds_ago < 1.minute
44
+ "1m"
45
+ elsif seconds_ago >= 1.minute && seconds_ago < 1.hour
46
+ "#{(seconds_ago / 60).floor}m"
47
+ elsif seconds_ago >= 1.hour && seconds_ago < 1.day
48
+ "#{(seconds_ago / 60 / 60).floor}h"
49
+ elsif seconds_ago >= 1.day && seconds_ago < 1.year
50
+ "#{(seconds_ago / 60 / 60 / 24).floor}d"
51
+ elsif seconds_ago >= 1.year
52
+ "#{(seconds_ago / 60 / 60 / 24 / 365).floor}y"
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,19 @@
1
+ <%= render Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes) do %>
2
+ <div>
3
+ <div class="ariadne-divide-y ariadne-divide-gray-200">
4
+ <div class="ariadne-pb-4">
5
+ <h2 id="activity-title" class="ariadne-text-lg ariadne-font-medium ariadne-text-gray-900">Timeline</h2>
6
+ </div>
7
+ <div class="ariadne-pt-6">
8
+ <!-- Activity feed-->
9
+ <div class="ariadne-flow-root">
10
+ <ul role="list" class="ariadne--mb-8">
11
+ <% items.each do %>
12
+ <%= items %>
13
+ <% end %>
14
+ </ul>
15
+ </div>
16
+ </div>
17
+ </div>
18
+ </div>
19
+ <% end %>
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ariadne
4
+ # Represents a linear timeline of events. Typically, this is shown
5
+ # as part of the Conversation component.
6
+ class TimelineComponent < Ariadne::Component
7
+ DEFAULT_TAG = :div
8
+ DEFAULT_CLASSES = ""
9
+
10
+ # The sub-items(s) to render
11
+ renders_many :items, lambda { |static_content = nil, &block|
12
+ next static_content if static_content.present?
13
+
14
+ view_context.capture { block&.call }
15
+ }
16
+
17
+ # @example Default
18
+ #
19
+ # <%= render(Ariadne::TimelineComponent.new) { "Example" } %>
20
+ #
21
+ # @param tag [Symbol, String] The rendered tag name
22
+ # @param classes [String] <%= link_to_classes_docs %>
23
+ # @param attributes [Hash] <%= link_to_attributes_docs %>
24
+ def initialize(tag: DEFAULT_TAG, classes: "", attributes: {})
25
+ @tag = check_incoming_tag(DEFAULT_TAG, tag)
26
+ @classes = merge_class_names(
27
+ DEFAULT_CLASSES,
28
+ classes,
29
+ )
30
+
31
+ @attributes = attributes
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,24 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+ import type { Instance, Placement } from '@popperjs/core';
3
+ export default class TooltipComponent extends Controller {
4
+ static targets: string[];
5
+ readonly triggerTarget: HTMLElement;
6
+ readonly tooltipTarget: HTMLElement;
7
+ static values: {
8
+ placement: {
9
+ type: StringConstructor;
10
+ default: string;
11
+ };
12
+ offset: {
13
+ type: ArrayConstructor;
14
+ default: number[];
15
+ };
16
+ };
17
+ readonly placementValue: Placement;
18
+ readonly offsetValue: Array<number>;
19
+ popperInstance: Instance;
20
+ connect(): void;
21
+ disconnect(): void;
22
+ show(): void;
23
+ hide(): void;
24
+ }
@@ -0,0 +1,43 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+ import { createPopper } from '@popperjs/core';
3
+ class TooltipComponent extends Controller {
4
+ // Create a new Popper instance
5
+ connect() {
6
+ this.popperInstance = createPopper(this.triggerTarget, this.tooltipTarget, {
7
+ placement: this.placementValue,
8
+ modifiers: [
9
+ {
10
+ name: 'offset',
11
+ options: {
12
+ offset: this.offsetValue,
13
+ },
14
+ },
15
+ ],
16
+ });
17
+ }
18
+ // Destroy the Popper instance
19
+ disconnect() {
20
+ if (this.popperInstance) {
21
+ this.popperInstance.destroy();
22
+ }
23
+ }
24
+ show() {
25
+ this.tooltipTarget.setAttribute('data-tooltip-show', '');
26
+ this.tooltipTarget.classList.remove('ariadne-invisible');
27
+ // We need to tell Popper to update the tooltip position
28
+ // after we show the tooltip, otherwise it will be incorrect
29
+ this.popperInstance.update();
30
+ this.dispatch('shown', { detail: { trigger: this.triggerTarget, tooltip: this.tooltipTarget } });
31
+ }
32
+ hide() {
33
+ this.tooltipTarget.removeAttribute('data-tooltip-show');
34
+ this.tooltipTarget.classList.add('ariadne-invisible');
35
+ this.dispatch('ariadne-hidden', { detail: { trigger: this.triggerTarget, tooltip: this.tooltipTarget } });
36
+ }
37
+ }
38
+ TooltipComponent.targets = ['trigger', 'tooltip'];
39
+ TooltipComponent.values = {
40
+ placement: { type: String, default: 'top' },
41
+ offset: { type: Array, default: [0, 8] },
42
+ };
43
+ export default TooltipComponent;
@@ -0,0 +1,57 @@
1
+ import {Controller} from '@hotwired/stimulus'
2
+ import {createPopper} from '@popperjs/core'
3
+ import type {Instance, Placement} from '@popperjs/core'
4
+
5
+ export default class TooltipComponent extends Controller {
6
+ static targets = ['trigger', 'tooltip']
7
+ declare readonly triggerTarget: HTMLElement
8
+ declare readonly tooltipTarget: HTMLElement
9
+
10
+ static values = {
11
+ placement: {type: String, default: 'top'},
12
+ offset: {type: Array, default: [0, 8]},
13
+ }
14
+ declare readonly placementValue: Placement
15
+ declare readonly offsetValue: Array<number>
16
+
17
+ popperInstance: Instance
18
+
19
+ // Create a new Popper instance
20
+ connect() {
21
+ this.popperInstance = createPopper(this.triggerTarget, this.tooltipTarget, {
22
+ placement: this.placementValue,
23
+ modifiers: [
24
+ {
25
+ name: 'offset',
26
+ options: {
27
+ offset: this.offsetValue,
28
+ },
29
+ },
30
+ ],
31
+ })
32
+ }
33
+
34
+ // Destroy the Popper instance
35
+ disconnect() {
36
+ if (this.popperInstance) {
37
+ this.popperInstance.destroy()
38
+ }
39
+ }
40
+
41
+ show() {
42
+ this.tooltipTarget.setAttribute('data-tooltip-show', '')
43
+ this.tooltipTarget.classList.remove('ariadne-invisible')
44
+
45
+ // We need to tell Popper to update the tooltip position
46
+ // after we show the tooltip, otherwise it will be incorrect
47
+ this.popperInstance.update()
48
+ this.dispatch('shown', {detail: {trigger: this.triggerTarget, tooltip: this.tooltipTarget}})
49
+ }
50
+
51
+ hide() {
52
+ this.tooltipTarget.removeAttribute('data-tooltip-show')
53
+ this.tooltipTarget.classList.add('ariadne-invisible')
54
+
55
+ this.dispatch('ariadne-hidden', {detail: {trigger: this.triggerTarget, tooltip: this.tooltipTarget}})
56
+ }
57
+ }
@@ -0,0 +1,4 @@
1
+ <%= render Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes) do %>
2
+ <span><%= @text %></span>
3
+ <span class="ariadne-tooltip-arrow ariadne-absolute ariadne-block" data-popper-arrow></span>
4
+ <% end %>