@primer/view-components 0.36.1 → 0.36.2-rc.a45e0a1b

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.
@@ -1,5 +1,6 @@
1
1
  import '@oddbird/popover-polyfill';
2
2
  import type { IncludeFragmentElement } from '@github/include-fragment-element';
3
+ import AnchoredPositionElement from '../../anchored_position';
3
4
  type SelectVariant = 'none' | 'single' | 'multiple' | null;
4
5
  type SelectedItem = {
5
6
  label: string | null | undefined;
@@ -9,6 +10,7 @@ type SelectedItem = {
9
10
  export declare class ActionMenuElement extends HTMLElement {
10
11
  #private;
11
12
  includeFragment: IncludeFragmentElement;
13
+ overlay: AnchoredPositionElement;
12
14
  get selectVariant(): SelectVariant;
13
15
  set selectVariant(variant: SelectVariant);
14
16
  get dynamicLabelPrefix(): string;
@@ -15,9 +15,10 @@ 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_invokerBeingClicked, _ActionMenuElement_softDisableItems, _ActionMenuElement_potentiallyDisallowActivation, _ActionMenuElement_isAnchorActivationViaSpace, _ActionMenuElement_isActivation, _ActionMenuElement_handleInvokerActivated, _ActionMenuElement_handleDialogItemActivated, _ActionMenuElement_handleItemActivated, _ActionMenuElement_handleIncludeFragmentReplaced, _ActionMenuElement_handleFocusOut, _ActionMenuElement_show, _ActionMenuElement_hide, _ActionMenuElement_isOpen, _ActionMenuElement_setDynamicLabel, _ActionMenuElement_updateInput, _ActionMenuElement_firstItem_get;
18
+ var _ActionMenuElement_instances, _ActionMenuElement_abortController, _ActionMenuElement_originalLabel, _ActionMenuElement_inputName, _ActionMenuElement_invokerBeingClicked, _ActionMenuElement_intersectionObserver, _ActionMenuElement_softDisableItems, _ActionMenuElement_potentiallyDisallowActivation, _ActionMenuElement_isAnchorActivationViaSpace, _ActionMenuElement_isActivation, _ActionMenuElement_handleInvokerActivated, _ActionMenuElement_handleDialogItemActivated, _ActionMenuElement_handleItemActivated, _ActionMenuElement_handleIncludeFragmentReplaced, _ActionMenuElement_handleFocusOut, _ActionMenuElement_show, _ActionMenuElement_hide, _ActionMenuElement_isOpen, _ActionMenuElement_setDynamicLabel, _ActionMenuElement_updateInput, _ActionMenuElement_firstItem_get;
19
19
  import { controller, target } from '@github/catalyst';
20
20
  import '@oddbird/popover-polyfill';
21
+ import { observeMutationsUntilConditionMet } from '../../utils';
21
22
  const validSelectors = ['[role="menuitem"]', '[role="menuitemcheckbox"]', '[role="menuitemradio"]'];
22
23
  const menuItemSelectors = validSelectors.map(selector => `:not([hidden]) > ${selector}`);
23
24
  let ActionMenuElement = class ActionMenuElement extends HTMLElement {
@@ -28,6 +29,7 @@ let ActionMenuElement = class ActionMenuElement extends HTMLElement {
28
29
  _ActionMenuElement_originalLabel.set(this, '');
29
30
  _ActionMenuElement_inputName.set(this, '');
30
31
  _ActionMenuElement_invokerBeingClicked.set(this, false);
32
+ _ActionMenuElement_intersectionObserver.set(this, void 0);
31
33
  }
32
34
  get selectVariant() {
33
35
  return this.getAttribute('data-select-variant');
@@ -103,6 +105,30 @@ let ActionMenuElement = class ActionMenuElement extends HTMLElement {
103
105
  signal,
104
106
  });
105
107
  }
108
+ // The code below updates the menu (i.e. overlay) position whenever the invoker button
109
+ // changes position within its scroll container.
110
+ //
111
+ // See: https://github.com/primer/view_components/issues/3175
112
+ const scrollUpdater = () => {
113
+ if (__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_isOpen).call(this)) {
114
+ this.overlay?.update();
115
+ }
116
+ };
117
+ __classPrivateFieldSet(this, _ActionMenuElement_intersectionObserver, new IntersectionObserver(entries => {
118
+ for (const entry of entries) {
119
+ const elem = entry.target;
120
+ if (elem === this.invokerElement) {
121
+ if (entry.isIntersecting) {
122
+ // eslint-disable-next-line github/prefer-observers
123
+ window.addEventListener('scroll', scrollUpdater, { capture: true });
124
+ }
125
+ else {
126
+ window.removeEventListener('scroll', scrollUpdater, { capture: true });
127
+ }
128
+ }
129
+ }
130
+ }), "f");
131
+ observeMutationsUntilConditionMet(this, () => Boolean(this.invokerElement), () => __classPrivateFieldGet(this, _ActionMenuElement_intersectionObserver, "f").observe(this.invokerElement));
106
132
  }
107
133
  disconnectedCallback() {
108
134
  __classPrivateFieldGet(this, _ActionMenuElement_abortController, "f").abort();
@@ -240,6 +266,7 @@ _ActionMenuElement_abortController = new WeakMap();
240
266
  _ActionMenuElement_originalLabel = new WeakMap();
241
267
  _ActionMenuElement_inputName = new WeakMap();
242
268
  _ActionMenuElement_invokerBeingClicked = new WeakMap();
269
+ _ActionMenuElement_intersectionObserver = new WeakMap();
243
270
  _ActionMenuElement_instances = new WeakSet();
244
271
  _ActionMenuElement_softDisableItems = function _ActionMenuElement_softDisableItems() {
245
272
  const { signal } = __classPrivateFieldGet(this, _ActionMenuElement_abortController, "f");
@@ -443,6 +470,9 @@ _ActionMenuElement_firstItem_get = function _ActionMenuElement_firstItem_get() {
443
470
  __decorate([
444
471
  target
445
472
  ], ActionMenuElement.prototype, "includeFragment", void 0);
473
+ __decorate([
474
+ target
475
+ ], ActionMenuElement.prototype, "overlay", void 0);
446
476
  ActionMenuElement = __decorate([
447
477
  controller
448
478
  ], ActionMenuElement);
@@ -15,12 +15,13 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
15
15
  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");
16
16
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
17
17
  };
18
- var _SelectPanelElement_instances, _SelectPanelElement_dialogIntersectionObserver, _SelectPanelElement_abortController, _SelectPanelElement_originalLabel, _SelectPanelElement_inputName, _SelectPanelElement_selectedItems, _SelectPanelElement_loadingDelayTimeoutId, _SelectPanelElement_loadingAnnouncementTimeoutId, _SelectPanelElement_hasLoadedData, _SelectPanelElement_waitForCondition, _SelectPanelElement_softDisableItems, _SelectPanelElement_updateTabIndices, _SelectPanelElement_potentiallyDisallowActivation, _SelectPanelElement_isAnchorActivationViaSpace, _SelectPanelElement_isActivation, _SelectPanelElement_checkSelectedItems, _SelectPanelElement_addSelectedItem, _SelectPanelElement_removeSelectedItem, _SelectPanelElement_setTextFieldLoadingSpinnerTimer, _SelectPanelElement_handleIncludeFragmentEvent, _SelectPanelElement_toggleIncludeFragmentElements, _SelectPanelElement_handleRemoteInputEvent, _SelectPanelElement_defaultFilterFn, _SelectPanelElement_handleSearchFieldEvent, _SelectPanelElement_updateItemVisibility, _SelectPanelElement_inErrorState, _SelectPanelElement_setErrorState, _SelectPanelElement_clearErrorState, _SelectPanelElement_maybeAnnounce, _SelectPanelElement_fetchStrategy_get, _SelectPanelElement_filterInputTextFieldElement_get, _SelectPanelElement_performFilteringLocally, _SelectPanelElement_handleInvokerActivated, _SelectPanelElement_handleDialogItemActivated, _SelectPanelElement_handleItemActivated, _SelectPanelElement_setDynamicLabel, _SelectPanelElement_updateInput, _SelectPanelElement_firstItem_get, _SelectPanelElement_hideItem, _SelectPanelElement_showItem, _SelectPanelElement_getItemContent;
18
+ var _SelectPanelElement_instances, _SelectPanelElement_dialogIntersectionObserver, _SelectPanelElement_abortController, _SelectPanelElement_originalLabel, _SelectPanelElement_inputName, _SelectPanelElement_selectedItems, _SelectPanelElement_loadingDelayTimeoutId, _SelectPanelElement_loadingAnnouncementTimeoutId, _SelectPanelElement_hasLoadedData, _SelectPanelElement_softDisableItems, _SelectPanelElement_updateTabIndices, _SelectPanelElement_potentiallyDisallowActivation, _SelectPanelElement_isAnchorActivationViaSpace, _SelectPanelElement_isActivation, _SelectPanelElement_checkSelectedItems, _SelectPanelElement_addSelectedItem, _SelectPanelElement_removeSelectedItem, _SelectPanelElement_setTextFieldLoadingSpinnerTimer, _SelectPanelElement_handleIncludeFragmentEvent, _SelectPanelElement_toggleIncludeFragmentElements, _SelectPanelElement_handleRemoteInputEvent, _SelectPanelElement_defaultFilterFn, _SelectPanelElement_handleSearchFieldEvent, _SelectPanelElement_updateItemVisibility, _SelectPanelElement_inErrorState, _SelectPanelElement_setErrorState, _SelectPanelElement_clearErrorState, _SelectPanelElement_maybeAnnounce, _SelectPanelElement_fetchStrategy_get, _SelectPanelElement_filterInputTextFieldElement_get, _SelectPanelElement_performFilteringLocally, _SelectPanelElement_handleInvokerActivated, _SelectPanelElement_handleDialogItemActivated, _SelectPanelElement_handleItemActivated, _SelectPanelElement_setDynamicLabel, _SelectPanelElement_updateInput, _SelectPanelElement_firstItem_get, _SelectPanelElement_hideItem, _SelectPanelElement_showItem, _SelectPanelElement_getItemContent;
19
19
  import { getAnchoredPosition } from '@primer/behaviors';
20
20
  import { controller, target } from '@github/catalyst';
21
21
  import { IncludeFragmentElement } from '@github/include-fragment-element';
22
22
  import '@primer/live-region-element';
23
23
  import '@oddbird/popover-polyfill';
24
+ import { observeMutationsUntilConditionMet } from '../utils';
24
25
  const validSelectors = ['[role="option"]'];
25
26
  const menuItemSelectors = validSelectors.join(',');
26
27
  const visibleMenuItemSelectors = validSelectors.map(selector => `:not([hidden]) > ${selector}`).join(',');
@@ -172,11 +173,11 @@ let SelectPanelElement = class SelectPanelElement extends HTMLElement {
172
173
  __classPrivateFieldGet(this, _SelectPanelElement_instances, "m", _SelectPanelElement_updateInput).call(this);
173
174
  __classPrivateFieldGet(this, _SelectPanelElement_instances, "m", _SelectPanelElement_softDisableItems).call(this);
174
175
  updateWhenVisible(this);
175
- __classPrivateFieldGet(this, _SelectPanelElement_instances, "m", _SelectPanelElement_waitForCondition).call(this, () => Boolean(this.remoteInput), () => {
176
+ observeMutationsUntilConditionMet(this, () => Boolean(this.remoteInput), () => {
176
177
  this.remoteInput.addEventListener('loadstart', this, { signal });
177
178
  this.remoteInput.addEventListener('loadend', this, { signal });
178
179
  });
179
- __classPrivateFieldGet(this, _SelectPanelElement_instances, "m", _SelectPanelElement_waitForCondition).call(this, () => Boolean(this.includeFragment), () => {
180
+ observeMutationsUntilConditionMet(this, () => Boolean(this.includeFragment), () => {
180
181
  this.includeFragment.addEventListener('include-fragment-replaced', this, { signal });
181
182
  this.includeFragment.addEventListener('error', this, { signal });
182
183
  this.includeFragment.addEventListener('loadend', this, { signal });
@@ -201,7 +202,7 @@ let SelectPanelElement = class SelectPanelElement extends HTMLElement {
201
202
  }
202
203
  }
203
204
  }), "f");
204
- __classPrivateFieldGet(this, _SelectPanelElement_instances, "m", _SelectPanelElement_waitForCondition).call(this, () => Boolean(this.dialog), () => {
205
+ observeMutationsUntilConditionMet(this, () => Boolean(this.dialog), () => {
205
206
  __classPrivateFieldGet(this, _SelectPanelElement_dialogIntersectionObserver, "f").observe(this.dialog);
206
207
  this.dialog.addEventListener('close', this, { signal });
207
208
  if (this.getAttribute('data-open-on-load') === 'true') {
@@ -209,7 +210,7 @@ let SelectPanelElement = class SelectPanelElement extends HTMLElement {
209
210
  }
210
211
  });
211
212
  if (__classPrivateFieldGet(this, _SelectPanelElement_instances, "a", _SelectPanelElement_fetchStrategy_get) === FetchStrategy.LOCAL) {
212
- __classPrivateFieldGet(this, _SelectPanelElement_instances, "m", _SelectPanelElement_waitForCondition).call(this, () => this.items.length > 0, () => {
213
+ observeMutationsUntilConditionMet(this, () => this.items.length > 0, () => {
213
214
  __classPrivateFieldGet(this, _SelectPanelElement_instances, "m", _SelectPanelElement_updateItemVisibility).call(this);
214
215
  __classPrivateFieldGet(this, _SelectPanelElement_instances, "m", _SelectPanelElement_updateInput).call(this);
215
216
  });
@@ -399,20 +400,6 @@ _SelectPanelElement_loadingDelayTimeoutId = new WeakMap();
399
400
  _SelectPanelElement_loadingAnnouncementTimeoutId = new WeakMap();
400
401
  _SelectPanelElement_hasLoadedData = new WeakMap();
401
402
  _SelectPanelElement_instances = new WeakSet();
402
- _SelectPanelElement_waitForCondition = function _SelectPanelElement_waitForCondition(condition, body) {
403
- if (condition()) {
404
- body();
405
- }
406
- else {
407
- const mutationObserver = new MutationObserver(() => {
408
- if (condition()) {
409
- body();
410
- mutationObserver.disconnect();
411
- }
412
- });
413
- mutationObserver.observe(this, { childList: true, subtree: true });
414
- }
415
- };
416
403
  _SelectPanelElement_softDisableItems = function _SelectPanelElement_softDisableItems() {
417
404
  const { signal } = __classPrivateFieldGet(this, _SelectPanelElement_abortController, "f");
418
405
  for (const item of this.querySelectorAll(validSelectors.join(','))) {
@@ -8,6 +8,7 @@ import './dialog_helper';
8
8
  import './focus_group';
9
9
  import './scrollable_region';
10
10
  import './shared_events';
11
+ import './utils';
11
12
  import './alpha/modal_dialog';
12
13
  import './beta/nav_list';
13
14
  import './beta/nav_list_group_element';
@@ -8,6 +8,7 @@ import './dialog_helper';
8
8
  import './focus_group';
9
9
  import './scrollable_region';
10
10
  import './shared_events';
11
+ import './utils';
11
12
  import './alpha/modal_dialog';
12
13
  import './beta/nav_list';
13
14
  import './beta/nav_list_group_element';
@@ -0,0 +1 @@
1
+ export declare const observeMutationsUntilConditionMet: (element: Element, condition: () => boolean, body: () => void) => void;
@@ -0,0 +1,16 @@
1
+ // Waits for condition to return true. If it returns false initially, this function creates a
2
+ // MutationObserver that calls body() whenever the contents of the component change.
3
+ export const observeMutationsUntilConditionMet = (element, condition, body) => {
4
+ if (condition()) {
5
+ body();
6
+ }
7
+ else {
8
+ const mutationObserver = new MutationObserver(() => {
9
+ if (condition()) {
10
+ body();
11
+ mutationObserver.disconnect();
12
+ }
13
+ });
14
+ mutationObserver.observe(element, { childList: true, subtree: true });
15
+ }
16
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primer/view-components",
3
- "version": "0.36.1",
3
+ "version": "0.36.2-rc.a45e0a1b",
4
4
  "description": "ViewComponents for the Primer Design System",
5
5
  "main": "app/assets/javascripts/primer_view_components.js",
6
6
  "module": "app/components/primer/primer.js",