@salesforcedevs/docs-components 0.17.0 → 0.17.12-search-alpha

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