primer_view_components 0.3.1 → 0.4.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 (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
  }