@salesforcedevs/docs-components 0.56.2-comp-flex-ref-1 → 0.56.2-example

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.
Files changed (77) hide show
  1. package/lwc.config.json +10 -2
  2. package/package.json +18 -12
  3. package/src/modules/doc/{amfReference/utils.ts → amfModelParser/amfModelParser.ts} +10 -5
  4. package/src/modules/doc/amfReference/amfReference.css +23 -3
  5. package/src/modules/doc/amfReference/amfReference.html +34 -21
  6. package/src/modules/doc/amfReference/amfReference.ts +386 -102
  7. package/src/modules/doc/amfReference/types.ts +5 -12
  8. package/src/modules/doc/amfTopic/amfTopic.css +20 -0
  9. package/src/modules/doc/amfTopic/amfTopic.ts +35 -18
  10. package/src/modules/doc/amfTopic/types.ts +15 -13
  11. package/src/modules/doc/amfTopic/utils.ts +12 -6
  12. package/src/modules/doc/breadcrumbItem/breadcrumbItem.css +2 -1
  13. package/src/modules/doc/breadcrumbItem/breadcrumbItem.html +1 -1
  14. package/src/modules/doc/breadcrumbItem/breadcrumbItem.ts +22 -0
  15. package/src/modules/doc/breadcrumbs/breadcrumbs.css +9 -1
  16. package/src/modules/doc/breadcrumbs/breadcrumbs.html +44 -34
  17. package/src/modules/doc/breadcrumbs/breadcrumbs.ts +62 -23
  18. package/src/modules/doc/componentPlayground/componentPlayground.css +22 -0
  19. package/src/modules/doc/componentPlayground/componentPlayground.html +20 -0
  20. package/src/modules/doc/componentPlayground/componentPlayground.ts +42 -0
  21. package/src/modules/doc/content/content.css +70 -76
  22. package/src/modules/doc/content/content.html +1 -0
  23. package/src/modules/doc/content/content.ts +26 -47
  24. package/src/modules/doc/contentCallout/contentCallout.css +15 -7
  25. package/src/modules/doc/contentCallout/contentCallout.html +13 -4
  26. package/src/modules/doc/contentCallout/contentCallout.ts +14 -2
  27. package/src/modules/doc/contentLayout/contentLayout.css +1 -100
  28. package/src/modules/doc/contentLayout/contentLayout.html +30 -17
  29. package/src/modules/doc/contentLayout/contentLayout.ts +315 -70
  30. package/src/modules/doc/doDont/doDont.css +47 -0
  31. package/src/modules/doc/doDont/doDont.html +27 -0
  32. package/src/modules/doc/doDont/doDont.ts +17 -0
  33. package/src/modules/doc/header/header.css +65 -36
  34. package/src/modules/doc/header/header.html +41 -139
  35. package/src/modules/doc/header/header.ts +54 -76
  36. package/src/modules/doc/heading/heading.css +16 -37
  37. package/src/modules/doc/heading/heading.html +4 -4
  38. package/src/modules/doc/heading/heading.ts +12 -10
  39. package/src/modules/doc/headingAnchor/headingAnchor.css +2 -2
  40. package/src/modules/doc/headingAnchor/headingAnchor.ts +2 -2
  41. package/src/modules/doc/headingContent/headingContent.css +6 -8
  42. package/src/modules/doc/headingContent/headingContent.html +9 -15
  43. package/src/modules/doc/headingContent/headingContent.ts +2 -14
  44. package/src/modules/doc/lwcContentLayout/lwcContentLayout.css +1 -0
  45. package/src/modules/doc/lwcContentLayout/lwcContentLayout.html +68 -0
  46. package/src/modules/doc/lwcContentLayout/lwcContentLayout.ts +256 -0
  47. package/src/modules/doc/overview/overview.css +40 -0
  48. package/src/modules/doc/overview/overview.html +34 -0
  49. package/src/modules/doc/overview/overview.ts +12 -0
  50. package/src/modules/doc/phase/phase.css +18 -3
  51. package/src/modules/doc/phase/phase.html +15 -3
  52. package/src/modules/doc/phase/phase.ts +44 -8
  53. package/src/modules/doc/specificationContent/specificationContent.css +36 -0
  54. package/src/modules/doc/specificationContent/specificationContent.html +167 -0
  55. package/src/modules/doc/specificationContent/specificationContent.ts +127 -0
  56. package/src/modules/doc/sprigSurvey/sprigSurvey.html +20 -0
  57. package/src/modules/doc/sprigSurvey/sprigSurvey.scoped.css +16 -0
  58. package/src/modules/doc/sprigSurvey/sprigSurvey.ts +16 -0
  59. package/src/modules/doc/toc/toc.ts +1 -1
  60. package/src/modules/doc/versionPicker/versionPicker.css +64 -0
  61. package/src/modules/doc/versionPicker/versionPicker.html +38 -0
  62. package/src/modules/doc/versionPicker/versionPicker.ts +65 -0
  63. package/src/modules/doc/xmlContent/types.ts +12 -3
  64. package/src/modules/doc/xmlContent/utils.ts +17 -12
  65. package/src/modules/doc/xmlContent/xmlContent.css +32 -3
  66. package/src/modules/doc/xmlContent/xmlContent.html +41 -15
  67. package/src/modules/doc/xmlContent/xmlContent.ts +310 -96
  68. package/src/modules/docHelpers/amfStyle/amfStyle.css +10 -45
  69. package/src/modules/docHelpers/contentLayoutStyle/contentLayoutStyle.css +131 -0
  70. package/src/modules/docHelpers/imgStyle/imgStyle.css +59 -0
  71. package/src/modules/docHelpers/status/status.css +1 -1
  72. package/src/modules/docUtils/{SearchSyncer/SearchSyncer.ts → searchSyncer/searchSyncer.ts} +1 -0
  73. package/src/modules/docUtils/utils/__mocks__/coveo.analytics.ts +16 -0
  74. package/src/modules/docUtils/utils/coveo.analytics.d.ts +10 -0
  75. package/src/modules/docUtils/utils/utils.ts +32 -0
  76. package/src/modules/docBaseElements/lightningElementWithState/lightningElementWithState.ts +0 -93
  77. package/src/modules/docHelpers/phaseContentLayout/phaseContentLayout.css +0 -39
@@ -1,16 +1,23 @@
1
1
  <template>
2
2
  <div class="content">
3
- <template if:true={useOldSidebar}>
3
+ <template lwc:if={useOldSidebar}>
4
4
  <dx-sidebar-old
5
5
  class="is-sticky left-nav-bar"
6
6
  trees={sidebarContent}
7
7
  value={sidebarValue}
8
8
  header={sidebarHeader}
9
+ ontogglesidebar={onToggleSidebar}
10
+ languages={languages}
11
+ language={language}
12
+ bail-href={bailHref}
13
+ bail-label={bailLabel}
14
+ dev-center={devCenter}
15
+ brand={brand}
9
16
  >
10
- <slot name="sidebar-header" slot="header"></slot>
17
+ <slot name="sidebar-header" slot="version-picker"></slot>
11
18
  </dx-sidebar-old>
12
19
  </template>
13
- <template if:false={useOldSidebar}>
20
+ <template lwc:else>
14
21
  <dx-sidebar
15
22
  class="is-sticky left-nav-bar"
16
23
  trees={sidebarContent}
@@ -20,36 +27,42 @@
20
27
  coveo-public-access-token={coveoPublicAccessToken}
21
28
  coveo-search-hub={coveoSearchHub}
22
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}
23
37
  >
24
- <slot name="sidebar-header" slot="header"></slot>
38
+ <slot name="sidebar-header" slot="version-picker"></slot>
25
39
  </dx-sidebar>
26
40
  </template>
27
41
  <div class="content-body-doc-phase-container">
28
42
  <slot name="doc-phase"></slot>
43
+ <slot name="version-banner"></slot>
29
44
  <div class="content-body-container">
30
45
  <div class="content-body">
31
- <dx-breadcrumbs
32
- if:true={breadcrumbs}
46
+ <doc-breadcrumbs
47
+ lwc:if={showBreadcrumbs}
33
48
  breadcrumbs={breadcrumbs}
34
- truncate
35
- hide-current-location
36
- ></dx-breadcrumbs>
37
- <dx-breadcrumbs
38
- if:false={breadcrumbs}
39
- pathname={pathname}
40
- hide-current-location
41
- ></dx-breadcrumbs>
49
+ ></doc-breadcrumbs>
42
50
  <slot onslotchange={onSlotChange}></slot>
51
+ <doc-sprig-survey
52
+ lwc:if={shouldDisplayFeedback}
53
+ ></doc-sprig-survey>
43
54
  </div>
44
- <div class="right-nav-bar is-sticky">
55
+ <div lwc:if={showToc} class="right-nav-bar is-sticky">
45
56
  <dx-toc
46
- if:true={showToc}
47
- title={tocTitle}
57
+ header={tocTitle}
48
58
  options={tocOptions}
49
59
  value={tocValue}
50
60
  ></dx-toc>
51
61
  </div>
52
62
  </div>
63
+ <div lwc:if={showFooter} class="footer-container">
64
+ <dx-footer variant="no-signup"></dx-footer>
65
+ </div>
53
66
  </div>
54
67
  </div>
55
68
  </template>
@@ -1,12 +1,17 @@
1
+ /* eslint-disable @lwc/lwc/no-document-query */
1
2
  import { LightningElement, api, track } from "lwc";
2
3
  import { closest } from "kagekiri";
3
4
  import { toJson } from "dxUtils/normalizers";
4
5
  import { highlightTerms } from "dxUtils/highlight";
5
- import { SearchSyncer } from "docUtils/SearchSyncer";
6
+ import { SearchSyncer } from "docUtils/searchSyncer";
7
+ import type { OptionWithLink } from "typings/custom";
6
8
 
7
9
  type AnchorMap = { [key: string]: { intersect: boolean; id: string } };
8
10
 
9
- const TOC_HEADER_TAG = "DOC-HEADING";
11
+ declare const Sprig: (eventType: string, eventNme: string) => void;
12
+
13
+ const TOC_HEADER_TAG = "doc-heading";
14
+
10
15
  const HIGHLIGHTABLE_SELECTOR = [
11
16
  "p",
12
17
  "h1",
@@ -20,18 +25,28 @@ const HIGHLIGHTABLE_SELECTOR = [
20
25
  "th",
21
26
  "td"
22
27
  ].join(",");
23
- const OBSERVER_ATTACH_WAIT_TIME = 500;
28
+ export const OBSERVER_ATTACH_WAIT_TIME = 500;
24
29
 
25
30
  export default class ContentLayout extends LightningElement {
26
- @api sidebarValue: string;
27
- @api sidebarHeader: string;
28
- @api tocTitle: string;
31
+ @api sidebarValue!: string;
32
+ @api sidebarHeader!: string;
33
+ @api tocTitle!: string;
29
34
  @api enableSlotChange = false;
30
35
  @api coveoOrganizationId!: string;
31
36
  @api coveoPublicAccessToken!: string;
37
+ @api coveoAnalyticsToken!: string;
32
38
  @api coveoSearchHub!: string;
33
39
  @api coveoAdvancedQueryConfig!: string;
34
40
  @api useOldSidebar?: boolean = false;
41
+ @api languages!: OptionWithLink[];
42
+ @api language!: string;
43
+ @api bailHref!: string;
44
+ @api bailLabel!: string;
45
+ @api devCenter: any;
46
+ @api brand: any;
47
+
48
+ // This is needed for now to prevent failing snapshot tests due to links in the footer
49
+ @api showFooter = false;
35
50
 
36
51
  @api
37
52
  get breadcrumbs() {
@@ -49,7 +64,7 @@ export default class ContentLayout extends LightningElement {
49
64
  return this._sidebarContent;
50
65
  }
51
66
 
52
- set sidebarContent(value) {
67
+ set sidebarContent(value: any) {
53
68
  this._sidebarContent = toJson(value);
54
69
  }
55
70
 
@@ -64,25 +79,33 @@ export default class ContentLayout extends LightningElement {
64
79
 
65
80
  @api
66
81
  setSidebarInputValue(searchTerm: string): void {
67
- this.template.querySelector("dx-sidebar")?.setInputValue(searchTerm);
82
+ (this.template.querySelector("dx-sidebar") as any)?.setInputValue(
83
+ searchTerm
84
+ );
68
85
  }
69
86
 
70
87
  @track
71
- private _sidebarContent: unknown;
88
+ protected _sidebarContent: unknown;
72
89
 
73
- private _breadcrumbs = null;
90
+ protected _breadcrumbs = null;
74
91
 
75
92
  @track
76
- private _tocOptions: Array<unknown>;
93
+ protected _tocOptions!: Array<unknown>;
94
+
95
+ protected tocOptionIdsSet = new Set();
96
+ protected anchoredElements: AnchorMap = {};
97
+ protected lastScrollPosition!: number;
98
+ protected observer?: IntersectionObserver;
99
+ protected hasRendered: boolean = false;
100
+ protected contentLoaded: boolean = false;
101
+ protected sidebarOpen: boolean = false;
102
+
103
+ get shouldDisplayFeedback() {
104
+ return this.contentLoaded && typeof Sprig !== "undefined";
105
+ }
77
106
 
78
- private anchoredElements: AnchorMap = {};
79
- private lastScrollPosition: number;
80
- private observer?: IntersectionObserver;
81
- private searchSyncer = new SearchSyncer({
107
+ protected searchSyncer = new SearchSyncer({
82
108
  callbacks: {
83
- onUrlChange: (nextSearchString: string): void => {
84
- this.updateHighlightsAndSearch(nextSearchString);
85
- },
86
109
  onSearchChange: (nextSearchString: string): void => {
87
110
  this.dispatchHighlightChange(
88
111
  new URLSearchParams(nextSearchString).get("q") || ""
@@ -95,9 +118,11 @@ export default class ContentLayout extends LightningElement {
95
118
  shouldStopPropagation: true,
96
119
  target: window
97
120
  });
98
- private tocValue?: string = undefined;
99
- private observerTimerId = null;
100
- private didScrollToSelectedHash = false;
121
+ protected tocValue?: string = undefined;
122
+ // eslint-disable-next-line no-undef
123
+ protected observerTimerId?: NodeJS.Timeout;
124
+ protected didScrollToSelectedHash = false;
125
+ protected _scrollInterval = 0;
101
126
 
102
127
  get showToc(): boolean {
103
128
  return this.tocOptions && this.tocOptions.length > 0;
@@ -108,6 +133,12 @@ export default class ContentLayout extends LightningElement {
108
133
  return window.location.pathname;
109
134
  }
110
135
 
136
+ get showBreadcrumbs(): boolean {
137
+ return (
138
+ this.breadcrumbs != null && (this.breadcrumbs as any[]).length > 1
139
+ );
140
+ }
141
+
111
142
  connectedCallback(): void {
112
143
  const hasParentHighlightListener = closest(
113
144
  "doc-xml-content",
@@ -122,6 +153,9 @@ export default class ContentLayout extends LightningElement {
122
153
  }
123
154
  }
124
155
 
156
+ // Placeholder for childs renderedCallback
157
+ protected postRenderedCallback?(): void;
158
+
125
159
  renderedCallback(): void {
126
160
  /**
127
161
  * Note: We are adding timeout because chrome is optimizing and not triggering recent renderedCallback though elements reference is changed
@@ -132,6 +166,18 @@ export default class ContentLayout extends LightningElement {
132
166
  this.attachInteractionObserver,
133
167
  OBSERVER_ATTACH_WAIT_TIME
134
168
  );
169
+
170
+ this.adjustNavPosition();
171
+ window.addEventListener("scroll", this.adjustNavPosition);
172
+ window.addEventListener("resize", this.adjustNavPosition);
173
+
174
+ if (!this.hasRendered) {
175
+ this.hasRendered = true;
176
+ this.restoreScroll();
177
+
178
+ // Dynamically call `renderedCallbackForLwcContentLayout` if it exists
179
+ this.postRenderedCallback?.();
180
+ }
135
181
  }
136
182
 
137
183
  disconnectedCallback(): void {
@@ -140,8 +186,17 @@ export default class ContentLayout extends LightningElement {
140
186
  "highlightedtermchange",
141
187
  this.updateHighlighted
142
188
  );
189
+ window.removeEventListener("scroll", this.adjustNavPosition);
190
+ window.removeEventListener("resize", this.adjustNavPosition);
143
191
  this.searchSyncer.dispose();
144
192
  this.clearRenderObserverTimer();
193
+
194
+ window.clearInterval(this._scrollInterval);
195
+ }
196
+
197
+ restoreScroll() {
198
+ document.body.scrollTop = document.documentElement.scrollTop =
199
+ window.history.state?.scrollValue;
145
200
  }
146
201
 
147
202
  clearRenderObserverTimer = () => {
@@ -150,98 +205,274 @@ export default class ContentLayout extends LightningElement {
150
205
  }
151
206
  };
152
207
 
153
- updateHighlighted = (event: Event): void =>
154
- highlightTerms(
155
- this.querySelectorAll(HIGHLIGHTABLE_SELECTOR),
156
- (event as CustomEvent<string>).detail
157
- );
208
+ /*
209
+ This is a workaround for the global nav sticky header being decoupled from the doc header & doc phase.
210
+ We have to account for the global nav changing height due to animations.
211
+ */
212
+ adjustNavPosition = () => {
213
+ const sidebarType = this.useOldSidebar
214
+ ? "dx-sidebar-old"
215
+ : "dx-sidebar";
216
+ const sidebarEl = this.template.querySelector(sidebarType);
217
+ const globalNavEl = document.querySelector(
218
+ "hgf-c360nav"
219
+ ) as HTMLElement;
220
+ const contextNavEl = document.querySelector(
221
+ "hgf-c360contextnav"
222
+ ) as HTMLElement;
223
+ const docHeaderEl = document.querySelector(
224
+ ".sticky-doc-header"
225
+ ) as HTMLElement;
226
+
227
+ let docPhaseEl = (
228
+ this.template.querySelector("[name=doc-phase]")! as any
229
+ ).assignedElements()[0] as HTMLSlotElement;
230
+
231
+ if (!docPhaseEl) {
232
+ docPhaseEl = (
233
+ this.template.querySelector("[name=version-banner]")! as any
234
+ ).assignedElements()[0] as HTMLSlotElement;
235
+ }
158
236
 
159
- attachInteractionObserver = (): void => {
160
- if (!this.enableSlotChange) {
237
+ if (!sidebarEl || !globalNavEl || !contextNavEl || !docHeaderEl) {
238
+ console.warn("One or more required elements are missing.");
161
239
  return;
162
240
  }
163
- this.disconnectObserver();
164
- this.observer = new IntersectionObserver((entries) => {
165
- entries.forEach(
166
- (entry) =>
167
- (this.anchoredElements[
168
- entry.target.getAttribute("id")
169
- ].intersect = entry.isIntersecting)
241
+
242
+ // sync with the browser to account for any reflows that may have happened
243
+ requestAnimationFrame(() => {
244
+ // ternary is a temporary fix for the global nav height reporting incorrectly on some browsers
245
+ const globalNavHeight =
246
+ (globalNavEl.getBoundingClientRect().height !== 72 ? 0 : 72) +
247
+ contextNavEl.getBoundingClientRect().height;
248
+ const docHeaderHeight = docHeaderEl.getBoundingClientRect().height;
249
+ const totalHeaderHeight = globalNavHeight + docHeaderHeight;
250
+
251
+ // Selecting the doc section heading and RNB here.
252
+ const docHeadingEls = Array.from(
253
+ document.querySelectorAll("doc-heading")
254
+ );
255
+ const rightNavBarEl = this.template.querySelector(".right-nav-bar");
256
+
257
+ sidebarEl.style.setProperty(
258
+ "--dx-c-content-sidebar-sticky-top",
259
+ `${globalNavHeight + docHeaderHeight}px`
260
+ );
261
+
262
+ docHeaderEl.style.setProperty(
263
+ "--dx-g-global-header-height",
264
+ `${globalNavHeight}px`
170
265
  );
171
- this.calculateActualSection();
266
+
267
+ // Adjusting the doc section heading on scroll.
268
+ docHeadingEls.forEach((docHeadingEl) => {
269
+ (docHeadingEl as any).style.scrollMarginTop = docPhaseEl
270
+ ? `${
271
+ totalHeaderHeight +
272
+ docPhaseEl.getBoundingClientRect().height +
273
+ 40
274
+ }px`
275
+ : `${totalHeaderHeight + 40}px`;
276
+ });
277
+
278
+ // Adjusting the right nav bar on scroll.
279
+ if (rightNavBarEl) {
280
+ rightNavBarEl.style.top = docPhaseEl
281
+ ? `${
282
+ totalHeaderHeight +
283
+ docPhaseEl.getBoundingClientRect().height
284
+ }px`
285
+ : `${totalHeaderHeight}px`;
286
+ }
287
+
288
+ // If doc phase element exists, we need to account for its sticky position. Mobile should include the sidebar height (since it becomes sticky aswell).
289
+ if (docPhaseEl) {
290
+ docPhaseEl.style.setProperty(
291
+ "--doc-c-phase-top",
292
+ `${
293
+ window.innerWidth < 769
294
+ ? globalNavHeight +
295
+ docHeaderHeight +
296
+ sidebarEl.getBoundingClientRect().height
297
+ : globalNavHeight + docHeaderHeight
298
+ }px`
299
+ );
300
+ }
172
301
  });
302
+ };
303
+
304
+ updateHighlighted = (event: Event): void =>
305
+ highlightTerms(
306
+ this.querySelectorAll(HIGHLIGHTABLE_SELECTOR),
307
+ (event as CustomEvent<string>).detail
308
+ );
173
309
 
310
+ protected getHeadingElements() {
174
311
  // Note: We are doing document.querySelectorAll as a quick fix as we are not getting heading elements reference this.querySelectorAll
175
312
  const headingElements = document.querySelectorAll(TOC_HEADER_TAG);
176
- for (const headingElement of headingElements) {
313
+ return headingElements;
314
+ }
315
+
316
+ updateHeadingForRNB(): void {
317
+ const headingElements = this.getHeadingElements();
318
+ this.addObserverAndScroll(headingElements);
319
+ }
320
+
321
+ addObserverAndScroll(headingElements: any) {
322
+ for (const headingElement of headingElements as any) {
177
323
  // Add headingElements to intersectionObserver for highlighting respective RNB item when user scroll
178
- const id = headingElement.getAttribute("id");
324
+ const id = headingElement.getAttribute("id")!;
179
325
  this.anchoredElements[id] = {
180
326
  id,
181
327
  intersect: false
182
328
  };
183
- this.observer.observe(headingElement);
329
+ this.observer?.observe(headingElement);
184
330
  }
331
+
185
332
  if (!this.didScrollToSelectedHash) {
186
333
  this.didScrollToSelectedHash = true;
187
334
  this.scrollToHash(headingElements);
188
335
  }
189
- };
336
+ }
190
337
 
191
- onSlotChange(event: Event): void {
192
- const slotElements = (
193
- event.target as HTMLSlotElement
194
- ).assignedElements();
338
+ attachInteractionObserver = (): void => {
339
+ if (!this.enableSlotChange) {
340
+ return;
341
+ }
342
+ this.disconnectObserver();
195
343
 
196
- if (slotElements.length) {
197
- const slotContentElement = slotElements[0];
198
- const headingElements =
199
- slotContentElement.ownerDocument?.getElementsByTagName(
200
- TOC_HEADER_TAG
344
+ const globalNavOffset = `-${getComputedStyle(
345
+ document.documentElement
346
+ ).getPropertyValue("--dx-g-doc-header-main-nav-height")}`;
347
+
348
+ this.observer = new IntersectionObserver(
349
+ (entries) => {
350
+ entries.forEach(
351
+ (entry) =>
352
+ (this.anchoredElements[
353
+ entry.target.getAttribute("id")!
354
+ ].intersect = entry.isIntersecting)
201
355
  );
202
- for (const headingElement of headingElements) {
203
- // Sometimes elements hash is not being set when slot content is wrapped with div
204
- headingElement.hash =
205
- headingElement.attributes["hash"]?.nodeValue;
356
+ this.calculateActualSection();
357
+ },
358
+ {
359
+ rootMargin: globalNavOffset.trim()
206
360
  }
207
- const tocOptions = [];
208
- for (const headingElement of headingElements) {
209
- headingElement.id = headingElement.hash;
361
+ );
362
+ this.updateHeadingForRNB();
363
+ };
364
+
365
+ // eslint-disable-next-line no-undef
366
+ updateTocItems(headingElements: any): void {
367
+ const tocOptions = [];
368
+
369
+ for (const headingElement of headingElements as any) {
370
+ headingElement.id = headingElement.hash;
210
371
 
211
- // Update tocOptions from anchorTags
372
+ // Update tocOptions from anchorTags only for H2, consider default as 2 as per component
373
+ const headingAriaLevel =
374
+ headingElement.attributes["aria-level"]?.nodeValue || "2";
375
+ const isH2 = headingAriaLevel === "2";
376
+
377
+ if (isH2) {
212
378
  const tocItem = {
213
379
  anchor: `#${headingElement.hash}`,
214
380
  id: headingElement.id,
215
- label: headingElement.title
381
+ label: headingElement.header
216
382
  };
217
383
  tocOptions.push(tocItem);
384
+ this.tocOptionIdsSet.add(headingElement.id);
218
385
  }
386
+ }
219
387
 
220
- this._tocOptions = tocOptions;
388
+ this._tocOptions = tocOptions;
389
+ }
390
+
391
+ setHashAndHeaderForDocHeading(headingElements: any) {
392
+ for (const headingElement of headingElements as any) {
393
+ // Sometimes elements hash and header is not being set when slot content is wrapped with div
394
+ if (!headingElement.hash) {
395
+ headingElement.hash = headingElement.attributes.hash?.nodeValue;
396
+ }
397
+
398
+ if (!headingElement.header) {
399
+ headingElement.header =
400
+ headingElement.attributes.header?.nodeValue;
401
+ }
221
402
  }
403
+
404
+ this.updateTocItems(headingElements);
405
+ }
406
+
407
+ updateRNB = () => {
408
+ const headingElements = this.getHeadingElements();
409
+ this.setHashAndHeaderForDocHeading(headingElements);
410
+ };
411
+
412
+ onSlotChange(): void {
413
+ this.updateRNB();
414
+ this.contentLoaded = true;
222
415
  }
223
416
 
224
- private disconnectObserver(): void {
417
+ protected disconnectObserver(): void {
225
418
  if (this.observer) {
226
419
  this.observer.disconnect();
227
- this.observer = null;
420
+ this.observer = undefined;
228
421
  }
229
422
  }
230
423
 
231
- private scrollToHash(headingElements: NodeListOf<Element>): void {
424
+ // eslint-disable-next-line no-undef
425
+ protected scrollToHash(headingElements: NodeListOf<Element>): void {
232
426
  let { hash } = window.location;
233
427
  if (hash) {
234
428
  hash = hash.substr(1);
235
- for (const headingElement of headingElements) {
429
+
430
+ const docHeaderEl = document.querySelector(
431
+ ".sticky-doc-header"
432
+ ) as HTMLElement;
433
+ const globalNavEl = document.querySelector(
434
+ "hgf-c360nav"
435
+ ) as HTMLElement;
436
+ const contextNavEl = document.querySelector(
437
+ "hgf-c360contextnav"
438
+ ) as HTMLElement;
439
+
440
+ const headerHeight =
441
+ docHeaderEl?.offsetHeight +
442
+ globalNavEl?.offsetHeight +
443
+ contextNavEl?.offsetHeight;
444
+
445
+ const docPhaseEl = (
446
+ this.template.querySelector("[name=doc-phase]")! as any
447
+ ).assignedElements()[0] as HTMLSlotElement;
448
+
449
+ const offset = docPhaseEl
450
+ ? headerHeight + docPhaseEl.offsetHeight
451
+ : headerHeight;
452
+
453
+ for (const headingElement of headingElements as any) {
236
454
  if (headingElement.getAttribute("id") === hash) {
237
- headingElement.scrollIntoView({ behavior: "auto" });
455
+ this.scrollIntoViewWithOffset(headingElement, offset);
238
456
  break;
239
457
  }
240
458
  }
241
459
  }
242
460
  }
243
461
 
244
- private calculateActualSection(): void {
462
+ protected scrollIntoViewWithOffset(
463
+ headingElement: HTMLElement,
464
+ offset: number
465
+ ) {
466
+ window.scrollTo({
467
+ behavior: "auto",
468
+ top:
469
+ headingElement.getBoundingClientRect().top -
470
+ document.body.getBoundingClientRect().top -
471
+ offset
472
+ });
473
+ }
474
+
475
+ protected calculateActualSection(): void {
245
476
  const currentScrollPosition = document.documentElement.scrollTop;
246
477
  const id = Object.keys(this.anchoredElements).find(
247
478
  (_id) => this.anchoredElements[_id].intersect
@@ -256,18 +487,21 @@ export default class ContentLayout extends LightningElement {
256
487
  this.lastScrollPosition = currentScrollPosition;
257
488
  }
258
489
 
259
- private calculatePreviousElementId(): string {
490
+ protected calculatePreviousElementId(): string | undefined {
260
491
  const keys = Object.keys(this.anchoredElements);
261
492
  const currentIndex = keys.findIndex((id) => this.tocValue === id);
262
493
 
263
494
  return currentIndex > 0 ? keys[currentIndex - 1] : undefined;
264
495
  }
265
496
 
266
- private assignElementId(id: string): void {
267
- this.tocValue = id;
497
+ protected assignElementId(id: string | undefined): void {
498
+ // Change toc(RNB) highlight only for H2
499
+ if (this.tocOptionIdsSet.has(id)) {
500
+ this.tocValue = id;
501
+ }
268
502
  }
269
503
 
270
- private dispatchHighlightChange(term: string): void {
504
+ protected dispatchHighlightChange(term: string): void {
271
505
  this.dispatchEvent(
272
506
  new CustomEvent("highlightedtermchange", {
273
507
  detail: term,
@@ -277,10 +511,21 @@ export default class ContentLayout extends LightningElement {
277
511
  );
278
512
  }
279
513
 
280
- private updateHighlightsAndSearch(nextSearchString: string): void {
514
+ protected updateHighlightsAndSearch(nextSearchString: string): void {
281
515
  const nextSearchParam =
282
516
  new URLSearchParams(nextSearchString).get("q") || "";
283
517
  this.setSidebarInputValue(nextSearchParam);
284
518
  this.dispatchHighlightChange(nextSearchParam);
285
519
  }
520
+
521
+ protected onToggleSidebar(e: CustomEvent): void {
522
+ this.sidebarOpen = e.detail.open;
523
+
524
+ // eslint-disable-next-line @lwc/lwc/no-document-query
525
+ const footer = document.querySelector("dx-footer") as HTMLElement;
526
+
527
+ if (footer) {
528
+ footer.style.display = this.sidebarOpen ? "none" : "block";
529
+ }
530
+ }
286
531
  }
@@ -0,0 +1,47 @@
1
+ @import "dxHelpers/reset";
2
+ @import "dxHelpers/text";
3
+
4
+ .container {
5
+ display: flex;
6
+ flex-direction: column;
7
+ gap: var(--dx-g-spacing-md);
8
+ flex: 1;
9
+ }
10
+
11
+ .doc-do-dont-header {
12
+ display: flex;
13
+ align-items: center;
14
+ gap: var(--dx-g-spacing-sm);
15
+ }
16
+
17
+ .doc-do-dont-label {
18
+ font-family: var(--dx-g-font-display);
19
+ font-size: var(--dx-g-spacing-md);
20
+ font-weight: var(--dx-g-font-demi);
21
+ line-height: var(--dx-g-spacing-lg);
22
+ }
23
+
24
+ .doc-do-color {
25
+ color: var(--dx-g-green-vibrant-50);
26
+ }
27
+
28
+ .doc-dont-color {
29
+ color: var(--dx-g-red-vibrant-30);
30
+ }
31
+
32
+ .do-dont-image-container {
33
+ display: flex;
34
+ max-height: 480px;
35
+ min-height: 140px;
36
+ padding: var(--dx-g-spacing-3xl) var(--dx-g-spacing-2xl);
37
+ flex-direction: column;
38
+ justify-content: center;
39
+ align-items: center;
40
+ flex: 1;
41
+ border-radius: var(--dx-g-spacing-sm);
42
+ border: 1px solid var(--dx-g-brand-default-color-border-2);
43
+ }
44
+
45
+ .doc-do-dont-img {
46
+ object-fit: contain;
47
+ }