@@ -15,7 +15,7 @@ import "react-photo-view/dist/react-photo-view.css";
1515import "./style.css" ;
1616import { PhotoProviderProps } from "react-photo-view/dist/PhotoProvider" ;
1717import { Dropzone } from "./Dropzone" ;
18- import { use } from "motion/react-client" ;
18+ import { image , use } from "motion/react-client" ;
1919
2020const RemoveIcon = ( ) => (
2121 < svg
@@ -52,6 +52,13 @@ const PreviewIcon = () => (
5252 </ svg >
5353) ;
5454
55+ type ValueItem = {
56+ url : string ;
57+ name ?: string ;
58+ } ;
59+
60+ type ValueType = string | ValueItem | ( string | ValueItem ) [ ] ;
61+
5562type ImageItem = {
5663 id ?: string ;
5764 url ?: string ;
@@ -60,15 +67,27 @@ type ImageItem = {
6067 loading ?: boolean ;
6168} ;
6269
70+ const checkValue = ( a : ValueType , b : ValueType ) => {
71+ return a === b || JSON . stringify ( a ) === JSON . stringify ( b ) ;
72+ } ;
73+
6374const defaultUpload = ( file : File ) => URL . createObjectURL ( file ) ;
75+ const defaultTransform = ( images : ImageItem [ ] , max : number ) : ValueType => {
76+ const value = images . map ( ( item ) => item . url ) ;
77+ if ( max === 1 ) {
78+ return value . join ( "," ) ;
79+ }
80+ return value ;
81+ } ;
6482
6583export type ImageUploadProps = {
6684 width ?: number ;
6785 height ?: number ;
6886 dropzoneOptions ?: DropzoneOptions ;
6987 photoProviderProps ?: Omit < PhotoProviderProps , "children" > ;
70- value ?: string | ImageItem | ( string | ImageItem ) [ ] ;
71- onChange ?: ( value : ImageItem [ ] ) => void ;
88+ value ?: ValueType ;
89+ onChange ?: ( value : ValueType ) => void ;
90+ transform ?: ( value : ImageItem [ ] , max : number ) => ValueType ;
7291 max ?: number ;
7392 onUpload ?: ( file : File ) => string | Promise < string > ;
7493 readonly ?: boolean ;
@@ -87,6 +106,7 @@ export const ImageUpload = forwardRef<HTMLElement, ImageUploadProps>(
87106 max = Infinity ,
88107 onChange,
89108 onUpload = defaultUpload ,
109+ transform = defaultTransform ,
90110 readonly,
91111 dropzoneOptions,
92112 photoProviderProps,
@@ -96,13 +116,17 @@ export const ImageUpload = forwardRef<HTMLElement, ImageUploadProps>(
96116 children,
97117 } = props ;
98118
119+ const valueRef = useRef < ValueType > ( ) ;
99120 const dropzoneRef = useRef < HTMLElement > ( null ) ;
100121
101122 useImperativeHandle ( ref , ( ) => dropzoneRef . current ) ;
102123
103124 const [ images , setImages ] = useState < ImageItem [ ] > ( [ ] ) ;
104125
105126 useEffect ( ( ) => {
127+ if ( checkValue ( valueRef . current , value ) ) {
128+ return ;
129+ }
106130 let newImages = [ ] ;
107131 if ( value ) {
108132 let innerValue = value ;
@@ -123,9 +147,18 @@ export const ImageUpload = forwardRef<HTMLElement, ImageUploadProps>(
123147 } )
124148 . slice ( 0 , max ) ;
125149 }
150+ valueRef . current = value ;
126151 setImages ( newImages ) ;
127152 } , [ value , max ] ) ;
128153
154+ const onChangeInner = useCallback (
155+ ( images : ImageItem [ ] ) => {
156+ valueRef . current = transform ?.( images , max ) ;
157+ onChange ?.( valueRef . current ) ;
158+ } ,
159+ [ transform , onChange , max ]
160+ ) ;
161+
129162 const onDropAccepted = useCallback (
130163 async ( acceptedFiles : File [ ] ) => {
131164 const addImages = acceptedFiles
@@ -146,15 +179,15 @@ export const ImageUpload = forwardRef<HTMLElement, ImageUploadProps>(
146179 return [ ...images ] ;
147180 } ) ;
148181 } )
149- ) . then ( ( ) => onChange ?. ( newImages ) ) ;
182+ ) . then ( ( ) => onChangeInner ( newImages ) ) ;
150183 } ,
151184 [ images , max , onChange ]
152185 ) ;
153186
154187 const onRemoveImage = useCallback (
155188 ( idx : number ) => {
156189 const newImages = images . filter ( ( _ , index ) => index != idx ) ;
157- onChange ?. ( newImages ) ;
190+ onChangeInner ( newImages ) ;
158191 setImages ( newImages ) ;
159192 } ,
160193 [ images , onChange ]
0 commit comments