From 73854fe5be87751adb002135051ce9abac920201 Mon Sep 17 00:00:00 2001 From: dog Date: Sun, 21 Jan 2024 16:51:10 +0300 Subject: [PATCH] prepare image crop component --- .../ImageCropper/ImageCropper.module.scss | 0 .../_shared/ImageCropper/ImageCropper.tsx | 1 + src/components/_shared/ImageCropper/index.tsx | 105 ++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 src/components/_shared/ImageCropper/ImageCropper.module.scss create mode 100644 src/components/_shared/ImageCropper/ImageCropper.tsx create mode 100644 src/components/_shared/ImageCropper/index.tsx diff --git a/src/components/_shared/ImageCropper/ImageCropper.module.scss b/src/components/_shared/ImageCropper/ImageCropper.module.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/components/_shared/ImageCropper/ImageCropper.tsx b/src/components/_shared/ImageCropper/ImageCropper.tsx new file mode 100644 index 00000000..08e025d1 --- /dev/null +++ b/src/components/_shared/ImageCropper/ImageCropper.tsx @@ -0,0 +1 @@ +export { ImageCropper } from './ImageCropper' diff --git a/src/components/_shared/ImageCropper/index.tsx b/src/components/_shared/ImageCropper/index.tsx new file mode 100644 index 00000000..a04b027b --- /dev/null +++ b/src/components/_shared/ImageCropper/index.tsx @@ -0,0 +1,105 @@ +import { createSignal, Show } from 'solid-js' +import { createStore } from 'solid-js/store' +import Cropper from 'cropperjs' + +import styles from './ImageCropper.module.scss' + +export default function ImageCropper(props) { + let cropImage + const [state, setState] = createStore({ + error: null, + loading: false, + file: {}, + croppedImage: null, + }), + [dropZoneActive, setDropZoneActive] = createSignal(false), + [uploading, setUploading] = createSignal(false), + [preview, setPreview] = createSignal(null), + [cropper, setCropper] = createSignal(null), + noPropagate = (e) => { + e.preventDefault() + }, + uploadFile = async (file) => { + if (!file) return + setUploading(true) + setState('loading', true) + setState('file', file) + try { + const reader = new FileReader() + reader.onload = (e) => { + setPreview(e.target.result) + setCropper( + new Cropper(cropImage, { + aspectRatio: 1 / 1, + viewMode: 1, + rotatable: false, + }), + ) + } + reader.readAsDataURL(file) + } catch (e) { + console.error('upload failed', e) + const message = e instanceof Error ? e.message : String(e) + setState('error', message) + } + setState('loading', false) + setUploading(false) + }, + handleFileDrop = async (e) => { + e.preventDefault() + setDropZoneActive(false) + uploadFile(e.dataTransfer.files[0]) + }, + handleFileInput = async (e) => { + e.preventDefault() + uploadFile(e.currentTarget.files[0]) + } + + return ( + <> + +
+
+ cropper +
+ +
+
+ +
+
(uploading() ? undefined : setDropZoneActive(true))} + onDragLeave={() => setDropZoneActive(false)} + onDragOver={noPropagate} + onDrop={(event) => (uploading() ? noPropagate(event) : handleFileDrop(event))} + > +
upload
+ +
+
+ + + + ) +}