primer_view_components 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/app/assets/javascripts/app/components/primer/alpha/action_bar_element.d.ts +16 -0
  4. data/app/assets/javascripts/app/components/primer/alpha/action_menu/action_menu_element.d.ts +30 -0
  5. data/app/assets/javascripts/app/components/primer/alpha/dropdown/menu.d.ts +1 -0
  6. data/app/assets/javascripts/app/components/primer/alpha/dropdown.d.ts +1 -0
  7. data/app/assets/javascripts/app/components/primer/alpha/image_crop.d.ts +1 -0
  8. data/app/assets/javascripts/app/components/primer/alpha/modal_dialog.d.ts +18 -0
  9. data/app/assets/javascripts/app/components/primer/alpha/nav_list.d.ts +28 -0
  10. data/app/assets/javascripts/app/components/primer/alpha/segmented_control.d.ts +12 -0
  11. data/app/assets/javascripts/app/components/primer/alpha/tab_container.d.ts +1 -0
  12. data/app/assets/javascripts/app/components/primer/alpha/toggle_switch.d.ts +30 -0
  13. data/app/assets/javascripts/app/components/primer/alpha/tool_tip.d.ts +26 -0
  14. data/app/assets/javascripts/app/components/primer/alpha/x_banner.d.ts +11 -0
  15. data/app/assets/javascripts/app/components/primer/anchored_position.d.ts +27 -0
  16. data/app/assets/javascripts/app/components/primer/beta/auto_complete/auto_complete.d.ts +1 -0
  17. data/app/assets/javascripts/app/components/primer/beta/clipboard_copy.d.ts +1 -0
  18. data/app/assets/javascripts/app/components/primer/beta/relative_time.d.ts +1 -0
  19. data/app/assets/javascripts/app/components/primer/focus_group.d.ts +19 -0
  20. data/app/assets/javascripts/app/components/primer/primer.d.ts +21 -0
  21. data/app/assets/javascripts/lib/primer/forms/primer_multi_input.d.ts +10 -0
  22. data/app/assets/javascripts/lib/primer/forms/primer_text_field.d.ts +1 -0
  23. data/app/assets/javascripts/lib/primer/forms/toggle_switch_input.d.ts +5 -0
  24. data/app/assets/javascripts/primer_view_components.js +1 -1
  25. data/app/assets/javascripts/primer_view_components.js.map +1 -1
  26. data/app/assets/styles/primer_view_components.css +1 -1
  27. data/app/assets/styles/primer_view_components.css.map +1 -1
  28. data/app/components/primer/alpha/action_bar/divider.rb +30 -0
  29. data/app/components/primer/alpha/action_bar/item.rb +26 -0
  30. data/app/components/primer/alpha/action_bar.css +1 -0
  31. data/app/components/primer/alpha/action_bar.css.json +17 -0
  32. data/app/components/primer/alpha/action_bar.css.map +1 -0
  33. data/app/components/primer/alpha/action_bar.html.erb +12 -0
  34. data/app/components/primer/alpha/action_bar.pcss +69 -0
  35. data/app/components/primer/alpha/action_bar.rb +110 -0
  36. data/app/components/primer/alpha/action_bar_element.d.ts +16 -0
  37. data/app/components/primer/alpha/action_bar_element.js +172 -0
  38. data/app/components/primer/alpha/action_bar_element.ts +175 -0
  39. data/app/components/primer/alpha/action_menu/action_menu_element.d.ts +2 -2
  40. data/app/components/primer/alpha/tool_tip.d.ts +3 -2
  41. data/app/components/primer/alpha/tool_tip.js +89 -44
  42. data/app/components/primer/alpha/tool_tip.ts +88 -41
  43. data/app/components/primer/alpha/tooltip.rb +1 -0
  44. data/app/components/primer/beta/link.css +1 -1
  45. data/app/components/primer/beta/link.css.map +1 -1
  46. data/app/components/primer/beta/link.pcss +4 -0
  47. data/app/components/primer/beta/link.rb +6 -10
  48. data/app/components/primer/primer.d.ts +1 -0
  49. data/app/components/primer/primer.js +1 -0
  50. data/app/components/primer/primer.pcss +1 -0
  51. data/app/components/primer/primer.ts +1 -0
  52. data/lib/primer/static/generate_previews.rb +9 -0
  53. data/lib/primer/view_components/linters/tooltipped_migration.rb +1 -3
  54. data/lib/primer/view_components/version.rb +2 -2
  55. data/lib/primer/yard.rb +5 -0
  56. data/previews/primer/alpha/action_bar_preview/inline.html.erb +16 -0
  57. data/previews/primer/alpha/action_bar_preview.rb +77 -0
  58. data/previews/primer/alpha/action_list_preview.rb +10 -0
  59. data/previews/primer/alpha/action_menu_preview.rb +5 -0
  60. data/previews/primer/alpha/auto_complete_preview.rb +1 -0
  61. data/previews/primer/alpha/banner_preview.rb +9 -1
  62. data/previews/primer/alpha/button_marketing_preview.rb +2 -0
  63. data/previews/primer/alpha/check_box_group_preview.rb +1 -0
  64. data/previews/primer/alpha/check_box_preview.rb +6 -0
  65. data/previews/primer/alpha/dialog_preview.rb +1 -0
  66. data/previews/primer/alpha/dropdown_preview.rb +1 -0
  67. data/previews/primer/alpha/hellip_button_preview.rb +1 -0
  68. data/previews/primer/alpha/hidden_text_expander_preview.rb +1 -0
  69. data/previews/primer/alpha/layout_preview.rb +4 -0
  70. data/previews/primer/alpha/menu_preview.rb +1 -0
  71. data/previews/primer/alpha/multi_input_preview.rb +4 -0
  72. data/previews/primer/alpha/nav_list_preview.rb +3 -0
  73. data/previews/primer/alpha/radio_button_group_preview.rb +2 -0
  74. data/previews/primer/alpha/radio_button_preview.rb +10 -0
  75. data/previews/primer/alpha/segmented_control_preview.rb +13 -0
  76. data/previews/primer/alpha/select_preview.rb +6 -0
  77. data/previews/primer/alpha/tab_nav_preview.rb +3 -0
  78. data/previews/primer/alpha/tab_panels_preview.rb +1 -0
  79. data/previews/primer/alpha/text_area_preview.rb +7 -0
  80. data/previews/primer/alpha/text_field_preview.rb +15 -0
  81. data/previews/primer/alpha/toggle_switch_preview.rb +7 -0
  82. data/previews/primer/alpha/tooltip_preview/tooltip_inside_primer_overlay.html.erb +20 -0
  83. data/previews/primer/alpha/tooltip_preview.rb +7 -0
  84. data/previews/primer/alpha/underline_nav_preview.rb +2 -0
  85. data/previews/primer/beta/auto_complete_item_preview.rb +2 -0
  86. data/previews/primer/beta/auto_complete_preview.rb +7 -0
  87. data/previews/primer/beta/avatar_preview.rb +10 -0
  88. data/previews/primer/beta/avatar_stack_preview.rb +3 -0
  89. data/previews/primer/beta/blankslate_preview.rb +9 -0
  90. data/previews/primer/beta/border_box_preview.rb +4 -0
  91. data/previews/primer/beta/breadcrumbs_preview.rb +1 -0
  92. data/previews/primer/beta/button_group_preview.rb +4 -0
  93. data/previews/primer/beta/button_preview.rb +10 -0
  94. data/previews/primer/beta/clipboard_copy_preview.rb +2 -0
  95. data/previews/primer/beta/close_button_preview.rb +1 -0
  96. data/previews/primer/beta/counter_preview.rb +11 -0
  97. data/previews/primer/beta/flash_preview.rb +8 -0
  98. data/previews/primer/beta/heading_preview.rb +1 -0
  99. data/previews/primer/beta/icon_button_preview.rb +3 -0
  100. data/previews/primer/beta/label_preview.rb +13 -0
  101. data/previews/primer/beta/link_preview.rb +11 -9
  102. data/previews/primer/beta/markdown_preview.rb +1 -0
  103. data/previews/primer/beta/octicon_preview.rb +1 -0
  104. data/previews/primer/beta/popover_preview.rb +6 -0
  105. data/previews/primer/beta/progress_bar_preview.rb +4 -0
  106. data/previews/primer/beta/spinner_preview.rb +1 -0
  107. data/previews/primer/beta/state_preview.rb +6 -0
  108. data/previews/primer/beta/subhead_preview.rb +4 -0
  109. data/previews/primer/beta/text_preview.rb +1 -0
  110. data/previews/primer/beta/timeline_item_preview.rb +1 -0
  111. data/previews/primer/beta/truncate_preview.rb +1 -0
  112. data/previews/primer/box_preview.rb +2 -0
  113. data/static/arguments.json +51 -7
  114. data/static/audited_at.json +3 -0
  115. data/static/classes.json +21 -0
  116. data/static/constants.json +20 -6
  117. data/static/info_arch.json +669 -7
  118. data/static/previews.json +571 -0
  119. data/static/statuses.json +3 -0
  120. metadata +43 -8
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nocov:
4
+
5
+ module Primer
6
+ module Alpha
7
+ class ActionBar
8
+ # ActionBar::Item is an internal component that wraps the items in a div with the `ActionBar-item` class.
9
+ class Divider < Primer::Component
10
+ def initialize
11
+ @system_arguments = {
12
+ tag: :hr,
13
+ role: :presentation,
14
+ aria: {
15
+ hidden: true
16
+ },
17
+ data: {
18
+ targets: "action-bar.items"
19
+ },
20
+ classes: "ActionBar-item ActionBar-divider"
21
+ }
22
+ end
23
+
24
+ def call
25
+ render(Primer::BaseComponent.new(**@system_arguments)) { content }
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nocov:
4
+
5
+ module Primer
6
+ module Alpha
7
+ class ActionBar
8
+ # ActionBar::Item is an internal component that wraps the items in a div with the `ActionBar-item` class.
9
+ class Item < Primer::Component
10
+ def initialize
11
+ @system_arguments = {
12
+ tag: :div,
13
+ data: {
14
+ targets: "action-bar.items"
15
+ },
16
+ classes: "ActionBar-item"
17
+ }
18
+ end
19
+
20
+ def call
21
+ render(Primer::BaseComponent.new(**@system_arguments)) { content }
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1 @@
1
+ .ActionBar{display:flex!important;flex-grow:1;flex-shrink:1;justify-content:flex-end;min-width:calc(var(--control-medium-size,2rem)*3);overflow:hidden;position:relative}.ActionBar,.ActionBar-item-container{align-items:center;box-sizing:initial}.ActionBar-item-container{display:flex;flex-grow:0;flex-shrink:0}.ActionBar-item{flex-shrink:0;position:relative}.ActionBar-more-menu{flex-shrink:0}.ActionBar--small{min-width:calc(var(--control-small-size,1.75rem)*3)}.ActionBar--large{min-width:calc(var(--control-large-size,2.5rem)*3)}.ActionBar-divider{border-left:var(--borderWidth-thin,max(1px,.0625rem)) solid var(--color-border-subtle);height:calc(var(--control-medium-size,2rem)/2);margin:0 var(--controlStack-medium-gap-condensed,.5rem)}.ActionBar--small .ActionBar-divider{margin:0 var(--controlStack-small-gap-condensed,.5rem)}.ActionBar--large .ActionBar-divider{margin:0 var(--controlStack-large-gap-condensed,.5rem)}@media (pointer:coarse){.ActionBar .ActionBar-item-container{gap:calc(var(--control-minTarget-coarse,2.75rem) - var(--control-medium-size,2rem))}.ActionBar--small .ActionBar-item-container{gap:calc(var(--control-minTarget-coarse,2.75rem) - var(--control-small-size,1.75rem))}.ActionBar--large .ActionBar-item-container{gap:calc(var(--control-minTarget-coarse,2.75rem) - var(--control-large-size,2.5rem))}}
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "alpha/action_bar",
3
+ "selectors": [
4
+ ".ActionBar",
5
+ ".ActionBar-item-container",
6
+ ".ActionBar-item",
7
+ ".ActionBar-more-menu",
8
+ ".ActionBar--small",
9
+ ".ActionBar--large",
10
+ ".ActionBar-divider",
11
+ ".ActionBar--small .ActionBar-divider",
12
+ ".ActionBar--large .ActionBar-divider",
13
+ ".ActionBar .ActionBar-item-container",
14
+ ".ActionBar--small .ActionBar-item-container",
15
+ ".ActionBar--large .ActionBar-item-container"
16
+ ]
17
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["action_bar.pcss"],"names":[],"mappings":"AACA,WAEE,sBAAwB,CAGxB,WAAY,CACZ,aAAc,CAGd,wBAAyB,CANzB,iDAA+C,CAK/C,eAAgB,CAPhB,iBASF,CAEA,qCARE,kBAAmB,CAGnB,kBAWF,CANA,0BACE,YAAa,CAIb,WAAY,CADZ,aAEF,CAEA,gBAEE,aAAc,CADd,iBAEF,CAEA,qBACE,aACF,CAEA,kBACE,mDACF,CAEA,kBACE,kDACF,CAIA,mBAGE,sFAAqE,CAFrE,8CAA4C,CAC5C,uDAEF,CAEA,qCACE,sDACF,CAEA,qCACE,sDACF,CAIA,wBACE,qCACE,mFACF,CAEA,4CACE,qFACF,CAEA,4CACE,oFACF,CACF","file":"action_bar.css","sourcesContent":["/* CSS for ActionBar */\n.ActionBar {\n position: relative;\n display: flex !important;\n min-width: calc(var(--control-medium-size) * 3); \n align-items: center;\n flex-grow: 1;\n flex-shrink: 1;\n box-sizing: content-box;\n overflow: hidden;\n justify-content: flex-end;\n}\n\n.ActionBar-item-container {\n display: flex;\n box-sizing: content-box;\n align-items: center;\n flex-shrink: 0;\n flex-grow: 0;\n}\n\n.ActionBar-item {\n position: relative;\n flex-shrink: 0;\n}\n\n.ActionBar-more-menu {\n flex-shrink: 0;\n}\n\n.ActionBar--small {\n min-width: calc(var(--control-small-size) * 3);\n}\n\n.ActionBar--large {\n min-width: calc(var(--control-large-size) * 3);\n}\n\n/* Divider */\n\n.ActionBar-divider {\n height: calc(var(--control-medium-size) / 2);\n margin: 0 var(--controlStack-medium-gap-condensed);\n border-left: var(--borderWidth-thin) solid var(--color-border-subtle);\n}\n\n.ActionBar--small .ActionBar-divider {\n margin: 0 var(--controlStack-small-gap-condensed);\n}\n\n.ActionBar--large .ActionBar-divider {\n margin: 0 var(--controlStack-large-gap-condensed);\n}\n\n/* Increase spacing so touch targets don't overlap */\n\n@media (pointer: coarse) {\n .ActionBar .ActionBar-item-container {\n gap: calc(var(--control-minTarget-coarse) - var(--control-medium-size)); /* 12px */\n }\n\n .ActionBar--small .ActionBar-item-container {\n gap: calc(var(--control-minTarget-coarse) - var(--control-small-size)); /* 16px */\n }\n\n .ActionBar--large .ActionBar-item-container {\n gap: calc(var(--control-minTarget-coarse) - var(--control-large-size)); /* 4px */\n }\n}\n"]}
@@ -0,0 +1,12 @@
1
+ <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
+ <%= render Primer::BaseComponent.new(tag: :div, classes: "ActionBar-item-container", "data-target": "action-bar.itemContainer") do %>
3
+ <% items.each do |item| %>
4
+ <%= item %>
5
+ <% end %>
6
+ <% end %>
7
+ <% if render_overflow_menu? %>
8
+ <%= render(@action_menu) do |menu| %>
9
+ <% menu.with_show_button(icon: :"kebab-horizontal", "aria-label": "Menu", size: @size, scheme: :invisible) %>
10
+ <% end %>
11
+ <% end %>
12
+ <% end %>
@@ -0,0 +1,69 @@
1
+ /* CSS for ActionBar */
2
+ .ActionBar {
3
+ position: relative;
4
+ display: flex !important;
5
+ min-width: calc(var(--control-medium-size) * 3);
6
+ align-items: center;
7
+ flex-grow: 1;
8
+ flex-shrink: 1;
9
+ box-sizing: content-box;
10
+ overflow: hidden;
11
+ justify-content: flex-end;
12
+ }
13
+
14
+ .ActionBar-item-container {
15
+ display: flex;
16
+ box-sizing: content-box;
17
+ align-items: center;
18
+ flex-shrink: 0;
19
+ flex-grow: 0;
20
+ }
21
+
22
+ .ActionBar-item {
23
+ position: relative;
24
+ flex-shrink: 0;
25
+ }
26
+
27
+ .ActionBar-more-menu {
28
+ flex-shrink: 0;
29
+ }
30
+
31
+ .ActionBar--small {
32
+ min-width: calc(var(--control-small-size) * 3);
33
+ }
34
+
35
+ .ActionBar--large {
36
+ min-width: calc(var(--control-large-size) * 3);
37
+ }
38
+
39
+ /* Divider */
40
+
41
+ .ActionBar-divider {
42
+ height: calc(var(--control-medium-size) / 2);
43
+ margin: 0 var(--controlStack-medium-gap-condensed);
44
+ border-left: var(--borderWidth-thin) solid var(--color-border-subtle);
45
+ }
46
+
47
+ .ActionBar--small .ActionBar-divider {
48
+ margin: 0 var(--controlStack-small-gap-condensed);
49
+ }
50
+
51
+ .ActionBar--large .ActionBar-divider {
52
+ margin: 0 var(--controlStack-large-gap-condensed);
53
+ }
54
+
55
+ /* Increase spacing so touch targets don't overlap */
56
+
57
+ @media (pointer: coarse) {
58
+ .ActionBar .ActionBar-item-container {
59
+ gap: calc(var(--control-minTarget-coarse) - var(--control-medium-size)); /* 12px */
60
+ }
61
+
62
+ .ActionBar--small .ActionBar-item-container {
63
+ gap: calc(var(--control-minTarget-coarse) - var(--control-small-size)); /* 16px */
64
+ }
65
+
66
+ .ActionBar--large .ActionBar-item-container {
67
+ gap: calc(var(--control-minTarget-coarse) - var(--control-large-size)); /* 4px */
68
+ }
69
+ }
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module Alpha
5
+ # Add a general description of component here
6
+ # Add additional usage considerations or best practices that may aid the user to use the component correctly.
7
+ # @accessibility Add any accessibility considerations
8
+ class ActionBar < Primer::Component
9
+ status :alpha
10
+
11
+ DEFAULT_SIZE = :medium
12
+ SIZE_MAPPINGS = {
13
+ DEFAULT_SIZE => nil,
14
+ :small => "ActionBar--small",
15
+ :large => "ActionBar--large"
16
+ }.freeze
17
+ SIZE_OPTIONS = SIZE_MAPPINGS.keys.freeze
18
+
19
+ renders_many :items, types: {
20
+ icon_button: lambda { |icon:, label:, **system_arguments|
21
+ item_id = self.class.generate_id
22
+
23
+ with_menu_item(id: item_id, label: label) do |c|
24
+ c.with_leading_visual_icon(icon: icon)
25
+ end
26
+
27
+ render(Item.new) do
28
+ render(Primer::Beta::IconButton.new(id: item_id, icon: icon, "aria-label": label, size: @size, scheme: :invisible, **system_arguments))
29
+ end
30
+ },
31
+ divider: lambda {
32
+ @action_menu.with_divider(hidden: true) if @overflow_menu
33
+ Divider.new
34
+ }
35
+ }
36
+
37
+ # @example Default
38
+ #
39
+ # <%= render(Primer::Alpha::ActionBar.new) do |component| %>
40
+ # <% component.with_item_icon_button(icon: :search, label: "Search")
41
+ # <% component.with_item_icon_button(icon: :pencil, label: "Edit") %>
42
+ # <% end %>
43
+ #
44
+ # @param size [Symbol] <%= one_of(Primer::Alpha::ActionBar::SIZE_OPTIONS) %>
45
+ # @param overflow_menu [Boolean] Whether to render the overflow menu.
46
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
47
+ def initialize(size: Primer::Alpha::ActionBar::DEFAULT_SIZE, overflow_menu: true, **system_arguments)
48
+ @system_arguments = system_arguments
49
+ @overflow_menu = overflow_menu
50
+
51
+ @size = fetch_or_fallback(Primer::Alpha::ActionBar::SIZE_OPTIONS, size, Primer::Alpha::ActionBar::DEFAULT_SIZE)
52
+
53
+ @system_arguments[:classes] = class_names(
54
+ system_arguments[:classes],
55
+ "ActionBar",
56
+ SIZE_MAPPINGS[@size]
57
+ )
58
+ @system_arguments[:role] = "toolbar"
59
+
60
+ return unless overflow_menu
61
+
62
+ @action_menu = Primer::Alpha::ActionMenu.new(
63
+ menu_id: self.class.generate_id,
64
+ "data-target": "action-bar.moreMenu",
65
+ hidden: true,
66
+ classes: "ActionBar-more-menu",
67
+ anchor_align: :end
68
+ )
69
+ end
70
+
71
+ private
72
+
73
+ def with_menu_item(id:, **system_arguments, &block)
74
+ return unless @overflow_menu
75
+
76
+ system_arguments = {
77
+ **system_arguments,
78
+ hidden: true,
79
+ tag: :button,
80
+ type: "button",
81
+ "data-for": id,
82
+ "data-action": "click:action-bar#menuItemClick"
83
+ }
84
+
85
+ @action_menu.with_item(
86
+ value: "",
87
+ **system_arguments,
88
+ &block
89
+ )
90
+ end
91
+
92
+ def render?
93
+ items.any?
94
+ end
95
+
96
+ def render_overflow_menu?
97
+ @overflow_menu && items.count > 3
98
+ end
99
+
100
+ def before_render
101
+ @system_arguments[:tag] = render_overflow_menu? ? :"action-bar" : :div
102
+ @system_arguments[:classes] = class_names(
103
+ @system_arguments[:classes],
104
+ "overflow-visible": !render_overflow_menu?
105
+ )
106
+ content
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,16 @@
1
+ declare class ActionBarElement extends HTMLElement {
2
+ #private;
3
+ items: HTMLElement[];
4
+ itemContainer: HTMLElement;
5
+ moreMenu: HTMLElement;
6
+ connectedCallback(): void;
7
+ disconnectedCallback(): void;
8
+ menuItemClick(event: Event): void;
9
+ update(rect?: DOMRect): void;
10
+ }
11
+ declare global {
12
+ interface Window {
13
+ ActionBarElement: typeof ActionBarElement;
14
+ }
15
+ }
16
+ export {};
@@ -0,0 +1,172 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
8
+ if (kind === "m") throw new TypeError("Private method is not writable");
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
10
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
11
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
12
+ };
13
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
14
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
15
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
16
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
17
+ };
18
+ var _ActionBarElement_instances, _ActionBarElement_initialBarWidth, _ActionBarElement_previousBarWidth, _ActionBarElement_focusZoneAbortController, _ActionBarElement_itemGap, _ActionBarElement_availableSpace, _ActionBarElement_menuSpace, _ActionBarElement_shrink, _ActionBarElement_grow, _ActionBarElement_showItem, _ActionBarElement_hideItem, _ActionBarElement_menuItems_get;
19
+ import { controller, targets, target } from '@github/catalyst';
20
+ import { focusZone, FocusKeys } from '@primer/behaviors';
21
+ const instersectionObserver = new IntersectionObserver(entries => {
22
+ for (const entry of entries) {
23
+ const action = entry.target;
24
+ if (entry.isIntersecting && action instanceof ActionBarElement) {
25
+ action.update();
26
+ }
27
+ }
28
+ });
29
+ const resizeObserver = new ResizeObserver(entries => {
30
+ for (const entry of entries) {
31
+ const action = entry.target;
32
+ if (action instanceof ActionBarElement) {
33
+ action.update(entry.contentRect);
34
+ }
35
+ }
36
+ });
37
+ let ActionBarElement = class ActionBarElement extends HTMLElement {
38
+ constructor() {
39
+ super(...arguments);
40
+ _ActionBarElement_instances.add(this);
41
+ _ActionBarElement_initialBarWidth.set(this, void 0);
42
+ _ActionBarElement_previousBarWidth.set(this, void 0);
43
+ _ActionBarElement_focusZoneAbortController.set(this, null);
44
+ }
45
+ connectedCallback() {
46
+ var _a, _b, _c, _d;
47
+ __classPrivateFieldSet(this, _ActionBarElement_previousBarWidth, (_a = this.offsetWidth) !== null && _a !== void 0 ? _a : Infinity, "f");
48
+ __classPrivateFieldSet(this, _ActionBarElement_initialBarWidth, (_b = this.itemContainer.offsetWidth) !== null && _b !== void 0 ? _b : Infinity, "f");
49
+ // Calculate the width of all the items before hiding anything
50
+ for (const item of this.items) {
51
+ const width = item.getBoundingClientRect().width;
52
+ const marginLeft = parseInt((_c = window.getComputedStyle(item)) === null || _c === void 0 ? void 0 : _c.marginLeft, 10);
53
+ const marginRight = parseInt((_d = window.getComputedStyle(item)) === null || _d === void 0 ? void 0 : _d.marginRight, 10);
54
+ item.setAttribute('data-offset-width', `${width + marginLeft + marginRight}`);
55
+ }
56
+ resizeObserver.observe(this);
57
+ instersectionObserver.observe(this);
58
+ setTimeout(() => {
59
+ this.style.overflow = 'visible';
60
+ this.update();
61
+ }, 20); // Wait for the items to be rendered, making this really short to avoid a flash of unstyled content
62
+ }
63
+ disconnectedCallback() {
64
+ resizeObserver.unobserve(this);
65
+ instersectionObserver.unobserve(this);
66
+ }
67
+ menuItemClick(event) {
68
+ var _a;
69
+ const currentTarget = event.currentTarget;
70
+ const id = currentTarget === null || currentTarget === void 0 ? void 0 : currentTarget.getAttribute('data-for');
71
+ if (id) {
72
+ (_a = document.getElementById(id)) === null || _a === void 0 ? void 0 : _a.click();
73
+ }
74
+ }
75
+ update(rect = this.getBoundingClientRect()) {
76
+ // Only recalculate if the bar width changed
77
+ if (rect.width <= __classPrivateFieldGet(this, _ActionBarElement_previousBarWidth, "f") || __classPrivateFieldGet(this, _ActionBarElement_previousBarWidth, "f") === 0) {
78
+ __classPrivateFieldGet(this, _ActionBarElement_instances, "m", _ActionBarElement_shrink).call(this);
79
+ }
80
+ else if (rect.width > __classPrivateFieldGet(this, _ActionBarElement_previousBarWidth, "f")) {
81
+ __classPrivateFieldGet(this, _ActionBarElement_instances, "m", _ActionBarElement_grow).call(this);
82
+ }
83
+ __classPrivateFieldSet(this, _ActionBarElement_previousBarWidth, rect.width, "f");
84
+ if (rect.width <= __classPrivateFieldGet(this, _ActionBarElement_initialBarWidth, "f")) {
85
+ this.style.justifyContent = 'space-between';
86
+ }
87
+ else {
88
+ this.style.justifyContent = 'flex-end';
89
+ }
90
+ if (__classPrivateFieldGet(this, _ActionBarElement_focusZoneAbortController, "f")) {
91
+ __classPrivateFieldGet(this, _ActionBarElement_focusZoneAbortController, "f").abort();
92
+ }
93
+ __classPrivateFieldSet(this, _ActionBarElement_focusZoneAbortController, focusZone(this.itemContainer, {
94
+ bindKeys: FocusKeys.ArrowHorizontal | FocusKeys.HomeAndEnd,
95
+ focusOutBehavior: 'wrap',
96
+ focusableElementFilter: element => {
97
+ return !element.closest('.ActionBar-item[hidden]');
98
+ }
99
+ }), "f");
100
+ }
101
+ };
102
+ _ActionBarElement_initialBarWidth = new WeakMap(), _ActionBarElement_previousBarWidth = new WeakMap(), _ActionBarElement_focusZoneAbortController = new WeakMap(), _ActionBarElement_instances = new WeakSet(), _ActionBarElement_itemGap = function _ActionBarElement_itemGap() {
103
+ var _a;
104
+ return parseInt((_a = window.getComputedStyle(this.itemContainer)) === null || _a === void 0 ? void 0 : _a.columnGap, 10) || 0;
105
+ }, _ActionBarElement_availableSpace = function _ActionBarElement_availableSpace() {
106
+ // Get the offset of the item container from the container edge
107
+ return this.offsetWidth - this.itemContainer.offsetWidth;
108
+ }, _ActionBarElement_menuSpace = function _ActionBarElement_menuSpace() {
109
+ if (this.moreMenu.hidden) {
110
+ return 0;
111
+ }
112
+ return this.moreMenu.offsetWidth + __classPrivateFieldGet(this, _ActionBarElement_instances, "m", _ActionBarElement_itemGap).call(this);
113
+ }, _ActionBarElement_shrink = function _ActionBarElement_shrink() {
114
+ if (this.items[0].hidden) {
115
+ return;
116
+ }
117
+ let index = this.items.length - 1;
118
+ for (const item of this.items.reverse()) {
119
+ if (!item.hidden && __classPrivateFieldGet(this, _ActionBarElement_instances, "m", _ActionBarElement_availableSpace).call(this) < __classPrivateFieldGet(this, _ActionBarElement_instances, "m", _ActionBarElement_menuSpace).call(this)) {
120
+ __classPrivateFieldGet(this, _ActionBarElement_instances, "m", _ActionBarElement_hideItem).call(this, index);
121
+ }
122
+ else if (__classPrivateFieldGet(this, _ActionBarElement_instances, "m", _ActionBarElement_availableSpace).call(this) >= __classPrivateFieldGet(this, _ActionBarElement_instances, "m", _ActionBarElement_menuSpace).call(this)) {
123
+ return;
124
+ }
125
+ index--;
126
+ }
127
+ }, _ActionBarElement_grow = function _ActionBarElement_grow() {
128
+ // If last item is visible, there is no need to grow
129
+ if (!this.items[this.items.length - 1].hidden) {
130
+ return;
131
+ }
132
+ let index = 0;
133
+ for (const item of this.items) {
134
+ if (item.hidden) {
135
+ const offsetWidth = Number(item.getAttribute('data-offset-width'));
136
+ if (__classPrivateFieldGet(this, _ActionBarElement_instances, "m", _ActionBarElement_availableSpace).call(this) >= __classPrivateFieldGet(this, _ActionBarElement_instances, "m", _ActionBarElement_menuSpace).call(this) + offsetWidth || index === this.items.length - 1) {
137
+ __classPrivateFieldGet(this, _ActionBarElement_instances, "m", _ActionBarElement_showItem).call(this, index);
138
+ }
139
+ else {
140
+ return;
141
+ }
142
+ }
143
+ index++;
144
+ }
145
+ if (!this.items[this.items.length - 1].hidden) {
146
+ this.moreMenu.hidden = true;
147
+ }
148
+ }, _ActionBarElement_showItem = function _ActionBarElement_showItem(index) {
149
+ this.items[index].hidden = false;
150
+ __classPrivateFieldGet(this, _ActionBarElement_instances, "a", _ActionBarElement_menuItems_get)[index].hidden = true;
151
+ }, _ActionBarElement_hideItem = function _ActionBarElement_hideItem(index) {
152
+ this.items[index].hidden = true;
153
+ __classPrivateFieldGet(this, _ActionBarElement_instances, "a", _ActionBarElement_menuItems_get)[index].hidden = false;
154
+ if (this.moreMenu.hidden) {
155
+ this.moreMenu.hidden = false;
156
+ }
157
+ }, _ActionBarElement_menuItems_get = function _ActionBarElement_menuItems_get() {
158
+ return this.moreMenu.querySelectorAll('[role="menu"] > li');
159
+ };
160
+ __decorate([
161
+ targets
162
+ ], ActionBarElement.prototype, "items", void 0);
163
+ __decorate([
164
+ target
165
+ ], ActionBarElement.prototype, "itemContainer", void 0);
166
+ __decorate([
167
+ target
168
+ ], ActionBarElement.prototype, "moreMenu", void 0);
169
+ ActionBarElement = __decorate([
170
+ controller
171
+ ], ActionBarElement);
172
+ window.ActionBarElement = ActionBarElement;
@@ -0,0 +1,175 @@
1
+ import {controller, targets, target} from '@github/catalyst'
2
+ import {focusZone, FocusKeys} from '@primer/behaviors'
3
+
4
+ const instersectionObserver = new IntersectionObserver(entries => {
5
+ for (const entry of entries) {
6
+ const action = entry.target
7
+ if (entry.isIntersecting && action instanceof ActionBarElement) {
8
+ action.update()
9
+ }
10
+ }
11
+ })
12
+
13
+ const resizeObserver = new ResizeObserver(entries => {
14
+ for (const entry of entries) {
15
+ const action = entry.target
16
+ if (action instanceof ActionBarElement) {
17
+ action.update(entry.contentRect)
18
+ }
19
+ }
20
+ })
21
+
22
+ @controller
23
+ class ActionBarElement extends HTMLElement {
24
+ @targets items: HTMLElement[]
25
+ @target itemContainer: HTMLElement
26
+ @target moreMenu: HTMLElement
27
+
28
+ #initialBarWidth: number
29
+ #previousBarWidth: number
30
+ #focusZoneAbortController: AbortController | null = null
31
+
32
+ connectedCallback() {
33
+ this.#previousBarWidth = this.offsetWidth ?? Infinity
34
+ this.#initialBarWidth = this.itemContainer.offsetWidth ?? Infinity
35
+
36
+ // Calculate the width of all the items before hiding anything
37
+ for (const item of this.items) {
38
+ const width = item.getBoundingClientRect().width
39
+ const marginLeft = parseInt(window.getComputedStyle(item)?.marginLeft, 10)
40
+ const marginRight = parseInt(window.getComputedStyle(item)?.marginRight, 10)
41
+ item.setAttribute('data-offset-width', `${width + marginLeft + marginRight}`)
42
+ }
43
+
44
+ resizeObserver.observe(this)
45
+ instersectionObserver.observe(this)
46
+
47
+ setTimeout(() => {
48
+ this.style.overflow = 'visible'
49
+ this.update()
50
+ }, 20) // Wait for the items to be rendered, making this really short to avoid a flash of unstyled content
51
+ }
52
+
53
+ disconnectedCallback() {
54
+ resizeObserver.unobserve(this)
55
+ instersectionObserver.unobserve(this)
56
+ }
57
+
58
+ menuItemClick(event: Event) {
59
+ const currentTarget = event.currentTarget as HTMLButtonElement
60
+
61
+ const id = currentTarget?.getAttribute('data-for')
62
+
63
+ if (id) {
64
+ document.getElementById(id)?.click()
65
+ }
66
+ }
67
+
68
+ update(rect: DOMRect = this.getBoundingClientRect()) {
69
+ // Only recalculate if the bar width changed
70
+ if (rect.width <= this.#previousBarWidth || this.#previousBarWidth === 0) {
71
+ this.#shrink()
72
+ } else if (rect.width > this.#previousBarWidth) {
73
+ this.#grow()
74
+ }
75
+ this.#previousBarWidth = rect.width
76
+
77
+ if (rect.width <= this.#initialBarWidth) {
78
+ this.style.justifyContent = 'space-between'
79
+ } else {
80
+ this.style.justifyContent = 'flex-end'
81
+ }
82
+ if (this.#focusZoneAbortController) {
83
+ this.#focusZoneAbortController.abort()
84
+ }
85
+ this.#focusZoneAbortController = focusZone(this.itemContainer, {
86
+ bindKeys: FocusKeys.ArrowHorizontal | FocusKeys.HomeAndEnd,
87
+ focusOutBehavior: 'wrap',
88
+ focusableElementFilter: element => {
89
+ return !element.closest('.ActionBar-item[hidden]')
90
+ }
91
+ })
92
+ }
93
+
94
+ #itemGap(): number {
95
+ return parseInt(window.getComputedStyle(this.itemContainer)?.columnGap, 10) || 0
96
+ }
97
+
98
+ #availableSpace(): number {
99
+ // Get the offset of the item container from the container edge
100
+ return this.offsetWidth - this.itemContainer.offsetWidth
101
+ }
102
+
103
+ #menuSpace(): number {
104
+ if (this.moreMenu.hidden) {
105
+ return 0
106
+ }
107
+ return this.moreMenu.offsetWidth + this.#itemGap()
108
+ }
109
+
110
+ #shrink() {
111
+ if (this.items[0]!.hidden) {
112
+ return
113
+ }
114
+
115
+ let index = this.items.length - 1
116
+ for (const item of this.items.reverse()) {
117
+ if (!item.hidden && this.#availableSpace() < this.#menuSpace()) {
118
+ this.#hideItem(index)
119
+ } else if (this.#availableSpace() >= this.#menuSpace()) {
120
+ return
121
+ }
122
+ index--
123
+ }
124
+ }
125
+
126
+ #grow() {
127
+ // If last item is visible, there is no need to grow
128
+ if (!this.items[this.items.length - 1]!.hidden) {
129
+ return
130
+ }
131
+ let index = 0
132
+ for (const item of this.items) {
133
+ if (item.hidden) {
134
+ const offsetWidth = Number(item.getAttribute('data-offset-width'))
135
+
136
+ if (this.#availableSpace() >= this.#menuSpace() + offsetWidth || index === this.items.length - 1) {
137
+ this.#showItem(index)
138
+ } else {
139
+ return
140
+ }
141
+ }
142
+ index++
143
+ }
144
+
145
+ if (!this.items[this.items.length - 1]!.hidden) {
146
+ this.moreMenu.hidden = true
147
+ }
148
+ }
149
+
150
+ #showItem(index: number) {
151
+ this.items[index]!.hidden = false
152
+ this.#menuItems[index]!.hidden = true
153
+ }
154
+
155
+ #hideItem(index: number) {
156
+ this.items[index]!.hidden = true
157
+ this.#menuItems[index]!.hidden = false
158
+
159
+ if (this.moreMenu.hidden) {
160
+ this.moreMenu.hidden = false
161
+ }
162
+ }
163
+
164
+ get #menuItems(): NodeListOf<HTMLElement> {
165
+ return this.moreMenu.querySelectorAll('[role="menu"] > li')
166
+ }
167
+ }
168
+
169
+ declare global {
170
+ interface Window {
171
+ ActionBarElement: typeof ActionBarElement
172
+ }
173
+ }
174
+
175
+ window.ActionBarElement = ActionBarElement
@@ -1,6 +1,6 @@
1
1
  import IncludeFragmentElement from '@github/include-fragment-element';
2
- declare type SelectVariant = 'none' | 'single' | 'multiple' | null;
3
- declare type SelectedItem = {
2
+ type SelectVariant = 'none' | 'single' | 'multiple' | null;
3
+ type SelectedItem = {
4
4
  label: string | null | undefined;
5
5
  value: string | null | undefined;
6
6
  element: Element;
@@ -1,4 +1,5 @@
1
- declare type Direction = 'n' | 's' | 'e' | 'w' | 'ne' | 'se' | 'nw' | 'sw';
1
+ import '@oddbird/popover-polyfill';
2
+ type Direction = 'n' | 's' | 'e' | 'w' | 'ne' | 'se' | 'nw' | 'sw';
2
3
  declare class ToolTipElement extends HTMLElement {
3
4
  #private;
4
5
  styles(): string;
@@ -13,7 +14,7 @@ declare class ToolTipElement extends HTMLElement {
13
14
  get hiddenFromView(): true | false;
14
15
  connectedCallback(): void;
15
16
  disconnectedCallback(): void;
16
- handleEvent(event: Event): void;
17
+ handleEvent(event: Event): Promise<void>;
17
18
  static observedAttributes: string[];
18
19
  attributeChangedCallback(name: string): void;
19
20
  }