@weavy/uikit-react 11.0.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 (223) hide show
  1. package/.github/workflows/publish.yml +16 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +110 -0
  4. package/changelog.md +50 -0
  5. package/dist/cjs/index.js +39 -0
  6. package/dist/cjs/index.js.map +1 -0
  7. package/dist/cjs/types/client/WeavyClient.d.ts +16 -0
  8. package/dist/cjs/types/components/Attachment.d.ts +13 -0
  9. package/dist/cjs/types/components/Avatar.d.ts +11 -0
  10. package/dist/cjs/types/components/Chat.d.ts +4 -0
  11. package/dist/cjs/types/components/Conversation.d.ts +4 -0
  12. package/dist/cjs/types/components/ConversationBadge.d.ts +3 -0
  13. package/dist/cjs/types/components/ConversationForm.d.ts +7 -0
  14. package/dist/cjs/types/components/ConversationList.d.ts +3 -0
  15. package/dist/cjs/types/components/ConversationListItem.d.ts +4 -0
  16. package/dist/cjs/types/components/File.d.ts +9 -0
  17. package/dist/cjs/types/components/FileBrowser.d.ts +6 -0
  18. package/dist/cjs/types/components/Image.d.ts +16 -0
  19. package/dist/cjs/types/components/Meeting.d.ts +8 -0
  20. package/dist/cjs/types/components/MeetingCard.d.ts +6 -0
  21. package/dist/cjs/types/components/Meetings.d.ts +6 -0
  22. package/dist/cjs/types/components/Message.d.ts +4 -0
  23. package/dist/cjs/types/components/Messages.d.ts +9 -0
  24. package/dist/cjs/types/components/Messenger.d.ts +4 -0
  25. package/dist/cjs/types/components/NewConversation.d.ts +3 -0
  26. package/dist/cjs/types/components/Presence.d.ts +7 -0
  27. package/dist/cjs/types/components/Reactions.d.ts +13 -0
  28. package/dist/cjs/types/components/SearchUsers.d.ts +7 -0
  29. package/dist/cjs/types/components/SeenBy.d.ts +9 -0
  30. package/dist/cjs/types/components/Typing.d.ts +8 -0
  31. package/dist/cjs/types/contexts/MessengerContext.d.ts +8 -0
  32. package/dist/cjs/types/contexts/PreviewContext.d.ts +7 -0
  33. package/dist/cjs/types/contexts/UserContext.d.ts +8 -0
  34. package/dist/cjs/types/contexts/WeavyContext.d.ts +10 -0
  35. package/dist/cjs/types/hooks/useBadge.d.ts +1 -0
  36. package/dist/cjs/types/hooks/useChat.d.ts +1 -0
  37. package/dist/cjs/types/hooks/useConversation.d.ts +1 -0
  38. package/dist/cjs/types/hooks/useConversations.d.ts +1 -0
  39. package/dist/cjs/types/hooks/useDebounce.d.ts +2 -0
  40. package/dist/cjs/types/hooks/useEvents.d.ts +6 -0
  41. package/dist/cjs/types/hooks/useFileUploader.d.ts +1 -0
  42. package/dist/cjs/types/hooks/useMembers.d.ts +1 -0
  43. package/dist/cjs/types/hooks/useMessages.d.ts +1 -0
  44. package/dist/cjs/types/hooks/useMutateChat.d.ts +4 -0
  45. package/dist/cjs/types/hooks/useMutateConversation.d.ts +3 -0
  46. package/dist/cjs/types/hooks/useMutateConversationName.d.ts +4 -0
  47. package/dist/cjs/types/hooks/useMutateDeleteReaction.d.ts +4 -0
  48. package/dist/cjs/types/hooks/useMutateExternalBlobs.d.ts +3 -0
  49. package/dist/cjs/types/hooks/useMutateMeeting.d.ts +3 -0
  50. package/dist/cjs/types/hooks/useMutateMembers.d.ts +4 -0
  51. package/dist/cjs/types/hooks/useMutateMessage.d.ts +9 -0
  52. package/dist/cjs/types/hooks/useMutatePinned.d.ts +4 -0
  53. package/dist/cjs/types/hooks/useMutateReaction.d.ts +4 -0
  54. package/dist/cjs/types/hooks/useMutateRead.d.ts +4 -0
  55. package/dist/cjs/types/hooks/useMutateRemoveMembers.d.ts +4 -0
  56. package/dist/cjs/types/hooks/useMutateTyping.d.ts +3 -0
  57. package/dist/cjs/types/hooks/usePresence.d.ts +1 -0
  58. package/dist/cjs/types/hooks/usePreview.d.ts +4 -0
  59. package/dist/cjs/types/hooks/useReactions.d.ts +3 -0
  60. package/dist/cjs/types/hooks/useSearchUsers.d.ts +1 -0
  61. package/dist/cjs/types/hooks/useThrottle.d.ts +2 -0
  62. package/dist/cjs/types/hooks/useUser.d.ts +1 -0
  63. package/dist/cjs/types/index.d.ts +15 -0
  64. package/dist/cjs/types/types/Chat.d.ts +3 -0
  65. package/dist/cjs/types/types/Conversation.d.ts +4 -0
  66. package/dist/cjs/types/types/ConversationListItem.d.ts +4 -0
  67. package/dist/cjs/types/types/Message.d.ts +15 -0
  68. package/dist/cjs/types/types/Messenger.d.ts +3 -0
  69. package/dist/cjs/types/types/types.d.ts +150 -0
  70. package/dist/cjs/types/ui/Button.d.ts +4 -0
  71. package/dist/cjs/types/ui/Dropdown.d.ts +19 -0
  72. package/dist/cjs/types/ui/Icon.d.ts +10 -0
  73. package/dist/cjs/types/ui/Overlay.d.ts +12 -0
  74. package/dist/cjs/types/utils/fileUtilities.d.ts +5 -0
  75. package/dist/cjs/types/utils/styles.d.ts +17 -0
  76. package/dist/esm/index.js +39 -0
  77. package/dist/esm/index.js.map +1 -0
  78. package/dist/esm/types/client/WeavyClient.d.ts +16 -0
  79. package/dist/esm/types/components/Attachment.d.ts +13 -0
  80. package/dist/esm/types/components/Avatar.d.ts +11 -0
  81. package/dist/esm/types/components/Chat.d.ts +4 -0
  82. package/dist/esm/types/components/Conversation.d.ts +4 -0
  83. package/dist/esm/types/components/ConversationBadge.d.ts +3 -0
  84. package/dist/esm/types/components/ConversationForm.d.ts +7 -0
  85. package/dist/esm/types/components/ConversationList.d.ts +3 -0
  86. package/dist/esm/types/components/ConversationListItem.d.ts +4 -0
  87. package/dist/esm/types/components/File.d.ts +9 -0
  88. package/dist/esm/types/components/FileBrowser.d.ts +6 -0
  89. package/dist/esm/types/components/Image.d.ts +16 -0
  90. package/dist/esm/types/components/Meeting.d.ts +8 -0
  91. package/dist/esm/types/components/MeetingCard.d.ts +6 -0
  92. package/dist/esm/types/components/Meetings.d.ts +6 -0
  93. package/dist/esm/types/components/Message.d.ts +4 -0
  94. package/dist/esm/types/components/Messages.d.ts +9 -0
  95. package/dist/esm/types/components/Messenger.d.ts +4 -0
  96. package/dist/esm/types/components/NewConversation.d.ts +3 -0
  97. package/dist/esm/types/components/Presence.d.ts +7 -0
  98. package/dist/esm/types/components/Reactions.d.ts +13 -0
  99. package/dist/esm/types/components/SearchUsers.d.ts +7 -0
  100. package/dist/esm/types/components/SeenBy.d.ts +9 -0
  101. package/dist/esm/types/components/Typing.d.ts +8 -0
  102. package/dist/esm/types/contexts/MessengerContext.d.ts +8 -0
  103. package/dist/esm/types/contexts/PreviewContext.d.ts +7 -0
  104. package/dist/esm/types/contexts/UserContext.d.ts +8 -0
  105. package/dist/esm/types/contexts/WeavyContext.d.ts +10 -0
  106. package/dist/esm/types/hooks/useBadge.d.ts +1 -0
  107. package/dist/esm/types/hooks/useChat.d.ts +1 -0
  108. package/dist/esm/types/hooks/useConversation.d.ts +1 -0
  109. package/dist/esm/types/hooks/useConversations.d.ts +1 -0
  110. package/dist/esm/types/hooks/useDebounce.d.ts +2 -0
  111. package/dist/esm/types/hooks/useEvents.d.ts +6 -0
  112. package/dist/esm/types/hooks/useFileUploader.d.ts +1 -0
  113. package/dist/esm/types/hooks/useMembers.d.ts +1 -0
  114. package/dist/esm/types/hooks/useMessages.d.ts +1 -0
  115. package/dist/esm/types/hooks/useMutateChat.d.ts +4 -0
  116. package/dist/esm/types/hooks/useMutateConversation.d.ts +3 -0
  117. package/dist/esm/types/hooks/useMutateConversationName.d.ts +4 -0
  118. package/dist/esm/types/hooks/useMutateDeleteReaction.d.ts +4 -0
  119. package/dist/esm/types/hooks/useMutateExternalBlobs.d.ts +3 -0
  120. package/dist/esm/types/hooks/useMutateMeeting.d.ts +3 -0
  121. package/dist/esm/types/hooks/useMutateMembers.d.ts +4 -0
  122. package/dist/esm/types/hooks/useMutateMessage.d.ts +9 -0
  123. package/dist/esm/types/hooks/useMutatePinned.d.ts +4 -0
  124. package/dist/esm/types/hooks/useMutateReaction.d.ts +4 -0
  125. package/dist/esm/types/hooks/useMutateRead.d.ts +4 -0
  126. package/dist/esm/types/hooks/useMutateRemoveMembers.d.ts +4 -0
  127. package/dist/esm/types/hooks/useMutateTyping.d.ts +3 -0
  128. package/dist/esm/types/hooks/usePresence.d.ts +1 -0
  129. package/dist/esm/types/hooks/usePreview.d.ts +4 -0
  130. package/dist/esm/types/hooks/useReactions.d.ts +3 -0
  131. package/dist/esm/types/hooks/useSearchUsers.d.ts +1 -0
  132. package/dist/esm/types/hooks/useThrottle.d.ts +2 -0
  133. package/dist/esm/types/hooks/useUser.d.ts +1 -0
  134. package/dist/esm/types/index.d.ts +15 -0
  135. package/dist/esm/types/types/Chat.d.ts +3 -0
  136. package/dist/esm/types/types/Conversation.d.ts +4 -0
  137. package/dist/esm/types/types/ConversationListItem.d.ts +4 -0
  138. package/dist/esm/types/types/Message.d.ts +15 -0
  139. package/dist/esm/types/types/Messenger.d.ts +3 -0
  140. package/dist/esm/types/types/types.d.ts +150 -0
  141. package/dist/esm/types/ui/Button.d.ts +4 -0
  142. package/dist/esm/types/ui/Dropdown.d.ts +19 -0
  143. package/dist/esm/types/ui/Icon.d.ts +10 -0
  144. package/dist/esm/types/ui/Overlay.d.ts +12 -0
  145. package/dist/esm/types/utils/fileUtilities.d.ts +5 -0
  146. package/dist/esm/types/utils/styles.d.ts +17 -0
  147. package/dist/index.d.ts +98 -0
  148. package/package.json +47 -0
  149. package/rollup.config.js +41 -0
  150. package/src/client/WeavyClient.ts +95 -0
  151. package/src/components/Attachment.tsx +33 -0
  152. package/src/components/Avatar.tsx +26 -0
  153. package/src/components/Chat.tsx +68 -0
  154. package/src/components/Conversation.tsx +220 -0
  155. package/src/components/ConversationBadge.tsx +44 -0
  156. package/src/components/ConversationForm.tsx +217 -0
  157. package/src/components/ConversationList.tsx +61 -0
  158. package/src/components/ConversationListItem.tsx +155 -0
  159. package/src/components/File.tsx +21 -0
  160. package/src/components/FileBrowser.tsx +86 -0
  161. package/src/components/Image.tsx +66 -0
  162. package/src/components/Meeting.tsx +21 -0
  163. package/src/components/MeetingCard.tsx +31 -0
  164. package/src/components/Meetings.tsx +58 -0
  165. package/src/components/Message.tsx +90 -0
  166. package/src/components/Messages.tsx +271 -0
  167. package/src/components/Messenger.tsx +34 -0
  168. package/src/components/NewConversation.tsx +50 -0
  169. package/src/components/Presence.tsx +15 -0
  170. package/src/components/Reactions.tsx +95 -0
  171. package/src/components/SearchUsers.tsx +90 -0
  172. package/src/components/SeenBy.tsx +26 -0
  173. package/src/components/Typing.tsx +131 -0
  174. package/src/contexts/MessengerContext.tsx +44 -0
  175. package/src/contexts/PreviewContext.tsx +105 -0
  176. package/src/contexts/UserContext.tsx +31 -0
  177. package/src/contexts/WeavyContext.tsx +66 -0
  178. package/src/hooks/useBadge.ts +32 -0
  179. package/src/hooks/useChat.ts +32 -0
  180. package/src/hooks/useConversation.ts +28 -0
  181. package/src/hooks/useConversations.ts +27 -0
  182. package/src/hooks/useDebounce.ts +22 -0
  183. package/src/hooks/useEvents.ts +43 -0
  184. package/src/hooks/useFileUploader.ts +35 -0
  185. package/src/hooks/useMembers.ts +27 -0
  186. package/src/hooks/useMessages.ts +42 -0
  187. package/src/hooks/useMessenger.ts +51 -0
  188. package/src/hooks/useMutateChat.ts +44 -0
  189. package/src/hooks/useMutateConversation.ts +40 -0
  190. package/src/hooks/useMutateConversationName.ts +41 -0
  191. package/src/hooks/useMutateDeleteReaction.ts +38 -0
  192. package/src/hooks/useMutateExternalBlobs.ts +39 -0
  193. package/src/hooks/useMutateMeeting.ts +39 -0
  194. package/src/hooks/useMutateMembers.ts +43 -0
  195. package/src/hooks/useMutateMessage.ts +116 -0
  196. package/src/hooks/useMutatePinned.ts +40 -0
  197. package/src/hooks/useMutateReaction.ts +38 -0
  198. package/src/hooks/useMutateRead.ts +40 -0
  199. package/src/hooks/useMutateRemoveMembers.ts +43 -0
  200. package/src/hooks/useMutateTyping.ts +34 -0
  201. package/src/hooks/usePresence.ts +32 -0
  202. package/src/hooks/usePreview.ts +21 -0
  203. package/src/hooks/useReactions.ts +53 -0
  204. package/src/hooks/useSearchUsers.ts +26 -0
  205. package/src/hooks/useThrottle.ts +13 -0
  206. package/src/hooks/useUser.ts +38 -0
  207. package/src/index.ts +33 -0
  208. package/src/types/Chat.ts +3 -0
  209. package/src/types/Conversation.ts +4 -0
  210. package/src/types/ConversationListItem.ts +4 -0
  211. package/src/types/Message.ts +16 -0
  212. package/src/types/Messenger.ts +3 -0
  213. package/src/types/emoji-toolkit.d.ts +1 -0
  214. package/src/types/types.ts +175 -0
  215. package/src/ui/Button.tsx +32 -0
  216. package/src/ui/Dropdown.tsx +58 -0
  217. package/src/ui/Icon.tsx +79 -0
  218. package/src/ui/Overlay.tsx +41 -0
  219. package/src/utils/fileUtilities.ts +230 -0
  220. package/src/utils/infiniteScroll.js +175 -0
  221. package/src/utils/scrollToBottom.js +75 -0
  222. package/src/utils/styles.ts +42 -0
  223. package/tsconfig.json +108 -0
@@ -0,0 +1,10 @@
1
+ /// <reference types="react" />
2
+ declare type Props = {
3
+ name: string;
4
+ color?: string;
5
+ size?: number;
6
+ };
7
+ declare const UIIcon: {
8
+ UI: ({ name, color, size, ...props }: Props) => JSX.Element;
9
+ };
10
+ export default UIIcon;
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { Styles } from 'react-modal';
3
+ declare type OverlayProps = {
4
+ children: React.ReactNode;
5
+ className?: string;
6
+ isOpen: boolean;
7
+ style?: Styles;
8
+ };
9
+ declare const UIOverlay: {
10
+ UI: ({ children, className, isOpen, style }: OverlayProps) => JSX.Element;
11
+ };
12
+ export default UIOverlay;
@@ -0,0 +1,5 @@
1
+ export declare const fileSizeAsString: (size: number) => string;
2
+ export declare const getIcon: (name: string, mediaType?: string) => {
3
+ icon: string;
4
+ color?: string;
5
+ };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Sets the prefix for CSS classes on the HTML element for usage in javascript.
3
+ * @param {string} prefix
4
+ */
5
+ export declare function setPrefix(prefix: string): void;
6
+ /**
7
+ * Prefixes one or more classnames (with or without dot) using the themePrefix
8
+ * @param {...string} strs
9
+ * @returns string[]
10
+ */
11
+ export declare function prefixes(...strs: string[]): string[];
12
+ /**
13
+ * Prefixes one classname (with or without dot) using the themePrefix
14
+ * @param {string} str
15
+ * @returns string
16
+ */
17
+ export declare function prefix(str: string): string;
@@ -0,0 +1,98 @@
1
+ /// <reference types="react" />
2
+ import * as _microsoft_signalr from '@microsoft/signalr';
3
+ import React, { FC } from 'react';
4
+ import { Styles } from 'react-modal';
5
+
6
+ declare class WeavyClient {
7
+ uri: string;
8
+ tokenFactory: () => string | Promise<string>;
9
+ connection: _microsoft_signalr.HubConnection;
10
+ groups: string[];
11
+ connectionEvents: any[];
12
+ isConnectionStarted: any;
13
+ EVENT_NAMESPACE: string;
14
+ EVENT_CLOSE: string;
15
+ EVENT_RECONNECTING: string;
16
+ EVENT_RECONNECTED: string;
17
+ constructor(options: WeavyClientOptions);
18
+ subscribe(group: string, event: string, callback: any): Promise<void>;
19
+ unsubscribe(group: string, event: string, callback: any): Promise<void>;
20
+ triggerHandler(name: string, ...data: any): void;
21
+ }
22
+
23
+ declare const WeavyContext: React.Context<WeavyContextProps>;
24
+ declare type Props$2 = {
25
+ children: React.ReactNode;
26
+ client: WeavyClient;
27
+ options?: WeavyContextOptions;
28
+ };
29
+ declare const WeavyProvider: ({ children, client, options }: Props$2) => JSX.Element;
30
+
31
+ declare const MessengerContext: React.Context<MessengerContextProps>;
32
+ declare type Props$1 = {
33
+ children: React.ReactNode;
34
+ options?: MessengerContextOptions;
35
+ };
36
+ declare const MessengerProvider: ({ children, options }: Props$1) => JSX.Element;
37
+
38
+ declare const Messenger: FC<Messenger>;
39
+
40
+ declare const ConversationBadge: () => JSX.Element;
41
+
42
+ declare const ConversationList: () => JSX.Element;
43
+
44
+ interface ConversationProps {
45
+ id?: number | null;
46
+ showBackButton?: boolean;
47
+ }
48
+
49
+ declare const _default: React.MemoExoticComponent<({ id, showBackButton }: ConversationProps) => JSX.Element>;
50
+
51
+ interface ChatProps {
52
+ id: string;
53
+ }
54
+
55
+ declare const Chat: ({ id }: ChatProps) => JSX.Element;
56
+
57
+ declare const UIButton: {
58
+ UI: any;
59
+ };
60
+
61
+ declare type DropdownProps = {
62
+ directionX?: "left" | "right";
63
+ directionY?: "up" | "down";
64
+ children: React.ReactNode;
65
+ className?: string;
66
+ props?: React.HTMLAttributes<HTMLSpanElement>;
67
+ };
68
+ declare type ItemProps = {
69
+ children: React.ReactNode;
70
+ className?: string;
71
+ onClick?: (e: any) => void;
72
+ props?: React.HTMLAttributes<HTMLDivElement>;
73
+ };
74
+ declare const UIDropdown: {
75
+ UI: ({ directionX, directionY, children, className, ...props }: DropdownProps) => JSX.Element;
76
+ Item: ({ children, className, onClick, ...props }: ItemProps) => JSX.Element;
77
+ };
78
+
79
+ declare type Props = {
80
+ name: string;
81
+ color?: string;
82
+ size?: number;
83
+ };
84
+ declare const UIIcon: {
85
+ UI: ({ name, color, size, ...props }: Props) => JSX.Element;
86
+ };
87
+
88
+ declare type OverlayProps = {
89
+ children: React.ReactNode;
90
+ className?: string;
91
+ isOpen: boolean;
92
+ style?: Styles;
93
+ };
94
+ declare const UIOverlay: {
95
+ UI: ({ children, className, isOpen, style }: OverlayProps) => JSX.Element;
96
+ };
97
+
98
+ export { UIButton as Button, Chat, _default as Conversation, ConversationBadge, ConversationList, UIDropdown as Dropdown, UIIcon as Icon, Messenger, MessengerContext, MessengerProvider, UIOverlay as Overlay, WeavyClient, WeavyContext, WeavyProvider };
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@weavy/uikit-react",
3
+ "version": "11.0.0",
4
+ "author": "Weavy",
5
+ "description": "React UI-kit for Weavy",
6
+ "homepage": "https://github.com/weavy/weavy-uikit-react",
7
+ "license": "MIT",
8
+ "main": "dist/cjs/index.js",
9
+ "module": "dist/esm/index.js",
10
+ "types": "./dist/cjs/types/index.d.ts",
11
+ "devDependencies": {
12
+ "@rollup/plugin-commonjs": "^22.0.0",
13
+ "@rollup/plugin-node-resolve": "^13.1.3",
14
+ "@rollup/plugin-typescript": "^8.3.1",
15
+ "@types/lodash.debounce": "^4.0.7",
16
+ "@types/lodash.throttle": "^4.1.7",
17
+ "@types/react": "^18.0.8",
18
+ "@types/react-dom": "^18.0.3",
19
+ "@types/react-modal": "^3.13.1",
20
+ "rollup": "^2.72.0",
21
+ "rollup-plugin-delete": "^2.0.0",
22
+ "rollup-plugin-dts": "^4.2.1",
23
+ "rollup-plugin-peer-deps-external": "^2.2.4",
24
+ "rollup-plugin-terser": "^7.0.2",
25
+ "tslib": "^2.4.0",
26
+ "typescript": "^4.6.4"
27
+ },
28
+ "peerDependencies": {
29
+ "react": "^18.1.0",
30
+ "react-dom": "^18.1.0"
31
+ },
32
+ "scripts": {
33
+ "build": "rollup -c",
34
+ "watch": "rollup -c --watch"
35
+ },
36
+ "dependencies": {
37
+ "@mdi/react": "^1.6.0",
38
+ "@microsoft/signalr": "^6.0.3",
39
+ "classnames": "^2.3.1",
40
+ "dayjs": "^1.11.1",
41
+ "emoji-toolkit": "^6.6.0",
42
+ "lodash.debounce": "^4.0.8",
43
+ "lodash.throttle": "^4.1.1",
44
+ "react-modal": "^3.14.4",
45
+ "react-query": "^3.34.16"
46
+ }
47
+ }
@@ -0,0 +1,41 @@
1
+ import resolve from "@rollup/plugin-node-resolve";
2
+ import commonjs from "@rollup/plugin-commonjs";
3
+ import typescript from "@rollup/plugin-typescript";
4
+ import dts from "rollup-plugin-dts";
5
+ import { terser } from "rollup-plugin-terser";
6
+ import peerDepsExternal from 'rollup-plugin-peer-deps-external';
7
+ import del from 'rollup-plugin-delete';
8
+
9
+ const packageJson = require("./package.json");
10
+
11
+ export default [
12
+ {
13
+ input: "src/index.ts",
14
+ output: [
15
+ {
16
+ file: packageJson.main,
17
+ format: "cjs",
18
+ sourcemap: true,
19
+ },
20
+ {
21
+ file: packageJson.module,
22
+ format: "esm",
23
+ sourcemap: true,
24
+ },
25
+ ],
26
+ plugins: [
27
+ del({ targets: 'dist/*' }),
28
+ peerDepsExternal(),
29
+ resolve(),
30
+ commonjs(),
31
+ typescript({ tsconfig: "./tsconfig.json" }),
32
+ terser(),
33
+ ],
34
+ external: ["react", "react-dom"]
35
+ },
36
+ {
37
+ input: "dist/esm/types/index.d.ts",
38
+ output: [{ file: "dist/index.d.ts", format: "esm" }],
39
+ plugins: [dts()],
40
+ },
41
+ ];
@@ -0,0 +1,95 @@
1
+ import { HubConnectionBuilder, LogLevel } from '@microsoft/signalr';
2
+
3
+ export default class WeavyClient {
4
+ uri;
5
+ tokenFactory;
6
+ connection;
7
+ groups: string[];
8
+ connectionEvents: any[];
9
+ isConnectionStarted: any;
10
+
11
+ EVENT_NAMESPACE = ".connection";
12
+ EVENT_CLOSE = "close";
13
+ EVENT_RECONNECTING = "reconnecting";
14
+ EVENT_RECONNECTED = "reconnected";
15
+
16
+ constructor(options: WeavyClientOptions) {
17
+ this.uri = options.uri;
18
+ this.tokenFactory = options.tokenFactory
19
+ this.groups = [];
20
+ this.connectionEvents = [];
21
+
22
+ this.connection = new HubConnectionBuilder()
23
+ .configureLogging(LogLevel.None)
24
+ .withUrl(this.uri + "/hubs/rtm", {
25
+ accessTokenFactory: this.tokenFactory
26
+ })
27
+ .withAutomaticReconnect()
28
+ .build();
29
+
30
+ this.isConnectionStarted = this.connection.start();
31
+
32
+ this.connection.onclose(error => this.triggerHandler(this.EVENT_CLOSE, error));
33
+ this.connection.onreconnecting(error => this.triggerHandler(this.EVENT_RECONNECTING, error));
34
+ this.connection.onreconnected(connectionId => this.triggerHandler(this.EVENT_RECONNECTED, connectionId));
35
+
36
+ }
37
+
38
+
39
+ async subscribe(group: string, event: string, callback: any) {
40
+ await this.isConnectionStarted;
41
+
42
+ try {
43
+ var name = group ? group + ":" + event : event;
44
+ await this.connection.invoke("AddToGroup", name);
45
+ this.groups.push(name);
46
+ this.connection.on(name, callback);
47
+ } catch(err: any){
48
+ console.warn("Error in AddToGroup:", err)
49
+ }
50
+
51
+ }
52
+
53
+ async unsubscribe(group: string, event: string, callback: any) {
54
+ await this.isConnectionStarted;
55
+ var name = group ? group + ":" + event : event;
56
+
57
+ // get first occurence of group name and remove it
58
+ const index = this.groups.findIndex(e => e === name);
59
+ if(index !== -1){
60
+ this.groups = this.groups.splice(index, 1);
61
+
62
+ try {
63
+ // if no more groups, remove from server
64
+ if(!this.groups.find(e => e === name)){
65
+ await this.connection.invoke("RemoveFromGroup", name);
66
+ }
67
+
68
+ } catch(err: any){
69
+ console.warn("Error in RemoveFromGroup:", err)
70
+ }
71
+ }
72
+
73
+ this.connection.off(name, callback);
74
+ }
75
+
76
+ triggerHandler(name: string, ...data: any) {
77
+ name = name.endsWith(this.EVENT_NAMESPACE) ? name : name + this.EVENT_NAMESPACE;
78
+ let event = new CustomEvent(name, { cancelable: false });
79
+
80
+ console.debug("triggerHandler", name);
81
+
82
+ this.connectionEvents.forEach((eventHandler) => {
83
+ if (eventHandler.name === name) {
84
+ eventHandler.handler(event, ...data);
85
+ }
86
+ });
87
+
88
+ if (name === this.EVENT_RECONNECTED + this.EVENT_NAMESPACE) {
89
+ // re-add to signalr groups after reconnect
90
+ for (var i = 0; i < this.groups.length; i++) {
91
+ this.connection.invoke("AddToGroup", this.groups[i]);
92
+ }
93
+ }
94
+ }
95
+ }
@@ -0,0 +1,33 @@
1
+ import React from "react";
2
+ import Icon from "../ui/Icon";
3
+ import { fileSizeAsString, getIcon } from "../utils/fileUtilities";
4
+ import { prefix as wy } from "../utils/styles";
5
+
6
+ type Props = {
7
+ previewFormat: string,
8
+ url: string,
9
+ previewUrl: string,
10
+ mediaType: string,
11
+ name: string,
12
+ kind: string,
13
+ size: number,
14
+ provider: string
15
+ }
16
+
17
+ const Attachment = ({ previewFormat, url, previewUrl, mediaType, name, kind, size, provider }: Props) => {
18
+ let fileSize = size > 0 ? fileSizeAsString(size) : null;
19
+ let { icon, color } = getIcon(name, mediaType)
20
+ return (
21
+ <a href={previewUrl || url} className={wy('attachment')} target={"_blank"} title={name}>
22
+ <div className={wy('attachment-icon')} title={kind}><Icon.UI name={icon} color={color} size={2} /></div>
23
+ <div className={wy('attachment-content')}>
24
+ <div className={wy('attachment-title')}>{name}</div>
25
+ {fileSize &&
26
+ <div className={wy('attachment-meta')} title={fileSize}>{fileSize}</div>
27
+ }
28
+ </div>
29
+ </a>
30
+ );
31
+ }
32
+
33
+ export default Attachment;
@@ -0,0 +1,26 @@
1
+ import React from "react";
2
+ import classNames from 'classnames';
3
+ import Presence from "./Presence";
4
+ import { prefix as wy } from "../utils/styles";
5
+
6
+ type Props = {
7
+ id?: number,
8
+ name: string,
9
+ src: string
10
+ presence?: string,
11
+ size?: number,
12
+ className?: string
13
+ }
14
+
15
+ const Avatar = ({ id, src, name, presence, size = 48, className }: Props) => {
16
+ return (
17
+ <div className={classNames(wy('avatar-presence'), className)}>
18
+ <img alt="" title={name} className={wy('avatar')} height={size} width={size} src={src} />
19
+ {presence && id &&
20
+ <Presence id={id} status={presence} />
21
+ }
22
+ </div>
23
+ )
24
+ }
25
+
26
+ export default Avatar;
@@ -0,0 +1,68 @@
1
+ import React, { useContext, useEffect, useState } from 'react';
2
+ import { WeavyContext } from '../contexts/WeavyContext';
3
+ import { ChatProps } from '../types/Chat';
4
+ import useChat from '../hooks/useChat';
5
+ import Messages from './Messages';
6
+ import useMembers from '../hooks/useMembers';
7
+ import Typing from './Typing';
8
+ import useConversation from '../hooks/useConversation';
9
+ import { prefix as wy } from "../utils/styles";
10
+
11
+ const Chat = ({ id }: ChatProps) => {
12
+ const { client } = useContext(WeavyContext);
13
+ const [selectedId, setSelectedId] = useState<number | null>(null)
14
+
15
+ if (!client) {
16
+ throw new Error('Weavy Chat component must be used within an WeavyProvider');
17
+ }
18
+
19
+ const { isLoading: isLoadingChat, data: dataChat } = useChat(id, {});
20
+
21
+ const { isLoading: isLoadingMembers, data: dataMembers } = useMembers(selectedId, {
22
+ // The query will not execute until the activeConversation exists
23
+ enabled: selectedId != null
24
+ });
25
+
26
+ const { isLoading: isLoadingConversation, data: dataConversation } = useConversation(selectedId, {
27
+ // The query will not execute until the activeConversation exists
28
+ enabled: selectedId != null
29
+ });
30
+
31
+ useEffect(() => {
32
+ if (dataChat) {
33
+ setSelectedId(dataChat.id);
34
+ } else {
35
+ setSelectedId(null);
36
+ }
37
+ }, [dataChat]);
38
+
39
+ return (
40
+ <>
41
+ <header className={wy('appbars')}>
42
+ <nav className={wy('appbar')}>
43
+
44
+ {selectedId && dataConversation &&
45
+
46
+ <>
47
+ <div>
48
+ <Typing id={selectedId} context="conversation">
49
+ {dataConversation.display_name}
50
+ </Typing>
51
+ </div>
52
+ </>
53
+ }
54
+ </nav>
55
+ </header>
56
+
57
+ {!isLoadingChat && !dataChat &&
58
+ <div>No chat with the contextual id <strong>{id}</strong></div>
59
+ }
60
+
61
+ {selectedId && dataMembers &&
62
+ <Messages id={selectedId} members={dataMembers} />
63
+ }
64
+ </>
65
+ )
66
+ }
67
+
68
+ export default Chat;
@@ -0,0 +1,220 @@
1
+ import React, { useCallback, useContext, useEffect, useState } from 'react';
2
+ import { useQueryClient } from 'react-query';
3
+ import { MessengerContext } from '../contexts/MessengerContext';
4
+ import { WeavyContext } from '../contexts/WeavyContext';
5
+ import useMembers from '../hooks/useMembers';
6
+ import { ConversationProps } from '../types/Conversation';
7
+ import Typing from './Typing';
8
+ import Dropdown from '../ui/Dropdown';
9
+ import Icon from '../ui/Icon';
10
+ import Button from '../ui/Button';
11
+ import Overlay from '../ui/Overlay';
12
+ import SearchUsers from './SearchUsers';
13
+ import useMutateMembers from '../hooks/useMutateMembers';
14
+ import useConversation from '../hooks/useConversation';
15
+ import useMutateConversationName from '../hooks/useMutateConversationName';
16
+ import { prefix as wy } from "../utils/styles";
17
+ import useMutateRemoveMembers from '../hooks/useMutateRemoveMembers';
18
+ import Avatar from './Avatar';
19
+ import { UserContext } from '../contexts/UserContext';
20
+ import Messages from './Messages';
21
+
22
+ const Conversation = ({ id, showBackButton }: ConversationProps) => {
23
+
24
+
25
+ const queryClient = useQueryClient();
26
+ const { client } = useContext(WeavyContext);
27
+ const { selectedConversationId, setSelectedConversationId } = useContext(MessengerContext);
28
+ const { user } = useContext(UserContext);
29
+ const [modalAddOpen, setModalAddOpen] = useState(false);
30
+ const [modalDetailsOpen, setModalDetailsOpen] = useState(false);
31
+ const [title, setTitle] = useState<string>("");
32
+
33
+ const ChatRoom = "edb400ac-839b-45a7-b2a8-6a01820d1c44";
34
+
35
+ if (!client) {
36
+ throw new Error('Weavy Conversation component must be used within an WeavyProvider');
37
+ }
38
+
39
+ const { isLoading: isLoadingConversation, data: dataConversation } = useConversation(selectedConversationId, {
40
+ // The query will not execute until the activeConversation exists
41
+ enabled: selectedConversationId != null
42
+ });
43
+
44
+ const { isLoading: isLoadingMembers, data: dataMembers } = useMembers(selectedConversationId, {
45
+ // The query will not execute until the activeConversation exists
46
+ enabled: selectedConversationId != null
47
+ });
48
+
49
+ // react-query (mutation)
50
+
51
+ const addMembersMutation = useMutateMembers();
52
+ const updateNameMutation = useMutateConversationName();
53
+ const removeMembers = useMutateRemoveMembers();
54
+
55
+ const handleRealtimeAppUpdated = useCallback((data: ConversationType) => {
56
+ if (data.id !== selectedConversationId) return;
57
+ queryClient.invalidateQueries(['conversation', selectedConversationId]);
58
+ }, [selectedConversationId]);
59
+
60
+ const handleAdd = async (selected: UserType[]) => {
61
+
62
+ const membersList = selected.map((m) => m.id);
63
+ await addMembersMutation.mutateAsync({ id: selectedConversationId, members: membersList });
64
+ setModalAddOpen(false);
65
+ }
66
+
67
+ const toggleAddModal = (open: boolean) => {
68
+ setModalAddOpen(open);
69
+ }
70
+
71
+ const toggleDetailsModal = (open: boolean) => {
72
+ setModalDetailsOpen(open);
73
+ }
74
+
75
+ const handleUpdateTitle = (e: any) => {
76
+ setTitle(e.target.value);
77
+ updateNameMutation.mutate({ id: selectedConversationId, name: e.target.value });
78
+ }
79
+
80
+ const handleLeaveConversation = () => {
81
+ removeMembers.mutate({ id: selectedConversationId, members: [user.id] });
82
+ }
83
+
84
+ const handleBack = () => {
85
+ setSelectedConversationId(null);
86
+ }
87
+
88
+
89
+
90
+
91
+
92
+ // set selected conversation id if id is supplied to component
93
+ useEffect(() => {
94
+ if (id) {
95
+ setSelectedConversationId(id);
96
+ }
97
+ }, [id]);
98
+
99
+ useEffect(() => {
100
+
101
+ if (selectedConversationId) {
102
+ client.subscribe(`a${selectedConversationId}`, "app-updated", handleRealtimeAppUpdated);
103
+ }
104
+
105
+ return () => {
106
+
107
+ if (selectedConversationId) {
108
+
109
+ client.unsubscribe(`a${selectedConversationId}`, "app-updated", handleRealtimeAppUpdated);
110
+ }
111
+ }
112
+ }, [selectedConversationId]);
113
+
114
+ useEffect(() => {
115
+ if (dataConversation && dataConversation.type === ChatRoom) {
116
+ setTitle(dataConversation?.display_name);
117
+ }
118
+ }, [dataConversation]);
119
+
120
+
121
+
122
+
123
+ return (
124
+ <>
125
+ <header className={wy('appbars')}>
126
+ <nav className={wy('appbar')}>
127
+ <div>
128
+ {showBackButton &&
129
+ <Button.UI onClick={handleBack}><Icon.UI name="back" /></Button.UI>
130
+ }</div>
131
+ {selectedConversationId && dataConversation &&
132
+
133
+ <>
134
+ <div>
135
+ <Typing id={selectedConversationId} context="conversation">
136
+ {dataConversation.display_name}
137
+ </Typing>
138
+ </div>
139
+ <Dropdown.UI directionX='left'>
140
+
141
+ <Dropdown.Item onClick={() => toggleDetailsModal(true)}>Details</Dropdown.Item>
142
+
143
+ {dataConversation.type === ChatRoom &&
144
+ <>
145
+ <Dropdown.Item onClick={() => toggleAddModal(true)}>Add people</Dropdown.Item>
146
+ <Dropdown.Item onClick={handleLeaveConversation}>Leave conversation</Dropdown.Item>
147
+ </>
148
+ }
149
+
150
+ </Dropdown.UI>
151
+ </>
152
+ }
153
+ </nav>
154
+ </header>
155
+
156
+ {!selectedConversationId &&
157
+ <div className={wy('avatar-header')}>
158
+ <Avatar src={user.avatar_url} name={user.title} presence={user.presence} id={user.id} size={256} />
159
+ <h2>Welcome {user.name}!</h2>
160
+ Select a conversation to get started
161
+ </div>
162
+ }
163
+ {selectedConversationId && dataMembers &&
164
+ <Messages id={selectedConversationId} members={dataMembers} displayName={dataConversation?.display_name} avatarUrl={dataConversation?.avatar_url} />
165
+ }
166
+
167
+ <Overlay.UI isOpen={modalAddOpen} className={wy('modal')}>
168
+ <header className={wy('appbars')}>
169
+ <nav className={wy('appbar')}>
170
+ <Button.UI onClick={() => toggleAddModal(false)}><Icon.UI name='close' /></Button.UI>
171
+ <div className={wy('appbar-text')}>Add people</div>
172
+ </nav>
173
+ </header>
174
+ <SearchUsers handleSubmit={handleAdd} buttonTitle="Add selected" />
175
+ </Overlay.UI>
176
+
177
+ <Overlay.UI isOpen={modalDetailsOpen} className={wy('modal')}>
178
+ <header className={wy('appbars')}>
179
+ <nav className={wy('appbar')}>
180
+ <Button.UI onClick={() => toggleDetailsModal(false)}><Icon.UI name='close' /></Button.UI>
181
+ <div className={wy('appbar-text')}>Conversation details</div>
182
+ </nav>
183
+ </header>
184
+ <div>
185
+ {dataConversation && <div className={wy('avatar-header')}><Avatar src={dataConversation?.avatar_url} name={title} size={128} /></div>}
186
+ {dataConversation?.type !== ChatRoom &&
187
+ <h4 className={wy('avatar-display-name')}>{dataConversation?.display_name}</h4>
188
+ }
189
+
190
+ {dataConversation?.type === ChatRoom && (
191
+ <>
192
+ <div className={wy('pane-group')}>
193
+ <input className={wy('input')} value={title} onChange={(e) => handleUpdateTitle(e)} />
194
+ </div>
195
+ <div className={wy('pane-group')}>
196
+ <table className={wy('search-result-table')}>
197
+ <tbody>
198
+ {dataMembers?.data.map((m: MemberType) => {
199
+ return (
200
+ <tr key={m.id} className={wy('search-result-table-checkbox')}>
201
+ <td className={wy('search-result-table-icon')}><Avatar src={m.avatar_url} name={m.display_name} id={m.id} size={24} presence={m.presence} /></td>
202
+ <td>{m.display_name}</td>
203
+ <td></td>
204
+ </tr>
205
+ )
206
+ })}
207
+ </tbody>
208
+ </table>
209
+ </div>
210
+ </>
211
+ )}
212
+ </div>
213
+ </Overlay.UI>
214
+
215
+
216
+ </>
217
+ )
218
+ }
219
+
220
+ export default React.memo(Conversation);