@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
|
@@ -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 =
|
|
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(
|
|
344
|
-
|
|
345
|
-
|
|
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
|
-
|
|
460
|
+
// eslint-disable-next-line no-undef
|
|
461
|
+
private updateTocItems(headingElements: NodeListOf<Element>): void {
|
|
462
|
+
const tocOptions = [];
|
|
364
463
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
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 {
|