primer_view_components 0.0.122 → 0.0.123

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.
@@ -187,6 +187,9 @@ module Primer
187
187
  @system_arguments[:aria] ||= {}
188
188
  @system_arguments[:aria][:disabled] = "true" if @disabled
189
189
 
190
+ @system_arguments[:data] ||= {}
191
+ @system_arguments[:data][:targets] = "#{list_class.custom_element_name}.items"
192
+
190
193
  @label_arguments = {
191
194
  classes: class_names(
192
195
  label_classes,
@@ -236,6 +239,10 @@ module Primer
236
239
  "ActionListContent--blockDescription" => description && @description_scheme == :block
237
240
  )
238
241
  end
242
+
243
+ def list_class
244
+ Primer::Alpha::ActionList
245
+ end
239
246
  end
240
247
  end
241
248
  end
@@ -119,6 +119,10 @@ module Primer
119
119
  def current_page?(url)
120
120
  helpers.current_page?(url)
121
121
  end
122
+
123
+ def list_class
124
+ Primer::Alpha::NavList
125
+ end
122
126
  end
123
127
  end
124
128
  end
@@ -38,7 +38,7 @@ module Primer
38
38
 
39
39
  # @private
40
40
  def self.custom_element_name
41
- "nav-list"
41
+ Primer::Alpha::NavList.custom_element_name
42
42
  end
43
43
 
44
44
  # @param selected_item_id [Symbol] The ID of the currently selected item. Used internally.
@@ -1,5 +1,7 @@
1
- declare class NavListElement extends HTMLElement {
1
+ export declare class NavListElement extends HTMLElement {
2
+ #private;
2
3
  list: HTMLElement;
4
+ items: HTMLElement[];
3
5
  showMoreItem: HTMLElement;
4
6
  focusMarkers: HTMLElement[];
5
7
  connectedCallback(): void;
@@ -9,17 +11,18 @@ declare class NavListElement extends HTMLElement {
9
11
  get currentPage(): number;
10
12
  get totalPages(): number;
11
13
  get paginationSrc(): string;
14
+ selectItemById(itemId: string | null): boolean;
15
+ selectItemByHref(href: string | null): boolean;
16
+ selectItemByCurrentLocation(): boolean;
12
17
  expandItem(item: HTMLElement): void;
13
18
  collapseItem(item: HTMLElement): void;
14
19
  itemIsExpanded(item: HTMLElement | null): boolean;
15
20
  handleItemWithSubItemClick(e: Event): void;
16
21
  private showMore;
17
22
  private setShowMoreItemState;
18
- private parseHTML;
19
23
  }
20
24
  declare global {
21
25
  interface Window {
22
26
  NavListElement: typeof NavListElement;
23
27
  }
24
28
  }
25
- export {};
@@ -4,9 +4,19 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
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
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ 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");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
12
+ var _NavListElement_instances, _NavListElement_parseHTML, _NavListElement_findSelectedNavItemById, _NavListElement_findSelectedNavItemByHref, _NavListElement_findSelectedNavItemByCurrentLocation, _NavListElement_select, _NavListElement_deselect, _NavListElement_findParentMenu;
7
13
  /* eslint-disable custom-elements/expose-class-on-global */
8
14
  import { controller, target, targets } from '@github/catalyst';
9
15
  let NavListElement = class NavListElement extends HTMLElement {
16
+ constructor() {
17
+ super(...arguments);
18
+ _NavListElement_instances.add(this);
19
+ }
10
20
  connectedCallback() {
11
21
  this.setShowMoreItemState();
12
22
  }
@@ -34,6 +44,34 @@ let NavListElement = class NavListElement extends HTMLElement {
34
44
  get paginationSrc() {
35
45
  return this.showMoreItem.getAttribute('src') || '';
36
46
  }
47
+ selectItemById(itemId) {
48
+ if (!itemId)
49
+ return false;
50
+ const selectedItem = __classPrivateFieldGet(this, _NavListElement_instances, "m", _NavListElement_findSelectedNavItemById).call(this, itemId);
51
+ if (selectedItem) {
52
+ __classPrivateFieldGet(this, _NavListElement_instances, "m", _NavListElement_select).call(this, selectedItem);
53
+ return true;
54
+ }
55
+ return false;
56
+ }
57
+ selectItemByHref(href) {
58
+ if (!href)
59
+ return false;
60
+ const selectedItem = __classPrivateFieldGet(this, _NavListElement_instances, "m", _NavListElement_findSelectedNavItemByHref).call(this, href);
61
+ if (selectedItem) {
62
+ __classPrivateFieldGet(this, _NavListElement_instances, "m", _NavListElement_select).call(this, selectedItem);
63
+ return true;
64
+ }
65
+ return false;
66
+ }
67
+ selectItemByCurrentLocation() {
68
+ const selectedItem = __classPrivateFieldGet(this, _NavListElement_instances, "m", _NavListElement_findSelectedNavItemByCurrentLocation).call(this);
69
+ if (selectedItem) {
70
+ __classPrivateFieldGet(this, _NavListElement_instances, "m", _NavListElement_select).call(this, selectedItem);
71
+ return true;
72
+ }
73
+ return false;
74
+ }
37
75
  // expand collapsible item onClick
38
76
  expandItem(item) {
39
77
  var _a;
@@ -92,7 +130,7 @@ let NavListElement = class NavListElement extends HTMLElement {
92
130
  this.currentPage--;
93
131
  return;
94
132
  }
95
- const fragment = this.parseHTML(document, html);
133
+ const fragment = __classPrivateFieldGet(this, _NavListElement_instances, "m", _NavListElement_parseHTML).call(this, document, html);
96
134
  (_a = fragment === null || fragment === void 0 ? void 0 : fragment.querySelector('li > a')) === null || _a === void 0 ? void 0 : _a.setAttribute('data-targets', 'nav-list.focusMarkers');
97
135
  this.list.insertBefore(fragment, this.showMoreItem);
98
136
  (_b = this.focusMarkers.pop()) === null || _b === void 0 ? void 0 : _b.focus();
@@ -109,16 +147,66 @@ let NavListElement = class NavListElement extends HTMLElement {
109
147
  this.showMoreItem.hidden = true;
110
148
  }
111
149
  }
112
- parseHTML(document, html) {
113
- const template = document.createElement('template');
114
- // eslint-disable-next-line github/no-inner-html
115
- template.innerHTML = html;
116
- return document.importNode(template.content, true);
150
+ };
151
+ _NavListElement_instances = new WeakSet(), _NavListElement_parseHTML = function _NavListElement_parseHTML(document, html) {
152
+ const template = document.createElement('template');
153
+ // eslint-disable-next-line github/no-inner-html
154
+ template.innerHTML = html;
155
+ return document.importNode(template.content, true);
156
+ }, _NavListElement_findSelectedNavItemById = function _NavListElement_findSelectedNavItemById(itemId) {
157
+ var _a;
158
+ // First we compare the selected link to data-item-id for each nav item
159
+ for (const navItem of this.items) {
160
+ const keys = ((_a = navItem.getAttribute('data-item-id')) === null || _a === void 0 ? void 0 : _a.split(' ')) || [];
161
+ if (keys.includes(itemId)) {
162
+ return navItem;
163
+ }
164
+ }
165
+ return null;
166
+ }, _NavListElement_findSelectedNavItemByHref = function _NavListElement_findSelectedNavItemByHref(href) {
167
+ // If we didn't find a match, we compare the selected link to the href of each nav item
168
+ const selectedNavItem = this.querySelector(`.ActionListContent[href="${href}"]`);
169
+ if (selectedNavItem) {
170
+ return selectedNavItem.closest('.ActionListItem');
171
+ }
172
+ return null;
173
+ }, _NavListElement_findSelectedNavItemByCurrentLocation = function _NavListElement_findSelectedNavItemByCurrentLocation() {
174
+ return __classPrivateFieldGet(this, _NavListElement_instances, "m", _NavListElement_findSelectedNavItemByHref).call(this, window.location.pathname);
175
+ }, _NavListElement_select = function _NavListElement_select(navItem) {
176
+ const currentlySelectedItem = this.querySelector('.ActionListItem--navActive');
177
+ if (currentlySelectedItem)
178
+ __classPrivateFieldGet(this, _NavListElement_instances, "m", _NavListElement_deselect).call(this, currentlySelectedItem);
179
+ navItem.classList.add('ActionListItem--navActive');
180
+ const parentMenu = __classPrivateFieldGet(this, _NavListElement_instances, "m", _NavListElement_findParentMenu).call(this, navItem);
181
+ if (parentMenu) {
182
+ this.expandItem(parentMenu);
183
+ parentMenu.classList.add('ActionListContent--hasActiveSubItem');
184
+ }
185
+ }, _NavListElement_deselect = function _NavListElement_deselect(navItem) {
186
+ navItem.classList.remove('ActionListItem--navActive');
187
+ const parentMenu = __classPrivateFieldGet(this, _NavListElement_instances, "m", _NavListElement_findParentMenu).call(this, navItem);
188
+ if (parentMenu) {
189
+ this.collapseItem(parentMenu);
190
+ parentMenu.classList.remove('ActionListContent--hasActiveSubItem');
191
+ }
192
+ }, _NavListElement_findParentMenu = function _NavListElement_findParentMenu(navItem) {
193
+ var _a;
194
+ if (!navItem.classList.contains('ActionListItem--subItem'))
195
+ return null;
196
+ const parent = (_a = navItem.closest('li.ActionListItem--hasSubItem')) === null || _a === void 0 ? void 0 : _a.querySelector('button.ActionListContent');
197
+ if (parent) {
198
+ return parent;
199
+ }
200
+ else {
201
+ return null;
117
202
  }
118
203
  };
119
204
  __decorate([
120
205
  target
121
206
  ], NavListElement.prototype, "list", void 0);
207
+ __decorate([
208
+ targets
209
+ ], NavListElement.prototype, "items", void 0);
122
210
  __decorate([
123
211
  target
124
212
  ], NavListElement.prototype, "showMoreItem", void 0);
@@ -128,3 +216,4 @@ __decorate([
128
216
  NavListElement = __decorate([
129
217
  controller
130
218
  ], NavListElement);
219
+ export { NavListElement };
@@ -17,6 +17,11 @@ module Primer
17
17
  class NavList < Primer::Component
18
18
  status :alpha
19
19
 
20
+ # @private
21
+ def self.custom_element_name
22
+ "nav-list"
23
+ end
24
+
20
25
  # Sections. Each section is a list of links and an optional heading.
21
26
  #
22
27
  # @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Alpha::NavList::Section) %>.
@@ -2,8 +2,9 @@
2
2
  import {controller, target, targets} from '@github/catalyst'
3
3
 
4
4
  @controller
5
- class NavListElement extends HTMLElement {
5
+ export class NavListElement extends HTMLElement {
6
6
  @target list: HTMLElement
7
+ @targets items: HTMLElement[]
7
8
  @target showMoreItem: HTMLElement
8
9
  @targets focusMarkers: HTMLElement[]
9
10
 
@@ -40,6 +41,43 @@ class NavListElement extends HTMLElement {
40
41
  return this.showMoreItem.getAttribute('src') || ''
41
42
  }
42
43
 
44
+ selectItemById(itemId: string | null): boolean {
45
+ if (!itemId) return false
46
+
47
+ const selectedItem = this.#findSelectedNavItemById(itemId)
48
+
49
+ if (selectedItem) {
50
+ this.#select(selectedItem)
51
+ return true
52
+ }
53
+
54
+ return false
55
+ }
56
+
57
+ selectItemByHref(href: string | null): boolean {
58
+ if (!href) return false
59
+
60
+ const selectedItem = this.#findSelectedNavItemByHref(href)
61
+
62
+ if (selectedItem) {
63
+ this.#select(selectedItem)
64
+ return true
65
+ }
66
+
67
+ return false
68
+ }
69
+
70
+ selectItemByCurrentLocation(): boolean {
71
+ const selectedItem = this.#findSelectedNavItemByCurrentLocation()
72
+
73
+ if (selectedItem) {
74
+ this.#select(selectedItem)
75
+ return true
76
+ }
77
+
78
+ return false
79
+ }
80
+
43
81
  // expand collapsible item onClick
44
82
  expandItem(item: HTMLElement) {
45
83
  item.nextElementSibling?.removeAttribute('data-hidden')
@@ -95,7 +133,7 @@ class NavListElement extends HTMLElement {
95
133
  this.currentPage--
96
134
  return
97
135
  }
98
- const fragment = this.parseHTML(document, html)
136
+ const fragment = this.#parseHTML(document, html)
99
137
  fragment?.querySelector('li > a')?.setAttribute('data-targets', 'nav-list.focusMarkers')
100
138
  this.list.insertBefore(fragment, this.showMoreItem)
101
139
  this.focusMarkers.pop()?.focus()
@@ -114,12 +152,76 @@ class NavListElement extends HTMLElement {
114
152
  }
115
153
  }
116
154
 
117
- private parseHTML(document: Document, html: string): DocumentFragment {
155
+ #parseHTML(document: Document, html: string): DocumentFragment {
118
156
  const template = document.createElement('template')
119
157
  // eslint-disable-next-line github/no-inner-html
120
158
  template.innerHTML = html
121
159
  return document.importNode(template.content, true)
122
160
  }
161
+
162
+ #findSelectedNavItemById(itemId: string): HTMLElement | null {
163
+ // First we compare the selected link to data-item-id for each nav item
164
+ for (const navItem of this.items) {
165
+ const keys = navItem.getAttribute('data-item-id')?.split(' ') || []
166
+
167
+ if (keys.includes(itemId)) {
168
+ return navItem
169
+ }
170
+ }
171
+
172
+ return null
173
+ }
174
+
175
+ #findSelectedNavItemByHref(href: string): HTMLElement | null {
176
+ // If we didn't find a match, we compare the selected link to the href of each nav item
177
+ const selectedNavItem = this.querySelector<HTMLAnchorElement>(`.ActionListContent[href="${href}"]`)
178
+ if (selectedNavItem) {
179
+ return selectedNavItem.closest('.ActionListItem')
180
+ }
181
+
182
+ return null
183
+ }
184
+
185
+ #findSelectedNavItemByCurrentLocation(): HTMLElement | null {
186
+ return this.#findSelectedNavItemByHref(window.location.pathname)
187
+ }
188
+
189
+ #select(navItem: HTMLElement) {
190
+ const currentlySelectedItem = this.querySelector('.ActionListItem--navActive') as HTMLElement
191
+ if (currentlySelectedItem) this.#deselect(currentlySelectedItem)
192
+
193
+ navItem.classList.add('ActionListItem--navActive')
194
+
195
+ const parentMenu = this.#findParentMenu(navItem)
196
+
197
+ if (parentMenu) {
198
+ this.expandItem(parentMenu)
199
+ parentMenu.classList.add('ActionListContent--hasActiveSubItem')
200
+ }
201
+ }
202
+
203
+ #deselect(navItem: HTMLElement) {
204
+ navItem.classList.remove('ActionListItem--navActive')
205
+
206
+ const parentMenu = this.#findParentMenu(navItem)
207
+
208
+ if (parentMenu) {
209
+ this.collapseItem(parentMenu)
210
+ parentMenu.classList.remove('ActionListContent--hasActiveSubItem')
211
+ }
212
+ }
213
+
214
+ #findParentMenu(navItem: HTMLElement): HTMLElement | null {
215
+ if (!navItem.classList.contains('ActionListItem--subItem')) return null
216
+
217
+ const parent = navItem.closest('li.ActionListItem--hasSubItem')?.querySelector('button.ActionListContent')
218
+
219
+ if (parent) {
220
+ return parent as HTMLElement
221
+ } else {
222
+ return null
223
+ }
224
+ }
123
225
  }
124
226
 
125
227
  declare global {
@@ -12,7 +12,7 @@ module Primer
12
12
  end
13
13
 
14
14
  if Module.const_defined?("ViewComponent::PolymorphicSlots") &&
15
- ViewComponent::Base < ViewComponent::PolymorphicSlots
15
+ !(ViewComponent::Base < ViewComponent::PolymorphicSlots)
16
16
  include ViewComponent::PolymorphicSlots
17
17
  end
18
18
 
@@ -6,7 +6,7 @@ module Primer
6
6
  module VERSION
7
7
  MAJOR = 0
8
8
  MINOR = 0
9
- PATCH = 122
9
+ PATCH = 123
10
10
 
11
11
  STRING = [MAJOR, MINOR, PATCH].join(".")
12
12
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: primer_view_components
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.122
4
+ version: 0.0.123
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub Open Source