flex-image-viewer 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.
- package/README.md +160 -0
- package/dist/FlexImageViewer/Content/index.js +193 -0
- package/dist/FlexImageViewer/Footer/Actions.js +115 -0
- package/dist/FlexImageViewer/Footer/index.js +56 -0
- package/dist/FlexImageViewer/Header/Actions.js +80 -0
- package/dist/FlexImageViewer/Header/index.js +42 -0
- package/dist/FlexImageViewer/Info/index.js +52 -0
- package/dist/FlexImageViewer/Thumbnail/index.js +90 -0
- package/dist/FlexImageViewer/index.css +582 -0
- package/dist/FlexImageViewer/index.js +117 -0
- package/dist/components/ActionItem.js +10 -0
- package/dist/components/BaseActions.js +69 -0
- package/dist/components/Icon/index.js +48 -0
- package/dist/components/Icon/svg/arrow-left.js +15 -0
- package/dist/components/Icon/svg/arrow-right.js +15 -0
- package/dist/components/Icon/svg/caret-right.js +15 -0
- package/dist/components/Icon/svg/check.js +15 -0
- package/dist/components/Icon/svg/clear.js +15 -0
- package/dist/components/Icon/svg/close.js +16 -0
- package/dist/components/Icon/svg/default-image.js +17 -0
- package/dist/components/Icon/svg/down.js +15 -0
- package/dist/components/Icon/svg/info-circle.js +20 -0
- package/dist/components/Icon/svg/rotate-left.js +20 -0
- package/dist/components/Icon/svg/rotate-right.js +20 -0
- package/dist/components/Icon/svg/save.js +15 -0
- package/dist/components/Icon/svg/size.js +19 -0
- package/dist/components/Icon/svg/thumbnail.js +19 -0
- package/dist/components/Icon/svg/zoom-adapt.js +24 -0
- package/dist/components/Icon/svg/zoom-in.js +15 -0
- package/dist/components/Icon/svg/zoom-out.js +15 -0
- package/dist/components/Image.js +148 -0
- package/dist/components/Modal.js +98 -0
- package/dist/components/PercentSelect.js +160 -0
- package/dist/components/ThumbnailIamge.js +65 -0
- package/dist/components/index.js +6 -0
- package/dist/context/ViewerContext.js +208 -0
- package/dist/hooks/useImageOperations.js +113 -0
- package/dist/hooks/useImageSource.js +52 -0
- package/dist/index.js +2 -0
- package/dist/rspress.config.d.ts +2 -0
- package/dist/src/FlexImageViewer/Content/index.d.ts +11 -0
- package/dist/src/FlexImageViewer/Footer/Actions.d.ts +13 -0
- package/dist/src/FlexImageViewer/Footer/index.d.ts +8 -0
- package/dist/src/FlexImageViewer/Header/Actions.d.ts +15 -0
- package/dist/src/FlexImageViewer/Header/index.d.ts +11 -0
- package/dist/src/FlexImageViewer/Info/index.d.ts +5 -0
- package/dist/src/FlexImageViewer/Thumbnail/index.d.ts +5 -0
- package/dist/src/FlexImageViewer/index.d.ts +21 -0
- package/dist/src/components/ActionItem.d.ts +6 -0
- package/dist/src/components/BaseActions.d.ts +17 -0
- package/dist/src/components/Icon/index.d.ts +6 -0
- package/dist/src/components/Image.d.ts +18 -0
- package/dist/src/components/Modal.d.ts +9 -0
- package/dist/src/components/PercentSelect.d.ts +17 -0
- package/dist/src/components/ThumbnailIamge.d.ts +8 -0
- package/dist/src/components/index.d.ts +13 -0
- package/dist/src/context/ViewerContext.d.ts +13 -0
- package/dist/src/hooks/useImageOperations.d.ts +12 -0
- package/dist/src/hooks/useImageSource.d.ts +7 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/src/utils/dict.d.ts +1 -0
- package/dist/src/utils/exif.d.ts +2 -0
- package/dist/src/utils/source.d.ts +1 -0
- package/dist/utils/dict.js +16 -0
- package/dist/utils/exif.js +17 -0
- package/dist/utils/source.js +2 -0
- package/package.json +74 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
const ZOOM_STEP = 0.1;
|
|
3
|
+
function useImageOperations(state, dispatch) {
|
|
4
|
+
const arrayIndex = state.currentIndex - 1;
|
|
5
|
+
const rotateLeft = useCallback(()=>{
|
|
6
|
+
dispatch({
|
|
7
|
+
type: 'ROTATE_LEFT',
|
|
8
|
+
payload: {
|
|
9
|
+
index: arrayIndex
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
}, [
|
|
13
|
+
dispatch,
|
|
14
|
+
arrayIndex
|
|
15
|
+
]);
|
|
16
|
+
const rotateRight = useCallback(()=>{
|
|
17
|
+
dispatch({
|
|
18
|
+
type: 'ROTATE_RIGHT',
|
|
19
|
+
payload: {
|
|
20
|
+
index: arrayIndex
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}, [
|
|
24
|
+
dispatch,
|
|
25
|
+
arrayIndex
|
|
26
|
+
]);
|
|
27
|
+
const setZoom = useCallback((scale)=>{
|
|
28
|
+
dispatch({
|
|
29
|
+
type: 'SET_ZOOM',
|
|
30
|
+
payload: {
|
|
31
|
+
index: arrayIndex,
|
|
32
|
+
scale
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}, [
|
|
36
|
+
dispatch,
|
|
37
|
+
arrayIndex
|
|
38
|
+
]);
|
|
39
|
+
const zoomIn = useCallback((step = ZOOM_STEP)=>{
|
|
40
|
+
dispatch({
|
|
41
|
+
type: 'ZOOM_IN',
|
|
42
|
+
payload: {
|
|
43
|
+
index: arrayIndex,
|
|
44
|
+
step
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}, [
|
|
48
|
+
dispatch,
|
|
49
|
+
arrayIndex
|
|
50
|
+
]);
|
|
51
|
+
const zoomOut = useCallback((step = ZOOM_STEP)=>{
|
|
52
|
+
dispatch({
|
|
53
|
+
type: 'ZOOM_OUT',
|
|
54
|
+
payload: {
|
|
55
|
+
index: arrayIndex,
|
|
56
|
+
step
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}, [
|
|
60
|
+
dispatch,
|
|
61
|
+
arrayIndex
|
|
62
|
+
]);
|
|
63
|
+
const adaptZoom = useCallback((scale)=>{
|
|
64
|
+
dispatch({
|
|
65
|
+
type: 'ADAPT_ZOOM',
|
|
66
|
+
payload: {
|
|
67
|
+
index: arrayIndex,
|
|
68
|
+
scale
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}, [
|
|
72
|
+
dispatch,
|
|
73
|
+
arrayIndex
|
|
74
|
+
]);
|
|
75
|
+
const clear = useCallback(()=>{
|
|
76
|
+
const file = state.files[arrayIndex];
|
|
77
|
+
dispatch({
|
|
78
|
+
type: 'CLEAR_IMAGE',
|
|
79
|
+
payload: {
|
|
80
|
+
index: arrayIndex,
|
|
81
|
+
angle: file?.angle ?? 0,
|
|
82
|
+
scale: file?.scale ?? 1
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}, [
|
|
86
|
+
dispatch,
|
|
87
|
+
arrayIndex,
|
|
88
|
+
state.files
|
|
89
|
+
]);
|
|
90
|
+
const updateCurrentFile = useCallback((file)=>{
|
|
91
|
+
dispatch({
|
|
92
|
+
type: 'UPDATE_FILE',
|
|
93
|
+
payload: {
|
|
94
|
+
index: arrayIndex,
|
|
95
|
+
file: file
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
}, [
|
|
99
|
+
dispatch,
|
|
100
|
+
arrayIndex
|
|
101
|
+
]);
|
|
102
|
+
return {
|
|
103
|
+
rotateLeft,
|
|
104
|
+
rotateRight,
|
|
105
|
+
setZoom,
|
|
106
|
+
zoomIn,
|
|
107
|
+
zoomOut,
|
|
108
|
+
adaptZoom,
|
|
109
|
+
clear,
|
|
110
|
+
updateCurrentFile
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
export { useImageOperations };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from "react";
|
|
2
|
+
import { DEFAULT_IMAGE } from "../utils/source.js";
|
|
3
|
+
import { getImageOrientation } from "../utils/exif.js";
|
|
4
|
+
function useImageSource(file, getSrc) {
|
|
5
|
+
const [src, setSrc] = useState(DEFAULT_IMAGE);
|
|
6
|
+
const [loading, setLoading] = useState(false);
|
|
7
|
+
const [orientation, setOrientation] = useState(void 0);
|
|
8
|
+
const requestIdRef = useRef(0);
|
|
9
|
+
const getSrcRef = useRef(getSrc);
|
|
10
|
+
getSrcRef.current = getSrc;
|
|
11
|
+
useEffect(()=>{
|
|
12
|
+
if (!file) {
|
|
13
|
+
setSrc(DEFAULT_IMAGE);
|
|
14
|
+
setLoading(false);
|
|
15
|
+
setOrientation(void 0);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const currentRequestId = ++requestIdRef.current;
|
|
19
|
+
setOrientation(void 0);
|
|
20
|
+
const resolveSrc = async ()=>{
|
|
21
|
+
if (getSrcRef.current) return getSrcRef.current(file);
|
|
22
|
+
return file.src ?? DEFAULT_IMAGE;
|
|
23
|
+
};
|
|
24
|
+
let cancelled = false;
|
|
25
|
+
setLoading(true);
|
|
26
|
+
resolveSrc().then((resolvedSrc)=>{
|
|
27
|
+
if (!cancelled && currentRequestId === requestIdRef.current) {
|
|
28
|
+
setSrc(resolvedSrc);
|
|
29
|
+
setLoading(false);
|
|
30
|
+
}
|
|
31
|
+
if (resolvedSrc && resolvedSrc !== DEFAULT_IMAGE) getImageOrientation(resolvedSrc).then((ori)=>{
|
|
32
|
+
if (!cancelled && currentRequestId === requestIdRef.current) setOrientation(ori);
|
|
33
|
+
});
|
|
34
|
+
}).catch(()=>{
|
|
35
|
+
if (!cancelled && currentRequestId === requestIdRef.current) {
|
|
36
|
+
setSrc(DEFAULT_IMAGE);
|
|
37
|
+
setLoading(false);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
return ()=>{
|
|
41
|
+
cancelled = true;
|
|
42
|
+
};
|
|
43
|
+
}, [
|
|
44
|
+
file
|
|
45
|
+
]);
|
|
46
|
+
return {
|
|
47
|
+
src,
|
|
48
|
+
loading,
|
|
49
|
+
orientation
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export { useImageSource };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ImageProps } from '../../components';
|
|
2
|
+
import type { FileData } from '../../types';
|
|
3
|
+
export interface ContentProps<T extends FileData> extends Pick<ImageProps<T>, 'getSrc'> {
|
|
4
|
+
preload?: boolean;
|
|
5
|
+
wheelZoom?: boolean;
|
|
6
|
+
wheelZoomStep?: number;
|
|
7
|
+
disableRightClick?: boolean;
|
|
8
|
+
onClose?: () => void;
|
|
9
|
+
}
|
|
10
|
+
declare function Content<T extends FileData>(props: ContentProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export default Content;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { FileData } from '../../types';
|
|
3
|
+
type ActionKey = 'thumbnail' | 'info' | 'zoomAdapt' | 'zoomSelect' | 'zoomOut' | 'zoomSlider' | 'zoomIn';
|
|
4
|
+
export interface FooterActionsProps<T extends FileData> {
|
|
5
|
+
zoom?: number;
|
|
6
|
+
updateCurrentFile?: (file: Partial<T>) => void;
|
|
7
|
+
renderAction?: (actions: Record<ActionKey, React.ReactNode>, context: {
|
|
8
|
+
zoom: number;
|
|
9
|
+
updateCurrentFile: (file: Partial<T>) => void;
|
|
10
|
+
}) => React.ReactNode;
|
|
11
|
+
}
|
|
12
|
+
declare function Actions<T extends FileData>(props: FooterActionsProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export default Actions;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FileData } from '../../types';
|
|
2
|
+
import type { FooterActionsProps } from './Actions';
|
|
3
|
+
export interface FooterProps<T extends FileData> {
|
|
4
|
+
renderAction?: FooterActionsProps<T>['renderAction'];
|
|
5
|
+
updateCurrentFile?: FooterActionsProps<T>['updateCurrentFile'];
|
|
6
|
+
}
|
|
7
|
+
declare function Footer<T extends FileData>({ renderAction, updateCurrentFile }: FooterProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export default Footer;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { FileData } from '../../types';
|
|
3
|
+
type ActionKey = 'rotateLeft' | 'rotateRight' | 'clear' | 'close';
|
|
4
|
+
export interface HeaderActionsProps<T extends FileData> {
|
|
5
|
+
rotate?: number;
|
|
6
|
+
updateCurrentFile?: (file: Partial<T>) => void;
|
|
7
|
+
renderAction?: (actions: Record<ActionKey, React.ReactNode>, context: {
|
|
8
|
+
rotate: number;
|
|
9
|
+
updateCurrentFile: (file: Partial<T>) => void;
|
|
10
|
+
}) => React.ReactNode;
|
|
11
|
+
onClear?: () => void;
|
|
12
|
+
onClose?: (e: React.MouseEvent) => void;
|
|
13
|
+
}
|
|
14
|
+
declare function Actions<T extends FileData>(props: HeaderActionsProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export default Actions;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { FileData } from '../../types';
|
|
3
|
+
import type { HeaderActionsProps } from './Actions';
|
|
4
|
+
export interface HeaderProps<T extends FileData> {
|
|
5
|
+
renderAction?: HeaderActionsProps<T>['renderAction'];
|
|
6
|
+
onClose?: (e: React.MouseEvent) => void;
|
|
7
|
+
onClear?: () => void;
|
|
8
|
+
updateCurrentFile?: HeaderActionsProps<T>['updateCurrentFile'];
|
|
9
|
+
}
|
|
10
|
+
declare function Header<T extends FileData>({ renderAction, onClose, onClear, updateCurrentFile, }: HeaderProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export default Header;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ThumbnailImageProps } from '../../components/ThumbnailIamge';
|
|
2
|
+
import type { FileData } from '../../types';
|
|
3
|
+
type ThumbnailProps<T extends FileData> = Pick<ThumbnailImageProps<T>, 'getThumbnail'>;
|
|
4
|
+
export default function Thumbnail<T extends FileData>(props: ThumbnailProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ImageProps, ModalProps } from '../components';
|
|
2
|
+
import type { FileData } from '../types';
|
|
3
|
+
import type { ThumbnailImageProps } from '../components/ThumbnailIamge';
|
|
4
|
+
import type { HeaderActionsProps } from './Header/Actions';
|
|
5
|
+
import type { FooterActionsProps } from './Footer/Actions';
|
|
6
|
+
import type { InfoProps } from './Info';
|
|
7
|
+
import type { ContentProps } from './Content';
|
|
8
|
+
import 'rc-slider/assets/index.css';
|
|
9
|
+
import 'rc-tooltip/assets/bootstrap.css';
|
|
10
|
+
import './index.css';
|
|
11
|
+
export interface FlexImageViewerProps<T extends FileData> extends Omit<ModalProps, 'children'>, InfoProps, Pick<ThumbnailImageProps<T>, 'getThumbnail'>, Pick<ImageProps<T>, 'getSrc'>, Pick<ContentProps<T>, 'wheelZoom' | 'wheelZoomStep' | 'preload' | 'disableRightClick'> {
|
|
12
|
+
files?: T[];
|
|
13
|
+
current?: number;
|
|
14
|
+
loop?: boolean;
|
|
15
|
+
onClear?: () => void;
|
|
16
|
+
onIndexChange?: (index: number) => void;
|
|
17
|
+
headerProps?: Pick<HeaderActionsProps<T>, 'renderAction'>;
|
|
18
|
+
footerProps?: Pick<FooterActionsProps<T>, 'renderAction'>;
|
|
19
|
+
}
|
|
20
|
+
declare function FlexImageViewer<T extends FileData>(props: FlexImageViewerProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
export default FlexImageViewer;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type ActionType = 'icon' | 'slider' | 'select';
|
|
3
|
+
export interface BaseActionItem {
|
|
4
|
+
key: string;
|
|
5
|
+
type: ActionType;
|
|
6
|
+
tooltipKey?: string;
|
|
7
|
+
iconName?: string;
|
|
8
|
+
tooltipPlacement?: 'topRight' | 'bottomRight' | 'topLeft' | 'bottomLeft';
|
|
9
|
+
valueKey?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface BaseActionsProps<C extends Record<string, unknown> = Record<string, unknown>> {
|
|
12
|
+
items: BaseActionItem[];
|
|
13
|
+
contextValues: C;
|
|
14
|
+
renderAction?: (actions: Record<string, React.ReactNode>, context: C) => React.ReactNode;
|
|
15
|
+
onAction: (key: string, value?: unknown, event?: React.MouseEvent) => void;
|
|
16
|
+
}
|
|
17
|
+
export default function BaseActions<C extends Record<string, unknown> = Record<string, unknown>>(props: BaseActionsProps<C>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { FileData } from '../types';
|
|
3
|
+
export interface ImageProps<T extends FileData> {
|
|
4
|
+
file?: T;
|
|
5
|
+
angle?: number;
|
|
6
|
+
scale?: number;
|
|
7
|
+
getSrc?: (file: T) => Promise<string>;
|
|
8
|
+
isAdapt?: boolean;
|
|
9
|
+
onAdapt?: (zoom: number) => void;
|
|
10
|
+
wheelZoom?: boolean;
|
|
11
|
+
wheelZoomStep?: number;
|
|
12
|
+
onWheelZoom?: (scale: number) => void;
|
|
13
|
+
onOrientation?: (orientation: number) => void;
|
|
14
|
+
disableRightClick?: boolean;
|
|
15
|
+
style?: React.CSSProperties;
|
|
16
|
+
}
|
|
17
|
+
declare function Image<T extends FileData>(props: ImageProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
export default Image;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface ModalProps {
|
|
3
|
+
visible: boolean;
|
|
4
|
+
onClose?: () => void;
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
getContainer?: string | (() => HTMLElement | null) | HTMLElement | null;
|
|
7
|
+
}
|
|
8
|
+
export declare const getContainer: string | (() => HTMLElement | null) | HTMLElement | null;
|
|
9
|
+
export default function Modal(props: ModalProps): React.ReactPortal | null;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export declare const getScaleValue: (sliderValue: number) => number;
|
|
3
|
+
export declare const getSliderValue: (scale: number) => number;
|
|
4
|
+
export interface PercentOption {
|
|
5
|
+
value: number;
|
|
6
|
+
label: string;
|
|
7
|
+
}
|
|
8
|
+
export interface PercentSelectProps {
|
|
9
|
+
value?: number;
|
|
10
|
+
onChange?: (value: number) => void;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
className?: string;
|
|
13
|
+
style?: React.CSSProperties;
|
|
14
|
+
options?: number[];
|
|
15
|
+
}
|
|
16
|
+
declare function PercentSelect({ value, onChange, disabled, className, style, options, }: PercentSelectProps): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export default PercentSelect;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FileData } from '../types';
|
|
2
|
+
export interface ThumbnailImageProps<T extends FileData> {
|
|
3
|
+
file?: T;
|
|
4
|
+
angle?: number;
|
|
5
|
+
getThumbnail?: (file: T) => Promise<string>;
|
|
6
|
+
}
|
|
7
|
+
declare function ThumbnailImage<T extends FileData>(props: ThumbnailImageProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export default ThumbnailImage;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import Icon from './Icon';
|
|
2
|
+
import Image from './Image';
|
|
3
|
+
import Modal from './Modal';
|
|
4
|
+
import PercentSelect from './PercentSelect';
|
|
5
|
+
import ActionItem from './ActionItem';
|
|
6
|
+
import BaseActions from './BaseActions';
|
|
7
|
+
import type { IconProps } from './Icon';
|
|
8
|
+
import type { ImageProps } from './Image';
|
|
9
|
+
import type { ModalProps } from './Modal';
|
|
10
|
+
import type { PercentSelectProps } from './PercentSelect';
|
|
11
|
+
import type { ActionItemProps } from './ActionItem';
|
|
12
|
+
import type { BaseActionsProps, BaseActionItem } from './BaseActions';
|
|
13
|
+
export { Icon, IconProps, Image, ImageProps, Modal, ModalProps, PercentSelect, PercentSelectProps, ActionItem, ActionItemProps, BaseActions, BaseActionsProps, BaseActionItem, };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ViewerState, ViewerAction, FileData } from '../types';
|
|
3
|
+
export declare const ViewerStateContext: React.Context<ViewerState<FileData> | null>;
|
|
4
|
+
export declare const ViewerDispatchContext: React.Context<React.Dispatch<ViewerAction<FileData>> | null>;
|
|
5
|
+
export declare function useViewerState<T extends FileData>(): ViewerState<T>;
|
|
6
|
+
export declare function useViewerDispatch(): React.Dispatch<ViewerAction<FileData>>;
|
|
7
|
+
export declare function viewerReducer<T extends FileData>(state: ViewerState<T>, action: ViewerAction<T>): ViewerState<T>;
|
|
8
|
+
export interface ViewerProviderProps {
|
|
9
|
+
children: React.ReactNode;
|
|
10
|
+
initialCurrent?: number;
|
|
11
|
+
initialFilesLength?: number;
|
|
12
|
+
}
|
|
13
|
+
export declare function ViewerProvider({ children, initialCurrent, initialFilesLength, }: ViewerProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ViewerState, ViewerAction, FileData } from '../types';
|
|
2
|
+
export interface ImageOperations {
|
|
3
|
+
rotateLeft: () => void;
|
|
4
|
+
rotateRight: () => void;
|
|
5
|
+
setZoom: (scale: number) => void;
|
|
6
|
+
zoomIn: (step?: number) => void;
|
|
7
|
+
zoomOut: (step?: number) => void;
|
|
8
|
+
adaptZoom: (scale: number) => void;
|
|
9
|
+
clear: () => void;
|
|
10
|
+
updateCurrentFile: (file: Partial<FileData>) => void;
|
|
11
|
+
}
|
|
12
|
+
export declare function useImageOperations<T extends FileData>(state: ViewerState<T>, dispatch: React.Dispatch<ViewerAction<T>>): ImageOperations;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FileData } from '../types';
|
|
2
|
+
export interface UseImageSourceResult {
|
|
3
|
+
src: string;
|
|
4
|
+
loading: boolean;
|
|
5
|
+
orientation?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function useImageSource<T extends FileData = FileData>(file?: T, getSrc?: (file: T) => Promise<string>): UseImageSourceResult;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ActionItem } from './components';
|
|
2
|
+
import FlexImageViewer from './FlexImageViewer';
|
|
3
|
+
import type { FileData } from './types';
|
|
4
|
+
import type { FlexImageViewerProps } from './FlexImageViewer';
|
|
5
|
+
import type { ActionItemProps } from './components';
|
|
6
|
+
export { FlexImageViewer, FlexImageViewerProps, ActionItem, ActionItemProps, FileData };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const TOOLTIP_CONFIG: Record<string, string>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const DEFAULT_IMAGE = "data:image/svg+xml;charset=utf-8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMC8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9UUi8yMDAxL1JFQy1TVkctMjAwMTA5MDQvRFREL3N2ZzEwLmR0ZCI+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgaWQ9ImJvZHlfMSIgd2lkdGg9IjE5NCIgaGVpZ2h0PSIxOTUiPgoKPGcgdHJhbnNmb3JtPSJtYXRyaXgoMS4zMzMzMzM0IDAgMCAxLjMzMzMzMzQgMCAwKSI+Cgk8aW1hZ2UgIHg9IjAiIHk9IjAiIHhsaW5rOmhyZWY9ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBTUlBQUFERENBWUFBQURRdmM2VUFBQUFDWEJJV1hNQUFBN0RBQUFPd3dISGI2aGtBQUFHT0VsRVFWUjRuT3pkcTA0a2F3QkZZVjRkaDhQaFFPSEE0WEE0SEE2SncrRjRBQ1kvQ1FrMDA5MUZYMnJ2aGs4c2RVNFlzbmF0cmt2WFpJNWVYMS9md01GZlB3YU8wcjhBT0dnNEJvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1N3UXM3VDA5UGI3ZTN0citEeDhURitzRFVqaENWaVhsNWUzbzZQajM4Tkp5Y244WU90R1NFc0VUTStRZE1INzY1eFZoRENqejhoaEpEL2xIWkdLQkFqaFB3R1FpZ1FJNFQ4QmtJb0VDT0UvQVpDS0JBamhQd0dRdmdGSVp5ZG5iMC9za3cvS2ZMVWFOcmVIcC91T0lTN3U3c3ZQK2Y1K2ZudDh2SXlIb0hIcDBLWTdZd3d2c0ZkOXVYYzZlbXBFQXJPOU00SU00U3c2Z3VybTVzYklSUWM4RUtZSVlSVlAyK2NMVndhNVE5NElUZ2plTVZDQ05sN2hJRjdoUHludmhCbUNtRThMbjE0ZVBoMm8zeDlmUjIvTFBMVVNBaXpmNDh3UHYwdkxpN2VTUi84UW5CR09PaHZsc2ZaWmRlWFUxN0Rkck44Y0NHTVAzOWNWbzF2cUlYZ0h1RlBobkIvZi8vbHI0dnU2bFVOWndSbmhJTUo0ZXJxNnR2dk1tSVFncWRHQjN0RytPbGx6Zm41K2RMZlo1d2xuQkgydDdlWDd2WVV3c2QzQ2xOakdQL2Z1Q2RZTmRhMnIybTROQkxDckdlRXo1YzNVMTY0Ry9jQTR5M1ZLYi9YTm0reUNrRUlzNFh3djAvMmRUZTg0NzlQL2IyMmVaSWtCQ0hNRXNJNDJKZGQzaXo3ZVorZkVQMGtoazJlSkFsQkNIc1BZUnlZNno3WkYyOTRWNzJidEk1Tkhxc0tRUWg3RDJIeEhhTmxqUHVIeGZ1SVRmbnBreVFoQ0dHdklTeis5Y3gxaktjLzY1NFFUV1g4MlVMWTNxUEhwMXVHc0l0UDltMzVPTXM0SXdnaEVzS3FMOERtWnNxVEpKZEd6Z2c3RDJIS0YyQnpNdVd4cWhDRXNOTVFwandoU3JEdVNaSVFoTERURUpvUHFFUDl2ZE80V2Q3Z2dFci82emZyRUlJUVp2bGtQVlNjRVp3UmhDQUVsMGJPQ000STdoRmNHcmswY3JQc0hzRTlncWRHVzkwcysrZGw4NDgwUFQ0dEVQUHhCZFY0UVc2OFNuSElqSGVSUERGeXN4d1BDdjBPZktGV01BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEdjRCQUFELy96VjJpUGdBQUFBR1NVUkJWQU1BbEwzNEprZXVucFlBQUFBQVNVVk9SSzVDWUlJPSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSIgd2lkdGg9IjE0NS41IiBoZWlnaHQ9IjE0Ni4yNSIvPgo8L2c+Cjwvc3ZnPgo=";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const TOOLTIP_CONFIG = {
|
|
2
|
+
arrowLeft: '查看上一张图片',
|
|
3
|
+
arrowRight: '查看下一张图片',
|
|
4
|
+
clear: '重置图片',
|
|
5
|
+
close: '关闭',
|
|
6
|
+
thumbnail: '显示或隐藏缩略图',
|
|
7
|
+
info: '显示或隐藏图片信息',
|
|
8
|
+
rotateLeft: '向左旋转图片',
|
|
9
|
+
rotateRight: '向右旋转图片',
|
|
10
|
+
zoomAdapt: '自适应缩放',
|
|
11
|
+
zoomSelect: '选择缩放比例',
|
|
12
|
+
zoomOut: '缩小图片',
|
|
13
|
+
zoomSlider: '调整缩放比例',
|
|
14
|
+
zoomIn: '放大图片'
|
|
15
|
+
};
|
|
16
|
+
export { TOOLTIP_CONFIG };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import exifreader from "exifreader";
|
|
2
|
+
async function getImageOrientation(source) {
|
|
3
|
+
try {
|
|
4
|
+
let input;
|
|
5
|
+
input = 'string' == typeof source ? source : source instanceof Blob ? await source.arrayBuffer() : source;
|
|
6
|
+
const tags = 'string' == typeof input ? await exifreader.load(input) : await exifreader.load(input);
|
|
7
|
+
const orientation = tags?.Orientation?.value;
|
|
8
|
+
if ('number' == typeof orientation) return orientation;
|
|
9
|
+
return;
|
|
10
|
+
} catch {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function shouldSwapDimensions(orientation) {
|
|
15
|
+
return 6 === orientation || 8 === orientation;
|
|
16
|
+
}
|
|
17
|
+
export { getImageOrientation, shouldSwapDimensions };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const DEFAULT_IMAGE = 'data:image/svg+xml;charset=utf-8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMC8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9UUi8yMDAxL1JFQy1TVkctMjAwMTA5MDQvRFREL3N2ZzEwLmR0ZCI+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgaWQ9ImJvZHlfMSIgd2lkdGg9IjE5NCIgaGVpZ2h0PSIxOTUiPgoKPGcgdHJhbnNmb3JtPSJtYXRyaXgoMS4zMzMzMzM0IDAgMCAxLjMzMzMzMzQgMCAwKSI+Cgk8aW1hZ2UgIHg9IjAiIHk9IjAiIHhsaW5rOmhyZWY9ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBTUlBQUFERENBWUFBQURRdmM2VUFBQUFDWEJJV1hNQUFBN0RBQUFPd3dISGI2aGtBQUFHT0VsRVFWUjRuT3pkcTA0a2F3QkZZVjRkaDhQaFFPSEE0WEE0SEE2SncrRjRBQ1kvQ1FrMDA5MUZYMnJ2aGs4c2RVNFlzbmF0cmt2WFpJNWVYMS9md01GZlB3YU8wcjhBT0dnNEJvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1N3UXM3VDA5UGI3ZTN0citEeDhURitzRFVqaENWaVhsNWUzbzZQajM4Tkp5Y244WU90R1NFc0VUTStRZE1INzY1eFZoRENqejhoaEpEL2xIWkdLQkFqaFB3R1FpZ1FJNFQ4QmtJb0VDT0UvQVpDS0JBamhQd0dRdmdGSVp5ZG5iMC9za3cvS2ZMVWFOcmVIcC91T0lTN3U3c3ZQK2Y1K2ZudDh2SXlIb0hIcDBLWTdZd3d2c0ZkOXVYYzZlbXBFQXJPOU00SU00U3c2Z3VybTVzYklSUWM4RUtZSVlSVlAyK2NMVndhNVE5NElUZ2plTVZDQ05sN2hJRjdoUHludmhCbUNtRThMbjE0ZVBoMm8zeDlmUjIvTFBMVVNBaXpmNDh3UHYwdkxpN2VTUi84UW5CR09PaHZsc2ZaWmRlWFUxN0Rkck44Y0NHTVAzOWNWbzF2cUlYZ0h1RlBobkIvZi8vbHI0dnU2bFVOWndSbmhJTUo0ZXJxNnR2dk1tSVFncWRHQjN0RytPbGx6Zm41K2RMZlo1d2xuQkgydDdlWDd2WVV3c2QzQ2xOakdQL2Z1Q2RZTmRhMnIybTROQkxDckdlRXo1YzNVMTY0Ry9jQTR5M1ZLYi9YTm0reUNrRUlzNFh3djAvMmRUZTg0NzlQL2IyMmVaSWtCQ0hNRXNJNDJKZGQzaXo3ZVorZkVQMGtoazJlSkFsQkNIc1BZUnlZNno3WkYyOTRWNzJidEk1Tkhxc0tRUWg3RDJIeEhhTmxqUHVIeGZ1SVRmbnBreVFoQ0dHdklTeis5Y3gxaktjLzY1NFFUV1g4MlVMWTNxUEhwMXVHc0l0UDltMzVPTXM0SXdnaEVzS3FMOERtWnNxVEpKZEd6Z2c3RDJIS0YyQnpNdVd4cWhDRXNOTVFwandoU3JEdVNaSVFoTERURUpvUHFFUDl2ZE80V2Q3Z2dFci82emZyRUlJUVp2bGtQVlNjRVp3UmhDQUVsMGJPQ000STdoRmNHcmswY3JQc0hzRTlncWRHVzkwcysrZGw4NDgwUFQ0dEVQUHhCZFY0UVc2OFNuSElqSGVSUERGeXN4d1BDdjBPZktGV01BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEb1JRTUFMeURvUlFNQUx5RG9SUU1BTHlEdjRCQUFELy96VjJpUGdBQUFBR1NVUkJWQU1BbEwzNEprZXVucFlBQUFBQVNVVk9SSzVDWUlJPSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSIgd2lkdGg9IjE0NS41IiBoZWlnaHQ9IjE0Ni4yNSIvPgo8L2c+Cjwvc3ZnPgo=';
|
|
2
|
+
export { DEFAULT_IMAGE };
|
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "flex-image-viewer",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "linie1119",
|
|
7
|
+
"email": "linie_1119@qq.com"
|
|
8
|
+
},
|
|
9
|
+
"description": "A React component for image viewer",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "rslib",
|
|
23
|
+
"build:storybook": "storybook build",
|
|
24
|
+
"dev": "rslib --watch",
|
|
25
|
+
"doc": "rspress dev",
|
|
26
|
+
"doc:build": "rspress build",
|
|
27
|
+
"doc:preview": "rspress preview",
|
|
28
|
+
"format": "prettier --write .",
|
|
29
|
+
"lint": "rslint",
|
|
30
|
+
"storybook": "storybook dev",
|
|
31
|
+
"test": "rstest",
|
|
32
|
+
"test:watch": "rstest --watch"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@rsbuild/core": "2.0.0-rc.3",
|
|
36
|
+
"@rsbuild/plugin-react": "^1.4.6",
|
|
37
|
+
"@rsbuild/plugin-svgr": "^1.3.1",
|
|
38
|
+
"@rslib/core": "^0.21.2",
|
|
39
|
+
"@rslint/core": "^0.4.2",
|
|
40
|
+
"@rspress/core": "^2.0.9",
|
|
41
|
+
"@rspress/plugin-api-docgen": "^2.0.9",
|
|
42
|
+
"@rspress/plugin-preview": "^2.0.9",
|
|
43
|
+
"@rstest/adapter-rslib": "^0.2.2",
|
|
44
|
+
"@rstest/core": "^0.9.7",
|
|
45
|
+
"@storybook/addon-docs": "^10.3.5",
|
|
46
|
+
"@storybook/addon-onboarding": "^10.3.5",
|
|
47
|
+
"@storybook/react": "^10.3.5",
|
|
48
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
49
|
+
"@testing-library/react": "^16.3.2",
|
|
50
|
+
"@types/node": "^24.12.2",
|
|
51
|
+
"@types/react": "^19.2.14",
|
|
52
|
+
"@types/react-dom": "^19.2.3",
|
|
53
|
+
"happy-dom": "^20.9.0",
|
|
54
|
+
"prettier": "^3.8.2",
|
|
55
|
+
"react": "^19.2.5",
|
|
56
|
+
"react-dom": "^19.2.5",
|
|
57
|
+
"rsbuild-plugin-workspace-dev": "^0.1.4",
|
|
58
|
+
"storybook": "^10.3.5",
|
|
59
|
+
"storybook-addon-rslib": "^3.3.3",
|
|
60
|
+
"storybook-react-rsbuild": "^3.3.3",
|
|
61
|
+
"typescript": "^6.0.2"
|
|
62
|
+
},
|
|
63
|
+
"peerDependencies": {
|
|
64
|
+
"react": ">=16.9.0",
|
|
65
|
+
"react-dom": ">=16.9.0"
|
|
66
|
+
},
|
|
67
|
+
"dependencies": {
|
|
68
|
+
"ahooks": "^3.9.7",
|
|
69
|
+
"es-toolkit": "^1.46.0",
|
|
70
|
+
"exifreader": "^4.41.0",
|
|
71
|
+
"rc-slider": "^11.1.9",
|
|
72
|
+
"rc-tooltip": "^6.4.0"
|
|
73
|
+
}
|
|
74
|
+
}
|