mirror of
https://github.com/laurent22/joplin.git
synced 2025-01-02 12:47:41 +02:00
Desktop: Add zoom feature on PDF viewer (#6748)
This commit is contained in:
parent
ae300de42f
commit
6498f94c36
@ -842,12 +842,12 @@ packages/app-mobile/components/BackButtonDialogBox.js.map
|
||||
packages/app-mobile/components/CameraView.d.ts
|
||||
packages/app-mobile/components/CameraView.js
|
||||
packages/app-mobile/components/CameraView.js.map
|
||||
packages/app-mobile/components/Dropdown.d.ts
|
||||
packages/app-mobile/components/Dropdown.js
|
||||
packages/app-mobile/components/Dropdown.js.map
|
||||
packages/app-mobile/components/CustomButton.d.ts
|
||||
packages/app-mobile/components/CustomButton.js
|
||||
packages/app-mobile/components/CustomButton.js.map
|
||||
packages/app-mobile/components/Dropdown.d.ts
|
||||
packages/app-mobile/components/Dropdown.js
|
||||
packages/app-mobile/components/Dropdown.js.map
|
||||
packages/app-mobile/components/NoteBodyViewer/NoteBodyViewer.d.ts
|
||||
packages/app-mobile/components/NoteBodyViewer/NoteBodyViewer.js
|
||||
packages/app-mobile/components/NoteBodyViewer/NoteBodyViewer.js.map
|
||||
@ -1985,6 +1985,9 @@ packages/pdf-viewer/hooks/usePdfData.js.map
|
||||
packages/pdf-viewer/hooks/useScaledSize.d.ts
|
||||
packages/pdf-viewer/hooks/useScaledSize.js
|
||||
packages/pdf-viewer/hooks/useScaledSize.js.map
|
||||
packages/pdf-viewer/hooks/useScrollSaver.d.ts
|
||||
packages/pdf-viewer/hooks/useScrollSaver.js
|
||||
packages/pdf-viewer/hooks/useScrollSaver.js.map
|
||||
packages/pdf-viewer/main.d.ts
|
||||
packages/pdf-viewer/main.js
|
||||
packages/pdf-viewer/main.js.map
|
||||
@ -1997,6 +2000,9 @@ packages/pdf-viewer/pdfSource.js.map
|
||||
packages/pdf-viewer/pdfSource.test.d.ts
|
||||
packages/pdf-viewer/pdfSource.test.js
|
||||
packages/pdf-viewer/pdfSource.test.js.map
|
||||
packages/pdf-viewer/ui/ZoomControls.d.ts
|
||||
packages/pdf-viewer/ui/ZoomControls.js
|
||||
packages/pdf-viewer/ui/ZoomControls.js.map
|
||||
packages/plugin-repo-cli/commands/updateRelease.d.ts
|
||||
packages/plugin-repo-cli/commands/updateRelease.js
|
||||
packages/plugin-repo-cli/commands/updateRelease.js.map
|
||||
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -1974,6 +1974,9 @@ packages/pdf-viewer/hooks/usePdfData.js.map
|
||||
packages/pdf-viewer/hooks/useScaledSize.d.ts
|
||||
packages/pdf-viewer/hooks/useScaledSize.js
|
||||
packages/pdf-viewer/hooks/useScaledSize.js.map
|
||||
packages/pdf-viewer/hooks/useScrollSaver.d.ts
|
||||
packages/pdf-viewer/hooks/useScrollSaver.js
|
||||
packages/pdf-viewer/hooks/useScrollSaver.js.map
|
||||
packages/pdf-viewer/main.d.ts
|
||||
packages/pdf-viewer/main.js
|
||||
packages/pdf-viewer/main.js.map
|
||||
@ -1986,6 +1989,9 @@ packages/pdf-viewer/pdfSource.js.map
|
||||
packages/pdf-viewer/pdfSource.test.d.ts
|
||||
packages/pdf-viewer/pdfSource.test.js
|
||||
packages/pdf-viewer/pdfSource.test.js.map
|
||||
packages/pdf-viewer/ui/ZoomControls.d.ts
|
||||
packages/pdf-viewer/ui/ZoomControls.js
|
||||
packages/pdf-viewer/ui/ZoomControls.js.map
|
||||
packages/plugin-repo-cli/commands/updateRelease.d.ts
|
||||
packages/plugin-repo-cli/commands/updateRelease.js
|
||||
packages/plugin-repo-cli/commands/updateRelease.js.map
|
||||
|
@ -13,7 +13,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"buildParallel": "yarn workspaces foreach --verbose --interlaced --parallel --jobs 2 run build && yarn run tsc",
|
||||
"buildSequential": "yarn workspaces foreach --verbose --interlaced run build && yarn run tsc",
|
||||
"buildSequential": "yarn workspaces foreach --verbose --interlaced --topological run build && yarn run tsc",
|
||||
"buildApiDoc": "yarn workspace joplin start apidoc ../../readme/api/references/rest_api.md",
|
||||
"buildCommandIndex": "gulp buildCommandIndex",
|
||||
"buildPluginDoc": "typedoc --name 'Joplin Plugin API Documentation' --mode file -theme './Assets/PluginDocTheme/' --readme './Assets/PluginDocTheme/index.md' --excludeNotExported --excludeExternals --excludePrivate --excludeProtected --out ../joplin-website/docs/api/references/plugin_api packages/lib/services/plugins/api/",
|
||||
|
@ -4,6 +4,7 @@ import { PdfData } from './pdfSource';
|
||||
import Page from './Page';
|
||||
import styled from 'styled-components';
|
||||
import useScaledSize, { ScaledSizeParams } from './hooks/useScaledSize';
|
||||
import useScrollSaver, { ScrollSaver } from './hooks/useScrollSaver';
|
||||
|
||||
|
||||
const PagesHolder = styled.div<{ pageGap: number }>`
|
||||
@ -11,7 +12,8 @@ const PagesHolder = styled.div<{ pageGap: number }>`
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-flow: column;
|
||||
width: 100%;
|
||||
width: fit-content;
|
||||
min-width: 100%;
|
||||
min-height: 100%;
|
||||
row-gap: ${(props)=> props.pageGap || 2}px;
|
||||
`;
|
||||
@ -22,15 +24,16 @@ export interface VerticalPagesProps {
|
||||
anchorPage?: number;
|
||||
rememberScroll?: boolean;
|
||||
pdfId?: string;
|
||||
zoom?: number;
|
||||
container: MutableRefObject<HTMLElement>;
|
||||
pageGap?: number;
|
||||
showPageNumbers?: boolean;
|
||||
}
|
||||
|
||||
|
||||
export default function VerticalPages(props: VerticalPagesProps) {
|
||||
const [containerWidth, setContainerWidth] = useState<number>(null);
|
||||
const innerContainerEl = useRef<HTMLDivElement>(null);
|
||||
|
||||
const scaledSize = useScaledSize({
|
||||
pdf: props.pdf,
|
||||
pdfId: props.pdfId,
|
||||
@ -40,15 +43,23 @@ export default function VerticalPages(props: VerticalPagesProps) {
|
||||
container: props.container,
|
||||
innerContainerEl,
|
||||
pageGap: props.pageGap,
|
||||
zoom: props.zoom,
|
||||
} as ScaledSizeParams);
|
||||
|
||||
useScrollSaver({
|
||||
container: props.container,
|
||||
scaledSize,
|
||||
pdfId: props.pdfId,
|
||||
rememberScroll: props.rememberScroll,
|
||||
} as ScrollSaver);
|
||||
|
||||
useEffect(() => {
|
||||
let resizeTimer: number = null;
|
||||
let cancelled = false;
|
||||
|
||||
const updateWidth = () => {
|
||||
if (cancelled) return;
|
||||
setContainerWidth(innerContainerEl.current.clientWidth);
|
||||
setContainerWidth(props.container.current.clientWidth);
|
||||
};
|
||||
|
||||
const onResize = () => {
|
||||
@ -70,37 +81,7 @@ export default function VerticalPages(props: VerticalPagesProps) {
|
||||
resizeTimer = null;
|
||||
}
|
||||
};
|
||||
}, [props.pdf]);
|
||||
|
||||
useEffect(() => {
|
||||
let scrollTimer: number = null;
|
||||
|
||||
const saveScroll = () => {
|
||||
const scrollTop = props.container.current.scrollTop;
|
||||
if (props.rememberScroll && props.pdfId) {
|
||||
sessionStorage.setItem(`pdf.${props.pdfId}.scrollTop`, `${scrollTop}`);
|
||||
}
|
||||
};
|
||||
|
||||
const onScroll = () => {
|
||||
if (scrollTimer) {
|
||||
clearTimeout(scrollTimer);
|
||||
scrollTimer = null;
|
||||
}
|
||||
scrollTimer = window.setTimeout(saveScroll, 200);
|
||||
};
|
||||
|
||||
props.container.current.addEventListener('scroll', onScroll);
|
||||
|
||||
return () => {
|
||||
props.container.current.removeEventListener('scroll', onScroll);
|
||||
if (scrollTimer) {
|
||||
clearTimeout(scrollTimer);
|
||||
scrollTimer = null;
|
||||
}
|
||||
};
|
||||
|
||||
}, [props.container, props.pdfId, props.rememberScroll]);
|
||||
}, [props.container, props.pdf]);
|
||||
|
||||
return (<PagesHolder pageGap={props.pageGap || 2} ref={innerContainerEl} >
|
||||
{scaledSize ?
|
||||
|
@ -3,6 +3,7 @@ import { useEffect, useState, MutableRefObject } from 'react';
|
||||
|
||||
const useIsVisible = (elementRef: MutableRefObject<HTMLElement>, rootRef: MutableRefObject<HTMLElement>) => {
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
let observer: IntersectionObserver = null;
|
||||
if (elementRef.current) {
|
||||
|
@ -11,16 +11,18 @@ export interface ScaledSizeParams {
|
||||
container: MutableRefObject<HTMLElement>;
|
||||
innerContainerEl: MutableRefObject<HTMLElement>;
|
||||
pageGap: number;
|
||||
zoom: number;
|
||||
}
|
||||
|
||||
const useScaledSize = ({ pdf, pdfId, containerWidth, rememberScroll, anchorPage, container, innerContainerEl, pageGap }: ScaledSizeParams) => {
|
||||
const useScaledSize = ({ pdf, pdfId, containerWidth, rememberScroll, anchorPage, container, innerContainerEl, pageGap, zoom }: ScaledSizeParams) => {
|
||||
const [scaledSize, setScaledSize] = useState<ScaledSize>(null);
|
||||
const currentScaleSize = useRef(scaledSize);
|
||||
|
||||
useAsyncEffect(async (event: AsyncEffectEvent) => {
|
||||
if (!pdf || !containerWidth) return;
|
||||
// console.log('scaledSize calculation triggered');
|
||||
const scaledSize_ = await pdf.getScaledSize(null, containerWidth - 10);
|
||||
const effectiveWidth = Math.min(containerWidth - 20, 900) * (zoom || 1);
|
||||
const scaledSize_ = await pdf.getScaledSize(null, effectiveWidth);
|
||||
if (event.cancelled) return;
|
||||
|
||||
const oldScaleSize = currentScaleSize.current;
|
||||
@ -40,11 +42,12 @@ const useScaledSize = ({ pdf, pdfId, containerWidth, rememberScroll, anchorPage,
|
||||
if (rememberScroll && pdfId && !oldScaleSize && !anchorPage) {
|
||||
const scrollOffset = parseInt(sessionStorage.getItem(`pdf.${pdfId}.scrollTop`), 10) || null;
|
||||
if (scrollOffset) {
|
||||
container.current.scrollTop = scrollOffset;
|
||||
// Adjusting it according to the new scale
|
||||
container.current.scrollTop = scrollOffset * scaledSize_.scale;
|
||||
// console.log('scroll set',container.current.scrollTop);
|
||||
}
|
||||
}
|
||||
}, [pdf, pdfId, rememberScroll, anchorPage, containerWidth]);
|
||||
}, [pdf, pdfId, rememberScroll, anchorPage, containerWidth, zoom]);
|
||||
|
||||
return scaledSize;
|
||||
};
|
||||
|
53
packages/pdf-viewer/hooks/useScrollSaver.ts
Normal file
53
packages/pdf-viewer/hooks/useScrollSaver.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import { useRef, useEffect, MutableRefObject } from 'react';
|
||||
import { ScaledSize } from '../pdfSource';
|
||||
|
||||
export interface ScrollSaver {
|
||||
container: MutableRefObject<HTMLElement>;
|
||||
scaledSize: ScaledSize;
|
||||
pdfId: string;
|
||||
rememberScroll: boolean;
|
||||
}
|
||||
|
||||
const useScrollSaver = ({ container, scaledSize, pdfId, rememberScroll }: ScrollSaver) => {
|
||||
const currentScaleSize = useRef(scaledSize);
|
||||
|
||||
useEffect(() => {
|
||||
let scrollTimer: number = null;
|
||||
const containerElement = container.current;
|
||||
|
||||
const saveScroll = () => {
|
||||
if (!currentScaleSize.current) return;
|
||||
const scale = currentScaleSize.current.scale;
|
||||
const scrollTop = container.current.scrollTop / scale;
|
||||
if (rememberScroll && pdfId) {
|
||||
sessionStorage.setItem(`pdf.${pdfId}.scrollTop`, `${scrollTop}`);
|
||||
}
|
||||
};
|
||||
|
||||
const onScroll = () => {
|
||||
if (scrollTimer) {
|
||||
clearTimeout(scrollTimer);
|
||||
scrollTimer = null;
|
||||
}
|
||||
scrollTimer = window.setTimeout(saveScroll, 200);
|
||||
};
|
||||
|
||||
containerElement.addEventListener('scroll', onScroll);
|
||||
|
||||
return () => {
|
||||
containerElement.removeEventListener('scroll', onScroll);
|
||||
if (scrollTimer) {
|
||||
clearTimeout(scrollTimer);
|
||||
scrollTimer = null;
|
||||
}
|
||||
};
|
||||
}, [container, pdfId, rememberScroll, currentScaleSize]);
|
||||
|
||||
useEffect(() => {
|
||||
currentScaleSize.current = scaledSize;
|
||||
} , [scaledSize]);
|
||||
|
||||
return scaledSize;
|
||||
};
|
||||
|
||||
export default useScrollSaver;
|
@ -1,7 +1,8 @@
|
||||
import React, { useRef } from 'react';
|
||||
import React, { useRef, useState } from 'react';
|
||||
import useIsFocused from './hooks/useIsFocused';
|
||||
import usePdfData from './hooks/usePdfData';
|
||||
import VerticalPages from './VerticalPages';
|
||||
import ZoomControls from './ui/ZoomControls';
|
||||
|
||||
export interface MiniViewerAppProps {
|
||||
pdfPath: string;
|
||||
@ -13,6 +14,7 @@ export interface MiniViewerAppProps {
|
||||
export default function MiniViewerApp(props: MiniViewerAppProps) {
|
||||
const pdf = usePdfData(props.pdfPath);
|
||||
const isFocused = useIsFocused();
|
||||
const [zoom, setZoom] = useState<number>(1);
|
||||
const containerEl = useRef<HTMLDivElement>(null);
|
||||
|
||||
if (!pdf) {
|
||||
@ -25,12 +27,20 @@ export default function MiniViewerApp(props: MiniViewerAppProps) {
|
||||
return (
|
||||
<div className={`mini-app${isFocused ? ' focused' : ''}`}>
|
||||
<div className={`app-pages${isFocused ? ' focused' : ''}`} ref={containerEl}>
|
||||
<VerticalPages pdf={pdf} isDarkTheme={props.isDarkTheme} anchorPage={props.anchorPage} pdfId={props.pdfId} rememberScroll={true}
|
||||
container={containerEl} showPageNumbers={true} />
|
||||
<VerticalPages
|
||||
pdf={pdf}
|
||||
isDarkTheme={props.isDarkTheme}
|
||||
anchorPage={props.anchorPage}
|
||||
pdfId={props.pdfId}
|
||||
rememberScroll={true}
|
||||
container={containerEl}
|
||||
showPageNumbers={true}
|
||||
zoom={zoom} />
|
||||
</div>
|
||||
<div className='app-bottom-bar'>
|
||||
<div className='pdf-info'>
|
||||
{pdf.pageCount} pages
|
||||
<div style={{ paddingRight: '0.4rem' }}>{pdf.pageCount} pages</div>
|
||||
<ZoomControls onChange={setZoom} zoom={zoom} />
|
||||
</div>
|
||||
<div>{isFocused ? '' : 'Click to enable scroll'}</div>
|
||||
</div>
|
||||
|
@ -36,6 +36,9 @@
|
||||
"webpack-cli": "^4.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^6.1.2",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.1.2",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@joplin/lib": "workspace:^",
|
||||
"pdfjs-dist": "^2.14.305",
|
||||
"react": "16.13.1",
|
||||
|
46
packages/pdf-viewer/ui/ZoomControls.tsx
Normal file
46
packages/pdf-viewer/ui/ZoomControls.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faMinus, faPlus } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
const ZoomGroup = styled.div<{ size: number }>`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-flow: row;
|
||||
color: var(--grey);
|
||||
cursor: initial;
|
||||
font-size: ${props => props.size}rem;
|
||||
padding: 0.2rem 0.4rem;
|
||||
user-select: none;
|
||||
border-radius: 5px;
|
||||
&:hover {
|
||||
background: #7676764d;
|
||||
}
|
||||
svg:hover {
|
||||
color: var(--secondary);
|
||||
}
|
||||
`;
|
||||
|
||||
export interface ZoomControlsProps {
|
||||
zoom: number;
|
||||
onChange: (zoom: number)=> void;
|
||||
size?: number;
|
||||
}
|
||||
|
||||
export default function ZoomControls(props: ZoomControlsProps) {
|
||||
|
||||
const zoomIn = () => {
|
||||
props.onChange(Math.min(props.zoom + 0.25, 2));
|
||||
};
|
||||
|
||||
const zoomOut = () => {
|
||||
props.onChange(Math.max(props.zoom - 0.25, 0.5));
|
||||
};
|
||||
|
||||
return (<ZoomGroup size={props.size || 0.8}>
|
||||
<FontAwesomeIcon icon={faMinus} title="Zoom Out" style={{ paddingRight: '0.2rem', cursor: 'pointer' }} onClick={zoomOut} />
|
||||
<span style={{ color: 'grey' }} >{props.zoom * 100}%</span>
|
||||
<FontAwesomeIcon icon={faPlus} title="Zoom In" style={{ paddingLeft: '0.2rem', cursor: 'pointer' }} onClick={zoomIn} />
|
||||
</ZoomGroup>);
|
||||
}
|
@ -115,23 +115,9 @@ hr {
|
||||
color: var(--grey);
|
||||
}
|
||||
|
||||
.pdf-info>a {
|
||||
padding: 0rem 0.4rem;
|
||||
color: var(--blue);
|
||||
cursor: pointer;
|
||||
border: solid thin transparent;
|
||||
border-radius: 5px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.pdf-info>a:hover {
|
||||
border-color: var(--grey);
|
||||
}
|
||||
|
||||
.app-pages {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: start;
|
||||
display: block;
|
||||
margin: 0px auto;
|
||||
overflow-x: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@ -154,4 +140,5 @@ hr {
|
||||
flex-direction: row;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
column-gap: 0.2rem;
|
||||
}
|
53
yarn.lock
53
yarn.lock
@ -3170,6 +3170,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@fortawesome/fontawesome-common-types@npm:6.1.2":
|
||||
version: 6.1.2
|
||||
resolution: "@fortawesome/fontawesome-common-types@npm:6.1.2"
|
||||
checksum: 16ba97f73256adef5cd680a027e6dbd3e76f34ba9227f7bd9e8c372cb4f337c7ccbf41f35dcfbc22b11320bbb579d01daccf1aa7ae47df5d0b17260c0097bb30
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@fortawesome/fontawesome-common-types@npm:^0.2.36":
|
||||
version: 0.2.36
|
||||
resolution: "@fortawesome/fontawesome-common-types@npm:0.2.36"
|
||||
@ -3193,6 +3200,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@fortawesome/fontawesome-svg-core@npm:^6.1.2":
|
||||
version: 6.1.2
|
||||
resolution: "@fortawesome/fontawesome-svg-core@npm:6.1.2"
|
||||
dependencies:
|
||||
"@fortawesome/fontawesome-common-types": 6.1.2
|
||||
checksum: bb82ed1e79ade9977746b4bb28ac0d03de7557e7c923446adec78cb3447740aca0859e91d6310007d758055a1b8f3a6f740915f04cac738931135c9bdbfe5d32
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@fortawesome/free-regular-svg-icons@npm:^5.13.0":
|
||||
version: 5.15.4
|
||||
resolution: "@fortawesome/free-regular-svg-icons@npm:5.15.4"
|
||||
@ -3211,6 +3227,27 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@fortawesome/free-solid-svg-icons@npm:^6.1.2":
|
||||
version: 6.1.2
|
||||
resolution: "@fortawesome/free-solid-svg-icons@npm:6.1.2"
|
||||
dependencies:
|
||||
"@fortawesome/fontawesome-common-types": 6.1.2
|
||||
checksum: b7258cd092304f9bd1e557cd3a59e9ff560165631b04f16785da14ce3148873fa8e688d62f95d68f668be32e1207c47a1fe556978ae7e9573a5b0fec09fc0f0c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@fortawesome/react-fontawesome@npm:^0.2.0":
|
||||
version: 0.2.0
|
||||
resolution: "@fortawesome/react-fontawesome@npm:0.2.0"
|
||||
dependencies:
|
||||
prop-types: ^15.8.1
|
||||
peerDependencies:
|
||||
"@fortawesome/fontawesome-svg-core": ~1 || ~6
|
||||
react: ">=16.3"
|
||||
checksum: f652a0c2172e7b209e2d9e7e511f9b8c17abad85f55e0bd09bb1175ea1927693215da47eb6cd95b1f3a23bd124368553c677907fa76cb17c5093afc1fcffe338
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@gar/promisify@npm:^1.0.1":
|
||||
version: 1.1.2
|
||||
resolution: "@gar/promisify@npm:1.1.2"
|
||||
@ -4293,6 +4330,9 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@joplin/pdf-viewer@workspace:packages/pdf-viewer"
|
||||
dependencies:
|
||||
"@fortawesome/fontawesome-svg-core": ^6.1.2
|
||||
"@fortawesome/free-solid-svg-icons": ^6.1.2
|
||||
"@fortawesome/react-fontawesome": ^0.2.0
|
||||
"@joplin/lib": "workspace:^"
|
||||
"@types/jest": ^28.1.6
|
||||
"@types/pdfjs-dist": ^2.10.378
|
||||
@ -27614,6 +27654,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"prop-types@npm:^15.8.1":
|
||||
version: 15.8.1
|
||||
resolution: "prop-types@npm:15.8.1"
|
||||
dependencies:
|
||||
loose-envify: ^1.4.0
|
||||
object-assign: ^4.1.1
|
||||
react-is: ^16.13.1
|
||||
checksum: c056d3f1c057cb7ff8344c645450e14f088a915d078dcda795041765047fa080d38e5d626560ccaac94a4e16e3aa15f3557c1a9a8d1174530955e992c675e459
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"proper-lockfile@npm:^2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "proper-lockfile@npm:2.0.1"
|
||||
@ -28036,7 +28087,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-is@npm:^16.12.0, react-is@npm:^16.7.0, react-is@npm:^16.8.1, react-is@npm:^16.8.6":
|
||||
"react-is@npm:^16.12.0, react-is@npm:^16.13.1, react-is@npm:^16.7.0, react-is@npm:^16.8.1, react-is@npm:^16.8.6":
|
||||
version: 16.13.1
|
||||
resolution: "react-is@npm:16.13.1"
|
||||
checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f
|
||||
|
Loading…
Reference in New Issue
Block a user