openproject-primer_view_components 0.64.1 → 0.65.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/app/assets/javascripts/components/primer/open_project/tree_view/tree_view.d.ts +29 -0
  4. data/app/assets/javascripts/components/primer/open_project/tree_view/tree_view_icon_pair_element.d.ts +15 -0
  5. data/app/assets/javascripts/components/primer/open_project/tree_view/tree_view_include_fragment_element.d.ts +9 -0
  6. data/app/assets/javascripts/components/primer/open_project/tree_view/tree_view_roving_tab_index.d.ts +3 -0
  7. data/app/assets/javascripts/components/primer/open_project/tree_view/tree_view_sub_tree_node_element.d.ts +38 -0
  8. data/app/assets/javascripts/components/primer/primer.d.ts +4 -0
  9. data/app/assets/javascripts/components/primer/shared_events.d.ts +15 -0
  10. data/app/assets/javascripts/primer_view_components.js +1 -1
  11. data/app/assets/javascripts/primer_view_components.js.map +1 -1
  12. data/app/assets/styles/primer_view_components.css +1 -1
  13. data/app/assets/styles/primer_view_components.css.map +1 -1
  14. data/app/components/primer/alpha/select_panel.css +1 -1
  15. data/app/components/primer/alpha/select_panel.css.json +2 -2
  16. data/app/components/primer/alpha/select_panel.css.map +1 -1
  17. data/app/components/primer/alpha/select_panel.html.erb +1 -1
  18. data/app/components/primer/alpha/select_panel.pcss +5 -2
  19. data/app/components/primer/beta/spinner.html.erb +1 -1
  20. data/app/components/primer/beta/spinner.rb +2 -0
  21. data/app/components/primer/open_project/file_tree_view/directory_node.html.erb +5 -0
  22. data/app/components/primer/open_project/file_tree_view/directory_node.rb +24 -0
  23. data/app/components/primer/open_project/file_tree_view/file_node.html.erb +2 -0
  24. data/app/components/primer/open_project/file_tree_view/file_node.rb +14 -0
  25. data/app/components/primer/open_project/file_tree_view.rb +15 -0
  26. data/app/components/primer/open_project/skeleton_box.css +1 -0
  27. data/app/components/primer/open_project/skeleton_box.css.json +6 -0
  28. data/app/components/primer/open_project/skeleton_box.css.map +1 -0
  29. data/app/components/primer/open_project/skeleton_box.html.erb +1 -0
  30. data/app/components/primer/open_project/skeleton_box.pcss +30 -0
  31. data/app/components/primer/open_project/skeleton_box.rb +27 -0
  32. data/app/components/primer/open_project/tree_view/icon.html.erb +1 -0
  33. data/app/components/primer/open_project/tree_view/icon.rb +22 -0
  34. data/app/components/primer/open_project/tree_view/icon_pair.html.erb +13 -0
  35. data/app/components/primer/open_project/tree_view/icon_pair.rb +42 -0
  36. data/app/components/primer/open_project/tree_view/leading_action.html.erb +3 -0
  37. data/app/components/primer/open_project/tree_view/leading_action.rb +18 -0
  38. data/app/components/primer/open_project/tree_view/leaf_node.html.erb +18 -0
  39. data/app/components/primer/open_project/tree_view/leaf_node.rb +96 -0
  40. data/app/components/primer/open_project/tree_view/loading_failure_message.html.erb +13 -0
  41. data/app/components/primer/open_project/tree_view/loading_failure_message.rb +31 -0
  42. data/app/components/primer/open_project/tree_view/node.html.erb +32 -0
  43. data/app/components/primer/open_project/tree_view/node.rb +155 -0
  44. data/app/components/primer/open_project/tree_view/skeleton_loader.html.erb +23 -0
  45. data/app/components/primer/open_project/tree_view/skeleton_loader.rb +36 -0
  46. data/app/components/primer/open_project/tree_view/spinner_loader.html.erb +20 -0
  47. data/app/components/primer/open_project/tree_view/spinner_loader.rb +33 -0
  48. data/app/components/primer/open_project/tree_view/sub_tree.html.erb +21 -0
  49. data/app/components/primer/open_project/tree_view/sub_tree.rb +106 -0
  50. data/app/components/primer/open_project/tree_view/sub_tree_container.html.erb +3 -0
  51. data/app/components/primer/open_project/tree_view/sub_tree_container.rb +39 -0
  52. data/app/components/primer/open_project/tree_view/sub_tree_node.html.erb +49 -0
  53. data/app/components/primer/open_project/tree_view/sub_tree_node.rb +172 -0
  54. data/app/components/primer/open_project/tree_view/tree_view.d.ts +29 -0
  55. data/app/components/primer/open_project/tree_view/tree_view.js +238 -0
  56. data/app/components/primer/open_project/tree_view/tree_view.ts +257 -0
  57. data/app/components/primer/open_project/tree_view/tree_view_icon_pair_element.d.ts +15 -0
  58. data/app/components/primer/open_project/tree_view/tree_view_icon_pair_element.js +62 -0
  59. data/app/components/primer/open_project/tree_view/tree_view_icon_pair_element.ts +56 -0
  60. data/app/components/primer/open_project/tree_view/tree_view_include_fragment_element.d.ts +9 -0
  61. data/app/components/primer/open_project/tree_view/tree_view_include_fragment_element.js +29 -0
  62. data/app/components/primer/open_project/tree_view/tree_view_include_fragment_element.ts +29 -0
  63. data/app/components/primer/open_project/tree_view/tree_view_roving_tab_index.d.ts +3 -0
  64. data/app/components/primer/open_project/tree_view/tree_view_roving_tab_index.js +126 -0
  65. data/app/components/primer/open_project/tree_view/tree_view_roving_tab_index.ts +156 -0
  66. data/app/components/primer/open_project/tree_view/tree_view_sub_tree_node_element.d.ts +38 -0
  67. data/app/components/primer/open_project/tree_view/tree_view_sub_tree_node_element.js +362 -0
  68. data/app/components/primer/open_project/tree_view/tree_view_sub_tree_node_element.ts +402 -0
  69. data/app/components/primer/open_project/tree_view/visual.html.erb +14 -0
  70. data/app/components/primer/open_project/tree_view/visual.rb +27 -0
  71. data/app/components/primer/open_project/tree_view.css +1 -0
  72. data/app/components/primer/open_project/tree_view.css.json +42 -0
  73. data/app/components/primer/open_project/tree_view.css.map +1 -0
  74. data/app/components/primer/open_project/tree_view.html.erb +7 -0
  75. data/app/components/primer/open_project/tree_view.pcss +319 -0
  76. data/app/components/primer/open_project/tree_view.rb +367 -0
  77. data/app/components/primer/primer.d.ts +4 -0
  78. data/app/components/primer/primer.js +4 -0
  79. data/app/components/primer/primer.pcss +2 -0
  80. data/app/components/primer/primer.ts +4 -0
  81. data/app/components/primer/shared_events.d.ts +15 -0
  82. data/app/components/primer/shared_events.ts +19 -0
  83. data/app/lib/primer/forms/acts_as_component.rb +1 -12
  84. data/lib/primer/view_components/version.rb +2 -2
  85. data/previews/primer/open_project/file_tree_view_preview/default.html.erb +16 -0
  86. data/previews/primer/open_project/file_tree_view_preview/playground.html.erb +4 -0
  87. data/previews/primer/open_project/file_tree_view_preview.rb +69 -0
  88. data/previews/primer/open_project/skeleton_box_preview.rb +20 -0
  89. data/previews/primer/open_project/tree_view_preview/default.html.erb +24 -0
  90. data/previews/primer/open_project/tree_view_preview/empty.html.erb +10 -0
  91. data/previews/primer/open_project/tree_view_preview/leaf_node_playground.html.erb +15 -0
  92. data/previews/primer/open_project/tree_view_preview/loading_failure.html.erb +36 -0
  93. data/previews/primer/open_project/tree_view_preview/loading_skeleton.html.erb +12 -0
  94. data/previews/primer/open_project/tree_view_preview/loading_spinner.html.erb +12 -0
  95. data/previews/primer/open_project/tree_view_preview/playground.html.erb +4 -0
  96. data/previews/primer/open_project/tree_view_preview.rb +139 -0
  97. data/static/arguments.json +388 -0
  98. data/static/audited_at.json +17 -0
  99. data/static/classes.json +15 -0
  100. data/static/constants.json +83 -0
  101. data/static/info_arch.json +1367 -0
  102. data/static/previews.json +167 -0
  103. data/static/statuses.json +17 -0
  104. metadata +75 -2
@@ -1 +1 @@
1
- .SelectPanel-emptyPanel,.SelectPanel-loadingPanel{min-height:min(var(--overlay-height) - 10rem,100vh - 2rem)}
1
+ .SelectPanel-loadingPanel{min-height:min(calc(var(--overlay-height) - 10rem),calc(100vh - 2rem))}.SelectPanel-emptyPanel{align-items:center;display:flex;justify-content:center;min-height:min(calc(var(--overlay-height) - 23rem),calc(100vh - 2rem))}
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "alpha/select_panel",
3
3
  "selectors": [
4
- ".SelectPanel-emptyPanel",
5
- ".SelectPanel-loadingPanel"
4
+ ".SelectPanel-loadingPanel",
5
+ ".SelectPanel-emptyPanel"
6
6
  ]
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["select_panel.pcss"],"names":[],"mappings":"AAIA,kDACE,0DACF","file":"select_panel.css","sourcesContent":[".SelectPanel-loadingPanel {\n min-height: min(var(--overlay-height) - 10rem, 100vh - 2rem);\n}\n\n.SelectPanel-emptyPanel {\n min-height: min(var(--overlay-height) - 10rem, 100vh - 2rem);\n}\n"]}
1
+ {"version":3,"sources":["select_panel.pcss"],"names":[],"mappings":"AAAA,0BACE,sEACF,CAEA,wBAEE,kBAAmB,CACnB,YAAa,CACb,sBAAuB,CAHvB,sEAIF","file":"select_panel.css","sourcesContent":[".SelectPanel-loadingPanel {\n min-height: min(calc(var(--overlay-height) - 10rem), calc(100vh - 2rem));\n}\n\n.SelectPanel-emptyPanel {\n min-height: min(calc(var(--overlay-height) - 23rem), calc(100vh - 2rem));\n align-items: center;\n display: flex;\n justify-content: center;\n}\n"]}
@@ -97,7 +97,7 @@
97
97
  <%= render(@list) %>
98
98
  <% end %>
99
99
  </div>
100
- <div data-target="select-panel.noResults" class="pt-2 color-border-muted text-center d-flex flex-items-start flex-justify-center SelectPanel-emptyPanel" hidden>
100
+ <div data-target="select-panel.noResults" class="SelectPanel-emptyPanel" hidden>
101
101
  <h2 class="v-align-middle m-3 f5"><%= @no_results_label %></h2>
102
102
  </div>
103
103
  <% end %>
@@ -1,7 +1,10 @@
1
1
  .SelectPanel-loadingPanel {
2
- min-height: min(var(--overlay-height) - 10rem, 100vh - 2rem);
2
+ min-height: min(calc(var(--overlay-height) - 10rem), calc(100vh - 2rem));
3
3
  }
4
4
 
5
5
  .SelectPanel-emptyPanel {
6
- min-height: min(var(--overlay-height) - 10rem, 100vh - 2rem);
6
+ min-height: min(calc(var(--overlay-height) - 23rem), calc(100vh - 2rem));
7
+ align-items: center;
8
+ display: flex;
9
+ justify-content: center;
7
10
  }
@@ -1,4 +1,4 @@
1
- <%= render(Primer::BaseComponent.new(tag: :span, hidden: @hidden, data: { target: @target })) do %>
1
+ <%= render(Primer::BaseComponent.new(tag: :span, hidden: @hidden, data: { target: @target }, **@wrapper_arguments)) do %>
2
2
  <%= render Primer::BaseComponent.new(**@system_arguments) do %>
3
3
  <circle cx="8" cy="8" r="7" stroke="currentColor" stroke-opacity="0.25" stroke-width="2" vector-effect="non-scaling-stroke" fill="none" />
4
4
  <path d="M15 8a7.002 7.002 0 00-7-7" stroke="currentColor" stroke-width="2" stroke-linecap="round" vector-effect="non-scaling-stroke" />
@@ -43,6 +43,8 @@ module Primer
43
43
 
44
44
  @target = extract_data(:target, @system_arguments)
45
45
  @hidden = @system_arguments.delete(:hidden)
46
+
47
+ @wrapper_arguments = @system_arguments.delete(:wrapper_arguments) || {}
46
48
  end
47
49
 
48
50
  def no_aria_label?
@@ -0,0 +1,5 @@
1
+ <% with_leading_visual_icons do |icons| %>
2
+ <% icons.with_expanded_icon(icon: :"file-directory-open-fill", **@expanded_icon_arguments) %>
3
+ <% icons.with_collapsed_icon(icon: :"file-directory-fill", **@collapsed_icon_arguments) %>
4
+ <% end %>
5
+ <%= render_parent %>
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module OpenProject
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,2 @@
1
+ <% with_leading_visual_icon(icon: :file, **@icon_arguments) %>
2
+ <%= render_parent %>
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module OpenProject
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 OpenProject
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,6 @@
1
+ {
2
+ "name": "open_project/skeleton_box",
3
+ "selectors": [
4
+ ".SkeletonBox"
5
+ ]
6
+ }
@@ -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,wDAAqE,CACrE,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%, rgba(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%, rgba(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,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module OpenProject
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
+ # @param height [String] Any valid CSS height.
9
+ # @param width [String] Any valid CSS width.
10
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
11
+ def initialize(height: nil, width: nil, **system_arguments)
12
+ @system_arguments = deny_tag_argument(**system_arguments)
13
+
14
+ styles = []
15
+ styles << "width: #{width}" if width
16
+ styles << "height: #{height}" if height
17
+
18
+ @system_arguments[:tag] = :div
19
+ @system_arguments[:style] = styles.join("; ") if styles.present?
20
+ @system_arguments[:classes] = class_names(
21
+ @system_arguments.delete(:classes),
22
+ "SkeletonBox"
23
+ )
24
+ end
25
+ end
26
+ end
27
+ 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 OpenProject
5
+ class TreeView
6
+ # An icon for a `TreeView` node.
7
+ #
8
+ # This component is part of the <%= link_to_component(Primer::OpenProject::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 OpenProject
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::OpenProject::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::OpenProject::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::OpenProject::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,3 @@
1
+ <div class="TreeViewItemLeadingAction" aria-hidden="true">
2
+ <%= render(@action) %>
3
+ </div>
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module OpenProject
5
+ class TreeView
6
+ # The leading action for `TreeView` nodes.
7
+ #
8
+ # This component is part of the <%= link_to_component(Primer::OpenProject::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 OpenProject
5
+ class TreeView
6
+ # A `TreeView` leaf node.
7
+ #
8
+ # This component is part of the <%= link_to_component(Primer::OpenProject::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::OpenProject::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::OpenProject::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::OpenProject::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::OpenProject::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 OpenProject
5
+ class TreeView
6
+ # A `TreeView` loading failure message.
7
+ #
8
+ # This component is part of the <%= link_to_component(Primer::OpenProject::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
+ <div id="<%= content_id %>" class="TreeViewItemContent">
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
+ </div>
30
+ </div>
31
+ <%= content %>
32
+ <% end %>