@weavy/uikit-react 11.2.0 → 12.1.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 (205) hide show
  1. package/.github/workflows/publish.yml +1 -1
  2. package/changelog.md +15 -0
  3. package/dist/cjs/index.js +6 -6
  4. package/dist/cjs/index.js.map +1 -1
  5. package/dist/cjs/types/components/Image.d.ts +2 -0
  6. package/dist/cjs/types/components/PdfViewer.d.ts +6 -0
  7. package/dist/cjs/types/components/Preview.d.ts +58 -0
  8. package/dist/cjs/types/types/types.d.ts +1 -0
  9. package/dist/cjs/types/utils/fileUtilities.d.ts +16 -1
  10. package/dist/css/weavy-chat.css +2684 -0
  11. package/dist/css/weavy-messenger.css +3039 -0
  12. package/dist/css/weavy.css +3039 -0
  13. package/dist/esm/index.js +6 -6
  14. package/dist/esm/index.js.map +1 -1
  15. package/dist/esm/types/components/Image.d.ts +2 -0
  16. package/dist/esm/types/components/PdfViewer.d.ts +6 -0
  17. package/dist/esm/types/components/Preview.d.ts +58 -0
  18. package/dist/esm/types/types/types.d.ts +1 -0
  19. package/dist/esm/types/utils/fileUtilities.d.ts +16 -1
  20. package/package.json +14 -4
  21. package/rollup.config.js +0 -2
  22. package/src/components/Attachment.tsx +5 -6
  23. package/src/components/Avatar.tsx +2 -3
  24. package/src/components/Chat.tsx +3 -4
  25. package/src/components/Conversation.tsx +20 -29
  26. package/src/components/ConversationBadge.tsx +1 -2
  27. package/src/components/ConversationForm.tsx +11 -18
  28. package/src/components/ConversationList.tsx +4 -5
  29. package/src/components/ConversationListItem.tsx +11 -13
  30. package/src/components/FileBrowser.tsx +1 -2
  31. package/src/components/Image.tsx +39 -7
  32. package/src/components/MeetingCard.tsx +7 -8
  33. package/src/components/Message.tsx +12 -13
  34. package/src/components/Messages.tsx +6 -7
  35. package/src/components/Messenger.tsx +3 -4
  36. package/src/components/NewConversation.tsx +5 -7
  37. package/src/components/PdfViewer.tsx +271 -0
  38. package/src/components/Presence.tsx +2 -2
  39. package/src/components/Preview.tsx +294 -0
  40. package/src/components/Reactions.tsx +6 -7
  41. package/src/components/SearchUsers.tsx +17 -16
  42. package/src/components/SeenBy.tsx +1 -2
  43. package/src/contexts/PreviewContext.tsx +4 -6
  44. package/src/hooks/useConversation.ts +0 -1
  45. package/src/hooks/usePresence.ts +4 -5
  46. package/src/hooks/useReactions.ts +0 -1
  47. package/src/scss/theme/_alert.scss +73 -0
  48. package/src/scss/theme/_appbar.scss +112 -0
  49. package/src/scss/theme/_attachments.scss +74 -0
  50. package/src/scss/theme/_avatar.scss +54 -0
  51. package/src/scss/theme/_badge.scss +47 -0
  52. package/src/scss/theme/_buttons.scss +96 -0
  53. package/src/scss/theme/_card.scss +7 -0
  54. package/src/scss/theme/_checkbox.scss +56 -0
  55. package/src/scss/theme/_cm-editor.scss +42 -0
  56. package/src/scss/theme/_code.scss +115 -0
  57. package/src/scss/theme/_colors.scss +520 -0
  58. package/src/scss/theme/_config.scss +6 -0
  59. package/src/scss/theme/_content.scss +15 -0
  60. package/src/scss/theme/_conversations.scss +91 -0
  61. package/src/scss/theme/_dropdown.scss +86 -0
  62. package/src/scss/theme/_emoji.scss +5 -0
  63. package/src/scss/theme/_filebrowser.scss +26 -0
  64. package/src/scss/theme/_files.scss +140 -0
  65. package/src/scss/theme/_icons.scss +62 -0
  66. package/src/scss/theme/_image-grid.scss +63 -0
  67. package/src/scss/theme/_inputs.scss +28 -0
  68. package/src/scss/theme/_message-editor.scss +90 -0
  69. package/src/scss/theme/_messages.scss +238 -0
  70. package/src/scss/theme/_nav.scss +52 -0
  71. package/src/scss/theme/_overlays.scss +157 -0
  72. package/src/scss/theme/_pager.scss +19 -0
  73. package/src/scss/theme/_palette.scss +165 -0
  74. package/src/scss/theme/_pane.scss +16 -0
  75. package/src/scss/theme/_panels.scss +137 -0
  76. package/src/scss/theme/_picker-list.scss +37 -0
  77. package/src/scss/theme/_preview-embed.scss +38 -0
  78. package/src/scss/theme/_preview-html.scss +7 -0
  79. package/src/scss/theme/_preview-icon.scss +41 -0
  80. package/src/scss/theme/_preview-image.scss +86 -0
  81. package/src/scss/theme/_preview-media.scss +28 -0
  82. package/src/scss/theme/_preview-pdf.scss +838 -0
  83. package/src/scss/theme/_preview-text.scss +5 -0
  84. package/src/scss/theme/_preview.scss +105 -0
  85. package/src/scss/theme/_reactions.scss +58 -0
  86. package/src/scss/theme/_reboot.scss +41 -0
  87. package/src/scss/theme/_root.scss +2 -0
  88. package/src/scss/theme/_scroll.scss +55 -0
  89. package/src/scss/theme/_search.scss +68 -0
  90. package/src/scss/theme/_spinner.scss +63 -0
  91. package/src/scss/theme/_tables.scss +53 -0
  92. package/src/scss/theme/_toasts.scss +47 -0
  93. package/src/scss/theme/_turbo.scss +17 -0
  94. package/src/scss/theme/_typing.scss +26 -0
  95. package/src/scss/theme/_variables.scss +139 -0
  96. package/src/scss/theme/bootstrap/_accordion.scss +146 -0
  97. package/src/scss/theme/bootstrap/_alert.scss +71 -0
  98. package/src/scss/theme/bootstrap/_badge.scss +38 -0
  99. package/src/scss/theme/bootstrap/_breadcrumb.scss +40 -0
  100. package/src/scss/theme/bootstrap/_button-group.scss +142 -0
  101. package/src/scss/theme/bootstrap/_buttons.scss +186 -0
  102. package/src/scss/theme/bootstrap/_card.scss +234 -0
  103. package/src/scss/theme/bootstrap/_carousel.scss +229 -0
  104. package/src/scss/theme/bootstrap/_close.scss +40 -0
  105. package/src/scss/theme/bootstrap/_containers.scss +41 -0
  106. package/src/scss/theme/bootstrap/_dropdown.scss +248 -0
  107. package/src/scss/theme/bootstrap/_forms.scss +9 -0
  108. package/src/scss/theme/bootstrap/_functions.scss +302 -0
  109. package/src/scss/theme/bootstrap/_grid.scss +33 -0
  110. package/src/scss/theme/bootstrap/_helpers.scss +10 -0
  111. package/src/scss/theme/bootstrap/_images.scss +42 -0
  112. package/src/scss/theme/bootstrap/_list-group.scss +191 -0
  113. package/src/scss/theme/bootstrap/_maps.scss +54 -0
  114. package/src/scss/theme/bootstrap/_mixins.scss +43 -0
  115. package/src/scss/theme/bootstrap/_modal.scss +237 -0
  116. package/src/scss/theme/bootstrap/_nav.scss +172 -0
  117. package/src/scss/theme/bootstrap/_navbar.scss +276 -0
  118. package/src/scss/theme/bootstrap/_offcanvas.scss +143 -0
  119. package/src/scss/theme/bootstrap/_pagination.scss +109 -0
  120. package/src/scss/theme/bootstrap/_placeholders.scss +51 -0
  121. package/src/scss/theme/bootstrap/_popover.scss +196 -0
  122. package/src/scss/theme/bootstrap/_progress.scss +59 -0
  123. package/src/scss/theme/bootstrap/_reboot.scss +610 -0
  124. package/src/scss/theme/bootstrap/_root.scss +73 -0
  125. package/src/scss/theme/bootstrap/_spinners.scss +85 -0
  126. package/src/scss/theme/bootstrap/_tables.scss +164 -0
  127. package/src/scss/theme/bootstrap/_toasts.scss +70 -0
  128. package/src/scss/theme/bootstrap/_tooltip.scss +120 -0
  129. package/src/scss/theme/bootstrap/_transitions.scss +27 -0
  130. package/src/scss/theme/bootstrap/_type.scss +106 -0
  131. package/src/scss/theme/bootstrap/_utilities.scss +647 -0
  132. package/src/scss/theme/bootstrap/_variables.scss +1633 -0
  133. package/src/scss/theme/bootstrap/forms/_floating-labels.scss +74 -0
  134. package/src/scss/theme/bootstrap/forms/_form-check.scss +175 -0
  135. package/src/scss/theme/bootstrap/forms/_form-control.scss +194 -0
  136. package/src/scss/theme/bootstrap/forms/_form-range.scss +91 -0
  137. package/src/scss/theme/bootstrap/forms/_form-select.scss +71 -0
  138. package/src/scss/theme/bootstrap/forms/_form-text.scss +11 -0
  139. package/src/scss/theme/bootstrap/forms/_input-group.scss +129 -0
  140. package/src/scss/theme/bootstrap/forms/_labels.scss +36 -0
  141. package/src/scss/theme/bootstrap/forms/_validation.scss +12 -0
  142. package/src/scss/theme/bootstrap/helpers/_clearfix.scss +3 -0
  143. package/src/scss/theme/bootstrap/helpers/_color-bg.scss +10 -0
  144. package/src/scss/theme/bootstrap/helpers/_colored-links.scss +12 -0
  145. package/src/scss/theme/bootstrap/helpers/_position.scss +36 -0
  146. package/src/scss/theme/bootstrap/helpers/_ratio.scss +26 -0
  147. package/src/scss/theme/bootstrap/helpers/_stacks.scss +15 -0
  148. package/src/scss/theme/bootstrap/helpers/_stretched-link.scss +15 -0
  149. package/src/scss/theme/bootstrap/helpers/_text-truncation.scss +7 -0
  150. package/src/scss/theme/bootstrap/helpers/_visually-hidden.scss +8 -0
  151. package/src/scss/theme/bootstrap/helpers/_vr.scss +8 -0
  152. package/src/scss/theme/bootstrap/mixins/_alert.scss +15 -0
  153. package/src/scss/theme/bootstrap/mixins/_backdrop.scss +14 -0
  154. package/src/scss/theme/bootstrap/mixins/_banner.scss +9 -0
  155. package/src/scss/theme/bootstrap/mixins/_border-radius.scss +78 -0
  156. package/src/scss/theme/bootstrap/mixins/_box-shadow.scss +18 -0
  157. package/src/scss/theme/bootstrap/mixins/_breakpoints.scss +127 -0
  158. package/src/scss/theme/bootstrap/mixins/_buttons.scss +70 -0
  159. package/src/scss/theme/bootstrap/mixins/_caret.scss +64 -0
  160. package/src/scss/theme/bootstrap/mixins/_clearfix.scss +9 -0
  161. package/src/scss/theme/bootstrap/mixins/_color-scheme.scss +7 -0
  162. package/src/scss/theme/bootstrap/mixins/_container.scss +11 -0
  163. package/src/scss/theme/bootstrap/mixins/_deprecate.scss +10 -0
  164. package/src/scss/theme/bootstrap/mixins/_forms.scss +152 -0
  165. package/src/scss/theme/bootstrap/mixins/_gradients.scss +47 -0
  166. package/src/scss/theme/bootstrap/mixins/_grid.scss +151 -0
  167. package/src/scss/theme/bootstrap/mixins/_image.scss +16 -0
  168. package/src/scss/theme/bootstrap/mixins/_list-group.scss +24 -0
  169. package/src/scss/theme/bootstrap/mixins/_lists.scss +7 -0
  170. package/src/scss/theme/bootstrap/mixins/_pagination.scss +10 -0
  171. package/src/scss/theme/bootstrap/mixins/_reset-text.scss +17 -0
  172. package/src/scss/theme/bootstrap/mixins/_resize.scss +6 -0
  173. package/src/scss/theme/bootstrap/mixins/_table-variants.scss +24 -0
  174. package/src/scss/theme/bootstrap/mixins/_text-truncate.scss +8 -0
  175. package/src/scss/theme/bootstrap/mixins/_transition.scss +26 -0
  176. package/src/scss/theme/bootstrap/mixins/_utilities.scss +97 -0
  177. package/src/scss/theme/bootstrap/mixins/_visually-hidden.scss +29 -0
  178. package/src/scss/theme/bootstrap/utilities/_api.scss +47 -0
  179. package/src/scss/theme/bootstrap/vendor/_rfs.scss +354 -0
  180. package/src/scss/theme/bs/_badge.scss +20 -0
  181. package/src/scss/theme/bs/_buttons.scss +185 -0
  182. package/src/scss/theme/bs/_dropdown.scss +86 -0
  183. package/src/scss/theme/bs/_forms.scss +161 -0
  184. package/src/scss/theme/bs/_list-group.scss +73 -0
  185. package/src/scss/theme/bs/_tables.scss +46 -0
  186. package/src/scss/theme/fonts/_fontmapping-roboto.scss +129 -0
  187. package/src/scss/theme/fonts/_fontmapping-segoe-ui.scss +127 -0
  188. package/src/scss/theme/fonts/_index.scss +2 -0
  189. package/src/scss/theme/mixins/_backdrop.scss +13 -0
  190. package/src/scss/theme/mixins/_palette.scss +165 -0
  191. package/src/scss/theme/mixins/_position.scss +33 -0
  192. package/src/scss/theme/mixins/_scrollbar.scss +110 -0
  193. package/src/scss/weavy-chat.scss +31 -0
  194. package/src/scss/weavy-messenger.scss +60 -0
  195. package/src/scss/weavy.scss +2 -0
  196. package/src/types/types.ts +2 -0
  197. package/src/ui/Button.tsx +3 -4
  198. package/src/ui/Dropdown.tsx +4 -5
  199. package/src/ui/Icon.tsx +75 -39
  200. package/src/ui/Overlay.tsx +2 -3
  201. package/src/utils/fileUtilities.ts +280 -72
  202. package/src/utils/scrollbarDetection.js +5 -7
  203. package/dist/cjs/types/utils/styles.d.ts +0 -17
  204. package/dist/esm/types/utils/styles.d.ts +0 -17
  205. package/src/utils/styles.ts +0 -57
@@ -1,5 +1,4 @@
1
- import React, { useState } from "react";
2
- import { prefix as wy } from "../utils/styles";
1
+ import React, { useCallback } from "react";
3
2
 
4
3
  type ImageProps = {
5
4
  src: string,
@@ -10,6 +9,33 @@ type ImageProps = {
10
9
  onClick: (e: any) => void
11
10
  }
12
11
 
12
+ export function checkImageLoad(img: HTMLImageElement) {
13
+ var isLoaded = img.complete && img.naturalHeight !== 0;
14
+ if (isLoaded) {
15
+ if (!img.classList.contains("wy-loading")) {
16
+ console.debug("image is instantly loaded")
17
+ img.classList.add("wy-loading", "wy-loaded");
18
+ } else {
19
+ img.decode().then(() => {
20
+ console.debug("image is loaded after delay")
21
+ img.classList.add("wy-loaded");
22
+ })
23
+ }
24
+
25
+
26
+ } else {
27
+ console.debug("image is loading")
28
+ img.classList.add("wy-loading");
29
+ }
30
+ }
31
+
32
+ export function imageLoaded(event: any) {
33
+ var img = event.target;
34
+ if (img.tagName === 'IMG' && img.classList.contains("wy-loading") && !img.classList.contains("wy-loaded")) {
35
+ console.debug("load event"); img.classList.add("wy-loaded")
36
+ }
37
+ }
38
+
13
39
  export const Image = ({src, previewSrc, width, height, more, onClick}: ImageProps) => {
14
40
  let ratio = width / height;
15
41
  let baseSize = 64;
@@ -20,17 +46,23 @@ export const Image = ({src, previewSrc, width, height, more, onClick}: ImageProp
20
46
  let intrinsicWidth = width + "px"
21
47
  let maxWidth = (maxScale * width) + "px";
22
48
 
49
+ const imageRef = useCallback((element: HTMLImageElement) => {
50
+ if (element) {
51
+ checkImageLoad(element);
52
+ }
53
+ }, [])
54
+
23
55
  return (
24
- <a href={src} className={wy('image')} onClick={(e) => onClick(e)} style={{
56
+ <a href={src} className="wy-image" onClick={(e) => onClick(e)} style={{
25
57
  flexBasis: flexBasis,
26
58
  flexGrow: flexRatio,
27
59
  flexShrink: flexRatio,
28
60
  width: intrinsicWidth,
29
61
  maxWidth: maxWidth
30
62
  }}>
31
- <div className={wy('image-area')} style={{ paddingBottom: padding}}>
32
- <img src={previewSrc} alt="" loading="lazy" decoding="async" />
33
- {!!more && <span className={wy('more')}>+{more}</span>}
63
+ <div className="wy-image-area" style={{ paddingBottom: padding }}>
64
+ <img ref={imageRef} src={previewSrc} onLoad={imageLoaded} alt="" loading="lazy" decoding="async" />
65
+ {!!more && <span className="wy-more">+{more}</span>}
34
66
  </div>
35
67
  </a>
36
68
  );
@@ -57,7 +89,7 @@ export const ImageGrid = ({ children, limit = 3}: ImageGridProps) => {
57
89
  }
58
90
 
59
91
  return (
60
- <div className={wy('image-grid')}>
92
+ <div className="wy-image-grid">
61
93
  {firstImages}
62
94
  </div>
63
95
  );
@@ -1,7 +1,6 @@
1
1
  import React from "react";
2
2
  import Button from '../ui/Button';
3
3
  import Icon from '../ui/Icon';
4
- import { prefix as wy } from "../utils/styles";
5
4
 
6
5
  type Props = {
7
6
  meeting: MeetingCardType
@@ -14,13 +13,13 @@ const MeetingCard = ({ meeting }: Props) => {
14
13
  }
15
14
 
16
15
  return (
17
- <div className={wy('attachments')}>
18
- <a className={wy('attachment')} href={meeting.join_url} target="_blank">
19
- <div className={wy('attachment-icon')} title="Zoom meeting"><Icon.UI name="zoom" color="#4a8cff" size={4} /></div>
20
- <div className={wy('attachment-content')}>
21
- <div className={wy('attachment-title')}>Zoom meeting</div>
22
- <div className={wy('attachment-meta')}>Meeting ID: {`${meeting.provider_id.substring(0,3)}-${meeting.provider_id.substring(3,6)}-${meeting.provider_id.substring(6)}`}</div>
23
- <Button.UI className={wy('button-primary')}>Join meeting</Button.UI>
16
+ <div className="wy-attachments">
17
+ <a className="wy-attachment" href={meeting.join_url} target="_blank">
18
+ <div className="wy-attachment-icon" title="Zoom meeting"><Icon.UI name="zoom" color="#4a8cff" size={4} /></div>
19
+ <div className="wy-attachment-content">
20
+ <div className="wy-attachment-title">Zoom meeting</div>
21
+ <div className="wy-attachment-meta">Meeting ID: {`${meeting.provider_id.substring(0,3)}-${meeting.provider_id.substring(3,6)}-${meeting.provider_id.substring(6)}`}</div>
22
+ <Button.UI className="wy-button-primary">Join meeting</Button.UI>
24
23
  </div>
25
24
  </a>
26
25
  </div>
@@ -9,13 +9,12 @@ import SeenBy from './SeenBy';
9
9
  import Avatar from "./Avatar";
10
10
  import MeetingCard from './MeetingCard';
11
11
  import usePreview from '../hooks/usePreview';
12
- import { prefix as wy } from "../utils/styles";
12
+ import classNames from 'classnames';
13
13
 
14
14
  const Message: FC<MessageProps> = ({ id, html, temp, me, avatar, name, created_at, attachments, meeting, parentId, reactions, seenBy }) => {
15
15
 
16
16
  const { open, close } = usePreview(attachments);
17
17
 
18
- var messageClassName = wy("message" + (me ? " message-me" : ""));
19
18
  var images = attachments?.filter((a: AttachmentType) => a.kind === "image" && a.thumbnail_url);
20
19
  var files = attachments?.filter((a: AttachmentType) => a.kind !== "image" || !a.thumbnail_url);
21
20
 
@@ -28,20 +27,20 @@ const Message: FC<MessageProps> = ({ id, html, temp, me, avatar, name, created_a
28
27
 
29
28
  return (
30
29
  <>
31
- <div className={messageClassName}>
30
+ <div className={classNames("wy-message", { "wy-message-me": me })}>
32
31
  {!me && (
33
- <div className={wy('message-author')}>
32
+ <div className="wy-message-author">
34
33
  {avatar && <Avatar src={avatar} size={32} name={name} />}
35
34
  </div>
36
35
  )}
37
- <div className={wy('message-content')}>
38
- <div className={wy('message-meta')}>
36
+ <div className="wy-message-content">
37
+ <div className="wy-message-meta">
39
38
  <time dateTime={created_at} title={date.format('LLLL')}>{date.fromNow()}</time>
40
39
  </div>
41
- <div className={wy('message-content-row')}>
42
- <div className={wy('message-bubble')}>
40
+ <div className="wy-message-content-row">
41
+ <div className="wy-message-bubble">
43
42
  {temp &&
44
- <div className={wy('message-text')}>{html}</div>
43
+ <div className="wy-message-text">{html}</div>
45
44
  }
46
45
  {!temp &&
47
46
  <>
@@ -51,13 +50,13 @@ const Message: FC<MessageProps> = ({ id, html, temp, me, avatar, name, created_a
51
50
  )}
52
51
  </ImageGrid>}
53
52
 
54
- {html && <div className={wy('message-text')} dangerouslySetInnerHTML={{ __html: joypixels.shortnameToUnicode(html || "") }}></div>}
53
+ {html && <div className="wy-message-text" dangerouslySetInnerHTML={{ __html: joypixels.shortnameToUnicode(html || "") }}></div>}
55
54
 
56
55
  {meeting &&
57
56
  <MeetingCard meeting={meeting} />
58
57
  }
59
58
 
60
- {files && !!files.length && <div className={wy('attachments')}>
59
+ {files && !!files.length && <div className="wy-attachments">
61
60
  {files.map((a: AttachmentType) =>
62
61
  <Attachment key={a.id} name={a.name} previewFormat={a.kind} provider={a.provider} url={a.download_url} previewUrl={a.provider ? a.external_url : a.preview_url} mediaType={a.media_type} kind={a.kind} size={a.size} />
63
62
  )}
@@ -66,13 +65,13 @@ const Message: FC<MessageProps> = ({ id, html, temp, me, avatar, name, created_a
66
65
 
67
66
  }
68
67
  </div>
69
- <div className={wy('message-buttons')}>
68
+ <div className="wy-message-buttons">
70
69
  {!temp && <ReactionsMenu id={id} reactions={reactions} />}
71
70
  </div>
72
71
  </div>
73
72
 
74
73
  {!temp && (
75
- <div className={wy('reactions')}>
74
+ <div className="wy-reactions">
76
75
  <ReactionsList id={id} parentId={parentId} reactions={reactions} />
77
76
  </div>
78
77
  )}
@@ -11,7 +11,6 @@ import useMutateRead from '../hooks/useMutateRead';
11
11
  import useMutateMessage from '../hooks/useMutateMessage';
12
12
  import { useQueryClient } from 'react-query';
13
13
  import { WeavyContext } from '../contexts/WeavyContext';
14
- import { prefix as wy } from "../utils/styles";
15
14
  import Avatar from './Avatar';
16
15
 
17
16
  type Props = {
@@ -198,16 +197,16 @@ const Messages = ({ id, members, displayName, avatarUrl }: Props) => {
198
197
  readMessageMutation.mutate({ id: id, read: true })
199
198
  }, [id]);
200
199
 
201
- let messageHeader = <div className={wy('avatar-header')}>
200
+ let messageHeader = <div className="wy-avatar-header">
202
201
  {avatarUrl && displayName && <Avatar src={avatarUrl} name={displayName} id={id} size={128} /> || ''}
203
- {displayName && <div className={wy('avatar-display-name')}>{displayName}</div> || ''}
202
+ {displayName && <div className="wy-avatar-display-name">{displayName}</div> || ''}
204
203
  </div>;
205
204
 
206
- let loadMoreButton = <Button.UI onClick={() => fetchNextPage()} disabled={!hasNextPage || isFetchingNextPage} className={wy('message-readmore')}>Load more</Button.UI>;
205
+ let loadMoreButton = <Button.UI onClick={() => fetchNextPage()} disabled={!hasNextPage || isFetchingNextPage} className="wy-message-readmore">Load more</Button.UI>;
207
206
 
208
207
  let messages = (
209
208
  <>
210
- <div className={wy('message-readmore')} ref={readMoreRef}>
209
+ <div className="wy-message-readmore" ref={readMoreRef}>
211
210
  {isFetchingNextPage
212
211
  ? 'Loading more...'
213
212
  : hasNextPage
@@ -258,10 +257,10 @@ const Messages = ({ id, members, displayName, avatarUrl }: Props) => {
258
257
 
259
258
  return (
260
259
  <>
261
- <div id="container" className={wy('messages')}>
260
+ <div id="container" className="wy-messages">
262
261
  {messages}
263
262
  </div>
264
- <div className={wy('message-editor')}>
263
+ <div className="wy-message-editor">
265
264
  <ConversationForm key={id} conversationId={id} handleInsert={handleNewMessage} />
266
265
  </div>
267
266
  </>
@@ -4,7 +4,6 @@ import Conversation from './Conversation';
4
4
  import ConversationList from './ConversationList';
5
5
  import { Messenger } from '../types/Messenger';
6
6
  import { WeavyContext } from '../contexts/WeavyContext';
7
- import { prefix as wy } from "../utils/styles";
8
7
 
9
8
  const Messenger: FC<Messenger> = () => {
10
9
 
@@ -16,13 +15,13 @@ const Messenger: FC<Messenger> = () => {
16
15
 
17
16
  return (
18
17
  <MessengerProvider>
19
- <div className={wy('messenger-provider')}>
18
+ <div className="wy-messenger-provider">
20
19
 
21
- <div className={wy('messenger-sidebar scroll-y')}>
20
+ <div className="wy-messenger-sidebar wy-scroll-y">
22
21
  <ConversationList />
23
22
  </div>
24
23
 
25
- <div className={wy('messenger-conversation scroll-y')}>
24
+ <div className="wy-messenger-conversation wy-scroll-y">
26
25
  <Conversation id={null} />
27
26
  </div>
28
27
  </div>
@@ -4,7 +4,6 @@ import Icon from '../ui/Icon';
4
4
  import Overlay from '../ui/Overlay';
5
5
  import Button from '../ui/Button';
6
6
  import SearchUsers from './SearchUsers';
7
- import { prefix as wy } from "../utils/styles";
8
7
 
9
8
  const NewConversation = () => {
10
9
  const [modalOpen, setModalOpen] = useState(false);
@@ -27,18 +26,17 @@ const NewConversation = () => {
27
26
 
28
27
  return (
29
28
  <>
30
-
31
29
  <Button.UI onClick={handleOpen}><Icon.UI name="plus" /></Button.UI>
32
30
 
33
- <Overlay.UI isOpen={modalOpen} className={wy('modal')}>
34
- <header className={wy('appbars')}>
35
- <nav className={wy('appbar')}>
31
+ <Overlay.UI isOpen={modalOpen} className="wy-modal">
32
+ <header className="wy-appbars">
33
+ <nav className="wy-appbar">
36
34
  <Button.UI onClick={handleClose}><Icon.UI name='close' /></Button.UI>
37
- <div className={wy('appbar-text')}>Create conversation</div>
35
+ <div className="wy-appbar-text">Create conversation</div>
38
36
  </nav>
39
37
  </header>
40
38
 
41
- <SearchUsers handleSubmit={handleCreate} buttonTitle="Create conversation"/>
39
+ <SearchUsers handleSubmit={handleCreate} buttonTitle="Next"/>
42
40
  </Overlay.UI>
43
41
  </>
44
42
 
@@ -0,0 +1,271 @@
1
+ import React, { useEffect, useRef, useCallback, useState } from "react";
2
+ import pdfjsLib from 'pdfjs-dist';
3
+ import pdfjsViewer from 'pdfjs-dist/web/pdf_viewer';
4
+ import Icon from "../ui/Icon";
5
+
6
+ type Props = {
7
+ src: string
8
+ }
9
+
10
+ const PdfViewer = ({ src }: Props) => {
11
+ //const viewerRef = useRef(null);
12
+ const pageNumberRef = useRef<HTMLInputElement>(null);
13
+ const totalPagesRef = useRef<HTMLSpanElement>(null);
14
+ const zoomLevelRef = useRef<HTMLInputElement>(null);
15
+
16
+ const [pdfEventBus, setPdfEventBus] = useState<pdfjsViewer.EventBus>();
17
+
18
+ const [pdfViewer, setPdfViewer] = useState<pdfjsViewer.PDFViewer>();
19
+ const [pdfLinkService, setPdfLinkService] = useState<pdfjsViewer.PDFLinkService>();
20
+ const [pdfFindController, setPdfFindController] = useState<pdfjsViewer.PDFFindController>();
21
+
22
+ const DEFAULT_SCALE_DELTA = 1.1;
23
+ const MAX_SCALE = 3.0;
24
+ const MIN_SCALE = 0.2;
25
+
26
+ const SEARCH_FOR = "";
27
+ const ENABLE_XFA = true;
28
+
29
+ // Some PDFs need external cmaps.
30
+ const CMAP_URL = "/cmaps/";
31
+ const CMAP_PACKED = true;
32
+
33
+ // Setting worker path to worker bundle.
34
+ pdfjsLib.GlobalWorkerOptions.workerSrc = "/js/pdf.worker.min.js";
35
+
36
+ const viewerRef = useCallback((container: any) => {
37
+ if (container !== null) {
38
+
39
+ let linkService = pdfLinkService;
40
+ let findController = pdfFindController;
41
+ let viewer = pdfViewer;
42
+ let eventBus = pdfEventBus;
43
+
44
+ if (!pdfEventBus) {
45
+ eventBus = new pdfjsViewer.EventBus();
46
+ setPdfEventBus(eventBus);
47
+ }
48
+
49
+ // (Optionally) enable hyperlinks within PDF files.
50
+ if (!pdfLinkService) {
51
+ linkService = new pdfjsViewer.PDFLinkService({
52
+ eventBus: eventBus!,
53
+ })
54
+ setPdfLinkService(linkService);
55
+ }
56
+
57
+ // (Optionally) enable find controller.
58
+ if (!pdfFindController) {
59
+ findController = new pdfjsViewer.PDFFindController({
60
+ eventBus: eventBus!,
61
+ linkService: linkService!,
62
+ })
63
+ setPdfFindController(findController);
64
+ }
65
+
66
+ if (!pdfViewer && eventBus) {
67
+ // @ts-ignore due to incorrect type def
68
+ viewer = new pdfjsViewer.PDFViewer({
69
+ container: container,
70
+ eventBus: eventBus,
71
+ linkService: linkService!,
72
+ findController: findController,
73
+ //defaultZoomValue: 1.0,
74
+ //scriptingManager: pdfScriptingManager,
75
+ //enableScripting: true, // Only necessary in PDF.js version 2.10.377 and below.
76
+ })
77
+ //pdfViewer!.MAX_AUTO_SCALE = 1.0;
78
+ linkService!.setViewer(viewer);
79
+ setPdfViewer(viewer);
80
+
81
+ eventBus.on("scalechanging", function () {
82
+ console.debug("scalechanging")
83
+ zoomLevelRef.current!.value = (Math.round(viewer!.currentScale * 100)).toFixed(0) + "%";
84
+ });
85
+
86
+ eventBus.on("pagechanging", function () {
87
+ console.debug("pagechanging")
88
+ if (pageNumberRef.current) {
89
+ pageNumberRef.current.value = viewer!.currentPageNumber.toFixed(0);
90
+ }
91
+ });
92
+
93
+ eventBus.on("pagesinit", function () {
94
+ // We can use pdfViewer now, e.g. let's change default scale.
95
+ viewer!.currentScaleValue = "auto";
96
+ pageNumberRef.current!.value = "1";
97
+ totalPagesRef.current!.innerText = viewer!.pagesCount.toFixed(0);
98
+
99
+ // We can try searching for things.
100
+ if (SEARCH_FOR) {
101
+ if (findController && !("_onFind" in findController)) {
102
+ // @ts-ignore due to missing type def
103
+ findController.executeCommand("find", { query: SEARCH_FOR });
104
+ } else {
105
+ eventBus!.dispatch("find", { type: "", query: SEARCH_FOR });
106
+ }
107
+ }
108
+ });
109
+ }
110
+
111
+ } else {
112
+ console.warn("pdf viewer dismounted")
113
+ }
114
+ }, []);
115
+
116
+ useEffect(() => {
117
+ if (src && pdfViewer && pdfLinkService) {
118
+ let loadingTask: pdfjsLib.PDFDocumentLoadingTask;
119
+ let loadedDoc: pdfjsLib.PDFDocumentProxy;
120
+
121
+ loadingTask = pdfjsLib.getDocument({
122
+ url: src,
123
+ enableXfa: ENABLE_XFA,
124
+ cMapUrl: CMAP_URL,
125
+ cMapPacked: CMAP_PACKED,
126
+ });
127
+
128
+ // Re-use the worker?
129
+ //pdfjsLib.GlobalWorkerOptions.workerPort = loadingTask._worker.port
130
+
131
+ loadingTask.promise.then(function (doc) {
132
+ loadedDoc = doc;
133
+ //console.log("LOADED PDF");
134
+ pdfViewer.setDocument(doc);
135
+ pdfLinkService.setDocument(doc, null);
136
+ });
137
+
138
+ return () => {
139
+ if (loadingTask) {
140
+ console.log("resetting pdf viewer");
141
+ if(loadingTask._transport){
142
+ loadingTask._transport.destroy();
143
+ }
144
+
145
+ if (loadedDoc) {
146
+ loadedDoc.destroy();
147
+ }
148
+
149
+ //loadingTask.destroy();
150
+ pdfViewer.cleanup();
151
+ }
152
+ }
153
+ }
154
+ }, [src, pdfViewer])
155
+
156
+ function setScale(scale: number | string) {
157
+ console.debug("setScale:", scale)
158
+ if (pdfViewer) {
159
+ pdfViewer.currentScaleValue = typeof scale === "number" ? scale.toFixed(2) : scale;
160
+ }
161
+ }
162
+
163
+ function setPage(pageNumber: number) {
164
+ console.debug("setPage:", pageNumber)
165
+ if (pdfViewer) {
166
+ pdfViewer.currentPageNumber = pageNumber;
167
+ }
168
+ }
169
+
170
+ function updatePage() {
171
+ console.debug("updatePage");
172
+ if (pdfViewer && pageNumberRef.current) {
173
+ let pageNumber = parseInt(pageNumberRef.current.value);
174
+
175
+ if (isNaN(pageNumber)) {
176
+ setPage(pdfViewer.currentPageNumber);
177
+ } else if (pageNumber > pdfViewer.pagesCount) {
178
+ setPage(pdfViewer.pagesCount);
179
+ } else if (pageNumber <= 0) {
180
+ setPage(1);
181
+ } else {
182
+ setPage(pageNumber);
183
+ }
184
+
185
+ }
186
+ }
187
+
188
+ function select(e: any) {
189
+ console.debug("select");
190
+ e.target.setSelectionRange(0, e.target.value.length);
191
+ }
192
+
193
+ function fitToPage() {
194
+ setScale("page-fit");
195
+ }
196
+
197
+ function fitToWidth() {
198
+ setScale("page-width");
199
+ }
200
+
201
+ function zoomIn() {
202
+ console.debug("zoomIn");
203
+
204
+ if (pdfViewer) {
205
+ let newScale = pdfViewer.currentScale;
206
+ let steps = 1;
207
+ do {
208
+ newScale = newScale * DEFAULT_SCALE_DELTA;
209
+ newScale = Math.floor(newScale * 10) / 10;
210
+ newScale = Math.min(MAX_SCALE, newScale);
211
+ } while (--steps > 0 && newScale < MAX_SCALE);
212
+
213
+ setScale(newScale);
214
+ }
215
+ }
216
+
217
+ function zoomOut() {
218
+ console.debug("zoomOut");
219
+ if (pdfViewer) {
220
+ let newScale = pdfViewer.currentScale;
221
+ let steps = 1;
222
+ do {
223
+ newScale = newScale / DEFAULT_SCALE_DELTA;
224
+ newScale = Math.floor(newScale * 10) / 10;
225
+ newScale = Math.max(MIN_SCALE, newScale);
226
+ } while (--steps > 0 && newScale > MIN_SCALE);
227
+
228
+ setScale(newScale);
229
+ }
230
+ }
231
+
232
+ function updateZoom() {
233
+ console.debug("updateZoom");
234
+ if (pdfViewer && zoomLevelRef.current) {
235
+ let zoomValue = parseFloat(zoomLevelRef.current.value.replace("%", ""));
236
+ if (isNaN(zoomValue)) {
237
+ setScale(pdfViewer.currentScale + 0.0001);
238
+ } else {
239
+ setScale(zoomValue / 100);
240
+ }
241
+ }
242
+ }
243
+
244
+ return (
245
+ <div className="wy-content-pdf" data-controller="pdf" data-pdf-url-value="">
246
+ <div className="wy-toolbar">
247
+ <nav className="wy-tools">
248
+ <div className="wy-tool">
249
+ <input type="text" className="wy-input" ref={pageNumberRef} onChange={updatePage} onClick={select} data-pdf-target="pageNumber"/>
250
+ <span>/</span>
251
+ <span ref={totalPagesRef}>1</span>
252
+ </div>
253
+ <div className="wy-tool">
254
+ <button className="wy-button wy-button-icon btn-zoom-out" onClick={zoomOut} title="Zoom out"><Icon.UI name="minus" /></button>
255
+ <input type="text" className="wy-input" ref={zoomLevelRef} onChange={updateZoom} onClick={select} value="100%" data-pdf-target="zoomLevel"/>
256
+ <button className="wy-button wy-button-icon btn-zoom-in" onClick={zoomIn} title="Zoom in"><Icon.UI name="plus" /></button>
257
+ </div>
258
+ <div className="wy-tool">
259
+ <button className="wy-button wy-button-icon btn-fit-page" onClick={fitToWidth} title="Fit to width"><Icon.UI name="fit-width" /></button>
260
+ <button className="wy-button wy-button-icon" onClick={fitToPage} title="Fit to screen"><Icon.UI name="fit-screen" /></button>
261
+ </div>
262
+ </nav>
263
+ </div>
264
+ <div ref={viewerRef} className="wy-pdf-container">
265
+ <div id="viewer" className="pdfViewer"></div>
266
+ </div>
267
+ </div>
268
+ )
269
+ }
270
+
271
+ export default PdfViewer;
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { prefix as wy } from "../utils/styles";
2
+ import classNames from "classnames";
3
3
 
4
4
  type Props = {
5
5
  id: number,
@@ -8,7 +8,7 @@ type Props = {
8
8
 
9
9
  const Presence = ({ id, status }: Props) => {
10
10
  return (
11
- <span className={wy(`presence ${status === "active" ? "presence-active" : ""}`)} data-presence-id={id}></span>
11
+ <span className={classNames("wy-presence", { "wy-presence-active": status === "active" })} data-presence-id={id}></span>
12
12
  )
13
13
  }
14
14