From 2366f5ee02624fbb2d96c6e6d36748deb678b34d Mon Sep 17 00:00:00 2001 From: morteza-mortezai Date: Fri, 26 Jun 2026 16:32:40 +0330 Subject: [PATCH] fix input shake on typing --- src/components/VoiceRecorder.tsx | 53 ++++++------- src/index.css | 4 + .../request/components/ManageAttribute.tsx | 75 +++++++++++++------ src/pages/request/components/Request.tsx | 25 +++++-- src/router/MainRouter.tsx | 2 +- 5 files changed, 99 insertions(+), 60 deletions(-) diff --git a/src/components/VoiceRecorder.tsx b/src/components/VoiceRecorder.tsx index 3aad16d..9b269b5 100644 --- a/src/components/VoiceRecorder.tsx +++ b/src/components/VoiceRecorder.tsx @@ -1,4 +1,4 @@ -import { type FC, useState, useEffect, useRef } from 'react' +import { memo, type FC, useState, useEffect, useRef, useMemo } from 'react' import { Microphone, Play, Pause } from 'iconsax-react' type Props = { @@ -9,7 +9,7 @@ type Props = { onRecordingComplete?: (audioBlob: Blob) => void } -const VoiceRecorder: FC = ({ +const VoiceRecorder: FC = memo(({ label = 'پیام شما', placeholder = 'پیام شما', value, @@ -110,31 +110,12 @@ const VoiceRecorder: FC = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [isPlaying]) - const generateWaveBars = () => { - const bars = [] - const barCount = 100 - const progress = duration > 0 ? currentTime / duration : 0 - - for (let i = 0; i < barCount; i++) { - const position = i / barCount - const isPassed = position <= progress - const baseHeight = 3 - const randomHeight = Math.random() * 20 + baseHeight - - bars.push( -
- ) - } - - return bars - } + const barCount = 100 + const waveHeights = useMemo( + () => Array.from({ length: barCount }, () => Math.random() * 20 + 3), + [audioUrl] + ) + const progress = duration > 0 ? currentTime / duration : 0 return (
@@ -175,7 +156,19 @@ const VoiceRecorder: FC = ({
- {generateWaveBars()} + {waveHeights.map((height, i) => { + const isPassed = i / barCount <= progress + return ( +
+ ) + })}
) -} +}) + +VoiceRecorder.displayName = 'VoiceRecorder' export default VoiceRecorder diff --git a/src/index.css b/src/index.css index 1567f43..16601d1 100644 --- a/src/index.css +++ b/src/index.css @@ -74,6 +74,10 @@ tbody tr:nth-child(odd) { width: 100%; } +.scrollbar-stable { + scrollbar-gutter: stable; +} + .rowTwoInput { @apply flex flex-col items-start sm:flex-row sm:gap-5 gap-5; } diff --git a/src/pages/request/components/ManageAttribute.tsx b/src/pages/request/components/ManageAttribute.tsx index bff843f..196afae 100644 --- a/src/pages/request/components/ManageAttribute.tsx +++ b/src/pages/request/components/ManageAttribute.tsx @@ -1,4 +1,4 @@ -import { type FC } from 'react' +import { memo, useCallback, useRef, type FC } from 'react' import type { AttributeType, RequestType } from '../type/Types' import { clx } from '@/helpers/utils' import { FieldTypeEnum } from '../enum/RequestEnum' @@ -15,25 +15,57 @@ type Props = { formik: FormikProps } +type AttributeFieldProps = { + item: AttributeType + value: string + onChange: (attributeId: string, value: string) => void +} + +const AttributeTextField = memo(({ item, value, onChange }) => ( +
+ onChange(item.id, e.target.value)} + /> +
+)) +AttributeTextField.displayName = 'AttributeTextField' + +const AttributeTextareaField = memo(({ item, value, onChange }) => ( +
+