@salesforcedevs/dx-components 1.5.0-alpha2 → 1.8.0-node-20-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 CHANGED
@@ -42,6 +42,7 @@
42
42
  "dx/dropdownOption",
43
43
  "dx/embeddedVideo",
44
44
  "dx/emptyState",
45
+ "dx/eyebrow",
45
46
  "dx/faq",
46
47
  "dx/feature",
47
48
  "dx/featureFlag",
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@salesforcedevs/dx-components",
3
- "version": "1.5.0-alpha2",
3
+ "version": "1.8.0-node-20-alpha",
4
4
  "description": "DX Lightning web components",
5
5
  "license": "MIT",
6
6
  "engines": {
7
- "node": "18.x"
7
+ "node": "20.x"
8
8
  },
9
9
  "publishConfig": {
10
10
  "access": "public"
@@ -44,6 +44,6 @@
44
44
  "luxon": "3.4.4"
45
45
  },
46
46
  "volta": {
47
- "node": "18.18.0"
47
+ "node": "20.19.0"
48
48
  }
49
49
  }
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <a href={href} class={className} target={target}>
2
+ <a href={href} class={className} target={target} part="base">
3
3
  <img
4
4
  if:true={imgSrc}
5
5
  alt={imgAlt}
@@ -8,22 +8,32 @@
8
8
  />
9
9
  <div
10
10
  class="dx-card-base_section-vertical dx-card-base_column card_section-text"
11
+ part="content"
11
12
  >
12
- <span class="dx-text-label-3" part="label">{label}</span>
13
+ <span class="dx-text-label-3" lwc:if={label} part="label">
14
+ {label}
15
+ </span>
13
16
  <dx-card-title
17
+ lwc:if={header}
14
18
  header={header}
15
19
  target={target}
16
20
  onclick={handleLinkClick}
21
+ exportparts="title"
17
22
  ></dx-card-title>
18
23
  <span
19
24
  lwc:if={body}
20
25
  class="dx-text-body-2"
21
26
  onclick={handleTextClick}
27
+ part="body"
22
28
  >
23
29
  {body}
24
30
  </span>
31
+ <span lwc:if={subText} class="dx-text-body-3">{subText}</span>
25
32
  </div>
26
- <div class="dx-card-base_section-vertical dx-card-base_ctas">
33
+ <div
34
+ class="dx-card-base_section-vertical dx-card-base_ctas"
35
+ part="action"
36
+ >
27
37
  <slot onslotchange={onSlotChange}></slot>
28
38
  </div>
29
39
  </a>
@@ -6,6 +6,7 @@ import { track } from "dxUtils/analytics";
6
6
 
7
7
  export default class CardDocs extends LightningElement {
8
8
  @api body!: string;
9
+ @api subText?: string | null = null;
9
10
  @api href!: string;
10
11
  @api imgAlt?: string = "";
11
12
  @api imgSrc?: string | null = null;
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <h3 class="dx-text-display-6">
2
+ <h3 class="dx-text-display-6" part="title">
3
3
  <a if:true={href} href={href} target={target}>
4
4
  {titleToWrap}
5
5
  <template if:true={needsSpace}>&#32;</template>
@@ -1,5 +1,4 @@
1
1
  /* eslint-disable @lwc/lwc/no-document-query */
2
- import { OPTIMIZELY_INSTANCE, USER_ID } from "dx/featureFlag";
3
2
  import { LightningElement } from "lwc";
4
3
 
5
4
  export const LOCAL_STORAGE_KEY = "dx-dark-mode-theme";
@@ -30,7 +29,10 @@ declare module globalThis {
30
29
 
31
30
  export const DARK_MODE_THEMES = ["dark", "light"];
32
31
  export const DARKMODE_TOGGLE_EVENT_NAME = "UPDATE_DARK_MODE";
33
- const DARK_MODE_FEATURE_FLAG = "dark_mode";
32
+
33
+ export const isDarkModeEnabled = () => {
34
+ return process.env.DARK_MODE;
35
+ };
34
36
 
35
37
  export const dispatchDarkModeToggleEvent = () => {
36
38
  window.dispatchEvent(new Event(DARKMODE_TOGGLE_EVENT_NAME));
@@ -53,40 +55,32 @@ export const setLocalStorageDarkModeSetting = (theme: string) => {
53
55
 
54
56
  export default class DarkModeManager extends LightningElement {
55
57
  renderedCallback(): void {
56
- OPTIMIZELY_INSTANCE!.onReady().then(({ success }) => {
57
- if (
58
- success &&
59
- OPTIMIZELY_INSTANCE!.isFeatureEnabled(
60
- DARK_MODE_FEATURE_FLAG,
61
- USER_ID
62
- )
63
- ) {
64
- if (!globalThis.singletonDarkModeManagerRendered) {
65
- const theme = getLocalStorageDarkModeSetting();
66
- if (theme) {
67
- if (DARK_MODE_THEMES.includes(theme)) {
68
- setTheme(theme);
69
- }
70
- } else if (isBrowserDarkModeEnabled()) {
71
- setTheme("dark");
72
- }
73
- window.addEventListener(
74
- DARKMODE_TOGGLE_EVENT_NAME,
75
- onDarkModeToggle
76
- );
77
- globalThis.singletonDarkModeManagerRendered = true;
58
+ if (
59
+ isDarkModeEnabled() &&
60
+ !globalThis.singletonDarkModeManagerRendered
61
+ ) {
62
+ const theme = getLocalStorageDarkModeSetting();
63
+ if (theme) {
64
+ if (DARK_MODE_THEMES.includes(theme)) {
65
+ setTheme(theme);
78
66
  }
67
+ } else if (isBrowserDarkModeEnabled()) {
68
+ setTheme("dark");
79
69
  }
80
- });
70
+ window.addEventListener(
71
+ DARKMODE_TOGGLE_EVENT_NAME,
72
+ onDarkModeToggle
73
+ );
74
+ globalThis.singletonDarkModeManagerRendered = true;
75
+ }
81
76
  }
82
77
 
83
78
  disconnectedCallback(): void {
84
- if (globalThis.singletonDarkModeManagerRendered) {
79
+ if (isDarkModeEnabled()) {
85
80
  window.removeEventListener(
86
81
  DARKMODE_TOGGLE_EVENT_NAME,
87
82
  onDarkModeToggle
88
83
  );
89
- globalThis.singletonDarkModeManagerRendered = false;
90
84
  }
91
85
  }
92
86
  }
@@ -0,0 +1,44 @@
1
+ @import "dxHelpers/text";
2
+
3
+ .eyebrow {
4
+ display: flex;
5
+ justify-content: center;
6
+ align-items: center;
7
+ background: var(--dx-g-blue-vibrant-10);
8
+ color: white;
9
+ padding: 6px 40px;
10
+ gap: 4px;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ .eyebrow.fixed {
15
+ position: fixed;
16
+ top: var(--dx-g-global-header-height, 0);
17
+ width: 100%;
18
+ z-index: var(--dx-g-z-index-max, 999);
19
+ }
20
+
21
+ .eyebrow > dx-icon {
22
+ padding-right: 5px;
23
+ }
24
+
25
+ .eyebrow > span {
26
+ text-align: center;
27
+ }
28
+
29
+ .eyebrow > span > a {
30
+ color: white;
31
+ text-decoration: underline;
32
+ }
33
+
34
+ @media (min-width: 768px) and (max-width: 1279px) {
35
+ .eyebrow {
36
+ padding: 6px 32px;
37
+ }
38
+ }
39
+
40
+ @media (max-width: 767px) {
41
+ .eyebrow {
42
+ padding: 6px 24px;
43
+ }
44
+ }
@@ -0,0 +1,16 @@
1
+ <template>
2
+ <div class={className}>
3
+ <dx-icon
4
+ sprite={iconSprite}
5
+ symbol={iconSymbol}
6
+ size={iconSize}
7
+ ></dx-icon>
8
+ <span>
9
+ {body}
10
+ <template lwc:if={hasCta}>
11
+ &nbsp;
12
+ <a target={ctaTarget} href={ctaHref}>{ctaLabel}</a>
13
+ </template>
14
+ </span>
15
+ </div>
16
+ </template>
@@ -0,0 +1,32 @@
1
+ import cx from "classnames";
2
+ import { normalizeBoolean } from "dxUtils/normalizers";
3
+ import { api, LightningElement } from "lwc";
4
+ import { IconSize, IconSprite, IconSymbol } from "typings/custom";
5
+
6
+ export default class Eyebrow extends LightningElement {
7
+ @api body = "";
8
+ @api ctaHref = "";
9
+ @api ctaLabel = "";
10
+ @api ctaTarget = "_blank";
11
+ @api iconSize: IconSize = "large";
12
+ @api iconSprite: IconSprite = "action";
13
+ @api iconSymbol: IconSymbol = "info";
14
+
15
+ @api
16
+ get fixed() {
17
+ return this._fixed;
18
+ }
19
+ set fixed(value: string | boolean) {
20
+ this._fixed = normalizeBoolean(value);
21
+ }
22
+
23
+ private _fixed: boolean = false;
24
+
25
+ get hasCta() {
26
+ return Boolean(this.ctaHref && this.ctaLabel);
27
+ }
28
+
29
+ get className() {
30
+ return cx("eyebrow", "dx-text-body-3", this.fixed && "fixed");
31
+ }
32
+ }
@@ -9,6 +9,9 @@
9
9
  --dx-c-feature-img-container-padding: 4rem;
10
10
  --dx-c-feature-image-max-width: 100%;
11
11
  --dx-c-feature-description-font-size: var(--dx-g-text-base);
12
+ --dx-c-feature-description-img-width: 45%;
13
+ --dx-c-feature-description-gap: 0;
14
+ --dx-c-feature-description-img-gap: 0;
12
15
  }
13
16
 
14
17
  .label {
@@ -31,11 +34,18 @@ h3 {
31
34
  section {
32
35
  display: flex;
33
36
  align-items: center;
37
+ gap: var(--dx-c-feature-description-img-gap);
38
+ }
39
+
40
+ .description {
41
+ display: flex;
42
+ flex-direction: column;
43
+ gap: var(--dx-c-feature-description-gap);
34
44
  }
35
45
 
36
46
  .description,
37
47
  .image {
38
- width: 45%;
48
+ width: var(--dx-c-feature-description-img-width);
39
49
  }
40
50
 
41
51
  .image {
@@ -2,8 +2,8 @@
2
2
  <section class={sectionClass}>
3
3
  <div class="description">
4
4
  <h2 if:true={hasLabel} class="dx-text-display-8 label">{label}</h2>
5
- <h3 class="dx-text-display-4">{header}</h3>
6
- <div class="body dx-text-body-2">
5
+ <h3 class="dx-text-display-4" part="header">{header}</h3>
6
+ <div class="body dx-text-body-2" part="body">
7
7
  <slot></slot>
8
8
  </div>
9
9
  <dx-button
@@ -13,6 +13,7 @@
13
13
  icon-symbol={iconSymbol}
14
14
  href={buttonHref}
15
15
  onclick={handleClick}
16
+ if:true={buttonHref}
16
17
  >
17
18
  {buttonLabel}
18
19
  </dx-button>
@@ -3,42 +3,37 @@ import optimizelySdk from "@optimizely/optimizely-sdk";
3
3
 
4
4
  // This is needed to specify user context (such as logged in, admin, ...etc).
5
5
  // leave this as hard-coded for now until we create audiences in Optimizely.
6
- export const USER_ID = "sf-dwo";
7
- const LOCAL_ENVIRONMENT_SDK_KEY = "DzwQxncbVQsbMnXfjpasL";
8
- const SDK_KEY = process.env.OPTIMIZELY_SDK_KEY;
9
- const DATAFILE_ACCESS_TOKEN = process.env.OPTIMIZELY_DATAFILE_ACCESS_TOKEN;
10
- const DATAFILE_OPTIONS =
11
- SDK_KEY && DATAFILE_ACCESS_TOKEN
12
- ? {
13
- urlTemplate: `https://config.optimizely.com/datafiles/auth/${SDK_KEY}.json`,
14
- datafileAccessToken: DATAFILE_ACCESS_TOKEN
15
- }
16
- : undefined;
17
- export const OPTIMIZELY_INSTANCE = optimizelySdk.createInstance({
18
- sdkKey: SDK_KEY || LOCAL_ENVIRONMENT_SDK_KEY,
19
- datafileOptions: DATAFILE_OPTIONS
20
- });
6
+ const userId = "user123";
21
7
 
22
8
  export default class FeatureFlag extends LightningElement {
23
9
  @api flag!: string;
24
10
 
11
+ private optimizelyInstance: any;
12
+
25
13
  private showElements(slot: any) {
26
14
  slot.classList.remove("hidden");
27
15
  }
28
16
 
29
- /*
30
- Note that this component only stops the element from being redered to the screen.
31
- If you want to stop the execution of the code for the element, you will need to also check
32
- the feature flag in that component.
33
- */
17
+ connectedCallback(): void {
18
+ this.optimizelyInstance = optimizelySdk.createInstance({
19
+ sdkKey: process.env.OPTIMIZELY_SDK_KEY
20
+ });
21
+ }
22
+
34
23
  renderedCallback(): void {
35
24
  const slotEl = this.template.querySelector("slot") as any;
36
25
 
37
- OPTIMIZELY_INSTANCE!.onReady().then(({ success }) => {
38
- if (
39
- success &&
40
- OPTIMIZELY_INSTANCE!.isFeatureEnabled(this.flag, USER_ID)
41
- ) {
26
+ this.optimizelyInstance?.onReady().then(({ success, reason }: any) => {
27
+ if (!success) {
28
+ console.log(
29
+ `Optimizely client initialization unsuccessful, reason: ${reason}`
30
+ );
31
+ return;
32
+ }
33
+ const user = this.optimizelyInstance?.createUserContext(userId);
34
+ const decision = user?.decide(this.flag);
35
+
36
+ if (decision?.enabled) {
42
37
  this.showElements(slotEl);
43
38
  }
44
39
  });
@@ -21,14 +21,14 @@
21
21
  <div>
22
22
  <slot name="language-selector"></slot>
23
23
  </div>
24
- <dx-feature-flag flag="dark_mode">
24
+ <template lwc:if={isDarkModeEnabled}>
25
25
  <div
26
26
  class="dark-mode-button"
27
27
  onclick={onDarkModeButtonClick}
28
28
  >
29
29
  <div class="dark-mode-icon"></div>
30
30
  </div>
31
- </dx-feature-flag>
31
+ </template>
32
32
  </div>
33
33
  </div>
34
34
  <div class="container-layout">
@@ -5,7 +5,10 @@ import { toJson } from "dxUtils/normalizers";
5
5
  import { track } from "dxUtils/analytics";
6
6
  import svgs from "./svgs";
7
7
  import ImageAndLabel from "dx/imageAndLabel";
8
- import { dispatchDarkModeToggleEvent } from "dx/darkModeManager";
8
+ import {
9
+ dispatchDarkModeToggleEvent,
10
+ isDarkModeEnabled
11
+ } from "dx/darkModeManager";
9
12
 
10
13
  export default class FeaturedContentHeader extends LightningElement {
11
14
  @api label?: string | null = null;
@@ -92,7 +95,7 @@ export default class FeaturedContentHeader extends LightningElement {
92
95
  }
93
96
 
94
97
  private get isDarkModeEnabled() {
95
- return this.enableDarkModeToggle;
98
+ return this.enableDarkModeToggle && isDarkModeEnabled();
96
99
  }
97
100
 
98
101
  private get hasPlainImage() {
@@ -250,7 +250,7 @@ footer.signup-variant-no-signup {
250
250
  }
251
251
 
252
252
  .content-container_bottom a {
253
- text-decoration: none;
253
+ text-decoration: underline;
254
254
  }
255
255
 
256
256
  .terms {