@salesforcedevs/dx-components 1.3.66-alpha-032 → 1.3.66-modal-001

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
@@ -98,7 +98,6 @@
98
98
  "dxUtils/analytics",
99
99
  "dxUtils/async",
100
100
  "dxUtils/constants",
101
- "dxUtils/contentTypes",
102
101
  "dxUtils/coveo",
103
102
  "dxUtils/dates",
104
103
  "dxUtils/highlight",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforcedevs/dx-components",
3
- "version": "1.3.66-alpha-032",
3
+ "version": "1.3.66-modal-001",
4
4
  "description": "DX Lightning web components",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -2,7 +2,6 @@
2
2
  <dx-modal
3
3
  if:true={hasTwoButtons}
4
4
  open={_modalOpen}
5
- ontogglemodal={toggleModal}
6
5
  onclosemodal={closeModal}
7
6
  >
8
7
  <dx-card-trial-expanded
@@ -24,6 +23,7 @@
24
23
  title={title}
25
24
  type-badge-value={modalTypeBadgeValue}
26
25
  type-badge-dark={modalTypeBadgeDark}
26
+ onclickclose={closeModal}
27
27
  ></dx-card-trial-expanded>
28
28
  </dx-modal>
29
29
  <div class="recommended-container" if:true={recommended}>
@@ -94,7 +94,7 @@
94
94
  <dx-button
95
95
  class="button-two"
96
96
  size="large"
97
- onclick={toggleModal}
97
+ onclick={openModal}
98
98
  variant="secondary"
99
99
  font="sans"
100
100
  icon-symbol={buttonTwoIcon}
@@ -96,8 +96,8 @@ export default class CardTrial extends LightningElement {
96
96
  return cx("details", this.hasButtons && "details_top-margin");
97
97
  }
98
98
 
99
- private toggleModal() {
100
- this._modalOpen = !this._modalOpen;
99
+ private openModal() {
100
+ this._modalOpen = true;
101
101
  }
102
102
 
103
103
  private closeModal() {
@@ -5,7 +5,7 @@
5
5
  class="button-close"
6
6
  variant="secondary"
7
7
  icon-symbol="close"
8
- onclick={handleModalClose}
8
+ onclick={onClickClose}
9
9
  >
10
10
  Close
11
11
  </dx-button>
@@ -40,13 +40,6 @@ export default class CardTrial extends LightningElement {
40
40
  private _colTwoDetails!: string[];
41
41
  private stickyCloseObserver!: IntersectionObserver;
42
42
 
43
- connectedCallback(): void {
44
- this.template.addEventListener(
45
- "keydown",
46
- this.handleKeyDown.bind(this)
47
- );
48
- }
49
-
50
43
  renderedCallback(): void {
51
44
  this.observeStickyClose();
52
45
  }
@@ -71,26 +64,8 @@ export default class CardTrial extends LightningElement {
71
64
  }
72
65
  }
73
66
 
74
- private handleKeyDown(event: KeyboardEvent): void {
75
- if (event.key === "Escape") {
76
- this.handleModalClose();
77
- }
78
- }
79
-
80
- private handleModalToggle() {
81
- this.dispatchEvent(
82
- new CustomEvent("togglemodal", {
83
- bubbles: true
84
- })
85
- );
86
- }
87
-
88
- private handleModalClose() {
89
- this.dispatchEvent(
90
- new CustomEvent("closemodal", {
91
- bubbles: true
92
- })
93
- );
67
+ private onClickClose() {
68
+ this.dispatchEvent(new CustomEvent("clickclose"));
94
69
  }
95
70
 
96
71
  private handleSignUpClick(e: PointerEvent) {
@@ -1,40 +1,7 @@
1
- :host {
2
- --dx-c-modal-drawer-z-index: 5000;
1
+ .dx-modal-drawer_container {
2
+ display: none !important;
3
3
  }
4
4
 
5
- .modal-drawer_container {
6
- display: none;
7
- }
8
-
9
- .modal-drawer_container.modal-drawer_active {
10
- position: fixed;
11
- top: 50%;
12
- left: 50%;
13
- transform: translate(-50%, -50%);
14
- display: grid;
15
- justify-content: center;
16
- align-items: center;
17
- z-index: var(--dx-c-modal-drawer-z-index);
18
- height: 100%;
19
- width: 100%;
20
- pointer-events: none;
21
- }
22
-
23
- .modal-drawer_overlay {
24
- background-color: #195594;
25
- bottom: 0;
26
- height: 100%;
27
- left: 0;
28
- opacity: 0.62;
29
- position: fixed;
30
- right: 0;
31
- top: 0;
32
- width: 100%;
33
- z-index: calc(var(--dx-c-modal-drawer-z-index) - 1);
34
- }
35
-
36
- @media screen and (max-width: 768px) {
37
- .modal-drawer_container.modal-drawer_active {
38
- pointer-events: all;
39
- }
5
+ .dx-modal-drawer_overlay {
6
+ display: none !important;
40
7
  }
@@ -1,10 +1,13 @@
1
1
  <template>
2
- <div class={containerClass} tabindex="0" role="dialog">
3
- <slot></slot>
4
- </div>
5
2
  <div
6
- if:true={open}
7
- class="modal-drawer_overlay"
8
- onclick={handleCloseModal}
9
- ></div>
3
+ class={containerClass}
4
+ onclick={onClickModal}
5
+ tabindex="0"
6
+ role="dialog"
7
+ >
8
+ <div style="pointer-events: all">
9
+ <slot onslotchange={onSlotChange}></slot>
10
+ </div>
11
+ </div>
12
+ <div class={overlayClass} onclick={onClickModal}></div>
10
13
  </template>
@@ -1,55 +1,98 @@
1
- import cx from "classnames";
2
1
  import { LightningElement, api } from "lwc";
3
2
  import { normalizeBoolean } from "dxUtils/normalizers";
3
+ import { LightningSlotElement } from "typings/custom";
4
+
5
+ const CONTAINER_CLASS = "dx-modal-drawer_container";
6
+ const OVERLAY_CLASS = "dx-modal-drawer_overlay";
7
+
8
+ const modalStyle =
9
+ "position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); display: grid; justify-content: center; align-items: center; z-index: 5000; height: 100%; width: 100%; pointer-events: none;";
10
+ const overlayStyle =
11
+ "background-color: #195594; bottom: 0; height: 100%; left: 0; opacity: 0.62; position: fixed; right: 0; top: 0; width: 100%; z-index: calc(5000 - 1);";
4
12
 
5
13
  export default class Modal extends LightningElement {
6
14
  private _open = false;
7
-
8
15
  @api get open() {
9
16
  return this._open;
10
17
  }
11
-
12
18
  set open(value) {
13
19
  this._open = normalizeBoolean(value);
20
+ if (this._open) {
21
+ this.openModal();
22
+ } else {
23
+ this.closeModal();
24
+ }
14
25
  }
15
26
 
27
+ private overlayClass = OVERLAY_CLASS;
28
+ private modal: HTMLElement | null = null;
29
+ private overlay: HTMLElement | null = null;
30
+ private root: HTMLElement | null = null;
31
+ private modalContent: HTMLElement | null = null;
32
+ private keydownListener: Event | null = null;
33
+
16
34
  get containerClass(): string {
17
- return cx(
18
- "modal-drawer_container",
19
- this._open && "modal-drawer_active"
20
- );
35
+ return CONTAINER_CLASS;
21
36
  }
22
37
 
23
- renderedCallback(): void {
24
- if (this._open) {
25
- this.focusFirstElement();
38
+ private onSlotChange = (e: LightningSlotElement) => {
39
+ // @ts-ignore
40
+ this.modalContent = e.target.assignedElements()[0];
41
+ if (!this.modal && !this.overlay) {
42
+ this.appendModalToHTML();
26
43
  }
27
- }
44
+ };
28
45
 
29
- connectedCallback(): void {
30
- this.template.addEventListener(
31
- "keydown",
32
- this.handleKeyDown.bind(this)
33
- );
46
+ private connectedCallback(): void {
47
+ document.addEventListener("keydown", this.handleKeyDown.bind(this));
34
48
  }
35
49
 
36
- focusFirstElement(): void {
37
- this.template.querySelector("div")!.focus();
50
+ private disconnectedCallback(): void {
51
+ window.removeEventListener("keydown", this.handleKeyDown.bind(this));
52
+ this.modal?.remove();
53
+ this.overlay?.remove();
38
54
  }
39
55
 
40
- handleKeyDown(event: KeyboardEvent): void {
56
+ private handleKeyDown(event: KeyboardEvent): void {
41
57
  if (event.key === "Escape") {
42
- this.handleCloseModal();
58
+ this.closeModal();
43
59
  }
44
60
  }
45
61
 
46
- handleToggleModal() {
47
- this._open = !this._open;
48
- this.dispatchEvent(new CustomEvent("togglemodal"));
62
+ private appendModalToHTML = () => {
63
+ // @ts-ignore
64
+ this.root = document.querySelector("html");
65
+ this.modal = this.template.querySelector(`.${CONTAINER_CLASS}`);
66
+ this.overlay = this.template.querySelector(`.${OVERLAY_CLASS}`);
67
+ if (this.overlay && this.modal && this.modalContent && this.root) {
68
+ this.modal.setAttribute("style", modalStyle);
69
+ this.overlay.setAttribute("style", overlayStyle);
70
+ this.modal.querySelector("div")?.appendChild(this.modalContent);
71
+ if (this.open) {
72
+ this.openModal();
73
+ }
74
+ }
75
+ };
76
+
77
+ private onClickModal(e) {
78
+ if (e?.target?.className === OVERLAY_CLASS) {
79
+ this.closeModal();
80
+ }
49
81
  }
50
82
 
51
- handleCloseModal() {
52
- this._open = false;
53
- this.dispatchEvent(new CustomEvent("closemodal"));
83
+ private openModal() {
84
+ if (this.overlay && this.modal) {
85
+ this.root?.appendChild(this.modal);
86
+ this.root?.appendChild(this.overlay);
87
+ this.modal.querySelector("div")?.focus();
88
+ }
54
89
  }
90
+
91
+ private closeModal = () => {
92
+ if (this.modal && this.overlay) {
93
+ this.modal.remove();
94
+ this.overlay.remove();
95
+ this.dispatchEvent(new CustomEvent("closemodal"));
96
+ }
97
+ };
55
98
  }
@@ -1,5 +1,4 @@
1
1
  @import "dxHelpers/reset";
2
- @import "dxHelpers/typeBadge";
3
2
  @import "./coveo.css";
4
3
 
5
4
  /* stylelint-disable selector-class-pattern */
@@ -386,8 +385,3 @@ a.CoveoResultLink,
386
385
  margin: 0 auto;
387
386
  width: fit-content;
388
387
  }
389
-
390
- .dx-badge {
391
- display: block;
392
- margin-bottom: var(--dx-g-spacing-smd);
393
- }
@@ -1,8 +1,6 @@
1
1
  import { LightningElement, api, track } from "lwc";
2
2
  import type * as CoveoSDK from "coveo-search-ui";
3
3
  import { track as trackGTM } from "dxUtils/analytics";
4
- import { CONTENT_TYPE_LABELS } from "dxConstants/contentTypes";
5
- import { getContentTypeColorVariables } from "dxUtils/contentTypes";
6
4
 
7
5
  interface CoveoSearch {
8
6
  state: typeof CoveoSDK.state;
@@ -40,7 +38,6 @@ const resultsTemplatesInnerHtml = `
40
38
  data-field-publicurl=""
41
39
  >
42
40
  <div class="dx-result">
43
- <span class="CoveoFieldValue" data-field="@content_type" data-helper="badge" data-html-value="true"></span>
44
41
  <p class="dx-result-title">
45
42
  <a
46
43
  class="CoveoResultLink"
@@ -56,7 +53,6 @@ const resultsTemplatesInnerHtml = `
56
53
  type="text/html"
57
54
  >
58
55
  <div class="dx-result">
59
- <span class="CoveoFieldValue" data-field="@content_type" data-helper="badge" data-html-value="true"></span>
60
56
  <p class="dx-result-title">
61
57
  <a class="CoveoResultLink"></a>
62
58
  </p>
@@ -175,15 +171,6 @@ export default class SearchResults extends LightningElement {
175
171
 
176
172
  this.attachListeners(this.root);
177
173
 
178
- Coveo.TemplateHelpers.registerTemplateHelper(
179
- "badge",
180
- (value: string) => {
181
- const style = getContentTypeColorVariables(value);
182
- const label = CONTENT_TYPE_LABELS[value];
183
- return `<div style="${style}" class="dx-badge"><span>${label}</span></div>`;
184
- }
185
- );
186
-
187
174
  Coveo.init(this.root);
188
175
  }
189
176
 
@@ -1,2 +1,33 @@
1
1
  @import "dxHelpers/reset";
2
- @import "dxHelpers/typeBadge";
2
+
3
+ .badge {
4
+ --background: var(--sds-g-gray-3);
5
+ --border-radius: var(--dx-g-spacing-smd);
6
+ --color: var(--sds-g-gray-10);
7
+ --height: var(--dx-g-spacing-lg);
8
+ --horizontal-spacing: var(--dx-g-spacing-smd);
9
+ --vertical-spacing: var(--dx-g-spacing-xs);
10
+
11
+ color: var(--dx-c-type-badge-color, var(--color));
12
+ background: var(--dx-c-type-badge-background, var(--background));
13
+ border-radius: var(--border-radius);
14
+ display: flex;
15
+ align-items: center;
16
+ justify-content: center;
17
+ height: var(--height);
18
+ width: min-content;
19
+ text-align: center;
20
+ white-space: nowrap;
21
+ font-family: var(--dx-g-font-sans);
22
+ font-size: 10px;
23
+ font-weight: var(--dx-g-font-bold);
24
+ padding: var(--vertical-spacing) var(--horizontal-spacing);
25
+ }
26
+
27
+ .badge.size-small {
28
+ --height: var(--dx-g-spacing-mlg);
29
+ }
30
+
31
+ dx-icon {
32
+ margin-right: var(--dx-g-spacing-sm);
33
+ }
@@ -5,20 +5,65 @@ import {
5
5
  Color,
6
6
  ContentType,
7
7
  IconSprite,
8
- IconData,
9
8
  IconSymbol,
10
9
  TypeBadgeSize
11
10
  } from "typings/custom";
12
11
  import { colorToDxColors, buildStyleColorVariables } from "dxUtils/css";
13
- import {
14
- isContentType,
15
- getContentTypeColorScope,
16
- getContentTypeColorVariables
17
- } from "dxUtils/contentTypes";
18
- import {
19
- CONTENT_TYPE_LABELS,
20
- CONTENT_TYPE_ICONS
21
- } from "dxConstants/contentTypes";
12
+ import { BRANDS } from "dxConstants/brands";
13
+ import { CONTENT_TYPES } from "dxConstants/contentTypes";
14
+
15
+ const contentTypeLabels = {
16
+ documentation: "Documentation",
17
+ trailhead: "Trailhead",
18
+ blog: "Blog",
19
+ forum: "Forum",
20
+ api: "API",
21
+ event: "Event",
22
+ website: "Website",
23
+ podcast: "Podcast"
24
+ };
25
+
26
+ type IconData = {
27
+ iconSymbol: IconSymbol;
28
+ iconSprite: IconSprite;
29
+ };
30
+
31
+ const contentTypeIcons: {
32
+ [K in ContentType]: IconData;
33
+ } = {
34
+ documentation: {
35
+ iconSprite: "utility",
36
+ iconSymbol: "knowledge_base"
37
+ },
38
+ trailhead: {
39
+ iconSprite: "salesforcebrand",
40
+ iconSymbol: "learning"
41
+ },
42
+ blog: {
43
+ iconSprite: "utility",
44
+ iconSymbol: "comments"
45
+ },
46
+ forum: {
47
+ iconSprite: "general",
48
+ iconSymbol: "question-circle"
49
+ },
50
+ api: {
51
+ iconSprite: "utility",
52
+ iconSymbol: "settings"
53
+ },
54
+ event: {
55
+ iconSprite: "utility",
56
+ iconSymbol: "event"
57
+ },
58
+ website: {
59
+ iconSprite: "utility",
60
+ iconSymbol: "home"
61
+ },
62
+ podcast: {
63
+ iconSprite: "utility",
64
+ iconSymbol: "unmuted"
65
+ }
66
+ };
22
67
 
23
68
  export default class TypeBadge extends LightningElement {
24
69
  @api size: TypeBadgeSize = "default";
@@ -66,29 +111,39 @@ export default class TypeBadge extends LightningElement {
66
111
  private _iconSymbol?: IconSymbol;
67
112
 
68
113
  private get variantIconData(): IconData | null {
69
- if (this.variant && this.variant in CONTENT_TYPE_ICONS) {
70
- return CONTENT_TYPE_ICONS[this.variant as ContentType];
114
+ if (this.variant && this.variant in contentTypeIcons) {
115
+ return contentTypeIcons[this.variant as ContentType];
71
116
  }
72
117
  return null;
73
118
  }
74
119
 
75
120
  private get variantLabel(): string | null {
76
121
  if (this.isContentType) {
77
- return CONTENT_TYPE_LABELS[this.variant as ContentType];
122
+ return contentTypeLabels[this.variant as ContentType];
78
123
  }
79
124
  return null;
80
125
  }
81
126
 
82
127
  private get variantColorScope(): string | null {
83
- return getContentTypeColorScope(this.variant);
128
+ if (this.isContentType) {
129
+ return "content-type";
130
+ }
131
+ if (this.isBrand) {
132
+ return "brand";
133
+ }
134
+ return null;
84
135
  }
85
136
 
86
137
  private get isContentType(): boolean {
87
- return isContentType(this.variant);
138
+ return CONTENT_TYPES.includes(this.variant as ContentType);
139
+ }
140
+
141
+ private get isBrand(): boolean {
142
+ return BRANDS.includes(this.variant as ContentType);
88
143
  }
89
144
 
90
145
  private get className(): string {
91
- return cx("dx-badge", `size-${this.size}`);
146
+ return cx("badge", `size-${this.size}`);
92
147
  }
93
148
 
94
149
  private get style(): string {
@@ -99,7 +154,10 @@ export default class TypeBadge extends LightningElement {
99
154
  });
100
155
  }
101
156
  if (this.variantColorScope) {
102
- return getContentTypeColorVariables(this.variant);
157
+ return buildStyleColorVariables({
158
+ background: `--dx-g-${this.variantColorScope}-${this.variant}-color-background`,
159
+ color: `--dx-g-${this.variantColorScope}-${this.variant}-color`
160
+ });
103
161
  }
104
162
  if (this.color) {
105
163
  const variables = colorToDxColors(this.color as Color);
@@ -1,54 +1,3 @@
1
- import { ContentType, IconData } from "typings/custom";
2
-
3
- export const CONTENT_TYPE_LABELS = {
4
- documentation: "Documentation",
5
- trailhead: "Trailhead",
6
- blog: "Blog",
7
- forum: "Forum",
8
- api: "API",
9
- event: "Event",
10
- website: "Website",
11
- podcast: "Podcast"
12
- };
13
-
14
- export const CONTENT_TYPE_ICONS: {
15
- [K in ContentType]: IconData;
16
- } = {
17
- documentation: {
18
- iconSprite: "utility",
19
- iconSymbol: "knowledge_base"
20
- },
21
- trailhead: {
22
- iconSprite: "salesforcebrand",
23
- iconSymbol: "learning"
24
- },
25
- blog: {
26
- iconSprite: "utility",
27
- iconSymbol: "comments"
28
- },
29
- forum: {
30
- iconSprite: "general",
31
- iconSymbol: "question-circle"
32
- },
33
- api: {
34
- iconSprite: "utility",
35
- iconSymbol: "settings"
36
- },
37
- event: {
38
- iconSprite: "utility",
39
- iconSymbol: "event"
40
- },
41
- website: {
42
- iconSprite: "utility",
43
- iconSymbol: "home"
44
- },
45
- podcast: {
46
- iconSprite: "utility",
47
- iconSymbol: "unmuted"
48
- }
49
- };
50
-
51
-
52
1
  export const CONTENT_TYPES = [
53
2
  "documentation",
54
3
  "trailhead",
@@ -1,31 +0,0 @@
1
- .dx-badge {
2
- --background: var(--sds-g-gray-3);
3
- --border-radius: var(--dx-g-spacing-smd);
4
- --color: var(--sds-g-gray-10);
5
- --height: var(--dx-g-spacing-lg);
6
- --horizontal-spacing: var(--dx-g-spacing-smd);
7
- --vertical-spacing: var(--dx-g-spacing-xs);
8
-
9
- color: var(--dx-c-type-badge-color, var(--color));
10
- background: var(--dx-c-type-badge-background, var(--background));
11
- border-radius: var(--border-radius);
12
- display: flex;
13
- align-items: center;
14
- justify-content: center;
15
- height: var(--height);
16
- width: min-content;
17
- text-align: center;
18
- white-space: nowrap;
19
- font-family: var(--dx-g-font-sans);
20
- font-size: 10px;
21
- font-weight: var(--dx-g-font-bold);
22
- padding: var(--vertical-spacing) var(--horizontal-spacing);
23
- }
24
-
25
- .dx-badge.size-small {
26
- --height: var(--dx-g-spacing-mlg);
27
- }
28
-
29
- dx-icon {
30
- margin-right: var(--dx-g-spacing-sm);
31
- }
@@ -1,30 +0,0 @@
1
- import { CONTENT_TYPES } from "dxConstants/contentTypes";
2
- import { BRANDS } from "dxConstants/brands";
3
- import { ContentType } from "typings/custom";
4
- import { buildStyleColorVariables } from "dxUtils/css";
5
-
6
- export const isBrand = (id: string): boolean => {
7
- return BRANDS.includes(id as ContentType);
8
- };
9
-
10
- export const isContentType = (id: string): boolean => {
11
- return CONTENT_TYPES.includes(id as ContentType);
12
- };
13
-
14
- export const getContentTypeColorScope = (id: string): string | null => {
15
- if (isContentType(id)) {
16
- return "content-type";
17
- }
18
- if (isBrand(id)) {
19
- return "brand";
20
- }
21
- return null;
22
- };
23
-
24
- export const getContentTypeColorVariables = (id: string): string => {
25
- const scope = getContentTypeColorScope(id);
26
- return buildStyleColorVariables({
27
- background: `--dx-g-${scope}-${id}-color-background`,
28
- color: `--dx-g-${scope}-${id}-color`
29
- });
30
- }