@salesforcedevs/docs-components 0.0.1-edit → 0.0.1-superscript
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/lwc.config.json +2 -1
- package/package.json +29 -28
- package/src/modules/doc/amfReference/amfReference.css +0 -12
- package/src/modules/doc/amfReference/amfReference.html +2 -6
- package/src/modules/doc/amfReference/amfReference.ts +48 -37
- package/src/modules/doc/amfTopic/amfTopic.ts +24 -0
- package/src/modules/doc/breadcrumbs/breadcrumbs.html +0 -1
- package/src/modules/doc/componentPlayground/componentPlayground.css +11 -3
- package/src/modules/doc/componentPlayground/componentPlayground.html +4 -4
- package/src/modules/doc/componentPlayground/componentPlayground.ts +69 -1
- package/src/modules/doc/content/content.ts +0 -1
- package/src/modules/doc/contentCallout/contentCallout.css +1 -0
- package/src/modules/doc/contentLayout/contentLayout.html +53 -56
- package/src/modules/doc/contentLayout/contentLayout.ts +82 -43
- package/src/modules/doc/contentMedia/contentMedia.css +1 -1
- package/src/modules/doc/header/header.html +5 -1
- package/src/modules/doc/header/header.ts +10 -0
- package/src/modules/doc/lwcContentLayout/lwcContentLayout.css +8 -0
- package/src/modules/doc/lwcContentLayout/lwcContentLayout.html +38 -42
- package/src/modules/doc/lwcContentLayout/lwcContentLayout.ts +116 -15
- package/src/modules/doc/phase/phase.css +0 -7
- package/src/modules/doc/redocReference/redocReference.css +7 -0
- package/src/modules/doc/redocReference/redocReference.html +13 -0
- package/src/modules/doc/redocReference/redocReference.ts +425 -0
- package/src/modules/doc/specificationContent/specificationContent.html +15 -9
- package/src/modules/doc/specificationContent/specificationContent.ts +39 -0
- package/src/modules/doc/superscriptSubscript/superscriptSubscript.html +8 -0
- package/src/modules/doc/superscriptSubscript/superscriptSubscript.ts +16 -0
- package/src/modules/doc/versionPicker/versionPicker.html +2 -0
- package/src/modules/doc/xmlContent/xmlContent.css +0 -10
- package/src/modules/doc/xmlContent/xmlContent.html +11 -8
- package/src/modules/doc/xmlContent/xmlContent.ts +95 -53
- package/src/modules/docHelpers/amfStyle/amfStyle.css +0 -2
- package/src/modules/docHelpers/contentLayoutStyle/contentLayoutStyle.css +32 -1
- package/src/modules/doc/chat/README.md +0 -179
- package/src/modules/doc/chat/chat.css +0 -818
- package/src/modules/doc/chat/chat.html +0 -241
- package/src/modules/doc/chat/chat.ts +0 -586
- package/src/modules/doc/editFile/editFile.css +0 -514
- package/src/modules/doc/editFile/editFile.html +0 -164
- package/src/modules/doc/editFile/editFile.ts +0 -213
|
@@ -5,6 +5,7 @@ import { toJson } from "dxUtils/normalizers";
|
|
|
5
5
|
import { highlightTerms } from "dxUtils/highlight";
|
|
6
6
|
import { SearchSyncer } from "docUtils/searchSyncer";
|
|
7
7
|
import type { OptionWithLink } from "typings/custom";
|
|
8
|
+
import { buildDocLinkClickHandler } from "dxUtils/analytics";
|
|
8
9
|
|
|
9
10
|
type AnchorMap = { [key: string]: { intersect: boolean; id: string } };
|
|
10
11
|
|
|
@@ -32,11 +33,6 @@ export default class ContentLayout extends LightningElement {
|
|
|
32
33
|
@api sidebarHeader!: string;
|
|
33
34
|
@api tocTitle!: string;
|
|
34
35
|
@api enableSlotChange = false;
|
|
35
|
-
@api coveoOrganizationId!: string;
|
|
36
|
-
@api coveoPublicAccessToken!: string;
|
|
37
|
-
@api coveoAnalyticsToken!: string;
|
|
38
|
-
@api coveoSearchHub!: string;
|
|
39
|
-
@api coveoAdvancedQueryConfig!: string;
|
|
40
36
|
@api useOldSidebar?: boolean = false;
|
|
41
37
|
@api languages!: OptionWithLink[];
|
|
42
38
|
@api language!: string;
|
|
@@ -44,10 +40,13 @@ export default class ContentLayout extends LightningElement {
|
|
|
44
40
|
@api bailLabel!: string;
|
|
45
41
|
@api devCenter: any;
|
|
46
42
|
@api brand: any;
|
|
43
|
+
@api emptyStateMessage?: string;
|
|
47
44
|
|
|
48
45
|
// This is needed for now to prevent failing snapshot tests due to links in the footer
|
|
49
46
|
@api showFooter = false;
|
|
50
47
|
|
|
48
|
+
@api readingTime?: number;
|
|
49
|
+
|
|
51
50
|
@api
|
|
52
51
|
get breadcrumbs() {
|
|
53
52
|
return this._breadcrumbs;
|
|
@@ -77,6 +76,12 @@ export default class ContentLayout extends LightningElement {
|
|
|
77
76
|
this._tocOptions = toJson(value);
|
|
78
77
|
}
|
|
79
78
|
|
|
79
|
+
/**
|
|
80
|
+
* The aria-level to filter headings by when building the TOC.
|
|
81
|
+
* Defaults to "2" (H2 headings).
|
|
82
|
+
*/
|
|
83
|
+
@api tocAriaLevel: string = "2";
|
|
84
|
+
|
|
80
85
|
@api
|
|
81
86
|
setSidebarInputValue(searchTerm: string): void {
|
|
82
87
|
(this.template.querySelector("dx-sidebar") as any)?.setInputValue(
|
|
@@ -123,6 +128,7 @@ export default class ContentLayout extends LightningElement {
|
|
|
123
128
|
protected observerTimerId?: NodeJS.Timeout;
|
|
124
129
|
protected didScrollToSelectedHash = false;
|
|
125
130
|
protected _scrollInterval = 0;
|
|
131
|
+
protected handleLinkClick = buildDocLinkClickHandler();
|
|
126
132
|
|
|
127
133
|
get showToc(): boolean {
|
|
128
134
|
return this.tocOptions && this.tocOptions.length > 0;
|
|
@@ -139,6 +145,10 @@ export default class ContentLayout extends LightningElement {
|
|
|
139
145
|
);
|
|
140
146
|
}
|
|
141
147
|
|
|
148
|
+
get showReadingTime(): boolean {
|
|
149
|
+
return this.readingTime != null && this.readingTime > 1;
|
|
150
|
+
}
|
|
151
|
+
|
|
142
152
|
connectedCallback(): void {
|
|
143
153
|
const hasParentHighlightListener = closest(
|
|
144
154
|
"doc-xml-content",
|
|
@@ -151,6 +161,9 @@ export default class ContentLayout extends LightningElement {
|
|
|
151
161
|
);
|
|
152
162
|
this.searchSyncer.init();
|
|
153
163
|
}
|
|
164
|
+
|
|
165
|
+
// Add click handler for all links
|
|
166
|
+
this.template.addEventListener("click", this.handleLinkClick);
|
|
154
167
|
}
|
|
155
168
|
|
|
156
169
|
// Placeholder for childs renderedCallback
|
|
@@ -192,6 +205,9 @@ export default class ContentLayout extends LightningElement {
|
|
|
192
205
|
this.clearRenderObserverTimer();
|
|
193
206
|
|
|
194
207
|
window.clearInterval(this._scrollInterval);
|
|
208
|
+
|
|
209
|
+
// Remove link click handler
|
|
210
|
+
this.template.removeEventListener("click", this.handleLinkClick);
|
|
195
211
|
}
|
|
196
212
|
|
|
197
213
|
restoreScroll() {
|
|
@@ -210,10 +226,7 @@ export default class ContentLayout extends LightningElement {
|
|
|
210
226
|
We have to account for the global nav changing height due to animations.
|
|
211
227
|
*/
|
|
212
228
|
adjustNavPosition = () => {
|
|
213
|
-
const
|
|
214
|
-
? "dx-sidebar-old"
|
|
215
|
-
: "dx-sidebar";
|
|
216
|
-
const sidebarEl = this.template.querySelector(sidebarType);
|
|
229
|
+
const sidebarEl = this.template.querySelector("dx-sidebar-old");
|
|
217
230
|
const globalNavEl = document.querySelector(
|
|
218
231
|
"hgf-c360nav"
|
|
219
232
|
) as HTMLElement;
|
|
@@ -224,15 +237,20 @@ export default class ContentLayout extends LightningElement {
|
|
|
224
237
|
".sticky-doc-header"
|
|
225
238
|
) as HTMLElement;
|
|
226
239
|
|
|
227
|
-
|
|
228
|
-
|
|
240
|
+
const docPhaseWrapper = this.template.querySelector(
|
|
241
|
+
".doc-phase-wrapper"
|
|
242
|
+
) as HTMLElement;
|
|
243
|
+
const versionWrapper = this.template.querySelector(
|
|
244
|
+
".version-wrapper"
|
|
245
|
+
) as HTMLElement;
|
|
246
|
+
|
|
247
|
+
const docPhaseEl = (
|
|
248
|
+
docPhaseWrapper.querySelector("[name=doc-phase]")! as any
|
|
229
249
|
).assignedElements()[0] as HTMLSlotElement;
|
|
230
250
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
).assignedElements()[0] as HTMLSlotElement;
|
|
235
|
-
}
|
|
251
|
+
const verBannerEl = (
|
|
252
|
+
versionWrapper.querySelector("[name=version-banner]")! as any
|
|
253
|
+
).assignedElements()[0] as HTMLSlotElement;
|
|
236
254
|
|
|
237
255
|
if (!sidebarEl || !globalNavEl || !contextNavEl || !docHeaderEl) {
|
|
238
256
|
console.warn("One or more required elements are missing.");
|
|
@@ -264,39 +282,54 @@ export default class ContentLayout extends LightningElement {
|
|
|
264
282
|
`${globalNavHeight}px`
|
|
265
283
|
);
|
|
266
284
|
|
|
285
|
+
const docPhaseElHeight =
|
|
286
|
+
docPhaseEl || verBannerEl
|
|
287
|
+
? (docPhaseEl || verBannerEl).getBoundingClientRect().height
|
|
288
|
+
: 0;
|
|
289
|
+
|
|
267
290
|
// Adjusting the doc section heading on scroll.
|
|
268
291
|
docHeadingEls.forEach((docHeadingEl) => {
|
|
269
|
-
(docHeadingEl as any).style.scrollMarginTop =
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
docPhaseEl.getBoundingClientRect().height +
|
|
273
|
-
40
|
|
274
|
-
}px`
|
|
275
|
-
: `${totalHeaderHeight + 40}px`;
|
|
292
|
+
(docHeadingEl as any).style.scrollMarginTop = `${
|
|
293
|
+
totalHeaderHeight + docPhaseElHeight + 40
|
|
294
|
+
}px`;
|
|
276
295
|
});
|
|
277
296
|
|
|
278
297
|
// Adjusting the right nav bar on scroll.
|
|
298
|
+
// setting maxheight to make the RNB scrollable based on different parent elements
|
|
279
299
|
if (rightNavBarEl) {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
300
|
+
const viewportHeight = window.innerHeight;
|
|
301
|
+
const maxHeight =
|
|
302
|
+
viewportHeight -
|
|
303
|
+
(docPhaseElHeight + totalHeaderHeight + 24); //added some margin of dx-toc
|
|
304
|
+
|
|
305
|
+
rightNavBarEl.style.top = `${
|
|
306
|
+
totalHeaderHeight + docPhaseElHeight
|
|
307
|
+
}px`;
|
|
308
|
+
|
|
309
|
+
const toc = rightNavBarEl.querySelector("dx-toc");
|
|
310
|
+
const listContainer = toc?.shadowRoot?.querySelector(
|
|
311
|
+
".toc"
|
|
312
|
+
) as HTMLElement;
|
|
313
|
+
|
|
314
|
+
if (listContainer) {
|
|
315
|
+
listContainer.style.maxHeight = `${maxHeight}px`;
|
|
316
|
+
}
|
|
286
317
|
}
|
|
287
318
|
|
|
319
|
+
const docPhaseTop =
|
|
320
|
+
window.innerWidth < 769
|
|
321
|
+
? globalNavHeight +
|
|
322
|
+
docHeaderHeight +
|
|
323
|
+
sidebarEl.getBoundingClientRect().height
|
|
324
|
+
: globalNavHeight + docHeaderHeight;
|
|
325
|
+
|
|
288
326
|
// If doc phase element exists, we need to account for its sticky position. Mobile should include the sidebar height (since it becomes sticky aswell).
|
|
327
|
+
// To handle sticky position for safari browser, position sticky given to wrapper class
|
|
289
328
|
if (docPhaseEl) {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
? globalNavHeight +
|
|
295
|
-
docHeaderHeight +
|
|
296
|
-
sidebarEl.getBoundingClientRect().height
|
|
297
|
-
: globalNavHeight + docHeaderHeight
|
|
298
|
-
}px`
|
|
299
|
-
);
|
|
329
|
+
docPhaseWrapper.style.top = `${docPhaseTop}px`;
|
|
330
|
+
} else if (verBannerEl) {
|
|
331
|
+
versionWrapper.style.position = "sticky";
|
|
332
|
+
versionWrapper.style.top = `${docPhaseTop}px`;
|
|
300
333
|
}
|
|
301
334
|
});
|
|
302
335
|
};
|
|
@@ -366,19 +399,25 @@ export default class ContentLayout extends LightningElement {
|
|
|
366
399
|
updateTocItems(headingElements: any): void {
|
|
367
400
|
const tocOptions = [];
|
|
368
401
|
|
|
402
|
+
const maxLevel = Number.parseInt(this.tocAriaLevel, 10) || 2;
|
|
403
|
+
const minLevel = 2;
|
|
404
|
+
|
|
369
405
|
for (const headingElement of headingElements as any) {
|
|
370
406
|
headingElement.id = headingElement.hash;
|
|
371
407
|
|
|
372
|
-
// Update tocOptions from anchorTags
|
|
408
|
+
// Update tocOptions from anchorTags for aria-levels 2..tocAriaLevel (inclusive)
|
|
373
409
|
const headingAriaLevel =
|
|
374
410
|
headingElement.attributes["aria-level"]?.nodeValue || "2";
|
|
375
|
-
const
|
|
411
|
+
const headingLevel = Number.parseInt(headingAriaLevel, 10) || 2;
|
|
412
|
+
const matchesLevel =
|
|
413
|
+
headingLevel >= minLevel && headingLevel <= maxLevel;
|
|
376
414
|
|
|
377
|
-
if (
|
|
415
|
+
if (matchesLevel) {
|
|
378
416
|
const tocItem = {
|
|
379
417
|
anchor: `#${headingElement.hash}`,
|
|
380
418
|
id: headingElement.id,
|
|
381
|
-
label: headingElement.header
|
|
419
|
+
label: headingElement.header,
|
|
420
|
+
level: headingLevel
|
|
382
421
|
};
|
|
383
422
|
tocOptions.push(tocItem);
|
|
384
423
|
this.tocOptionIdsSet.add(headingElement.id);
|
|
@@ -8,7 +8,11 @@
|
|
|
8
8
|
></dx-banner>
|
|
9
9
|
<!-- To-Do: Move the devCenter as a new component and use it here, as devCenter is also used in Sidebar now -->
|
|
10
10
|
<div lwc:if={devCenter} class="dev-center-link">
|
|
11
|
-
<a
|
|
11
|
+
<a
|
|
12
|
+
href={devCenter.link}
|
|
13
|
+
onclick={onLinkClick}
|
|
14
|
+
class="dev-center-content"
|
|
15
|
+
>
|
|
12
16
|
<dx-icon symbol="back"></dx-icon>
|
|
13
17
|
<dx-icon
|
|
14
18
|
class="brand-icon"
|
|
@@ -3,6 +3,7 @@ import cx from "classnames";
|
|
|
3
3
|
import type { OptionWithNested, DevCenterConfig } from "typings/custom";
|
|
4
4
|
import { HeaderBase } from "dxBaseElements/headerBase";
|
|
5
5
|
import { toJson, normalizeBoolean } from "dxUtils/normalizers";
|
|
6
|
+
import { track } from "dxUtils/analytics";
|
|
6
7
|
|
|
7
8
|
const TABLET_MATCH = "980px";
|
|
8
9
|
const MOBILE_MATCH = "768px";
|
|
@@ -117,4 +118,13 @@ export default class Header extends HeaderBase {
|
|
|
117
118
|
this.showScopedNavItems && "has-scoped-nav-items"
|
|
118
119
|
);
|
|
119
120
|
}
|
|
121
|
+
|
|
122
|
+
private onLinkClick(event: Event): void {
|
|
123
|
+
track(event.target!, "custEv_linkClick", {
|
|
124
|
+
click_text: this.devCenter.title,
|
|
125
|
+
click_url: this.devCenter.link,
|
|
126
|
+
element_type: "link",
|
|
127
|
+
content_category: "dev-center"
|
|
128
|
+
});
|
|
129
|
+
}
|
|
120
130
|
}
|
|
@@ -1,58 +1,54 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="content">
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
>
|
|
17
|
-
|
|
18
|
-
</dx-sidebar-old>
|
|
19
|
-
</template>
|
|
20
|
-
<template lwc:else>
|
|
21
|
-
<dx-sidebar
|
|
22
|
-
class="is-sticky left-nav-bar"
|
|
23
|
-
trees={sidebarContent}
|
|
24
|
-
value={sidebarValue}
|
|
25
|
-
header={sidebarHeader}
|
|
26
|
-
coveo-organization-id={coveoOrganizationId}
|
|
27
|
-
coveo-public-access-token={coveoPublicAccessToken}
|
|
28
|
-
coveo-search-hub={coveoSearchHub}
|
|
29
|
-
coveo-advanced-query-config={coveoAdvancedQueryConfig}
|
|
30
|
-
ontogglesidebar={onToggleSidebar}
|
|
31
|
-
languages={languages}
|
|
32
|
-
language={language}
|
|
33
|
-
bail-href={bailHref}
|
|
34
|
-
bail-label={bailLabel}
|
|
35
|
-
dev-center={devCenter}
|
|
36
|
-
brand={brand}
|
|
37
|
-
>
|
|
38
|
-
<slot name="sidebar-header" slot="version-picker"></slot>
|
|
39
|
-
</dx-sidebar>
|
|
40
|
-
</template>
|
|
3
|
+
<dx-sidebar-old
|
|
4
|
+
class="is-sticky left-nav-bar"
|
|
5
|
+
trees={sidebarContent}
|
|
6
|
+
value={sidebarValue}
|
|
7
|
+
header={sidebarHeader}
|
|
8
|
+
ontogglesidebar={onToggleSidebar}
|
|
9
|
+
languages={languages}
|
|
10
|
+
language={language}
|
|
11
|
+
bail-href={bailHref}
|
|
12
|
+
bail-label={bailLabel}
|
|
13
|
+
dev-center={devCenter}
|
|
14
|
+
brand={brand}
|
|
15
|
+
>
|
|
16
|
+
<slot name="sidebar-header" slot="version-picker"></slot>
|
|
17
|
+
</dx-sidebar-old>
|
|
41
18
|
<div class="content-body-doc-phase-container">
|
|
42
|
-
<
|
|
43
|
-
|
|
19
|
+
<div class="doc-phase-wrapper">
|
|
20
|
+
<slot name="doc-phase"></slot>
|
|
21
|
+
</div>
|
|
22
|
+
<div class="version-wrapper">
|
|
23
|
+
<slot name="version-banner"></slot>
|
|
24
|
+
</div>
|
|
44
25
|
<div class="content-body-container">
|
|
45
|
-
<div class=
|
|
26
|
+
<div class={contentBodyClasses}>
|
|
46
27
|
<doc-breadcrumbs
|
|
47
28
|
lwc:if={showBreadcrumbs}
|
|
48
29
|
breadcrumbs={breadcrumbs}
|
|
49
30
|
></doc-breadcrumbs>
|
|
31
|
+
<div class="read" lwc:if={showReadingTime}>
|
|
32
|
+
<svg
|
|
33
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
34
|
+
width="18"
|
|
35
|
+
height="18"
|
|
36
|
+
viewBox="0 0 52 52"
|
|
37
|
+
>
|
|
38
|
+
<g fill="#3e3e3c">
|
|
39
|
+
<path
|
|
40
|
+
d="m26 2c-13.2 0-24 10.8-24 24s10.8 24 24 24 24-10.8 24-24-10.8-24-24-24z m0 42c-9.9 0-18-8.1-18-18s8.1-18 18-18 18 8.1 18 18-8.1 18-18 18z m3.4-17.8c-0.3-0.3-0.4-0.7-0.4-1.1v-9.6c0-0.8-0.7-1.5-1.5-1.5h-3c-0.8 0-1.5 0.7-1.5 1.5v12.1c0 0.4 0.2 0.8 0.4 1.1l7.4 7.4c0.6 0.6 1.5 0.6 2.1 0l2.1-2.1c0.6-0.6 0.6-1.5 0-2.1l-5.6-5.7z"
|
|
41
|
+
></path>
|
|
42
|
+
</g>
|
|
43
|
+
</svg>
|
|
44
|
+
{readingTime} minute read
|
|
45
|
+
</div>
|
|
50
46
|
<slot onslotchange={onSlotChange}></slot>
|
|
51
47
|
<doc-sprig-survey
|
|
52
48
|
lwc:if={shouldDisplayFeedback}
|
|
53
49
|
></doc-sprig-survey>
|
|
54
50
|
</div>
|
|
55
|
-
<div lwc:if={showToc} class=
|
|
51
|
+
<div lwc:if={showToc} class={rightNavBarClasses}>
|
|
56
52
|
<dx-toc
|
|
57
53
|
header={tocTitle}
|
|
58
54
|
options={tocOptions}
|
|
@@ -1,45 +1,125 @@
|
|
|
1
1
|
import ContentLayout from "doc/contentLayout";
|
|
2
|
+
import cx from "classnames";
|
|
2
3
|
|
|
3
4
|
const TOC_HEADER_TAG = "doc-heading";
|
|
4
5
|
const RNB_BY_TAB = "docs-tab";
|
|
5
|
-
const
|
|
6
|
+
const SPECIFICATION_TAG = "doc-specification-content";
|
|
6
7
|
export const OBSERVER_ATTACH_WAIT_TIME = 500;
|
|
7
8
|
|
|
8
9
|
export default class LwcContentLayout extends ContentLayout {
|
|
9
10
|
private rnbByTab: boolean = false;
|
|
10
11
|
|
|
12
|
+
// DOM element caches to avoid repeated queries
|
|
13
|
+
private tabPanelListCache: any = null;
|
|
14
|
+
private hasSpecContentCache: boolean | null = null;
|
|
15
|
+
private allTabsCache: any[] | null = null;
|
|
16
|
+
private mainSlotCache: any = null;
|
|
17
|
+
|
|
11
18
|
private setRNBByTab() {
|
|
12
|
-
const tabPanelListItem
|
|
13
|
-
this.rnbByTab = tabPanelListItem?.id === RNB_BY_TAB
|
|
19
|
+
const tabPanelListItem = this.getTabPanelList();
|
|
20
|
+
this.rnbByTab = tabPanelListItem?.id === RNB_BY_TAB;
|
|
14
21
|
}
|
|
15
22
|
|
|
16
23
|
get showTabBasedRNB() {
|
|
17
24
|
return this.rnbByTab;
|
|
18
25
|
}
|
|
19
26
|
|
|
27
|
+
get rightNavBarClasses() {
|
|
28
|
+
return cx(
|
|
29
|
+
"right-nav-bar",
|
|
30
|
+
"is-sticky",
|
|
31
|
+
this.showTabBasedRNB && "fixed-right-nav-bar"
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
get contentBodyClasses() {
|
|
36
|
+
return cx("content-body", !this.showToc && "content-body-no-rnb");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Check if the main slot contains doc-specification-content
|
|
41
|
+
* Uses caching to avoid repeated DOM queries
|
|
42
|
+
*/
|
|
43
|
+
private hasSpecificationContent(): boolean {
|
|
44
|
+
if (this.hasSpecContentCache !== null) {
|
|
45
|
+
return this.hasSpecContentCache;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const mainSlot = this.getMainSlot();
|
|
49
|
+
if (mainSlot) {
|
|
50
|
+
const assignedElements = (mainSlot as any).assignedElements();
|
|
51
|
+
|
|
52
|
+
for (const element of assignedElements) {
|
|
53
|
+
if (
|
|
54
|
+
element.tagName === SPECIFICATION_TAG ||
|
|
55
|
+
element.querySelector(SPECIFICATION_TAG) ||
|
|
56
|
+
element.shadowRoot?.querySelector(SPECIFICATION_TAG)
|
|
57
|
+
) {
|
|
58
|
+
return (this.hasSpecContentCache = true);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return (this.hasSpecContentCache = false);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Clear all caches when content changes
|
|
67
|
+
*/
|
|
68
|
+
private clearAllCaches(): void {
|
|
69
|
+
this.hasSpecContentCache = null;
|
|
70
|
+
this.tabPanelListCache = null;
|
|
71
|
+
this.allTabsCache = null;
|
|
72
|
+
this.mainSlotCache = null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Get the main slot element with caching
|
|
77
|
+
*/
|
|
78
|
+
private getMainSlot(): any {
|
|
79
|
+
if (!this.mainSlotCache) {
|
|
80
|
+
this.mainSlotCache =
|
|
81
|
+
this.template.querySelector("slot:not([name])");
|
|
82
|
+
}
|
|
83
|
+
return this.mainSlotCache;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Get tab panel list with caching
|
|
88
|
+
*/
|
|
89
|
+
private getTabPanelList(): any {
|
|
90
|
+
if (!this.tabPanelListCache) {
|
|
91
|
+
// eslint-disable-next-line @lwc/lwc/no-document-query
|
|
92
|
+
this.tabPanelListCache =
|
|
93
|
+
document.querySelector("dx-tab-panel-list");
|
|
94
|
+
}
|
|
95
|
+
return this.tabPanelListCache;
|
|
96
|
+
}
|
|
97
|
+
|
|
20
98
|
onRNBClick = (event: CustomEvent) => {
|
|
21
99
|
event.stopPropagation();
|
|
22
|
-
|
|
23
|
-
if (currentTab === SPECIFICATION_TAB_TITLE) {
|
|
100
|
+
if (this.hasSpecificationContent()) {
|
|
24
101
|
this.didScrollToSelectedHash = false;
|
|
25
102
|
}
|
|
26
103
|
};
|
|
27
104
|
|
|
28
105
|
onTabChanged = () => {
|
|
29
106
|
this.updateRNB();
|
|
30
|
-
};
|
|
31
107
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
108
|
+
const { hash } = window.location;
|
|
109
|
+
if (this.hasSpecificationContent() && hash) {
|
|
110
|
+
this.didScrollToSelectedHash = false;
|
|
111
|
+
|
|
112
|
+
requestAnimationFrame(() => this.updateHeadingForRNB());
|
|
113
|
+
}
|
|
114
|
+
};
|
|
36
115
|
|
|
37
116
|
protected getHeadingElements() {
|
|
38
117
|
let headingElements = super.getHeadingElements();
|
|
39
118
|
if (this.showTabBasedRNB) {
|
|
40
|
-
const tabPanelListItem
|
|
119
|
+
const tabPanelListItem = this.getTabPanelList();
|
|
41
120
|
const tabPanels =
|
|
42
121
|
tabPanelListItem?.querySelectorAll("dx-tab-panel");
|
|
122
|
+
|
|
43
123
|
for (const tabPanelItem of tabPanels) {
|
|
44
124
|
if (tabPanelItem.active) {
|
|
45
125
|
// This is needed for Specification tab content
|
|
@@ -65,6 +145,7 @@ export default class LwcContentLayout extends ContentLayout {
|
|
|
65
145
|
private updateURL() {
|
|
66
146
|
const tabs = this.getAllTabs();
|
|
67
147
|
const selectedTabId = this.getSelectedTabId();
|
|
148
|
+
|
|
68
149
|
tabs.forEach((tab: any) => {
|
|
69
150
|
if (tab.getAttribute("aria-selected") === "true") {
|
|
70
151
|
const tabID = tab.getAttribute("aria-label");
|
|
@@ -101,22 +182,38 @@ export default class LwcContentLayout extends ContentLayout {
|
|
|
101
182
|
const selectedTabId = this.getSelectedTabId();
|
|
102
183
|
if (selectedTabId) {
|
|
103
184
|
this.selectTabById(selectedTabId);
|
|
185
|
+
|
|
186
|
+
// If there's a hash and we have specification content,
|
|
187
|
+
// we need to wait for the content to load before scrolling
|
|
188
|
+
const { hash } = window.location;
|
|
189
|
+
if (this.hasSpecificationContent() && hash) {
|
|
190
|
+
// Reset the scroll flag to allow scrolling once content is loaded
|
|
191
|
+
this.didScrollToSelectedHash = false;
|
|
192
|
+
}
|
|
104
193
|
}
|
|
105
194
|
});
|
|
106
195
|
}
|
|
107
196
|
|
|
108
197
|
private getAllTabs(): any[] {
|
|
109
|
-
|
|
198
|
+
// Return cached result if available
|
|
199
|
+
if (this.allTabsCache) {
|
|
200
|
+
return this.allTabsCache;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const tabPanelListItem = this.getTabPanelList();
|
|
110
204
|
if (tabPanelListItem?.shadowRoot) {
|
|
111
|
-
|
|
205
|
+
this.allTabsCache = Array.from(
|
|
112
206
|
tabPanelListItem.shadowRoot.querySelectorAll(
|
|
113
207
|
"dx-tab-panel-item"
|
|
114
208
|
)
|
|
115
209
|
).map((tabPanelItem: any) =>
|
|
116
210
|
tabPanelItem.shadowRoot.querySelector("button")
|
|
117
211
|
);
|
|
212
|
+
} else {
|
|
213
|
+
this.allTabsCache = [];
|
|
118
214
|
}
|
|
119
|
-
|
|
215
|
+
|
|
216
|
+
return this.allTabsCache;
|
|
120
217
|
}
|
|
121
218
|
|
|
122
219
|
private selectTabById(tabId: string) {
|
|
@@ -158,8 +255,12 @@ export default class LwcContentLayout extends ContentLayout {
|
|
|
158
255
|
}
|
|
159
256
|
}
|
|
160
257
|
|
|
258
|
+
onSlotChange(): void {
|
|
259
|
+
this.clearAllCaches();
|
|
260
|
+
super.onSlotChange();
|
|
261
|
+
}
|
|
262
|
+
|
|
161
263
|
updateHeadingForRNB(): void {
|
|
162
|
-
// We only need to update URL in case of /docs and ignore if tabs are used anywhere else in DSC
|
|
163
264
|
if (this.showTabBasedRNB) {
|
|
164
265
|
this.updateURL();
|
|
165
266
|
}
|
|
@@ -3,14 +3,7 @@
|
|
|
3
3
|
@import "docHelpers/status";
|
|
4
4
|
|
|
5
5
|
:host {
|
|
6
|
-
--doc-c-phase-top: 0;
|
|
7
6
|
--doc-c-phase-container-align-items: flex-start;
|
|
8
|
-
|
|
9
|
-
position: sticky;
|
|
10
|
-
top: var(--doc-c-phase-top);
|
|
11
|
-
|
|
12
|
-
/* NOTE: If you are changing z-index value here, ensure it's less than z-index of dx-sidebar in contentLayout.css */
|
|
13
|
-
z-index: var(--dx-g-z-index-100);
|
|
14
7
|
}
|
|
15
8
|
|
|
16
9
|
.doc-phase-container {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<template lwc:if={showError}>
|
|
3
|
+
<dx-error
|
|
4
|
+
header="We lost communication with the space station."
|
|
5
|
+
subtitle="We encountered a server-related issue. (Don't worry, we're on it.) Refresh your browser or try again later."
|
|
6
|
+
image=""
|
|
7
|
+
code="500"
|
|
8
|
+
></dx-error>
|
|
9
|
+
</template>
|
|
10
|
+
<template lwc:else>
|
|
11
|
+
<slot></slot>
|
|
12
|
+
</template>
|
|
13
|
+
</template>
|