mirror of https://github.com/fantasticit/think.git
feat: support preview pdf, image, audio and video
This commit is contained in:
parent
b290a2305d
commit
39cf943eaa
|
@ -76,6 +76,7 @@
|
||||||
"react": "17.0.2",
|
"react": "17.0.2",
|
||||||
"react-dom": "17.0.2",
|
"react-dom": "17.0.2",
|
||||||
"react-helmet": "^6.1.0",
|
"react-helmet": "^6.1.0",
|
||||||
|
"react-pdf": "^5.7.2",
|
||||||
"react-split-pane": "^0.1.92",
|
"react-split-pane": "^0.1.92",
|
||||||
"scroll-into-view-if-needed": "^2.2.29",
|
"scroll-into-view-if-needed": "^2.2.29",
|
||||||
"swr": "^1.2.0",
|
"swr": "^1.2.0",
|
||||||
|
|
|
@ -2,12 +2,13 @@ import { useEffect } from 'react';
|
||||||
import Viewer from 'viewerjs';
|
import Viewer from 'viewerjs';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
containerSelector: string;
|
containerSelector?: string;
|
||||||
|
container?: HTMLElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ImageViewer: React.FC<IProps> = ({ containerSelector }) => {
|
export const ImageViewer: React.FC<IProps> = ({ container, containerSelector }) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const el = document.querySelector(containerSelector);
|
const el = container || document.querySelector(containerSelector);
|
||||||
if (!el) {
|
if (!el) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -24,7 +25,7 @@ export const ImageViewer: React.FC<IProps> = ({ containerSelector }) => {
|
||||||
io.disconnect();
|
io.disconnect();
|
||||||
viewer.destroy();
|
viewer.destroy();
|
||||||
};
|
};
|
||||||
}, [containerSelector]);
|
}, [container, containerSelector]);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,11 +31,13 @@ export const normalizeFileSize = (size) => {
|
||||||
return (size / 1024 / 1024).toFixed(2) + ' MB';
|
return (size / 1024 / 1024).toFixed(2) + ' MB';
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FileType = 'image' | 'audio' | 'video' | 'file';
|
export type FileType = 'image' | 'audio' | 'video' | 'pdf' | 'file';
|
||||||
|
|
||||||
export const normalizeFileType = (fileType): FileType => {
|
export const normalizeFileType = (fileType): FileType => {
|
||||||
if (!fileType) return 'file';
|
if (!fileType) return 'file';
|
||||||
|
|
||||||
|
if (fileType === 'application/pdf') return 'pdf';
|
||||||
|
|
||||||
if (fileType.startsWith('image')) {
|
if (fileType.startsWith('image')) {
|
||||||
return 'image';
|
return 'image';
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { IconFile, IconSong, IconVideo, IconImage } from '@douyinfe/semi-icons';
|
||||||
|
import { normalizeFileType } from '../../services/file';
|
||||||
|
|
||||||
|
export const getFileTypeIcon = (fileType: string) => {
|
||||||
|
const type = normalizeFileType(fileType);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'audio':
|
||||||
|
return <IconSong />;
|
||||||
|
|
||||||
|
case 'video':
|
||||||
|
return <IconVideo />;
|
||||||
|
|
||||||
|
case 'file':
|
||||||
|
return <IconFile />;
|
||||||
|
|
||||||
|
case 'image':
|
||||||
|
return <IconImage />;
|
||||||
|
|
||||||
|
case 'pdf':
|
||||||
|
return <IconFile />;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
const value: never = type;
|
||||||
|
throw new Error(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,12 +1,17 @@
|
||||||
.wrap {
|
.wrap {
|
||||||
|
border: 1px solid var(--semi-color-border);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
|
||||||
|
&.isPreviewing {
|
||||||
|
&::after {
|
||||||
|
background-color: transparent !important ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> div:first-child {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
border: 1px solid var(--semi-color-border);
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border: 1px solid var(--semi-color-link);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,51 +2,18 @@ import { useEffect, useRef } from 'react';
|
||||||
import cls from 'classnames';
|
import cls from 'classnames';
|
||||||
import { NodeViewWrapper, NodeViewContent } from '@tiptap/react';
|
import { NodeViewWrapper, NodeViewContent } from '@tiptap/react';
|
||||||
import { Button, Typography, Spin, Collapsible, Space } from '@douyinfe/semi-ui';
|
import { Button, Typography, Spin, Collapsible, Space } from '@douyinfe/semi-ui';
|
||||||
import {
|
import { IconDownload, IconPlayCircle, IconClose } from '@douyinfe/semi-icons';
|
||||||
IconDownload,
|
|
||||||
IconPlayCircle,
|
|
||||||
IconFile,
|
|
||||||
IconSong,
|
|
||||||
IconVideo,
|
|
||||||
IconImage,
|
|
||||||
IconClose,
|
|
||||||
} from '@douyinfe/semi-icons';
|
|
||||||
import { Tooltip } from 'components/tooltip';
|
import { Tooltip } from 'components/tooltip';
|
||||||
import { useToggle } from 'hooks/use-toggle';
|
import { useToggle } from 'hooks/use-toggle';
|
||||||
import { download } from '../../services/download';
|
import { download } from '../../services/download';
|
||||||
import { uploadFile } from 'services/file';
|
import { uploadFile } from 'services/file';
|
||||||
import {
|
import { normalizeFileSize, extractFileExtension, extractFilename } from '../../services/file';
|
||||||
normalizeFileSize,
|
import { Player } from './player';
|
||||||
extractFileExtension,
|
import { getFileTypeIcon } from './file-icon';
|
||||||
extractFilename,
|
|
||||||
normalizeFileType,
|
|
||||||
FileType,
|
|
||||||
} from '../../services/file';
|
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
const { Text } = Typography;
|
const { Text } = Typography;
|
||||||
|
|
||||||
const getFileTypeIcon = (type: FileType) => {
|
|
||||||
switch (type) {
|
|
||||||
case 'audio':
|
|
||||||
return <IconSong />;
|
|
||||||
|
|
||||||
case 'video':
|
|
||||||
return <IconVideo />;
|
|
||||||
|
|
||||||
case 'file':
|
|
||||||
return <IconFile />;
|
|
||||||
|
|
||||||
case 'image':
|
|
||||||
return <IconImage />;
|
|
||||||
|
|
||||||
default: {
|
|
||||||
const value: never = type;
|
|
||||||
throw new Error(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const AttachmentWrapper = ({ editor, node, updateAttributes }) => {
|
export const AttachmentWrapper = ({ editor, node, updateAttributes }) => {
|
||||||
const $upload = useRef<HTMLInputElement>();
|
const $upload = useRef<HTMLInputElement>();
|
||||||
const isEditable = editor.isEditable;
|
const isEditable = editor.isEditable;
|
||||||
|
@ -78,8 +45,6 @@ export const AttachmentWrapper = ({ editor, node, updateAttributes }) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const type = normalizeFileType(fileType);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!url && !hasTrigger) {
|
if (!url && !hasTrigger) {
|
||||||
selectFile();
|
selectFile();
|
||||||
|
@ -88,7 +53,7 @@ export const AttachmentWrapper = ({ editor, node, updateAttributes }) => {
|
||||||
}, [url, hasTrigger]);
|
}, [url, hasTrigger]);
|
||||||
|
|
||||||
const content = (() => {
|
const content = (() => {
|
||||||
if (error) {
|
if (error !== 'null') {
|
||||||
return (
|
return (
|
||||||
<div className={cls(styles.wrap, 'render-wrapper')} onClick={selectFile}>
|
<div className={cls(styles.wrap, 'render-wrapper')} onClick={selectFile}>
|
||||||
<Text>{error}</Text>
|
<Text>{error}</Text>
|
||||||
|
@ -99,17 +64,17 @@ export const AttachmentWrapper = ({ editor, node, updateAttributes }) => {
|
||||||
if (url) {
|
if (url) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={cls(styles.wrap, 'render-wrapper')} onClick={selectFile}>
|
<div className={cls(styles.wrap, visible && styles.isPreviewing, 'render-wrapper')} onClick={selectFile}>
|
||||||
|
<div>
|
||||||
<Space>
|
<Space>
|
||||||
{getFileTypeIcon(type)}
|
{getFileTypeIcon(fileType)}
|
||||||
<Text ellipsis={{ showTooltip: true }} style={{ maxWidth: 320 }}>
|
<Text ellipsis={{ showTooltip: true }} style={{ maxWidth: 320 }}>
|
||||||
{fileName}.{fileExt}
|
{fileName}.{fileExt}
|
||||||
</Text>
|
</Text>
|
||||||
<Text type="tertiary"> ({normalizeFileSize(fileSize)})</Text>
|
<Text type="tertiary"> ({normalizeFileSize(fileSize)})</Text>
|
||||||
</Space>
|
</Space>
|
||||||
<span>
|
<span>
|
||||||
{type === 'video' || type === 'audio' ? (
|
<Tooltip content={!visible ? '预览' : '收起'}>
|
||||||
<Tooltip content={!visible ? '播放' : '收起'}>
|
|
||||||
<Button
|
<Button
|
||||||
theme={'borderless'}
|
theme={'borderless'}
|
||||||
type="tertiary"
|
type="tertiary"
|
||||||
|
@ -117,7 +82,6 @@ export const AttachmentWrapper = ({ editor, node, updateAttributes }) => {
|
||||||
onClick={toggleVisible}
|
onClick={toggleVisible}
|
||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
) : null}
|
|
||||||
<Tooltip content="下载">
|
<Tooltip content="下载">
|
||||||
<Button
|
<Button
|
||||||
theme={'borderless'}
|
theme={'borderless'}
|
||||||
|
@ -128,13 +92,12 @@ export const AttachmentWrapper = ({ editor, node, updateAttributes }) => {
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{url ? (
|
{url ? (
|
||||||
<Collapsible isOpen={visible}>
|
<Collapsible isOpen={visible}>
|
||||||
{type === 'video' && <video controls autoPlay src={url}></video>}
|
<Player fileType={fileType} url={url} />
|
||||||
{type === 'audio' && <audio controls autoPlay src={url}></audio>}
|
|
||||||
</Collapsible>
|
</Collapsible>
|
||||||
) : null}
|
) : null}
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
.playerWrap {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
border-top: 1px solid var(--semi-color-border);
|
||||||
|
padding: 12px;
|
||||||
|
|
||||||
|
> video {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
import React, { useMemo, useRef } from 'react';
|
||||||
|
import { Typography } from '@douyinfe/semi-ui';
|
||||||
|
import { ImageViewer } from 'components/image-viewer';
|
||||||
|
import {
|
||||||
|
normalizeFileSize,
|
||||||
|
extractFileExtension,
|
||||||
|
extractFilename,
|
||||||
|
normalizeFileType,
|
||||||
|
FileType,
|
||||||
|
} from '../../../services/file';
|
||||||
|
import { PDFPlayer } from './pdf-player';
|
||||||
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
url: string;
|
||||||
|
fileType: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { Text } = Typography;
|
||||||
|
|
||||||
|
export const Player: React.FC<IProps> = ({ url, fileType }) => {
|
||||||
|
const ref = useRef();
|
||||||
|
const type = useMemo(() => normalizeFileType(fileType), [fileType]);
|
||||||
|
|
||||||
|
const player = useMemo(() => {
|
||||||
|
if (type === 'video') return <video controls autoPlay src={url}></video>;
|
||||||
|
|
||||||
|
if (type === 'audio') return <audio controls autoPlay src={url}></audio>;
|
||||||
|
|
||||||
|
if (type === 'image')
|
||||||
|
return <img style={{ width: 'auto', height: 'auto', maxWidth: '100%', maxHeight: 300 }} src={url} />;
|
||||||
|
|
||||||
|
if (type === 'pdf') return <PDFPlayer url={url} />;
|
||||||
|
|
||||||
|
return <Text type="tertiary">暂不支持预览该类型文件</Text>;
|
||||||
|
}, [type, url]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div ref={ref} className={styles.playerWrap}>
|
||||||
|
{player}
|
||||||
|
</div>
|
||||||
|
<ImageViewer container={ref.current} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,37 @@
|
||||||
|
.playerWrap {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
:global {
|
||||||
|
.react-pdf__Document {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-pdf__Page {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 420px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-pdf__Page canvas {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-pdf__message {
|
||||||
|
padding: 20px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.paginationWrap {
|
||||||
|
margin-top: 1em;
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Document, Page, pdfjs } from 'react-pdf';
|
||||||
|
import { Pagination } from '@douyinfe/semi-ui';
|
||||||
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
|
pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/legacy/build/pdf.worker.min.js`;
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PDFPlayer: React.FC<IProps> = ({ url }) => {
|
||||||
|
const [total, setTotal] = useState(1);
|
||||||
|
const [pageNumber, setPageNumber] = useState(1);
|
||||||
|
|
||||||
|
function onDocumentLoadSuccess({ numPages }) {
|
||||||
|
setTotal(numPages);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.playerWrap}>
|
||||||
|
<Document file={url} onLoadSuccess={onDocumentLoadSuccess}>
|
||||||
|
<Page pageNumber={pageNumber} />
|
||||||
|
</Document>
|
||||||
|
<div className={styles.paginationWrap}>
|
||||||
|
<Pagination total={total} pageSize={1} onChange={(page) => setPageNumber(page)} size="small"></Pagination>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -104,6 +104,7 @@ importers:
|
||||||
react: 17.0.2
|
react: 17.0.2
|
||||||
react-dom: 17.0.2
|
react-dom: 17.0.2
|
||||||
react-helmet: ^6.1.0
|
react-helmet: ^6.1.0
|
||||||
|
react-pdf: ^5.7.2
|
||||||
react-split-pane: ^0.1.92
|
react-split-pane: ^0.1.92
|
||||||
scroll-into-view-if-needed: ^2.2.29
|
scroll-into-view-if-needed: ^2.2.29
|
||||||
swr: ^1.2.0
|
swr: ^1.2.0
|
||||||
|
@ -182,6 +183,7 @@ importers:
|
||||||
react: 17.0.2
|
react: 17.0.2
|
||||||
react-dom: 17.0.2_react@17.0.2
|
react-dom: 17.0.2_react@17.0.2
|
||||||
react-helmet: 6.1.0_react@17.0.2
|
react-helmet: 6.1.0_react@17.0.2
|
||||||
|
react-pdf: 5.7.2_react-dom@17.0.2+react@17.0.2
|
||||||
react-split-pane: 0.1.92_react-dom@17.0.2+react@17.0.2
|
react-split-pane: 0.1.92_react-dom@17.0.2+react@17.0.2
|
||||||
scroll-into-view-if-needed: 2.2.29
|
scroll-into-view-if-needed: 2.2.29
|
||||||
swr: 1.2.0_react@17.0.2
|
swr: 1.2.0_react@17.0.2
|
||||||
|
@ -3871,6 +3873,16 @@ packages:
|
||||||
flat-cache: 3.0.4
|
flat-cache: 3.0.4
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/file-loader/6.2.0:
|
||||||
|
resolution: {integrity: sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==}
|
||||||
|
engines: {node: '>= 10.13.0'}
|
||||||
|
peerDependencies:
|
||||||
|
webpack: ^4.0.0 || ^5.0.0
|
||||||
|
dependencies:
|
||||||
|
loader-utils: 2.0.0
|
||||||
|
schema-utils: 3.1.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/file-uri-to-path/2.0.0:
|
/file-uri-to-path/2.0.0:
|
||||||
resolution: {integrity: sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==}
|
resolution: {integrity: sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==}
|
||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
|
@ -5591,6 +5603,10 @@ packages:
|
||||||
sourcemap-codec: 1.4.8
|
sourcemap-codec: 1.4.8
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/make-cancellable-promise/1.1.0:
|
||||||
|
resolution: {integrity: sha512-X5Opjm2xcZsOLuJ+Bnhb4t5yfu4ehlA3OKEYLtqUchgVzL/QaqW373ZUVxVHKwvJ38cmYuR4rAHD2yUvAIkTPA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/make-dir/3.1.0:
|
/make-dir/3.1.0:
|
||||||
resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
|
resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
@ -5602,6 +5618,10 @@ packages:
|
||||||
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
|
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/make-event-props/1.3.0:
|
||||||
|
resolution: {integrity: sha512-oWiDZMcVB1/A487251hEWza1xzgCzl6MXxe9aF24l5Bt9N9UEbqTqKumEfuuLhmlhRZYnc+suVvW4vUs8bwO7Q==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/makeerror/1.0.12:
|
/makeerror/1.0.12:
|
||||||
resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==}
|
resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -5696,10 +5716,18 @@ packages:
|
||||||
yargs-parser: 20.2.9
|
yargs-parser: 20.2.9
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/merge-class-names/1.4.2:
|
||||||
|
resolution: {integrity: sha512-bOl98VzwCGi25Gcn3xKxnR5p/WrhWFQB59MS/aGENcmUc6iSm96yrFDF0XSNurX9qN4LbJm0R9kfvsQ17i8zCw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/merge-descriptors/1.0.1:
|
/merge-descriptors/1.0.1:
|
||||||
resolution: {integrity: sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=}
|
resolution: {integrity: sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/merge-refs/1.0.0:
|
||||||
|
resolution: {integrity: sha512-WZ4S5wqD9FCR9hxkLgvcHJCBxzXzy3VVE6p8W2OzxRzB+hLRlcadGE2bW9xp2KSzk10rvp4y+pwwKO6JQVguMg==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/merge-stream/2.0.0:
|
/merge-stream/2.0.0:
|
||||||
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
|
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -6250,6 +6278,15 @@ packages:
|
||||||
resolution: {integrity: sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=}
|
resolution: {integrity: sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/pdfjs-dist/2.12.313:
|
||||||
|
resolution: {integrity: sha512-1x6iXO4Qnv6Eb+YFdN5JdUzt4pAkxSp3aLAYPX93eQCyg/m7QFzXVWJHJVtoW48CI8HCXju4dSkhQZwoheL5mA==}
|
||||||
|
peerDependencies:
|
||||||
|
worker-loader: ^3.0.8
|
||||||
|
peerDependenciesMeta:
|
||||||
|
worker-loader:
|
||||||
|
optional: true
|
||||||
|
dev: false
|
||||||
|
|
||||||
/picocolors/0.2.1:
|
/picocolors/0.2.1:
|
||||||
resolution: {integrity: sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==}
|
resolution: {integrity: sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==}
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -6672,6 +6709,29 @@ packages:
|
||||||
resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==}
|
resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/react-pdf/5.7.2_react-dom@17.0.2+react@17.0.2:
|
||||||
|
resolution: {integrity: sha512-hdDwvf007V0i2rPCqQVS1fa70CXut17SN3laJYlRHzuqcu8sLLjEoeXihty6c0Ev5g1mw31b8OT8EwRw1s8C4g==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^16.3.0 || ^17.0.0 || ^18.0.0
|
||||||
|
react-dom: ^16.3.0 || ^17.0.0 || ^18.0.0
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.16.7
|
||||||
|
file-loader: 6.2.0
|
||||||
|
make-cancellable-promise: 1.1.0
|
||||||
|
make-event-props: 1.3.0
|
||||||
|
merge-class-names: 1.4.2
|
||||||
|
merge-refs: 1.0.0
|
||||||
|
pdfjs-dist: 2.12.313
|
||||||
|
prop-types: 15.8.1
|
||||||
|
react: 17.0.2
|
||||||
|
react-dom: 17.0.2_react@17.0.2
|
||||||
|
tiny-invariant: 1.2.0
|
||||||
|
tiny-warning: 1.0.3
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- webpack
|
||||||
|
- worker-loader
|
||||||
|
dev: false
|
||||||
|
|
||||||
/react-resizable/1.11.1_react-dom@17.0.2+react@17.0.2:
|
/react-resizable/1.11.1_react-dom@17.0.2+react@17.0.2:
|
||||||
resolution: {integrity: sha512-S70gbLaAYqjuAd49utRHibtHLrHXInh7GuOR+6OO6RO6uleQfuBnWmZjRABfqNEx3C3Z6VPLg0/0uOYFrkfu9Q==}
|
resolution: {integrity: sha512-S70gbLaAYqjuAd49utRHibtHLrHXInh7GuOR+6OO6RO6uleQfuBnWmZjRABfqNEx3C3Z6VPLg0/0uOYFrkfu9Q==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -7737,6 +7797,14 @@ packages:
|
||||||
/through/2.3.8:
|
/through/2.3.8:
|
||||||
resolution: {integrity: sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=}
|
resolution: {integrity: sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=}
|
||||||
|
|
||||||
|
/tiny-invariant/1.2.0:
|
||||||
|
resolution: {integrity: sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/tiny-warning/1.0.3:
|
||||||
|
resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/tippy.js/6.3.7:
|
/tippy.js/6.3.7:
|
||||||
resolution: {integrity: sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==}
|
resolution: {integrity: sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
Loading…
Reference in New Issue