Skip to content

Commit 8a49712

Browse files
committed
extract style [skip ci]
1 parent 3e87680 commit 8a49712

5 files changed

Lines changed: 68 additions & 73 deletions

File tree

docs/src/pages/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import Heading from "@theme/Heading";
66

77
import styles from "./index.module.css";
88
import { ImageUpload } from "@fourcels/react-image-upload";
9+
import "@fourcels/react-image-upload/dist/index.css";
910

1011
function HomepageHeader() {
1112
const { siteConfig } = useDocusaurusContext();

packages/react-image-upload/src/Dropzone.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { DropzoneOptions, useDropzone } from "react-dropzone";
22
import clsx from "clsx";
3+
import { forwardRef, useImperativeHandle } from "react";
4+
import { u } from "motion/react-client";
35

46
const PlusIcon = () => (
57
<svg
@@ -26,16 +28,19 @@ export type DropzoneProps = {
2628
children?: React.ReactNode;
2729
};
2830

29-
export function Dropzone(props: DropzoneProps) {
31+
export const Dropzone = forwardRef<HTMLElement, DropzoneProps>((props, ref) => {
3032
const { className, options, children, width, height } = props;
3133
const {
34+
rootRef,
3235
getRootProps,
3336
getInputProps,
3437
isDragActive,
3538
isDragAccept,
3639
isDragReject,
3740
} = useDropzone(options);
3841

42+
useImperativeHandle(ref, () => rootRef.current);
43+
3944
return (
4045
<div
4146
{...getRootProps({
@@ -59,4 +64,6 @@ export function Dropzone(props: DropzoneProps) {
5964
)}
6065
</div>
6166
);
62-
}
67+
});
68+
69+
Dropzone.displayName = "Dropzone";

packages/react-image-upload/src/ImageUpload.tsx

Lines changed: 56 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import React, {
22
forwardRef,
33
useCallback,
4+
useEffect,
45
useImperativeHandle,
6+
useRef,
57
useState,
68
} from "react";
79
import { DropzoneOptions } from "react-dropzone";
@@ -13,6 +15,7 @@ import "react-photo-view/dist/react-photo-view.css";
1315
import "./style.css";
1416
import { PhotoProviderProps } from "react-photo-view/dist/PhotoProvider";
1517
import { Dropzone } from "./Dropzone";
18+
import { use } from "motion/react-client";
1619

1720
const RemoveIcon = () => (
1821
<svg
@@ -49,13 +52,8 @@ const PreviewIcon = () => (
4952
</svg>
5053
);
5154

52-
type ValueItem = {
53-
url: string;
54-
name?: string;
55-
};
56-
5755
type ImageItem = {
58-
id: string;
56+
id?: string;
5957
url?: string;
6058
name?: string;
6159
file?: File;
@@ -69,7 +67,7 @@ export type ImageUploadProps = {
6967
height?: number;
7068
dropzoneOptions?: DropzoneOptions;
7169
photoProviderProps?: Omit<PhotoProviderProps, "children">;
72-
value?: string | ValueItem | (string | ValueItem)[];
70+
value?: string | ImageItem | (string | ImageItem)[];
7371
onChange?: (value: ImageItem[]) => void;
7472
max?: number;
7573
onUpload?: (file: File) => string | Promise<string>;
@@ -80,12 +78,7 @@ export type ImageUploadProps = {
8078
children?: React.ReactNode;
8179
};
8280

83-
export type ImageUploadRef = {
84-
reset: (value?: string | ValueItem | (string | ValueItem)[]) => void;
85-
value: ImageItem[];
86-
};
87-
88-
export const ImageUpload = forwardRef<ImageUploadRef, ImageUploadProps>(
81+
export const ImageUpload = forwardRef<HTMLElement, ImageUploadProps>(
8982
(props, ref) => {
9083
const {
9184
width = 100,
@@ -103,76 +96,69 @@ export const ImageUpload = forwardRef<ImageUploadRef, ImageUploadProps>(
10396
children,
10497
} = props;
10598

106-
const getImages = useCallback(
107-
(value: string | ValueItem | (string | ValueItem)[]) => {
108-
if (!Array.isArray(value)) {
109-
value = [value];
110-
}
111-
112-
return value
113-
.map<ImageItem>((item) => {
114-
if (typeof item === "string") {
115-
item = { url: item };
116-
}
117-
return {
118-
id: uuidv7(),
119-
...item,
120-
};
121-
})
122-
.slice(0, max);
123-
},
124-
[max]
125-
);
99+
const dropzoneRef = useRef<HTMLElement>(null);
126100

127-
const [images, setImages] = useState<ImageItem[]>(() => getImages(value));
128-
129-
useImperativeHandle(
130-
ref,
131-
() => ({
132-
reset: (val = value) => {
133-
setImages(getImages(val));
134-
},
135-
get value() {
136-
return images;
137-
},
138-
}),
139-
[value, images]
140-
);
101+
useImperativeHandle(ref, () => dropzoneRef.current);
102+
103+
const getImages = useCallback(() => {
104+
let innerValue = value;
105+
if (!Array.isArray(innerValue)) {
106+
innerValue = [innerValue];
107+
}
108+
109+
return innerValue
110+
.map<ImageItem>((item) => {
111+
if (typeof item === "string") {
112+
item = { url: item };
113+
}
114+
115+
return {
116+
id: uuidv7(),
117+
...item,
118+
};
119+
})
120+
.slice(0, max);
121+
}, [value, max]);
122+
123+
const [images, setImages] = useState<ImageItem[]>(() => getImages());
124+
125+
useEffect(() => {
126+
setImages(getImages());
127+
}, [getImages]);
141128

142129
const onDropAccepted = useCallback(
143130
async (acceptedFiles: File[]) => {
144-
const newImages = acceptedFiles
131+
const addImages = acceptedFiles
145132
.slice(0, max - images.length)
146133
.map<ImageItem>((file) => ({
147134
id: uuidv7(),
148135
name: file.name,
149136
loading: true,
150137
file,
151138
}));
152-
setImages((images) => {
153-
images = images.concat(newImages);
154-
Promise.all(
155-
newImages.map(async (item) => {
156-
item.url = await onUpload?.(item.file);
157-
item.loading = false;
158-
setImages((images) => {
159-
return [...images];
160-
});
161-
})
162-
).then(() => onChange?.(images));
163-
return images;
164-
});
139+
const newImages = images.concat(addImages);
140+
setImages(newImages);
141+
Promise.all(
142+
newImages.map(async (item) => {
143+
item.url = await onUpload?.(item.file);
144+
item.loading = false;
145+
setImages((images) => {
146+
return [...images];
147+
});
148+
})
149+
).then(() => onChange?.(newImages));
165150
},
166-
[images.length, max]
151+
[images, max, onChange]
167152
);
168153

169-
const onRemoveImage = useCallback((idx: number) => {
170-
setImages((images) => {
171-
images = images.filter((_, index) => index != idx);
172-
onChange?.(images);
173-
return images;
174-
});
175-
}, []);
154+
const onRemoveImage = useCallback(
155+
(idx: number) => {
156+
const newImages = images.filter((_, index) => index != idx);
157+
onChange?.(newImages);
158+
setImages(newImages);
159+
},
160+
[images, onChange]
161+
);
176162

177163
return (
178164
<PhotoProvider {...photoProviderProps}>
@@ -232,6 +218,7 @@ export const ImageUpload = forwardRef<ImageUploadRef, ImageUploadProps>(
232218
className={dropzoneClassName}
233219
width={width}
234220
height={height}
221+
ref={dropzoneRef}
235222
>
236223
{children}
237224
</Dropzone>

packages/react-image-upload/src/style.css

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@
8888
cursor: pointer;
8989
user-select: none;
9090

91-
&:hover {
91+
&:hover,
92+
&:focus {
9293
border-color: #2196f3;
9394
}
9495

packages/react-image-upload/tsup.config.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,4 @@ export default defineConfig({
77
splitting: false,
88
sourcemap: true,
99
clean: true,
10-
injectStyle: true,
1110
});

0 commit comments

Comments
 (0)