primer_view_components 0.43.5 → 0.44.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/app/assets/javascripts/components/primer/alpha/tree_view/tree_view.d.ts +39 -0
- data/app/assets/javascripts/components/primer/alpha/tree_view/tree_view_icon_pair_element.d.ts +15 -0
- data/app/assets/javascripts/components/primer/alpha/tree_view/tree_view_include_fragment_element.d.ts +9 -0
- data/app/assets/javascripts/components/primer/alpha/tree_view/tree_view_roving_tab_index.d.ts +3 -0
- data/app/assets/javascripts/components/primer/alpha/tree_view/tree_view_sub_tree_node_element.d.ts +42 -0
- data/app/assets/javascripts/components/primer/primer.d.ts +4 -0
- data/app/assets/javascripts/components/primer/shared_events.d.ts +15 -0
- data/app/assets/javascripts/primer_view_components.js +1 -1
- data/app/assets/javascripts/primer_view_components.js.map +1 -1
- data/app/assets/styles/primer_view_components.css +1 -1
- data/app/assets/styles/primer_view_components.css.map +1 -1
- data/app/components/primer/alpha/file_tree_view/directory_node.html.erb +5 -0
- data/app/components/primer/alpha/file_tree_view/directory_node.rb +24 -0
- data/app/components/primer/alpha/file_tree_view/file_node.html.erb +2 -0
- data/app/components/primer/alpha/file_tree_view/file_node.rb +14 -0
- data/app/components/primer/alpha/file_tree_view.rb +15 -0
- data/app/components/primer/alpha/skeleton_box.css +1 -0
- data/app/components/primer/alpha/skeleton_box.css.json +6 -0
- data/app/components/primer/alpha/skeleton_box.css.map +1 -0
- data/app/components/primer/alpha/skeleton_box.html.erb +1 -0
- data/app/components/primer/alpha/skeleton_box.pcss +30 -0
- data/app/components/primer/alpha/skeleton_box.rb +29 -0
- data/app/components/primer/alpha/tree_view/icon.html.erb +1 -0
- data/app/components/primer/alpha/tree_view/icon.rb +22 -0
- data/app/components/primer/alpha/tree_view/icon_pair.html.erb +13 -0
- data/app/components/primer/alpha/tree_view/icon_pair.rb +42 -0
- data/app/components/primer/alpha/tree_view/leading_action.html.erb +3 -0
- data/app/components/primer/alpha/tree_view/leading_action.rb +18 -0
- data/app/components/primer/alpha/tree_view/leaf_node.html.erb +18 -0
- data/app/components/primer/alpha/tree_view/leaf_node.rb +96 -0
- data/app/components/primer/alpha/tree_view/loading_failure_message.html.erb +13 -0
- data/app/components/primer/alpha/tree_view/loading_failure_message.rb +31 -0
- data/app/components/primer/alpha/tree_view/node.html.erb +32 -0
- data/app/components/primer/alpha/tree_view/node.rb +194 -0
- data/app/components/primer/alpha/tree_view/skeleton_loader.html.erb +23 -0
- data/app/components/primer/alpha/tree_view/skeleton_loader.rb +36 -0
- data/app/components/primer/alpha/tree_view/spinner_loader.html.erb +20 -0
- data/app/components/primer/alpha/tree_view/spinner_loader.rb +33 -0
- data/app/components/primer/alpha/tree_view/sub_tree.html.erb +21 -0
- data/app/components/primer/alpha/tree_view/sub_tree.rb +113 -0
- data/app/components/primer/alpha/tree_view/sub_tree_container.html.erb +3 -0
- data/app/components/primer/alpha/tree_view/sub_tree_container.rb +39 -0
- data/app/components/primer/alpha/tree_view/sub_tree_node.html.erb +49 -0
- data/app/components/primer/alpha/tree_view/sub_tree_node.rb +188 -0
- data/app/components/primer/alpha/tree_view/tree_view.d.ts +39 -0
- data/app/components/primer/alpha/tree_view/tree_view.js +363 -0
- data/app/components/primer/alpha/tree_view/tree_view.ts +396 -0
- data/app/components/primer/alpha/tree_view/tree_view_icon_pair_element.d.ts +15 -0
- data/app/components/primer/alpha/tree_view/tree_view_icon_pair_element.js +62 -0
- data/app/components/primer/alpha/tree_view/tree_view_icon_pair_element.ts +56 -0
- data/app/components/primer/alpha/tree_view/tree_view_include_fragment_element.d.ts +9 -0
- data/app/components/primer/alpha/tree_view/tree_view_include_fragment_element.js +28 -0
- data/app/components/primer/alpha/tree_view/tree_view_include_fragment_element.ts +28 -0
- data/app/components/primer/alpha/tree_view/tree_view_roving_tab_index.d.ts +3 -0
- data/app/components/primer/alpha/tree_view/tree_view_roving_tab_index.js +130 -0
- data/app/components/primer/alpha/tree_view/tree_view_roving_tab_index.ts +161 -0
- data/app/components/primer/alpha/tree_view/tree_view_sub_tree_node_element.d.ts +42 -0
- data/app/components/primer/alpha/tree_view/tree_view_sub_tree_node_element.js +418 -0
- data/app/components/primer/alpha/tree_view/tree_view_sub_tree_node_element.ts +470 -0
- data/app/components/primer/alpha/tree_view/visual.html.erb +14 -0
- data/app/components/primer/alpha/tree_view/visual.rb +27 -0
- data/app/components/primer/alpha/tree_view.css +1 -0
- data/app/components/primer/alpha/tree_view.css.json +52 -0
- data/app/components/primer/alpha/tree_view.css.map +1 -0
- data/app/components/primer/alpha/tree_view.html.erb +12 -0
- data/app/components/primer/alpha/tree_view.pcss +373 -0
- data/app/components/primer/alpha/tree_view.rb +439 -0
- data/app/components/primer/beta/breadcrumbs.css +1 -1
- data/app/components/primer/beta/breadcrumbs.css.json +0 -1
- data/app/components/primer/beta/breadcrumbs.css.map +1 -1
- data/app/components/primer/beta/breadcrumbs.pcss +2 -8
- data/app/components/primer/beta/progress_bar.css +1 -1
- data/app/components/primer/beta/progress_bar.css.map +1 -1
- data/app/components/primer/beta/progress_bar.pcss +3 -2
- data/app/components/primer/beta/relative_time.rb +3 -0
- data/app/components/primer/beta/spinner.html.erb +1 -1
- data/app/components/primer/beta/spinner.rb +2 -0
- data/app/components/primer/primer.d.ts +4 -0
- data/app/components/primer/primer.js +4 -0
- data/app/components/primer/primer.pcss +2 -0
- data/app/components/primer/primer.ts +4 -0
- data/app/components/primer/shared_events.d.ts +15 -0
- data/app/components/primer/shared_events.ts +19 -0
- data/app/controllers/primer/view_components/tree_view_items.json +293 -0
- data/app/controllers/primer/view_components/tree_view_items_controller.rb +55 -0
- data/app/forms/check_box_with_nested_form.rb +10 -10
- data/app/forms/radio_button_with_nested_form.rb +16 -16
- data/app/views/primer/view_components/tree_view_items/async_alpha.html_fragment.erb +23 -0
- data/app/views/primer/view_components/tree_view_items/index.html_fragment.erb +24 -0
- data/config/routes.rb +2 -0
- data/lib/primer/view_components/version.rb +2 -2
- data/previews/primer/alpha/file_tree_view_preview/default.html.erb +16 -0
- data/previews/primer/alpha/file_tree_view_preview/playground.html.erb +4 -0
- data/previews/primer/alpha/file_tree_view_preview.rb +69 -0
- data/previews/primer/alpha/skeleton_box_preview.rb +20 -0
- data/previews/primer/alpha/tree_view_preview/async_alpha.html.erb +12 -0
- data/previews/primer/alpha/tree_view_preview/buttons.html.erb +10 -0
- data/previews/primer/alpha/tree_view_preview/default.html.erb +24 -0
- data/previews/primer/alpha/tree_view_preview/empty.html.erb +10 -0
- data/previews/primer/alpha/tree_view_preview/form_input.html.erb +14 -0
- data/previews/primer/alpha/tree_view_preview/leaf_node_playground.html.erb +15 -0
- data/previews/primer/alpha/tree_view_preview/links.html.erb +17 -0
- data/previews/primer/alpha/tree_view_preview/loading_failure.html.erb +36 -0
- data/previews/primer/alpha/tree_view_preview/loading_skeleton.html.erb +12 -0
- data/previews/primer/alpha/tree_view_preview/loading_spinner.html.erb +12 -0
- data/previews/primer/alpha/tree_view_preview/playground.html.erb +4 -0
- data/previews/primer/alpha/tree_view_preview.rb +208 -0
- data/static/arguments.json +456 -0
- data/static/audited_at.json +17 -0
- data/static/classes.json +15 -0
- data/static/constants.json +101 -0
- data/static/info_arch.json +1410 -56
- data/static/previews.json +232 -0
- data/static/statuses.json +17 -0
- metadata +89 -8
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module Alpha
|
5
|
+
class FileTreeView
|
6
|
+
class DirectoryNode < TreeView::SubTreeNode
|
7
|
+
def initialize(icon_arguments: nil, expanded_icon_arguments: nil, collapsed_icon_arguments: nil, **system_arguments)
|
8
|
+
@expanded_icon_arguments = expanded_icon_arguments || icon_arguments || {}
|
9
|
+
@collapsed_icon_arguments = collapsed_icon_arguments || icon_arguments || {}
|
10
|
+
|
11
|
+
super(**system_arguments)
|
12
|
+
end
|
13
|
+
|
14
|
+
def with_file(**system_arguments, &block)
|
15
|
+
with_leaf(**system_arguments, component_klass: FileNode, &block)
|
16
|
+
end
|
17
|
+
|
18
|
+
def with_directory(**system_arguments, &block)
|
19
|
+
with_sub_tree(**system_arguments, component_klass: DirectoryNode, &block)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module Alpha
|
5
|
+
class FileTreeView
|
6
|
+
class FileNode < TreeView::LeafNode
|
7
|
+
def initialize(icon_arguments: {}, **system_arguments)
|
8
|
+
@icon_arguments = icon_arguments
|
9
|
+
super(**system_arguments)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module Alpha
|
5
|
+
class FileTreeView < TreeView
|
6
|
+
def with_file(**system_arguments, &block)
|
7
|
+
with_leaf(**system_arguments, component_klass: FileNode, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
def with_directory(**system_arguments, &block)
|
11
|
+
with_sub_tree(**system_arguments, component_klass: DirectoryNode, &block)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
@keyframes shimmer{0%{mask-position:200%}to{mask-position:0}}.SkeletonBox{animation:shimmer;background-color:var(--bgColor-muted);border-radius:var(--borderRadius-small);display:block;height:1rem}@media (prefers-reduced-motion:no-preference){.SkeletonBox{animation:shimmer;animation-duration:1s;animation-iteration-count:infinite;mask-image:linear-gradient(75deg,#000 30%,#000000a6 80%);mask-size:200%}}@media (forced-colors:active){.SkeletonBox{outline:1px solid #0000;outline-offset:-1px}}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["skeleton_box.pcss"],"names":[],"mappings":"AAAA,mBACE,GACE,kBACF,CAEA,GACE,eACF,CACF,CAEA,aAKE,iBAAkB,CAFlB,qCAAsC,CACtC,uCAAwC,CAHxC,aAAc,CACd,WAiBF,CAZE,8CAPF,aAUI,iBAAkB,CAClB,qBAAsB,CACtB,kCAAmC,CAJnC,wDAAoE,CACpE,cAUJ,CANE,CAEA,8BAfF,aAgBI,uBAA8B,CAC9B,mBAEJ,CADE","file":"skeleton_box.css","sourcesContent":["@keyframes shimmer {\n from {\n mask-position: 200%;\n }\n\n to {\n mask-position: 0%;\n }\n}\n\n.SkeletonBox {\n display: block;\n height: 1rem;\n background-color: var(--bgColor-muted);\n border-radius: var(--borderRadius-small);\n animation: shimmer;\n\n @media (prefers-reduced-motion: no-preference) {\n mask-image: linear-gradient(75deg, #000 30%, rgb(0, 0, 0, 0.65) 80%);\n mask-size: 200%;\n animation: shimmer;\n animation-duration: 1s;\n animation-iteration-count: infinite;\n }\n\n @media (forced-colors: active) {\n outline: 1px solid transparent;\n outline-offset: -1px;\n }\n}\n"]}
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render(Primer::BaseComponent.new(**@system_arguments)) %>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
@keyframes shimmer {
|
2
|
+
from {
|
3
|
+
mask-position: 200%;
|
4
|
+
}
|
5
|
+
|
6
|
+
to {
|
7
|
+
mask-position: 0%;
|
8
|
+
}
|
9
|
+
}
|
10
|
+
|
11
|
+
.SkeletonBox {
|
12
|
+
display: block;
|
13
|
+
height: 1rem;
|
14
|
+
background-color: var(--bgColor-muted);
|
15
|
+
border-radius: var(--borderRadius-small);
|
16
|
+
animation: shimmer;
|
17
|
+
|
18
|
+
@media (prefers-reduced-motion: no-preference) {
|
19
|
+
mask-image: linear-gradient(75deg, #000 30%, rgb(0, 0, 0, 0.65) 80%);
|
20
|
+
mask-size: 200%;
|
21
|
+
animation: shimmer;
|
22
|
+
animation-duration: 1s;
|
23
|
+
animation-iteration-count: infinite;
|
24
|
+
}
|
25
|
+
|
26
|
+
@media (forced-colors: active) {
|
27
|
+
outline: 1px solid transparent;
|
28
|
+
outline-offset: -1px;
|
29
|
+
}
|
30
|
+
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module Alpha
|
5
|
+
# A SkeletonBox provides a placeholder for non-text, non-Avatar elements (e.g., hero images)
|
6
|
+
# that are still loading. You can adjust width and height to match the content's dimensions.
|
7
|
+
class SkeletonBox < Primer::Component
|
8
|
+
status :alpha
|
9
|
+
|
10
|
+
# @param height [String] Any valid CSS height.
|
11
|
+
# @param width [String] Any valid CSS width.
|
12
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
13
|
+
def initialize(height: nil, width: nil, **system_arguments)
|
14
|
+
@system_arguments = deny_tag_argument(**system_arguments)
|
15
|
+
|
16
|
+
styles = []
|
17
|
+
styles << "width: #{width}" if width
|
18
|
+
styles << "height: #{height}" if height
|
19
|
+
|
20
|
+
@system_arguments[:tag] = :div
|
21
|
+
@system_arguments[:style] = styles.join("; ") if styles.present?
|
22
|
+
@system_arguments[:classes] = class_names(
|
23
|
+
@system_arguments.delete(:classes),
|
24
|
+
"SkeletonBox"
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render(Primer::Beta::Octicon.new(**@system_arguments)) %>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module Alpha
|
5
|
+
class TreeView
|
6
|
+
# An icon for a `TreeView` node.
|
7
|
+
#
|
8
|
+
# This component is part of the <%= link_to_component(Primer::Alpha::TreeView) %> component and should
|
9
|
+
# not be used directly.
|
10
|
+
class Icon < Primer::Component
|
11
|
+
# @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Beta::Octicon) %>.
|
12
|
+
def initialize(**system_arguments)
|
13
|
+
@system_arguments = system_arguments
|
14
|
+
@system_arguments[:focusable] = "false"
|
15
|
+
@system_arguments[:display] = :inline_block
|
16
|
+
@system_arguments[:overflow] = :visible
|
17
|
+
@system_arguments[:style] = "vertical-align: text-bottom;"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<%= render(Primer::BaseComponent.new(**@system_arguments)) do %>
|
2
|
+
<% if expanded_icon? %>
|
3
|
+
<div data-target="tree-view-icon-pair.expandedIcon" <%= expanded? ? "" : "hidden" %>>
|
4
|
+
<%= expanded_icon %>
|
5
|
+
</div>
|
6
|
+
<% end %>
|
7
|
+
|
8
|
+
<% if collapsed_icon? %>
|
9
|
+
<div data-target="tree-view-icon-pair.collapsedIcon" <%= expanded? ? "hidden" : "" %>>
|
10
|
+
<%= collapsed_icon %>
|
11
|
+
</div>
|
12
|
+
<% end %>
|
13
|
+
<% end %>
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module Alpha
|
5
|
+
class TreeView
|
6
|
+
# A pair of icons for a `TreeView` sub-tree that displays distinct icons when the sub-tree is
|
7
|
+
# expanded and collapsed.
|
8
|
+
#
|
9
|
+
# This component is part of the <%= link_to_component(Primer::Alpha::TreeView) %> component and should
|
10
|
+
# not be used directly.
|
11
|
+
class IconPair < Primer::Component
|
12
|
+
# The expanded icon.
|
13
|
+
#
|
14
|
+
# @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Alpha::TreeView::Icon) %>.
|
15
|
+
renders_one :expanded_icon, lambda { |**system_arguments|
|
16
|
+
Icon.new(**system_arguments)
|
17
|
+
}
|
18
|
+
|
19
|
+
# The collapsed icon.
|
20
|
+
#
|
21
|
+
# @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Alpha::TreeView::Icon) %>.
|
22
|
+
renders_one :collapsed_icon, lambda { |**system_arguments|
|
23
|
+
Icon.new(**system_arguments)
|
24
|
+
}
|
25
|
+
|
26
|
+
# Whether or not this icon is expanded.
|
27
|
+
#
|
28
|
+
# @return [Boolean]
|
29
|
+
attr_reader :expanded
|
30
|
+
alias expanded? expanded
|
31
|
+
|
32
|
+
# @param expanded [Boolean] If true, the expanded icon is shown and the collapsed icon is hidden, etc.
|
33
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
34
|
+
def initialize(expanded: false, **system_arguments)
|
35
|
+
@expanded = expanded
|
36
|
+
@system_arguments = deny_tag_argument(**system_arguments)
|
37
|
+
@system_arguments[:tag] = :"tree-view-icon-pair"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module Alpha
|
5
|
+
class TreeView
|
6
|
+
# The leading action for `TreeView` nodes.
|
7
|
+
#
|
8
|
+
# This component is part of the <%= link_to_component(Primer::Alpha::TreeView) %> component and should
|
9
|
+
# not be used directly.
|
10
|
+
class LeadingAction < Primer::Component
|
11
|
+
# @param action [ViewComponent::Base] A component or other renderable to use as the action button etc.
|
12
|
+
def initialize(action:)
|
13
|
+
@action = action
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<%= render(@node) do |node| %>
|
2
|
+
<% if leading_action? %>
|
3
|
+
<% node.with_leading_action do %>
|
4
|
+
<%= leading_action %>
|
5
|
+
<% end %>
|
6
|
+
<% end %>
|
7
|
+
<% if leading_visual? %>
|
8
|
+
<% node.with_leading_visual do %>
|
9
|
+
<%= leading_visual %>
|
10
|
+
<% end %>
|
11
|
+
<% end %>
|
12
|
+
<% if trailing_visual? %>
|
13
|
+
<% node.with_trailing_visual do %>
|
14
|
+
<%= trailing_visual %>
|
15
|
+
<% end %>
|
16
|
+
<% end %>
|
17
|
+
<% node.with_text_content { @label } %>
|
18
|
+
<% end %>
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module Alpha
|
5
|
+
class TreeView
|
6
|
+
# A `TreeView` leaf node.
|
7
|
+
#
|
8
|
+
# This component is part of the <%= link_to_component(Primer::Alpha::TreeView) %> component and should
|
9
|
+
# not be used directly.
|
10
|
+
class LeafNode < Primer::Component
|
11
|
+
# @!parse
|
12
|
+
# # Adds a leading visual icon rendered to the left of the node's label.
|
13
|
+
# #
|
14
|
+
# # @param label [String] A label describing the visual, displayed only to screen readers.
|
15
|
+
# # @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Alpha::TreeView::Icon) %>.
|
16
|
+
# def with_leading_visual_icon(label: nil, **system_arguments, &block)
|
17
|
+
# end
|
18
|
+
|
19
|
+
renders_one :leading_visual, types: {
|
20
|
+
icon: lambda { |label: nil, **system_arguments|
|
21
|
+
merge_system_arguments!(
|
22
|
+
aria: { describedby: leading_visual_label_id }
|
23
|
+
)
|
24
|
+
|
25
|
+
Visual.new(
|
26
|
+
id: leading_visual_label_id,
|
27
|
+
visual: Icon.new(**system_arguments),
|
28
|
+
label: label
|
29
|
+
)
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
# @!parse
|
34
|
+
# # Adds a leading action rendered to the left of the node's label and any leading visuals or checkboxes.
|
35
|
+
# #
|
36
|
+
# # @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Beta::IconButton) %>.
|
37
|
+
# def with_leading_action_button(**system_arguments, &block)
|
38
|
+
# end
|
39
|
+
|
40
|
+
renders_one :leading_action, types: {
|
41
|
+
button: lambda { |**system_arguments|
|
42
|
+
LeadingAction.new(
|
43
|
+
action: Primer::Beta::IconButton.new(
|
44
|
+
scheme: :invisible,
|
45
|
+
**system_arguments
|
46
|
+
)
|
47
|
+
)
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
# @!parse
|
52
|
+
# # Adds a trailing visual icon rendered to the right of the node's label.
|
53
|
+
# #
|
54
|
+
# # @param label [String] A label describing the visual, displayed only to screen readers.
|
55
|
+
# # @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Alpha::TreeView::Icon) %>.
|
56
|
+
# def with_trailing_visual_icon(label: nil, **system_arguments, &block)
|
57
|
+
# end
|
58
|
+
|
59
|
+
renders_one :trailing_visual, types: {
|
60
|
+
icon: lambda { |label: nil, **system_arguments|
|
61
|
+
Visual.new(
|
62
|
+
id: nil,
|
63
|
+
visual: Icon.new(**system_arguments),
|
64
|
+
label: label
|
65
|
+
)
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
delegate :current?, :merge_system_arguments!, to: :@node
|
70
|
+
|
71
|
+
# @param label [String] The node's label, i.e. it's textual content.
|
72
|
+
# @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Alpha::TreeView::Node) %>.
|
73
|
+
def initialize(label:, **system_arguments)
|
74
|
+
@label = label
|
75
|
+
@system_arguments = system_arguments
|
76
|
+
@system_arguments[:data] = merge_data(
|
77
|
+
@system_arguments,
|
78
|
+
data: { "node-type": "leaf" }
|
79
|
+
)
|
80
|
+
|
81
|
+
@node = Primer::Alpha::TreeView::Node.new(**@system_arguments)
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def base_id
|
87
|
+
@base_id ||= self.class.generate_id
|
88
|
+
end
|
89
|
+
|
90
|
+
def leading_visual_label_id
|
91
|
+
@leading_visual_id ||= "#{base_id}-leading-visual-label"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<%= render(Primer::BaseComponent.new(**@system_arguments)) do %>
|
2
|
+
<%= render(Primer::Beta::Octicon.new(icon: :"alert-fill", color: :danger)) %>
|
3
|
+
<span><%= @text %></span>
|
4
|
+
<div></div> <!-- spacer -->
|
5
|
+
<%= render(Primer::Beta::Button.new(
|
6
|
+
size: :small,
|
7
|
+
scheme: :default,
|
8
|
+
style: "justify-self: start",
|
9
|
+
**@retry_button_arguments
|
10
|
+
)) do %>
|
11
|
+
<%= @retry_button_label %>
|
12
|
+
<% end %>
|
13
|
+
<% end %>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module Alpha
|
5
|
+
class TreeView
|
6
|
+
# A `TreeView` loading failure message.
|
7
|
+
#
|
8
|
+
# This component is part of the <%= link_to_component(Primer::Alpha::TreeView) %> component and should
|
9
|
+
# not be used directly.
|
10
|
+
class LoadingFailureMessage < Primer::Component
|
11
|
+
DEFAULT_TEXT = "Something went wrong"
|
12
|
+
DEFAULT_RETRY_BUTTON_LABEL = "Retry"
|
13
|
+
|
14
|
+
# @param text [String] The failure message to display.
|
15
|
+
# @param retry_button_label [String] The text shown on the retry button.
|
16
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
17
|
+
def initialize(text: DEFAULT_TEXT, retry_button_label: DEFAULT_RETRY_BUTTON_LABEL, **system_arguments)
|
18
|
+
@text = text
|
19
|
+
@retry_button_label = retry_button_label
|
20
|
+
@retry_button_arguments = system_arguments.delete(:retry_button_arguments)
|
21
|
+
@system_arguments = deny_tag_argument(**system_arguments)
|
22
|
+
@system_arguments[:tag] = :div
|
23
|
+
@system_arguments[:classes] = class_names(
|
24
|
+
@system_arguments.delete(:classes),
|
25
|
+
"TreeViewFailureMessage"
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
<%= render(Primer::BaseComponent.new(**@system_arguments)) do %>
|
2
|
+
<div class="TreeViewItemContainer" style="--level: <%= level %>;">
|
3
|
+
<div style="grid-area: spacer; display: flex;">
|
4
|
+
<div style="width: 100%; display: flex;">
|
5
|
+
<% (0...(level - 1)).each do %>
|
6
|
+
<div class="TreeViewItemLevelLine"></div>
|
7
|
+
<% end %>
|
8
|
+
</div>
|
9
|
+
</div>
|
10
|
+
<% if toggle? %>
|
11
|
+
<%= toggle %>
|
12
|
+
<% end %>
|
13
|
+
<% if leading_action? %>
|
14
|
+
<%= leading_action %>
|
15
|
+
<% end %>
|
16
|
+
<%= render(Primer::BaseComponent.new(**@content_arguments)) do %>
|
17
|
+
<% if @select_variant == :multiple %>
|
18
|
+
<div aria-hidden="true" class="TreeViewItemCheckbox" tabindex="-1">
|
19
|
+
<div class="FormControl-checkbox"></div>
|
20
|
+
</div>
|
21
|
+
<% end %>
|
22
|
+
<% if leading_visual? %>
|
23
|
+
<%= leading_visual %>
|
24
|
+
<% end %>
|
25
|
+
<span class="TreeViewItemContentText"><%= text_content %></span>
|
26
|
+
<% if trailing_visual? %>
|
27
|
+
<%= trailing_visual %>
|
28
|
+
<% end %>
|
29
|
+
<% end %>
|
30
|
+
</div>
|
31
|
+
<%= content %>
|
32
|
+
<% end %>
|
@@ -0,0 +1,194 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module Alpha
|
5
|
+
class TreeView
|
6
|
+
# A generic `TreeView` node.
|
7
|
+
#
|
8
|
+
# This component is part of the <%= link_to_component(Primer::Alpha::TreeView) %> component and should
|
9
|
+
# not be used directly.
|
10
|
+
class Node < Primer::Component
|
11
|
+
DEFAULT_NODE_VARIANT = Primer::Alpha::TreeView::DEFAULT_NODE_VARIANT
|
12
|
+
NODE_VARIANT_TAG_MAP = { DEFAULT_NODE_VARIANT => :div, :button => :button, :anchor => :a }.freeze
|
13
|
+
NODE_VARIANT_TAG_OPTIONS = NODE_VARIANT_TAG_MAP.keys.freeze
|
14
|
+
|
15
|
+
# Generic leading action slot
|
16
|
+
renders_one :leading_action
|
17
|
+
|
18
|
+
# Generic leading visual slot
|
19
|
+
renders_one :leading_visual
|
20
|
+
|
21
|
+
# Generic trailing visual slot
|
22
|
+
renders_one :trailing_visual
|
23
|
+
|
24
|
+
# Generic toggle button slot
|
25
|
+
renders_one :toggle
|
26
|
+
|
27
|
+
# Generic text content slot (for node's label)
|
28
|
+
renders_one :text_content
|
29
|
+
|
30
|
+
# Wether or not this node is the current node.
|
31
|
+
#
|
32
|
+
# @return [Boolean]
|
33
|
+
attr_reader :current
|
34
|
+
alias current? current
|
35
|
+
|
36
|
+
# This node's checked state.
|
37
|
+
#
|
38
|
+
# @return [String]
|
39
|
+
attr_reader :checked
|
40
|
+
|
41
|
+
# This node's select variant (i.e. check box variant).
|
42
|
+
#
|
43
|
+
# @return [Symbol]
|
44
|
+
attr_reader :select_variant
|
45
|
+
|
46
|
+
# This node's variant, eg. `:button`, `:div`, etc.
|
47
|
+
#
|
48
|
+
# @return [Symbol]
|
49
|
+
attr_reader :node_variant
|
50
|
+
|
51
|
+
# Whether or not this node is disabled, i.e. cannot be activated.
|
52
|
+
#
|
53
|
+
# @return [Boolean]
|
54
|
+
attr_reader :disabled
|
55
|
+
alias disabled? disabled
|
56
|
+
|
57
|
+
DEFAULT_SELECT_VARIANT = :none
|
58
|
+
SELECT_VARIANT_OPTIONS = [
|
59
|
+
:multiple,
|
60
|
+
DEFAULT_SELECT_VARIANT
|
61
|
+
].freeze
|
62
|
+
|
63
|
+
DEFAULT_CHECKED_STATE = false
|
64
|
+
CHECKED_STATES = [
|
65
|
+
DEFAULT_CHECKED_STATE,
|
66
|
+
true,
|
67
|
+
"mixed"
|
68
|
+
]
|
69
|
+
|
70
|
+
# @param path [Array<String>] The node's "path," i.e. this node's label and the labels of all its ancestors. This node should be reachable by traversing the tree following this path.
|
71
|
+
# @param node_variant [Symbol] The node variant to use for the node's content, i.e. the `:button` or `:div`. <%= one_of(Primer::Alpha::TreeView::NODE_VARIANT_OPTIONS) %>
|
72
|
+
# @param href [String] The URL to use as the `href` attribute for this node. If set to a truthy value, the `tag:` parameter is ignored and assumed to be `:a`.
|
73
|
+
# @param current [Boolean] Whether or not this node is the current node. The current node is styled differently than regular nodes and is the first element that receives focus when tabbing to the `TreeView` component.
|
74
|
+
# @param select_variant [Symbol] Controls the type of checkbox that appears. <%= one_of(Primer::Alpha::TreeView::Node::SELECT_VARIANT_OPTIONS) %>
|
75
|
+
# @param checked [Boolean | String] The checked state of the node's checkbox. <%= one_of(Primer::Alpha::TreeView::Node::CHECKED_STATES) %>
|
76
|
+
# @param disabled [Boolean] Whether or not the node can be activated. Passing `false` here will cause the node to appear visually disabled but it is still keyboard-focusable.
|
77
|
+
# @param value [String] If this node is checked, this value will be sent to the server on form submission.
|
78
|
+
# @param content_arguments [Hash] Arguments attached to the node's content, i.e the `<button>` or `<a>` element. <%= link_to_system_arguments_docs %>
|
79
|
+
def initialize(
|
80
|
+
path:,
|
81
|
+
node_variant:,
|
82
|
+
href: nil,
|
83
|
+
current: false,
|
84
|
+
select_variant: DEFAULT_SELECT_VARIANT,
|
85
|
+
checked: DEFAULT_CHECKED_STATE,
|
86
|
+
disabled: false,
|
87
|
+
value: nil,
|
88
|
+
**content_arguments
|
89
|
+
)
|
90
|
+
@system_arguments = {
|
91
|
+
tag: :li,
|
92
|
+
role: :none,
|
93
|
+
classes: "TreeViewItem"
|
94
|
+
}
|
95
|
+
|
96
|
+
@content_arguments = content_arguments
|
97
|
+
|
98
|
+
@path = path
|
99
|
+
@current = current
|
100
|
+
@select_variant = fetch_or_fallback(SELECT_VARIANT_OPTIONS, select_variant, DEFAULT_SELECT_VARIANT)
|
101
|
+
@checked = fetch_or_fallback(CHECKED_STATES, checked, DEFAULT_CHECKED_STATE)
|
102
|
+
@disabled = disabled
|
103
|
+
@node_variant = fetch_or_fallback(NODE_VARIANT_TAG_OPTIONS, node_variant, DEFAULT_NODE_VARIANT)
|
104
|
+
|
105
|
+
@content_arguments[:tag] = NODE_VARIANT_TAG_MAP[@node_variant]
|
106
|
+
@content_arguments[:href] = href if href
|
107
|
+
@content_arguments[:id] = content_id
|
108
|
+
@content_arguments[:role] = :treeitem
|
109
|
+
@content_arguments[:tabindex] = current? ? 0 : -1
|
110
|
+
@content_arguments[:classes] = class_names(
|
111
|
+
@content_arguments.delete(:classes),
|
112
|
+
"TreeViewItemContent"
|
113
|
+
)
|
114
|
+
|
115
|
+
@content_arguments[:aria] = merge_aria(
|
116
|
+
@content_arguments, {
|
117
|
+
aria: {
|
118
|
+
level: level,
|
119
|
+
selected: false,
|
120
|
+
checked: checked,
|
121
|
+
labelledby: content_id,
|
122
|
+
disabled: disabled?
|
123
|
+
}
|
124
|
+
}
|
125
|
+
)
|
126
|
+
|
127
|
+
@content_arguments[:data] = merge_data(
|
128
|
+
@content_arguments, {
|
129
|
+
data: {
|
130
|
+
value: value,
|
131
|
+
path: @path.to_json
|
132
|
+
}
|
133
|
+
}
|
134
|
+
)
|
135
|
+
|
136
|
+
return unless current?
|
137
|
+
|
138
|
+
@content_arguments[:aria] = merge_aria(
|
139
|
+
@content_arguments,
|
140
|
+
{ aria: { current: true } }
|
141
|
+
)
|
142
|
+
end
|
143
|
+
|
144
|
+
# The numeric depth of this node.
|
145
|
+
#
|
146
|
+
# @return [Integer] This node's depth.
|
147
|
+
def level
|
148
|
+
@level ||= @path.size
|
149
|
+
end
|
150
|
+
|
151
|
+
# Merges the given arguments into the current hash of system arguments provided when the component was
|
152
|
+
# initially constructed. This method can be used to add additional arguments just before rendering.
|
153
|
+
#
|
154
|
+
# @param other_arguments [Hash] The other hash of system arguments to merge into the current one.
|
155
|
+
def merge_system_arguments!(**other_arguments)
|
156
|
+
@content_arguments[:aria] = merge_aria(
|
157
|
+
@content_arguments,
|
158
|
+
other_arguments
|
159
|
+
)
|
160
|
+
|
161
|
+
@content_arguments[:data] = merge_data(
|
162
|
+
@content_arguments,
|
163
|
+
other_arguments
|
164
|
+
)
|
165
|
+
|
166
|
+
@content_arguments.merge!(**other_arguments)
|
167
|
+
end
|
168
|
+
|
169
|
+
private
|
170
|
+
|
171
|
+
def before_render
|
172
|
+
if leading_action?
|
173
|
+
@content_arguments[:data] = merge_data(
|
174
|
+
@content_arguments,
|
175
|
+
{ data: { "has-leading-action": true } }
|
176
|
+
)
|
177
|
+
end
|
178
|
+
|
179
|
+
if select_variant != :none && node_variant != :div
|
180
|
+
raise ArgumentError, "TreeView nodes do not support select variants for tags other than :div."
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def content_id
|
185
|
+
@content_id ||= "#{base_id}-content"
|
186
|
+
end
|
187
|
+
|
188
|
+
def base_id
|
189
|
+
@base_id ||= self.class.generate_id
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<% unless loading_failure_message? %>
|
2
|
+
<% with_loading_failure_message # set the default %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<%= render(Primer::BaseComponent.new(tag: :"tree-view-include-fragment", src: @src, loading: :lazy, data: { target: "tree-view-sub-tree-node.subTree tree-view-sub-tree-node.includeFragment", path: @container.path.to_json }, hidden: @container.expanded?, accept: "text/fragment+html")) do %>
|
6
|
+
<%= render(@container) do %>
|
7
|
+
<%= render(Primer::Alpha::TreeView::Node.new(path: [*@container.path, :loader], node_variant: :div)) do |node| %>
|
8
|
+
<% node.with_text_content do %>
|
9
|
+
<div data-target="tree-view-sub-tree-node.loadingIndicator">
|
10
|
+
<% @count.times do %>
|
11
|
+
<span class="TreeViewSkeletonItemContainerStyle TreeViewItemSkeleton">
|
12
|
+
<%= render(Primer::Alpha::SkeletonBox.new(width: "16px")) %>
|
13
|
+
<%= render(Primer::Alpha::SkeletonBox.new(width: "100%", classes: "TreeItemSkeletonTextStyles")) %>
|
14
|
+
</span>
|
15
|
+
<% end %>
|
16
|
+
</div>
|
17
|
+
<div data-target="tree-view-sub-tree-node.loadingFailureMessage" hidden>
|
18
|
+
<%= loading_failure_message %>
|
19
|
+
</div>
|
20
|
+
<% end %>
|
21
|
+
<% end %>
|
22
|
+
<% end %>
|
23
|
+
<% end %>
|