Files
klz-cables.com/.pnpm-store/v10/files/ef/f7626c9b688c5709088ef24b58d76885999b46d14d355e7a018459af2172d0289c8341eef7673589b496371f6427d1b9ba7852327c2bc4e4331cd7b072be96
Marc Mintel 5397309103
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
fix(products): fix breadcrumbs and product filtering (backport from main)
2026-02-24 16:04:21 +01:00

143 lines
4.1 KiB
Plaintext

import React, { useState, useRef } from 'react'
import ReactCrop, { centerCrop, makeAspectCrop, Crop, PixelCrop } from '..'
import { canvasPreview } from './canvasPreview'
import { useDebounceEffect } from './useDebounceEffect'
import '../ReactCrop.scss'
import './index.scss'
// This is to demonstate how to make and center a % aspect crop
// which is a bit trickier so we use some helper functions.
function centerAspectCrop(mediaWidth: number, mediaHeight: number, aspect: number) {
return centerCrop(
makeAspectCrop(
{
unit: '%',
width: 90,
},
aspect,
mediaWidth,
mediaHeight
),
mediaWidth,
mediaHeight
)
}
// const defaultAspect = 9 / 16
const defaultAspect = 16 / 9
export function Demo() {
const [imgSrc, setImgSrc] = useState('')
const previewCanvasRef = useRef<HTMLCanvasElement>(null)
const imgRef = useRef<HTMLImageElement>(null)
const [crop, setCrop] = useState<Crop>()
const [completedCrop, setCompletedCrop] = useState<PixelCrop>()
const [scale, setScale] = useState(1)
const [rotate, setRotate] = useState(0)
const [aspect, setAspect] = useState<number | undefined>(defaultAspect)
function onSelectFile(e: React.ChangeEvent<HTMLInputElement>) {
if (e.target.files && e.target.files.length > 0) {
setCrop(undefined) // Makes crop preview update between images.
const reader = new FileReader()
reader.addEventListener('load', () => setImgSrc(reader.result?.toString() || ''))
reader.readAsDataURL(e.target.files[0])
}
}
function onImageLoad(e: React.SyntheticEvent<HTMLImageElement>) {
if (aspect) {
const { width, height } = e.currentTarget
setCrop(centerAspectCrop(width, height, aspect))
}
}
useDebounceEffect(
async () => {
if (completedCrop?.width && completedCrop?.height && imgRef.current && previewCanvasRef.current) {
// We use canvasPreview as it's much faster than imgPreview.
canvasPreview(imgRef.current, previewCanvasRef.current, completedCrop, scale, rotate)
}
},
100,
[completedCrop, scale, rotate]
)
function handleToggleAspectClick() {
if (aspect) {
setAspect(undefined)
} else {
setAspect(defaultAspect)
if (imgRef.current) {
const { width, height } = imgRef.current
setCrop(centerAspectCrop(width, height, defaultAspect))
}
}
}
return (
<div className="App">
<div className="Crop-Controls">
<input type="file" accept="image/*" onChange={onSelectFile} />
<div>
<label htmlFor="scale-input">Scale: </label>
<input
id="scale-input"
type="number"
step="0.1"
value={scale}
disabled={!imgSrc}
onChange={e => setScale(Number(e.target.value))}
/>
</div>
<div>
<label htmlFor="rotate-input">Rotate: </label>
<input
id="rotate-input"
type="number"
value={rotate}
disabled={!imgSrc}
onChange={e => setRotate(Math.min(180, Math.max(-180, Number(e.target.value))))}
/>
</div>
<div>
<button onClick={handleToggleAspectClick}>Toggle aspect {aspect ? 'off' : 'on'}</button>
</div>
</div>
{!!imgSrc && (
<ReactCrop
crop={crop}
onChange={(_, percentCrop) => setCrop(percentCrop)}
onComplete={c => setCompletedCrop(c)}
aspect={aspect}
minWidth={400}
minHeight={200}
>
<img
ref={imgRef}
alt="Crop me"
src={imgSrc}
style={{ transform: `scale(${scale}) rotate(${rotate}deg)` }}
onLoad={onImageLoad}
/>
</ReactCrop>
)}
<div>
{!!completedCrop && (
<canvas
ref={previewCanvasRef}
style={{
border: '1px solid black',
objectFit: 'contain',
width: completedCrop.width,
height: completedCrop.height,
}}
/>
)}
</div>
</div>
)
}