@vendorflow/components 2.0.42 → 2.0.46

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.
@@ -10,5 +10,4 @@ export { default as InputCheckboxGroup } from './material-ui/InputCheckboxGroup'
10
10
  export { default as InputRadioGroup } from './material-ui/InputRadioGroup';
11
11
  export { default as InputSearchDropdown } from './material-ui/InputSearchDropdown';
12
12
  export { default as InputTime } from './material-ui/InputTime';
13
- export { default as InfiniteScroll } from './InfiniteScroll';
14
13
  export { default as Modal } from './material-ui/Modal';
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.Modal = exports.InfiniteScroll = exports.InputTime = exports.InputSearchDropdown = exports.InputRadioGroup = exports.InputCheckboxGroup = exports.InputGroup = exports.InputDateTime = exports.InputDate = exports.DataTable = exports.ColorPicker = exports.ChatInterface = exports.ButtonMenu = exports.Button = void 0;
6
+ exports.Modal = exports.InputTime = exports.InputSearchDropdown = exports.InputRadioGroup = exports.InputCheckboxGroup = exports.InputGroup = exports.InputDateTime = exports.InputDate = exports.DataTable = exports.ColorPicker = exports.ChatInterface = exports.ButtonMenu = exports.Button = void 0;
7
7
  var Button_1 = require("./material-ui/Button");
8
8
  Object.defineProperty(exports, "Button", { enumerable: true, get: function () { return __importDefault(Button_1).default; } });
9
9
  var ButtonMenu_1 = require("./material-ui/ButtonMenu");
@@ -28,7 +28,5 @@ var InputSearchDropdown_1 = require("./material-ui/InputSearchDropdown");
28
28
  Object.defineProperty(exports, "InputSearchDropdown", { enumerable: true, get: function () { return __importDefault(InputSearchDropdown_1).default; } });
29
29
  var InputTime_1 = require("./material-ui/InputTime");
30
30
  Object.defineProperty(exports, "InputTime", { enumerable: true, get: function () { return __importDefault(InputTime_1).default; } });
31
- var InfiniteScroll_1 = require("./InfiniteScroll");
32
- Object.defineProperty(exports, "InfiniteScroll", { enumerable: true, get: function () { return __importDefault(InfiniteScroll_1).default; } });
33
31
  var Modal_1 = require("./material-ui/Modal");
34
32
  Object.defineProperty(exports, "Modal", { enumerable: true, get: function () { return __importDefault(Modal_1).default; } });
@@ -3,6 +3,8 @@ export interface Message {
3
3
  id: string;
4
4
  userId: string;
5
5
  username: string;
6
+ /** use for building chat icon */
7
+ initials: string;
6
8
  timestamp: string;
7
9
  content: string;
8
10
  }
@@ -101,7 +101,7 @@ function ChatInterface(_a) {
101
101
  } }, function (_a) {
102
102
  var measureRef = _a.measureRef;
103
103
  return ((0, react_1.jsx)(react_2.Fragment, null,
104
- (0, react_1.jsx)(MessageThread_1.default, { userId: userId, messages: messages, inputHeight: inputHeight, hasNextPage: hasNextPage, fetchNextPage: fetchNextPage, isLoading: isLoading, isFetching: isFetching, colors: colors }),
104
+ (0, react_1.jsx)(MessageThread_1.default, { userId: userId, messages: messages, inputHeight: inputHeight, hasNextPage: hasNextPage, fetchNextPage: fetchNextPage, isLoading: isLoading, isFetching: isFetching, isSubmitting: isSubmitting, colors: colors }),
105
105
  renderInputComponent ? (renderInputComponent(measureRef)) : ((0, react_1.jsx)(MessageInput_1.default, { ref: measureRef, handleClickSend: handleClickSend, message: message, setMessage: setMessage, isSubmitting: isSubmitting, placeholder: placeholder }))));
106
106
  })));
107
107
  }
@@ -40,6 +40,7 @@ var react_2 = require("react");
40
40
  var faker_1 = __importDefault(require("faker"));
41
41
  var short_uuid_1 = __importDefault(require("short-uuid"));
42
42
  var ChatInterface_1 = __importDefault(require("./ChatInterface"));
43
+ var Workspaces_constants_1 = require("@vendorflow/common/lib/constants/Workspaces.constants");
43
44
  // tslint:disable-next-line:no-console
44
45
  function ChatInterface() {
45
46
  var _a = __read((0, react_2.useState)(true), 2), isLoading = _a[0], setLoading = _a[1];
@@ -48,7 +49,7 @@ function ChatInterface() {
48
49
  var _d = __read((0, react_2.useState)([]), 2), messages = _d[0], setMessages = _d[1];
49
50
  var _e = __read((0, react_2.useState)(true), 2), hasMore = _e[0], setHasMore = _e[1];
50
51
  (0, react_2.useEffect)(function () {
51
- setMessages(new Array(5).fill(null).map(generateMessage));
52
+ setMessages(new Array(5).fill(null).map(generateMessage).concat([generateSystemMessage()]));
52
53
  setLoading(false);
53
54
  setFetching(false);
54
55
  }, []);
@@ -58,21 +59,39 @@ function ChatInterface() {
58
59
  function generateId() {
59
60
  return short_uuid_1.default.generate();
60
61
  }
62
+ function generateSystemMessage() {
63
+ return {
64
+ id: generateId(),
65
+ userId: Workspaces_constants_1.SYSTEM_IDENTITY_ID,
66
+ username: 'System',
67
+ initials: 'S',
68
+ timestamp: generateTimestamp(),
69
+ content: faker_1.default.lorem.sentence(5, 2),
70
+ };
71
+ }
61
72
  function generateMessage() {
62
73
  var user = faker_1.default.random.arrayElement([
63
74
  {
64
75
  id: 'user1',
65
76
  name: 'Socorro Aguilar',
77
+ initials: 'SA',
66
78
  },
67
79
  {
68
80
  id: 'user2',
69
81
  name: 'Greg Bujak',
82
+ initials: 'GB',
83
+ },
84
+ {
85
+ id: 'user3',
86
+ name: 'xinyi@vendorflow.co',
87
+ initials: 'X',
70
88
  },
71
89
  ]);
72
90
  return {
73
91
  id: generateId(),
74
92
  userId: user.id,
75
93
  username: user.name,
94
+ initials: user.initials,
76
95
  timestamp: generateTimestamp(),
77
96
  content: faker_1.default.lorem.sentence(5, 2),
78
97
  };
@@ -80,35 +99,36 @@ function ChatInterface() {
80
99
  function generateMessagePage() {
81
100
  return new Array(10).fill(null).map(generateMessage);
82
101
  }
83
- function loadMore() {
102
+ var fetchNextPage = (0, react_2.useCallback)(function () {
84
103
  setFetching(true);
85
104
  setTimeout(function () {
86
105
  setMessages(__spreadArray(__spreadArray([], __read(messages), false), __read(generateMessagePage()), false));
87
106
  setFetching(false);
88
107
  }, 100);
89
- }
108
+ }, [messages, generateMessagePage, setMessages]);
90
109
  function handleSend(message) {
91
110
  setSubmitting(true);
92
111
  setFetching(true);
93
112
  return new Promise(function (resolve) {
94
113
  setTimeout(function () {
95
- setSubmitting(false);
96
- setFetching(false);
97
114
  setMessages(__spreadArray([
98
115
  {
99
116
  id: generateId(),
100
117
  userId: 'user1',
101
118
  username: 'Socorro Aguilar',
119
+ initials: 'SA',
102
120
  timestamp: generateTimestamp(),
103
121
  content: message,
104
122
  }
105
123
  ], __read(messages), false));
124
+ setSubmitting(false);
125
+ setFetching(false);
106
126
  resolve(true);
107
127
  }, 500);
108
128
  });
109
129
  }
110
130
  return ((0, react_1.jsx)("div", { css: (0, react_1.css)(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n border: 1px solid #ededed;\n height: 30rem;\n "], ["\n border: 1px solid #ededed;\n height: 30rem;\n "]))) },
111
- (0, react_1.jsx)(ChatInterface_1.default, { userId: "user1", messages: messages, handleSend: handleSend, fetchNextPage: loadMore, hasNextPage: hasMore, isLoading: isLoading, isFetching: isFetching, isSubmitting: isSubmitting })));
131
+ (0, react_1.jsx)(ChatInterface_1.default, { userId: "user1", messages: messages, handleSend: handleSend, fetchNextPage: fetchNextPage, hasNextPage: hasMore, isLoading: isLoading, isFetching: isFetching, isSubmitting: isSubmitting })));
112
132
  }
113
133
  exports.ChatInterface = ChatInterface;
114
134
  var templateObject_1;
@@ -27,6 +27,7 @@ var date_fns_1 = require("date-fns");
27
27
  var icons_material_1 = require("@mui/icons-material");
28
28
  var material_1 = require("@mui/material");
29
29
  var react_2 = require("react");
30
+ var Workspaces_constants_1 = require("@vendorflow/common/lib/constants/Workspaces.constants");
30
31
  function MessageItem(_a) {
31
32
  var userId = _a.userId, message = _a.message, colors = _a.colors;
32
33
  var _b = __read((0, react_2.useState)(getUnixTimestamp()), 2), displayUpdateAt = _b[0], setDisplayUpdateAt = _b[1];
@@ -56,16 +57,15 @@ function MessageItem(_a) {
56
57
  return ((0, react_1.jsx)("div", { css: (0, react_1.css)(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n width: 100%;\n background: white;\n margin-top: 0.5rem;\n border-radius: 4px;\n display: flex;\n flex-direction: row;\n "], ["\n width: 100%;\n background: white;\n margin-top: 0.5rem;\n border-radius: 4px;\n display: flex;\n flex-direction: row;\n "]))) },
57
58
  (0, react_1.jsx)(material_1.Avatar, { css: function (theme) {
58
59
  var _a, _b, _c, _d, _e;
59
- return (0, react_1.css)(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n && {\n height: 2rem;\n width: 2rem;\n margin-right: 0.5rem;\n background-color: ", ";\n }\n "], ["\n && {\n height: 2rem;\n width: 2rem;\n margin-right: 0.5rem;\n background-color: ", ";\n }\n "])), userId === message.userId
60
+ return (0, react_1.css)(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n && {\n font-size: 1rem;\n height: 2rem;\n width: 2rem;\n margin-right: 0.5rem;\n visibility: ", ";\n background-color: ", ";\n }\n "], ["\n && {\n font-size: 1rem;\n height: 2rem;\n width: 2rem;\n margin-right: 0.5rem;\n visibility: ", ";\n background-color: ", ";\n }\n "])), message.userId === Workspaces_constants_1.SYSTEM_IDENTITY_ID ? 'hidden' : 'visible', userId === message.userId
60
61
  ? (colors === null || colors === void 0 ? void 0 : colors.user) || ((_c = (_b = (_a = theme === null || theme === void 0 ? void 0 : theme.custom) === null || _a === void 0 ? void 0 : _a.palette) === null || _b === void 0 ? void 0 : _b.tertiary) === null || _c === void 0 ? void 0 : _c.main) || 'hsl(0, 0%, 89%)'
61
62
  : (colors === null || colors === void 0 ? void 0 : colors.others) || ((_e = (_d = theme === null || theme === void 0 ? void 0 : theme.palette) === null || _d === void 0 ? void 0 : _d.primary) === null || _e === void 0 ? void 0 : _e.main) || 'hsl(0, 0%, 47%)');
62
- } },
63
- (0, react_1.jsx)(icons_material_1.Person, null)),
63
+ } }, message.initials === '' ? (0, react_1.jsx)(icons_material_1.Person, null) : message.initials),
64
64
  (0, react_1.jsx)("div", null,
65
65
  (0, react_1.jsx)("div", { css: (0, react_1.css)(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n display: flex;\n flex-direction: row;\n justify-content: flex-start;\n align-items: flex-start;\n "], ["\n display: flex;\n flex-direction: row;\n justify-content: flex-start;\n align-items: flex-start;\n "]))) },
66
66
  (0, react_1.jsx)("div", { css: (0, react_1.css)(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n font-weight: 700;\n font-size: 0.75rem;\n display: inline-block;\n margin-right: 0.25rem;\n "], ["\n font-weight: 700;\n font-size: 0.75rem;\n display: inline-block;\n margin-right: 0.25rem;\n "]))) }, message.username),
67
67
  (0, react_1.jsx)("div", { css: (0, react_1.css)(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n font-size: 0.75rem;\n display: inline-block;\n "], ["\n font-size: 0.75rem;\n display: inline-block;\n "]))) }, timeDisplay)),
68
- (0, react_1.jsx)("div", { css: (0, react_1.css)(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n font-size: 0.875rem;\n white-space: break-spaces;\n "], ["\n font-size: 0.875rem;\n white-space: break-spaces;\n "]))) }, message.content))));
68
+ (0, react_1.jsx)("div", { css: (0, react_1.css)(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n color: ", ";\n font-size: 0.875rem;\n white-space: break-spaces;\n "], ["\n color: ", ";\n font-size: 0.875rem;\n white-space: break-spaces;\n "])), message.userId === Workspaces_constants_1.SYSTEM_IDENTITY_ID ? 'hsl(0, 0%, 65%)' : 'inherit') }, message.content))));
69
69
  }
70
70
  exports.default = MessageItem;
71
71
  var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6;
@@ -1,6 +1,6 @@
1
1
  import { ChatInterfaceProps } from './ChatInterface';
2
- interface Props extends Pick<ChatInterfaceProps, 'userId' | 'messages' | 'hasNextPage' | 'fetchNextPage' | 'isLoading' | 'isFetching' | 'colors'> {
2
+ interface Props extends Pick<ChatInterfaceProps, 'userId' | 'messages' | 'hasNextPage' | 'fetchNextPage' | 'isLoading' | 'isFetching' | 'isSubmitting' | 'colors'> {
3
3
  inputHeight: number;
4
4
  }
5
- export default function MessageThread({ userId, messages, inputHeight, hasNextPage, fetchNextPage, isLoading, isFetching, colors, }: Props): JSX.Element;
5
+ export default function MessageThread({ userId, messages, inputHeight, hasNextPage, fetchNextPage, isLoading, isFetching, isSubmitting, colors, }: Props): JSX.Element;
6
6
  export {};
@@ -12,12 +12,108 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  var react_1 = require("@emotion/react");
13
13
  var react_2 = require("react");
14
14
  var MessageItem_1 = __importDefault(require("./MessageItem"));
15
- var InfiniteScroll_1 = __importDefault(require("../../InfiniteScroll/InfiniteScroll"));
15
+ var lodash_1 = require("lodash");
16
+ var material_1 = require("@mui/material");
16
17
  function MessageThread(_a) {
17
- var userId = _a.userId, messages = _a.messages, inputHeight = _a.inputHeight, hasNextPage = _a.hasNextPage, fetchNextPage = _a.fetchNextPage, isLoading = _a.isLoading, isFetching = _a.isFetching, colors = _a.colors;
18
+ var _b;
19
+ var userId = _a.userId, messages = _a.messages, inputHeight = _a.inputHeight, hasNextPage = _a.hasNextPage, fetchNextPage = _a.fetchNextPage, isLoading = _a.isLoading, isFetching = _a.isFetching, isSubmitting = _a.isSubmitting, colors = _a.colors;
20
+ var isInitialized = (0, react_2.useRef)(false);
21
+ var isScrollLoad = (0, react_2.useRef)(false);
22
+ var hasSubmitted = (0, react_2.useRef)(false);
23
+ var prevScrollTop = (0, react_2.useRef)(null);
24
+ var prevScrollHeight = (0, react_2.useRef)(null);
25
+ var shouldScrollToPrevPosition = (0, react_2.useRef)(false);
18
26
  var scrollParent = (0, react_2.useRef)(null);
27
+ var handleScrollEvent = (0, react_2.useCallback)((0, lodash_1.debounce)(function (evt) {
28
+ var parent = evt.target;
29
+ if (parent.scrollTop === 0 && hasNextPage && fetchNextPage && !isLoading && !isFetching) {
30
+ isScrollLoad.current = true;
31
+ prevScrollHeight.current = parent.scrollHeight;
32
+ fetchNextPage();
33
+ }
34
+ }, 300), [hasNextPage, fetchNextPage, isLoading, isFetching]);
35
+ (0, react_2.useEffect)(function () {
36
+ if (isSubmitting) {
37
+ hasSubmitted.current = true;
38
+ }
39
+ }, [isSubmitting]);
40
+ // This will handle the initial loading of messages, then scroll to bottom
41
+ (0, react_2.useEffect)(function () {
42
+ if (!isInitialized.current && !isFetching && scrollParent.current) {
43
+ var _a = scrollParent.current, clientHeight = _a.clientHeight, scrollHeight = _a.scrollHeight;
44
+ if (clientHeight >= scrollHeight && hasNextPage && fetchNextPage) {
45
+ fetchNextPage();
46
+ return;
47
+ }
48
+ isInitialized.current = true;
49
+ scrollParent.current.scrollTo(0, scrollHeight - clientHeight);
50
+ }
51
+ }, [isFetching, isInitialized.current, hasNextPage, fetchNextPage]);
52
+ // Sets up the scroll event listener
53
+ (0, react_2.useEffect)(function () {
54
+ if (scrollParent.current) {
55
+ scrollParent.current.addEventListener('scroll', handleScrollEvent);
56
+ }
57
+ return function () {
58
+ if (scrollParent.current) {
59
+ scrollParent.current.removeEventListener('scroll', handleScrollEvent);
60
+ }
61
+ };
62
+ }, [scrollParent.current, hasNextPage, fetchNextPage, isLoading, isFetching]);
63
+ // Handles the scroll position adjustment after fetching the next page
64
+ (0, react_2.useEffect)(function () {
65
+ if (!isFetching &&
66
+ isInitialized.current &&
67
+ scrollParent.current &&
68
+ isScrollLoad.current &&
69
+ prevScrollHeight.current &&
70
+ scrollParent.current.scrollHeight !== prevScrollHeight.current) {
71
+ var delta = scrollParent.current.scrollHeight - prevScrollHeight.current;
72
+ scrollParent.current.scrollTo(0, delta);
73
+ isScrollLoad.current = false;
74
+ prevScrollHeight.current = 0;
75
+ }
76
+ }, [isFetching, prevScrollHeight.current]);
77
+ // Manages scroll position for data changes that are triggered from anything other than the scroll event
78
+ (0, react_2.useEffect)(function () {
79
+ var _a;
80
+ if (scrollParent.current && !isScrollLoad.current && isInitialized.current) {
81
+ var _b = scrollParent.current, scrollHeight = _b.scrollHeight, scrollTop = _b.scrollTop, clientHeight = _b.clientHeight;
82
+ if (isFetching) {
83
+ // track the current position
84
+ prevScrollHeight.current = scrollHeight;
85
+ prevScrollTop.current = scrollTop;
86
+ var distanceFromBottom = scrollHeight - scrollTop - clientHeight;
87
+ if (!isSubmitting && distanceFromBottom > 200) {
88
+ shouldScrollToPrevPosition.current = true;
89
+ }
90
+ }
91
+ else {
92
+ // init to scroll to bottom delta
93
+ var delta = scrollHeight - clientHeight;
94
+ if (hasSubmitted.current) {
95
+ // scroll to bottom if this was triggered by the current user's sent message
96
+ (_a = scrollParent.current) === null || _a === void 0 ? void 0 : _a.scrollTo(0, delta);
97
+ }
98
+ else if (!isFetching && prevScrollHeight.current !== null && prevScrollTop.current !== null) {
99
+ if (shouldScrollToPrevPosition.current) {
100
+ delta = prevScrollTop.current;
101
+ }
102
+ scrollParent.current.scrollTo(0, delta);
103
+ }
104
+ // clean up
105
+ prevScrollHeight.current = null;
106
+ prevScrollTop.current = null;
107
+ hasSubmitted.current = false;
108
+ shouldScrollToPrevPosition.current = false;
109
+ }
110
+ }
111
+ }, [isFetching, (_b = scrollParent.current) === null || _b === void 0 ? void 0 : _b.scrollHeight]);
19
112
  return ((0, react_1.jsx)("div", { ref: scrollParent, css: (0, react_1.css)(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n box-sizing: border-box;\n height: calc(100% - ", "px);\n width: 100%;\n padding: 0.5rem 1rem;\n overflow-y: auto;\n "], ["\n box-sizing: border-box;\n height: calc(100% - ", "px);\n width: 100%;\n padding: 0.5rem 1rem;\n overflow-y: auto;\n "])), inputHeight) },
20
- (0, react_1.jsx)(InfiniteScroll_1.default, { scrollParent: scrollParent, isReverse: true, isLoading: isLoading, isFetching: isFetching, hasNextPage: hasNextPage, fetchNextPage: fetchNextPage }, messages.map(function (message) { return ((0, react_1.jsx)(MessageItem_1.default, { key: "" + message.id, message: message, userId: userId, colors: colors })); }))));
113
+ (0, react_1.jsx)("div", { css: (0, react_1.css)(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n display: flex;\n flex-direction: column-reverse;\n justify-content: flex-start;\n align-items: flex-start;\n "], ["\n display: flex;\n flex-direction: column-reverse;\n justify-content: flex-start;\n align-items: flex-start;\n "]))) },
114
+ messages.map(function (message) { return ((0, react_1.jsx)(MessageItem_1.default, { key: "" + message.id, message: message, userId: userId, colors: colors })); }),
115
+ hasNextPage && ((0, react_1.jsx)("div", { key: "loader", css: (0, react_1.css)(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n width: 100%;\n margin: 0.5rem 0;\n height: auto;\n display: flex;\n justify-content: center;\n align-items: center;\n\n && {\n visibility: ", ";\n }\n "], ["\n width: 100%;\n margin: 0.5rem 0;\n height: auto;\n display: flex;\n justify-content: center;\n align-items: center;\n\n && {\n visibility: ", ";\n }\n "])), isFetching && isScrollLoad ? 'visible' : 'hidden') },
116
+ (0, react_1.jsx)(material_1.CircularProgress, { size: "1.5rem", disableShrink: true }))))));
21
117
  }
22
118
  exports.default = MessageThread;
23
- var templateObject_1;
119
+ var templateObject_1, templateObject_2, templateObject_3;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vendorflow/components",
3
- "version": "2.0.42",
3
+ "version": "2.0.46",
4
4
  "description": "React components for vendorflow",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -62,6 +62,7 @@
62
62
  "@types/react-table": "^7.7.6",
63
63
  "@typescript-eslint/eslint-plugin": "^4.32.0",
64
64
  "@typescript-eslint/parser": "^4.32.0",
65
+ "@vendorflow/common": "^1.0.36",
65
66
  "babel-eslint": "10.1.0",
66
67
  "babel-jest": "^24.9.0",
67
68
  "babel-loader": "^8.2.2",