@salesforcedevs/dx-components 0.21.0 → 0.24.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.
Files changed (44) hide show
  1. package/lwc.config.json +2 -0
  2. package/package.json +2 -2
  3. package/src/assets/svg/slack-cta-blog-background-left.svg +14 -0
  4. package/src/assets/svg/slack-cta-blog-background-right.svg +11 -0
  5. package/src/assets/svg/slack-cta-podcast-background-left.svg +28 -0
  6. package/src/assets/svg/slack-cta-podcast-background-right.svg +38 -0
  7. package/src/assets/svg/slack-logo.svg +6 -0
  8. package/src/modules/dx/cardExpanded/__tests__/cardExpanded.test.ts +193 -0
  9. package/src/modules/dx/cardExpanded/__tests__/mockProps.ts +21 -0
  10. package/src/modules/dx/cardExpanded/cardExpanded.css +49 -0
  11. package/src/modules/dx/cardExpanded/cardExpanded.html +37 -0
  12. package/src/modules/dx/cardExpanded/cardExpanded.stories.ts +59 -0
  13. package/src/modules/dx/cardExpanded/cardExpanded.ts +45 -0
  14. package/src/modules/dx/cardMinimal/__tests__/cardMinimal.test.ts +87 -0
  15. package/src/modules/dx/cardMinimal/__tests__/mockProps.ts +10 -0
  16. package/src/modules/dx/cardMinimal/cardMinimal.css +31 -0
  17. package/src/modules/dx/cardMinimal/cardMinimal.html +13 -0
  18. package/src/modules/dx/cardMinimal/cardMinimal.stories.ts +32 -0
  19. package/src/modules/dx/cardMinimal/cardMinimal.ts +3 -0
  20. package/src/modules/dx/codeBlock/__tests__/codeBlock.test.ts +0 -4
  21. package/src/modules/dx/grid/__tests__/grid.test.ts +2 -7
  22. package/src/modules/dx/headerSearch/__tests__/headerSearch.test.ts +0 -1
  23. package/src/modules/dx/imageAndLabel/imageAndLabel.html +14 -2
  24. package/src/modules/dx/popover/__tests__/popover.test.ts +26 -37
  25. package/src/modules/dx/sidebar/__tests__/sidebar.test.ts +0 -4
  26. package/src/modules/dx/sidebarOld/__tests__/sidebarOld.test.ts +0 -4
  27. package/src/modules/dx/sidebarSearch/sidebarSearch.html +2 -2
  28. package/src/modules/dx/slackAdd/__tests__/slackAdd.test.ts +52 -0
  29. package/src/modules/dx/slackAdd/slackAdd.css +93 -0
  30. package/src/modules/dx/slackAdd/slackAdd.html +17 -0
  31. package/src/modules/dx/slackAdd/slackAdd.stories.ts +25 -0
  32. package/src/modules/dx/slackAdd/slackAdd.ts +13 -0
  33. package/src/modules/dx/socials/__tests__/socials.test.ts +12 -22
  34. package/src/modules/dx/topics/__tests__/mockProps.ts +3 -0
  35. package/src/modules/dx/topics/__tests__/topics.test.ts +31 -0
  36. package/src/modules/dx/topics/topics.css +25 -0
  37. package/src/modules/dx/topics/topics.html +12 -0
  38. package/src/modules/dx/topics/topics.ts +25 -0
  39. package/src/modules/dx/tree/__tests__/tree.test.ts +17 -28
  40. package/src/modules/dx/treeItem/__tests__/treeItem.test.ts +36 -59
  41. package/src/modules/dx/typeBadge/typeBadge.css +1 -1
  42. package/src/modules/helpers/text/text.css +7 -0
  43. package/src/modules/utils/archiveCard/archiveCard.ts +35 -0
  44. package/src/modules/utils/normalizers/normalizers.ts +2 -2
@@ -0,0 +1,12 @@
1
+ <template>
2
+ <div class="container dx-text-label-1-dark">
3
+ <template for:each={normalizedTopics} for:item="topic">
4
+ <span key={topic.id}>{topic.label}</span>
5
+ <span
6
+ key={topic.id}
7
+ if:false={topic.isLast}
8
+ class="dot-separator"
9
+ ></span>
10
+ </template>
11
+ </div>
12
+ </template>
@@ -0,0 +1,25 @@
1
+ import { LightningElement, api } from "lwc";
2
+ import { normalizeToArray } from "utils/normalizers";
3
+
4
+ export default class Topics extends LightningElement {
5
+ private _topics: Array<string> = [];
6
+
7
+ @api
8
+ get topics() {
9
+ return this._topics;
10
+ }
11
+
12
+ set topics(value) {
13
+ this._topics = normalizeToArray(value);
14
+ }
15
+
16
+ get normalizedTopics() {
17
+ const { length } = this._topics;
18
+
19
+ return this._topics?.map((topic, index) => ({
20
+ id: topic,
21
+ label: topic,
22
+ isLast: index === length - 1
23
+ }));
24
+ }
25
+ }
@@ -37,10 +37,6 @@ describe(TAG, () => {
37
37
  mockInitialize.mockReturnValue(INITIALIZE_MOCK_RESULT);
38
38
  });
39
39
 
40
- afterEach(() => {
41
- jest.clearAllMocks();
42
- });
43
-
44
40
  describe("component render", () => {
45
41
  it("should render dx-tree-item with appropiate properties", () => {
46
42
  const component = renderComponent({
@@ -49,9 +45,8 @@ describe(TAG, () => {
49
45
  expect(component.treeRoot).toEqual(INITIALIZE_MOCK_RESULT);
50
46
  expect(component.value).toBeUndefined();
51
47
 
52
- const treeItem: TreeItem = component.shadowRoot.querySelector(
53
- "dx-tree-item"
54
- );
48
+ const treeItem: TreeItem =
49
+ component.shadowRoot.querySelector("dx-tree-item");
55
50
  expect(treeItem).not.toBeNull();
56
51
  expect(treeItem.treeNode).toEqual(INITIALIZE_MOCK_RESULT);
57
52
  expect(treeItem.isRoot).toBe(true);
@@ -81,9 +76,8 @@ describe(TAG, () => {
81
76
  expect(component.treeRoot).toEqual(INITIALIZE_MOCK_RESULT);
82
77
  expect(component.value).toBe(INITIALIZE_MOCK_PARAMETER.name);
83
78
 
84
- const treeItem: TreeItem = component.shadowRoot.querySelector(
85
- "dx-tree-item"
86
- );
79
+ const treeItem: TreeItem =
80
+ component.shadowRoot.querySelector("dx-tree-item");
87
81
  expect(treeItem).not.toBeNull();
88
82
  expect(treeItem.treeNode).toEqual(INITIALIZE_MOCK_RESULT);
89
83
  expect(treeItem.isRoot).toBe(true);
@@ -122,9 +116,8 @@ describe(TAG, () => {
122
116
  value: INITIALIZE_MOCK_PARAMETER.name
123
117
  });
124
118
 
125
- const treeItem: TreeItem = component.shadowRoot.querySelector(
126
- "dx-tree-item"
127
- );
119
+ const treeItem: TreeItem =
120
+ component.shadowRoot.querySelector("dx-tree-item");
128
121
  expect(treeItem).not.toBeNull();
129
122
  expect(treeItem.selectedKey).toBe(validKey);
130
123
 
@@ -183,9 +176,8 @@ describe(TAG, () => {
183
176
  expect(mockGetNode).not.toBeCalled();
184
177
 
185
178
  return Promise.resolve().then(() => {
186
- const treeItem: TreeItem = component.shadowRoot.querySelector(
187
- "dx-tree-item"
188
- );
179
+ const treeItem: TreeItem =
180
+ component.shadowRoot.querySelector("dx-tree-item");
189
181
  expect(treeItem).not.toBeNull();
190
182
  expect(treeItem.selectedKey).toBe(expectedKey);
191
183
 
@@ -241,9 +233,8 @@ describe(TAG, () => {
241
233
  const mockTileSelected = jest.fn();
242
234
  component.addEventListener("tileselected", mockTileSelected);
243
235
 
244
- const treeItem: TreeItem = component.shadowRoot.querySelector(
245
- "dx-tree-item"
246
- );
236
+ const treeItem: TreeItem =
237
+ component.shadowRoot.querySelector("dx-tree-item");
247
238
  treeItem.dispatchEvent(
248
239
  new CustomEvent("tileselected", MOCK_TILE_DETAIL)
249
240
  );
@@ -339,15 +330,13 @@ describe(TAG, () => {
339
330
  const mockRegister = jest.fn();
340
331
  component.addEventListener("register", mockRegister);
341
332
 
342
- component.shadowRoot
343
- .querySelector("dx-tree-item")
344
- .dispatchEvent(
345
- new CustomEvent("register", {
346
- detail,
347
- bubbles: true,
348
- composed: true
349
- })
350
- );
333
+ component.shadowRoot.querySelector("dx-tree-item").dispatchEvent(
334
+ new CustomEvent("register", {
335
+ detail,
336
+ bubbles: true,
337
+ composed: true
338
+ })
339
+ );
351
340
 
352
341
  expect(mockRegisterSetExpanded).toBeCalledTimes(1);
353
342
  expect(mockRegisterSetExpanded).toBeCalledWith(detail);
@@ -31,9 +31,8 @@ describe(TAG, () => {
31
31
  const link = component.shadowRoot.querySelector("a");
32
32
  expect(link).not.toBeNull();
33
33
 
34
- const tile: TreeTile = component.shadowRoot.querySelector(
35
- "a > dx-tree-tile"
36
- );
34
+ const tile: TreeTile =
35
+ component.shadowRoot.querySelector("a > dx-tree-tile");
37
36
  expect(tile).not.toBeNull();
38
37
  assertTile(tile, {
39
38
  isRoot: true,
@@ -43,9 +42,8 @@ describe(TAG, () => {
43
42
  isSelected: false
44
43
  });
45
44
 
46
- const childTreeItem = component.shadowRoot.querySelector(
47
- "dx-tree-item"
48
- );
45
+ const childTreeItem =
46
+ component.shadowRoot.querySelector("dx-tree-item");
49
47
  expect(childTreeItem).toBeNull();
50
48
 
51
49
  return expect(component).toBeAccessible();
@@ -57,9 +55,8 @@ describe(TAG, () => {
57
55
  treeNode
58
56
  });
59
57
 
60
- const tile: TreeTile = component.shadowRoot.querySelector(
61
- "a > dx-tree-tile"
62
- );
58
+ const tile: TreeTile =
59
+ component.shadowRoot.querySelector("a > dx-tree-tile");
63
60
  expect(tile).not.toBeNull();
64
61
  assertTile(tile, {
65
62
  isRoot: false,
@@ -69,9 +66,8 @@ describe(TAG, () => {
69
66
  isSelected: false
70
67
  });
71
68
 
72
- const children: Array<TreeItem> = component.shadowRoot.querySelectorAll(
73
- "dx-tree-item"
74
- );
69
+ const children: Array<TreeItem> =
70
+ component.shadowRoot.querySelectorAll("dx-tree-item");
75
71
  expect(children).toHaveLength(NODE_WITH_CHILDREN.children!.length);
76
72
 
77
73
  children.forEach((child, index) => {
@@ -99,9 +95,8 @@ describe(TAG, () => {
99
95
  SINGLE_NODE_WITH_LINK.link!.target
100
96
  );
101
97
 
102
- const tile: TreeTile = component.shadowRoot.querySelector(
103
- "a > dx-tree-tile"
104
- );
98
+ const tile: TreeTile =
99
+ component.shadowRoot.querySelector("a > dx-tree-tile");
105
100
  expect(tile).not.toBeNull();
106
101
  assertTile(tile, {
107
102
  isRoot: false,
@@ -111,9 +106,8 @@ describe(TAG, () => {
111
106
  isSelected: true
112
107
  });
113
108
 
114
- const anyChild: TreeItem = component.shadowRoot.querySelector(
115
- "dx-tree-item"
116
- );
109
+ const anyChild: TreeItem =
110
+ component.shadowRoot.querySelector("dx-tree-item");
117
111
  expect(anyChild).toBeNull();
118
112
 
119
113
  return expect(component).toBeAccessible();
@@ -143,9 +137,8 @@ describe(TAG, () => {
143
137
  selectedKey: "not_this"
144
138
  });
145
139
 
146
- const tile: TreeTile = component.shadowRoot.querySelector(
147
- "a > dx-tree-tile"
148
- );
140
+ const tile: TreeTile =
141
+ component.shadowRoot.querySelector("a > dx-tree-tile");
149
142
  expect(tile).not.toBeNull();
150
143
  assertTile(tile, {
151
144
  isRoot: false,
@@ -163,10 +156,6 @@ describe(TAG, () => {
163
156
  const mockExpandCollapse = jest.fn();
164
157
  const mockTileSelected = jest.fn();
165
158
 
166
- afterEach(() => {
167
- jest.clearAllMocks();
168
- });
169
-
170
159
  it("should render the children when the dx-tree-tile emits iconclick", () => {
171
160
  const component = renderComponent({
172
161
  treeNode: NODE_WITH_CHILDREN
@@ -175,14 +164,12 @@ describe(TAG, () => {
175
164
  component.addEventListener("expandcollapse", mockExpandCollapse);
176
165
  component.addEventListener("tileselected", mockTileSelected);
177
166
 
178
- const anyChild: TreeItem = component.shadowRoot.querySelector(
179
- "dx-tree-item"
180
- );
167
+ const anyChild: TreeItem =
168
+ component.shadowRoot.querySelector("dx-tree-item");
181
169
  expect(anyChild).toBeNull();
182
170
 
183
- const tile: HTMLElement = component.shadowRoot.querySelector(
184
- "dx-tree-tile"
185
- )!;
171
+ const tile: HTMLElement =
172
+ component.shadowRoot.querySelector("dx-tree-tile")!;
186
173
  expect(tile).toHaveProperty("isExpanded", false);
187
174
  tile.dispatchEvent(new CustomEvent("iconclick"));
188
175
 
@@ -193,9 +180,8 @@ describe(TAG, () => {
193
180
  });
194
181
 
195
182
  return Promise.resolve().then(() => {
196
- const children: Array<TreeItem> = component.shadowRoot.querySelectorAll(
197
- "dx-tree-item"
198
- );
183
+ const children: Array<TreeItem> =
184
+ component.shadowRoot.querySelectorAll("dx-tree-item");
199
185
  expect(children).toHaveLength(
200
186
  NODE_WITH_CHILDREN.children!.length
201
187
  );
@@ -224,14 +210,12 @@ describe(TAG, () => {
224
210
  component.addEventListener("expandcollapse", mockExpandCollapse);
225
211
  component.addEventListener("tileselected", mockTileSelected);
226
212
 
227
- const tile: HTMLElement = component.shadowRoot.querySelector(
228
- "dx-tree-tile"
229
- );
213
+ const tile: HTMLElement =
214
+ component.shadowRoot.querySelector("dx-tree-tile");
230
215
  expect(tile).toHaveProperty("isExpanded", true);
231
216
 
232
- const children: Array<TreeItem> = component.shadowRoot.querySelectorAll(
233
- "dx-tree-item"
234
- );
217
+ const children: Array<TreeItem> =
218
+ component.shadowRoot.querySelectorAll("dx-tree-item");
235
219
  expect(children).toHaveLength(NODE_WITH_CHILDREN.children!.length);
236
220
 
237
221
  tile.dispatchEvent(new CustomEvent("iconclick"));
@@ -245,9 +229,8 @@ describe(TAG, () => {
245
229
  return Promise.resolve().then(() => {
246
230
  expect(tile).toHaveProperty("isExpanded", false);
247
231
 
248
- const anyChild: TreeItem = component.shadowRoot.querySelector(
249
- "dx-tree-item"
250
- );
232
+ const anyChild: TreeItem =
233
+ component.shadowRoot.querySelector("dx-tree-item");
251
234
  expect(anyChild).toBeNull();
252
235
 
253
236
  expect(mockExpandCollapse).toBeCalledTimes(1);
@@ -313,9 +296,8 @@ describe(TAG, () => {
313
296
  component.addEventListener("tileselected", mockTileSelected);
314
297
  component.addEventListener("expandcollapse", mockExpandCollapse);
315
298
 
316
- const tile: TreeTile = component.shadowRoot.querySelector(
317
- "dx-tree-tile"
318
- );
299
+ const tile: TreeTile =
300
+ component.shadowRoot.querySelector("dx-tree-tile");
319
301
  expect(tile).toHaveProperty("isSelected", true);
320
302
 
321
303
  const link: HTMLElement = component.shadowRoot.querySelector("a");
@@ -349,16 +331,13 @@ describe(TAG, () => {
349
331
  });
350
332
 
351
333
  expect(mockRegister).toBeCalledTimes(1);
352
- const {
353
- key: actualKey,
354
- setExpanded
355
- } = mockRegister.mock.calls[0][0].detail;
334
+ const { key: actualKey, setExpanded } =
335
+ mockRegister.mock.calls[0][0].detail;
356
336
  expect(actualKey).toBe(NODE_WITH_CHILDREN.key);
357
337
  expect(typeof setExpanded).toBe("function");
358
338
 
359
- const tile: TreeTile = component.shadowRoot.querySelector(
360
- "dx-tree-tile"
361
- );
339
+ const tile: TreeTile =
340
+ component.shadowRoot.querySelector("dx-tree-tile");
362
341
  expect(tile).not.toBeNull();
363
342
  expect(tile).toHaveProperty("isExpanded", false);
364
343
 
@@ -371,9 +350,8 @@ describe(TAG, () => {
371
350
  return Promise.resolve().then(() => {
372
351
  expect(tile).toHaveProperty("isExpanded", true);
373
352
 
374
- const trees = component.shadowRoot.querySelectorAll(
375
- "dx-tree-item"
376
- );
353
+ const trees =
354
+ component.shadowRoot.querySelectorAll("dx-tree-item");
377
355
  expect(trees).toHaveLength(NODE_WITH_CHILDREN.children!.length);
378
356
  });
379
357
  });
@@ -383,9 +361,8 @@ describe(TAG, () => {
383
361
  treeNode: SINGLE_NODE_WITH_LINK
384
362
  });
385
363
 
386
- const link: HTMLAnchorElement = component.shadowRoot.querySelector(
387
- "a"
388
- );
364
+ const link: HTMLAnchorElement =
365
+ component.shadowRoot.querySelector("a");
389
366
  expect(link).not.toBeNull();
390
367
 
391
368
  link.click();
@@ -66,7 +66,7 @@
66
66
  }
67
67
 
68
68
  @media screen and (max-width: 768px) {
69
- .typebadge:not(.size-small):not(.size-xs) {
69
+ .typebadge.typebadge_metadata:not(.size-small) {
70
70
  height: var(--dx-g-spacing-lg);
71
71
  padding: 0 var(--dx-g-spacing-sm);
72
72
  font-size: var(--dx-g-text-2xs);
@@ -154,3 +154,10 @@
154
154
  font-size: var(--dx-g-text-xs);
155
155
  line-height: 14px;
156
156
  }
157
+
158
+ .dx-text-truncate {
159
+ display: -webkit-box;
160
+ -webkit-line-clamp: var(--dx-c-max-lines, 6);
161
+ -webkit-box-orient: vertical;
162
+ overflow: hidden;
163
+ }
@@ -0,0 +1,35 @@
1
+ import { LightningElement, api } from "lwc";
2
+ import { LinkTarget, Color } from "typings/custom";
3
+
4
+ const MOBILE_QUERY = "(max-width: 640px)";
5
+
6
+ export abstract class ArchiveCard extends LightningElement {
7
+ @api contentType: "Blog" | "Podcast" = "Blog";
8
+ @api href!: string;
9
+ @api title!: string;
10
+ @api target: LinkTarget = "_self";
11
+
12
+ private matchMedia!: MediaQueryList;
13
+ protected mobile = false;
14
+
15
+ protected get badgeColor(): Color {
16
+ return this.contentType === "Blog" ? "teal" : "blue";
17
+ }
18
+
19
+ connectedCallback(): void {
20
+ this.matchMedia = window.matchMedia(MOBILE_QUERY);
21
+ this.onMediaChange(this.matchMedia);
22
+ this.matchMedia.addEventListener("change", this.onMediaChange);
23
+ }
24
+
25
+ disconnectedCallback(): void {
26
+ this.matchMedia.removeEventListener("change", this.onMediaChange);
27
+ }
28
+
29
+ private onMediaChange = (e: MediaQueryListEvent | MediaQueryList) =>
30
+ (this.mobile = e.matches);
31
+
32
+ protected get badgeSize(): string {
33
+ return (this.mobile && "small") || "default";
34
+ }
35
+ }
@@ -6,7 +6,7 @@ export const toJson = (value: string | object | null) =>
6
6
  export const normalizeToArray = (
7
7
  value: string[] | string | null,
8
8
  splitKey: string = ","
9
- ) => {
9
+ ): Array<string> => {
10
10
  if (!value) {
11
11
  return [];
12
12
  }
@@ -19,7 +19,7 @@ export const normalizeToArray = (
19
19
  }
20
20
  }
21
21
 
22
- return Array.isArray(value) ? value : [value];
22
+ return (Array.isArray(value) ? value : [value]) as Array<string>;
23
23
  };
24
24
 
25
25
  type WordpressPodcastEpisode = {