@salesforcedevs/docs-components 1.3.327-do-dont-2 → 1.3.327-rnbtab-alpha1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforcedevs/docs-components",
3
- "version": "1.3.327-do-dont-2",
3
+ "version": "1.3.327-rnbtab-alpha1",
4
4
  "description": "Docs Lightning web components for DSC",
5
5
  "license": "MIT",
6
6
  "main": "index.js",
@@ -11,6 +11,7 @@ type AnchorMap = { [key: string]: { intersect: boolean; id: string } };
11
11
  declare const Sprig: (eventType: string, eventNme: string) => void;
12
12
 
13
13
  const TOC_HEADER_TAG = "doc-heading";
14
+ const RNB_BY_TAB = "docs-tab";
14
15
  const HIGHLIGHTABLE_SELECTOR = [
15
16
  "p",
16
17
  "h1",
@@ -96,11 +97,72 @@ export default class ContentLayout extends LightningElement {
96
97
  private hasRendered: boolean = false;
97
98
  private contentLoaded: boolean = false;
98
99
  private sidebarOpen: boolean = false;
100
+ private rnbByTab: boolean = false;
99
101
 
100
102
  get shouldDisplayFeedback() {
101
103
  return this.contentLoaded && typeof Sprig !== "undefined";
102
104
  }
103
105
 
106
+ private setRNBByTab() {
107
+ const tabPanelListItem: any = this.getTabPanelList();
108
+ this.rnbByTab = tabPanelListItem?.id === RNB_BY_TAB ? true : false;
109
+ }
110
+
111
+ get showTabBasedRNB() {
112
+ return this.rnbByTab;
113
+ }
114
+
115
+ onTabChanged = () => {
116
+ this.updateRNB();
117
+ };
118
+
119
+ private getTabPanelList() {
120
+ return document.querySelector("dx-tab-panel-list");
121
+ }
122
+
123
+ updateRNB = () => {
124
+ const headingElements = this.getHeadingElements();
125
+ headingElements.forEach((headingElement: any) => {
126
+ // Sometimes elements hash and header is not being set when slot content is wrapped with div
127
+ headingElement.hash = headingElement.attributes.hash?.nodeValue;
128
+ headingElement.header = headingElement.attributes.header?.nodeValue;
129
+ });
130
+ this.updateTocItems(headingElements);
131
+ };
132
+
133
+ private getHeadingElements() {
134
+ let headingElements = document.querySelectorAll(TOC_HEADER_TAG);
135
+ if (this.showTabBasedRNB) {
136
+ const tabPanelListItem: any = this.getTabPanelList();
137
+ const tabPanels =
138
+ tabPanelListItem?.querySelectorAll("dx-tab-panel");
139
+ for (const tabPanelItem of tabPanels) {
140
+ if (tabPanelItem.active) {
141
+ headingElements =
142
+ tabPanelItem.querySelectorAll(TOC_HEADER_TAG);
143
+ break;
144
+ }
145
+ }
146
+ }
147
+ return headingElements;
148
+ }
149
+
150
+ private updateURL() {
151
+ const tabs = this.getAllTabs();
152
+ const selectedTabId = this.getSelectedTabId();
153
+ tabs.forEach((tab: any) => {
154
+ if (tab.getAttribute("aria-selected") === "true") {
155
+ const tabID = tab.getAttribute("aria-label");
156
+ const url = new URL(window.location.href);
157
+ if (selectedTabId !== tabID) {
158
+ url.searchParams.set("type", tabID);
159
+ url.hash = "";
160
+ window.history.pushState({}, "", url.toString());
161
+ }
162
+ }
163
+ });
164
+ }
165
+
104
166
  private searchSyncer = new SearchSyncer({
105
167
  callbacks: {
106
168
  onSearchChange: (nextSearchString: string): void => {
@@ -148,6 +210,46 @@ export default class ContentLayout extends LightningElement {
148
210
  );
149
211
  this.searchSyncer.init();
150
212
  }
213
+
214
+ if (this.showTabBasedRNB) {
215
+ window.addEventListener("tabchanged", this.onTabChanged);
216
+ }
217
+ }
218
+
219
+ private getSelectedTabId() {
220
+ const urlParams = new URLSearchParams(window.location.search);
221
+ const selectedTabId = urlParams.get("type");
222
+ return selectedTabId;
223
+ }
224
+
225
+ private restoreTabSelection() {
226
+ const selectedTabId = this.getSelectedTabId();
227
+ if (selectedTabId) {
228
+ this.selectTabById(selectedTabId);
229
+ }
230
+ }
231
+
232
+ private getAllTabs(): any[] {
233
+ const tabPanelListItem: any = this.getTabPanelList();
234
+ if (tabPanelListItem?.shadowRoot) {
235
+ return Array.from(
236
+ tabPanelListItem.shadowRoot.querySelectorAll(
237
+ "dx-tab-panel-item"
238
+ )
239
+ ).map((tabPanelItem: any) =>
240
+ tabPanelItem.shadowRoot.querySelector("button")
241
+ );
242
+ }
243
+ return [];
244
+ }
245
+
246
+ private selectTabById(tabId: string) {
247
+ const tabs = this.getAllTabs();
248
+ tabs.forEach((tab: any) => {
249
+ if (tab.getAttribute("aria-label") === tabId) {
250
+ tab.click();
251
+ }
252
+ });
151
253
  }
152
254
 
153
255
  renderedCallback(): void {
@@ -167,6 +269,10 @@ export default class ContentLayout extends LightningElement {
167
269
 
168
270
  if (!this.hasRendered) {
169
271
  this.hasRendered = true;
272
+ this.setRNBByTab();
273
+ if (this.showTabBasedRNB) {
274
+ this.restoreTabSelection();
275
+ }
170
276
  this.restoreScroll();
171
277
  }
172
278
  }
@@ -179,6 +285,7 @@ export default class ContentLayout extends LightningElement {
179
285
  );
180
286
  window.removeEventListener("scroll", this.adjustNavPosition);
181
287
  window.removeEventListener("resize", this.adjustNavPosition);
288
+ window.removeEventListener("tabchanged", this.onTabChanged);
182
289
  this.searchSyncer.dispose();
183
290
  this.clearRenderObserverTimer();
184
291
 
@@ -324,7 +431,13 @@ export default class ContentLayout extends LightningElement {
324
431
  );
325
432
 
326
433
  // Note: We are doing document.querySelectorAll as a quick fix as we are not getting heading elements reference this.querySelectorAll
327
- const headingElements = document.querySelectorAll(TOC_HEADER_TAG);
434
+ const headingElements = this.getHeadingElements();
435
+
436
+ // We only need to update URL in case of /docs and ignore if tabs are used anywhere else in DSC
437
+ if (this.showTabBasedRNB) {
438
+ this.updateURL();
439
+ }
440
+
328
441
  for (const headingElement of headingElements as any) {
329
442
  // Add headingElements to intersectionObserver for highlighting respective RNB item when user scroll
330
443
  const id = headingElement.getAttribute("id")!;
@@ -340,49 +453,34 @@ export default class ContentLayout extends LightningElement {
340
453
  }
341
454
  };
342
455
 
343
- onSlotChange(event: Event): void {
344
- const slotElements = (
345
- event.target as HTMLSlotElement
346
- ).assignedElements();
347
-
348
- if (slotElements.length) {
349
- this.contentLoaded = true;
350
- const slotContentElement = slotElements[0];
351
- const headingElements =
352
- slotContentElement.ownerDocument?.getElementsByTagName(
353
- TOC_HEADER_TAG
354
- );
355
-
356
- for (const headingElement of headingElements as any) {
357
- // Sometimes elements hash and header is not being set when slot content is wrapped with div
358
- headingElement.hash = headingElement.attributes.hash?.nodeValue;
359
- headingElement.header =
360
- headingElement.attributes.header?.nodeValue;
361
- }
456
+ onSlotChange(): void {
457
+ this.updateRNB();
458
+ }
362
459
 
363
- const tocOptions = [];
460
+ // eslint-disable-next-line no-undef
461
+ private updateTocItems(headingElements: NodeListOf<Element>): void {
462
+ const tocOptions = [];
364
463
 
365
- for (const headingElement of headingElements as any) {
366
- headingElement.id = headingElement.hash;
367
-
368
- // Update tocOptions from anchorTags only for H2, consider default as 2 as per component
369
- const headingAriaLevel =
370
- headingElement.attributes["aria-level"]?.nodeValue || "2";
371
- const isH2 = headingAriaLevel === "2";
372
-
373
- if (isH2) {
374
- const tocItem = {
375
- anchor: `#${headingElement.hash}`,
376
- id: headingElement.id,
377
- label: headingElement.header
378
- };
379
- tocOptions.push(tocItem);
380
- this.tocOptionIdsSet.add(headingElement.id);
381
- }
464
+ for (const headingElement of headingElements as any) {
465
+ headingElement.id = headingElement.hash;
466
+
467
+ // Update tocOptions from anchorTags only for H2, consider default as 2 as per component
468
+ const headingAriaLevel =
469
+ headingElement.attributes["aria-level"]?.nodeValue || "2";
470
+ const isH2 = headingAriaLevel === "2";
471
+
472
+ if (isH2) {
473
+ const tocItem = {
474
+ anchor: `#${headingElement.hash}`,
475
+ id: headingElement.id,
476
+ label: headingElement.header
477
+ };
478
+ tocOptions.push(tocItem);
479
+ this.tocOptionIdsSet.add(headingElement.id);
382
480
  }
383
-
384
- this._tocOptions = tocOptions;
385
481
  }
482
+
483
+ this._tocOptions = tocOptions;
386
484
  }
387
485
 
388
486
  private disconnectObserver(): void {
@@ -20,7 +20,7 @@
20
20
  </template>
21
21
  </div>
22
22
  <div class="do-dont-image-container">
23
- <img class="doc-do-dont-img" src={imgSrc} alt={caption} />
23
+ <img class="doc-do-dont-img" src={src} alt={caption} />
24
24
  </div>
25
25
  <div class="dx-text-body-4">{caption}</div>
26
26
  </div>
@@ -3,7 +3,7 @@ import { normalizeBoolean } from "dxUtils/normalizers";
3
3
 
4
4
  export default class DoDont extends LightningElement {
5
5
  @api caption: string = "";
6
- @api imgSrc!: string;
6
+ @api src!: string;
7
7
  _isDo: boolean = false;
8
8
 
9
9
  @api