@salesforcedevs/dx-components 1.3.38 → 1.3.40-alpha.0
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 +4 -3
- package/src/assets/icons/terms-privacy/privacyicon.png +0 -0
- package/src/modules/dx/cardBlogPost/cardBlogPost.html +1 -3
- package/src/modules/dx/cardBlogPost/cardBlogPost.ts +1 -3
- package/src/modules/dx/cardContent/cardContent.css +5 -0
- package/src/modules/dx/cardContent/cardContent.html +10 -6
- package/src/modules/dx/cardContent/cardContent.ts +22 -7
- package/src/modules/dx/cardExpanded/cardExpanded.css +15 -5
- package/src/modules/dx/cardExpanded/cardExpanded.html +9 -5
- package/src/modules/dx/cardExpanded/cardExpanded.ts +24 -8
- package/src/modules/dx/cardTrial/cardTrial.html +2 -0
- package/src/modules/dx/cardTrial/cardTrial.ts +32 -1
- package/src/modules/dx/cardTrialExpanded/cardTrialExpanded.html +1 -0
- package/src/modules/dx/cardTrialExpanded/cardTrialExpanded.ts +13 -0
- package/src/modules/dx/codeBlock/codeBlock.ts +10 -4
- package/src/modules/dx/dropdown/dropdown.html +2 -4
- package/src/modules/dx/dropdown/dropdown.ts +2 -7
- package/src/modules/dx/dropdownOption/dropdownOption.ts +11 -21
- package/src/modules/dx/featuredContentHeader/featuredContentHeader.ts +1 -1
- package/src/modules/dx/footer/footer.css +5 -0
- package/src/modules/dx/footer/footer.html +6 -0
- package/src/modules/dx/footer/footer.ts +4 -8
- package/src/modules/dx/footer/links.ts +5 -0
- package/src/modules/dx/footerOption/footerOption.ts +5 -4
- package/src/modules/dx/groupText/groupText.ts +6 -12
- package/src/modules/dx/headerNav/headerNav.html +1 -0
- package/src/modules/dx/headerNav/headerNav.ts +4 -0
- package/src/modules/dx/mainContentHeader/mainContentHeader.html +2 -2
- package/src/modules/dx/mainContentHeader/mainContentHeader.ts +11 -3
- package/src/modules/dx/pagination/pagination.ts +6 -9
- package/src/modules/dx/scrollManager/scrollManager.ts +14 -9
- package/src/modules/dx/tab/tab.ts +6 -3
- package/src/modules/dx/treeItem/treeItem.ts +14 -5
- package/src/modules/dxBaseElements/headerBase/headerBase.ts +6 -6
- package/src/modules/dxUtils/normalizers/normalizers.ts +1 -3
- package/LICENSE +0 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforcedevs/dx-components",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.40-alpha.0",
|
|
4
4
|
"description": "DX Lightning web components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": {
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"@coveo/headless": "^1.32.0",
|
|
14
14
|
"@floating-ui/dom": "^1.0.4",
|
|
15
15
|
"@sfdocs-internal/wires": "^0.6.3",
|
|
16
|
+
"@types/throttle-debounce": "^5.0.0",
|
|
16
17
|
"@vimeo/player": "^2.16.4",
|
|
17
18
|
"classnames": "^2.2.6",
|
|
18
19
|
"coveo-search-ui": "^2.10082.5",
|
|
@@ -23,6 +24,7 @@
|
|
|
23
24
|
"lodash.kebabcase": "^4.1.1",
|
|
24
25
|
"microtip": "0.2.2",
|
|
25
26
|
"salesforce-oauth2": "^0.2.0",
|
|
27
|
+
"throttle-debounce": "^5.0.0",
|
|
26
28
|
"uuid": "^9.0.0"
|
|
27
29
|
},
|
|
28
30
|
"devDependencies": {
|
|
@@ -37,6 +39,5 @@
|
|
|
37
39
|
"@types/vimeo__player": "^2.16.2",
|
|
38
40
|
"eventsourcemock": "^2.0.0",
|
|
39
41
|
"luxon": "^3.1.0"
|
|
40
|
-
}
|
|
41
|
-
"gitHead": "9cc8fbc4b276d28eb128f5f7fd1eec7844e831b2"
|
|
42
|
+
}
|
|
42
43
|
}
|
|
Binary file
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { LightningElement, api } from "lwc";
|
|
2
2
|
|
|
3
3
|
export default class CardBlogPost extends LightningElement {
|
|
4
|
-
@api authorHref?: string | null = null;
|
|
5
|
-
@api authorImgSrc!: string | null;
|
|
6
|
-
@api authorLabel!: string | null;
|
|
7
4
|
@api body!: string;
|
|
8
5
|
@api datetime!: string;
|
|
9
6
|
@api dateTime?: string | null = null;
|
|
@@ -14,6 +11,7 @@ export default class CardBlogPost extends LightningElement {
|
|
|
14
11
|
@api label?: string;
|
|
15
12
|
@api target?: string | null = null;
|
|
16
13
|
@api title!: string;
|
|
14
|
+
@api authors?: Array<any> | null = null;
|
|
17
15
|
|
|
18
16
|
// LWC is being compiled so that datetime is being interpreted as date-time
|
|
19
17
|
// ONLY from from the implementation in dx-card-blog-post-provider
|
|
@@ -42,12 +42,16 @@
|
|
|
42
42
|
>
|
|
43
43
|
{subtitle}
|
|
44
44
|
</span>
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
<div class="authors" if:true={authors}>
|
|
46
|
+
<template for:each={authors} for:item="author">
|
|
47
|
+
<dx-image-and-label
|
|
48
|
+
key={author.key}
|
|
49
|
+
img-src={author.imgSrc}
|
|
50
|
+
label={author.name}
|
|
51
|
+
href={author.href}
|
|
52
|
+
></dx-image-and-label>
|
|
53
|
+
</template>
|
|
54
|
+
</div>
|
|
51
55
|
<span if:true={body} class="body dx-text-body-2" part="body">
|
|
52
56
|
{body}
|
|
53
57
|
</span>
|
|
@@ -3,11 +3,10 @@ import cx from "classnames";
|
|
|
3
3
|
import { LightningSlotElement } from "typings/custom";
|
|
4
4
|
import { isSlotEmpty } from "dxUtils/slot";
|
|
5
5
|
import { toDxColor } from "dxUtils/css";
|
|
6
|
+
import { toJson } from "dxUtils/normalizers";
|
|
7
|
+
import { ImageAndLabel } from "../imageAndLabel";
|
|
6
8
|
|
|
7
9
|
export default class CardContent extends LightningElement {
|
|
8
|
-
@api authorHref?: string | null = null;
|
|
9
|
-
@api authorImgSrc?: string | null = null;
|
|
10
|
-
@api authorLabel?: string | null = null;
|
|
11
10
|
@api backgroundColor?: string | null = null;
|
|
12
11
|
@api body?: string | null = null;
|
|
13
12
|
@api featured?: boolean = false;
|
|
@@ -19,14 +18,30 @@ export default class CardContent extends LightningElement {
|
|
|
19
18
|
@api subtitle?: string | null = null;
|
|
20
19
|
@api target?: string | null = null;
|
|
21
20
|
@api title!: string;
|
|
21
|
+
@api
|
|
22
|
+
get authors() {
|
|
23
|
+
if (this._authors && this._authors.length) {
|
|
24
|
+
return this._authors!.map((author, index) => ({
|
|
25
|
+
...author,
|
|
26
|
+
imgSrc: author.image_src,
|
|
27
|
+
key: index
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
set authors(value: any) {
|
|
34
|
+
if (value !== "undefined") {
|
|
35
|
+
this._authors = (toJson(value) as Array<any>)?.filter(
|
|
36
|
+
(author) => author.name
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
private _authors?: Array<ImageAndLabel>;
|
|
22
41
|
|
|
23
42
|
private isDatetimeEmpty: boolean = true;
|
|
24
43
|
private isLinkHovered: boolean = false;
|
|
25
44
|
|
|
26
|
-
private get hasAuthor() {
|
|
27
|
-
return this.authorImgSrc && this.authorLabel;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
45
|
private get backgroundStyle(): string {
|
|
31
46
|
return this.backgroundColor
|
|
32
47
|
? `background: ${toDxColor(this.backgroundColor)}`
|
|
@@ -12,6 +12,7 @@ dx-formatted-date-time,
|
|
|
12
12
|
.podcast-length {
|
|
13
13
|
/* Push down a little to align with dx-image-and-label */
|
|
14
14
|
margin-top: 3px;
|
|
15
|
+
margin-right: var(--dx-g-spacing-sm);
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
.card-body {
|
|
@@ -19,8 +20,7 @@ dx-formatted-date-time,
|
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
.card-extra-info {
|
|
22
|
-
|
|
23
|
-
align-items: center;
|
|
23
|
+
text-align: start;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
.card-container {
|
|
@@ -28,11 +28,19 @@ dx-formatted-date-time,
|
|
|
28
28
|
padding-bottom: var(--dx-g-spacing-xl);
|
|
29
29
|
flex-direction: column;
|
|
30
30
|
gap: var(--dx-g-spacing-smd);
|
|
31
|
+
display: flex;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
.card-
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
.card-extra-info .authors {
|
|
35
|
+
margin-bottom: var(--dx-g-spacing-smd);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.card-extra-info .authors > *:not(:last-child) {
|
|
39
|
+
padding-right: var(--dx-g-spacing-md);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.card-extra-info .authors > * {
|
|
43
|
+
display: inline-flex;
|
|
36
44
|
}
|
|
37
45
|
|
|
38
46
|
.card-dot-separator {
|
|
@@ -43,6 +51,8 @@ dx-formatted-date-time,
|
|
|
43
51
|
background-color: var(--dx-g-text-label-color);
|
|
44
52
|
border-radius: 100%;
|
|
45
53
|
margin-bottom: 3px;
|
|
54
|
+
display: inline-block;
|
|
55
|
+
margin-right: var(--dx-g-spacing-sm);
|
|
46
56
|
}
|
|
47
57
|
|
|
48
58
|
.card-mobile .card-body {
|
|
@@ -8,11 +8,15 @@
|
|
|
8
8
|
title={title}
|
|
9
9
|
></dx-card-title>
|
|
10
10
|
<div class="card-extra-info dx-text-label-1-dark">
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
<div class="authors" if:true={renderAuthor}>
|
|
12
|
+
<template for:each={authors} for:item="author">
|
|
13
|
+
<dx-image-and-label
|
|
14
|
+
key={author.key}
|
|
15
|
+
label={author.name}
|
|
16
|
+
img-src={author.imgSrc}
|
|
17
|
+
></dx-image-and-label>
|
|
18
|
+
</template>
|
|
19
|
+
</div>
|
|
16
20
|
<span class="podcast-length" if:true={renderLength}>{length}</span>
|
|
17
21
|
<span if:true={renderDot} class="card-dot-separator"></span>
|
|
18
22
|
<dx-formatted-date-time
|
|
@@ -1,21 +1,41 @@
|
|
|
1
1
|
import { api } from "lwc";
|
|
2
2
|
import { ArchiveCard } from "dxBaseElements/archiveCard";
|
|
3
3
|
import cx from "classnames";
|
|
4
|
+
import ImageAndLabel from "../imageAndLabel";
|
|
5
|
+
import { toJson } from "dxUtils/normalizers";
|
|
4
6
|
|
|
5
7
|
export default class ExpandedCard extends ArchiveCard {
|
|
6
8
|
@api body!: string;
|
|
7
9
|
@api date: string | null = null;
|
|
8
10
|
@api topics: Array<string> = [];
|
|
9
|
-
@api authorLabel?: string | null = null;
|
|
10
|
-
@api authorImgSrc?: string | null = null;
|
|
11
11
|
@api length?: string;
|
|
12
|
+
@api
|
|
13
|
+
get authors() {
|
|
14
|
+
if (this._authors && this._authors.length) {
|
|
15
|
+
return this._authors!.map((author, index) => ({
|
|
16
|
+
...author,
|
|
17
|
+
imgSrc: !this.mobile ? author.image_src : "",
|
|
18
|
+
key: index
|
|
19
|
+
}));
|
|
20
|
+
}
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
set authors(value: any) {
|
|
25
|
+
if (value !== "undefined") {
|
|
26
|
+
this._authors = (toJson(value) as Array<any>)?.filter(
|
|
27
|
+
(author) => author.name
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
private _authors?: Array<ImageAndLabel>;
|
|
12
32
|
|
|
13
33
|
private get isBlog(): boolean {
|
|
14
34
|
return this.contentType === "blog";
|
|
15
35
|
}
|
|
16
36
|
|
|
17
37
|
private get hasAuthor(): boolean {
|
|
18
|
-
return
|
|
38
|
+
return this.authors?.length;
|
|
19
39
|
}
|
|
20
40
|
|
|
21
41
|
private get renderAuthor(): boolean {
|
|
@@ -27,17 +47,13 @@ export default class ExpandedCard extends ArchiveCard {
|
|
|
27
47
|
}
|
|
28
48
|
|
|
29
49
|
private get renderDot(): boolean {
|
|
30
|
-
return !!(
|
|
50
|
+
return !!(this.renderLength && this.date);
|
|
31
51
|
}
|
|
32
52
|
|
|
33
53
|
private get hasTopics(): boolean {
|
|
34
54
|
return !!this.topics?.length;
|
|
35
55
|
}
|
|
36
56
|
|
|
37
|
-
private get authorImage(): string {
|
|
38
|
-
return !this.mobile && this.authorImgSrc ? this.authorImgSrc : "";
|
|
39
|
-
}
|
|
40
|
-
|
|
41
57
|
private get containerClass(): string {
|
|
42
58
|
return cx("card-container", this.mobile && "card-mobile");
|
|
43
59
|
}
|
|
@@ -69,6 +69,7 @@
|
|
|
69
69
|
size="large"
|
|
70
70
|
href={buttonOneHref}
|
|
71
71
|
variant="primary"
|
|
72
|
+
target={buttonOneTarget}
|
|
72
73
|
font="sans"
|
|
73
74
|
icon-symbol={buttonOneIcon}
|
|
74
75
|
icon-size={buttonOneIconSize}
|
|
@@ -82,6 +83,7 @@
|
|
|
82
83
|
href={buttonOneHref}
|
|
83
84
|
variant="primary"
|
|
84
85
|
font="sans"
|
|
86
|
+
target={buttonOneTarget}
|
|
85
87
|
icon-symbol={buttonOneIcon}
|
|
86
88
|
icon-size={buttonOneIconSize}
|
|
87
89
|
>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { LightningElement, api } from "lwc";
|
|
2
2
|
import cx from "classnames";
|
|
3
3
|
import { toJson } from "dxUtils/normalizers";
|
|
4
|
+
import { track } from "dxUtils/analytics";
|
|
4
5
|
|
|
5
6
|
export default class CardTrial extends LightningElement {
|
|
6
7
|
@api badgeBackgroundColor?: string = "indigo-vibrant-90";
|
|
@@ -71,6 +72,10 @@ export default class CardTrial extends LightningElement {
|
|
|
71
72
|
return this.hasButtons ? "menu" : "link";
|
|
72
73
|
}
|
|
73
74
|
|
|
75
|
+
get buttonOneTarget() {
|
|
76
|
+
return this.isExternalURL(this.buttonOneHref) ? "_blank" : null;
|
|
77
|
+
}
|
|
78
|
+
|
|
74
79
|
private _details!: string[];
|
|
75
80
|
private _modalDetails!: [{ title: string; subtitle: string }];
|
|
76
81
|
private _modalOpen = false;
|
|
@@ -93,10 +98,36 @@ export default class CardTrial extends LightningElement {
|
|
|
93
98
|
this._modalOpen = !this._modalOpen;
|
|
94
99
|
}
|
|
95
100
|
|
|
96
|
-
private handleClick() {
|
|
101
|
+
private handleClick(e: PointerEvent) {
|
|
97
102
|
// card is clickable only if it doesn't contain buttons (for accessibility reasons)
|
|
98
103
|
if (!this.hasButtons) {
|
|
99
104
|
window.location.assign(this.href);
|
|
105
|
+
if (this.href.includes("signup")) {
|
|
106
|
+
this.handleSignUpClick(e);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private handleSignUpClick(e: PointerEvent) {
|
|
112
|
+
track(e.currentTarget!, "custEv_signupStart", {
|
|
113
|
+
click_text: this.label,
|
|
114
|
+
element_title: this.title,
|
|
115
|
+
element_type: "card",
|
|
116
|
+
click_url: this.href,
|
|
117
|
+
content_category: "cta"
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private isExternalURL(url: string | undefined): boolean {
|
|
122
|
+
if (!url) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
const value = new URL(url);
|
|
128
|
+
return value.host !== window.location.host;
|
|
129
|
+
} catch (e) {
|
|
130
|
+
return false;
|
|
100
131
|
}
|
|
101
132
|
}
|
|
102
133
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { LightningElement, api } from "lwc";
|
|
2
2
|
import { toJson } from "dxUtils/normalizers";
|
|
3
|
+
import { track } from "dxUtils/analytics";
|
|
3
4
|
|
|
4
5
|
export default class CardTrial extends LightningElement {
|
|
5
6
|
@api badgeBackgroundColor?: string = "indigo-vibrant-90";
|
|
@@ -64,4 +65,16 @@ export default class CardTrial extends LightningElement {
|
|
|
64
65
|
private handleModalClose() {
|
|
65
66
|
this.dispatchEvent(new CustomEvent("togglemodal"));
|
|
66
67
|
}
|
|
68
|
+
|
|
69
|
+
private handleSignUpClick(e: PointerEvent) {
|
|
70
|
+
if (this.href.includes("signup")) {
|
|
71
|
+
track(e.currentTarget!, "custEv_signupStart", {
|
|
72
|
+
click_text: this.buttonCta,
|
|
73
|
+
element_title: this.title,
|
|
74
|
+
element_type: "card",
|
|
75
|
+
click_url: this.href,
|
|
76
|
+
content_category: "cta"
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
67
80
|
}
|
|
@@ -181,8 +181,11 @@ export default class CodeBlock extends LightningElement {
|
|
|
181
181
|
* https://github.com/storybookjs/storybook/issues/13529
|
|
182
182
|
*/
|
|
183
183
|
async copySource(event: any) {
|
|
184
|
-
gtmTrack(event.target, "
|
|
185
|
-
|
|
184
|
+
gtmTrack(event.target, "custEv_iconClick", {
|
|
185
|
+
clickText: this.copyBtnText,
|
|
186
|
+
elementType: "icon",
|
|
187
|
+
elementTitle: "dx-icon",
|
|
188
|
+
contentCategory: "code block"
|
|
186
189
|
});
|
|
187
190
|
|
|
188
191
|
try {
|
|
@@ -206,8 +209,11 @@ export default class CodeBlock extends LightningElement {
|
|
|
206
209
|
this.theme = this.theme === DARK ? LIGHT : DARK;
|
|
207
210
|
setLocalStorageData(LOCAL_STORAGE_KEY, this.theme);
|
|
208
211
|
|
|
209
|
-
gtmTrack(event.target, "
|
|
210
|
-
|
|
212
|
+
gtmTrack(event.target, "custEv_iconClick", {
|
|
213
|
+
clickText: this.updateThemeBtnText,
|
|
214
|
+
elementType: "icon",
|
|
215
|
+
elementTitle: "dx-icon",
|
|
216
|
+
contentCategory: "code block"
|
|
211
217
|
});
|
|
212
218
|
}
|
|
213
219
|
|
|
@@ -21,9 +21,8 @@
|
|
|
21
21
|
>
|
|
22
22
|
<template for:each={options} for:item="option" for:index="index">
|
|
23
23
|
<dx-dropdown-option
|
|
24
|
-
suppress-gtm-nav-headings={suppressGtmNavHeadings}
|
|
25
24
|
analytics-event={analyticsEvent}
|
|
26
|
-
analytics-
|
|
25
|
+
analytics-payload={analyticsPayload}
|
|
27
26
|
active={option.active}
|
|
28
27
|
key-value={option.keyValue}
|
|
29
28
|
if:false={option.options}
|
|
@@ -44,9 +43,8 @@
|
|
|
44
43
|
<span class="menu_heading">{option.label}</span>
|
|
45
44
|
<template for:each={option.options} for:item="suboption">
|
|
46
45
|
<dx-dropdown-option
|
|
47
|
-
suppress-gtm-nav-headings={suppressGTMNavHeadings}
|
|
48
46
|
analytics-event={analyticsEvent}
|
|
49
|
-
analytics-
|
|
47
|
+
analytics-payload={analyticsPayload}
|
|
50
48
|
active={suboption.active}
|
|
51
49
|
key={suboption.id}
|
|
52
50
|
key-value={suboption.keyValue}
|
|
@@ -38,13 +38,8 @@ export default class Dropdown extends LightningElement {
|
|
|
38
38
|
@api variant: DropdownVariant = "base";
|
|
39
39
|
|
|
40
40
|
// props forwarded to dropdown option
|
|
41
|
-
@api analyticsEvent
|
|
42
|
-
@api
|
|
43
|
-
elementType: "dropdown",
|
|
44
|
-
destinationType: "internal",
|
|
45
|
-
ctaClick: true
|
|
46
|
-
};
|
|
47
|
-
@api suppressGtmNavHeadings?: boolean = false;
|
|
41
|
+
@api analyticsEvent?: string;
|
|
42
|
+
@api analyticsPayload?: AnalyticsPayload;
|
|
48
43
|
|
|
49
44
|
@api
|
|
50
45
|
get options() {
|
|
@@ -9,12 +9,11 @@ import { track } from "dxUtils/analytics";
|
|
|
9
9
|
|
|
10
10
|
export default class DropdownOption extends LightningElement {
|
|
11
11
|
@api option!: OptionWithNested;
|
|
12
|
-
@api suppressGtmNavHeadings: boolean = false;
|
|
13
12
|
@api keyValue!: string;
|
|
14
13
|
@api active: boolean = false;
|
|
15
14
|
@api navItemLabel: String | null = null;
|
|
16
15
|
@api analyticsEvent: string | null = null;
|
|
17
|
-
@api
|
|
16
|
+
@api analyticsPayload?: AnalyticsPayload | undefined;
|
|
18
17
|
@api indexPosition: number = 0;
|
|
19
18
|
@api variant: DropdownVariant = "base";
|
|
20
19
|
|
|
@@ -43,25 +42,16 @@ export default class DropdownOption extends LightningElement {
|
|
|
43
42
|
new CustomEvent("select", { detail: this.keyValue })
|
|
44
43
|
);
|
|
45
44
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (!this.suppressGtmNavHeadings) {
|
|
58
|
-
payload.navHeading = navHeading;
|
|
59
|
-
payload.navSubHeading = navSubHeading;
|
|
60
|
-
payload.pageLocation = window.location.pathname;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (this.analyticsEvent && e.currentTarget) {
|
|
64
|
-
track(e.currentTarget, this.analyticsEvent, payload);
|
|
45
|
+
if (this.analyticsEvent && this.analyticsPayload && e.currentTarget) {
|
|
46
|
+
track(e.currentTarget, this.analyticsEvent, {
|
|
47
|
+
...this.analyticsPayload,
|
|
48
|
+
clickText: this.option.label,
|
|
49
|
+
clickUrl: this.option.link?.href,
|
|
50
|
+
elementType: this.analyticsPayload?.elementType || "dropdown",
|
|
51
|
+
...(this.analyticsPayload?.navType
|
|
52
|
+
? { navItem: this.option.label }
|
|
53
|
+
: {})
|
|
54
|
+
});
|
|
65
55
|
}
|
|
66
56
|
}
|
|
67
57
|
}
|
|
@@ -39,7 +39,7 @@ export default class FeaturedContentHeader extends LightningElement {
|
|
|
39
39
|
if (this._authors && this._authors.length) {
|
|
40
40
|
return this._authors!.map((author, index) => ({
|
|
41
41
|
...author,
|
|
42
|
-
imgSrc: author.
|
|
42
|
+
imgSrc: author.image_src,
|
|
43
43
|
key: index
|
|
44
44
|
}));
|
|
45
45
|
}
|
|
@@ -139,6 +139,12 @@
|
|
|
139
139
|
</template>
|
|
140
140
|
<template if:false={term.onclick}>
|
|
141
141
|
<a href={term.href} key={term.label} rel={term.rel}>
|
|
142
|
+
<img
|
|
143
|
+
if:true={term.img}
|
|
144
|
+
class="term-icon"
|
|
145
|
+
src={term.img}
|
|
146
|
+
alt="Footer Term Icon"
|
|
147
|
+
/>
|
|
142
148
|
{term.label}
|
|
143
149
|
</a>
|
|
144
150
|
</template>
|
|
@@ -18,12 +18,6 @@ const createNewsletterSignupHref = (email: string): string => {
|
|
|
18
18
|
return PATH;
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
const ANALYTICS_INFO = {
|
|
22
|
-
itemTitle: "Newsletter Sign Up Footer",
|
|
23
|
-
elementType: "button",
|
|
24
|
-
destinationType: "internal",
|
|
25
|
-
ctaClick: true
|
|
26
|
-
};
|
|
27
21
|
export default class Footer extends LightningElement {
|
|
28
22
|
@api locale: string | null = null;
|
|
29
23
|
@api
|
|
@@ -107,9 +101,11 @@ export default class Footer extends LightningElement {
|
|
|
107
101
|
const href = createNewsletterSignupHref(e.detail);
|
|
108
102
|
|
|
109
103
|
track(e.currentTarget, "custEv_ctaButtonClick", {
|
|
110
|
-
...ANALYTICS_INFO,
|
|
111
104
|
clickText: this.inputSubmitLabel,
|
|
112
|
-
clickUrl: PATH
|
|
105
|
+
clickUrl: PATH,
|
|
106
|
+
elementType: "button",
|
|
107
|
+
elementTitle: "dx-footer",
|
|
108
|
+
contentCategory: "cta"
|
|
113
109
|
});
|
|
114
110
|
|
|
115
111
|
window.location.assign(href);
|
|
@@ -167,6 +167,11 @@ export const termsLinks = [
|
|
|
167
167
|
rel: "nofollow",
|
|
168
168
|
label: "Cookie Preferences",
|
|
169
169
|
onclick: openOneTrustInfoDisplay
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
href: "https://www.salesforce.com/form/other/privacy-request/",
|
|
173
|
+
label: "Your Privacy Choices",
|
|
174
|
+
img: "/assets/icons/terms-privacy/privacyicon.png"
|
|
170
175
|
}
|
|
171
176
|
];
|
|
172
177
|
|
|
@@ -10,10 +10,11 @@ export default class FooterOption extends LightningElement {
|
|
|
10
10
|
|
|
11
11
|
sendGtm(e: PointerEvent) {
|
|
12
12
|
track(e.currentTarget, "custEv_bottomNavLinkClick", {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
clickText: this.label || undefined,
|
|
14
|
+
clickUrl: this.href || undefined,
|
|
15
|
+
navItem: this.label || undefined,
|
|
16
|
+
elementType: "link",
|
|
17
|
+
navType: "footer"
|
|
17
18
|
});
|
|
18
19
|
}
|
|
19
20
|
}
|
|
@@ -20,12 +20,6 @@ const subtitleClasses = {
|
|
|
20
20
|
[MEDIUM]: "dx-text-heading-7"
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
-
const ANALYTICS_INFO = {
|
|
24
|
-
elementType: "button",
|
|
25
|
-
destinationType: "internal",
|
|
26
|
-
ctaClick: true
|
|
27
|
-
};
|
|
28
|
-
|
|
29
23
|
export default class GroupText extends LightningElement {
|
|
30
24
|
@api title!: string;
|
|
31
25
|
@api body?: string;
|
|
@@ -99,13 +93,13 @@ export default class GroupText extends LightningElement {
|
|
|
99
93
|
}
|
|
100
94
|
|
|
101
95
|
private trackClick(event: Event) {
|
|
102
|
-
|
|
103
|
-
...ANALYTICS_INFO,
|
|
96
|
+
track(event.target!, "custEv_ctaButtonClick", {
|
|
104
97
|
clickText: event.currentTarget.innerText,
|
|
105
98
|
itemTitle: event.currentTarget.innerText,
|
|
106
|
-
clickUrl: event.currentTarget.href
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
99
|
+
clickUrl: event.currentTarget.href,
|
|
100
|
+
elementType: "button",
|
|
101
|
+
elementTitle: "dx-group-text",
|
|
102
|
+
contentCategory: "cta"
|
|
103
|
+
});
|
|
110
104
|
}
|
|
111
105
|
}
|
|
@@ -46,6 +46,10 @@ export default class HeaderNav extends LightningElement {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
private _navItems: OptionWithNested[] = [];
|
|
49
|
+
private ANALYTICS_PAYLOAD = {
|
|
50
|
+
navLevel: "2",
|
|
51
|
+
navType: "global"
|
|
52
|
+
};
|
|
49
53
|
|
|
50
54
|
private requestOpenNavMenu(e: PointerEvent) {
|
|
51
55
|
const detail = (<HTMLButtonElement>e.currentTarget).getAttribute(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="container">
|
|
3
|
-
<div class="text-container"
|
|
2
|
+
<div class="container" style={style}>
|
|
3
|
+
<div class="text-container">
|
|
4
4
|
<h1 class="heading dx-text-heading-2">{title}</h1>
|
|
5
5
|
<span class="body dx-text-body-1">{body}</span>
|
|
6
6
|
<span if:true={subtitle} class="subtitle dx-text-heading-4b">
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LightningElement, api } from "lwc";
|
|
2
|
+
import cx from "classnames";
|
|
2
3
|
import { track } from "dxUtils/analytics";
|
|
3
4
|
|
|
4
5
|
export default class MainContentHeader extends LightningElement {
|
|
@@ -10,16 +11,23 @@ export default class MainContentHeader extends LightningElement {
|
|
|
10
11
|
@api imgSrc!: string;
|
|
11
12
|
@api imgSrcMobile!: string;
|
|
12
13
|
@api ctaTarget?: string | null = null;
|
|
14
|
+
@api backgroundGradientColor?: string;
|
|
15
|
+
|
|
16
|
+
private get style() {
|
|
17
|
+
return cx(
|
|
18
|
+
this.backgroundGradientColor &&
|
|
19
|
+
`background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #ffff 100%), var(--dx-g-${this.backgroundGradientColor});`
|
|
20
|
+
);
|
|
21
|
+
}
|
|
13
22
|
|
|
14
23
|
private onCtaClick(e: Event) {
|
|
15
24
|
if (e.currentTarget) {
|
|
16
25
|
track(e.currentTarget, "custEv_ctaButtonClick", {
|
|
17
26
|
clickText: this.ctaLabel,
|
|
18
|
-
itemTitle: this.title,
|
|
19
27
|
clickUrl: this.ctaHref,
|
|
20
28
|
elementType: "button",
|
|
21
|
-
|
|
22
|
-
|
|
29
|
+
elementTitle: "dx-button",
|
|
30
|
+
contentCategory: "cta"
|
|
23
31
|
});
|
|
24
32
|
}
|
|
25
33
|
}
|
|
@@ -2,13 +2,6 @@ import classNames from "classnames";
|
|
|
2
2
|
import { LightningElement, api } from "lwc";
|
|
3
3
|
import { track } from "dxUtils/analytics";
|
|
4
4
|
|
|
5
|
-
const ANALYTICS_INFO = {
|
|
6
|
-
clickUrl: window.location.href,
|
|
7
|
-
ctaClick: false,
|
|
8
|
-
elementType: "button",
|
|
9
|
-
destinationType: "internal"
|
|
10
|
-
};
|
|
11
|
-
|
|
12
5
|
enum PaginationClickType {
|
|
13
6
|
Number,
|
|
14
7
|
Next,
|
|
@@ -98,10 +91,14 @@ export default class Pagination extends LightningElement {
|
|
|
98
91
|
? page
|
|
99
92
|
: (e.target as HTMLElement).dataset.partId;
|
|
100
93
|
|
|
94
|
+
console.log("clickURL", e.target.href);
|
|
95
|
+
|
|
101
96
|
track(e.currentTarget!, "custEv_pagination", {
|
|
102
|
-
...ANALYTICS_INFO,
|
|
103
97
|
clickText,
|
|
104
|
-
|
|
98
|
+
clickUrl: window.location.href,
|
|
99
|
+
elementType: "button",
|
|
100
|
+
navType: "pagination",
|
|
101
|
+
navItem: clickText
|
|
105
102
|
});
|
|
106
103
|
|
|
107
104
|
this.dispatchEvent(new CustomEvent("pagechange", { detail: page }));
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LightningElement } from "lwc";
|
|
2
|
+
import { throttle } from "throttle-debounce";
|
|
2
3
|
|
|
3
4
|
const RESTORE_SCROLL_EVENT_NAME = "restore-scroll";
|
|
4
5
|
const LOAD_TIME_SCROLL_RESTORE_DELAY = 750;
|
|
@@ -8,7 +9,13 @@ declare module globalThis {
|
|
|
8
9
|
let singletonScrollManagerConnected: boolean;
|
|
9
10
|
}
|
|
10
11
|
// mostly components shouldn't be using this, but there are a few exceptions such as amfReference
|
|
12
|
+
|
|
13
|
+
let scrollUnlocked: boolean = false;
|
|
14
|
+
|
|
11
15
|
export const restoreScroll = () => {
|
|
16
|
+
if (scrollUnlocked) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
12
19
|
document.body.scrollTop = document.documentElement.scrollTop =
|
|
13
20
|
window.history.state?.scroll.value;
|
|
14
21
|
};
|
|
@@ -32,13 +39,13 @@ export default class ScrollManager extends LightningElement {
|
|
|
32
39
|
*/
|
|
33
40
|
|
|
34
41
|
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
|
|
35
|
-
protected scrollUnlocked = false;
|
|
36
42
|
|
|
37
43
|
renderedCallback() {
|
|
38
|
-
|
|
44
|
+
scrollUnlocked = window.location.hash !== ""; // if we have anchor links, skip the entire scroll restore
|
|
45
|
+
if (!globalThis.singletonScrollManagerRendered && !scrollUnlocked) {
|
|
39
46
|
globalThis.singletonScrollManagerRendered = true;
|
|
40
47
|
if (
|
|
41
|
-
window.history.state?.scroll
|
|
48
|
+
window.history.state?.scroll?.docSize ===
|
|
42
49
|
document.body.scrollHeight
|
|
43
50
|
) {
|
|
44
51
|
// only do this if loading is complete and the scrollHeight matches expectations
|
|
@@ -49,10 +56,8 @@ export default class ScrollManager extends LightningElement {
|
|
|
49
56
|
// sometimes loading is slow, so we may want to reset the scroll to
|
|
50
57
|
// the correct position after loading is complete, to avoid weird behavior
|
|
51
58
|
// but only if the user hasn't scrolled around in the meantime
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
this.scrollUnlocked = true;
|
|
55
|
-
}
|
|
59
|
+
restoreScroll();
|
|
60
|
+
scrollUnlocked = true;
|
|
56
61
|
}, LOAD_TIME_SCROLL_RESTORE_DELAY);
|
|
57
62
|
}
|
|
58
63
|
} else {
|
|
@@ -75,7 +80,7 @@ export default class ScrollManager extends LightningElement {
|
|
|
75
80
|
}
|
|
76
81
|
}
|
|
77
82
|
|
|
78
|
-
saveScroll = () => {
|
|
83
|
+
saveScroll = throttle(100, () => {
|
|
79
84
|
window.history.replaceState(
|
|
80
85
|
{
|
|
81
86
|
scroll: {
|
|
@@ -86,7 +91,7 @@ export default class ScrollManager extends LightningElement {
|
|
|
86
91
|
"",
|
|
87
92
|
window.location.href
|
|
88
93
|
);
|
|
89
|
-
};
|
|
94
|
+
});
|
|
90
95
|
|
|
91
96
|
manualScrollListener = () => {
|
|
92
97
|
if (this.scrollCount < 5) {
|
|
@@ -32,9 +32,12 @@ export default class Tab extends LightningElement {
|
|
|
32
32
|
|
|
33
33
|
private sendGtm(e: PointerEvent) {
|
|
34
34
|
track(e.currentTarget!, "custEv_topNavLinkClick", {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
clickText: this.label || undefined,
|
|
36
|
+
clickUrl: this.href || undefined,
|
|
37
|
+
navLevel: "1",
|
|
38
|
+
navItem: this.label || undefined,
|
|
39
|
+
elementType: "link",
|
|
40
|
+
navType: "global"
|
|
38
41
|
});
|
|
39
42
|
}
|
|
40
43
|
|
|
@@ -97,10 +97,18 @@ export default class TreeItem extends LightningElement {
|
|
|
97
97
|
this.sendGtm(event);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
private
|
|
101
|
-
if
|
|
100
|
+
private preventDefaultLinkBehavior(event: Event) {
|
|
101
|
+
// prevent page refresh if href isn't present or link is already active
|
|
102
|
+
if (
|
|
103
|
+
!this._treeNode.link?.href ||
|
|
104
|
+
this._treeNode.link?.href === window.location.pathname
|
|
105
|
+
) {
|
|
102
106
|
event.preventDefault();
|
|
103
107
|
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
private onLinkClick(event: Event): void {
|
|
111
|
+
this.preventDefaultLinkBehavior(event);
|
|
104
112
|
|
|
105
113
|
if (this.isParent) {
|
|
106
114
|
const isSelectAction = true;
|
|
@@ -138,11 +146,12 @@ export default class TreeItem extends LightningElement {
|
|
|
138
146
|
}
|
|
139
147
|
|
|
140
148
|
private sendGtm(event: Event) {
|
|
141
|
-
track(event.currentTarget!, "
|
|
142
|
-
navType: "left nav bar",
|
|
149
|
+
track(event.currentTarget!, "custEv_leftNavLinkClick", {
|
|
143
150
|
clickText: this._treeNode.label,
|
|
144
151
|
clickUrl: this.href,
|
|
145
|
-
navItem: this.parentName
|
|
152
|
+
navItem: this.parentName,
|
|
153
|
+
navType: "left nav bar",
|
|
154
|
+
elementType: "link"
|
|
146
155
|
});
|
|
147
156
|
}
|
|
148
157
|
}
|
|
@@ -21,11 +21,11 @@ const VALID_BRANDS = [
|
|
|
21
21
|
];
|
|
22
22
|
|
|
23
23
|
export const ANALYTICS_INFO = {
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
click_text: "Sign Up",
|
|
25
|
+
element_title: "Sign Up Header Button",
|
|
26
26
|
elementType: "button",
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
element_type: "internal",
|
|
28
|
+
content_category: "cta"
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
export abstract class HeaderBase extends LightningElement {
|
|
@@ -201,9 +201,9 @@ export abstract class HeaderBase extends LightningElement {
|
|
|
201
201
|
};
|
|
202
202
|
|
|
203
203
|
private handleSignUpClick(e: PointerEvent) {
|
|
204
|
-
track(e.currentTarget!, "
|
|
204
|
+
track(e.currentTarget!, "custEv_browseTrialsClick", {
|
|
205
205
|
...ANALYTICS_INFO,
|
|
206
|
-
|
|
206
|
+
click_url: this.signupLink
|
|
207
207
|
});
|
|
208
208
|
}
|
|
209
209
|
|
|
@@ -58,9 +58,7 @@ export const normalizePost = ({
|
|
|
58
58
|
body: description,
|
|
59
59
|
datetime: date,
|
|
60
60
|
href: url,
|
|
61
|
-
|
|
62
|
-
authorImgSrc: get(authors, "[0].avatar_urls.48"),
|
|
63
|
-
authorName: get(authors, "[0].name"),
|
|
61
|
+
authors: authors,
|
|
64
62
|
imgAlt: "Blogpost image",
|
|
65
63
|
imgSrc: featuredImage,
|
|
66
64
|
id,
|
package/LICENSE
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
Copyright (c) 2020, Salesforce.com, Inc.
|
|
2
|
-
All rights reserved.
|
|
3
|
-
|
|
4
|
-
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
5
|
-
|
|
6
|
-
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
7
|
-
|
|
8
|
-
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
9
|
-
|
|
10
|
-
* Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
|
11
|
-
|
|
12
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|