@salesforcedevs/docs-components 0.17.1 → 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.
- package/lwc.config.json +17 -3
- package/package.json +18 -7
- package/src/modules/README.md +41 -0
- package/src/modules/doc/amfModelParser/amfModelParser.ts +674 -0
- package/src/modules/doc/amfReference/amfReference.css +25 -0
- package/src/modules/doc/amfReference/amfReference.html +55 -0
- package/src/modules/doc/amfReference/amfReference.ts +1467 -0
- package/src/modules/doc/amfReference/constants.ts +76 -0
- package/src/modules/doc/amfReference/types.ts +125 -0
- package/src/modules/doc/amfTopic/amfTopic.css +21 -0
- package/src/modules/doc/amfTopic/amfTopic.html +3 -0
- package/src/modules/doc/amfTopic/amfTopic.ts +111 -0
- package/src/modules/doc/amfTopic/types.ts +56 -0
- package/src/modules/doc/amfTopic/utils.ts +136 -0
- package/src/modules/doc/breadcrumbItem/breadcrumbItem.css +51 -0
- package/src/modules/doc/breadcrumbItem/breadcrumbItem.html +5 -0
- package/src/modules/doc/breadcrumbItem/breadcrumbItem.ts +71 -0
- package/src/modules/doc/breadcrumbs/breadcrumbs.css +27 -0
- package/src/modules/doc/breadcrumbs/breadcrumbs.html +58 -0
- package/src/modules/doc/breadcrumbs/breadcrumbs.ts +183 -0
- package/src/modules/doc/componentPlayground/componentPlayground.css +22 -0
- package/src/modules/doc/componentPlayground/componentPlayground.html +20 -0
- package/src/modules/doc/componentPlayground/componentPlayground.ts +42 -0
- package/src/modules/doc/content/content.css +89 -70
- package/src/modules/doc/content/content.html +1 -0
- package/src/modules/doc/content/content.ts +188 -195
- package/src/modules/doc/contentCallout/contentCallout.css +18 -10
- package/src/modules/doc/contentCallout/contentCallout.html +13 -4
- package/src/modules/doc/contentCallout/contentCallout.ts +14 -2
- package/src/modules/doc/contentLayout/contentLayout.css +1 -0
- package/src/modules/doc/contentLayout/contentLayout.html +46 -0
- package/src/modules/doc/contentLayout/contentLayout.ts +524 -0
- package/src/modules/doc/doDont/doDont.css +47 -0
- package/src/modules/doc/doDont/doDont.html +27 -0
- package/src/modules/doc/doDont/doDont.ts +17 -0
- package/src/modules/doc/header/header.css +70 -37
- package/src/modules/doc/header/header.html +41 -138
- package/src/modules/doc/header/header.ts +56 -78
- package/src/modules/doc/heading/heading.css +33 -0
- package/src/modules/doc/heading/heading.html +14 -0
- package/src/modules/doc/heading/heading.ts +67 -0
- package/src/modules/doc/headingAnchor/headingAnchor.css +3 -3
- package/src/modules/doc/headingAnchor/headingAnchor.ts +2 -2
- package/src/modules/doc/headingContent/headingContent.css +53 -0
- package/src/modules/doc/headingContent/headingContent.html +13 -0
- package/src/modules/doc/headingContent/headingContent.ts +30 -0
- package/src/modules/doc/lwcContentLayout/lwcContentLayout.css +1 -0
- package/src/modules/doc/lwcContentLayout/lwcContentLayout.html +45 -0
- package/src/modules/doc/lwcContentLayout/lwcContentLayout.ts +256 -0
- package/src/modules/doc/overview/overview.css +40 -0
- package/src/modules/doc/overview/overview.html +34 -0
- package/src/modules/doc/overview/overview.ts +12 -0
- package/src/modules/doc/phase/phase.css +21 -6
- package/src/modules/doc/phase/phase.html +15 -3
- package/src/modules/doc/phase/phase.ts +48 -12
- package/src/modules/doc/specificationContent/specificationContent.css +36 -0
- package/src/modules/doc/specificationContent/specificationContent.html +167 -0
- package/src/modules/doc/specificationContent/specificationContent.ts +127 -0
- package/src/modules/doc/sprigSurvey/sprigSurvey.html +20 -0
- package/src/modules/doc/sprigSurvey/sprigSurvey.scoped.css +16 -0
- package/src/modules/doc/sprigSurvey/sprigSurvey.ts +16 -0
- package/src/modules/doc/toc/toc.ts +1 -1
- package/src/modules/doc/versionPicker/versionPicker.css +64 -0
- package/src/modules/doc/versionPicker/versionPicker.html +38 -0
- package/src/modules/doc/versionPicker/versionPicker.ts +65 -0
- package/src/modules/doc/xmlContent/types.ts +120 -0
- package/src/modules/doc/xmlContent/utils.ts +163 -0
- package/src/modules/doc/xmlContent/xmlContent.css +54 -0
- package/src/modules/doc/xmlContent/xmlContent.html +54 -0
- package/src/modules/doc/xmlContent/xmlContent.ts +763 -0
- package/src/modules/docHelpers/amfStyle/amfStyle.css +355 -0
- package/src/modules/docHelpers/contentLayoutStyle/contentLayoutStyle.css +131 -0
- package/src/modules/docHelpers/imgStyle/imgStyle.css +59 -0
- package/src/modules/{helpers → docHelpers}/status/status.css +1 -1
- package/src/modules/docUtils/searchSyncer/searchSyncer.ts +86 -0
- package/src/modules/docUtils/utils/__mocks__/coveo.analytics.ts +16 -0
- package/src/modules/docUtils/utils/coveo.analytics.d.ts +10 -0
- package/src/modules/docUtils/utils/utils.ts +32 -0
- package/LICENSE +0 -12
- package/src/modules/doc/content/__tests__/content.test.ts +0 -312
- package/src/modules/doc/content/__tests__/mockDocContent.ts +0 -348
- package/src/modules/doc/content/__tests__/mockPageReference.ts +0 -8
- package/src/modules/doc/content/__tests__/mockSidebar.ts +0 -81
- package/src/modules/doc/content/content.stories.ts +0 -148
- package/src/modules/doc/contentCallout/__tests__/contentCallout.test.ts +0 -80
- package/src/modules/doc/contentCallout/__tests__/mockProps.ts +0 -14
- package/src/modules/doc/contentCallout/contentCallout.stories.ts +0 -29
- package/src/modules/doc/contentMedia/__tests__/contentMedia.test.ts +0 -97
- package/src/modules/doc/contentMedia/contentMedia.stories.ts +0 -113
- package/src/modules/doc/header/__tests__/coveoConfig.ts +0 -12
- package/src/modules/doc/header/__tests__/header.test.ts +0 -445
- package/src/modules/doc/header/__tests__/mockNavDevelopers.ts +0 -427
- package/src/modules/doc/header/__tests__/mockNavs.ts +0 -115
- package/src/modules/doc/header/__tests__/mockProps.ts +0 -152
- package/src/modules/doc/header/header.stories.ts +0 -190
- package/src/modules/doc/headingAnchor/__tests__/headingAnchor.test.ts +0 -111
- package/src/modules/doc/headingAnchor/headingAnchor.stories.ts +0 -33
- package/src/modules/doc/nav/__tests__/mockAvailableLanguages.ts +0 -8
- package/src/modules/doc/nav/__tests__/mockAvailableVersions.ts +0 -122
- package/src/modules/doc/nav/__tests__/mockPageReference.ts +0 -8
- package/src/modules/doc/nav/__tests__/mockPdfUrl.ts +0 -1
- package/src/modules/doc/nav/__tests__/mockSelectedLanguage.ts +0 -8
- package/src/modules/doc/nav/__tests__/mockSelectedVersion.ts +0 -8
- package/src/modules/doc/nav/__tests__/mockToc.ts +0 -146
- package/src/modules/doc/nav/__tests__/nav.test.ts +0 -58
- package/src/modules/doc/phase/__tests__/mockProps.ts +0 -13
- package/src/modules/doc/phase/__tests__/phase.test.ts +0 -60
- package/src/modules/doc/phase/phase.stories.ts +0 -12
- package/src/modules/doc/toc/__tests__/mockPageReference.ts +0 -8
- package/src/modules/doc/toc/__tests__/mockToc.ts +0 -146
- package/src/modules/doc/toc/__tests__/toc.test.ts +0 -29
- package/src/modules/doc/toolbar/__tests__/mockAvailableLanguages.ts +0 -8
- package/src/modules/doc/toolbar/__tests__/mockAvailableVersions.ts +0 -122
- package/src/modules/doc/toolbar/__tests__/mockPdfUrl.ts +0 -1
- package/src/modules/doc/toolbar/__tests__/mockSelectedLanguage.ts +0 -8
- package/src/modules/doc/toolbar/__tests__/mockSelectedVersion.ts +0 -8
- 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
|
+
}
|