openproject-primer_view_components 0.12.1 → 0.13.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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -0
  3. data/app/assets/javascripts/app/components/primer/alpha/tool_tip.d.ts +1 -0
  4. data/app/assets/javascripts/primer_view_components.js +1 -1
  5. data/app/assets/javascripts/primer_view_components.js.map +1 -1
  6. data/app/assets/styles/primer_view_components.css +1 -1
  7. data/app/assets/styles/primer_view_components.css.map +1 -1
  8. data/app/components/primer/alpha/action_bar/item.rb +7 -4
  9. data/app/components/primer/alpha/action_bar.rb +2 -2
  10. data/app/components/primer/alpha/action_bar_element.js +9 -4
  11. data/app/components/primer/alpha/action_bar_element.ts +9 -2
  12. data/app/components/primer/alpha/action_list/form_wrapper.html.erb +4 -2
  13. data/app/components/primer/alpha/action_list/form_wrapper.rb +20 -9
  14. data/app/components/primer/alpha/action_menu/action_menu_element.js +160 -85
  15. data/app/components/primer/alpha/action_menu/action_menu_element.ts +195 -81
  16. data/app/components/primer/alpha/action_menu/list.rb +0 -2
  17. data/app/components/primer/alpha/action_menu.rb +120 -3
  18. data/app/components/primer/alpha/modal_dialog.js +10 -13
  19. data/app/components/primer/alpha/modal_dialog.ts +10 -13
  20. data/app/components/primer/alpha/segmented_control/item.html.erb +1 -8
  21. data/app/components/primer/alpha/segmented_control/item.rb +38 -4
  22. data/app/components/primer/alpha/segmented_control.css +1 -1
  23. data/app/components/primer/alpha/segmented_control.css.json +14 -13
  24. data/app/components/primer/alpha/segmented_control.css.map +1 -1
  25. data/app/components/primer/alpha/segmented_control.pcss +75 -66
  26. data/app/components/primer/alpha/segmented_control.rb +10 -0
  27. data/app/components/primer/alpha/text_field.css +1 -1
  28. data/app/components/primer/alpha/tool_tip.d.ts +1 -0
  29. data/app/components/primer/alpha/tool_tip.js +26 -93
  30. data/app/components/primer/alpha/tool_tip.ts +25 -91
  31. data/app/components/primer/beta/base_button.rb +4 -0
  32. data/app/components/primer/beta/button.css +1 -1
  33. data/app/components/primer/beta/button.css.map +1 -1
  34. data/app/components/primer/beta/button.pcss +6 -2
  35. data/app/components/primer/focus_group.js +28 -3
  36. data/app/components/primer/focus_group.ts +27 -1
  37. data/lib/primer/accessibility.rb +3 -1
  38. data/lib/primer/static/generate_info_arch.rb +86 -5
  39. data/lib/primer/view_components/version.rb +2 -2
  40. data/previews/primer/alpha/action_menu_preview/single_select_form_items.html.erb +31 -0
  41. data/previews/primer/alpha/action_menu_preview/with_actions.html.erb +6 -5
  42. data/previews/primer/alpha/action_menu_preview.rb +10 -1
  43. data/previews/primer/alpha/check_box_preview.rb +1 -0
  44. data/previews/primer/alpha/dialog_preview/autofocus_element.html.erb +8 -0
  45. data/previews/primer/alpha/dialog_preview.rb +5 -0
  46. data/previews/primer/alpha/radio_button_preview.rb +1 -0
  47. data/previews/primer/alpha/segmented_control_preview.rb +35 -0
  48. data/previews/primer/alpha/tooltip_preview/tooltip_with_dialog_moving_focus_to_input.html.erb +23 -0
  49. data/previews/primer/alpha/tooltip_preview.rb +6 -1
  50. data/previews/primer/beta/button_group_preview.rb +6 -6
  51. data/previews/primer/beta/button_preview.rb +20 -2
  52. data/previews/primer/beta/icon_button_preview.rb +3 -0
  53. data/static/arguments.json +18 -1
  54. data/static/classes.json +12 -0
  55. data/static/constants.json +12 -1
  56. data/static/info_arch.json +137 -161
  57. data/static/previews.json +91 -172
  58. metadata +5 -310
@@ -7,14 +7,17 @@ module Primer
7
7
  class ActionBar
8
8
  # ActionBar::Item is an internal component that wraps the items in a div with the `ActionBar-item` class.
9
9
  class Item < Primer::Component
10
- def initialize(item_content)
10
+ # @param item_content [String] The content to render inside the item.
11
+ # @param item_arguments [Hash] <%= link_to_system_arguments_docs %>
12
+ def initialize(item_content, **item_arguments)
11
13
  @system_arguments = {
12
- tag: :div,
14
+ tag: item_arguments[:tag] || :div,
13
15
  data: {
14
16
  targets: "action-bar.items"
15
- },
16
- classes: "ActionBar-item"
17
+ }.merge(item_arguments[:data] || {}),
18
+ classes: class_names("ActionBar-item", item_arguments[:classes])
17
19
  }
20
+
18
21
  @item_content = item_content
19
22
  end
20
23
 
@@ -16,14 +16,14 @@ module Primer
16
16
  SIZE_OPTIONS = SIZE_MAPPINGS.keys.freeze
17
17
 
18
18
  renders_many :items, types: {
19
- icon_button: lambda { |icon:, label:, **system_arguments|
19
+ icon_button: lambda { |icon:, label:, item_arguments: {}, **system_arguments|
20
20
  item_id = self.class.generate_id
21
21
 
22
22
  with_menu_item(id: item_id, label: label) do |c|
23
23
  c.with_leading_visual_icon(icon: icon)
24
24
  end
25
25
 
26
- Item.new(Primer::Beta::IconButton.new(id: item_id, icon: icon, "aria-label": label, size: @size, scheme: :invisible, **system_arguments))
26
+ Item.new(Primer::Beta::IconButton.new(id: item_id, icon: icon, "aria-label": label, size: @size, scheme: :invisible, **system_arguments), **item_arguments)
27
27
  },
28
28
  divider: lambda {
29
29
  @action_menu.with_divider(hidden: true) if @overflow_menu
@@ -15,7 +15,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
15
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
16
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
17
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;
18
+ var _ActionBarElement_instances, _ActionBarElement_initialBarWidth, _ActionBarElement_previousBarWidth, _ActionBarElement_focusZoneAbortController, _ActionBarElement_isVisible, _ActionBarElement_itemGap, _ActionBarElement_availableSpace, _ActionBarElement_menuSpace, _ActionBarElement_shrink, _ActionBarElement_grow, _ActionBarElement_showItem, _ActionBarElement_hideItem, _ActionBarElement_menuItems_get;
19
19
  import { controller, targets, target } from '@github/catalyst';
20
20
  import { focusZone, FocusKeys } from '@primer/behaviors';
21
21
  const instersectionObserver = new IntersectionObserver(entries => {
@@ -90,16 +90,21 @@ let ActionBarElement = class ActionBarElement extends HTMLElement {
90
90
  if (__classPrivateFieldGet(this, _ActionBarElement_focusZoneAbortController, "f")) {
91
91
  __classPrivateFieldGet(this, _ActionBarElement_focusZoneAbortController, "f").abort();
92
92
  }
93
- __classPrivateFieldSet(this, _ActionBarElement_focusZoneAbortController, focusZone(this.itemContainer, {
93
+ __classPrivateFieldSet(this, _ActionBarElement_focusZoneAbortController, focusZone(this, {
94
94
  bindKeys: FocusKeys.ArrowHorizontal | FocusKeys.HomeAndEnd,
95
95
  focusOutBehavior: 'wrap',
96
96
  focusableElementFilter: element => {
97
- return !element.closest('.ActionBar-item[hidden]');
97
+ return __classPrivateFieldGet(this, _ActionBarElement_instances, "m", _ActionBarElement_isVisible).call(this, element);
98
98
  }
99
99
  }), "f");
100
100
  }
101
101
  };
102
- _ActionBarElement_initialBarWidth = new WeakMap(), _ActionBarElement_previousBarWidth = new WeakMap(), _ActionBarElement_focusZoneAbortController = new WeakMap(), _ActionBarElement_instances = new WeakSet(), _ActionBarElement_itemGap = function _ActionBarElement_itemGap() {
102
+ _ActionBarElement_initialBarWidth = new WeakMap(), _ActionBarElement_previousBarWidth = new WeakMap(), _ActionBarElement_focusZoneAbortController = new WeakMap(), _ActionBarElement_instances = new WeakSet(), _ActionBarElement_isVisible = function _ActionBarElement_isVisible(element) {
103
+ // Safari doesn't support `checkVisibility` yet.
104
+ if (typeof element.checkVisibility === 'function')
105
+ return element.checkVisibility();
106
+ return Boolean(element.offsetParent || element.offsetWidth || element.offsetHeight);
107
+ }, _ActionBarElement_itemGap = function _ActionBarElement_itemGap() {
103
108
  var _a;
104
109
  return parseInt((_a = window.getComputedStyle(this.itemContainer)) === null || _a === void 0 ? void 0 : _a.columnGap, 10) || 0;
105
110
  }, _ActionBarElement_availableSpace = function _ActionBarElement_availableSpace() {
@@ -82,15 +82,22 @@ class ActionBarElement extends HTMLElement {
82
82
  if (this.#focusZoneAbortController) {
83
83
  this.#focusZoneAbortController.abort()
84
84
  }
85
- this.#focusZoneAbortController = focusZone(this.itemContainer, {
85
+ this.#focusZoneAbortController = focusZone(this, {
86
86
  bindKeys: FocusKeys.ArrowHorizontal | FocusKeys.HomeAndEnd,
87
87
  focusOutBehavior: 'wrap',
88
88
  focusableElementFilter: element => {
89
- return !element.closest('.ActionBar-item[hidden]')
89
+ return this.#isVisible(element)
90
90
  }
91
91
  })
92
92
  }
93
93
 
94
+ #isVisible(element: HTMLElement): boolean {
95
+ // Safari doesn't support `checkVisibility` yet.
96
+ if (typeof element.checkVisibility === 'function') return element.checkVisibility()
97
+
98
+ return Boolean(element.offsetParent || element.offsetWidth || element.offsetHeight)
99
+ }
100
+
94
101
  #itemGap(): number {
95
102
  return parseInt(window.getComputedStyle(this.itemContainer)?.columnGap, 10) || 0
96
103
  }
@@ -1,7 +1,9 @@
1
1
  <% if form_required? %>
2
2
  <%= form_with(url: @action, method: @http_method, **@form_arguments) do %>
3
- <% if render_input? %>
4
- <%= render(Primer::BaseComponent.new(tag: :input, **@input_arguments)) %>
3
+ <% if render_inputs? %>
4
+ <% @inputs.each do |input_arguments| %>
5
+ <%= render(Primer::BaseComponent.new(tag: :input, **input_arguments)) %>
6
+ <% end %>
5
7
  <% end %>
6
8
  <%= content %>
7
9
  <% end %>
@@ -24,14 +24,25 @@ module Primer
24
24
 
25
25
  name = @form_arguments.delete(:name)
26
26
  value = @form_arguments.delete(:value) || name
27
+ inputs = @form_arguments.delete(:inputs) || []
27
28
 
28
- @input_arguments = {
29
- type: :hidden,
30
- name: name,
31
- value: value,
32
- data: { list_item_input: true },
33
- **(@form_arguments.delete(:input_arguments) || {})
34
- }
29
+ # For the older version of this component that only allowed you to
30
+ # specify a single input
31
+ if inputs.empty?
32
+ inputs << {
33
+ name: name,
34
+ value: value,
35
+ **(@form_arguments.delete(:input_arguments) || {})
36
+ }
37
+ end
38
+
39
+ @inputs = inputs.map do |input_data|
40
+ input_data = input_data.dup
41
+ input_data[:type] ||= :hidden
42
+ input_data[:data] ||= {}
43
+ input_data[:data][:list_item_input] = true
44
+ input_data
45
+ end
35
46
  end
36
47
 
37
48
  def get?
@@ -42,8 +53,8 @@ module Primer
42
53
  @action && !get?
43
54
  end
44
55
 
45
- def render_input?
46
- @input_arguments[:name].present?
56
+ def render_inputs?
57
+ @inputs.present?
47
58
  end
48
59
 
49
60
  private
@@ -15,7 +15,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
15
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
16
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
17
17
  };
18
- var _ActionMenuElement_instances, _ActionMenuElement_abortController, _ActionMenuElement_originalLabel, _ActionMenuElement_inputName, _ActionMenuElement_setDynamicLabel, _ActionMenuElement_updateInput, _ActionMenuElement_isActivationKeydown, _ActionMenuElement_firstItem_get;
18
+ var _ActionMenuElement_instances, _ActionMenuElement_abortController, _ActionMenuElement_originalLabel, _ActionMenuElement_inputName, _ActionMenuElement_invokerBeingClicked, _ActionMenuElement_softDisableItems, _ActionMenuElement_potentiallyDisallowActivation, _ActionMenuElement_isKeyboardActivation, _ActionMenuElement_isMouseActivation, _ActionMenuElement_isActivation, _ActionMenuElement_handleInvokerActivated, _ActionMenuElement_handleDialogItemActivated, _ActionMenuElement_handleItemActivated, _ActionMenuElement_activateItem, _ActionMenuElement_handleIncludeFragmentReplaced, _ActionMenuElement_handleFocusOut, _ActionMenuElement_show, _ActionMenuElement_hide, _ActionMenuElement_isOpen, _ActionMenuElement_setDynamicLabel, _ActionMenuElement_updateInput, _ActionMenuElement_firstItem_get, _ActionMenuElement_items_get;
19
19
  import { controller, target } from '@github/catalyst';
20
20
  import '@oddbird/popover-polyfill';
21
21
  const validSelectors = ['[role="menuitem"]', '[role="menuitemcheckbox"]', '[role="menuitemradio"]'];
@@ -27,6 +27,7 @@ let ActionMenuElement = class ActionMenuElement extends HTMLElement {
27
27
  _ActionMenuElement_abortController.set(this, void 0);
28
28
  _ActionMenuElement_originalLabel.set(this, '');
29
29
  _ActionMenuElement_inputName.set(this, '');
30
+ _ActionMenuElement_invokerBeingClicked.set(this, false);
30
31
  }
31
32
  get selectVariant() {
32
33
  return this.getAttribute('data-select-variant');
@@ -94,8 +95,10 @@ let ActionMenuElement = class ActionMenuElement extends HTMLElement {
94
95
  this.addEventListener('click', this, { signal });
95
96
  this.addEventListener('mouseover', this, { signal });
96
97
  this.addEventListener('focusout', this, { signal });
98
+ this.addEventListener('mousedown', this, { signal });
97
99
  __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_setDynamicLabel).call(this);
98
100
  __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_updateInput).call(this);
101
+ __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_softDisableItems).call(this);
99
102
  if (this.includeFragment) {
100
103
  this.includeFragment.addEventListener('include-fragment-replaced', this, {
101
104
  signal
@@ -106,98 +109,173 @@ let ActionMenuElement = class ActionMenuElement extends HTMLElement {
106
109
  __classPrivateFieldGet(this, _ActionMenuElement_abortController, "f").abort();
107
110
  }
108
111
  handleEvent(event) {
109
- var _a, _b, _c, _d, _e;
110
- const activation = __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_isActivationKeydown).call(this, event);
111
- if (event.target === this.invokerElement && activation) {
112
- if (__classPrivateFieldGet(this, _ActionMenuElement_instances, "a", _ActionMenuElement_firstItem_get)) {
113
- event.preventDefault();
114
- (_a = this.popoverElement) === null || _a === void 0 ? void 0 : _a.showPopover();
115
- __classPrivateFieldGet(this, _ActionMenuElement_instances, "a", _ActionMenuElement_firstItem_get).focus();
116
- return;
117
- }
118
- }
119
- // Ignore events within dialogs within menus
120
- if (((_b = event.target) === null || _b === void 0 ? void 0 : _b.closest('dialog')) || ((_c = event.target) === null || _c === void 0 ? void 0 : _c.closest('modal-dialog'))) {
112
+ var _a;
113
+ const targetIsInvoker = (_a = this.invokerElement) === null || _a === void 0 ? void 0 : _a.contains(event.target);
114
+ const eventIsActivation = __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_isActivation).call(this, event);
115
+ if (targetIsInvoker && event.type === 'mousedown') {
116
+ __classPrivateFieldSet(this, _ActionMenuElement_invokerBeingClicked, true, "f");
121
117
  return;
122
118
  }
123
- // If a dialog has been rendered within the menu, we do not want to hide
124
- // the entire menu, as that will also hide the Dialog. Instead we want to
125
- // show the Dialog while hiding just the visible part of the menu.
126
- if ((activation || event.type === 'click') && ((_d = event.target) === null || _d === void 0 ? void 0 : _d.closest('[data-show-dialog-id]'))) {
127
- const dialogInvoker = event.target.closest('[data-show-dialog-id]');
128
- const dialog = this.ownerDocument.getElementById((dialogInvoker === null || dialogInvoker === void 0 ? void 0 : dialogInvoker.getAttribute('data-show-dialog-id')) || '');
129
- if (dialogInvoker && dialog && this.contains(dialogInvoker) && this.contains(dialog)) {
130
- this.querySelector('.ActionListWrap').style.display = 'none';
131
- const dialog_controller = new AbortController();
132
- const { signal } = dialog_controller;
133
- const handleDialogClose = () => {
134
- var _a, _b;
135
- dialog_controller.abort();
136
- this.querySelector('.ActionListWrap').style.display = '';
137
- if ((_a = this.popoverElement) === null || _a === void 0 ? void 0 : _a.matches(':popover-open')) {
138
- (_b = this.popoverElement) === null || _b === void 0 ? void 0 : _b.hidePopover();
139
- }
140
- };
141
- dialog.addEventListener('close', handleDialogClose, { signal });
142
- dialog.addEventListener('cancel', handleDialogClose, { signal });
143
- return;
144
- }
119
+ // Prevent safari bug that dismisses menu on mousedown instead of allowing
120
+ // the click event to propagate to the button
121
+ if (event.type === 'mousedown') {
122
+ event.preventDefault();
123
+ return;
145
124
  }
146
- if (!((_e = this.popoverElement) === null || _e === void 0 ? void 0 : _e.matches(':popover-open')))
125
+ if (targetIsInvoker && eventIsActivation) {
126
+ __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_handleInvokerActivated).call(this, event);
127
+ __classPrivateFieldSet(this, _ActionMenuElement_invokerBeingClicked, false, "f");
147
128
  return;
148
- if (event.type === 'include-fragment-replaced') {
149
- if (__classPrivateFieldGet(this, _ActionMenuElement_instances, "a", _ActionMenuElement_firstItem_get))
150
- __classPrivateFieldGet(this, _ActionMenuElement_instances, "a", _ActionMenuElement_firstItem_get).focus();
151
129
  }
152
- else if (activation || (event instanceof MouseEvent && event.type === 'click')) {
153
- // Hide popover after current event loop to prevent changes in focus from
154
- // altering the target of the event. Not doing this specifically affects
155
- // <a> tags. It causes the event to be sent to the currently focused element
156
- // instead of the anchor, which effectively prevents navigation, i.e. it
157
- // appears as if hitting enter does nothing. Curiously, clicking instead
158
- // works fine.
159
- if (this.selectVariant !== 'multiple') {
160
- setTimeout(() => {
161
- var _a, _b;
162
- if ((_a = this.popoverElement) === null || _a === void 0 ? void 0 : _a.matches(':popover-open')) {
163
- (_b = this.popoverElement) === null || _b === void 0 ? void 0 : _b.hidePopover();
164
- }
165
- });
166
- }
167
- // The rest of the code below deals with single/multiple selection behavior, and should not
168
- // interfere with events fired by menu items whose behavior is specified outside the library.
169
- if (this.selectVariant !== 'multiple' && this.selectVariant !== 'single')
130
+ if (event.type === 'focusout') {
131
+ if (__classPrivateFieldGet(this, _ActionMenuElement_invokerBeingClicked, "f"))
170
132
  return;
171
- const item = event.target.closest(menuItemSelectors.join(','));
172
- if (!item)
173
- return;
174
- const ariaChecked = item.getAttribute('aria-checked');
175
- const checked = ariaChecked !== 'true';
176
- if (this.selectVariant === 'single') {
177
- // Only check, never uncheck here. Single-select mode does not allow unchecking a checked item.
178
- if (checked) {
179
- item.setAttribute('aria-checked', 'true');
133
+ // Give the browser time to focus the next element
134
+ requestAnimationFrame(() => {
135
+ if (!this.contains(document.activeElement) || document.activeElement === this.invokerElement) {
136
+ __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_handleFocusOut).call(this);
180
137
  }
181
- for (const checkedItem of this.querySelectorAll('[aria-checked]')) {
182
- if (checkedItem !== item) {
183
- checkedItem.setAttribute('aria-checked', 'false');
184
- }
138
+ });
139
+ return;
140
+ }
141
+ const item = event.target.closest(menuItemSelectors.join(','));
142
+ const targetIsItem = item !== null;
143
+ if (targetIsItem && eventIsActivation) {
144
+ const dialogInvoker = item.closest('[data-show-dialog-id]');
145
+ if (dialogInvoker) {
146
+ const dialog = this.ownerDocument.getElementById(dialogInvoker.getAttribute('data-show-dialog-id') || '');
147
+ if (dialog && this.contains(dialogInvoker) && this.contains(dialog)) {
148
+ __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_handleDialogItemActivated).call(this, event, dialog);
149
+ return;
185
150
  }
186
- __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_setDynamicLabel).call(this);
187
151
  }
188
- else {
189
- // multi-select mode allows unchecking a checked item
190
- item.setAttribute('aria-checked', `${checked}`);
152
+ __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_activateItem).call(this, event, item);
153
+ __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_handleItemActivated).call(this, event, item);
154
+ return;
155
+ }
156
+ if (event.type === 'include-fragment-replaced') {
157
+ __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_handleIncludeFragmentReplaced).call(this);
158
+ }
159
+ }
160
+ };
161
+ _ActionMenuElement_abortController = new WeakMap(), _ActionMenuElement_originalLabel = new WeakMap(), _ActionMenuElement_inputName = new WeakMap(), _ActionMenuElement_invokerBeingClicked = new WeakMap(), _ActionMenuElement_instances = new WeakSet(), _ActionMenuElement_softDisableItems = function _ActionMenuElement_softDisableItems() {
162
+ const { signal } = __classPrivateFieldGet(this, _ActionMenuElement_abortController, "f");
163
+ for (const item of __classPrivateFieldGet(this, _ActionMenuElement_instances, "a", _ActionMenuElement_items_get)) {
164
+ item.addEventListener('click', __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_potentiallyDisallowActivation).bind(this), { signal });
165
+ item.addEventListener('keydown', __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_potentiallyDisallowActivation).bind(this), { signal });
166
+ }
167
+ }, _ActionMenuElement_potentiallyDisallowActivation = function _ActionMenuElement_potentiallyDisallowActivation(event) {
168
+ if (!__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_isActivation).call(this, event))
169
+ return;
170
+ const item = event.target.closest(menuItemSelectors.join(','));
171
+ if (!item)
172
+ return;
173
+ if (item.getAttribute('aria-disabled')) {
174
+ event.preventDefault();
175
+ event.stopPropagation();
176
+ event.stopImmediatePropagation();
177
+ }
178
+ }, _ActionMenuElement_isKeyboardActivation = function _ActionMenuElement_isKeyboardActivation(event) {
179
+ return (event instanceof KeyboardEvent &&
180
+ event.type === 'keydown' &&
181
+ !(event.ctrlKey || event.altKey || event.metaKey || event.shiftKey) &&
182
+ (event.key === 'Enter' || event.key === ' '));
183
+ }, _ActionMenuElement_isMouseActivation = function _ActionMenuElement_isMouseActivation(event) {
184
+ return event instanceof MouseEvent && event.type === 'click';
185
+ }, _ActionMenuElement_isActivation = function _ActionMenuElement_isActivation(event) {
186
+ return __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_isMouseActivation).call(this, event) || __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_isKeyboardActivation).call(this, event);
187
+ }, _ActionMenuElement_handleInvokerActivated = function _ActionMenuElement_handleInvokerActivated(event) {
188
+ var _a;
189
+ event.preventDefault();
190
+ event.stopPropagation();
191
+ if (__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_isOpen).call(this)) {
192
+ __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_hide).call(this);
193
+ }
194
+ else {
195
+ __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_show).call(this);
196
+ (_a = __classPrivateFieldGet(this, _ActionMenuElement_instances, "a", _ActionMenuElement_firstItem_get)) === null || _a === void 0 ? void 0 : _a.focus();
197
+ }
198
+ }, _ActionMenuElement_handleDialogItemActivated = function _ActionMenuElement_handleDialogItemActivated(event, dialog) {
199
+ this.querySelector('.ActionListWrap').style.display = 'none';
200
+ const dialog_controller = new AbortController();
201
+ const { signal } = dialog_controller;
202
+ const handleDialogClose = () => {
203
+ dialog_controller.abort();
204
+ this.querySelector('.ActionListWrap').style.display = '';
205
+ if (__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_isOpen).call(this)) {
206
+ __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_hide).call(this);
207
+ }
208
+ };
209
+ dialog.addEventListener('close', handleDialogClose, { signal });
210
+ dialog.addEventListener('cancel', handleDialogClose, { signal });
211
+ }, _ActionMenuElement_handleItemActivated = function _ActionMenuElement_handleItemActivated(event, item) {
212
+ // Hide popover after current event loop to prevent changes in focus from
213
+ // altering the target of the event. Not doing this specifically affects
214
+ // <a> tags. It causes the event to be sent to the currently focused element
215
+ // instead of the anchor, which effectively prevents navigation, i.e. it
216
+ // appears as if hitting enter does nothing. Curiously, clicking instead
217
+ // works fine.
218
+ if (this.selectVariant !== 'multiple') {
219
+ setTimeout(() => {
220
+ if (__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_isOpen).call(this)) {
221
+ __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_hide).call(this);
191
222
  }
192
- __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_updateInput).call(this);
193
- if (event instanceof KeyboardEvent && event.target instanceof HTMLButtonElement) {
194
- // prevent buttons from being clicked twice
195
- event.preventDefault();
223
+ });
224
+ }
225
+ // The rest of the code below deals with single/multiple selection behavior, and should not
226
+ // interfere with events fired by menu items whose behavior is specified outside the library.
227
+ if (this.selectVariant !== 'multiple' && this.selectVariant !== 'single')
228
+ return;
229
+ const ariaChecked = item.getAttribute('aria-checked');
230
+ const checked = ariaChecked !== 'true';
231
+ if (this.selectVariant === 'single') {
232
+ // Only check, never uncheck here. Single-select mode does not allow unchecking a checked item.
233
+ if (checked) {
234
+ item.setAttribute('aria-checked', 'true');
235
+ }
236
+ for (const checkedItem of this.querySelectorAll('[aria-checked]')) {
237
+ if (checkedItem !== item) {
238
+ checkedItem.setAttribute('aria-checked', 'false');
196
239
  }
197
240
  }
241
+ __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_setDynamicLabel).call(this);
198
242
  }
199
- };
200
- _ActionMenuElement_abortController = new WeakMap(), _ActionMenuElement_originalLabel = new WeakMap(), _ActionMenuElement_inputName = new WeakMap(), _ActionMenuElement_instances = new WeakSet(), _ActionMenuElement_setDynamicLabel = function _ActionMenuElement_setDynamicLabel() {
243
+ else {
244
+ // multi-select mode allows unchecking a checked item
245
+ item.setAttribute('aria-checked', `${checked}`);
246
+ }
247
+ __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_updateInput).call(this);
248
+ }, _ActionMenuElement_activateItem = function _ActionMenuElement_activateItem(event, item) {
249
+ const eventWillActivateByDefault = (event instanceof MouseEvent && event.type === 'click') ||
250
+ (event instanceof KeyboardEvent &&
251
+ event.type === 'keydown' &&
252
+ !(event.ctrlKey || event.altKey || event.metaKey || event.shiftKey) &&
253
+ event.key === 'Enter');
254
+ // if the event will result in activating the current item by default, i.e. is a
255
+ // mouse click or keyboard enter, bail out
256
+ if (eventWillActivateByDefault)
257
+ return;
258
+ // otherwise, event will not result in activation by default, so we stop it and
259
+ // simulate a click
260
+ event.stopPropagation();
261
+ const elem = item;
262
+ elem.click();
263
+ }, _ActionMenuElement_handleIncludeFragmentReplaced = function _ActionMenuElement_handleIncludeFragmentReplaced() {
264
+ if (__classPrivateFieldGet(this, _ActionMenuElement_instances, "a", _ActionMenuElement_firstItem_get))
265
+ __classPrivateFieldGet(this, _ActionMenuElement_instances, "a", _ActionMenuElement_firstItem_get).focus();
266
+ __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_softDisableItems).call(this);
267
+ }, _ActionMenuElement_handleFocusOut = function _ActionMenuElement_handleFocusOut() {
268
+ __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_hide).call(this);
269
+ }, _ActionMenuElement_show = function _ActionMenuElement_show() {
270
+ var _a;
271
+ (_a = this.popoverElement) === null || _a === void 0 ? void 0 : _a.showPopover();
272
+ }, _ActionMenuElement_hide = function _ActionMenuElement_hide() {
273
+ var _a;
274
+ (_a = this.popoverElement) === null || _a === void 0 ? void 0 : _a.hidePopover();
275
+ }, _ActionMenuElement_isOpen = function _ActionMenuElement_isOpen() {
276
+ var _a;
277
+ return (_a = this.popoverElement) === null || _a === void 0 ? void 0 : _a.matches(':popover-open');
278
+ }, _ActionMenuElement_setDynamicLabel = function _ActionMenuElement_setDynamicLabel() {
201
279
  if (!this.dynamicLabel)
202
280
  return;
203
281
  const invokerLabel = this.invokerLabel;
@@ -252,13 +330,10 @@ _ActionMenuElement_abortController = new WeakMap(), _ActionMenuElement_originalL
252
330
  input.remove();
253
331
  }
254
332
  }
255
- }, _ActionMenuElement_isActivationKeydown = function _ActionMenuElement_isActivationKeydown(event) {
256
- return (event instanceof KeyboardEvent &&
257
- event.type === 'keydown' &&
258
- !(event.ctrlKey || event.altKey || event.metaKey || event.shiftKey) &&
259
- (event.key === 'Enter' || event.key === ' '));
260
333
  }, _ActionMenuElement_firstItem_get = function _ActionMenuElement_firstItem_get() {
261
334
  return this.querySelector(menuItemSelectors.join(','));
335
+ }, _ActionMenuElement_items_get = function _ActionMenuElement_items_get() {
336
+ return Array.from(this.querySelectorAll(menuItemSelectors.join(',')));
262
337
  };
263
338
  __decorate([
264
339
  target