@salesforcedevs/arch-components 1.20.17-alpha2 → 1.20.17-alpha4

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 (77) hide show
  1. package/package.json +1 -1
  2. package/src/modules/common/context/context.ts +14 -14
  3. package/src/modules/common/effectAdapter/__tests__/effectAdapter.test.ts +4 -4
  4. package/src/modules/common/effectAdapter/effectAdapter.ts +13 -7
  5. package/src/modules/common/reflectedElement/__tests__/reflectedElement.test.ts +5 -5
  6. package/src/modules/common/reflectedElement/reflectedElement.ts +1 -1
  7. package/src/modules/common/slot/__tests__/slot.test.ts +12 -12
  8. package/src/modules/common/slot/slot.ts +4 -3
  9. package/src/modules/sa/coverage/coverage.ts +14 -18
  10. package/src/modules/sa/coverage/types.d.ts +12 -12
  11. package/src/modules/sa/explorer/explorer.ts +25 -25
  12. package/src/modules/sa/gallery/gallery.ts +11 -11
  13. package/src/modules/shared/a11y/a11y.ts +5 -5
  14. package/src/modules/shared/color/color.ts +13 -13
  15. package/src/modules/shared/fetch/fetch.ts +6 -6
  16. package/src/modules/shared/helpers/helpers.ts +6 -6
  17. package/src/modules/shared/i18n/i18n.ts +1 -1
  18. package/src/modules/shared/labels/__tests__/helpers.test.ts +3 -3
  19. package/src/modules/shared/labels/__tests__/pointHelpers.test.ts +3 -3
  20. package/src/modules/shared/labels/__tests__/timeHelpers.test.ts +8 -8
  21. package/src/modules/shared/labels/helpers.ts +4 -4
  22. package/src/modules/shared/labels/pointHelpers.ts +2 -2
  23. package/src/modules/shared/labels/timeHelpers.ts +3 -3
  24. package/src/modules/shared/menu/menu.ts +22 -22
  25. package/src/modules/shared/polling-request.ts +2 -2
  26. package/src/modules/shared/testutils.ts +4 -4
  27. package/src/modules/shared/useEffectAttr.ts +5 -5
  28. package/src/modules/tds/appLauncher/__tests__/appLauncher.test.ts +8 -8
  29. package/src/modules/tds/appLauncher/appLauncher.ts +6 -6
  30. package/src/modules/tds/avatar/__tests__/avatar.test.ts +1 -1
  31. package/src/modules/tds/button/__tests__/button.test.ts +5 -5
  32. package/src/modules/tds/buttonIcon/__tests__/buttonIcon.test.ts +1 -1
  33. package/src/modules/tds/buttonLink/__tests__/buttonLink.test.ts +1 -1
  34. package/src/modules/tds/childSummary/childSummary.ts +2 -2
  35. package/src/modules/tds/contentChildListItem/__tests__/contentChildListItem.test.ts +2 -2
  36. package/src/modules/tds/contentIcon/contentIcon.ts +1 -1
  37. package/src/modules/tds/footerLinks/__tests__/footerLinks.test.ts +2 -2
  38. package/src/modules/tds/headerAvatar/__tests__/headerAvatar.test.ts +4 -4
  39. package/src/modules/tds/headerAvatar/headerAvatar.ts +5 -5
  40. package/src/modules/tds/headerHelpButton/__tests__/headerHelpButton.test.ts +2 -2
  41. package/src/modules/tds/heading/__tests__/heading.test.ts +7 -7
  42. package/src/modules/tds/icon/icon.ts +11 -11
  43. package/src/modules/tds/radio/__tests__/radio.test.ts +1 -1
  44. package/src/modules/tds/search/__tests__/search.test.ts +17 -17
  45. package/src/modules/tds/search/lib/__tests__/listbox.test.ts +16 -16
  46. package/src/modules/tds/search/lib/listbox.ts +16 -16
  47. package/src/modules/tds/search/search.ts +10 -10
  48. package/src/modules/tds/select/__tests__/select.test.ts +1 -1
  49. package/src/modules/tds/summary/__tests__/summary.test.ts +16 -16
  50. package/src/modules/tds/summary/summary.ts +2 -2
  51. package/src/modules/tds/themeProvider/themeProvider.ts +4 -4
  52. package/src/modules/th/favoriteButton/__tests__/favoriteButton.test.ts +1 -1
  53. package/src/modules/th/favoriteButton/mocks/index.ts +2 -2
  54. package/src/modules/th/search/__tests__/search.test.ts +2 -2
  55. package/src/modules/th/search/mocks/index.ts +1 -1
  56. package/src/modules/th/search/search.ts +21 -21
  57. package/src/modules/tm/card/card.ts +15 -15
  58. package/src/modules/tm/content/content.ts +11 -11
  59. package/src/modules/tm/endCapA/__tests__/endCapA.test.ts +2 -2
  60. package/src/modules/tm/eventsA/eventsA.ts +1 -1
  61. package/src/modules/tm/faqA/faqA.ts +4 -4
  62. package/src/modules/tm/featureGridA/__tests__/featureGridA.test.ts +2 -2
  63. package/src/modules/tm/footnote/footnote.ts +1 -1
  64. package/src/modules/tm/heroA/__tests__/heroA.test.ts +2 -2
  65. package/src/modules/tm/heroA/heroA.ts +3 -3
  66. package/src/modules/tm/promoA/__tests__/promoA.test.ts +3 -3
  67. package/src/modules/tm/promoA/promoA.ts +4 -4
  68. package/src/modules/tm/sectionA/sectionA.ts +1 -1
  69. package/src/modules/tm/utils/utils.ts +5 -5
  70. package/src/modules/tm/youtube/youtube.ts +2 -2
  71. package/src/modules/ui/focusTrap/focusTrap.ts +7 -7
  72. package/src/modules/ui/focusVisible/focusVisible.ts +7 -7
  73. package/src/modules/th/tbid/__tests__/__snapshots__/tbid.test.ts.snap +0 -3
  74. package/src/modules/th/tbid/__tests__/tbid.test.ts +0 -242
  75. package/src/modules/th/tbid/tbid.html +0 -1
  76. package/src/modules/th/tbid/tbid.stories.mdx +0 -25
  77. package/src/modules/th/tbid/tbid.ts +0 -215
@@ -1,13 +1,13 @@
1
1
  export function waitForPageSettled() {
2
2
  return new Promise<void>((resolve) => {
3
3
  let prevH: number = 0;
4
- let prevY = window.scrollY;
4
+ const prevY = window.scrollY;
5
5
  function check() {
6
- let nextH = window.innerHeight + document.body.scrollHeight;
7
- let nextY = window.scrollY;
8
- let settled = nextH === prevH;
6
+ const nextH = window.innerHeight + document.body.scrollHeight;
7
+ const nextY = window.scrollY;
8
+ const settled = nextH === prevH;
9
9
  if (settled) {
10
- if (nextY === prevY) resolve();
10
+ if (nextY === prevY) {resolve();}
11
11
  return;
12
12
  }
13
13
  prevH = nextH;
@@ -17,8 +17,8 @@ export default class extends LightningElement {
17
17
  if (!this.didSetSize) {
18
18
  this.didSetSize = true;
19
19
  waitForPageSettled().then(() => {
20
- let w = this.template.host.offsetWidth;
21
- let ratio = 0.5625;
20
+ const w = this.template.host.offsetWidth;
21
+ const ratio = 0.5625;
22
22
  this.height = w * ratio;
23
23
  this.width = w;
24
24
  });
@@ -26,8 +26,8 @@ export default class extends LightningElement {
26
26
  }
27
27
 
28
28
  renderedCallback() {
29
- if (this.init) return;
30
- else this.init = true;
29
+ if (this.init) {return;}
30
+ this.init = true;
31
31
 
32
32
  this.$start = this.template.querySelector(
33
33
  `[data-id="start"]`
@@ -52,7 +52,7 @@ export default class extends LightningElement {
52
52
  this.removeEventListener('focusin', this.onFocusIn);
53
53
  this.removeEventListener('focusout', this.onFocusOut);
54
54
  if (this.$activeElement && this.$activeElement instanceof HTMLElement)
55
- this.$activeElement.focus();
55
+ {this.$activeElement.focus();}
56
56
  }
57
57
 
58
58
  private focusFirstElement = () => {
@@ -79,14 +79,14 @@ export default class extends LightningElement {
79
79
 
80
80
  private getFocusableElements(): HTMLElement[] {
81
81
  // @ts-ignore
82
- let children = this.template.querySelector('slot').assignedElements();
82
+ const children = this.template.querySelector('slot').assignedElements();
83
83
  // @ts-ignore
84
84
  return queryShadowRoot({ children }, isHidden, isFocusable);
85
85
  }
86
86
 
87
87
  private trapFocus(trapToEnd?: boolean) {
88
- if (this.inactive) return;
89
- let focusableElements = this.getFocusableElements();
88
+ if (this.inactive) {return;}
89
+ const focusableElements = this.getFocusableElements();
90
90
  if (focusableElements.length > 0) {
91
91
  if (trapToEnd) {
92
92
  focusableElements[focusableElements.length - 1].focus();
@@ -99,6 +99,6 @@ export default class extends LightningElement {
99
99
 
100
100
  function getActiveElement(element: Element | null): Element | null {
101
101
  if (element && element.shadowRoot)
102
- return getActiveElement(element.shadowRoot.activeElement);
102
+ {return getActiveElement(element.shadowRoot.activeElement);}
103
103
  return element;
104
104
  }
@@ -23,7 +23,7 @@ export default class extends LightningElement {
23
23
  }
24
24
 
25
25
  private onChange = () => {
26
- for (let node of Array.from(this.template.host.children)) {
26
+ for (const node of Array.from(this.template.host.children)) {
27
27
  node.setAttribute('data-focus-visible', String(focusVisible));
28
28
  }
29
29
  };
@@ -34,13 +34,13 @@ document.addEventListener('mousemove', onMouse, { passive: true });
34
34
  document.addEventListener('keydown', onKeyboard, { passive: true });
35
35
 
36
36
  function onMouse(event: MouseEvent) {
37
- if (!focusVisible) return;
38
- else focusVisible = false;
39
- for (let handler of handlers) handler();
37
+ if (!focusVisible) {return;}
38
+ focusVisible = false;
39
+ for (const handler of handlers) {handler();}
40
40
  }
41
41
 
42
42
  function onKeyboard(event: KeyboardEvent) {
43
- if (focusVisible) return;
44
- else focusVisible = true;
45
- for (let handler of handlers) handler();
43
+ if (focusVisible) {return;}
44
+ focusVisible = true;
45
+ for (const handler of handlers) {handler();}
46
46
  }
@@ -1,3 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`undefined: toMatchHTMLSnapshot 1`] = `"<head><meta name="salesforce-cache-max-age" content="0"><meta name="salesforce-brand" content="trailhead"><meta name="salesforce-community" content="/tbid-community-uri"><meta name="salesforce-use-min-js" content="false"><meta name="salesforce-init-handler" content="__tbid_init"><meta name="salesforce-login-handler" content="__tbid_login"><meta name="salesforce-logout-handler" content="__tbid_logout"><meta name="salesforce-mode" content="authprovider"><meta name="salesforce-redirect-uri" content="/tbid-redirect-uri"><meta name="salesforce-authprovider-login" content="/tbid-auth-provider-login-path"><meta name="salesforce-authprovider-signup" content="/tbid-auth-provider-signup-path"><script src="/tbid-community-uri/resource/authProviderEmbeddedLogin_v1_3"></script></head>"`;
@@ -1,242 +0,0 @@
1
- import fetchMock from 'jest-fetch-mock';
2
-
3
- import { html, renderIntoBody, nextTick } from 'shared/testutils';
4
-
5
- import Tbid, {
6
- EVENT_LOGIN,
7
- EVENT_LOGOUT,
8
- TRAILHEAD_EVENT_LOGIN,
9
- TRAILHEAD_EVENT_LOGOUT,
10
- TRAILHEAD_EVENT_SIGNUP,
11
- TBID_EVENT_INIT,
12
- TBID_EVENT_LOGIN,
13
- TBID_EVENT_LOGOUT,
14
- TBID_INIT,
15
- TBID_LOGIN,
16
- TBID_LOGOUT,
17
- TBID_LOGOUT_PATH,
18
- Lock,
19
- LOCK_KEY,
20
- LOCK_TIMEOUT
21
- } from '../tbid';
22
-
23
- customElements.define('th-tbid', Tbid.CustomElementConstructor);
24
-
25
- const render = ({
26
- authenticated = 'false',
27
- loginTried = 'false'
28
- }: { authenticated?: string; loginTried?: string } = {}) =>
29
- renderIntoBody(
30
- html`
31
- <th-tbid
32
- authenticated=${authenticated}
33
- csrf-token="token"
34
- login-redirect-path="/login-redirect-path"
35
- login-status-path="/login-status-path"
36
- login-tried=${loginTried}
37
- logout-redirect-path="/logout-redirect-path"
38
- tbid-auth-provider-login-path="/tbid-auth-provider-login-path"
39
- tbid-auth-provider-signup-path="/tbid-auth-provider-signup-path"
40
- tbid-community-uri="/tbid-community-uri"
41
- tbid-redirect-uri="/tbid-redirect-uri"
42
- ></th-tbid>
43
- `
44
- ) as unknown as Tbid;
45
-
46
- let location = {};
47
-
48
- Object.defineProperty(window, 'location', {
49
- get: () => location
50
- });
51
-
52
- beforeEach(() => {
53
- window.location.href = '/';
54
- window.sessionStorage.removeItem(LOCK_KEY);
55
- });
56
-
57
- describe('th-tbid', () => {
58
- afterEach(() => {
59
- document.head.querySelectorAll('meta').forEach((n) => n.remove());
60
- });
61
- it('sets the correct meta tags', () => {
62
- render();
63
- expect(document.head.outerHTML).toMatchHTMLSnapshot();
64
- });
65
- it('sets the window globals', () => {
66
- render();
67
- // @ts-ignore
68
- expect(window[TBID_INIT]).toBeInstanceOf(Function);
69
- // @ts-ignore
70
- expect(window[TBID_LOGIN]).toBeInstanceOf(Function);
71
- // @ts-ignore
72
- expect(window[TBID_LOGOUT]).toBeInstanceOf(Function);
73
- });
74
- it(`handles the ${TRAILHEAD_EVENT_LOGIN} event`, () => {
75
- render();
76
- let fn = jest.fn();
77
- Object.defineProperty(window, 'SFIDWidget', {
78
- value: { login: fn },
79
- writable: true
80
- });
81
- document.dispatchEvent(new CustomEvent(TRAILHEAD_EVENT_LOGIN));
82
- expect(fn).toHaveBeenCalled();
83
- });
84
- it(`handles the ${TRAILHEAD_EVENT_LOGOUT} event`, async () => {
85
- render();
86
- let fn = jest.fn();
87
- Object.defineProperty(window, 'SFIDWidget', {
88
- value: { logout: fn },
89
- writable: true
90
- });
91
- document.dispatchEvent(new CustomEvent(TRAILHEAD_EVENT_LOGOUT));
92
- let iframe = document.body.querySelector(
93
- `iframe[src="/tbid-community-uri${TBID_LOGOUT_PATH}"]`
94
- );
95
- expect(iframe).toBeInTheDocument();
96
- iframe!.dispatchEvent(new CustomEvent('load'));
97
- await nextTick();
98
- expect(fn).toHaveBeenCalled();
99
- });
100
- it(`handles the ${TRAILHEAD_EVENT_SIGNUP}`, () => {
101
- render();
102
- let fn = jest.fn();
103
- Object.defineProperty(window, 'SFIDWidget', {
104
- value: { signup: fn },
105
- writable: true
106
- });
107
- document.dispatchEvent(new CustomEvent(TRAILHEAD_EVENT_SIGNUP));
108
- expect(fn).toHaveBeenCalled();
109
- });
110
- describe('onLogin', () => {
111
- it('redirects if user is not_logged_in & login-tried != true', async () => {
112
- fetchMock.doMockOnceIf(
113
- (r) => r.url === '/login-status-path',
114
- JSON.stringify({ user: 'not_logged_in' })
115
- );
116
- render();
117
- // @ts-ignore
118
- await window[TBID_LOGIN]();
119
- expect(window.location.href).toEqual('/login-redirect-path');
120
- });
121
- it('retries if there is a lock', async () => {
122
- jest.useFakeTimers();
123
- fetchMock.doMockIf(
124
- (r) => r.url === '/login-status-path',
125
- JSON.stringify({ user: 'not_logged_in' })
126
- );
127
- let element = render();
128
- let onLogin = jest.fn();
129
- element.addEventListener(TBID_EVENT_LOGIN, onLogin);
130
- // A: No lock
131
- // @ts-ignore
132
- await window[TBID_LOGIN]();
133
- expect(onLogin).toHaveBeenCalledTimes(1);
134
- expect(window.location.href).toEqual('/login-redirect-path');
135
- window.location.href = '/';
136
- // B: Lock
137
- // @ts-ignore
138
- await window[TBID_LOGIN]();
139
- expect(onLogin).toHaveBeenCalledTimes(2);
140
- expect(window.location.href).toEqual('/');
141
- // C: Lock expired
142
- let now = Date.now();
143
- let nowMock = jest
144
- .spyOn(Date, 'now')
145
- .mockImplementation(() => now + LOCK_TIMEOUT);
146
- jest.runAllTimers();
147
- jest.useRealTimers();
148
- await nextTick();
149
- expect(onLogin).toHaveBeenCalledTimes(3);
150
- nowMock.mockRestore();
151
- fetchMock.resetMocks();
152
- });
153
- it('calls onInit if user is logged_in and authenticated', async () => {
154
- fetchMock.doMockOnceIf(
155
- (r) => r.url === '/login-status-path',
156
- JSON.stringify({ user: 'logged_in' })
157
- );
158
- let element = render({ authenticated: 'true' });
159
- let onInit = jest.fn();
160
- element.addEventListener(TBID_EVENT_INIT, onInit);
161
- // @ts-ignore
162
- await window[TBID_LOGIN]();
163
- expect(onInit).toHaveBeenCalled();
164
- expect(window.sessionStorage.getItem(LOCK_KEY)).toBeNull();
165
- });
166
- it('calls onInit if user is not_logged_in and login-tried', async () => {
167
- fetchMock.doMockOnceIf(
168
- (r) => r.url === '/login-status-path',
169
- JSON.stringify({ user: 'not_logged_in' })
170
- );
171
- let element = render({ loginTried: 'true' });
172
- let onInit = jest.fn();
173
- element.addEventListener(TBID_EVENT_INIT, onInit);
174
- // @ts-ignore
175
- await window[TBID_LOGIN]();
176
- expect(onInit).toHaveBeenCalled();
177
- expect(window.sessionStorage.getItem(LOCK_KEY)).toBeNull();
178
- });
179
- it('dispatches login', () => {
180
- fetchMock.doMockOnceIf(
181
- (r) => r.url === '/login-status-path',
182
- JSON.stringify({ user: 'not_logged_in' })
183
- );
184
- let element = render();
185
- let fn = jest.fn();
186
- element.addEventListener(EVENT_LOGIN, fn);
187
- // @ts-ignore
188
- window[TBID_LOGIN]();
189
- expect(fn).toHaveBeenCalled();
190
- });
191
- });
192
- describe('onLogout', () => {
193
- it('calls SFIDWidget.init()', () => {
194
- render();
195
- let init = jest.fn();
196
- Object.defineProperty(window, 'SFIDWidget', {
197
- value: { init },
198
- writable: true
199
- });
200
- // @ts-ignore
201
- window[TBID_LOGOUT]();
202
- expect(init).toHaveBeenCalled();
203
- });
204
- it('redirects', () => {
205
- render();
206
- // @ts-ignore
207
- window[TBID_LOGOUT]();
208
- expect(window.location.href).toEqual('/logout-redirect-path');
209
- });
210
- it('dispatches logout', () => {
211
- let element = render();
212
- let fn = jest.fn();
213
- element.addEventListener(EVENT_LOGOUT, fn);
214
- // @ts-ignore
215
- window[TBID_LOGOUT]();
216
- expect(fn).toHaveBeenCalled();
217
- });
218
- });
219
- describe('Lock', () => {
220
- afterEach(() => {
221
- window.sessionStorage.removeItem('tbid');
222
- });
223
- it('acquire', async () => {
224
- let now = Date.now();
225
- let lock = new Lock('tbid', 1000);
226
- expect(lock.aquire()).toBe(true);
227
- expect(lock.aquire()).toBe(false);
228
- let mock = jest
229
- .spyOn(Date, 'now')
230
- .mockImplementation(() => now + 2000);
231
- expect(lock.aquire()).toBe(true);
232
- mock.mockRestore();
233
- });
234
- it('release', async () => {
235
- let lock = new Lock('tbid', 1000);
236
- expect(lock.aquire()).toBe(true);
237
- expect(lock.aquire()).toBe(false);
238
- lock.release();
239
- expect(lock.aquire()).toBe(true);
240
- });
241
- });
242
- });
@@ -1 +0,0 @@
1
- <template></template>
@@ -1,25 +0,0 @@
1
- import { Meta } from "@storybook/addon-docs/blocks";
2
-
3
- <Meta title="th/th-tbid" />
4
-
5
- # Usage
6
-
7
- ```html
8
- <th-tbid
9
- authenticated="false"
10
- csrf-token="token"
11
- login-redirect-path="/login-redirect-path"
12
- login-status-path="/login-status-path"
13
- login-tried="false"
14
- logout-redirect-path="/logout-path"
15
- tbid-auth-provider-login-path="/tbid-auth-provider-login-path"
16
- tbid-auth-provider-signup-path="/tbid-auth-provider-signup-path"
17
- tbid-community-uri="/tbid-community-uri"
18
- tbid-redirect-uri="/tbid-redirect-uri"
19
- ></th-tbid>
20
-
21
- <script
22
- src="https://trailhead.salesforce.com/ui/modules/th-tbid.js"
23
- type="module"
24
- ></script>
25
- ```
@@ -1,215 +0,0 @@
1
- import { api, LightningElement } from 'lwc';
2
-
3
- import { getJSON, csrfHeader } from 'shared/fetch';
4
-
5
- export const EVENT_LOGIN = 'login';
6
- export const EVENT_LOGOUT = 'logout';
7
-
8
- export const TRAILHEAD_EVENT_LOGIN = 'trailhead_login';
9
- export const TRAILHEAD_EVENT_LOGOUT = 'trailhead_logout';
10
- export const TRAILHEAD_EVENT_SIGNUP = 'trailhead_signup';
11
-
12
- export const TBID_EVENT_INIT = 'tbid_will_init';
13
- export const TBID_EVENT_LOGIN = 'tbid_will_login';
14
- export const TBID_EVENT_LOGOUT = 'tbid_will_logout';
15
-
16
- export const TBID_INIT = '__tbid_init';
17
- export const TBID_LOGIN = '__tbid_login';
18
- export const TBID_LOGOUT = '__tbid_logout';
19
-
20
- export const TBID_SCRIPT_PATH = '/resource/authProviderEmbeddedLogin_v1_3';
21
- export const TBID_LOGOUT_PATH = '/services/auth/rp/oidc/logout';
22
-
23
- export const LOCK_KEY = 'tbid.tabAuthLock';
24
- export const LOCK_TIMEOUT = 5000;
25
-
26
- declare var SFIDWidget: {
27
- init: () => void;
28
- login: () => void;
29
- logout: () => void;
30
- signup: () => void;
31
- };
32
-
33
- export default class extends LightningElement {
34
- @api authenticated: string | null = null;
35
-
36
- @api csrfToken: string = '';
37
-
38
- @api loginRedirectPath: string = null!;
39
- @api loginStatusPath: string = null!;
40
- @api loginTried: string | null = null;
41
- @api logoutRedirectPath: string = null!;
42
-
43
- @api tbidAuthProviderLoginPath: string = null!;
44
- @api tbidAuthProviderSignupPath: string = null!;
45
- @api tbidCommunityUri: string = null!;
46
- @api tbidRedirectUri: string = null!;
47
-
48
- private loadSFID: Promise<unknown> = null!;
49
-
50
- private get scriptSrc() {
51
- return `${this.tbidCommunityUri}${TBID_SCRIPT_PATH}`;
52
- }
53
-
54
- private get logoutIframeSrc() {
55
- return `${this.tbidCommunityUri}${TBID_LOGOUT_PATH}`;
56
- }
57
-
58
- connectedCallback() {
59
- this.appendMetaTag('salesforce-cache-max-age', '0');
60
- this.appendMetaTag('salesforce-brand', 'trailhead');
61
- this.appendMetaTag('salesforce-community', this.tbidCommunityUri);
62
- this.appendMetaTag('salesforce-use-min-js', 'false');
63
-
64
- this.appendMetaTag('salesforce-init-handler', TBID_INIT);
65
- this.appendMetaTag('salesforce-login-handler', TBID_LOGIN);
66
- this.appendMetaTag('salesforce-logout-handler', TBID_LOGOUT);
67
-
68
- this.appendMetaTag('salesforce-mode', 'authprovider');
69
- this.appendMetaTag('salesforce-redirect-uri', this.tbidRedirectUri);
70
-
71
- this.appendMetaTag(
72
- 'salesforce-authprovider-login',
73
- this.tbidAuthProviderLoginPath
74
- );
75
- this.appendMetaTag(
76
- 'salesforce-authprovider-signup',
77
- this.tbidAuthProviderSignupPath
78
- );
79
-
80
- Object.defineProperty(window, TBID_INIT, {
81
- value: () => this.onInit(),
82
- writable: process.env.NODE_ENV === 'test'
83
- });
84
- Object.defineProperty(window, TBID_LOGIN, {
85
- value: () => this.onLogin(),
86
- writable: process.env.NODE_ENV === 'test'
87
- });
88
- Object.defineProperty(window, TBID_LOGOUT, {
89
- value: () => this.onLogout(),
90
- writable: process.env.NODE_ENV === 'test'
91
- });
92
-
93
- this.loadSFID = loadSFID(this.scriptSrc).catch((error) => {
94
- this.dispatchEvent(
95
- new CustomEvent('error', {
96
- detail: { error }
97
- })
98
- );
99
- });
100
-
101
- document.addEventListener(TRAILHEAD_EVENT_LOGIN, this);
102
- document.addEventListener(TRAILHEAD_EVENT_LOGOUT, this);
103
- document.addEventListener(TRAILHEAD_EVENT_SIGNUP, this);
104
- }
105
-
106
- disconnectedCallback() {
107
- document.removeEventListener(TRAILHEAD_EVENT_LOGIN, this);
108
- document.removeEventListener(TRAILHEAD_EVENT_LOGOUT, this);
109
- document.removeEventListener(TRAILHEAD_EVENT_SIGNUP, this);
110
- }
111
-
112
- handleEvent(e: Event) {
113
- switch (e.type) {
114
- case TRAILHEAD_EVENT_LOGIN:
115
- SFIDWidget.login();
116
- break;
117
- case TRAILHEAD_EVENT_LOGOUT:
118
- loadIframe(this.logoutIframeSrc).then(() => {
119
- SFIDWidget.logout();
120
- });
121
- break;
122
- case TRAILHEAD_EVENT_SIGNUP:
123
- SFIDWidget.signup();
124
- break;
125
- }
126
- }
127
-
128
- private appendMetaTag(name: string, content: string) {
129
- let tag = document.createElement('meta');
130
- tag.name = name;
131
- tag.content = content;
132
- document.head.appendChild(tag);
133
- }
134
-
135
- private onInit() {
136
- this.dispatchEvent(new CustomEvent(TBID_EVENT_INIT));
137
- }
138
-
139
- private async onLogin() {
140
- this.dispatchEvent(new CustomEvent(TBID_EVENT_LOGIN));
141
- this.dispatchEvent(new CustomEvent(EVENT_LOGIN));
142
- let lock = new Lock(LOCK_KEY, LOCK_TIMEOUT);
143
- let { user } = await getJSON<{ user: string }>(this.loginStatusPath, {
144
- headers: csrfHeader(this.csrfToken)
145
- });
146
- let newSession =
147
- (user === 'logged_in' && this.authenticated !== 'true') ||
148
- (user === 'not_logged_in' && this.loginTried !== 'true');
149
- if (newSession) {
150
- if (lock.aquire()) window.location.href = this.loginRedirectPath;
151
- else setTimeout(this.onLogin.bind(this), LOCK_TIMEOUT);
152
- } else {
153
- lock.release();
154
- this.onInit();
155
- }
156
- }
157
-
158
- private onLogout() {
159
- this.dispatchEvent(new CustomEvent(TBID_EVENT_LOGOUT));
160
- this.dispatchEvent(new CustomEvent(EVENT_LOGOUT));
161
- SFIDWidget.init();
162
- window.location.href = this.logoutRedirectPath;
163
- }
164
- }
165
-
166
- export class Lock {
167
- constructor(private key: string, private timeout: number) {}
168
-
169
- aquire() {
170
- if (this.locked) return false;
171
- sessionStorage.setItem(this.key, String(Date.now() + this.timeout));
172
- return true;
173
- }
174
-
175
- release() {
176
- sessionStorage.removeItem(this.key);
177
- }
178
-
179
- private get existingLock() {
180
- let storageValue = sessionStorage.getItem(this.key) || '';
181
- let value = parseInt(storageValue, 10);
182
- return Number.isNaN(value) ? 0 : value;
183
- }
184
-
185
- private get locked() {
186
- return this.existingLock > Date.now();
187
- }
188
- }
189
-
190
- function loadSFID(src: string) {
191
- let load = new Promise<void>((resolve, reject) => {
192
- let script = document.createElement('script');
193
- script.onload = () => resolve(undefined);
194
- script.onerror = () => reject(new Error('TH_TBID_SFID_LOAD'));
195
- script.async = false;
196
- script.src = src;
197
- document.head.appendChild(script);
198
- });
199
- let timeout = new Promise((_, reject) =>
200
- setTimeout(reject, 5000, new Error('TH_TBID_SFID_TIMEOUT'))
201
- );
202
- return Promise.race([load, timeout]);
203
- }
204
-
205
- function loadIframe(url: string) {
206
- return new Promise((resolve, reject) => {
207
- const iframe = document.createElement('iframe');
208
- iframe.setAttribute('sandbox', 'allow-scripts');
209
- iframe.style.display = 'none';
210
- iframe.addEventListener('load', resolve, { once: true });
211
- iframe.addEventListener('error', reject, { once: true });
212
- iframe.src = url;
213
- document.body.appendChild(iframe);
214
- });
215
- }