@lnco-ai/ui 1.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 (288) hide show
  1. package/CHANGELOG.md +1323 -0
  2. package/LICENSE +661 -0
  3. package/README.md +60 -0
  4. package/dist/Authorization/PreventGuestWrapper.d.ts +19 -0
  5. package/dist/Authorization/PreventGuestWrapper.js +15 -0
  6. package/dist/Authorization/RedirectionContent.d.ts +9 -0
  7. package/dist/Authorization/RedirectionContent.js +24 -0
  8. package/dist/Authorization/SignedInWrapper.d.ts +10 -0
  9. package/dist/Authorization/SignedInWrapper.js +21 -0
  10. package/dist/Avatar/Avatar.d.ts +24 -0
  11. package/dist/Avatar/Avatar.js +22 -0
  12. package/dist/Avatar/stringToColor.d.ts +12 -0
  13. package/dist/Avatar/stringToColor.js +31 -0
  14. package/dist/Avatar/stringToColor.test.d.ts +1 -0
  15. package/dist/Avatar/stringToColor.test.js +8 -0
  16. package/dist/Card/Card.d.ts +39 -0
  17. package/dist/Card/Card.js +76 -0
  18. package/dist/Card/CardHeader.d.ts +12 -0
  19. package/dist/Card/CardHeader.js +8 -0
  20. package/dist/Card/CardThumbnail.d.ts +10 -0
  21. package/dist/Card/CardThumbnail.js +14 -0
  22. package/dist/Card/FolderCard.d.ts +14 -0
  23. package/dist/Card/FolderCard.js +44 -0
  24. package/dist/Card/LinkCard.d.ts +11 -0
  25. package/dist/Card/LinkCard.js +41 -0
  26. package/dist/Card/components/CardThumbnail.d.ts +8 -0
  27. package/dist/Card/components/CardThumbnail.js +15 -0
  28. package/dist/Card/constants.d.ts +1 -0
  29. package/dist/Card/constants.js +1 -0
  30. package/dist/Collapse/Collapse.d.ts +10 -0
  31. package/dist/Collapse/Collapse.js +48 -0
  32. package/dist/Collapse/withCollapse.d.ts +7 -0
  33. package/dist/Collapse/withCollapse.js +8 -0
  34. package/dist/CookiesBanner/CookiesBanner.d.ts +10 -0
  35. package/dist/CookiesBanner/CookiesBanner.js +60 -0
  36. package/dist/CreativeCommons/CreativeCommons.d.ts +14 -0
  37. package/dist/CreativeCommons/CreativeCommons.js +75 -0
  38. package/dist/CreativeCommons/icons/By.d.ts +3 -0
  39. package/dist/CreativeCommons/icons/By.js +3 -0
  40. package/dist/CreativeCommons/icons/CCIconsProps.d.ts +3 -0
  41. package/dist/CreativeCommons/icons/CCIconsProps.js +1 -0
  42. package/dist/CreativeCommons/icons/Cc.d.ts +3 -0
  43. package/dist/CreativeCommons/icons/Cc.js +3 -0
  44. package/dist/CreativeCommons/icons/Cc0.d.ts +3 -0
  45. package/dist/CreativeCommons/icons/Cc0.js +3 -0
  46. package/dist/CreativeCommons/icons/Nc.d.ts +3 -0
  47. package/dist/CreativeCommons/icons/Nc.js +3 -0
  48. package/dist/CreativeCommons/icons/Nd.d.ts +3 -0
  49. package/dist/CreativeCommons/icons/Nd.js +3 -0
  50. package/dist/CreativeCommons/icons/Sa.d.ts +3 -0
  51. package/dist/CreativeCommons/icons/Sa.js +3 -0
  52. package/dist/CustomInitialLoader/CustomInitialLoader.d.ts +5 -0
  53. package/dist/CustomInitialLoader/CustomInitialLoader.js +25 -0
  54. package/dist/DrawerHeader/DrawerHeader.d.ts +7 -0
  55. package/dist/DrawerHeader/DrawerHeader.js +16 -0
  56. package/dist/GraaspLogo/EpflLogo.d.ts +5 -0
  57. package/dist/GraaspLogo/EpflLogo.js +3 -0
  58. package/dist/GraaspLogo/GraaspLogo.d.ts +8 -0
  59. package/dist/GraaspLogo/GraaspLogo.js +5 -0
  60. package/dist/Header/Header.d.ts +21 -0
  61. package/dist/Header/Header.js +33 -0
  62. package/dist/HeaderUserInformation/HeaderUserInformation.d.ts +22 -0
  63. package/dist/HeaderUserInformation/HeaderUserInformation.js +23 -0
  64. package/dist/ItemBadges/ItemBadges.d.ts +17 -0
  65. package/dist/ItemBadges/ItemBadges.js +10 -0
  66. package/dist/ItemFlag/ItemFlagButton.d.ts +9 -0
  67. package/dist/ItemFlag/ItemFlagButton.js +11 -0
  68. package/dist/ItemFlag/ItemFlagDialog.d.ts +14 -0
  69. package/dist/ItemFlag/ItemFlagDialog.js +25 -0
  70. package/dist/Loader/Loader.d.ts +7 -0
  71. package/dist/Loader/Loader.js +4 -0
  72. package/dist/Main/LogoHeader.d.ts +2 -0
  73. package/dist/Main/LogoHeader.js +5 -0
  74. package/dist/Main/Main.d.ts +59 -0
  75. package/dist/Main/Main.js +82 -0
  76. package/dist/MainMenu/MainMenu.d.ts +10 -0
  77. package/dist/MainMenu/MainMenu.js +6 -0
  78. package/dist/MainMenu/MenuItem/MenuItem.d.ts +16 -0
  79. package/dist/MainMenu/MenuItem/MenuItem.js +16 -0
  80. package/dist/MainMenu/hooks.d.ts +10 -0
  81. package/dist/MainMenu/hooks.js +21 -0
  82. package/dist/Navigation/CurrentItemNavigation.d.ts +15 -0
  83. package/dist/Navigation/CurrentItemNavigation.js +12 -0
  84. package/dist/Navigation/ExtraItemsMenu.d.ts +10 -0
  85. package/dist/Navigation/ExtraItemsMenu.js +24 -0
  86. package/dist/Navigation/ExtraItemsNavigation.d.ts +11 -0
  87. package/dist/Navigation/ExtraItemsNavigation.js +11 -0
  88. package/dist/Navigation/HomeMenu.d.ts +17 -0
  89. package/dist/Navigation/HomeMenu.js +28 -0
  90. package/dist/Navigation/ItemMenu.d.ts +16 -0
  91. package/dist/Navigation/ItemMenu.js +32 -0
  92. package/dist/Navigation/Navigation.d.ts +26 -0
  93. package/dist/Navigation/Navigation.js +15 -0
  94. package/dist/Navigation/ParentsNavigation.d.ts +10 -0
  95. package/dist/Navigation/ParentsNavigation.js +8 -0
  96. package/dist/Navigation/common/CenterAlignWrapper.d.ts +3 -0
  97. package/dist/Navigation/common/CenterAlignWrapper.js +7 -0
  98. package/dist/Navigation/common/NavigationLink.d.ts +8 -0
  99. package/dist/Navigation/common/NavigationLink.js +7 -0
  100. package/dist/Navigation/common/constants.d.ts +1 -0
  101. package/dist/Navigation/common/constants.js +1 -0
  102. package/dist/PlatformSwitch/PlatformSwitch.d.ts +57 -0
  103. package/dist/PlatformSwitch/PlatformSwitch.js +66 -0
  104. package/dist/PlatformSwitch/hooks.d.ts +30 -0
  105. package/dist/PlatformSwitch/hooks.js +49 -0
  106. package/dist/SearchInput/SearchInput.d.ts +20 -0
  107. package/dist/SearchInput/SearchInput.js +14 -0
  108. package/dist/Select/Select.d.ts +24 -0
  109. package/dist/Select/Select.js +7 -0
  110. package/dist/Sidebar/Sidebar.d.ts +11 -0
  111. package/dist/Sidebar/Sidebar.js +25 -0
  112. package/dist/StyledComponents/StyledBaseComponents.d.ts +11 -0
  113. package/dist/StyledComponents/StyledBaseComponents.js +11 -0
  114. package/dist/TextDisplay/TextDisplay.d.ts +5 -0
  115. package/dist/TextDisplay/TextDisplay.js +24 -0
  116. package/dist/TextDisplay/fixtures.d.ts +3 -0
  117. package/dist/TextDisplay/fixtures.js +84 -0
  118. package/dist/TextDisplay/withFlavor.d.ts +8 -0
  119. package/dist/TextDisplay/withFlavor.js +25 -0
  120. package/dist/TextEditor/TextEditor.d.ts +16 -0
  121. package/dist/TextEditor/TextEditor.js +74 -0
  122. package/dist/ThemeContext/LanguageSelect.d.ts +15 -0
  123. package/dist/ThemeContext/LanguageSelect.js +19 -0
  124. package/dist/ThemeContext/ThemeContext.d.ts +22 -0
  125. package/dist/ThemeContext/ThemeContext.js +31 -0
  126. package/dist/Thumbnail/Thumbnail.d.ts +28 -0
  127. package/dist/Thumbnail/Thumbnail.js +27 -0
  128. package/dist/Tree/Breadcrumbs.d.ts +14 -0
  129. package/dist/Tree/Breadcrumbs.js +30 -0
  130. package/dist/Tree/RowMenu.d.ts +12 -0
  131. package/dist/Tree/RowMenu.js +37 -0
  132. package/dist/Tree/RowMenus.d.ts +18 -0
  133. package/dist/Tree/RowMenus.js +7 -0
  134. package/dist/Tree/types.d.ts +6 -0
  135. package/dist/Tree/types.js +1 -0
  136. package/dist/UserSwitch/UserSwitch.d.ts +17 -0
  137. package/dist/UserSwitch/UserSwitch.js +46 -0
  138. package/dist/UserSwitch/UserSwitchWrapper.d.ts +37 -0
  139. package/dist/UserSwitch/UserSwitchWrapper.js +74 -0
  140. package/dist/appComponents/ErrorFallback.d.ts +57 -0
  141. package/dist/appComponents/ErrorFallback.js +72 -0
  142. package/dist/appComponents/QuestionLabel.d.ts +9 -0
  143. package/dist/appComponents/QuestionLabel.js +4 -0
  144. package/dist/appComponents/index.d.ts +6 -0
  145. package/dist/appComponents/index.js +5 -0
  146. package/dist/appComponents/statusChips/RequiredChip.d.ts +3 -0
  147. package/dist/appComponents/statusChips/RequiredChip.js +5 -0
  148. package/dist/appComponents/statusChips/SavedChip.d.ts +3 -0
  149. package/dist/appComponents/statusChips/SavedChip.js +5 -0
  150. package/dist/appComponents/statusChips/SubmittedChip.d.ts +3 -0
  151. package/dist/appComponents/statusChips/SubmittedChip.js +5 -0
  152. package/dist/appComponents/statusChips/types.d.ts +5 -0
  153. package/dist/appComponents/statusChips/types.js +1 -0
  154. package/dist/appComponents/types.d.ts +8 -0
  155. package/dist/appComponents/types.js +1 -0
  156. package/dist/apps.d.ts +1 -0
  157. package/dist/apps.js +1 -0
  158. package/dist/buttons/BookmarkButton/BookmarkButton.d.ts +24 -0
  159. package/dist/buttons/BookmarkButton/BookmarkButton.js +24 -0
  160. package/dist/buttons/Button/Button.d.ts +37 -0
  161. package/dist/buttons/Button/Button.js +4 -0
  162. package/dist/buttons/ChatboxButton/ChatboxButton.d.ts +15 -0
  163. package/dist/buttons/ChatboxButton/ChatboxButton.js +21 -0
  164. package/dist/buttons/CopyButton/CopyButton.d.ts +13 -0
  165. package/dist/buttons/CopyButton/CopyButton.js +14 -0
  166. package/dist/buttons/DeleteButton/DeleteButton.d.ts +12 -0
  167. package/dist/buttons/DeleteButton/DeleteButton.js +17 -0
  168. package/dist/buttons/DownloadButton/DownloadButton.d.ts +30 -0
  169. package/dist/buttons/DownloadButton/DownloadButton.js +20 -0
  170. package/dist/buttons/EditButton/EditButton.d.ts +13 -0
  171. package/dist/buttons/EditButton/EditButton.js +17 -0
  172. package/dist/buttons/LikeButton/LikeButton.d.ts +28 -0
  173. package/dist/buttons/LikeButton/LikeButton.js +10 -0
  174. package/dist/buttons/MenuItemButton.d.ts +11 -0
  175. package/dist/buttons/MenuItemButton.js +12 -0
  176. package/dist/buttons/MoveButton/MoveButton.d.ts +13 -0
  177. package/dist/buttons/MoveButton/MoveButton.js +19 -0
  178. package/dist/buttons/PinButton/PinButton.d.ts +15 -0
  179. package/dist/buttons/PinButton/PinButton.js +21 -0
  180. package/dist/buttons/SaveButton/SaveButton.d.ts +24 -0
  181. package/dist/buttons/SaveButton/SaveButton.js +4 -0
  182. package/dist/buttons/ShareButton/ShareButton.d.ts +14 -0
  183. package/dist/buttons/ShareButton/ShareButton.js +17 -0
  184. package/dist/buttons/hooks.d.ts +5 -0
  185. package/dist/buttons/hooks.js +14 -0
  186. package/dist/buttons/index.d.ts +12 -0
  187. package/dist/buttons/index.js +12 -0
  188. package/dist/constants.d.ts +11 -0
  189. package/dist/constants.js +12 -0
  190. package/dist/draggable/DraggableElement.d.ts +11 -0
  191. package/dist/draggable/DraggableElement.js +42 -0
  192. package/dist/draggable/DraggingWrapper.d.ts +23 -0
  193. package/dist/draggable/DraggingWrapper.js +20 -0
  194. package/dist/draggable/InBetween.d.ts +10 -0
  195. package/dist/draggable/InBetween.js +34 -0
  196. package/dist/draggable/types.d.ts +10 -0
  197. package/dist/draggable/types.js +1 -0
  198. package/dist/enums/errors.d.ts +3 -0
  199. package/dist/enums/errors.js +3 -0
  200. package/dist/hooks/useFullscreen.d.ts +5 -0
  201. package/dist/hooks/useFullscreen.js +37 -0
  202. package/dist/hooks/useMobileView.d.ts +4 -0
  203. package/dist/hooks/useMobileView.js +6 -0
  204. package/dist/icons/AnalyticsIcon.d.ts +15 -0
  205. package/dist/icons/AnalyticsIcon.js +7 -0
  206. package/dist/icons/BuildIcon.d.ts +15 -0
  207. package/dist/icons/BuildIcon.js +7 -0
  208. package/dist/icons/EtherpadIcon.d.ts +7 -0
  209. package/dist/icons/EtherpadIcon.js +7 -0
  210. package/dist/icons/H5PIcon.d.ts +6 -0
  211. package/dist/icons/H5PIcon.js +6 -0
  212. package/dist/icons/ItemIcon.d.ts +23 -0
  213. package/dist/icons/ItemIcon.js +75 -0
  214. package/dist/icons/LibraryIcon.d.ts +16 -0
  215. package/dist/icons/LibraryIcon.js +7 -0
  216. package/dist/icons/PlayIcon.d.ts +15 -0
  217. package/dist/icons/PlayIcon.js +7 -0
  218. package/dist/icons/ResizingIcon.d.ts +2 -0
  219. package/dist/icons/ResizingIcon.js +21 -0
  220. package/dist/icons/StyledSVGComponents.d.ts +35 -0
  221. package/dist/icons/StyledSVGComponents.js +53 -0
  222. package/dist/icons/index.d.ts +6 -0
  223. package/dist/icons/index.js +6 -0
  224. package/dist/index.d.ts +61 -0
  225. package/dist/index.js +60 -0
  226. package/dist/itemLogin/ForbiddenContent.d.ts +20 -0
  227. package/dist/itemLogin/ForbiddenContent.js +4 -0
  228. package/dist/itemLogin/ForbiddenText.d.ts +8 -0
  229. package/dist/itemLogin/ForbiddenText.js +6 -0
  230. package/dist/itemLogin/ItemLoginScreen.d.ts +26 -0
  231. package/dist/itemLogin/ItemLoginScreen.js +72 -0
  232. package/dist/itemLogin/ItemLoginWrapper.d.ts +23 -0
  233. package/dist/itemLogin/ItemLoginWrapper.js +43 -0
  234. package/dist/itemLogin/constants.d.ts +1 -0
  235. package/dist/itemLogin/constants.js +1 -0
  236. package/dist/items/AppItem.d.ts +60 -0
  237. package/dist/items/AppItem.js +69 -0
  238. package/dist/items/DocumentItem.d.ts +19 -0
  239. package/dist/items/DocumentItem.js +25 -0
  240. package/dist/items/DownloadButtonFileItem.d.ts +9 -0
  241. package/dist/items/DownloadButtonFileItem.js +10 -0
  242. package/dist/items/EtherpadItem.d.ts +26 -0
  243. package/dist/items/EtherpadItem.js +15 -0
  244. package/dist/items/FileAudio.d.ts +9 -0
  245. package/dist/items/FileAudio.js +10 -0
  246. package/dist/items/FileImage.d.ts +7 -0
  247. package/dist/items/FileImage.js +10 -0
  248. package/dist/items/FileItem.d.ts +25 -0
  249. package/dist/items/FileItem.js +81 -0
  250. package/dist/items/FilePdf.d.ts +14 -0
  251. package/dist/items/FilePdf.js +29 -0
  252. package/dist/items/FileVideo.d.ts +8 -0
  253. package/dist/items/FileVideo.js +9 -0
  254. package/dist/items/H5PItem.d.ts +20 -0
  255. package/dist/items/H5PItem.js +80 -0
  256. package/dist/items/ItemSkeleton/ItemSkeleton.d.ts +12 -0
  257. package/dist/items/ItemSkeleton/ItemSkeleton.js +35 -0
  258. package/dist/items/LinkItem.d.ts +43 -0
  259. package/dist/items/LinkItem.js +97 -0
  260. package/dist/items/SizingWrapper.d.ts +6 -0
  261. package/dist/items/SizingWrapper.js +23 -0
  262. package/dist/items/appItemHooks.d.ts +27 -0
  263. package/dist/items/appItemHooks.js +124 -0
  264. package/dist/items/constants.d.ts +1 -0
  265. package/dist/items/constants.js +1 -0
  266. package/dist/items/iframeStyles.d.ts +4 -0
  267. package/dist/items/iframeStyles.js +5 -0
  268. package/dist/items/index.d.ts +5 -0
  269. package/dist/items/index.js +5 -0
  270. package/dist/items/withCaption.d.ts +19 -0
  271. package/dist/items/withCaption.js +58 -0
  272. package/dist/items/withResizing.d.ts +9 -0
  273. package/dist/items/withResizing.js +42 -0
  274. package/dist/text-editor.d.ts +2 -0
  275. package/dist/text-editor.js +2 -0
  276. package/dist/theme.d.ts +108 -0
  277. package/dist/theme.js +214 -0
  278. package/dist/types.d.ts +43 -0
  279. package/dist/types.js +32 -0
  280. package/dist/upload/FileDropper/FileDropper.d.ts +50 -0
  281. package/dist/upload/FileDropper/FileDropper.js +43 -0
  282. package/dist/upload/UploadFileButton/UploadFileButton.d.ts +35 -0
  283. package/dist/upload/UploadFileButton/UploadFileButton.js +17 -0
  284. package/dist/utils/fixtures.d.ts +3 -0
  285. package/dist/utils/fixtures.js +7 -0
  286. package/dist/utils/storybook.d.ts +5 -0
  287. package/dist/utils/storybook.js +5 -0
  288. package/package.json +172 -0
@@ -0,0 +1,81 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Alert, Box, Skeleton } from '@mui/material';
3
+ import { memo, useEffect, useState } from 'react';
4
+ import { ItemType, MimeTypes, formatFileSize, getFileExtra, getS3FileExtra, } from '@lnco-ai/sdk';
5
+ import { Errors } from '../enums/errors.js';
6
+ import withCollapse from '../Collapse/withCollapse.js';
7
+ import { SCREEN_MAX_HEIGHT, UNEXPECTED_ERROR_MESSAGE } from '../constants.js';
8
+ import DownloadButtonFileItem from './DownloadButtonFileItem.js';
9
+ import FileAudio from './FileAudio.js';
10
+ import FileImage from './FileImage.js';
11
+ import FilePdf from './FilePdf.js';
12
+ import FileVideo from './FileVideo.js';
13
+ import { SizingWrapper } from './SizingWrapper.js';
14
+ import { CaptionWrapper } from './withCaption.js';
15
+ const FileItem = ({ content, fileUrl, defaultItem, errorMessage = UNEXPECTED_ERROR_MESSAGE, id, item, maxHeight = '100%', showCollapse, pdfViewerLink, onClick, onCollapse, }) => {
16
+ const [url, setUrl] = useState();
17
+ useEffect(() => {
18
+ (async () => {
19
+ if (fileUrl) {
20
+ setUrl(fileUrl);
21
+ }
22
+ else if (content) {
23
+ // Build a URL from the file
24
+ const urlFromContent = URL.createObjectURL(content);
25
+ if (urlFromContent) {
26
+ setUrl(urlFromContent);
27
+ }
28
+ else {
29
+ setUrl(Errors.BlobURL);
30
+ }
31
+ }
32
+ return () => {
33
+ if (content && url) {
34
+ URL.revokeObjectURL(url);
35
+ }
36
+ };
37
+ })();
38
+ // does not include url to avoid infinite loop
39
+ }, [content, fileUrl]);
40
+ if (!url) {
41
+ return (_jsx(Skeleton, { variant: 'rectangular', width: '100%', height: maxHeight || SCREEN_MAX_HEIGHT }));
42
+ }
43
+ if (url === Errors.BlobURL) {
44
+ return _jsx(Alert, { severity: 'error', children: errorMessage });
45
+ }
46
+ const getComponent = () => {
47
+ const fileExtra = item.type === ItemType.LOCAL_FILE ? getFileExtra(item.extra) : undefined;
48
+ const s3FileExtra = item.type === ItemType.S3_FILE ? getS3FileExtra(item.extra) : undefined;
49
+ const { mimetype, altText, size } = { ...fileExtra, ...s3FileExtra };
50
+ if (mimetype) {
51
+ if (MimeTypes.isImage(mimetype)) {
52
+ return (
53
+ /* The box prevent the image to take full available space due to the stack */
54
+ _jsx(Box, { children: _jsx(FileImage, { id: id, url: url, alt: altText || item.name }) }));
55
+ }
56
+ else if (MimeTypes.isAudio(mimetype)) {
57
+ return _jsx(FileAudio, { id: id, url: url, type: mimetype });
58
+ }
59
+ else if (MimeTypes.isVideo(mimetype)) {
60
+ // does not specify mimetype in video source, this way, it works with more container formats in more browsers (especially Chrome with video/quicktime)
61
+ return _jsx(FileVideo, { id: id, url: url });
62
+ }
63
+ else if (MimeTypes.isPdf(mimetype)) {
64
+ return (_jsx(FilePdf, { id: id, url: url, height: maxHeight, showCollapse: showCollapse, pdfViewerLink: pdfViewerLink }));
65
+ }
66
+ }
67
+ if (defaultItem) {
68
+ return defaultItem;
69
+ }
70
+ return (_jsx(DownloadButtonFileItem, { id: id, name: item.name, caption: size ? formatFileSize(size) : undefined, url: url, onClick: onClick }));
71
+ };
72
+ let fileItem = getComponent();
73
+ fileItem = (_jsx(SizingWrapper, { size: item.settings.maxWidth, children: fileItem }));
74
+ // display element with caption
75
+ fileItem = _jsx(CaptionWrapper, { item: item, children: fileItem });
76
+ if (showCollapse) {
77
+ fileItem = withCollapse({ item, onCollapse })(fileItem);
78
+ }
79
+ return fileItem;
80
+ };
81
+ export default memo(FileItem);
@@ -0,0 +1,14 @@
1
+ import { SxProps } from '@mui/material';
2
+ type FilePdfProps = {
3
+ id?: string;
4
+ url: string;
5
+ height?: number | string;
6
+ sx?: SxProps;
7
+ showCollapse?: boolean;
8
+ /**
9
+ * use a custom pdf reader from the link if defined
10
+ * */
11
+ pdfViewerLink?: string;
12
+ };
13
+ declare const FilePdf: ({ url, id, sx, height: defaultHeight, showCollapse, pdfViewerLink, }: FilePdfProps) => JSX.Element;
14
+ export default FilePdf;
@@ -0,0 +1,29 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { styled } from '@mui/material';
3
+ import { useRef, useState } from 'react';
4
+ import { ITEM_MAX_HEIGHT } from './constants.js';
5
+ const StyledEmbed = styled('embed')({
6
+ maxHeight: ITEM_MAX_HEIGHT,
7
+ });
8
+ const FilePdf = ({ url, id, sx, height: defaultHeight, showCollapse, pdfViewerLink, }) => {
9
+ const embedRef = useRef(null);
10
+ const [height, setHeight] = useState(defaultHeight ?? '100%');
11
+ const onLoad = (e) => {
12
+ // only set pdf height if not using collapse
13
+ if (!showCollapse) {
14
+ // set pdf height -> probably very high
15
+ const newHeight = e.target?.offsetParent
16
+ ?.scrollHeight;
17
+ if (newHeight) {
18
+ setHeight(newHeight);
19
+ }
20
+ }
21
+ };
22
+ // use custom pdf viewer if defined
23
+ let urlWithPdfViewer = url;
24
+ if (pdfViewerLink) {
25
+ urlWithPdfViewer = `${pdfViewerLink}${encodeURIComponent(url)}`;
26
+ }
27
+ return (_jsx(StyledEmbed, { ref: embedRef, id: id, src: urlWithPdfViewer, width: '100%', height: height || '100%', onLoad: onLoad, sx: sx }));
28
+ };
29
+ export default FilePdf;
@@ -0,0 +1,8 @@
1
+ import { SxProps } from '@mui/material';
2
+ type FileVideoProps = {
3
+ id?: string;
4
+ url?: string;
5
+ sx?: SxProps;
6
+ };
7
+ declare const FileVideo: ({ id, url, sx }: FileVideoProps) => JSX.Element;
8
+ export default FileVideo;
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { styled } from '@mui/material';
3
+ const StyledVideo = styled('video')({
4
+ maxWidth: '100%',
5
+ });
6
+ const FileVideo = ({ id, url, sx }) => {
7
+ return (_jsx(StyledVideo, { sx: sx, id: id, controls: true, children: _jsx("source", { src: url }) }));
8
+ };
9
+ export default FileVideo;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * React props types for {@link H5PItem}
3
+ */
4
+ type H5PItemProps = {
5
+ itemName: string;
6
+ itemId: string;
7
+ contentId: string;
8
+ integrationUrl: string;
9
+ iframeId?: string;
10
+ showCollapse?: boolean;
11
+ onCollapse?: (c: boolean) => void;
12
+ };
13
+ /**
14
+ * The H5PItem component displays an iframe with the content of an H5P
15
+ *
16
+ * This component bridges the gap between the procedural "h5p-standalone"
17
+ * package and the Graasp React ecosystem
18
+ */
19
+ declare const H5PItem: ({ itemName, itemId, contentId, integrationUrl: integrationBase, iframeId, showCollapse, onCollapse, }: H5PItemProps) => JSX.Element;
20
+ export default H5PItem;
@@ -0,0 +1,80 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { validate, version } from 'uuid';
3
+ import { useEffect, useRef } from 'react';
4
+ import withCollapse from '../Collapse/withCollapse.js';
5
+ /**
6
+ * The H5PItem component displays an iframe with the content of an H5P
7
+ *
8
+ * This component bridges the gap between the procedural "h5p-standalone"
9
+ * package and the Graasp React ecosystem
10
+ */
11
+ const H5PItem = ({ itemName, itemId, contentId, integrationUrl: integrationBase, iframeId = `h5p-container-${itemId}`, showCollapse = false, onCollapse, }) => {
12
+ /*
13
+ h5p-standalone (and H5P itself) expect the integration to be done on the
14
+ window global object, which does not allow multiple H5Ps to be loaded
15
+ simultaneously (as they will be competing for the same global object)
16
+ As a workaround, we wrap the H5P integration into an iframe, such that it
17
+ gets its own window object. We can also enable the sandbox attribute for
18
+ additional security
19
+ */
20
+ const integrationUrl = new URL(integrationBase);
21
+ integrationUrl.searchParams.set('content', encodeURIComponent(contentId));
22
+ const iframeRef = useRef(null);
23
+ // Listen for content height changes
24
+ useEffect(() => {
25
+ const onResize = (event) => {
26
+ // iframe must be mounted
27
+ if (iframeRef.current === null) {
28
+ return;
29
+ }
30
+ // message origin must be same window
31
+ if (event.origin !== integrationUrl.origin) {
32
+ return;
33
+ }
34
+ // message source must be iframe of this H5P integration
35
+ if (event.source !== iframeRef.current.contentWindow) {
36
+ return;
37
+ }
38
+ // message data should be object
39
+ if (!event.data || typeof event.data !== 'object') {
40
+ return;
41
+ }
42
+ // message should have fields contentId and height
43
+ if (!event.data.contentId || !event.data.height) {
44
+ return;
45
+ }
46
+ // contentId should be UUID string
47
+ if (typeof event.data.contentId !== 'string' ||
48
+ version(event.data.contentId) !== 4 ||
49
+ !validate(event.data.contentId)) {
50
+ return;
51
+ }
52
+ // contentId should match current item
53
+ if (event.data.contentId !== contentId) {
54
+ return;
55
+ }
56
+ // height should be number
57
+ if (typeof event.data.height !== 'number') {
58
+ return;
59
+ }
60
+ // height should be int
61
+ const newHeight = parseInt(event.data.height);
62
+ iframeRef.current.height = newHeight.toString();
63
+ };
64
+ window.addEventListener('message', onResize);
65
+ // cleanup on unmount
66
+ return () => {
67
+ window.removeEventListener('message', onResize);
68
+ };
69
+ }, []);
70
+ let iframeH5Pitem = (_jsx("iframe", { ref: iframeRef, id: iframeId, src: integrationUrl.href, allowFullScreen: true, scrolling: 'no', style: {
71
+ width: '100%',
72
+ border: 'none',
73
+ display: 'block',
74
+ } }));
75
+ if (showCollapse) {
76
+ iframeH5Pitem = withCollapse({ item: { name: itemName }, onCollapse })(iframeH5Pitem);
77
+ }
78
+ return iframeH5Pitem;
79
+ };
80
+ export default H5PItem;
@@ -0,0 +1,12 @@
1
+ import { DiscriminatedItem } from '@lnco-ai/sdk';
2
+ export type ItemSkeletonProps = {
3
+ /**
4
+ * prevent displaying skeleton if item is a folder
5
+ */
6
+ isChildren: boolean;
7
+ isCollapsible?: boolean;
8
+ itemType: DiscriminatedItem['type'];
9
+ screenMaxHeight?: number;
10
+ };
11
+ declare const ItemSkeleton: ({ isChildren, isCollapsible, itemType, screenMaxHeight, }: ItemSkeletonProps) => JSX.Element | null;
12
+ export default ItemSkeleton;
@@ -0,0 +1,35 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Skeleton } from '@mui/material';
3
+ import { ItemType } from '@lnco-ai/sdk';
4
+ import { SCREEN_MAX_HEIGHT } from '../../constants.js';
5
+ const SKELETON_COLLAPSE_HEIGHT = '3.5em';
6
+ const SKELETON_FOLDER_BUTTON_HEIGHT = '8.125em';
7
+ const ItemSkeleton = ({ isChildren, isCollapsible, itemType, screenMaxHeight, }) => {
8
+ switch (true) {
9
+ case isCollapsible: {
10
+ return (_jsx(Skeleton, { variant: 'rectangular', width: '100%', height: SKELETON_COLLAPSE_HEIGHT }));
11
+ }
12
+ case itemType === ItemType.FOLDER && isChildren: {
13
+ return null;
14
+ }
15
+ case itemType === ItemType.FOLDER: {
16
+ return (_jsx(Skeleton, { variant: 'rectangular', width: '100%', height: SKELETON_FOLDER_BUTTON_HEIGHT }));
17
+ }
18
+ case [
19
+ ItemType.LOCAL_FILE,
20
+ ItemType.S3_FILE,
21
+ ItemType.LINK,
22
+ ItemType.APP,
23
+ ].includes(itemType):
24
+ {
25
+ return (_jsx(Skeleton, { variant: 'rectangular', width: '100%', height: screenMaxHeight || SCREEN_MAX_HEIGHT }));
26
+ }
27
+ case itemType === ItemType.DOCUMENT: {
28
+ return (_jsxs(_Fragment, { children: [_jsx(Skeleton, { variant: 'text' }), _jsx(Skeleton, { variant: 'text' }), _jsx(Skeleton, { variant: 'text' })] }));
29
+ }
30
+ default: {
31
+ return _jsx(Skeleton, { variant: 'rectangular', width: '100%' });
32
+ }
33
+ }
34
+ };
35
+ export default ItemSkeleton;
@@ -0,0 +1,43 @@
1
+ import { LinkItemType } from '@lnco-ai/sdk';
2
+ type LinkItemProps = {
3
+ /**
4
+ * Id of the component used for testing
5
+ */
6
+ id?: string;
7
+ /**
8
+ * Id of the current member used for saving the resizing preferences
9
+ */
10
+ memberId?: string;
11
+ errorMessage?: string;
12
+ height?: number | string;
13
+ /**
14
+ * whether the link can be resized
15
+ */
16
+ isResizable?: boolean;
17
+ item: LinkItemType;
18
+ /**
19
+ * Thumbnail url of the item
20
+ */
21
+ thumbnail?: string;
22
+ loadingMessage?: string;
23
+ /**
24
+ * whether the caption should be displayed
25
+ */
26
+ showCaption?: boolean;
27
+ /**
28
+ * whether the iframe should be displayed
29
+ */
30
+ showIframe?: boolean;
31
+ /**
32
+ * whether the button should be displayed
33
+ */
34
+ showButton?: boolean;
35
+ /**
36
+ * whether the component should be collapse
37
+ */
38
+ showCollapse?: boolean;
39
+ onClick?: () => void;
40
+ onCollapse?: (c: boolean) => void;
41
+ };
42
+ declare const _default: import("react").MemoExoticComponent<({ id, item, thumbnail, memberId, showCaption, showIframe, showButton, loadingMessage, height: defaultHeight, errorMessage, isResizable, showCollapse, onClick, onCollapse, }: LinkItemProps) => JSX.Element>;
43
+ export default _default;
@@ -0,0 +1,97 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Alert, Box, Link as MUILink, styled } from '@mui/material';
3
+ import { Fragment, memo, useEffect, useState } from 'react';
4
+ import { getLinkExtra } from '@lnco-ai/sdk';
5
+ import LinkCard from '../Card/LinkCard.js';
6
+ import withCollapse from '../Collapse/withCollapse.js';
7
+ import { DEFAULT_LINK_SHOW_BUTTON } from '../constants.js';
8
+ import { ITEM_MAX_HEIGHT } from './constants.js';
9
+ import { iframeCommonStyles } from './iframeStyles.js';
10
+ import withCaption from './withCaption.js';
11
+ import withResizing from './withResizing.js';
12
+ const StyledIFrame = styled('iframe')(({ isResizable, height }) => ({
13
+ ...iframeCommonStyles,
14
+ maxHeight: !isResizable ? ITEM_MAX_HEIGHT : undefined,
15
+ height: !isResizable ? height : '100%',
16
+ }));
17
+ function isURLExternal(url) {
18
+ try {
19
+ return new URL(url).origin !== window.location.origin;
20
+ }
21
+ catch {
22
+ return false;
23
+ }
24
+ }
25
+ const IFrameContainer = styled('div')(({ theme }) => ({
26
+ width: '100%',
27
+ backgroundColor: '#eee',
28
+ borderRadius: theme.spacing(2),
29
+ display: 'flex',
30
+ alignItems: 'center',
31
+ justifyContent: 'center',
32
+ flexGrow: 1,
33
+ height: '100%',
34
+ maxHeight: ITEM_MAX_HEIGHT,
35
+ overflow: 'auto',
36
+ }));
37
+ const LinkIframe = ({ id, url, title, height, isResizable, isLoading, onDoneLoading, itemId, memberId, loadingMessage, }) => {
38
+ const iframe = (_jsx(StyledIFrame, { sx: { display: isLoading ? 'unset' : 'block' }, height: height, width: '100%', id: id, isResizable: isResizable, onLoad: onDoneLoading, src: url, title: title }));
39
+ const ResizableLink = withResizing({
40
+ height,
41
+ component: iframe,
42
+ memberId,
43
+ itemId,
44
+ });
45
+ return (_jsxs(_Fragment, { children: [_jsx(IFrameContainer, { sx: { display: isLoading ? 'flex' : 'none' }, children: loadingMessage }), isResizable ? _jsx(ResizableLink, {}) : iframe] }));
46
+ };
47
+ const LinkItem = ({ id, item, thumbnail, memberId, showCaption = true, showIframe = false, showButton = DEFAULT_LINK_SHOW_BUTTON, loadingMessage = 'Link is Loading...', height: defaultHeight = 400, errorMessage = 'The link is malformed.', isResizable = false, showCollapse = false, onClick, onCollapse, }) => {
48
+ const [isLoading, setIsLoading] = useState(true);
49
+ const [height] = useState(defaultHeight);
50
+ const { id: itemId, name } = item;
51
+ const extra = getLinkExtra(item.extra);
52
+ const html = extra?.html;
53
+ // default case is an iframe with given link
54
+ const url = extra?.url;
55
+ useEffect(() => {
56
+ if (!isLoading) {
57
+ setIsLoading(true);
58
+ }
59
+ }, [url]);
60
+ const CaptionWrapper = withCaption({
61
+ item,
62
+ });
63
+ const getComponent = () => {
64
+ if (!url) {
65
+ return _jsx(Alert, { severity: 'error', children: errorMessage });
66
+ }
67
+ const isExternal = isURLExternal(url);
68
+ const linkCard = (_jsx(LinkCard, { id: id, thumbnail: thumbnail ?? item.extra.embeddedLink.icons?.[0], title: item.name, url: url, description: item.extra.embeddedLink.description ?? '', onClick: onClick, isExternal: isExternal }));
69
+ if (showIframe) {
70
+ // for rich media we use the provided html
71
+ // this is highly unsafe, and could allow XSS vulnerability if the backend does not protect this property
72
+ if (html) {
73
+ return (_jsx(Box
74
+ // this is allows for the box to not really exist and instead display the children box
75
+ // we can not get rid of this div as we need a way to attach the onClick handler for registering actions
76
+ , {
77
+ // this is allows for the box to not really exist and instead display the children box
78
+ // we can not get rid of this div as we need a way to attach the onClick handler for registering actions
79
+ display: 'contents', id: id, onClick: onClick, dangerouslySetInnerHTML: { __html: html } }));
80
+ }
81
+ return (_jsxs(Fragment, { children: [_jsx(LinkIframe, { id: id, url: url, isResizable: isResizable, height: height, title: name, isLoading: isLoading, onDoneLoading: () => setIsLoading(false), itemId: itemId, memberId: memberId, loadingMessage: loadingMessage }), showButton && linkCard] }));
82
+ }
83
+ if (showButton) {
84
+ return linkCard;
85
+ }
86
+ return (_jsx(MUILink, { href: url, onClick: onClick, children: url }));
87
+ };
88
+ let linkItem = getComponent();
89
+ if (showCaption) {
90
+ linkItem = CaptionWrapper(linkItem);
91
+ }
92
+ if (showCollapse) {
93
+ linkItem = withCollapse({ item: { name }, onCollapse })(linkItem);
94
+ }
95
+ return linkItem;
96
+ };
97
+ export default memo(LinkItem);
@@ -0,0 +1,6 @@
1
+ import { ReactNode } from 'react';
2
+ import { MaxWidth } from '@lnco-ai/sdk';
3
+ export declare const SizingWrapper: ({ size, children, }: {
4
+ size?: MaxWidth;
5
+ children: ReactNode;
6
+ }) => JSX.Element;
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box } from '@mui/material';
3
+ import { MaxWidth } from '@lnco-ai/sdk';
4
+ const getWidthFromSizing = (size) => {
5
+ switch (size) {
6
+ case MaxWidth.ExtraSmall:
7
+ return '100px';
8
+ case MaxWidth.Small:
9
+ return '200px';
10
+ case MaxWidth.Medium:
11
+ return '400px';
12
+ case MaxWidth.Large:
13
+ return '800px';
14
+ // default is for the element to take all available horizontal space
15
+ case MaxWidth.ExtraLarge:
16
+ default:
17
+ return '100%';
18
+ }
19
+ };
20
+ export const SizingWrapper = ({ size = MaxWidth.ExtraLarge, children, }) => {
21
+ const width = getWidthFromSizing(size);
22
+ return (_jsx(Box, { maxWidth: '100%', width: width, children: children }));
23
+ };
@@ -0,0 +1,27 @@
1
+ import { DiscriminatedItem, LocalContext, UUID } from '@lnco-ai/sdk';
2
+ export type Token = string;
3
+ declare const CALIBRATION_FONT_SIZES: readonly ["small", "normal", "large", "extra-large"];
4
+ type CalibrationFontSize = (typeof CALIBRATION_FONT_SIZES)[number];
5
+ type ScreenCalibration = {
6
+ scale?: number;
7
+ fontSize?: CalibrationFontSize;
8
+ participantId?: string;
9
+ participantCode?: string;
10
+ };
11
+ export type ContextPayload = Pick<LocalContext, 'apiHost' | 'itemId' | 'settings' | 'permission' | 'lang' | 'context' | 'accountId'> & {
12
+ screenCalibration?: ScreenCalibration;
13
+ };
14
+ declare const useAppCommunication: ({ item, contextPayload, appUrl, iFrameRef, requestApiAccessToken, }: {
15
+ item: DiscriminatedItem;
16
+ appUrl: string;
17
+ contextPayload: ContextPayload;
18
+ iFrameRef: React.RefObject<HTMLIFrameElement>;
19
+ requestApiAccessToken: (payload: {
20
+ id: UUID;
21
+ key: string;
22
+ origin: string;
23
+ }) => Promise<{
24
+ token: Token;
25
+ }>;
26
+ }) => void;
27
+ export { useAppCommunication };
@@ -0,0 +1,124 @@
1
+ import { useEffect } from 'react';
2
+ const CALIBRATION_FONT_SIZES = [
3
+ 'small',
4
+ 'normal',
5
+ 'large',
6
+ 'extra-large',
7
+ ];
8
+ const isCalibrationFontSize = (value) => typeof value === 'string' &&
9
+ CALIBRATION_FONT_SIZES.includes(value);
10
+ const buildPostMessageKeys = (itemId) => ({
11
+ GET_CONTEXT_SUCCESS: `GET_CONTEXT_SUCCESS_${itemId}`,
12
+ GET_CONTEXT_FAILURE: `GET_CONTEXT_FAILURE_${itemId}`,
13
+ GET_CONTEXT: `GET_CONTEXT_${itemId}`,
14
+ GET_AUTH_TOKEN: `GET_AUTH_TOKEN_${itemId}`,
15
+ GET_AUTH_TOKEN_SUCCESS: `GET_AUTH_TOKEN_SUCCESS_${itemId}`,
16
+ GET_AUTH_TOKEN_FAILURE: `GET_AUTH_TOKEN_FAILURE_${itemId}`,
17
+ POST_AUTO_RESIZE: `POST_AUTO_RESIZE_${itemId}`,
18
+ POST_CALIBRATION_SCALE: `POST_CALIBRATION_SCALE_${itemId}`,
19
+ });
20
+ const useAppCommunication = ({ item, contextPayload, appUrl, iFrameRef, requestApiAccessToken, }) => {
21
+ useEffect(() => {
22
+ // receive message from app through MessageChannel
23
+ const setupOnMessage = (port) => async (e) => {
24
+ const { data, origin: requestOrigin } = e;
25
+ const POST_MESSAGE_KEYS = buildPostMessageKeys(item.id);
26
+ // responds only to corresponding app
27
+ if (!appUrl?.includes(requestOrigin)) {
28
+ return;
29
+ }
30
+ const { type, payload } = JSON.parse(data);
31
+ switch (type) {
32
+ case POST_MESSAGE_KEYS.GET_AUTH_TOKEN: {
33
+ port.postMessage(JSON.stringify({
34
+ type: POST_MESSAGE_KEYS.GET_AUTH_TOKEN_SUCCESS,
35
+ payload: await requestApiAccessToken({
36
+ id: item.id,
37
+ ...payload,
38
+ }),
39
+ }));
40
+ break;
41
+ }
42
+ case POST_MESSAGE_KEYS.POST_AUTO_RESIZE: {
43
+ // item should not be manually resizable
44
+ if (item.settings.isResizable) {
45
+ return;
46
+ }
47
+ // iframe must be mounted
48
+ if (iFrameRef.current === null) {
49
+ return;
50
+ }
51
+ // payload should be number
52
+ if (typeof payload !== 'number') {
53
+ return;
54
+ }
55
+ iFrameRef.current.height = payload.toString();
56
+ break;
57
+ }
58
+ case POST_MESSAGE_KEYS.POST_CALIBRATION_SCALE: {
59
+ const { scale, fontSize, participantId, participantCode } = payload?.screenCalibration ?? {};
60
+ if (scale === undefined && fontSize === undefined)
61
+ return;
62
+ if (scale !== undefined &&
63
+ (typeof scale !== 'number' ||
64
+ Number.isNaN(scale) ||
65
+ scale <= 0.5 ||
66
+ scale >= 3))
67
+ return;
68
+ if (fontSize !== undefined && !isCalibrationFontSize(fontSize))
69
+ return;
70
+ try {
71
+ localStorage.setItem('lnco_screen_calibration', JSON.stringify({
72
+ screenCalibration: {
73
+ ...(scale !== undefined && { scale }),
74
+ ...(fontSize !== undefined && { fontSize }),
75
+ ...(participantId !== undefined && { participantId }),
76
+ ...(participantCode !== undefined && { participantCode }),
77
+ },
78
+ timestamp: Date.now(),
79
+ calibrationAppId: item.id,
80
+ }));
81
+ }
82
+ catch {
83
+ return;
84
+ }
85
+ break;
86
+ }
87
+ }
88
+ };
89
+ const windowOnMessage = (e) => {
90
+ const { data, origin: requestOrigin } = e;
91
+ const POST_MESSAGE_KEYS = buildPostMessageKeys(item.id);
92
+ // responds only to corresponding app
93
+ if (!appUrl?.includes(requestOrigin)) {
94
+ return;
95
+ }
96
+ // return context data and message channel port to app
97
+ const { type } = JSON.parse(data);
98
+ if (type === POST_MESSAGE_KEYS.GET_CONTEXT) {
99
+ // create/reset channel and
100
+ // Listen for messages on port1
101
+ const channel = new MessageChannel();
102
+ const { port1 } = channel;
103
+ port1.onmessage = setupOnMessage(port1);
104
+ // ensure to only send the message to the domain where the app is hosted for security reasons
105
+ const targetOrigin = new URL(appUrl).origin;
106
+ // Transfer port2 to the iframe
107
+ // provide port2 to app and item's data
108
+ iFrameRef?.current?.contentWindow?.postMessage(JSON.stringify({
109
+ type: POST_MESSAGE_KEYS.GET_CONTEXT_SUCCESS,
110
+ payload: {
111
+ /**
112
+ * Legacy for old apps or apps that does not use apps-query-client
113
+ */
114
+ memberId: contextPayload.accountId,
115
+ ...contextPayload,
116
+ },
117
+ }), targetOrigin, [channel.port2]);
118
+ }
119
+ };
120
+ window.addEventListener('message', windowOnMessage);
121
+ return () => window.removeEventListener('message', windowOnMessage);
122
+ }, [item, iFrameRef]);
123
+ };
124
+ export { useAppCommunication };
@@ -0,0 +1 @@
1
+ export declare const ITEM_MAX_HEIGHT = "70vh";
@@ -0,0 +1 @@
1
+ export const ITEM_MAX_HEIGHT = '70vh';
@@ -0,0 +1,4 @@
1
+ export declare const iframeCommonStyles: {
2
+ border: string;
3
+ width: string;
4
+ };
@@ -0,0 +1,5 @@
1
+ export const iframeCommonStyles = {
2
+ // remove ugly borders
3
+ border: 'none',
4
+ width: '100%',
5
+ };
@@ -0,0 +1,5 @@
1
+ export { default as AppItem } from './AppItem.js';
2
+ export { default as EtherpadItem } from './EtherpadItem.js';
3
+ export { default as FileItem } from './FileItem.js';
4
+ export { default as H5PItem } from './H5PItem.js';
5
+ export { default as LinkItem } from './LinkItem.js';
@@ -0,0 +1,5 @@
1
+ export { default as AppItem } from './AppItem.js';
2
+ export { default as EtherpadItem } from './EtherpadItem.js';
3
+ export { default as FileItem } from './FileItem.js';
4
+ export { default as H5PItem } from './H5PItem.js';
5
+ export { default as LinkItem } from './LinkItem.js';