Merge pull request 'dev' (#334) from dev into prd-deploy
Reviewed-on: #334
This commit is contained in:
commit
eef21b9023
@ -1,8 +1,8 @@
|
|||||||
import React, { useState, useRef, useEffect } from 'react'
|
import React, { useState, useRef, useEffect, forwardRef } from 'react'
|
||||||
import { createCalculator } from '@/util/calc-utils'
|
import { createCalculator } from '@/util/calc-utils'
|
||||||
import '@/styles/calc.scss'
|
import '@/styles/calc.scss'
|
||||||
|
|
||||||
export const CalculatorInput = ({ value, onChange, label, options = {}, id, className = 'calculator-input', readOnly = false }) => {
|
export const CalculatorInput = forwardRef(({ value, onChange, label, options = {}, id, className = 'calculator-input', readOnly = false, placeholder}, ref) => {
|
||||||
const [showKeypad, setShowKeypad] = useState(false)
|
const [showKeypad, setShowKeypad] = useState(false)
|
||||||
const [displayValue, setDisplayValue] = useState(value || '0')
|
const [displayValue, setDisplayValue] = useState(value || '0')
|
||||||
const [hasOperation, setHasOperation] = useState(false)
|
const [hasOperation, setHasOperation] = useState(false)
|
||||||
@ -10,6 +10,17 @@ export const CalculatorInput = ({ value, onChange, label, options = {}, id, clas
|
|||||||
const containerRef = useRef(null)
|
const containerRef = useRef(null)
|
||||||
const inputRef = useRef(null)
|
const inputRef = useRef(null)
|
||||||
|
|
||||||
|
// 외부 ref와 내부 ref를 동기화
|
||||||
|
useEffect(() => {
|
||||||
|
if (ref) {
|
||||||
|
if (typeof ref === 'function') {
|
||||||
|
ref(inputRef.current)
|
||||||
|
} else {
|
||||||
|
ref.current = inputRef.current
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [ref])
|
||||||
|
|
||||||
// Sync displayValue with value prop
|
// Sync displayValue with value prop
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setDisplayValue(value || '0')
|
setDisplayValue(value || '0')
|
||||||
@ -138,7 +149,7 @@ export const CalculatorInput = ({ value, onChange, label, options = {}, id, clas
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 계산 실행 함수 수정
|
// 계산 실행 함수 수정
|
||||||
const handleCompute = () => {
|
const handleCompute = (fromEnterKey = false) => {
|
||||||
const calculator = calculatorRef.current
|
const calculator = calculatorRef.current
|
||||||
if (!hasOperation || !calculator.currentOperand) return
|
if (!hasOperation || !calculator.currentOperand) return
|
||||||
|
|
||||||
@ -150,14 +161,16 @@ export const CalculatorInput = ({ value, onChange, label, options = {}, id, clas
|
|||||||
// Only call onChange with the final result
|
// Only call onChange with the final result
|
||||||
onChange(resultStr)
|
onChange(resultStr)
|
||||||
|
|
||||||
// 포커스 유지 및 커서 위치 설정 (맨 뒤로)
|
// 엔터키로 호출된 경우 포커스 설정하지 않음
|
||||||
requestAnimationFrame(() => {
|
if (!fromEnterKey) {
|
||||||
if (inputRef.current) {
|
requestAnimationFrame(() => {
|
||||||
inputRef.current.focus()
|
if (inputRef.current) {
|
||||||
const len = resultStr.length
|
inputRef.current.focus()
|
||||||
inputRef.current.setSelectionRange(len, len)
|
const len = resultStr.length
|
||||||
}
|
inputRef.current.setSelectionRange(len, len)
|
||||||
})
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,12 +268,22 @@ export const CalculatorInput = ({ value, onChange, label, options = {}, id, clas
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 방향키는 기본 동작 허용
|
// 모든 방향키는 기본 동작 허용
|
||||||
if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
|
if (e.key === 'ArrowLeft' || e.key === 'ArrowRight' || e.key === 'ArrowUp' || e.key === 'ArrowDown') {
|
||||||
setShowKeypad(true)
|
setShowKeypad(true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 계산기 허용 키들이 입력되면 키패드 표시 (엔터키 제외)
|
||||||
|
if (/^[0-9+\-×÷.=]$/.test(e.key) || e.key === 'Backspace' || e.key === 'Delete' || e.key === '*' || e.key === '/') {
|
||||||
|
setShowKeypad(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 키패드가 숨겨진 상태에서 엔터키는 페이지로 전달
|
||||||
|
if (!showKeypad && e.key === 'Enter') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
const calculator = calculatorRef.current
|
const calculator = calculatorRef.current
|
||||||
const { allowDecimal } = options
|
const { allowDecimal } = options
|
||||||
@ -291,7 +314,12 @@ export const CalculatorInput = ({ value, onChange, label, options = {}, id, clas
|
|||||||
break
|
break
|
||||||
case 'Enter':
|
case 'Enter':
|
||||||
case '=':
|
case '=':
|
||||||
handleCompute()
|
if (showKeypad) {
|
||||||
|
// 키패드가 보이는 상태에서 엔터키: 계산 후 키패드만 숨김
|
||||||
|
handleCompute(true) // 엔터키로 호출됨을 표시
|
||||||
|
setShowKeypad(false)
|
||||||
|
}
|
||||||
|
// 키패드가 숨겨진 상태에서 엔터키: 페이지로 전달 (preventDefault 하지 않음)
|
||||||
break
|
break
|
||||||
case 'Backspace':
|
case 'Backspace':
|
||||||
case 'Delete':
|
case 'Delete':
|
||||||
@ -328,6 +356,8 @@ export const CalculatorInput = ({ value, onChange, label, options = {}, id, clas
|
|||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
tabIndex={readOnly ? -1 : 0}
|
tabIndex={readOnly ? -1 : 0}
|
||||||
|
placeholder={placeholder}
|
||||||
|
autoComplete={'off'}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{showKeypad && !readOnly && (
|
{showKeypad && !readOnly && (
|
||||||
@ -391,7 +421,7 @@ export const CalculatorInput = ({ value, onChange, label, options = {}, id, clas
|
|||||||
.
|
.
|
||||||
</button>
|
</button>
|
||||||
{/* = 버튼 */}
|
{/* = 버튼 */}
|
||||||
<button onClick={handleCompute} className="btn-equals">
|
<button onClick={() => handleCompute(false)} className="btn-equals">
|
||||||
=
|
=
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -399,4 +429,6 @@ export const CalculatorInput = ({ value, onChange, label, options = {}, id, clas
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
|
|
||||||
|
CalculatorInput.displayName = 'CalculatorInput'
|
||||||
|
|||||||
@ -2,29 +2,90 @@
|
|||||||
|
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { normalizeDigits } from '@/util/input-utils'
|
import { normalizeDigits } from '@/util/input-utils'
|
||||||
|
import { getChonByDegree, getDegreeByChon } from '@/util/canvas-util'
|
||||||
|
import { CalculatorInput } from '@/components/common/input/CalcInput'
|
||||||
|
import { useEffect, useRef } from 'react'
|
||||||
|
|
||||||
export default function OuterLineWall({ props }) {
|
export default function OuterLineWall({ props }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
|
||||||
const { length1, setLength1, length1Ref, arrow1, setArrow1 } = props
|
const { length1, setLength1, length1Ref, arrow1, setArrow1 } = props
|
||||||
|
|
||||||
|
// 키보드 입력 처리
|
||||||
|
useEffect(() => {
|
||||||
|
const handleKeyDown = (e) => {
|
||||||
|
// 계산기 키패드가 보이는지 확인
|
||||||
|
const keypadVisible = document.querySelector('.keypad-container')
|
||||||
|
|
||||||
|
// 계산기 키패드가 보이면 계산기가 처리하도록 함
|
||||||
|
if (keypadVisible) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 이미 계산기 input에 포커스가 있으면 계산기가 처리하도록 함
|
||||||
|
if (document.activeElement && document.activeElement.classList.contains('calculator-input')) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 엔터키는 계산기가 숨겨진 상태에서만 페이지가 처리
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
// 엔터키를 페이지 레벨로 전달 (useOuterLineWall.js에서 처리)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 숫자 키가 입력되면 계산기 input에 포커스만 주기
|
||||||
|
if (/^[0-9+\-*\/=.]$/.test(e.key) || e.key === 'Backspace' || e.key === 'Delete') {
|
||||||
|
const calcInput = document.querySelector('.calculator-input')
|
||||||
|
if (calcInput) {
|
||||||
|
// 포커스만 주고 이벤트는 preventDefault 하지 않음
|
||||||
|
calcInput.focus()
|
||||||
|
calcInput.click()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// capture: true로 설정하여 다른 핸들러보다 먼저 실행
|
||||||
|
document.addEventListener('keydown', handleKeyDown, { capture: true })
|
||||||
|
return () => document.removeEventListener('keydown', handleKeyDown, { capture: true })
|
||||||
|
}, [])
|
||||||
return (
|
return (
|
||||||
<div className="outline-wrap">
|
<div className="outline-wrap">
|
||||||
<div className="outline-inner">
|
<div className="outline-inner">
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<span className="mr10">{getMessage('straight.line')}</span>
|
<span className="mr10">{getMessage('straight.line')}</span>
|
||||||
<div className="input-grid" style={{ width: '63px' }}>
|
<div className="input-grid" style={{ width: '63px' }}>
|
||||||
<input
|
{/*<input*/}
|
||||||
type="text"
|
{/* type="text"*/}
|
||||||
className="input-origin block"
|
{/* className="input-origin block"*/}
|
||||||
|
{/* value={length1}*/}
|
||||||
|
{/* ref={length1Ref}*/}
|
||||||
|
{/* onFocus={(e) => {*/}
|
||||||
|
{/* if (length1Ref.current.value === '0') {*/}
|
||||||
|
{/* length1Ref.current.value = ''*/}
|
||||||
|
{/* }*/}
|
||||||
|
{/* }}*/}
|
||||||
|
{/* onChange={(e) => setLength1(normalizeDigits(e.target.value))}*/}
|
||||||
|
{/* placeholder="3000"*/}
|
||||||
|
{/*/>*/}
|
||||||
|
|
||||||
|
<CalculatorInput
|
||||||
|
id="length1-calc"
|
||||||
|
label=""
|
||||||
|
className="input-origin block calculator-input"
|
||||||
|
readOnly={false}
|
||||||
value={length1}
|
value={length1}
|
||||||
|
onChange={(value) => setLength1(value)}
|
||||||
|
options={{
|
||||||
|
allowNegative: false,
|
||||||
|
allowDecimal: false //(index !== 0),
|
||||||
|
}}
|
||||||
|
placeholder={'3000'}
|
||||||
ref={length1Ref}
|
ref={length1Ref}
|
||||||
onFocus={(e) => {
|
onFocus={() => {
|
||||||
if (length1Ref.current.value === '0') {
|
if (length1Ref.current && length1Ref.current.value === '0') {
|
||||||
length1Ref.current.value = ''
|
length1Ref.current.value = ''
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onChange={(e) => setLength1(normalizeDigits(e.target.value))}
|
|
||||||
placeholder="3000"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<button className="reset-btn" onClick={() => setLength1(0)}></button>
|
<button className="reset-btn" onClick={() => setLength1(0)}></button>
|
||||||
|
|||||||
@ -129,7 +129,7 @@ export function useEvent() {
|
|||||||
let arrivalPoint = { x: pointer.x, y: pointer.y }
|
let arrivalPoint = { x: pointer.x, y: pointer.y }
|
||||||
|
|
||||||
if (adsorptionPointMode) {
|
if (adsorptionPointMode) {
|
||||||
const roofsPoints = roofs.map((roof) => roof.points).flat()
|
const roofsPoints = roofs.map((roof) => roof.getCurrentPoints()).flat()
|
||||||
roofAdsorptionPoints.current = [...roofsPoints]
|
roofAdsorptionPoints.current = [...roofsPoints]
|
||||||
|
|
||||||
const auxiliaryLines = canvas.getObjects().filter((obj) => obj.name === 'auxiliaryLine')
|
const auxiliaryLines = canvas.getObjects().filter((obj) => obj.name === 'auxiliaryLine')
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user