@salesforcedevs/dx-components 0.10.1-alpha.13 → 0.10.1-alpha.133

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 (55) hide show
  1. package/lwc.config.json +3 -1
  2. package/package.json +2 -2
  3. package/src/assets/svg/docs-empty-state-small.svg +72 -0
  4. package/src/assets/svg/sidebar-loading.svg +34 -0
  5. package/src/modules/dx/cardGrid/__tests__/cardMockProps.ts +78 -148
  6. package/src/modules/dx/codeBlock/codeBlock.stories.ts +2 -69
  7. package/src/modules/dx/codeBlock/codeBlock.ts +5 -1
  8. package/src/modules/dx/codeBlock/darkTheme.css +0 -1
  9. package/src/modules/dx/codeBlock/lightTheme.css +0 -1
  10. package/src/modules/dx/emptyState/__tests__/emptyState.test.ts +29 -9
  11. package/src/modules/dx/emptyState/emptyState.css +14 -0
  12. package/src/modules/dx/emptyState/emptyState.html +2 -2
  13. package/src/modules/dx/emptyState/emptyState.stories.ts +8 -0
  14. package/src/modules/dx/emptyState/emptyState.ts +14 -0
  15. package/src/modules/dx/footer/links.ts +3 -5
  16. package/src/modules/dx/headerNav/__tests__/headerNav.test.ts +2 -4
  17. package/src/modules/dx/headerNav/headerNav.html +8 -6
  18. package/src/modules/dx/headerNav/headerNav.ts +2 -2
  19. package/src/modules/dx/lazy/lazy.ts +0 -7
  20. package/src/modules/dx/newsletterForm/newsletterForm.html +5 -3
  21. package/src/modules/dx/searchResults/coveo.css +314 -111
  22. package/src/modules/dx/sidebar/__tests__/mockDocContent.ts +48 -0
  23. package/src/modules/dx/sidebar/__tests__/mockPageReference.ts +8 -0
  24. package/src/modules/dx/sidebar/sidebar.css +38 -17
  25. package/src/modules/dx/sidebar/sidebar.html +62 -58
  26. package/src/modules/dx/sidebar/sidebar.stories.ts +53 -54
  27. package/src/modules/dx/sidebar/sidebar.ts +99 -10
  28. package/src/modules/dx/sidebarSearch/__tests__/mockPreloadedState.ts +8843 -0
  29. package/src/modules/dx/sidebarSearch/__tests__/sidebarSearch.test.ts +121 -0
  30. package/src/modules/dx/sidebarSearch/sidebarSearch.ts +282 -120
  31. package/src/modules/dx/sidebarSearch/utils.ts +2 -0
  32. package/src/modules/dx/sidebarSearchResult/__tests__/sidebarSearchResult.test.ts +55 -0
  33. package/src/modules/dx/sidebarSearchResult/sidebarSearchResult.css +12 -2
  34. package/src/modules/dx/sidebarSearchResult/sidebarSearchResult.html +1 -1
  35. package/src/modules/dx/sidebarSearchResult/sidebarSearchResult.ts +8 -2
  36. package/src/modules/dx/spinner/__tests__/spinner.test.ts +37 -0
  37. package/src/modules/dx/spinner/spinner.css +750 -0
  38. package/src/modules/dx/spinner/spinner.html +6 -0
  39. package/src/modules/dx/spinner/spinner.stories.ts +69 -0
  40. package/src/modules/dx/spinner/spinner.ts +20 -0
  41. package/src/modules/dx/{headerNavOption/__tests__/headerNavOption.test.ts → tab/__tests__/tab.test.ts} +40 -24
  42. package/src/modules/dx/{headerNavOption/headerNavOption.css → tab/tab.css} +24 -9
  43. package/src/modules/dx/{headerNavOption/headerNavOption.html → tab/tab.html} +5 -1
  44. package/src/modules/dx/tab/tab.stories.ts +57 -0
  45. package/src/modules/dx/{headerNavOption/headerNavOption.ts → tab/tab.ts} +26 -5
  46. package/src/modules/helpers/table/table.css +23 -7
  47. package/src/modules/utils/coveo/coveo.ts +50 -12
  48. package/src/modules/utils/highlight/__tests__/highlight.test.ts +154 -0
  49. package/src/modules/utils/highlight/highlight.ts +32 -0
  50. package/src/modules/utils/jest/jest.ts +35 -0
  51. package/src/modules/utils/normalizers/normalizers.ts +3 -0
  52. package/src/modules/utils/recentSearches/__tests__/recentSearches.test.ts +79 -0
  53. package/src/modules/utils/recentSearches/recentSearches.ts +12 -17
  54. package/src/modules/utils/regexps/regexps.ts +5 -0
  55. package/src/modules/utils/tests/tests.ts +18 -11
@@ -0,0 +1,32 @@
1
+ import { createSearchRegExp } from "utils/regexps";
2
+
3
+ const MARK_TAGS = /<\/?mark>/gi;
4
+
5
+ export const highlightTerms = (
6
+ // eslint-disable-next-line no-undef
7
+ elements: NodeListOf<Element>,
8
+ searchTerm: string
9
+ ): void => {
10
+ searchTerm = searchTerm.trim();
11
+ const searchExp = createSearchRegExp(searchTerm);
12
+ elements.forEach((element) => {
13
+ if (
14
+ element?.innerHTML.includes("<dx-") ||
15
+ element?.innerHTML.includes("<doc-")
16
+ ) {
17
+ return;
18
+ }
19
+
20
+ let innerHtml = element.innerHTML.replace(
21
+ // Remove previously added mark tags
22
+ MARK_TAGS,
23
+ ""
24
+ );
25
+
26
+ if (searchTerm) {
27
+ innerHtml = innerHtml.replace(searchExp, "<mark>$&</mark>");
28
+ }
29
+
30
+ element.innerHTML = innerHtml;
31
+ });
32
+ };
@@ -21,3 +21,38 @@ export const createMediaMock = (
21
21
  };
22
22
 
23
23
  export const matchMediaMock = createMediaMock();
24
+
25
+ export const mockLocalStorage = function () {
26
+ let store: { [key: string]: string } = {};
27
+ return {
28
+ getItem: function (key: string) {
29
+ return store[key] || null;
30
+ },
31
+ setItem: function (key: string, value: string) {
32
+ store[key] = value.toString();
33
+ },
34
+ removeItem: function (key: string) {
35
+ delete store[key];
36
+ },
37
+ clear: function () {
38
+ store = {};
39
+ }
40
+ };
41
+ };
42
+
43
+ export const mockQueryParameter = (q: string): void => {
44
+ global.window = Object.create(window);
45
+ const search = q ? `?q=${q}` : "";
46
+ const href = `http://dummy.com${search}`;
47
+ // @ts-ignore
48
+ delete window.location.value;
49
+ Object.defineProperty(window, "location", {
50
+ value: {
51
+ href,
52
+ search
53
+ },
54
+ writable: true
55
+ });
56
+ };
57
+
58
+ export const unmockQueryParameter = () => mockQueryParameter("");
@@ -86,3 +86,6 @@ export const normalizePost = ({
86
86
  id,
87
87
  title
88
88
  });
89
+
90
+ export const normalizeBoolean = (value: string | boolean | number): boolean =>
91
+ typeof value === "string" ? value === "true" : !!value;
@@ -0,0 +1,79 @@
1
+ import { RecentSearches, LOCAL_STORAGE_KEY, LIMIT } from "utils/recentSearches";
2
+
3
+ describe("recentSearches", () => {
4
+ beforeEach(() => {
5
+ window.localStorage.clear();
6
+ });
7
+
8
+ it("initializes correctly from local storage", () => {
9
+ const initial = ["test", "test1", "test2"];
10
+
11
+ window.localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(initial));
12
+ const Searches = new RecentSearches();
13
+
14
+ expect(Searches.get()).toEqual(initial);
15
+ });
16
+
17
+ it("ignores exact duplicate additions", () => {
18
+ const Searches = new RecentSearches();
19
+
20
+ const item = "test";
21
+
22
+ Searches.add(item);
23
+ Searches.add(item);
24
+
25
+ expect(Searches.get().length).toEqual(1);
26
+ });
27
+
28
+ it("ignores duplicate additions with extraneous white space", () => {
29
+ const Searches = new RecentSearches();
30
+
31
+ const item1 = "test";
32
+ const item2 = " test ";
33
+
34
+ Searches.add(item1);
35
+ Searches.add(item2);
36
+
37
+ expect(Searches.get().length).toEqual(1);
38
+ expect(Searches.get()[0]).toEqual(item1);
39
+ });
40
+
41
+ it("prioritizes the last searched item", () => {
42
+ const Searches = new RecentSearches();
43
+
44
+ const item1 = "test1";
45
+ const item2 = "test2";
46
+
47
+ Searches.add(item1);
48
+ Searches.add(item2);
49
+
50
+ expect(Searches.get().length).toEqual(2);
51
+
52
+ expect(Searches.get()[0]).toEqual(item2);
53
+ expect(Searches.get()[1]).toEqual(item1);
54
+
55
+ Searches.add(item1);
56
+
57
+ expect(Searches.get().length).toEqual(2);
58
+ expect(Searches.get()[0]).toEqual(item1);
59
+ expect(Searches.get()[1]).toEqual(item2);
60
+ });
61
+
62
+ it("will not exceed the limit", () => {
63
+ const Searches = new RecentSearches();
64
+
65
+ Array.apply(null, Array(LIMIT + 1)).forEach((_, i) => {
66
+ Searches.add(i.toString());
67
+ });
68
+
69
+ expect(Searches.get().length).toEqual(LIMIT);
70
+ });
71
+
72
+ it("doesn't add a bogus value", () => {
73
+ const Searches = new RecentSearches();
74
+
75
+ [null, "", " ", " ", 5].forEach((v) => Searches.add(v));
76
+
77
+ expect(Searches.get().length).toEqual(0);
78
+ });
79
+ });
@@ -1,6 +1,6 @@
1
- const RECENT_SEARCHES = "dx-sidebar-recent-searches";
1
+ export const LOCAL_STORAGE_KEY = "dx-sidebar-recent-searches";
2
2
 
3
- const LIMIT = 5;
3
+ export const LIMIT = 5;
4
4
 
5
5
  export class RecentSearches {
6
6
  items: string[] = [];
@@ -10,15 +10,19 @@ export class RecentSearches {
10
10
  }
11
11
 
12
12
  get() {
13
- return this.items.map((item) => ({ id: item, label: item }));
13
+ return this.items;
14
14
  }
15
15
 
16
16
  add(item: string | undefined) {
17
- if (!item || this._hasDuplicateRecentSearches(item)) {
17
+ if (!item || typeof item !== "string") {
18
18
  return;
19
19
  }
20
- this._prepend(item);
21
- this._removeDuplicates(item);
20
+ const normalized = item.trim();
21
+ if (normalized === "") {
22
+ return;
23
+ }
24
+ this._prepend(normalized);
25
+ this._removeDuplicates(normalized);
22
26
  this._cutOffExcess();
23
27
  this._addToStorage();
24
28
  }
@@ -26,7 +30,7 @@ export class RecentSearches {
26
30
  // private
27
31
  _init() {
28
32
  this.items = JSON.parse(
29
- window.localStorage.getItem(RECENT_SEARCHES) || "[]"
33
+ window.localStorage.getItem(LOCAL_STORAGE_KEY) || "[]"
30
34
  );
31
35
  }
32
36
 
@@ -46,17 +50,8 @@ export class RecentSearches {
46
50
 
47
51
  _addToStorage() {
48
52
  window.localStorage.setItem(
49
- RECENT_SEARCHES,
53
+ LOCAL_STORAGE_KEY,
50
54
  JSON.stringify(this.items)
51
55
  );
52
56
  }
53
-
54
- _hasDuplicateRecentSearches(searchItem: string) {
55
- return (
56
- this.items.filter(
57
- (item: string) =>
58
- item.toLowerCase() === searchItem.toLowerCase()
59
- ).length > 0
60
- );
61
- }
62
57
  }
@@ -0,0 +1,5 @@
1
+ const escapeRegExp = (text: string) =>
2
+ text.replace(/[-[\]{}()*+?.,\\^$|]/g, "\\$&");
3
+
4
+ export const createSearchRegExp = (searchTerm: string): RegExp =>
5
+ new RegExp(`(?:${escapeRegExp(searchTerm)})(?![^<>]*>)`, "gi");
@@ -1,18 +1,25 @@
1
1
  import { createElement, LightningElement } from "lwc";
2
2
 
3
- export const createRenderComponent = (
4
- tag: string,
5
- LWC: new () => LightningElement
6
- ) => (properties = {}) => {
7
- const component = createElement(tag, {
8
- is: LWC
9
- });
10
-
11
- Object.assign(component, properties);
12
- document.body.appendChild(component);
13
- return component;
3
+ export const renderLightningElement = (
4
+ element: LightningElement,
5
+ properties = {}
6
+ ) => {
7
+ Object.assign(element, properties);
8
+ document.body.appendChild(element as unknown as Node);
9
+ return element;
14
10
  };
15
11
 
12
+ export const createRenderComponent =
13
+ (tag: string, LWC: new () => LightningElement) =>
14
+ (properties = {}) => {
15
+ const component = createElement(tag, {
16
+ is: LWC
17
+ });
18
+
19
+ renderLightningElement(component, properties);
20
+ return component;
21
+ };
22
+
16
23
  export const mockSlottedElement = <T extends HTMLElement>(
17
24
  element: any,
18
25
  elementType = "button",