@servicetitan/notifications 26.0.0 → 26.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2 @@
1
+ import '@testing-library/jest-dom';
2
+ //# sourceMappingURL=container.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container.test.d.ts","sourceRoot":"","sources":["../../../src/components/__tests__/container.test.tsx"],"names":[],"mappings":"AAAA,OAAO,2BAA2B,CAAC"}
@@ -0,0 +1,59 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { jsx as _jsx } from "react/jsx-runtime";
11
+ import '@testing-library/jest-dom';
12
+ import { render, waitFor, within } from '@testing-library/react';
13
+ import { Container } from '../container';
14
+ describe('[notifications] Container', () => {
15
+ beforeEach(() => {
16
+ var _a;
17
+ (_a = document.getElementById('servicetitan-notifications')) === null || _a === void 0 ? void 0 : _a.remove();
18
+ });
19
+ const subject = (children) => {
20
+ return render(_jsx(Container, { children: children }));
21
+ };
22
+ test('renders #servicetitan-notifications.initialized > .ToastGroup', () => __awaiter(void 0, void 0, void 0, function* () {
23
+ subject();
24
+ yield waitFor(() => expect(document.querySelectorAll('#servicetitan-notifications.initialized > .ToastGroup')).toHaveLength(1));
25
+ }));
26
+ test('renders children within .ToastGroup', () => __awaiter(void 0, void 0, void 0, function* () {
27
+ subject(_jsx("button", { children: "Foo" }));
28
+ yield waitFor(() => {
29
+ expect(within(document.querySelector('#servicetitan-notifications.initialized > .ToastGroup')).getByRole('button', { name: 'Foo' })).toBeInTheDocument();
30
+ });
31
+ }));
32
+ describe('when #servicetitan-notifications already exists', () => {
33
+ let container;
34
+ beforeEach(() => {
35
+ container = document.createElement('div');
36
+ container.setAttribute('id', 'servicetitan-notifications');
37
+ document.body.appendChild(container);
38
+ });
39
+ test('creates .ToastGroup within existing container', () => __awaiter(void 0, void 0, void 0, function* () {
40
+ subject();
41
+ yield waitFor(() => {
42
+ expect(container.querySelectorAll('.ToastGroup')).toHaveLength(1);
43
+ });
44
+ }));
45
+ describe('when .ToastGroup already exists', () => {
46
+ let toastGroup;
47
+ beforeEach(() => {
48
+ toastGroup = document.createElement('div');
49
+ toastGroup.classList.add('ToastGroup');
50
+ container.appendChild(toastGroup);
51
+ });
52
+ test('renders children inside existing ToastGroup', () => {
53
+ subject(_jsx("button", { children: "Baz" }));
54
+ expect(within(toastGroup).getByRole('button', { name: 'Baz' })).toBeInTheDocument();
55
+ });
56
+ });
57
+ });
58
+ });
59
+ //# sourceMappingURL=container.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container.test.js","sourceRoot":"","sources":["../../../src/components/__tests__/container.test.tsx"],"names":[],"mappings":";;;;;;;;;;AAAA,OAAO,2BAA2B,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAGjE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACvC,UAAU,CAAC,GAAG,EAAE;;QACZ,MAAA,QAAQ,CAAC,cAAc,CAAC,4BAA4B,CAAC,0CAAE,MAAM,EAAE,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,CAAC,QAAoB,EAAE,EAAE;QACrC,OAAO,MAAM,CAAC,KAAC,SAAS,cAAE,QAAQ,GAAa,CAAC,CAAC;IACrD,CAAC,CAAC;IAEF,IAAI,CAAC,+DAA+D,EAAE,GAAS,EAAE;QAC7E,OAAO,EAAE,CAAC;QAEV,MAAM,OAAO,CAAC,GAAG,EAAE,CACf,MAAM,CACF,QAAQ,CAAC,gBAAgB,CAAC,uDAAuD,CAAC,CACrF,CAAC,YAAY,CAAC,CAAC,CAAC,CACpB,CAAC;IACN,CAAC,CAAA,CAAC,CAAC;IAEH,IAAI,CAAC,qCAAqC,EAAE,GAAS,EAAE;QACnD,OAAO,CAAC,mCAAoB,CAAC,CAAC;QAE9B,MAAM,OAAO,CAAC,GAAG,EAAE;YACf,MAAM,CACF,MAAM,CACF,QAAQ,CAAC,aAAa,CAAC,uDAAuD,CAAE,CACnF,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CACzC,CAAC,iBAAiB,EAAE,CAAC;QAC1B,CAAC,CAAC,CAAC;IACP,CAAC,CAAA,CAAC,CAAC;IAEH,QAAQ,CAAC,iDAAiD,EAAE,GAAG,EAAE;QAC7D,IAAI,SAAsB,CAAC;QAE3B,UAAU,CAAC,GAAG,EAAE;YACZ,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YAC1C,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,4BAA4B,CAAC,CAAC;YAC3D,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,+CAA+C,EAAE,GAAS,EAAE;YAC7D,OAAO,EAAE,CAAC;YAEV,MAAM,OAAO,CAAC,GAAG,EAAE;gBACf,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACtE,CAAC,CAAC,CAAC;QACP,CAAC,CAAA,CAAC,CAAC;QAEH,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;YAC7C,IAAI,UAAuB,CAAC;YAE5B,UAAU,CAAC,GAAG,EAAE;gBACZ,UAAU,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;gBAC3C,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;gBACvC,SAAS,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;YACtC,CAAC,CAAC,CAAC;YAEH,IAAI,CAAC,6CAA6C,EAAE,GAAG,EAAE;gBACrD,OAAO,CAAC,mCAAoB,CAAC,CAAC;gBAE9B,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC;YACxF,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../src/components/container.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,EAAE,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAMxD,eAAO,MAAM,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAS3C,CAAC"}
1
+ {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../src/components/container.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAY,iBAAiB,EAAuB,MAAM,OAAO,CAAC;AAK7E,eAAO,MAAM,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAwB3C,CAAC"}
@@ -1,12 +1,26 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useState } from 'react';
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
2
  import { Toast } from '@servicetitan/design-system';
3
+ import { Fragment, useEffect, useState } from 'react';
4
+ import { createPortal } from 'react-dom';
4
5
  import { createElement } from '../create-element';
5
6
  export const Container = ({ children }) => {
6
7
  const [container] = useState(() => {
7
8
  var _a;
8
9
  return ((_a = document.getElementById('servicetitan-notifications')) !== null && _a !== void 0 ? _a : document.body.appendChild(createElement('div', { id: 'servicetitan-notifications' })));
9
10
  });
10
- return container ? _jsx(Toast.Group, Object.assign({ portal: container }, { children: children })) : null;
11
+ const [toastGroup, setToastGroup] = useState(() => findToastGroup(container));
12
+ const [foundGroup] = useState(() => !!toastGroup);
13
+ useEffect(() => {
14
+ if (!toastGroup) {
15
+ setToastGroup(findToastGroup(container));
16
+ // This stops old code running in MFE from rendering duplicate Toast.Group
17
+ container.classList.add('initialized');
18
+ }
19
+ }, [container, toastGroup]);
20
+ return (_jsxs(Fragment, { children: [foundGroup ? null : _jsx(Toast.Group, { portal: container }), toastGroup ? createPortal(children, toastGroup) : null] }));
11
21
  };
22
+ function findToastGroup(parent) {
23
+ var _a;
24
+ return (_a = parent.getElementsByClassName('ToastGroup')[0]) !== null && _a !== void 0 ? _a : null;
25
+ }
12
26
  //# sourceMappingURL=container.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/components/container.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAyB,MAAM,OAAO,CAAC;AAExD,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAEpD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,MAAM,CAAC,MAAM,SAAS,GAA0B,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;IAC7D,MAAM,CAAC,SAAS,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE;;QAC9B,OAAO,CACH,MAAA,QAAQ,CAAC,cAAc,CAAC,4BAA4B,CAAC,mCACrD,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,4BAA4B,EAAE,CAAC,CAAC,CACxF,CAAC;IACN,CAAC,CAAC,CAAC;IAEH,OAAO,SAAS,CAAC,CAAC,CAAC,KAAC,KAAK,CAAC,KAAK,kBAAC,MAAM,EAAE,SAAS,gBAAG,QAAQ,IAAe,CAAC,CAAC,CAAC,IAAI,CAAC;AACvF,CAAC,CAAC"}
1
+ {"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/components/container.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AACpD,OAAO,EAAM,QAAQ,EAAqB,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,MAAM,CAAC,MAAM,SAAS,GAA0B,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;IAC7D,MAAM,CAAC,SAAS,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE;;QAC9B,OAAO,CACH,MAAA,QAAQ,CAAC,cAAc,CAAC,4BAA4B,CAAC,mCACrD,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,4BAA4B,EAAE,CAAC,CAAC,CACxF,CAAC;IACN,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC;IAC9E,MAAM,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAElD,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,CAAC,UAAU,EAAE;YACb,aAAa,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC;YACzC,0EAA0E;YAC1E,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;SAC1C;IACL,CAAC,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IAE5B,OAAO,CACH,MAAC,QAAQ,eACJ,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAC,KAAK,CAAC,KAAK,IAAC,MAAM,EAAE,SAAS,GAAI,EACtD,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,IAChD,CACd,CAAC;AACN,CAAC,CAAC;AAEF,SAAS,cAAc,CAAC,MAAmB;;IACvC,OAAO,MAAA,MAAM,CAAC,sBAAsB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,mCAAI,IAAI,CAAC;AAClE,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import { FC, PropsWithChildren } from 'react';
2
2
  import { interfaces } from '@servicetitan/react-ioc';
3
3
  import { NotificationsApi } from '../api/notifications.api';
4
- export interface NotificationsProps extends PropsWithChildren {
4
+ export interface NotificationsProps extends PropsWithChildren<{}> {
5
5
  apiService?: interfaces.Newable<NotificationsApi>;
6
6
  }
7
7
  export declare const Notifications: FC<NotificationsProps>;
@@ -1 +1 @@
1
- {"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../src/components/notifications.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAE9C,OAAO,EAAY,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,EACH,gBAAgB,EAGnB,MAAM,0BAA0B,CAAC;AAelC,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IACzD,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACrD;AAED,eAAO,MAAM,aAAa,EAAE,EAAE,CAAC,kBAAkB,CAWhD,CAAC"}
1
+ {"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../src/components/notifications.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAE9C,OAAO,EAAY,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,EACH,gBAAgB,EAGnB,MAAM,0BAA0B,CAAC;AAelC,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB,CAAC,EAAE,CAAC;IAC7D,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACrD;AAED,eAAO,MAAM,aAAa,EAAE,EAAE,CAAC,kBAAkB,CAWhD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servicetitan/notifications",
3
- "version": "26.0.0",
3
+ "version": "26.1.0",
4
4
  "description": "",
5
5
  "homepage": "https://docs.st.dev/docs/frontend/notifications-center",
6
6
  "repository": {
@@ -25,12 +25,14 @@
25
25
  "@servicetitan/log-service": "^23.2.1",
26
26
  "@servicetitan/react-ioc": "^23.2.1",
27
27
  "@servicetitan/web-components": "^23.2.1",
28
+ "@testing-library/jest-dom": "^6.4.2",
29
+ "@testing-library/react": "^14.2.1",
28
30
  "@types/react": "~18.2.55",
29
31
  "@types/react-router": "~5.1.17",
30
32
  "@types/react-shadow-dom-retarget-events": "~1.0.0",
31
33
  "axios": "~0.27.2",
32
34
  "mobx": "~6.6.0",
33
- "mobx-react": "~7.5.0",
35
+ "mobx-react": "~7.5.1",
34
36
  "react": "~18.2.0",
35
37
  "react-dom": "~18.2.0",
36
38
  "react-router-dom": "~5.3.0"
@@ -42,7 +44,7 @@
42
44
  "@servicetitan/web-components": ">21.0.0",
43
45
  "axios": "~0.27.2",
44
46
  "mobx": "~6.6.0",
45
- "mobx-react": "~7.5.0",
47
+ "mobx-react": ">=7.5.1",
46
48
  "react": ">=17.0.2",
47
49
  "react-dom": ">=17.0.2",
48
50
  "react-router-dom": ">=5.3.0 <7.0.0"
@@ -53,5 +55,5 @@
53
55
  "cli": {
54
56
  "webpack": false
55
57
  },
56
- "gitHead": "2027b0cb3bb4a06b8e381e3e9af8469a30b20f11"
58
+ "gitHead": "a859628bb29f8f17153e2a4e23bb38f14f447b10"
57
59
  }
@@ -0,0 +1,71 @@
1
+ import '@testing-library/jest-dom';
2
+ import { render, waitFor, within } from '@testing-library/react';
3
+ import { ReactNode } from 'react';
4
+
5
+ import { Container } from '../container';
6
+
7
+ describe('[notifications] Container', () => {
8
+ beforeEach(() => {
9
+ document.getElementById('servicetitan-notifications')?.remove();
10
+ });
11
+
12
+ const subject = (children?: ReactNode) => {
13
+ return render(<Container>{children}</Container>);
14
+ };
15
+
16
+ test('renders #servicetitan-notifications.initialized > .ToastGroup', async () => {
17
+ subject();
18
+
19
+ await waitFor(() =>
20
+ expect(
21
+ document.querySelectorAll('#servicetitan-notifications.initialized > .ToastGroup')
22
+ ).toHaveLength(1)
23
+ );
24
+ });
25
+
26
+ test('renders children within .ToastGroup', async () => {
27
+ subject(<button>Foo</button>);
28
+
29
+ await waitFor(() => {
30
+ expect(
31
+ within(
32
+ document.querySelector('#servicetitan-notifications.initialized > .ToastGroup')!
33
+ ).getByRole('button', { name: 'Foo' })
34
+ ).toBeInTheDocument();
35
+ });
36
+ });
37
+
38
+ describe('when #servicetitan-notifications already exists', () => {
39
+ let container: HTMLElement;
40
+
41
+ beforeEach(() => {
42
+ container = document.createElement('div');
43
+ container.setAttribute('id', 'servicetitan-notifications');
44
+ document.body.appendChild(container);
45
+ });
46
+
47
+ test('creates .ToastGroup within existing container', async () => {
48
+ subject();
49
+
50
+ await waitFor(() => {
51
+ expect(container.querySelectorAll('.ToastGroup')).toHaveLength(1);
52
+ });
53
+ });
54
+
55
+ describe('when .ToastGroup already exists', () => {
56
+ let toastGroup: HTMLElement;
57
+
58
+ beforeEach(() => {
59
+ toastGroup = document.createElement('div');
60
+ toastGroup.classList.add('ToastGroup');
61
+ container.appendChild(toastGroup);
62
+ });
63
+
64
+ test('renders children inside existing ToastGroup', () => {
65
+ subject(<button>Baz</button>);
66
+
67
+ expect(within(toastGroup).getByRole('button', { name: 'Baz' })).toBeInTheDocument();
68
+ });
69
+ });
70
+ });
71
+ });
@@ -1,6 +1,6 @@
1
- import { useState, FC, PropsWithChildren } from 'react';
2
-
3
1
  import { Toast } from '@servicetitan/design-system';
2
+ import { FC, Fragment, PropsWithChildren, useEffect, useState } from 'react';
3
+ import { createPortal } from 'react-dom';
4
4
 
5
5
  import { createElement } from '../create-element';
6
6
 
@@ -11,6 +11,25 @@ export const Container: FC<PropsWithChildren> = ({ children }) => {
11
11
  document.body.appendChild(createElement('div', { id: 'servicetitan-notifications' }))
12
12
  );
13
13
  });
14
+ const [toastGroup, setToastGroup] = useState(() => findToastGroup(container));
15
+ const [foundGroup] = useState(() => !!toastGroup);
16
+
17
+ useEffect(() => {
18
+ if (!toastGroup) {
19
+ setToastGroup(findToastGroup(container));
20
+ // This stops old code running in MFE from rendering duplicate Toast.Group
21
+ container.classList.add('initialized');
22
+ }
23
+ }, [container, toastGroup]);
14
24
 
15
- return container ? <Toast.Group portal={container}>{children}</Toast.Group> : null;
25
+ return (
26
+ <Fragment>
27
+ {foundGroup ? null : <Toast.Group portal={container} />}
28
+ {toastGroup ? createPortal(children, toastGroup) : null}
29
+ </Fragment>
30
+ );
16
31
  };
32
+
33
+ function findToastGroup(parent: HTMLElement) {
34
+ return parent.getElementsByClassName('ToastGroup')[0] ?? null;
35
+ }
@@ -21,7 +21,7 @@ import {
21
21
  import { DefaultNotification } from './default-notification';
22
22
  import { NotificationsUnwrapped } from './notifications-unwrapped';
23
23
 
24
- export interface NotificationsProps extends PropsWithChildren {
24
+ export interface NotificationsProps extends PropsWithChildren<{}> {
25
25
  apiService?: interfaces.Newable<NotificationsApi>;
26
26
  }
27
27