primer_view_components 0.0.23 → 0.0.28

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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +98 -0
  3. data/app/assets/javascripts/primer_view_components.js +1 -1
  4. data/app/assets/javascripts/primer_view_components.js.map +1 -1
  5. data/app/assets/javascripts/primer_view_components.js.map.orig +5 -0
  6. data/app/assets/javascripts/primer_view_components.js.orig +6 -0
  7. data/app/components/primer/auto_complete_component.d.ts +1 -0
  8. data/app/components/primer/auto_complete_component.html.erb +5 -0
  9. data/app/components/primer/auto_complete_component.js +1 -0
  10. data/app/components/primer/auto_complete_component.rb +98 -0
  11. data/app/components/primer/auto_complete_component.ts +1 -0
  12. data/app/components/primer/auto_complete_item_component.rb +40 -0
  13. data/app/components/primer/avatar_component.rb +8 -9
  14. data/app/components/primer/base_component.rb +7 -15
  15. data/app/components/primer/blankslate_component.html.erb +1 -5
  16. data/app/components/primer/blankslate_component.rb +2 -0
  17. data/app/components/primer/border_box_component.rb +32 -6
  18. data/app/components/primer/box_component.rb +3 -5
  19. data/app/components/primer/breadcrumb_component.html.erb +1 -2
  20. data/app/components/primer/breadcrumb_component.rb +24 -12
  21. data/app/components/primer/component.rb +1 -13
  22. data/app/components/primer/counter_component.rb +17 -9
  23. data/app/components/primer/details_component.rb +3 -3
  24. data/app/components/primer/dropdown_menu_component.rb +2 -4
  25. data/app/components/primer/flash_component.html.erb +2 -2
  26. data/app/components/primer/flash_component.rb +2 -4
  27. data/app/components/primer/flex_component.rb +16 -16
  28. data/app/components/primer/heading_component.rb +1 -1
  29. data/app/components/primer/label_component.rb +9 -9
  30. data/app/components/primer/layout_component.html.erb +3 -9
  31. data/app/components/primer/layout_component.rb +30 -5
  32. data/app/components/primer/link_component.rb +37 -9
  33. data/app/components/primer/octicon_component.rb +4 -7
  34. data/app/components/primer/popover_component.html.erb +3 -7
  35. data/app/components/primer/popover_component.rb +58 -62
  36. data/app/components/primer/primer.d.ts +3 -0
  37. data/app/components/primer/primer.js +2 -0
  38. data/app/components/primer/primer.ts +2 -0
  39. data/app/components/primer/progress_bar_component.html.erb +1 -1
  40. data/app/components/primer/progress_bar_component.rb +24 -27
  41. data/app/components/primer/spinner_component.rb +2 -4
  42. data/app/components/primer/state_component.rb +2 -4
  43. data/app/components/primer/subhead_component.rb +2 -0
  44. data/app/components/primer/tab_container_component.d.ts +1 -0
  45. data/app/components/primer/text_component.rb +3 -1
  46. data/app/components/primer/time_ago_component.d.ts +1 -0
  47. data/app/components/primer/time_ago_component.js +1 -0
  48. data/app/components/primer/time_ago_component.rb +47 -0
  49. data/app/components/primer/time_ago_component.ts +1 -0
  50. data/app/components/primer/timeline_item_component.rb +2 -1
  51. data/app/components/primer/underline_nav_component.html.erb +5 -5
  52. data/app/components/primer/underline_nav_component.rb +24 -5
  53. data/app/lib/primer/classify.rb +9 -14
  54. data/app/lib/primer/classify/cache.rb +7 -2
  55. data/app/lib/primer/classify/functional_background_colors.rb +61 -0
  56. data/app/lib/primer/classify/functional_border_colors.rb +51 -0
  57. data/app/lib/primer/classify/functional_colors.rb +66 -0
  58. data/app/lib/primer/classify/functional_text_colors.rb +62 -0
  59. data/app/lib/primer/fetch_or_fallback_helper.rb +13 -4
  60. data/app/lib/primer/status/dsl.rb +43 -0
  61. data/app/lib/primer/test_selector_helper.rb +20 -0
  62. data/app/lib/primer/view_helper.rb +9 -12
  63. data/lib/primer/view_components/engine.rb +4 -0
  64. data/lib/primer/view_components/version.rb +1 -1
  65. data/static/statuses.json +1 -1
  66. metadata +37 -4
  67. data/app/lib/primer/view_helper/dsl.rb +0 -34
@@ -3,9 +3,10 @@
3
3
  module Primer
4
4
  # Renders an [Octicon](https://primer.style/octicons/) with <%= link_to_system_arguments_docs %>.
5
5
  class OcticonComponent < Primer::Component
6
- view_helper :octicon
6
+ status :beta
7
7
 
8
- include Primer::ClassNameHelper
8
+ include ClassNameHelper
9
+ include TestSelectorHelper
9
10
  include OcticonsHelper
10
11
 
11
12
  SIZE_DEFAULT = :small
@@ -38,15 +39,11 @@ module Primer
38
39
  # Filter out classify options to prevent them from becoming invalid html attributes.
39
40
  # Note height and width are both classify options and valid html attributes.
40
41
  octicon_helper_options = @system_arguments.slice(:height, :width)
41
- @system_arguments = @system_arguments.except(*Primer::Classify::VALID_KEYS, :classes).merge(octicon_helper_options)
42
+ @system_arguments = add_test_selector(@system_arguments).except(*Primer::Classify::VALID_KEYS, :classes).merge(octicon_helper_options)
42
43
  end
43
44
 
44
45
  def call
45
46
  octicon(@icon, { **@system_arguments })
46
47
  end
47
-
48
- def self.status
49
- Primer::Component::STATUSES[:beta]
50
- end
51
48
  end
52
49
  end
@@ -1,10 +1,6 @@
1
1
  <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
- <%= render body.component do %>
3
- <% if heading %>
4
- <%= render heading.component do %>
5
- <%= heading.content %>
6
- <% end %>
7
- <% end %>
8
- <%= body.content %>
2
+ <%= render(body_component) do %>
3
+ <%= heading %>
4
+ <%= body %>
9
5
  <% end %>
10
6
  <% end %>
@@ -5,37 +5,84 @@ module Primer
5
5
  #
6
6
  # By default, the popover renders with absolute positioning, meaning it should usually be wrapped in an element with a relative position in order to be positioned properly. To render the popover with relative positioning, use the relative property.
7
7
  class PopoverComponent < Primer::Component
8
- include ViewComponent::Slotable
8
+ include ViewComponent::SlotableV2
9
+ status :beta
9
10
 
10
- with_slot :heading, class_name: "Heading"
11
- with_slot :body, class_name: "Body"
11
+ CARET_DEFAULT = :top
12
+ CARET_MAPPINGS = {
13
+ CARET_DEFAULT => "",
14
+ :bottom => "Popover-message--bottom",
15
+ :bottom_right => "Popover-message--bottom-right",
16
+ :bottom_left => "Popover-message--bottom-left",
17
+ :left => "Popover-message--left",
18
+ :left_bottom => "Popover-message--left-bottom",
19
+ :left_top => "Popover-message--left-top",
20
+ :right => "Popover-message--right",
21
+ :right_bottom => "Popover-message--right-bottom",
22
+ :right_top => "Popover-message--right-top",
23
+ :top_left => "Popover-message--top-left",
24
+ :top_right => "Popover-message--top-right"
25
+ }.freeze
26
+
27
+ # The heading
28
+ #
29
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
30
+ renders_one :heading, lambda { |**system_arguments|
31
+ system_arguments[:mb] ||= 2
32
+ system_arguments[:tag] ||= :h4
33
+
34
+ Primer::HeadingComponent.new(**system_arguments)
35
+ }
36
+
37
+ # The body
38
+ #
39
+ # @param caret [Symbol] <%= one_of(Primer::PopoverComponent::CARET_MAPPINGS.keys) %>
40
+ # @param large [Boolean] Whether to use the large version of the component.
41
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
42
+ renders_one :body, lambda { |caret: CARET_DEFAULT, large: false, **system_arguments, &block|
43
+ system_arguments[:classes] = class_names(
44
+ system_arguments[:classes],
45
+ "Popover-message Box",
46
+ CARET_MAPPINGS[fetch_or_fallback(CARET_MAPPINGS.keys, caret, CARET_DEFAULT)],
47
+ "Popover-message--large" => large
48
+ )
49
+ system_arguments[:p] ||= 4
50
+ system_arguments[:mt] ||= 2
51
+ system_arguments[:mx] ||= :auto
52
+ system_arguments[:text_align] ||= :left
53
+ system_arguments[:box_shadow] ||= :large
54
+
55
+ # This is a hack to allow the parent to set the slot's content
56
+ @body_arguments = system_arguments
57
+ block&.call
58
+ }
12
59
 
13
60
  # @example Default
14
61
  # <%= render Primer::PopoverComponent.new do |component| %>
15
- # <% component.slot(:heading) do %>
62
+ # <% component.heading do %>
16
63
  # Activity feed
17
64
  # <% end %>
18
- # <% component.slot(:body) do %>
65
+ # <% component.body do %>
19
66
  # This is the Popover body.
20
67
  # <% end %>
21
68
  # <% end %>
22
69
  #
23
70
  # @example Large
24
71
  # <%= render Primer::PopoverComponent.new do |component| %>
25
- # <% component.slot(:heading) do %>
72
+ # <% component.heading do %>
26
73
  # Activity feed
27
74
  # <% end %>
28
- # <% component.slot(:body, large: true) do %>
75
+ # <% component.body(large: true) do %>
29
76
  # This is the large Popover body.
30
77
  # <% end %>
31
78
  # <% end %>
32
79
  #
33
80
  # @example Caret position
34
81
  # <%= render Primer::PopoverComponent.new do |component| %>
35
- # <% component.slot(:heading) do %>
82
+ # <% component.heading do %>
36
83
  # Activity feed
37
84
  # <% end %>
38
- # <% component.slot(:body, caret: :left) do %>
85
+ # <% component.body(caret: :left) do %>
39
86
  # This is the large Popover body.
40
87
  # <% end %>
41
88
  # <% end %>
@@ -57,59 +104,8 @@ module Primer
57
104
  body.present?
58
105
  end
59
106
 
60
- # :nodoc:
61
- class Heading < Primer::Slot
62
- # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
63
- def initialize(**system_arguments)
64
- @system_arguments = system_arguments
65
- @system_arguments[:mb] ||= 2
66
- @system_arguments[:tag] ||= :h4
67
- end
68
-
69
- def component
70
- Primer::HeadingComponent.new(**@system_arguments)
71
- end
72
- end
73
-
74
- # :nodoc:
75
- class Body < Slot
76
- CARET_DEFAULT = :top
77
- CARET_MAPPINGS = {
78
- CARET_DEFAULT => "",
79
- :bottom => "Popover-message--bottom",
80
- :bottom_right => "Popover-message--bottom-right",
81
- :bottom_left => "Popover-message--bottom-left",
82
- :left => "Popover-message--left",
83
- :left_bottom => "Popover-message--left-bottom",
84
- :left_top => "Popover-message--left-top",
85
- :right => "Popover-message--right",
86
- :right_bottom => "Popover-message--right-bottom",
87
- :right_top => "Popover-message--right-top",
88
- :top_left => "Popover-message--top-left",
89
- :top_right => "Popover-message--top-right"
90
- }.freeze
91
-
92
- # @param caret [Symbol] <%= one_of(Primer::PopoverComponent::Body::CARET_MAPPINGS.keys) %>
93
- # @param large [Boolean] Whether to use the large version of the component.
94
- # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
95
- def initialize(caret: CARET_DEFAULT, large: false, **system_arguments)
96
- @system_arguments = system_arguments
97
- @system_arguments[:classes] = class_names(
98
- system_arguments[:classes],
99
- "Popover-message Box",
100
- CARET_MAPPINGS[fetch_or_fallback(CARET_MAPPINGS.keys, caret, CARET_DEFAULT)],
101
- "Popover-message--large" => large
102
- )
103
- @system_arguments[:p] ||= 4
104
- @system_arguments[:mt] ||= 2
105
- @system_arguments[:mx] ||= :auto
106
- @system_arguments[:text_align] ||= :left
107
- @system_arguments[:box_shadow] ||= :large
108
- end
109
-
110
- def component
111
- Primer::BoxComponent.new(**@system_arguments)
112
- end
107
+ def body_component
108
+ Primer::BoxComponent.new(**@body_arguments)
113
109
  end
114
110
  end
115
111
  end
@@ -0,0 +1,3 @@
1
+ import './auto_complete_component';
2
+ import './tab_container_component';
3
+ import './time_ago_component';
@@ -1 +1,3 @@
1
+ import './auto_complete_component';
1
2
  import './tab_container_component';
3
+ import './time_ago_component';
@@ -1 +1,3 @@
1
+ import './auto_complete_component'
1
2
  import './tab_container_component'
3
+ import './time_ago_component'
@@ -1,5 +1,5 @@
1
1
  <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
2
  <% items.each do |item| %>
3
- <%= render Primer::BaseComponent.new(**item.system_arguments) %>
3
+ <%= item %>
4
4
  <% end %>
5
5
  <% end %>
@@ -3,9 +3,25 @@
3
3
  module Primer
4
4
  # Use ProgressBar to visualize task completion.
5
5
  class ProgressBarComponent < Primer::Component
6
- include ViewComponent::Slotable
6
+ include ViewComponent::SlotableV2
7
+ status :beta
7
8
 
8
- with_slot :item, collection: true, class_name: "Item"
9
+ # Use the Item slot to add an item to the progress bas
10
+ #
11
+ # @param percentage [Integer] The percent complete
12
+ # @param bg [Symbol] The background color
13
+ # @param kwargs [Hash] The same arguments as <%= link_to_system_arguments_docs %>.
14
+ renders_many :items, lambda { |percentage: 0, bg: :success_inverse, **system_arguments|
15
+ percentage = percentage
16
+ system_arguments = system_arguments
17
+
18
+ system_arguments[:tag] = :span
19
+ system_arguments[:bg] = bg
20
+ system_arguments[:style] = join_style_arguments(system_arguments[:style], "width: #{percentage}%;")
21
+ system_arguments[:classes] = class_names("Progress-item", system_arguments[:classes])
22
+
23
+ Primer::BaseComponent.new(**system_arguments)
24
+ }
9
25
 
10
26
  SIZE_DEFAULT = :default
11
27
 
@@ -18,24 +34,24 @@ module Primer
18
34
  SIZE_OPTIONS = SIZE_MAPPINGS.keys
19
35
  # @example Default
20
36
  # <%= render(Primer::ProgressBarComponent.new) do |component| %>
21
- # <% component.slot(:item, percentage: 25) %>
37
+ # <% component.item(percentage: 25) %>
22
38
  # <% end %>
23
39
  #
24
40
  # @example Small
25
41
  # <%= render(Primer::ProgressBarComponent.new(size: :small)) do |component| %>
26
- # <% component.slot(:item, bg: :blue_4, percentage: 50) %>
42
+ # <% component.item(bg: :info_inverse, percentage: 50) %>
27
43
  # <% end %>
28
44
  #
29
45
  # @example Large
30
46
  # <%= render(Primer::ProgressBarComponent.new(size: :large)) do |component| %>
31
- # <% component.slot(:item, bg: :red_4, percentage: 75) %>
47
+ # <% component.item(bg: :danger_inverse, percentage: 75) %>
32
48
  # <% end %>
33
49
  #
34
50
  # @example Multiple items
35
51
  # <%= render(Primer::ProgressBarComponent.new) do |component| %>
36
- # <% component.slot(:item, percentage: 10) %>
37
- # <% component.slot(:item, bg: :blue_4, percentage: 20) %>
38
- # <% component.slot(:item, bg: :red_4, percentage: 30) %>
52
+ # <% component.item(percentage: 10) %>
53
+ # <% component.item(bg: :info_inverse, percentage: 20) %>
54
+ # <% component.item(bg: :danger_inverse, percentage: 30) %>
39
55
  # <% end %>
40
56
  #
41
57
  # @param size [Symbol] <%= one_of(Primer::ProgressBarComponent::SIZE_OPTIONS) %> Increases height.
@@ -53,24 +69,5 @@ module Primer
53
69
  def render?
54
70
  items.any?
55
71
  end
56
-
57
- # :nodoc:
58
- class Item < Primer::Slot
59
- attr_reader :system_arguments
60
-
61
- # @param percentage [Integer] Percentage completion of item.
62
- # @param bg [Symbol] Color of item.
63
- # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
64
- def initialize(percentage: 0, bg: :green, **system_arguments)
65
- @percentage = percentage
66
- @system_arguments = system_arguments
67
-
68
- @system_arguments[:tag] = :span
69
- @system_arguments[:bg] = bg
70
- @system_arguments[:style] =
71
- join_style_arguments(@system_arguments[:style], "width: #{@percentage}%;")
72
- @system_arguments[:classes] = class_names("Progress-item", @system_arguments[:classes])
73
- end
74
- end
75
72
  end
76
73
  end
@@ -3,6 +3,8 @@
3
3
  module Primer
4
4
  # Use Primer::SpinnerComponent to let users know that content is being loaded.
5
5
  class SpinnerComponent < Primer::Component
6
+ status :beta
7
+
6
8
  DEFAULT_SIZE = :medium
7
9
  SIZE_MAPPINGS = {
8
10
  :small => 16,
@@ -34,9 +36,5 @@ module Primer
34
36
  @system_arguments[:viewBox] = "0 0 16 16"
35
37
  @system_arguments[:fill] = :none
36
38
  end
37
-
38
- def self.status
39
- Primer::Component::STATUSES[:beta]
40
- end
41
39
  end
42
40
  end
@@ -3,6 +3,8 @@
3
3
  module Primer
4
4
  # Component for rendering the status of an item.
5
5
  class StateComponent < Primer::Component
6
+ status :beta
7
+
6
8
  COLOR_DEFAULT = :default
7
9
  NEW_COLOR_MAPPINGS = {
8
10
  open: "State--open",
@@ -68,9 +70,5 @@ module Primer
68
70
  def call
69
71
  render(Primer::BaseComponent.new(**@system_arguments)) { content }
70
72
  end
71
-
72
- def self.status
73
- Primer::Component::STATUSES[:beta]
74
- end
75
73
  end
76
74
  end
@@ -3,6 +3,8 @@
3
3
  module Primer
4
4
  # Use the Subhead component for page headings.
5
5
  class SubheadComponent < Primer::Component
6
+ status :beta
7
+
6
8
  include ViewComponent::SlotableV2
7
9
 
8
10
  # The heading
@@ -0,0 +1 @@
1
+ import '@github/tab-container-element';
@@ -3,9 +3,11 @@
3
3
  module Primer
4
4
  # The Text component is a wrapper component that will apply typography styles to the text inside.
5
5
  class TextComponent < Primer::Component
6
+ status :beta
7
+
6
8
  # @example Default
7
9
  # <%= render(Primer::TextComponent.new(tag: :p, font_weight: :bold)) { "Bold Text" } %>
8
- # <%= render(Primer::TextComponent.new(tag: :p, color: :red_5)) { "Red Text" } %>
10
+ # <%= render(Primer::TextComponent.new(tag: :p, color: :text_danger)) { "Danger Text" } %>
9
11
  #
10
12
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
11
13
  def initialize(**system_arguments)
@@ -0,0 +1 @@
1
+ import '@github/time-elements';
@@ -0,0 +1 @@
1
+ import '@github/time-elements';
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ # Use Primer::TimeAgoComponent to display a time relative to how long ago it was. This component requires JavaScript.
5
+ class TimeAgoComponent < Primer::Component
6
+ #
7
+ # @example Default
8
+ # <%= render(Primer::TimeAgoComponent.new(time: Time.at(628232400))) %>
9
+ #
10
+ # @param time [Time] The time to be formatted
11
+ # @param micro [Boolean] If true then the text will be formatted in "micro" mode, using as few characters as possible
12
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
13
+ def initialize(time:, micro: false, **system_arguments)
14
+ @system_arguments = system_arguments
15
+ @system_arguments[:datetime] = time.utc.iso8601
16
+ @system_arguments[:classes] = class_names("no-wrap", @system_arguments[:classes])
17
+ @system_arguments[:tag] = "time-ago"
18
+ @system_arguments[:format] = "micro" if micro
19
+ @time = time
20
+ @micro = micro
21
+ end
22
+
23
+ def call
24
+ render(Primer::BaseComponent.new(**@system_arguments)) { time_in_words }
25
+ end
26
+
27
+ private
28
+
29
+ def time_in_words
30
+ return @time.in_time_zone.strftime("%b %-d, %Y") unless @micro
31
+
32
+ seconds_ago = Time.current - @time
33
+
34
+ if seconds_ago < 1.minute
35
+ "1m"
36
+ elsif seconds_ago >= 1.minute && seconds_ago < 1.hour
37
+ "#{(seconds_ago / 60).floor}m"
38
+ elsif seconds_ago >= 1.hour && seconds_ago < 1.day
39
+ "#{(seconds_ago / 60 / 60).floor}h"
40
+ elsif seconds_ago >= 1.day && seconds_ago < 1.year
41
+ "#{(seconds_ago / 60 / 60 / 24).floor}d"
42
+ elsif seconds_ago >= 1.year
43
+ "#{(seconds_ago / 60 / 60 / 24 / 365).floor}y"
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1 @@
1
+ import '@github/time-elements'
@@ -4,6 +4,7 @@ module Primer
4
4
  # Use `TimelineItem` to display items on a vertical timeline, connected by badge elements.
5
5
  class TimelineItemComponent < Primer::Component
6
6
  include ViewComponent::SlotableV2
7
+ status :beta
7
8
 
8
9
  # Avatar to be rendered to the left of the Badge.
9
10
  #
@@ -40,7 +41,7 @@ module Primer
40
41
  # <div style="padding-left: 60px">
41
42
  # <%= render(Primer::TimelineItemComponent.new) do |component| %>
42
43
  # <% component.avatar(src: "https://github.com/github.png", alt: "github") %>
43
- # <% component.badge(bg: :green, color: :white, icon: :check) %>
44
+ # <% component.badge(bg: :success_inverse, color: :text_white, icon: :check) %>
44
45
  # <% component.body { "Success!" } %>
45
46
  # <% end %>
46
47
  # </div>