Merge pull request 'dev' (#334) from dev into prd-deploy

Reviewed-on: #334
This commit is contained in:
ysCha 2025-09-09 17:16:43 +09:00
commit eef21b9023
3 changed files with 119 additions and 26 deletions

View File

@ -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'

View File

@ -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>

View File

@ -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')