@salesforcedevs/dx-components 1.3.66 → 1.3.71
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 +2 -2
- package/src/modules/dx/breadcrumbs/breadcrumbs.ts +10 -8
- package/src/modules/dx/cardBlogPost/cardBlogPost.ts +1 -1
- package/src/modules/dx/cardCallout/cardCallout.ts +4 -4
- package/src/modules/dx/cardContent/cardContent.html +1 -4
- package/src/modules/dx/cardDocs/cardDocs.html +1 -4
- package/src/modules/dx/cardDocs/cardDocs.ts +7 -6
- package/src/modules/dx/codeBlock/codeBlock.ts +38 -18
- package/src/modules/dx/dropdown/dropdown.ts +3 -2
- package/src/modules/dx/dropdownOption/dropdownOption.ts +1 -1
- package/src/modules/dx/featuredContentHeader/featuredContentHeader.ts +1 -1
- package/src/modules/dx/filterMenu/filterMenu.html +2 -7
- package/src/modules/dx/filterMenu/filterMenu.ts +3 -4
- package/src/modules/dx/footer/links.ts +4 -2
- package/src/modules/dx/footerOption/footerOption.ts +2 -1
- package/src/modules/dx/grid/grid.ts +1 -3
- package/src/modules/dx/mainContentHeader/mainContentHeader.ts +4 -4
- package/src/modules/dx/popover/popover.ts +3 -3
- package/src/modules/dx/scrollManager/scrollManager.ts +85 -16
- package/src/modules/dx/searchResults/searchResults.ts +3 -1
- package/src/modules/dx/select/select.ts +3 -2
- package/src/modules/dx/sidebar/sidebar.ts +5 -9
- package/src/modules/dx/sidebarOld/sidebarOld.ts +0 -2
- package/src/modules/dx/sidebarSearch/sidebarSearch.ts +5 -2
- package/src/modules/dx/tab/tab.ts +1 -1
- package/src/modules/dx/tabPanelList/tabPanelList.ts +2 -2
- package/src/modules/dx/toc/toc.ts +2 -2
- package/src/modules/dx/treeItem/treeItem.ts +3 -2
- package/src/modules/dxBaseElements/headerBase/headerBase.ts +1 -1
- package/src/modules/dxBaseElements/matchMediaElement/matchMediaElement.ts +4 -2
- package/src/modules/dxUtils/prismjs/prismjs.ts +167 -287
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforcedevs/dx-components",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.71",
|
|
4
4
|
"description": "DX Lightning web components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": {
|
|
@@ -40,5 +40,5 @@
|
|
|
40
40
|
"eventsourcemock": "^2.0.0",
|
|
41
41
|
"luxon": "^3.1.0"
|
|
42
42
|
},
|
|
43
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "2189b873b414cccf79905cf0b1401db76abbd9d0"
|
|
44
44
|
}
|
|
@@ -85,14 +85,16 @@ export default class Breadcrumbs extends LightningElement {
|
|
|
85
85
|
breadcrumbs: Breadcrumb[]
|
|
86
86
|
): NormalizedBreadcrumb[] {
|
|
87
87
|
const { length } = breadcrumbs;
|
|
88
|
-
return breadcrumbs.map(
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
88
|
+
return breadcrumbs.map(
|
|
89
|
+
(breadcrumb, i): NormalizedBreadcrumb => {
|
|
90
|
+
const last = i === length - 1;
|
|
91
|
+
return {
|
|
92
|
+
...breadcrumb,
|
|
93
|
+
asLink: this.hideCurrentLocation || !last,
|
|
94
|
+
last
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
);
|
|
96
98
|
}
|
|
97
99
|
|
|
98
100
|
private get breadcrumbDropdownOptions() {
|
|
@@ -24,7 +24,7 @@ export default class CardBlogPost extends LightningElement {
|
|
|
24
24
|
const payload = {
|
|
25
25
|
click_text: this.title,
|
|
26
26
|
click_url: this.href,
|
|
27
|
-
element_title:
|
|
27
|
+
element_title: this.title,
|
|
28
28
|
element_type: "card",
|
|
29
29
|
content_category: "link"
|
|
30
30
|
};
|
|
@@ -37,12 +37,12 @@ export default class CardCallout extends LightningElement {
|
|
|
37
37
|
elementType: "card callout",
|
|
38
38
|
destinationType: "internal"
|
|
39
39
|
});
|
|
40
|
-
track(e.currentTarget!, "
|
|
40
|
+
track(e.currentTarget!, "custEv_ctaLinkClick", {
|
|
41
41
|
click_text: this.title,
|
|
42
42
|
click_url: this.href,
|
|
43
|
-
element_title:
|
|
44
|
-
element_type: "
|
|
45
|
-
content_category: "
|
|
43
|
+
element_title: this.title,
|
|
44
|
+
element_type: "link",
|
|
45
|
+
content_category: "cta"
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
48
|
}
|
|
@@ -21,10 +21,7 @@
|
|
|
21
21
|
/>
|
|
22
22
|
</a>
|
|
23
23
|
<div
|
|
24
|
-
class="
|
|
25
|
-
dx-card-base_section-vertical dx-card-base_column
|
|
26
|
-
card_section-text
|
|
27
|
-
"
|
|
24
|
+
class="dx-card-base_section-vertical dx-card-base_column card_section-text"
|
|
28
25
|
>
|
|
29
26
|
<span if:true={label} part="label" class="label dx-text-label-3">
|
|
30
27
|
{label}
|
|
@@ -7,10 +7,7 @@
|
|
|
7
7
|
class="image dx-card-base_image"
|
|
8
8
|
/>
|
|
9
9
|
<div
|
|
10
|
-
class="
|
|
11
|
-
dx-card-base_section-vertical dx-card-base_column
|
|
12
|
-
card_section-text
|
|
13
|
-
"
|
|
10
|
+
class="dx-card-base_section-vertical dx-card-base_column card_section-text"
|
|
14
11
|
>
|
|
15
12
|
<span class="dx-text-label-3">{label}</span>
|
|
16
13
|
<dx-card-title
|
|
@@ -27,7 +27,6 @@ export default class CardDocs extends LightningElement {
|
|
|
27
27
|
|
|
28
28
|
private onSlotChange(e: LightningSlotElement) {
|
|
29
29
|
const payloadInnerButton = {
|
|
30
|
-
element_title: "dx-button",
|
|
31
30
|
element_type: "link",
|
|
32
31
|
content_category: "card"
|
|
33
32
|
};
|
|
@@ -38,11 +37,13 @@ export default class CardDocs extends LightningElement {
|
|
|
38
37
|
slotElement?.addEventListener("click", (event: Event) => {
|
|
39
38
|
track(event.currentTarget!, "custEv_cardClick", {
|
|
40
39
|
...payloadInnerButton,
|
|
40
|
+
element_title: slotElement.innerText,
|
|
41
41
|
click_text: slotElement.innerText,
|
|
42
42
|
click_url: slotElement.href
|
|
43
43
|
});
|
|
44
44
|
track(event.currentTarget!, "custEv_linkClick", {
|
|
45
45
|
...payloadInnerButton,
|
|
46
|
+
element_title: slotElement.innerText,
|
|
46
47
|
click_text: slotElement.innerText,
|
|
47
48
|
click_url: slotElement.href
|
|
48
49
|
});
|
|
@@ -52,21 +53,21 @@ export default class CardDocs extends LightningElement {
|
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
private handleLinkClick(event: PointerEvent) {
|
|
55
|
-
const
|
|
56
|
+
const payloadCardInfo = {
|
|
56
57
|
click_text: this.title,
|
|
57
|
-
element_title:
|
|
58
|
+
element_title: this.title,
|
|
58
59
|
click_url: this.href,
|
|
59
60
|
element_type: "link",
|
|
60
61
|
content_category: "cta"
|
|
61
62
|
};
|
|
62
|
-
track(event.currentTarget!, "custEv_cardClick",
|
|
63
|
-
track(event.currentTarget!, "custEv_linkClick",
|
|
63
|
+
track(event.currentTarget!, "custEv_cardClick", payloadCardInfo);
|
|
64
|
+
track(event.currentTarget!, "custEv_linkClick", payloadCardInfo);
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
private handleTextClick(event: PointerEvent) {
|
|
67
68
|
const payloadCardTextInfo = {
|
|
68
69
|
click_text: this.body,
|
|
69
|
-
element_title:
|
|
70
|
+
element_title: this.body,
|
|
70
71
|
click_url: this.href,
|
|
71
72
|
element_type: "tile",
|
|
72
73
|
content_category: "cta"
|
|
@@ -68,10 +68,9 @@ export default class CodeBlock extends LightningElement {
|
|
|
68
68
|
set codeBlock(value: string) {
|
|
69
69
|
this._codeBlockRendered = false;
|
|
70
70
|
let match;
|
|
71
|
-
this._codeBlock = (
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
: match[1]
|
|
71
|
+
this._codeBlock = ((match = preTagRegexp.exec(value.trim())) === null
|
|
72
|
+
? value.trim()
|
|
73
|
+
: match[1]
|
|
75
74
|
).trim();
|
|
76
75
|
}
|
|
77
76
|
|
|
@@ -108,23 +107,35 @@ export default class CodeBlock extends LightningElement {
|
|
|
108
107
|
formatCodeBlock() {
|
|
109
108
|
const divEl = this.template.querySelector("div.code-block-content");
|
|
110
109
|
const templateEl = document.createElement("template");
|
|
110
|
+
|
|
111
|
+
// Replace any <var> markup with a temporary nonsense sentinel (but one that is very
|
|
112
|
+
// unlikely to affect Prism's tokenization) so that Prism will not strip them but does
|
|
113
|
+
// still tokenize correctly. We want to italicize the "variables" ourselves after Prism
|
|
114
|
+
// does its own thing (W-11975205).
|
|
115
|
+
let cleanCodeBlock = this.codeBlock.replace(
|
|
116
|
+
/<var.*?>(.+?)<\/var>/g,
|
|
117
|
+
"vvvvv$1vvvvv"
|
|
118
|
+
);
|
|
119
|
+
|
|
111
120
|
if (
|
|
112
121
|
!this.isEncoded &&
|
|
113
122
|
this.markupLangs.includes(this.selectedLanguage.id || "")
|
|
114
123
|
) {
|
|
115
|
-
//
|
|
116
|
-
|
|
124
|
+
// Temporarily replace HTML comment characters, which Prism would also strip
|
|
125
|
+
cleanCodeBlock = `<!--${cleanCodeBlock.replace(
|
|
117
126
|
/<!--(.*?)-->/gs,
|
|
118
127
|
"@@$1##"
|
|
119
|
-
)}
|
|
128
|
+
)}-->`;
|
|
120
129
|
} else {
|
|
121
|
-
//
|
|
122
|
-
|
|
123
|
-
?
|
|
124
|
-
:
|
|
125
|
-
|
|
126
|
-
templateEl.innerHTML = `<pre class='codeblock'>${innerHtml}</pre>`;
|
|
130
|
+
// If this is a non-encoded markup language, encode angle brackets that Prism would strip
|
|
131
|
+
cleanCodeBlock = this.isEncoded
|
|
132
|
+
? cleanCodeBlock
|
|
133
|
+
: cleanCodeBlock.replace(/</g, "<").replace(/>/g, ">");
|
|
127
134
|
}
|
|
135
|
+
|
|
136
|
+
// eslint-disable-next-line
|
|
137
|
+
templateEl.innerHTML = `<pre class='codeblock'>${cleanCodeBlock}</pre>`;
|
|
138
|
+
|
|
128
139
|
const codeBlockEls = templateEl.content.querySelectorAll("pre");
|
|
129
140
|
codeBlockEls.forEach((codeBlockEl) => {
|
|
130
141
|
// eslint-disable-next-line
|
|
@@ -141,12 +152,19 @@ export default class CodeBlock extends LightningElement {
|
|
|
141
152
|
// for custom markup content, it is a workaround to be refactored later.
|
|
142
153
|
// eslint-disable-next-line
|
|
143
154
|
this.language !== "text"
|
|
144
|
-
?
|
|
155
|
+
? // eslint-disable-next-line
|
|
156
|
+
(codeEl.innerHTML = codeHTML)
|
|
145
157
|
: (codeEl.textContent = this._codeBlock.trim());
|
|
146
158
|
// eslint-disable-next-line
|
|
147
159
|
codeBlockEl.innerHTML = "";
|
|
148
160
|
codeBlockEl.appendChild(codeEl);
|
|
149
161
|
Prism.highlightAllUnder(codeBlockEl);
|
|
162
|
+
// Italicize anything marked as a "variable" by the docs team
|
|
163
|
+
// eslint-disable-next-line
|
|
164
|
+
codeBlockEl.innerHTML = codeBlockEl.innerHTML.replace(
|
|
165
|
+
/vvvvv(.+?)vvvvv/g,
|
|
166
|
+
"<span class='token italic'>$1</span>"
|
|
167
|
+
);
|
|
150
168
|
});
|
|
151
169
|
|
|
152
170
|
if (divEl) {
|
|
@@ -156,6 +174,7 @@ export default class CodeBlock extends LightningElement {
|
|
|
156
174
|
if (this.markupLangs.includes(this.selectedLanguage.id || "")) {
|
|
157
175
|
const res = this.template.querySelector(`code.language-markup`);
|
|
158
176
|
if (res) {
|
|
177
|
+
// Restore any temporarily replaced HTML comment characters
|
|
159
178
|
// eslint-disable-next-line
|
|
160
179
|
res.innerHTML = res.innerHTML.replace(
|
|
161
180
|
/@@(.*?)##/gs,
|
|
@@ -193,13 +212,14 @@ export default class CodeBlock extends LightningElement {
|
|
|
193
212
|
gtmTrack(event.target, "custEv_iconClick", {
|
|
194
213
|
click_text: this.copyBtnText,
|
|
195
214
|
element_type: "icon",
|
|
196
|
-
element_title:
|
|
215
|
+
element_title: this.copyBtnText,
|
|
197
216
|
content_category: "code block"
|
|
198
217
|
});
|
|
199
218
|
|
|
200
219
|
try {
|
|
201
|
-
const snippetContainer: HTMLElement | null =
|
|
202
|
-
|
|
220
|
+
const snippetContainer: HTMLElement | null = this.template.querySelector(
|
|
221
|
+
".code-block-content"
|
|
222
|
+
);
|
|
203
223
|
if (snippetContainer && snippetContainer.textContent) {
|
|
204
224
|
await navigator.clipboard.writeText(
|
|
205
225
|
snippetContainer.textContent
|
|
@@ -221,7 +241,7 @@ export default class CodeBlock extends LightningElement {
|
|
|
221
241
|
gtmTrack(event.target, "custEv_iconClick", {
|
|
222
242
|
click_text: this.updateThemeBtnText,
|
|
223
243
|
element_type: "icon",
|
|
224
|
-
element_title:
|
|
244
|
+
element_title: this.updateThemeBtnText,
|
|
225
245
|
content_category: "code block"
|
|
226
246
|
});
|
|
227
247
|
}
|
|
@@ -172,8 +172,9 @@ export default class Dropdown extends LightningElement {
|
|
|
172
172
|
? this.findOptionElementIndex(this.value)
|
|
173
173
|
: 0;
|
|
174
174
|
|
|
175
|
-
const optionToFocus: any =
|
|
176
|
-
|
|
175
|
+
const optionToFocus: any = this.optionsElements[
|
|
176
|
+
defaultIndex < 0 ? 0 : defaultIndex
|
|
177
|
+
];
|
|
177
178
|
if (optionToFocus) {
|
|
178
179
|
optionToFocus.focus();
|
|
179
180
|
this._focusedValue = optionToFocus.option.id;
|
|
@@ -49,7 +49,7 @@ export default class DropdownOption extends LightningElement {
|
|
|
49
49
|
click_url: this.option.link?.href,
|
|
50
50
|
element_type: this.analyticsPayload?.element_type || "dropdown",
|
|
51
51
|
...(this.analyticsPayload?.nav_type
|
|
52
|
-
? { nav_item: this.option.label }
|
|
52
|
+
? { nav_item: `${this.navItemLabel}:${this.option.label}` }
|
|
53
53
|
: {})
|
|
54
54
|
});
|
|
55
55
|
}
|
|
@@ -205,7 +205,7 @@ export default class FeaturedContentHeader extends LightningElement {
|
|
|
205
205
|
track(event.target!, trackEvent, {
|
|
206
206
|
media_name: this.title,
|
|
207
207
|
media_action: action,
|
|
208
|
-
media_episode: this.
|
|
208
|
+
media_episode: this.title.split(":")[0],
|
|
209
209
|
media_percentage_played: percentagePlayed,
|
|
210
210
|
media_seconds_played: timePlayed,
|
|
211
211
|
media_type: "podcast"
|
|
@@ -62,10 +62,7 @@
|
|
|
62
62
|
stroke-width="2"
|
|
63
63
|
stroke-linecap="round"
|
|
64
64
|
stroke-linejoin="round"
|
|
65
|
-
class="
|
|
66
|
-
feather feather-chevron-down
|
|
67
|
-
year-caret
|
|
68
|
-
"
|
|
65
|
+
class="feather feather-chevron-down year-caret"
|
|
69
66
|
>
|
|
70
67
|
<polyline
|
|
71
68
|
points="6 9 12 15 18 9"
|
|
@@ -88,9 +85,7 @@
|
|
|
88
85
|
{month.id}
|
|
89
86
|
<span
|
|
90
87
|
if:true={filtersDatesLoading}
|
|
91
|
-
class="
|
|
92
|
-
filters-dates-loading
|
|
93
|
-
"
|
|
88
|
+
class="filters-dates-loading"
|
|
94
89
|
></span>
|
|
95
90
|
<span
|
|
96
91
|
if:false={filtersDatesLoading}
|
|
@@ -80,10 +80,9 @@ export default class FilterMenu extends LightningElement {
|
|
|
80
80
|
|
|
81
81
|
private setIntedeterminateStatus(checkbox: any, value: boolean) {
|
|
82
82
|
if ("isYear" in checkbox.value && !checkbox.value.isYear) {
|
|
83
|
-
const yearCheckBox: any =
|
|
84
|
-
checkbox
|
|
85
|
-
|
|
86
|
-
);
|
|
83
|
+
const yearCheckBox: any = checkbox.parentElement.parentElement.parentElement.querySelector(
|
|
84
|
+
".checkbox-year"
|
|
85
|
+
);
|
|
87
86
|
yearCheckBox.indeterminate = value;
|
|
88
87
|
}
|
|
89
88
|
}
|
|
@@ -81,7 +81,8 @@ export const generalLinksRaw: OptionWithRequiredNested[] = [
|
|
|
81
81
|
options: [
|
|
82
82
|
{
|
|
83
83
|
link: {
|
|
84
|
-
href:
|
|
84
|
+
href:
|
|
85
|
+
"https://trailhead.salesforce.com/trailblazer-community/feed"
|
|
85
86
|
},
|
|
86
87
|
label: "Trailblazer Community",
|
|
87
88
|
id: "Trailblazer Community"
|
|
@@ -158,7 +159,8 @@ export const termsLinks = [
|
|
|
158
159
|
label: "Legal"
|
|
159
160
|
},
|
|
160
161
|
{
|
|
161
|
-
href:
|
|
162
|
+
href:
|
|
163
|
+
"https://www.salesforce.com/company/privacy/full_privacy/#nav_info",
|
|
162
164
|
label: "Use of Cookies"
|
|
163
165
|
},
|
|
164
166
|
{ href: "https://trust.salesforce.com/en/", label: "Trust" },
|
|
@@ -13,12 +13,13 @@ export default class FooterOption extends LightningElement {
|
|
|
13
13
|
click_text: this.label || undefined,
|
|
14
14
|
click_url: this.href || undefined,
|
|
15
15
|
nav_item: this.label || undefined,
|
|
16
|
+
nav_level: "2",
|
|
16
17
|
element_type: "link",
|
|
17
18
|
nav_type: "footer"
|
|
18
19
|
});
|
|
19
20
|
track(e.currentTarget!, "custEv_linkClick", {
|
|
20
21
|
click_text: this.label,
|
|
21
|
-
element_title:
|
|
22
|
+
element_title: this.label,
|
|
22
23
|
click_url: this.href,
|
|
23
24
|
element_type: "link",
|
|
24
25
|
content_category: "cta"
|
|
@@ -67,8 +67,6 @@ export default class Grid extends LightningElement {
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
onSlotChange(e: Event) {
|
|
70
|
-
this._itemCount = (
|
|
71
|
-
e.target as LightningSlotElement
|
|
72
|
-
).assignedElements().length;
|
|
70
|
+
this._itemCount = (e.target as LightningSlotElement).assignedElements().length;
|
|
73
71
|
}
|
|
74
72
|
}
|
|
@@ -41,12 +41,12 @@ export default class MainContentHeader extends LightningElement {
|
|
|
41
41
|
click_text: this.ctaLabel,
|
|
42
42
|
click_url: this.ctaHref,
|
|
43
43
|
element_type: "button",
|
|
44
|
-
element_title:
|
|
44
|
+
element_title: this.ctaLabel,
|
|
45
45
|
content_category: "cta"
|
|
46
46
|
});
|
|
47
47
|
track(e.currentTarget!, "custEv_linkClick", {
|
|
48
48
|
click_text: this.ctaLabel,
|
|
49
|
-
element_title:
|
|
49
|
+
element_title: this.ctaLabel,
|
|
50
50
|
click_url: this.ctaHref,
|
|
51
51
|
element_type: "link",
|
|
52
52
|
content_category: "cta"
|
|
@@ -60,12 +60,12 @@ export default class MainContentHeader extends LightningElement {
|
|
|
60
60
|
click_text: this.ctaLabelSecondary,
|
|
61
61
|
click_url: this.ctaHrefSecondary,
|
|
62
62
|
element_type: "button",
|
|
63
|
-
element_title:
|
|
63
|
+
element_title: this.ctaLabelSecondary,
|
|
64
64
|
content_category: "cta"
|
|
65
65
|
});
|
|
66
66
|
track(e.currentTarget!, "custEv_linkClick", {
|
|
67
67
|
click_text: this.ctaLabelSecondary,
|
|
68
|
-
element_title:
|
|
68
|
+
element_title: this.ctaLabelSecondary,
|
|
69
69
|
click_url: this.ctaHrefSecondary,
|
|
70
70
|
element_type: "link",
|
|
71
71
|
content_category: "cta"
|
|
@@ -246,9 +246,9 @@ export default class Popover extends LightningElement {
|
|
|
246
246
|
const elements = slot.assignedElements();
|
|
247
247
|
const slotted = elements.length === 0 ? null : elements[0];
|
|
248
248
|
// allows dropdown/select to compose popover
|
|
249
|
-
const slotElement = (
|
|
250
|
-
|
|
251
|
-
|
|
249
|
+
const slotElement = (slotted?.tagName === "SLOT"
|
|
250
|
+
? slotted.firstChild
|
|
251
|
+
: slotted) as HTMLElement | null;
|
|
252
252
|
const isWorkToDo =
|
|
253
253
|
slotElement &&
|
|
254
254
|
(!this.control || !slotElement.isSameNode(this.control));
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { LightningElement } from "lwc";
|
|
2
2
|
import { throttle } from "throttle-debounce";
|
|
3
|
+
import { track } from "dxUtils/analytics";
|
|
3
4
|
|
|
4
5
|
const RESTORE_SCROLL_EVENT_NAME = "restore-scroll";
|
|
5
6
|
const LOAD_TIME_SCROLL_RESTORE_DELAY = 750;
|
|
@@ -17,29 +18,36 @@ export const restoreScroll = () => {
|
|
|
17
18
|
return;
|
|
18
19
|
}
|
|
19
20
|
document.body.scrollTop = document.documentElement.scrollTop =
|
|
20
|
-
window.history.state?.scroll
|
|
21
|
+
window.history.state?.scroll?.value;
|
|
21
22
|
};
|
|
22
23
|
|
|
23
24
|
export default class ScrollManager extends LightningElement {
|
|
24
25
|
/*
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
26
|
+
WARNING: Dark Magic(TM) follows. This code is likely to be unreliable if:
|
|
27
|
+
- Our load times significantly change (in this case, LOAD_TIME_SCROLL_RESTORE_DELAY may need to be adjusted)
|
|
28
|
+
- Any other components attempt to manipulate the body scroll (including #a links) before LOAD_TIME_SCROLL_RESTORE_DELAY has expired
|
|
29
|
+
|
|
30
|
+
This Dark Magic(TM) was required because of the following super annoying race condition occuring while trying to restore scroll position:
|
|
31
|
+
1. Load a page on our site (reproducible consistently at time of writing at https://developer.salesforce.com)
|
|
32
|
+
2. Scroll down somewhere (remember where)
|
|
33
|
+
3. Navigate to another page
|
|
34
|
+
4. Navigate back/forward/back, using the browser forward/back buttons (sometimes it takes a few tries to reproduce the race condition)
|
|
35
|
+
5. If the page you're on takes long enough for its components to finish rendering asynchronously, sometimes your scroll position will be incorrect
|
|
36
|
+
(until the second scroll restore is called. To see the really bad behavior, simply remove the window.setTimeout bit)
|
|
37
|
+
This is because basically it scrolls you down a bit, then a component gets bigger above you as it finishes rendering
|
|
38
|
+
This pushes your whole view down, so unless we do this Dark Magic(TM) where we attempt to restore scroll _again_
|
|
39
|
+
after some reasonable interval, your window will be in the wrong spot when everything finishes rendering
|
|
40
|
+
*/
|
|
40
41
|
|
|
41
42
|
protected scrollCount = 0; // this is for dark magic, basically we lock the user out of scrolling in the first quarter second, unless they really mean it. We do this because load timings mean that the scroll can get messed up in that period
|
|
42
43
|
|
|
44
|
+
private scrollPosition = 0;
|
|
45
|
+
private scrolledTwentyFivePercent = false;
|
|
46
|
+
private scrolledFiftyPercent = false;
|
|
47
|
+
private scrolledSevenFivePercent = false;
|
|
48
|
+
private scrolledOneHundredPercent = false;
|
|
49
|
+
private scrollUnlocked = false;
|
|
50
|
+
|
|
43
51
|
renderedCallback() {
|
|
44
52
|
scrollUnlocked = window.location.hash !== ""; // if we have anchor links, skip the entire scroll restore
|
|
45
53
|
if (!globalThis.singletonScrollManagerRendered && !scrollUnlocked) {
|
|
@@ -51,12 +59,22 @@ export default class ScrollManager extends LightningElement {
|
|
|
51
59
|
// only do this if loading is complete and the scrollHeight matches expectations
|
|
52
60
|
// otherwise, we're likely still loading, so just chill to avoid jumping around so much
|
|
53
61
|
restoreScroll();
|
|
62
|
+
this.setScrolledPercentagesFromRestore(
|
|
63
|
+
this.calculateScrollPercentage(
|
|
64
|
+
+window.history.state?.scroll?.value
|
|
65
|
+
)
|
|
66
|
+
);
|
|
54
67
|
} else {
|
|
55
68
|
window.setTimeout(() => {
|
|
56
69
|
// sometimes loading is slow, so we may want to reset the scroll to
|
|
57
70
|
// the correct position after loading is complete, to avoid weird behavior
|
|
58
71
|
// but only if the user hasn't scrolled around in the meantime
|
|
59
72
|
restoreScroll();
|
|
73
|
+
this.setScrolledPercentagesFromRestore(
|
|
74
|
+
this.calculateScrollPercentage(
|
|
75
|
+
+window.history.state?.scroll?.value
|
|
76
|
+
)
|
|
77
|
+
);
|
|
60
78
|
scrollUnlocked = true;
|
|
61
79
|
}, LOAD_TIME_SCROLL_RESTORE_DELAY);
|
|
62
80
|
}
|
|
@@ -80,6 +98,56 @@ export default class ScrollManager extends LightningElement {
|
|
|
80
98
|
}
|
|
81
99
|
}
|
|
82
100
|
|
|
101
|
+
sendGtmScrollThresholdEvent(threshold: "25" | "50" | "75" | "100") {
|
|
102
|
+
track(document.body, "custEv_scroll", {
|
|
103
|
+
scrollDepth: threshold
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
calculateScrollPercentage(scrollTop: number = document.body.scrollTop) {
|
|
108
|
+
return (
|
|
109
|
+
(scrollTop / (document.body.scrollHeight - window.innerHeight)) *
|
|
110
|
+
100
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// do not re-send scrolled events when scroll position is restored and user scrolls up
|
|
115
|
+
setScrolledPercentagesFromRestore(scrollPercentage: number) {
|
|
116
|
+
if (scrollPercentage > 25) {
|
|
117
|
+
this.scrolledTwentyFivePercent = true;
|
|
118
|
+
}
|
|
119
|
+
if (scrollPercentage > 50) {
|
|
120
|
+
this.scrolledFiftyPercent = true;
|
|
121
|
+
}
|
|
122
|
+
if (scrollPercentage > 75) {
|
|
123
|
+
this.scrolledSevenFivePercent = true;
|
|
124
|
+
}
|
|
125
|
+
if (scrollPercentage > 100) {
|
|
126
|
+
this.scrolledOneHundredPercent = true;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
scrollThresholdHandler() {
|
|
131
|
+
this.scrollPosition = this.calculateScrollPercentage();
|
|
132
|
+
|
|
133
|
+
if (this.scrollPosition > 25 && !this.scrolledTwentyFivePercent) {
|
|
134
|
+
this.scrolledTwentyFivePercent = true;
|
|
135
|
+
this.sendGtmScrollThresholdEvent("25");
|
|
136
|
+
} else if (this.scrollPosition > 50 && !this.scrolledFiftyPercent) {
|
|
137
|
+
this.scrolledFiftyPercent = true;
|
|
138
|
+
this.sendGtmScrollThresholdEvent("50");
|
|
139
|
+
} else if (this.scrollPosition > 75 && !this.scrolledSevenFivePercent) {
|
|
140
|
+
this.scrolledSevenFivePercent = true;
|
|
141
|
+
this.sendGtmScrollThresholdEvent("75");
|
|
142
|
+
} else if (
|
|
143
|
+
this.scrollPosition === 100 &&
|
|
144
|
+
!this.scrolledOneHundredPercent
|
|
145
|
+
) {
|
|
146
|
+
this.scrolledOneHundredPercent = true;
|
|
147
|
+
this.sendGtmScrollThresholdEvent("100");
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
83
151
|
saveScroll = throttle(100, () => {
|
|
84
152
|
window.history.replaceState(
|
|
85
153
|
{
|
|
@@ -101,6 +169,7 @@ export default class ScrollManager extends LightningElement {
|
|
|
101
169
|
}
|
|
102
170
|
if (this.scrollUnlocked) {
|
|
103
171
|
this.saveScroll();
|
|
172
|
+
this.scrollThresholdHandler();
|
|
104
173
|
}
|
|
105
174
|
};
|
|
106
175
|
|
|
@@ -17,7 +17,9 @@ interface CoveoSearch {
|
|
|
17
17
|
|
|
18
18
|
declare const Coveo: CoveoSearch;
|
|
19
19
|
|
|
20
|
-
function getPaginationState(
|
|
20
|
+
function getPaginationState(
|
|
21
|
+
event: CoveoSDK.IQuerySuccessEventArgs
|
|
22
|
+
): {
|
|
21
23
|
numberOfPages: number;
|
|
22
24
|
currentPage: number;
|
|
23
25
|
} {
|
|
@@ -79,8 +79,9 @@ export default class Select extends LightningElement {
|
|
|
79
79
|
|
|
80
80
|
get selectElement() {
|
|
81
81
|
if (!this._selectElement) {
|
|
82
|
-
this._selectElement =
|
|
83
|
-
|
|
82
|
+
this._selectElement = this.template.querySelector<HTMLSelectElement>(
|
|
83
|
+
"select"
|
|
84
|
+
);
|
|
84
85
|
}
|
|
85
86
|
return this._selectElement;
|
|
86
87
|
}
|
|
@@ -51,11 +51,9 @@ export default class Sidebar extends SidebarBase {
|
|
|
51
51
|
|
|
52
52
|
@api
|
|
53
53
|
setInputValue(searchTerm: string) {
|
|
54
|
-
(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
) as unknown as SidebarSearch
|
|
58
|
-
)?.setInputValue(searchTerm);
|
|
54
|
+
((this.template.querySelector(
|
|
55
|
+
"dx-sidebar-search"
|
|
56
|
+
) as unknown) as SidebarSearch)?.setInputValue(searchTerm);
|
|
59
57
|
}
|
|
60
58
|
|
|
61
59
|
private expanded: boolean = true;
|
|
@@ -169,8 +167,6 @@ export default class Sidebar extends SidebarBase {
|
|
|
169
167
|
|
|
170
168
|
private onSelect(event: CustomEvent) {
|
|
171
169
|
this._value = event.detail.name;
|
|
172
|
-
|
|
173
|
-
this.dispatchEvent(new CustomEvent("sidebarclick"));
|
|
174
170
|
}
|
|
175
171
|
|
|
176
172
|
private onToggleClick(event: Event) {
|
|
@@ -217,9 +213,9 @@ export default class Sidebar extends SidebarBase {
|
|
|
217
213
|
return;
|
|
218
214
|
}
|
|
219
215
|
|
|
220
|
-
const search = this.template.querySelector(
|
|
216
|
+
const search = (this.template.querySelector(
|
|
221
217
|
"dx-sidebar-search"
|
|
222
|
-
) as unknown as SidebarSearch;
|
|
218
|
+
) as unknown) as SidebarSearch;
|
|
223
219
|
|
|
224
220
|
if (
|
|
225
221
|
this.isNearBottomOfSearchResults &&
|