리사이징, 체크박스,엔터치면 다음 칸으로 이동, 표수정, 컬럼에서 이미지 넣는거 등등
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState, useCallback } from "react";
|
||||
import React, { useState, useCallback, useEffect } from "react";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ResizableDialog, ResizableDialogContent, ResizableDialogHeader, DialogTitle } from "@/components/ui/dialog";
|
||||
import { ResizableDialog, ResizableDialogContent, ResizableDialogHeader } from "@/components/ui/resizable-dialog";
|
||||
import { DialogTitle, DialogHeader } from "@/components/ui/dialog";
|
||||
import { useAuth } from "@/hooks/useAuth";
|
||||
import { uploadFilesAndCreateData } from "@/lib/api/file";
|
||||
import { toast } from "sonner";
|
||||
@@ -120,6 +121,67 @@ export const InteractiveScreenViewerDynamic: React.FC<InteractiveScreenViewerPro
|
||||
[userName],
|
||||
);
|
||||
|
||||
// 🆕 Enter 키로 다음 필드 이동
|
||||
useEffect(() => {
|
||||
const handleEnterKey = (e: KeyboardEvent) => {
|
||||
if (e.key === "Enter" && !e.shiftKey) {
|
||||
const target = e.target as HTMLElement;
|
||||
|
||||
// textarea는 제외 (여러 줄 입력)
|
||||
if (target.tagName === "TEXTAREA") {
|
||||
return;
|
||||
}
|
||||
|
||||
// input, select 등의 폼 요소에서만 작동
|
||||
if (
|
||||
target.tagName === "INPUT" ||
|
||||
target.tagName === "SELECT" ||
|
||||
target.getAttribute("role") === "combobox"
|
||||
) {
|
||||
e.preventDefault();
|
||||
|
||||
// 모든 포커스 가능한 요소 찾기
|
||||
const focusableElements = document.querySelectorAll<HTMLElement>(
|
||||
'input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), [role="combobox"]:not([disabled])'
|
||||
);
|
||||
|
||||
// 화면에 보이는 순서(Y 좌표 → X 좌표)대로 정렬
|
||||
const focusableArray = Array.from(focusableElements).sort((a, b) => {
|
||||
const rectA = a.getBoundingClientRect();
|
||||
const rectB = b.getBoundingClientRect();
|
||||
|
||||
// Y 좌표 차이가 10px 이상이면 Y 좌표로 정렬 (위에서 아래로)
|
||||
if (Math.abs(rectA.top - rectB.top) > 10) {
|
||||
return rectA.top - rectB.top;
|
||||
}
|
||||
|
||||
// 같은 줄이면 X 좌표로 정렬 (왼쪽에서 오른쪽으로)
|
||||
return rectA.left - rectB.left;
|
||||
});
|
||||
|
||||
const currentIndex = focusableArray.indexOf(target);
|
||||
|
||||
if (currentIndex !== -1 && currentIndex < focusableArray.length - 1) {
|
||||
// 다음 요소로 포커스 이동
|
||||
const nextElement = focusableArray[currentIndex + 1];
|
||||
nextElement.focus();
|
||||
|
||||
// input이면 전체 선택
|
||||
if (nextElement.tagName === "INPUT") {
|
||||
(nextElement as HTMLInputElement).select();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener("keydown", handleEnterKey);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener("keydown", handleEnterKey);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// 🆕 autoFill 자동 입력 초기화
|
||||
React.useEffect(() => {
|
||||
const initAutoInputFields = async () => {
|
||||
@@ -630,11 +692,17 @@ export const InteractiveScreenViewerDynamic: React.FC<InteractiveScreenViewerPro
|
||||
|
||||
{/* 팝업 화면 렌더링 */}
|
||||
{popupScreen && (
|
||||
<Dialog open={!!popupScreen} onOpenChange={() => setPopupScreen(null)}>
|
||||
<DialogContent
|
||||
className={` ${
|
||||
popupScreen.size === "small" ? "max-w-md" : popupScreen.size === "large" ? "max-w-6xl" : "max-w-4xl"
|
||||
} max-h-[90vh] overflow-y-auto`}
|
||||
<ResizableDialog open={!!popupScreen} onOpenChange={() => setPopupScreen(null)}>
|
||||
<ResizableDialogContent
|
||||
className="overflow-hidden p-0"
|
||||
defaultWidth={popupScreen.size === "small" ? 600 : popupScreen.size === "large" ? 1400 : 1000}
|
||||
defaultHeight={800}
|
||||
minWidth={500}
|
||||
minHeight={400}
|
||||
maxWidth={1600}
|
||||
maxHeight={1200}
|
||||
modalId={`popup-screen-${popupScreen.screenId}`}
|
||||
userId={user?.userId || "guest"}
|
||||
>
|
||||
<DialogHeader>
|
||||
<DialogTitle>{popupScreen.title}</DialogTitle>
|
||||
@@ -668,8 +736,8 @@ export const InteractiveScreenViewerDynamic: React.FC<InteractiveScreenViewerPro
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</ResizableDialogContent>
|
||||
</ResizableDialog>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user