@salesforcedevs/dx-components 1.3.148 → 1.3.150-canary.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/lwc.config.json CHANGED
@@ -4,6 +4,7 @@
4
4
  { "npm": "@salesforcedevs/dw-components" }
5
5
  ],
6
6
  "expose": [
7
+ "dx/alert",
7
8
  "dx/audio",
8
9
  "dx/banner",
9
10
  "dx/brandThemeProvider",
@@ -22,6 +23,7 @@
22
23
  "dx/cardNews",
23
24
  "dx/cardPodcastEpisode",
24
25
  "dx/cardSmall",
26
+ "dx/cardStep",
25
27
  "dx/cardTrailheadModule",
26
28
  "dx/cardTrial",
27
29
  "dx/cardTrialExpanded",
@@ -49,6 +51,7 @@
49
51
  "dx/headerSearch",
50
52
  "dx/helmet",
51
53
  "dx/hr",
54
+ "dx/htmlRenderer",
52
55
  "dx/icon",
53
56
  "dx/iconBadge",
54
57
  "dx/imageAndLabel",
@@ -89,6 +92,7 @@
89
92
  "dx/typeBadge",
90
93
  "dx/vimeoPlayer",
91
94
  "dxBaseElements/headerBase",
95
+ "dxBaseElements/lightningElementWithState",
92
96
  "dxBaseElements/matchMediaElement",
93
97
  "dxConstants/brands",
94
98
  "dxConstants/colors",
@@ -110,6 +114,7 @@
110
114
  "dxUtils/dates",
111
115
  "dxUtils/highlight",
112
116
  "dxUtils/language",
117
+ "dxUtils/list",
113
118
  "dxUtils/lwc",
114
119
  "dxUtils/normalizers",
115
120
  "dxUtils/queryCoordinator",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforcedevs/dx-components",
3
- "version": "1.3.148",
3
+ "version": "1.3.150-canary.0",
4
4
  "description": "DX Lightning web components",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -39,6 +39,5 @@
39
39
  "@types/vimeo__player": "^2.16.2",
40
40
  "eventsourcemock": "^2.0.0",
41
41
  "luxon": "^3.1.0"
42
- },
43
- "gitHead": "45e05ff97064929d80f2a5212c78b9c714144dec"
42
+ }
44
43
  }
@@ -0,0 +1,108 @@
1
+ @import "dxHelpers/reset";
2
+ @import "dxHelpers/text";
3
+
4
+ :host {
5
+ --dx-c-alert-top: 0;
6
+ --dx-c-alert-container-align-items: flex-start;
7
+ --dx-c-alert-vertical-padding: var(--dx-g-spacing-md);
8
+ --dx-c-alert-success-color: var(--dx-g-green-vibrant-95);
9
+ --dx-c-alert-warning-color: rgb(254, 243, 217);
10
+ --dx-c-alert-danger-color: var(--dx-g-red-vibrant-95);
11
+ --dx-c-alert-success-accent-color: var(--dx-g-green-vibrant-80);
12
+ --dx-c-alert-warning-accent-color: var(--dx-g-yellow-vibrant-80);
13
+ --dx-c-alert-danger-accent-color: var(--dx-g-red-vibrant-50);
14
+ }
15
+
16
+ .alert-icon {
17
+ margin-right: var(--dx-g-spacing-md);
18
+ }
19
+
20
+ .alert-base {
21
+ padding: var(--dx-c-alert-vertical-padding);
22
+ }
23
+
24
+ .alert-container {
25
+ display: flex;
26
+ flex-direction: column;
27
+ align-items: var(--dx-c-alert-container-align-items);
28
+ padding-left: var(--dx-g-global-header-padding-horizontal);
29
+ padding-right: var(--dx-g-global-header-padding-horizontal);
30
+ width: 100%;
31
+ border: none;
32
+ }
33
+
34
+ .alert-container.alert-type-success {
35
+ background-color: var(--dx-c-alert-success-color);
36
+ border-color: var(--dx-c-alert-success-accent-color);
37
+ }
38
+
39
+ .alert-container.alert-type-warning {
40
+ background-color: var(--dx-c-alert-warning-color);
41
+ border-color: var(--dx-c-alert-warning-accent-color);
42
+ }
43
+
44
+ .alert-container.alert-type-danger {
45
+ background-color: var(--dx-c-alert-danger-color);
46
+ border-color: var(--dx-c-alert-danger-accent-color);
47
+ }
48
+
49
+ .alert-container.alert-variant-accented {
50
+ border-style: solid;
51
+ border-width: 0;
52
+ border-left-width: 4px;
53
+ }
54
+
55
+ .alert-title-container {
56
+ display: flex;
57
+ flex-direction: row;
58
+ align-items: center;
59
+ width: 100%;
60
+ }
61
+
62
+ .alert-title {
63
+ font-weight: var(--dx-g-font-bold);
64
+ }
65
+
66
+ dx-button {
67
+ margin-left: auto;
68
+ }
69
+
70
+ /*
71
+ NOTE: Here we are assuming that indicator height won't go beyond 1000px.
72
+
73
+ It's one of the suggested way to achieve the expand/collapse animation
74
+ Ref: https://stackoverflow.com/a/41164095
75
+
76
+ Otherwise we need to change the height when user clicks on button
77
+ Ref: https://stackoverflow.com/a/11837673
78
+ */
79
+
80
+ .alert-body {
81
+ display: block;
82
+ max-height: 1000px;
83
+ overflow: hidden;
84
+ padding-top: var(--dx-g-spacing-smd);
85
+ transition: max-height 0.25s ease, padding 0.25s ease;
86
+ }
87
+
88
+ .alert-body-hidden {
89
+ max-height: 0;
90
+ padding-top: 0;
91
+ transition: max-height 0.1s ease-out, padding 0.25s ease-out;
92
+ }
93
+
94
+ .alert-body a {
95
+ color: var(--dx-g-blue-vibrant-50);
96
+ }
97
+
98
+ .dismissible-icon {
99
+ margin-left: auto;
100
+ cursor: pointer;
101
+ }
102
+
103
+ /* Small Devices */
104
+ @media screen and (max-width: 480px) {
105
+ .alert-container {
106
+ padding: var(--dx-c-alert-vertical-padding);
107
+ }
108
+ }
@@ -0,0 +1,36 @@
1
+ <template>
2
+ <div class={className} part="container">
3
+ <div class="alert-title-container">
4
+ <dx-icon
5
+ class="alert-icon"
6
+ symbol={iconName}
7
+ sprite={iconSprite}
8
+ size="large"
9
+ color={iconColor}
10
+ ></dx-icon>
11
+ <p class="alert-title dx-text-body-3">{alertTitle}</p>
12
+ <dx-button
13
+ if:true={hideable}
14
+ variant="inline"
15
+ onclick={onShowHide}
16
+ aria-label={hideBodyText}
17
+ >
18
+ {hideBodyText}
19
+ </dx-button>
20
+ <dx-icon
21
+ class="dismissible-icon"
22
+ onclick={onDismiss}
23
+ if:true={dismissible}
24
+ symbol="close"
25
+ size="large"
26
+ color="status-icon-color"
27
+ ></dx-icon>
28
+ </div>
29
+ <!--
30
+ NOTE: Here we are rendering mark up using lwc:dom & innerHTML
31
+ option instead of slots because the html markup will come as a
32
+ property to the component from a configuration
33
+ -->
34
+ <span lwc:dom="manual" class={bodyClassName}></span>
35
+ </div>
36
+ </template>
@@ -0,0 +1,137 @@
1
+ import { LightningElement, api } from "lwc";
2
+ import cx from "classnames";
3
+
4
+ import { AlertInfo } from "typings/custom";
5
+ import { toJson } from "dxUtils/normalizers";
6
+
7
+ export default class Alert extends LightningElement {
8
+ _alertInfo: AlertInfo | null = null;
9
+ _dismissible = false;
10
+ _iconName = "";
11
+ _iconSprite = "";
12
+ _iconColor = "";
13
+ @api control: "none" | "hideable" | "dismissible" = "none";
14
+ @api type: "success" | "warning" | "danger" = "warning";
15
+ @api variant: "base" | "accented" = "base";
16
+
17
+ @api
18
+ get alertInfo(): AlertInfo | null {
19
+ return this._alertInfo;
20
+ }
21
+ set alertInfo(value) {
22
+ this._alertInfo = toJson(value);
23
+ }
24
+
25
+ @api
26
+ get iconColor(): string {
27
+ return this._iconColor || this.variant === "base"
28
+ ? "gray-10"
29
+ : this.accentedIconColor;
30
+ }
31
+ set iconColor(value) {
32
+ if (value) {
33
+ this._iconColor = value;
34
+ }
35
+ }
36
+
37
+ @api
38
+ get iconName(): string {
39
+ return this._iconName || this.type === "success"
40
+ ? "check-circle"
41
+ : "warning";
42
+ }
43
+ set iconName(value) {
44
+ if (value) {
45
+ this._iconName = value;
46
+ }
47
+ }
48
+
49
+ @api
50
+ get iconSprite(): string {
51
+ return this._iconSprite || this.type === "success"
52
+ ? "general"
53
+ : "utility";
54
+ }
55
+ set iconSprite(value) {
56
+ if (value) {
57
+ this._iconSprite = value;
58
+ }
59
+ }
60
+
61
+ get accentedIconColor() {
62
+ const baseColor =
63
+ this.type === "danger"
64
+ ? "red"
65
+ : this.type === "warning"
66
+ ? "yellow"
67
+ : "green";
68
+ return `${baseColor}-vibrant-50`;
69
+ }
70
+
71
+ get dismissible(): boolean {
72
+ return this.control === "dismissible";
73
+ }
74
+
75
+ get hideable(): boolean {
76
+ return this.control === "hideable";
77
+ }
78
+
79
+ get alertTitle() {
80
+ return this.alertInfo?.title;
81
+ }
82
+
83
+ get hideBodyText() {
84
+ return this.isBodyHidden ? "Show" : "Hide";
85
+ }
86
+
87
+ get alertType() {
88
+ return this.type || "warning";
89
+ }
90
+
91
+ get alertVariant() {
92
+ return this.variant || "base";
93
+ }
94
+
95
+ get className() {
96
+ return cx(
97
+ "alert-base",
98
+ "alert-container",
99
+ `alert-variant-${this.alertVariant}`,
100
+ `alert-type-${this.alertType}`
101
+ );
102
+ }
103
+
104
+ get bodyClassName() {
105
+ return cx(
106
+ "alert-body",
107
+ "dx-text-body-3",
108
+ this.isBodyHidden && "alert-body-hidden"
109
+ );
110
+ }
111
+
112
+ isBodyHidden = false;
113
+
114
+ renderedCallback() {
115
+ const phaseBodyContainer = this.template.querySelector(".alert-body");
116
+ if (phaseBodyContainer && this.alertInfo) {
117
+ // eslint-disable-next-line @lwc/lwc/no-inner-html
118
+ phaseBodyContainer.innerHTML = this.alertInfo.body;
119
+ }
120
+ }
121
+
122
+ onShowHide() {
123
+ this.isBodyHidden = !this.isBodyHidden;
124
+ }
125
+
126
+ onDismiss() {
127
+ this.dispatchEvent(
128
+ new CustomEvent("dismissphase", {
129
+ detail: {
130
+ alertInfo: this.alertInfo
131
+ },
132
+ composed: true,
133
+ bubbles: true
134
+ })
135
+ );
136
+ }
137
+ }
@@ -132,16 +132,26 @@
132
132
  border-color: var(--dx-c-button-primary-color-hover);
133
133
  }
134
134
 
135
- /* secondary */
135
+ /* secondary / quaternary */
136
136
 
137
137
  .button.variant_secondary {
138
- color: var(--dx-c-button-primary-color);
139
138
  background: var(--dx-c-button-background-color);
139
+ }
140
+
141
+ .button.variant_quaternary {
142
+ background: white;
143
+ }
144
+
145
+ .button.variant_secondary,
146
+ .button.variant_quaternary {
147
+ color: var(--dx-c-button-primary-color);
140
148
  border: 1px solid var(--dx-c-button-primary-color);
141
149
  }
142
150
 
143
151
  .button.variant_secondary:hover,
144
- :host([aria-expanded="true"]) .button.variant_secondary {
152
+ .button.variant_quaternary:hover,
153
+ :host([aria-expanded="true"]) .button.variant_secondary,
154
+ :host([aria-expanded="true"]) .button.variant_quaternary {
145
155
  background: var(--dx-c-button-secondary-color-hover);
146
156
  }
147
157
 
@@ -10,6 +10,7 @@ import {
10
10
  } from "typings/custom";
11
11
 
12
12
  export default class Button extends LightningElement {
13
+ private _didSetFormAttribute = false;
13
14
  @api ariaLabel: string = "";
14
15
  @api disabled: boolean | null = null;
15
16
  @api iconSize?: IconSize = "small";
@@ -21,6 +22,7 @@ export default class Button extends LightningElement {
21
22
  @api variant: ButtonVariant = "primary";
22
23
  @api inlineTextColor: ButtonTextColor = "dark";
23
24
  @api font: "display" | "sans" = "display";
25
+ @api form: string | undefined;
24
26
  @api name?: string;
25
27
  @api value?: any;
26
28
 
@@ -61,6 +63,19 @@ export default class Button extends LightningElement {
61
63
  );
62
64
  }
63
65
 
66
+ renderedCallback() {
67
+ if (
68
+ !this.href &&
69
+ typeof this.form !== "undefined" &&
70
+ !this._didSetFormAttribute
71
+ ) {
72
+ this._didSetFormAttribute = true;
73
+ this.template
74
+ .querySelector("button")
75
+ ?.setAttribute("form", this.form);
76
+ }
77
+ }
78
+
64
79
  private onSlotChange(e: LightningSlotElement) {
65
80
  const slot = e.target;
66
81
  this.isSlotEmpty = slot.assignedElements().length !== 0;
@@ -0,0 +1,90 @@
1
+ @import "dxHelpers/reset";
2
+ @import "dxHelpers/text";
3
+ @import "dxHelpers/card";
4
+
5
+ .container {
6
+ margin: var(--dx-c-card-step-container-margin, 40px auto);
7
+ max-width: 90%;
8
+ width: var(--dx-c-card-step-container-width, 796px);
9
+ }
10
+
11
+ .header-container {
12
+ background-color: var(
13
+ --dx-c-card-step-header-background-color,
14
+ var(--dx-g-indigo-vibrant-20)
15
+ );
16
+ padding: var(--dw-card-sequence-header-padding, var(--dx-g-spacing-3xl));
17
+ text-align: center;
18
+ }
19
+
20
+ .header-container > * {
21
+ display: inline-block;
22
+ }
23
+
24
+ .card-title {
25
+ color: var(--dx-c-card-step-header-text-color, white);
26
+ }
27
+
28
+ .card-title-icon {
29
+ height: 40px;
30
+ padding-right: 16px;
31
+ vertical-align: top;
32
+ }
33
+
34
+ .body-container {
35
+ font-family: var(--dx-g-font-display);
36
+ font-size: var(--dx-g-text-base);
37
+ font-weight: var(--dx-g-font-demi);
38
+ padding: var(--dw-card-sequence-body-padding, var(--dx-g-spacing-xl));
39
+ }
40
+
41
+ .body-container ul {
42
+ list-style-type: none;
43
+ }
44
+
45
+ .body-container li {
46
+ line-height: var(--dx-g-text-2xl);
47
+ }
48
+
49
+ .body-container p:not(:last-child) {
50
+ padding-bottom: 20px;
51
+ }
52
+
53
+ .form-row {
54
+ display: flex;
55
+ justify-content: space-between;
56
+ padding-bottom: var(--dx-g-spacing-md);
57
+ }
58
+
59
+ .form-row > * {
60
+ max-width: 95%;
61
+ }
62
+
63
+ .footer-container {
64
+ display: flex;
65
+ align-items: center;
66
+ justify-content: space-between;
67
+ padding: var(--dw-card-sequence-body-padding, var(--dx-g-spacing-xl));
68
+ }
69
+
70
+ .footer-section {
71
+ display: flex;
72
+ flex: 1;
73
+ justify-content: center;
74
+ }
75
+
76
+ .footer-section:first-child {
77
+ justify-content: start;
78
+ }
79
+
80
+ .footer-section:last-child {
81
+ justify-content: end;
82
+ }
83
+
84
+ .footer-section:nth-child(2) {
85
+ flex: 0.7;
86
+ font-size: var(--dx-g-text-xs, 12px);
87
+ font-family: var(--dx-g-font-sans);
88
+ line-height: 18px;
89
+ text-align: center;
90
+ }
@@ -0,0 +1,31 @@
1
+ <template>
2
+ <div class="dx-card-base container">
3
+ <div if:true={stepTitle} class="header-container">
4
+ <dx-icon
5
+ if:true={hasDefinedIcon}
6
+ class="card-title-icon"
7
+ size="xlarge"
8
+ color={headerIconColor}
9
+ sprite={headerIconSprite}
10
+ symbol={headerIconSymbol}
11
+ ></dx-icon>
12
+ <h3 class="card-title dx-text-display-5">{stepTitle}</h3>
13
+ </div>
14
+ <div class="body-container">
15
+ <slot name="card-body"></slot>
16
+ </div>
17
+ <div class="footer-container" part="footer-container">
18
+ <div class="footer-section">
19
+ <slot name="secondary-action-section"></slot>
20
+ </div>
21
+ <div class="footer-section">
22
+ <span if:true={showStepNumber} class="step-id">
23
+ {stepDetails}
24
+ </span>
25
+ </div>
26
+ <div class="footer-section">
27
+ <slot name="primary-action-section"></slot>
28
+ </div>
29
+ </div>
30
+ </div>
31
+ </template>
@@ -0,0 +1,55 @@
1
+ import { api, LightningElement } from "lwc";
2
+ import { toDxColor } from "dxUtils/css";
3
+
4
+ export type HeaderData = {
5
+ backgroundColor?: string;
6
+ iconColor?: string;
7
+ iconSymbol?: string;
8
+ iconSprite?: string;
9
+ textColor?: string;
10
+ };
11
+
12
+ export default class StepSequenceStep extends LightningElement {
13
+ @api headerIconColor = "";
14
+ @api headerIconSymbol = "";
15
+ @api headerIconSprite = "";
16
+ @api headerBackgroundColor = "indigo-vibrant-20";
17
+ @api headerTextColor = "white";
18
+ @api showStepNumber = false;
19
+ @api stepCount: number | undefined;
20
+ @api stepFormatString: string | undefined;
21
+ @api stepIndex: number | undefined;
22
+ @api stepTitle: string | undefined;
23
+
24
+ get stepDetails() {
25
+ if (
26
+ typeof this.stepIndex !== "number" ||
27
+ typeof this.stepCount !== "number"
28
+ ) {
29
+ return "";
30
+ }
31
+
32
+ const displayStepNumber = this.stepIndex + 1;
33
+
34
+ return this.stepFormatString
35
+ ? this.stepFormatString
36
+ .replace("%d", displayStepNumber.toString())
37
+ .replace("%d", this.stepCount.toString())
38
+ : `Step ${displayStepNumber} of ${this.stepCount}`;
39
+ }
40
+
41
+ get hasDefinedIcon() {
42
+ return Boolean(this.headerIconSymbol && this.headerIconSprite);
43
+ }
44
+
45
+ connectedCallback() {
46
+ this.template.host.style.setProperty(
47
+ "--dx-c-card-step-header-background-color",
48
+ toDxColor(this.headerBackgroundColor)
49
+ );
50
+ this.template.host.style.setProperty(
51
+ "--dx-c-card-step-header-text-color",
52
+ toDxColor(this.headerTextColor)
53
+ );
54
+ }
55
+ }
@@ -6,11 +6,11 @@ export default class Checkbox extends LightningElement {
6
6
  @api errorMessage?: string = "Please check this box if you want to proceed";
7
7
  @api label?: string;
8
8
  @api name: string | null = null;
9
- @api required: boolean = false;
10
9
  @api type: "checkbox" | "radio" = "checkbox";
11
10
  @api value!: string;
12
11
 
13
12
  private _checked: boolean = false;
13
+ private _required: boolean = false;
14
14
 
15
15
  @api
16
16
  get checked(): boolean {
@@ -20,6 +20,15 @@ export default class Checkbox extends LightningElement {
20
20
  this._checked = value;
21
21
  }
22
22
 
23
+ @api
24
+ get required(): boolean {
25
+ return this._required;
26
+ }
27
+ set required(value: boolean) {
28
+ this._required = value;
29
+ this.setAttribute("required", value); // reflect to HTML
30
+ }
31
+
23
32
  private showValidity = false;
24
33
 
25
34
  private get valid(): boolean {
@@ -40,6 +49,11 @@ export default class Checkbox extends LightningElement {
40
49
  return this.valid;
41
50
  }
42
51
 
52
+ @api
53
+ checkValidity(): boolean {
54
+ return this.valid;
55
+ }
56
+
43
57
  private onChange(e: InputEvent) {
44
58
  this._checked = ((e.currentTarget as HTMLInputElement) || {}).checked;
45
59
  this.dispatchEvent(
@@ -63,7 +63,7 @@
63
63
  <dx-button
64
64
  if:true={ctaSecondaryLabel}
65
65
  href={ctaSecondaryHref}
66
- variant="secondary"
66
+ variant="quaternary"
67
67
  icon-symbol={ctaSecondarySymbol}
68
68
  target={ctaSecondaryTarget}
69
69
  size="large"
@@ -0,0 +1,3 @@
1
+ <template>
2
+ <span lwc:dom="manual"></span>
3
+ </template>
@@ -0,0 +1,10 @@
1
+ import { api, LightningElement } from "lwc";
2
+
3
+ // Renders provided innerHtml. Useful for manual DOM elements created inside of loops.
4
+ export default class HtmlRenderer extends LightningElement {
5
+ @api innerHtml = "";
6
+
7
+ renderedCallback() {
8
+ this.template.querySelector("span")!.innerHTML = this.innerHtml;
9
+ }
10
+ }