@salesforcedevs/docs-components 1.3.15 → 1.3.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforcedevs/docs-components",
3
- "version": "1.3.15",
3
+ "version": "1.3.19",
4
4
  "description": "Docs Lightning web components for DSC",
5
5
  "license": "MIT",
6
6
  "main": "index.js",
@@ -24,5 +24,5 @@
24
24
  "@types/lodash.orderby": "^4.6.7",
25
25
  "@types/lodash.uniqby": "^4.7.7"
26
26
  },
27
- "gitHead": "4f666690d99a33edd60c92c55d84732b7feadb07"
27
+ "gitHead": "bbeea73fe1ce336f60e304b3edcc0ff7afd5b99d"
28
28
  }
@@ -17,11 +17,9 @@ const CONSTANTS = {
17
17
  dropdownWidth: 32
18
18
  };
19
19
 
20
- export const ANALYTICS_EVENT_NAME = "custEv_breadcrumbClick";
20
+ export const ANALYTICS_EVENT_NAME = "custEv_breadcrumbNavClick";
21
21
  export const ANALYTICS_BASE_PAYLOAD = {
22
- elementType: "breadcrumb",
23
- locationOnPage: "breadcrumb",
24
- ctaClick: true
22
+ navType: "breadcrumb"
25
23
  };
26
24
 
27
25
  export default class Breadcrumbs extends LightningElement {
@@ -111,7 +109,7 @@ export default class Breadcrumbs extends LightningElement {
111
109
  private get analyticsBasePayload() {
112
110
  return {
113
111
  ...ANALYTICS_BASE_PAYLOAD,
114
- itemTitle: this.breadcrumbs.map((crumb) => crumb.label).join("/")
112
+ navItem: this.breadcrumbs.map((crumb) => crumb.label).join("/")
115
113
  };
116
114
  }
117
115
 
@@ -6,6 +6,7 @@
6
6
  trees={sidebarContent}
7
7
  value={sidebarValue}
8
8
  header={sidebarHeader}
9
+ onsidebarclick={onSidebarClick}
9
10
  >
10
11
  <slot name="sidebar-header" slot="header"></slot>
11
12
  </dx-sidebar-old>
@@ -20,6 +21,7 @@
20
21
  coveo-public-access-token={coveoPublicAccessToken}
21
22
  coveo-search-hub={coveoSearchHub}
22
23
  coveo-advanced-query-config={coveoAdvancedQueryConfig}
24
+ onsidebarclick={onSidebarClick}
23
25
  >
24
26
  <slot name="sidebar-header" slot="header"></slot>
25
27
  </dx-sidebar>
@@ -35,7 +37,9 @@
35
37
  <div style={docContentStyle}>
36
38
  <slot onslotchange={onSlotChange}></slot>
37
39
  </div>
38
- <doc-sprig-survey></doc-sprig-survey>
40
+ <doc-sprig-survey
41
+ if:true={shouldDisplayFeedback}
42
+ ></doc-sprig-survey>
39
43
  </div>
40
44
  <div class="right-nav-bar is-sticky">
41
45
  <dx-toc
@@ -3,9 +3,12 @@ import { closest } from "kagekiri";
3
3
  import { toJson } from "dxUtils/normalizers";
4
4
  import { highlightTerms } from "dxUtils/highlight";
5
5
  import { SearchSyncer } from "docUtils/SearchSyncer";
6
+ import { track as sendGtm } from "dxUtils/analytics";
6
7
 
7
8
  type AnchorMap = { [key: string]: { intersect: boolean; id: string } };
8
9
 
10
+ declare const Sprig: (eventType: string, eventNme: string) => void;
11
+
9
12
  const TOC_HEADER_TAG = "DOC-HEADING";
10
13
  const HIGHLIGHTABLE_SELECTOR = [
11
14
  "p",
@@ -79,6 +82,11 @@ export default class ContentLayout extends LightningElement {
79
82
  private lastScrollPosition: number;
80
83
  private observer?: IntersectionObserver;
81
84
  private hasRendered: boolean = false;
85
+ private contentLoaded: boolean = false;
86
+
87
+ get shouldDisplayFeedback() {
88
+ return this.contentLoaded && typeof Sprig !== "undefined";
89
+ }
82
90
 
83
91
  private searchSyncer = new SearchSyncer({
84
92
  callbacks: {
@@ -101,6 +109,12 @@ export default class ContentLayout extends LightningElement {
101
109
  private observerTimerId = null;
102
110
  private didScrollToSelectedHash = false;
103
111
  private _scrollInterval = 0;
112
+ private scrollPosition = 0;
113
+
114
+ private scrolledTwentyFivePercent = false;
115
+ private scrolledFiftyPercent = false;
116
+ private scrolledSevenFivePercent = false;
117
+ private scrolledOneHundredPercent = false;
104
118
 
105
119
  get showToc(): boolean {
106
120
  return this.tocOptions && this.tocOptions.length > 0;
@@ -137,6 +151,11 @@ export default class ContentLayout extends LightningElement {
137
151
  this._scrollInterval = window.setInterval(() => {
138
152
  this.saveScroll();
139
153
  }, 1000);
154
+
155
+ document.addEventListener(
156
+ "scroll",
157
+ this.scrollThresholdHandler.bind(this)
158
+ );
140
159
  }
141
160
 
142
161
  renderedCallback(): void {
@@ -165,6 +184,8 @@ export default class ContentLayout extends LightningElement {
165
184
  this.clearRenderObserverTimer();
166
185
 
167
186
  window.clearInterval(this._scrollInterval);
187
+
188
+ document.removeEventListener("scroll", this.scrollThresholdHandler);
168
189
  }
169
190
 
170
191
  saveScroll() {
@@ -224,17 +245,82 @@ export default class ContentLayout extends LightningElement {
224
245
  }
225
246
  };
226
247
 
248
+ onSidebarClick() {
249
+ this.resetScrollThreshold();
250
+ }
251
+
252
+ sendGtmScrollThresholdEvent(threshold: "25" | "50" | "75" | "100") {
253
+ sendGtm(document.body, "custEv_scroll", {
254
+ scrollDepth: threshold
255
+ });
256
+ }
257
+
258
+ resetScrollThreshold() {
259
+ this.scrolledTwentyFivePercent = false;
260
+ this.scrolledFiftyPercent = false;
261
+ this.scrolledSevenFivePercent = false;
262
+ this.scrolledOneHundredPercent = false;
263
+ }
264
+
265
+ scrollThresholdHandler() {
266
+ this.scrollPosition =
267
+ ((document.documentElement.scrollTop + document.body.scrollTop) /
268
+ (document.documentElement.scrollHeight -
269
+ document.documentElement.clientHeight)) *
270
+ 100;
271
+
272
+ if (this.scrollPosition > 25 && !this.scrolledTwentyFivePercent) {
273
+ this.scrolledTwentyFivePercent = true;
274
+ this.sendGtmScrollThresholdEvent("25");
275
+ } else if (this.scrollPosition > 50 && !this.scrolledFiftyPercent) {
276
+ this.scrolledFiftyPercent = true;
277
+ this.sendGtmScrollThresholdEvent("50");
278
+ } else if (this.scrollPosition > 75 && !this.scrolledSevenFivePercent) {
279
+ this.scrolledSevenFivePercent = true;
280
+ this.sendGtmScrollThresholdEvent("75");
281
+ } else if (
282
+ this.scrollPosition === 100 &&
283
+ !this.scrolledOneHundredPercent
284
+ ) {
285
+ this.scrolledOneHundredPercent = true;
286
+ this.sendGtmScrollThresholdEvent("100");
287
+ }
288
+ }
289
+
227
290
  onSlotChange(event: Event): void {
228
291
  const slotElements = (
229
292
  event.target as HTMLSlotElement
230
293
  ).assignedElements();
231
294
 
232
295
  if (slotElements.length) {
296
+ this.contentLoaded = true;
233
297
  const slotContentElement = slotElements[0];
234
298
  const headingElements =
235
299
  slotContentElement.ownerDocument?.getElementsByTagName(
236
300
  TOC_HEADER_TAG
237
301
  );
302
+
303
+ const docContentEl = slotElements.find(
304
+ (el) => el.tagName === "DOC-CONTENT"
305
+ );
306
+ const topicTitleEl =
307
+ docContentEl?.shadowRoot?.getElementById("topic-title");
308
+ const anchorElements =
309
+ docContentEl?.shadowRoot?.querySelectorAll("a[href]");
310
+
311
+ // Attach click listeners to all anchor elements for analytics
312
+ anchorElements?.forEach((anchorElement) => {
313
+ anchorElement.addEventListener("click", () => {
314
+ sendGtm(anchorElement, "custEv_docContentClick", {
315
+ clickText: anchorElement.textContent,
316
+ clickUrl: anchorElement.getAttribute("href"),
317
+ elementType: "link",
318
+ locationOnPage: "docContent",
319
+ itemTitle: topicTitleEl?.textContent
320
+ });
321
+ });
322
+ });
323
+
238
324
  for (const headingElement of headingElements) {
239
325
  // Sometimes elements hash is not being set when slot content is wrapped with div
240
326
  headingElement.hash = headingElement.attributes.hash?.nodeValue;