primer_view_components 0.0.122 → 0.0.123

Sign up to get free protection for your applications and to get access to all the features.
@@ -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