primer_view_components 0.1.7 → 0.1.8

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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -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/styles/primer_view_components.css +2 -2
  6. data/app/assets/styles/primer_view_components.css.map +1 -1
  7. data/app/components/primer/alpha/action_list/divider.rb +1 -1
  8. data/app/components/primer/alpha/action_list/heading.html.erb +2 -2
  9. data/app/components/primer/alpha/action_list/heading.rb +9 -5
  10. data/app/components/primer/alpha/action_list.css +1 -1
  11. data/app/components/primer/alpha/action_list.css.json +1 -0
  12. data/app/components/primer/alpha/action_list.css.map +1 -1
  13. data/app/components/primer/alpha/action_list.html.erb +1 -0
  14. data/app/components/primer/alpha/action_list.pcss +5 -0
  15. data/app/components/primer/alpha/action_list.rb +14 -11
  16. data/app/components/primer/alpha/dialog.rb +4 -0
  17. data/app/components/primer/alpha/nav_list/divider.rb +14 -0
  18. data/app/components/primer/alpha/nav_list/group.html.erb +7 -0
  19. data/app/components/primer/alpha/nav_list/group.rb +24 -11
  20. data/app/components/primer/alpha/nav_list/item.rb +4 -0
  21. data/app/components/primer/alpha/nav_list.d.ts +0 -1
  22. data/app/components/primer/alpha/nav_list.html.erb +9 -4
  23. data/app/components/primer/alpha/nav_list.js +3 -4
  24. data/app/components/primer/alpha/nav_list.rb +87 -10
  25. data/app/components/primer/alpha/nav_list.ts +3 -2
  26. data/app/components/primer/alpha/segmented_control.css +1 -1
  27. data/app/components/primer/alpha/segmented_control.css.json +2 -2
  28. data/app/components/primer/alpha/segmented_control.css.map +1 -1
  29. data/app/components/primer/alpha/segmented_control.pcss +10 -8
  30. data/app/components/primer/alpha/text_field.css +1 -1
  31. data/app/components/primer/alpha/text_field.css.json +11 -11
  32. data/app/components/primer/alpha/text_field.css.map +1 -1
  33. data/app/components/primer/alpha/text_field.pcss +2 -2
  34. data/app/components/primer/beta/button.css +1 -1
  35. data/app/components/primer/beta/button.css.json +2 -0
  36. data/app/components/primer/beta/button.css.map +1 -1
  37. data/app/components/primer/beta/button.pcss +9 -0
  38. data/app/components/primer/component.rb +3 -96
  39. data/app/lib/primer/attributes_helper.rb +105 -0
  40. data/lib/primer/forms/text_field.rb +6 -0
  41. data/lib/primer/view_components/version.rb +1 -1
  42. data/previews/primer/alpha/nav_list_preview/trailing_action.html.erb +10 -10
  43. data/previews/primer/alpha/nav_list_preview.rb +37 -16
  44. data/previews/primer/beta/button_preview/trailing_counter.html.erb +11 -0
  45. data/previews/primer/beta/button_preview.rb +15 -0
  46. data/previews/primer/box_preview.rb +28 -0
  47. data/static/arguments.json +22 -12
  48. data/static/audited_at.json +1 -0
  49. data/static/classes.json +3 -0
  50. data/static/constants.json +3 -0
  51. data/static/info_arch.json +136 -19
  52. data/static/previews.json +38 -0
  53. data/static/statuses.json +1 -0
  54. metadata +7 -2
@@ -16,6 +16,7 @@ module Primer
16
16
  include ViewComponent::PolymorphicSlots
17
17
  end
18
18
 
19
+ include AttributesHelper
19
20
  include ClassNameHelper
20
21
  include FetchOrFallbackHelper
21
22
  include TestSelectorHelper
@@ -25,15 +26,13 @@ module Primer
25
26
  include Audited::Dsl
26
27
 
27
28
  INVALID_ARIA_LABEL_TAGS = [:div, :span, :p].freeze
28
- PLURAL_ARIA_ATTRIBUTES = %i[describedby labelledby].freeze
29
- PLURAL_DATA_ATTRIBUTES = %i[target targets].freeze
30
29
 
31
30
  def self.deprecated?
32
31
  status == :deprecated
33
32
  end
34
33
 
35
- def self.generate_id
36
- "#{name.demodulize.underscore.dasherize}-#{SecureRandom.uuid}"
34
+ def self.generate_id(base_name: name.demodulize.underscore.dasherize)
35
+ "#{base_name}-#{SecureRandom.uuid}"
37
36
  end
38
37
 
39
38
  private
@@ -56,98 +55,6 @@ module Primer
56
55
  ActiveSupport::Deprecation.warn(message)
57
56
  end
58
57
 
59
- def aria(val, system_arguments)
60
- system_arguments[:"aria-#{val}"] || system_arguments.dig(:aria, val.to_sym)
61
- end
62
-
63
- # Merges hashes that contain "aria-*" keys and nested aria: hashes. Removes keys from
64
- # each hash and returns them in the new hash.
65
- #
66
- # Eg. merge_aria({ "aria-disabled": "true" }, { aria: { invalid: "true" } })
67
- # => { disabled: "true", invalid: "true" }
68
- #
69
- # Certain aria attributes can contain multiple values separated by spaces. merge_aria
70
- # will combine these plural attributes into a composite string.
71
- #
72
- # Eg. merge_aria({ "aria-labelledby": "foo" }, { aria: { labelledby: "bar" } })
73
- # => { labelledby: "foo bar" }
74
- #
75
- # It's designed to be used to normalize and merge aria information from system_arguments
76
- # hashes. Consider using this pattern in component initializers:
77
- #
78
- # @system_arguments[:aria] = merge_aria(
79
- # @system_arguments,
80
- # { aria: { labelled_by: id } }
81
- # )
82
- def merge_aria(*hashes)
83
- merge_prefixed_attribute_hashes(
84
- *hashes, prefix: :aria, plural_keys: PLURAL_ARIA_ATTRIBUTES
85
- )
86
- end
87
-
88
- # Merges hashes that contain "data-*" keys and nested data: hashes. Removes keys from
89
- # each hash and returns them in the new hash.
90
- #
91
- # Eg. merge_data({ "data-foo": "true" }, { data: { bar: "true" } })
92
- # => { foo: "true", bar: "true" }
93
- #
94
- # Certain data attributes can contain multiple values separated by spaces. merge_data
95
- # will combine these plural attributes into a composite string.
96
- #
97
- # Eg. merge_data({ "data-target": "foo" }, { data: { target: "bar" } })
98
- # => { target: "foo bar" }
99
- #
100
- # It's designed to be used to normalize and merge data information from system_arguments
101
- # hashes. Consider using this pattern in component initializers:
102
- #
103
- # @system_arguments[:data] = merge_aria(
104
- # @system_arguments,
105
- # { data: { foo: "bar" } }
106
- # )
107
- def merge_data(*hashes)
108
- merge_prefixed_attribute_hashes(
109
- *hashes, prefix: :data, plural_keys: PLURAL_DATA_ATTRIBUTES
110
- )
111
- end
112
-
113
- def merge_prefixed_attribute_hashes(*hashes, prefix:, plural_keys:)
114
- {}.tap do |result|
115
- hashes.each do |hash|
116
- next unless hash
117
-
118
- prefix_hash = hash.delete(prefix) || {}
119
-
120
- prefix_hash.each_pair do |key, val|
121
- result[key] =
122
- if plural_keys.include?(key)
123
- [*(result[key] || "").split, val].join(" ").strip
124
- else
125
- val
126
- end
127
- end
128
-
129
- hash.delete_if do |key, val|
130
- key_s = key.to_s
131
-
132
- if key.start_with?("#{prefix}-")
133
- bare_key = key_s.sub("#{prefix}-", "").to_sym
134
-
135
- result[bare_key] =
136
- if plural_keys.include?(bare_key)
137
- [*(result[bare_key] || "").split, val].join(" ").strip
138
- else
139
- val
140
- end
141
-
142
- true
143
- else
144
- false
145
- end
146
- end
147
- end
148
- end
149
- end
150
-
151
58
  def validate_aria_label
152
59
  aria_label = aria("label", @system_arguments)
153
60
  aria_labelledby = aria("labelledby", @system_arguments)
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ # :nodoc:
5
+ module AttributesHelper
6
+ PLURAL_ARIA_ATTRIBUTES = %i[describedby labelledby].freeze
7
+ PLURAL_DATA_ATTRIBUTES = %i[target targets].freeze
8
+
9
+ def aria(val, system_arguments)
10
+ system_arguments[:"aria-#{val}"] || system_arguments.dig(:aria, val.to_sym)
11
+ end
12
+
13
+ def data(val, system_arguments)
14
+ system_arguments[:"data-#{val}"] || system_arguments.dig(:data, val.to_sym)
15
+ end
16
+
17
+ # Merges hashes that contain "aria-*" keys and nested aria: hashes. Removes keys from
18
+ # each hash and returns them in the new hash.
19
+ #
20
+ # Eg. merge_aria({ "aria-disabled": "true" }, { aria: { invalid: "true" } })
21
+ # => { disabled: "true", invalid: "true" }
22
+ #
23
+ # Certain aria attributes can contain multiple values separated by spaces. merge_aria
24
+ # will combine these plural attributes into a composite string.
25
+ #
26
+ # Eg. merge_aria({ "aria-labelledby": "foo" }, { aria: { labelledby: "bar" } })
27
+ # => { labelledby: "foo bar" }
28
+ #
29
+ # It's designed to be used to normalize and merge aria information from system_arguments
30
+ # hashes. Consider using this pattern in component initializers:
31
+ #
32
+ # @system_arguments[:aria] = merge_aria(
33
+ # @system_arguments,
34
+ # { aria: { labelled_by: id } }
35
+ # )
36
+ def merge_aria(*hashes)
37
+ merge_prefixed_attribute_hashes(
38
+ *hashes, prefix: :aria, plural_keys: PLURAL_ARIA_ATTRIBUTES
39
+ )
40
+ end
41
+
42
+ # Merges hashes that contain "data-*" keys and nested data: hashes. Removes keys from
43
+ # each hash and returns them in the new hash.
44
+ #
45
+ # Eg. merge_data({ "data-foo": "true" }, { data: { bar: "true" } })
46
+ # => { foo: "true", bar: "true" }
47
+ #
48
+ # Certain data attributes can contain multiple values separated by spaces. merge_data
49
+ # will combine these plural attributes into a composite string.
50
+ #
51
+ # Eg. merge_data({ "data-target": "foo" }, { data: { target: "bar" } })
52
+ # => { target: "foo bar" }
53
+ #
54
+ # It's designed to be used to normalize and merge data information from system_arguments
55
+ # hashes. Consider using this pattern in component initializers:
56
+ #
57
+ # @system_arguments[:data] = merge_aria(
58
+ # @system_arguments,
59
+ # { data: { foo: "bar" } }
60
+ # )
61
+ def merge_data(*hashes)
62
+ merge_prefixed_attribute_hashes(
63
+ *hashes, prefix: :data, plural_keys: PLURAL_DATA_ATTRIBUTES
64
+ )
65
+ end
66
+
67
+ def merge_prefixed_attribute_hashes(*hashes, prefix:, plural_keys:)
68
+ {}.tap do |result|
69
+ hashes.each do |hash|
70
+ next unless hash
71
+
72
+ prefix_hash = hash.delete(prefix) || {}
73
+
74
+ prefix_hash.each_pair do |key, val|
75
+ result[key] =
76
+ if plural_keys.include?(key)
77
+ [*(result[key] || "").split, val].join(" ").strip
78
+ else
79
+ val
80
+ end
81
+ end
82
+
83
+ hash.delete_if do |key, val|
84
+ key_s = key.to_s
85
+
86
+ if key.start_with?("#{prefix}-")
87
+ bare_key = key_s.sub("#{prefix}-", "").to_sym
88
+
89
+ result[bare_key] =
90
+ if plural_keys.include?(bare_key)
91
+ [*(result[bare_key] || "").split, val].join(" ").strip
92
+ else
93
+ val
94
+ end
95
+
96
+ true
97
+ else
98
+ false
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -6,6 +6,11 @@ module Primer
6
6
  class TextField < BaseComponent
7
7
  delegate :builder, :form, to: :@input
8
8
 
9
+ INPUT_WRAP_SIZE = {
10
+ small: "FormControl-input-wrap--small",
11
+ large: "FormControl-input-wrap--large"
12
+ }.freeze
13
+
9
14
  def initialize(input:)
10
15
  @input = input
11
16
 
@@ -17,6 +22,7 @@ module Primer
17
22
  @field_wrap_arguments = {
18
23
  class: class_names(
19
24
  "FormControl-input-wrap",
25
+ INPUT_WRAP_SIZE[input.size],
20
26
  "FormControl-input-wrap--trailingAction": @input.show_clear_button?,
21
27
  "FormControl-input-wrap--leadingVisual": @input.leading_visual?
22
28
  ),
@@ -6,7 +6,7 @@ module Primer
6
6
  module VERSION
7
7
  MAJOR = 0
8
8
  MINOR = 1
9
- PATCH = 7
9
+ PATCH = 8
10
10
 
11
11
  STRING = [MAJOR, MINOR, PATCH].join(".")
12
12
  end
@@ -1,19 +1,19 @@
1
- <%= render(Primer::Alpha::NavList.new) do |list| %>
1
+ <%= render(Primer::Alpha::NavList.new(aria: { label: "Workflow results" })) do |list| %>
2
2
  <% list.with_group do |group| %>
3
- <%= group.with_heading(title: "Shopping list") %>
4
- <% group.with_item(label: "Bread", href: "/list/1") do |item| %>
5
- <%= item.with_trailing_action(icon: :plus, aria: { label: "Activate alert" }, name: "bread_button") %>
3
+ <% group.with_heading(title: "Workflows") %>
4
+ <% group.with_item(label: "Build and Test", href: "/workflows/1") do |item| %>
5
+ <%= item.with_trailing_action(icon: :sync, aria: { label: "Build and test: re-run workflow" }, name: "build_and_test_button") %>
6
6
  <% end %>
7
- <% group.with_item(label: "Cheese", href: "/list/2") do |item| %>
8
- <%= item.with_trailing_action(icon: :plus, aria: { label: "Activate alert" }, name: "cheese_button") %>
7
+ <% group.with_item(label: "Publish", href: "/workflows/2") do |item| %>
8
+ <%= item.with_trailing_action(icon: :sync, aria: { label: "Publish: re-run workflow" }, name: "publish_button") %>
9
9
  <% end %>
10
10
  <% end %>
11
11
  <% end %>
12
12
 
13
13
  <script type="text/javascript" data-eval="true">
14
- const breadButton = document.querySelector("[name=bread_button]")
15
- breadButton.addEventListener("click", () => alert("You selected bread."))
14
+ const breadButton = document.querySelector("[name=build_and_test_button]")
15
+ breadButton.addEventListener("click", () => alert("The 'Build and Test' workflow will be re-run."))
16
16
 
17
- const cheeseButton = document.querySelector("[name=cheese_button]")
18
- cheeseButton.addEventListener("click", () => alert("You selected cheese."))
17
+ const cheeseButton = document.querySelector("[name=publish_button]")
18
+ cheeseButton.addEventListener("click", () => alert("The 'Publish' workflow will be re-run."))
19
19
  </script>
@@ -6,13 +6,11 @@ module Primer
6
6
  class NavListPreview < ViewComponent::Preview
7
7
  # @label Playground
8
8
  def playground
9
- render(Primer::Alpha::NavList.new(selected_item_id: :code_review_limits)) do |list|
10
- list.with_group do |group|
11
- group.with_heading(title: "Repository settings")
9
+ render(Primer::Alpha::NavList.new(aria: { label: "Repository settings" }, selected_item_id: :code_review_limits)) do |list|
10
+ list.with_heading(title: "Repository settings")
12
11
 
13
- group.with_item(label: "General", href: "/general") do |item|
14
- item.with_leading_visual_icon(icon: :gear)
15
- end
12
+ list.with_item(label: "General", href: "/general") do |item|
13
+ item.with_leading_visual_icon(icon: :gear)
16
14
  end
17
15
 
18
16
  list.with_group do |group|
@@ -35,13 +33,17 @@ module Primer
35
33
 
36
34
  # @label Default
37
35
  def default
38
- render(Primer::Alpha::NavList.new(selected_item_id: :code_review_limits)) do |list|
39
- list.with_group do |group|
40
- group.with_heading(title: "Repository settings")
36
+ render(Primer::Alpha::NavList.new(aria: { label: "Repository settings" }, selected_item_id: :code_review_limits)) do |list|
37
+ list.with_heading(title: "Repository settings")
41
38
 
42
- group.with_item(label: "General", href: "/general") do |item|
43
- item.with_leading_visual_icon(icon: :gear)
44
- end
39
+ list.with_item(label: "General", href: "/general") do |item|
40
+ item.with_leading_visual_icon(icon: :gear)
41
+ end
42
+
43
+ list.with_divider
44
+
45
+ list.with_item(label: "Settings", href: "/settings") do |item|
46
+ item.with_leading_visual_icon(icon: :beaker)
45
47
  end
46
48
 
47
49
  list.with_group do |group|
@@ -62,21 +64,40 @@ module Primer
62
64
  end
63
65
  end
64
66
 
67
+ # @label Top-level items
68
+ #
69
+ def top_level_items
70
+ render(Primer::Alpha::NavList.new(aria: { label: "Account settings" })) do |list|
71
+ list.with_heading(title: "Account settings")
72
+
73
+ list.with_item(label: "General", href: "/general") do |item|
74
+ item.with_leading_visual_icon(icon: :gear)
75
+ end
76
+
77
+ list.with_item(label: "Billing", href: "/billing") do |item|
78
+ item.with_leading_visual_icon(icon: :"credit-card")
79
+ end
80
+
81
+ list.with_item(label: "Change password", href: "/change_password") do |item|
82
+ item.with_leading_visual_icon(icon: :key)
83
+ end
84
+ end
85
+ end
86
+
65
87
  # @label Show more item
66
88
  def show_more_item
67
- render(Primer::Alpha::NavList.new) do |list|
89
+ render(Primer::Alpha::NavList.new(aria: { label: "My favorite foods" })) do |list|
68
90
  list.with_group do |group|
69
91
  group.with_heading(title: "My favorite foods")
70
92
  group.with_item(label: "Popplers", href: "/foods/popplers")
71
93
  group.with_item(label: "Slurm", href: "/foods/slurm")
72
- group.with_show_more_item(label: "Show more", src: "/nav_list_items", pages: 2)
94
+ group.with_show_more_item(label: "Show more foods", src: UrlHelpers.nav_list_items_path, pages: 2)
73
95
  end
74
96
  end
75
97
  end
76
98
 
77
99
  # @label Trailing action
78
- def trailing_action
79
- end
100
+ def trailing_action; end
80
101
  end
81
102
  end
82
103
  end
@@ -0,0 +1,11 @@
1
+ <%= render(Primer::Beta::Button.new(
2
+ scheme: :primary,
3
+ size: :medium,
4
+ block: block,
5
+ id: id,
6
+ align_content: align_content
7
+ )) do |component| %>
8
+ <% component.with_leading_visual_icon(icon: :star) %>
9
+ <% component.with_trailing_visual_counter(count: 15) %>
10
+ Button
11
+ <% end %>
@@ -266,6 +266,21 @@ module Primer
266
266
  })
267
267
  end
268
268
 
269
+ # @label Trailing Counter
270
+ # @param block toggle
271
+ # @param align_content select [center, start]
272
+ def trailing_counter(
273
+ block: false,
274
+ id: "button-preview",
275
+ align_content: :center
276
+ )
277
+ render_with_template(locals: {
278
+ block: block,
279
+ id: id,
280
+ align_content: align_content
281
+ })
282
+ end
283
+
269
284
  # @label With tooltip
270
285
  # @param scheme select [default, primary, danger, invisible, link]
271
286
  # @param size select [small, medium]
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ # @label Box
5
+ class BoxPreview < ViewComponent::Preview
6
+ # @label Playground
7
+ #
8
+ # @param content [String] text
9
+ def playground(content: "Playground")
10
+ render(Primer::Box.new) { content }
11
+ end
12
+
13
+ # @label Default
14
+ def default(content: "Default")
15
+ render(Primer::Box.new) { content }
16
+ end
17
+
18
+ # @label Border
19
+ def border(content: "Box with border")
20
+ render(Primer::Box.new(border: true, p: 3)) { content }
21
+ end
22
+
23
+ # @label Border Bottom
24
+ def border_bottom(content: "Box with bottom border")
25
+ render(Primer::Box.new(border: :bottom, p: 3)) { content }
26
+ end
27
+ end
28
+ end
@@ -98,12 +98,6 @@
98
98
  "source": "https://github.com/primer/view_components/tree/main/app/components/primer/alpha/action_list/heading.rb",
99
99
  "lookbook": "https://primer.style/view-components/lookbook/inspect/primer/alpha/action_list/heading/default/",
100
100
  "parameters": [
101
- {
102
- "name": "id",
103
- "type": "String",
104
- "default": "`self.class.generate_id`",
105
- "description": "The group's identifier (ID attribute in HTML)."
106
- },
107
101
  {
108
102
  "name": "title",
109
103
  "type": "String",
@@ -128,12 +122,6 @@
128
122
  "default": "`:subtle`",
129
123
  "description": "Display a background color if scheme is `filled`."
130
124
  },
131
- {
132
- "name": "tag",
133
- "type": "Integer",
134
- "default": "N/A",
135
- "description": "Semantic tag for the heading."
136
- },
137
125
  {
138
126
  "name": "system_arguments",
139
127
  "type": "Hash",
@@ -1396,6 +1384,28 @@
1396
1384
  }
1397
1385
  ]
1398
1386
  },
1387
+ {
1388
+ "component": "NavList::Divider",
1389
+ "status": "alpha",
1390
+ "a11y_reviewed": false,
1391
+ "short_name": "NavListDivider",
1392
+ "source": "https://github.com/primer/view_components/tree/main/app/components/primer/alpha/nav_list/divider.rb",
1393
+ "lookbook": "https://primer.style/view-components/lookbook/inspect/primer/alpha/nav_list/divider/default/",
1394
+ "parameters": [
1395
+ {
1396
+ "name": "scheme",
1397
+ "type": "Symbol",
1398
+ "default": "`:subtle`",
1399
+ "description": "Display a background color if scheme is `filled`."
1400
+ },
1401
+ {
1402
+ "name": "system_arguments",
1403
+ "type": "Hash",
1404
+ "default": "N/A",
1405
+ "description": "[System arguments](/system-arguments)"
1406
+ }
1407
+ ]
1408
+ },
1399
1409
  {
1400
1410
  "component": "NavList::Group",
1401
1411
  "status": "alpha",
@@ -31,6 +31,7 @@
31
31
  "Primer::Alpha::Menu": "",
32
32
  "Primer::Alpha::MultiInput": "",
33
33
  "Primer::Alpha::NavList": "",
34
+ "Primer::Alpha::NavList::Divider": "",
34
35
  "Primer::Alpha::NavList::Group": "",
35
36
  "Primer::Alpha::NavList::Item": "",
36
37
  "Primer::Alpha::Navigation::Tab": "",
data/static/classes.json CHANGED
@@ -237,6 +237,9 @@
237
237
  "Subhead-actions": [
238
238
  "Primer::Beta::Subhead"
239
239
  ],
240
+ "ActionListHeader": [
241
+ "Primer::Alpha::ActionList"
242
+ ],
240
243
  "SegmentedControl": [
241
244
  "Primer::Alpha::SegmentedControl"
242
245
  ],
@@ -381,9 +381,12 @@
381
381
  "Primer::Alpha::MultiInput": {
382
382
  },
383
383
  "Primer::Alpha::NavList": {
384
+ "Divider": "Primer::Alpha::NavList::Divider",
384
385
  "Group": "Primer::Alpha::NavList::Group",
385
386
  "Item": "Primer::Alpha::NavList::Item"
386
387
  },
388
+ "Primer::Alpha::NavList::Divider": {
389
+ },
387
390
  "Primer::Alpha::NavList::Group": {
388
391
  },
389
392
  "Primer::Alpha::NavList::Item": {