revert: SelectBasicComponent.tsx 이전 상태로 복원
This commit is contained in:
parent
893cd428a0
commit
0281d3722e
|
|
@ -1,5 +1,4 @@
|
||||||
import React, { useState, useEffect, useRef, useMemo } from "react";
|
import React, { useState, useEffect, useRef, useMemo } from "react";
|
||||||
import { createPortal } from "react-dom";
|
|
||||||
import { filterDOMProps } from "@/lib/utils/domPropsFilter";
|
import { filterDOMProps } from "@/lib/utils/domPropsFilter";
|
||||||
import { useCodeOptions, useTableCodeCategory } from "@/hooks/queries/useCodes";
|
import { useCodeOptions, useTableCodeCategory } from "@/hooks/queries/useCodes";
|
||||||
import { cn } from "@/lib/registry/components/common/inputStyles";
|
import { cn } from "@/lib/registry/components/common/inputStyles";
|
||||||
|
|
@ -61,8 +60,6 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
|
||||||
});
|
});
|
||||||
|
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
// 드롭다운 위치 (Portal 렌더링용)
|
|
||||||
const [dropdownPosition, setDropdownPosition] = useState({ top: 0, left: 0, width: 0 });
|
|
||||||
|
|
||||||
// webTypeConfig 또는 componentConfig 사용 (DynamicWebTypeRenderer 호환성)
|
// webTypeConfig 또는 componentConfig 사용 (DynamicWebTypeRenderer 호환성)
|
||||||
const config = (props as any).webTypeConfig || componentConfig || {};
|
const config = (props as any).webTypeConfig || componentConfig || {};
|
||||||
|
|
@ -283,26 +280,9 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
|
||||||
}, [selectedValue, codeOptions, config.options]);
|
}, [selectedValue, codeOptions, config.options]);
|
||||||
|
|
||||||
// 클릭 이벤트 핸들러 (React Query로 간소화)
|
// 클릭 이벤트 핸들러 (React Query로 간소화)
|
||||||
// 드롭다운 위치 계산 함수
|
|
||||||
const updateDropdownPosition = () => {
|
|
||||||
if (selectRef.current) {
|
|
||||||
const rect = selectRef.current.getBoundingClientRect();
|
|
||||||
setDropdownPosition({
|
|
||||||
top: rect.bottom + window.scrollY,
|
|
||||||
left: rect.left + window.scrollX,
|
|
||||||
width: rect.width,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleToggle = () => {
|
const handleToggle = () => {
|
||||||
if (isDesignMode) return;
|
if (isDesignMode) return;
|
||||||
|
|
||||||
// 드롭다운 열기 전에 위치 계산
|
|
||||||
if (!isOpen) {
|
|
||||||
updateDropdownPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
// React Query가 자동으로 캐시 관리하므로 수동 새로고침 불필요
|
// React Query가 자동으로 캐시 관리하므로 수동 새로고침 불필요
|
||||||
setIsOpen(!isOpen);
|
setIsOpen(!isOpen);
|
||||||
};
|
};
|
||||||
|
|
@ -424,13 +404,9 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
|
||||||
value={searchQuery || selectedLabel}
|
value={searchQuery || selectedLabel}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setSearchQuery(e.target.value);
|
setSearchQuery(e.target.value);
|
||||||
updateDropdownPosition();
|
|
||||||
setIsOpen(true);
|
|
||||||
}}
|
|
||||||
onFocus={() => {
|
|
||||||
updateDropdownPosition();
|
|
||||||
setIsOpen(true);
|
setIsOpen(true);
|
||||||
}}
|
}}
|
||||||
|
onFocus={() => setIsOpen(true)}
|
||||||
placeholder="코드 또는 코드명 입력..."
|
placeholder="코드 또는 코드명 입력..."
|
||||||
className={cn(
|
className={cn(
|
||||||
"h-10 w-full rounded-lg border border-gray-300 bg-white px-3 py-2 transition-all outline-none",
|
"h-10 w-full rounded-lg border border-gray-300 bg-white px-3 py-2 transition-all outline-none",
|
||||||
|
|
@ -439,16 +415,8 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
|
||||||
)}
|
)}
|
||||||
readOnly={isDesignMode}
|
readOnly={isDesignMode}
|
||||||
/>
|
/>
|
||||||
{/* Portal을 사용하여 드롭다운을 document.body에 렌더링 */}
|
{isOpen && !isDesignMode && filteredOptions.length > 0 && (
|
||||||
{isOpen && !isDesignMode && filteredOptions.length > 0 && typeof document !== "undefined" && createPortal(
|
<div className="absolute z-[99999] mt-1 max-h-60 w-full overflow-auto rounded-md border border-gray-300 bg-white shadow-lg">
|
||||||
<div
|
|
||||||
className="fixed z-[99999] max-h-60 overflow-auto rounded-md border border-gray-300 bg-white shadow-lg"
|
|
||||||
style={{
|
|
||||||
top: dropdownPosition.top,
|
|
||||||
left: dropdownPosition.left,
|
|
||||||
width: dropdownPosition.width,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{filteredOptions.map((option, index) => (
|
{filteredOptions.map((option, index) => (
|
||||||
<div
|
<div
|
||||||
key={`${option.value}-${index}`}
|
key={`${option.value}-${index}`}
|
||||||
|
|
@ -464,8 +432,7 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>,
|
</div>
|
||||||
document.body
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
@ -495,16 +462,8 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
{/* Portal을 사용하여 드롭다운을 document.body에 렌더링 */}
|
{isOpen && !isDesignMode && (
|
||||||
{isOpen && !isDesignMode && typeof document !== "undefined" && createPortal(
|
<div className="absolute z-[99999] mt-1 max-h-60 w-full overflow-auto rounded-md border border-gray-300 bg-white shadow-lg">
|
||||||
<div
|
|
||||||
className="fixed z-[99999] max-h-60 overflow-auto rounded-md border border-gray-300 bg-white shadow-lg"
|
|
||||||
style={{
|
|
||||||
top: dropdownPosition.top,
|
|
||||||
left: dropdownPosition.left,
|
|
||||||
width: dropdownPosition.width,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{isLoadingCodes ? (
|
{isLoadingCodes ? (
|
||||||
<div className="bg-white px-3 py-2 text-gray-900">로딩 중...</div>
|
<div className="bg-white px-3 py-2 text-gray-900">로딩 중...</div>
|
||||||
) : allOptions.length > 0 ? (
|
) : allOptions.length > 0 ? (
|
||||||
|
|
@ -520,8 +479,7 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
|
||||||
) : (
|
) : (
|
||||||
<div className="bg-white px-3 py-2 text-gray-900">옵션이 없습니다</div>
|
<div className="bg-white px-3 py-2 text-gray-900">옵션이 없습니다</div>
|
||||||
)}
|
)}
|
||||||
</div>,
|
</div>
|
||||||
document.body
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
@ -586,13 +544,9 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
|
||||||
value={searchQuery}
|
value={searchQuery}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setSearchQuery(e.target.value);
|
setSearchQuery(e.target.value);
|
||||||
updateDropdownPosition();
|
|
||||||
setIsOpen(true);
|
|
||||||
}}
|
|
||||||
onFocus={() => {
|
|
||||||
updateDropdownPosition();
|
|
||||||
setIsOpen(true);
|
setIsOpen(true);
|
||||||
}}
|
}}
|
||||||
|
onFocus={() => setIsOpen(true)}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
className={cn(
|
className={cn(
|
||||||
"h-10 w-full rounded-lg border border-gray-300 bg-white px-3 py-2 transition-all outline-none",
|
"h-10 w-full rounded-lg border border-gray-300 bg-white px-3 py-2 transition-all outline-none",
|
||||||
|
|
@ -601,16 +555,8 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
|
||||||
)}
|
)}
|
||||||
readOnly={isDesignMode}
|
readOnly={isDesignMode}
|
||||||
/>
|
/>
|
||||||
{/* Portal을 사용하여 드롭다운을 document.body에 렌더링 */}
|
{isOpen && !isDesignMode && filteredOptions.length > 0 && (
|
||||||
{isOpen && !isDesignMode && filteredOptions.length > 0 && typeof document !== "undefined" && createPortal(
|
<div className="absolute z-[99999] mt-1 max-h-60 w-full overflow-auto rounded-md border border-gray-300 bg-white shadow-lg">
|
||||||
<div
|
|
||||||
className="fixed z-[99999] max-h-60 overflow-auto rounded-md border border-gray-300 bg-white shadow-lg"
|
|
||||||
style={{
|
|
||||||
top: dropdownPosition.top,
|
|
||||||
left: dropdownPosition.left,
|
|
||||||
width: dropdownPosition.width,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{filteredOptions.map((option, index) => (
|
{filteredOptions.map((option, index) => (
|
||||||
<div
|
<div
|
||||||
key={`${option.value}-${index}`}
|
key={`${option.value}-${index}`}
|
||||||
|
|
@ -628,8 +574,7 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
|
||||||
{option.label}
|
{option.label}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>,
|
</div>
|
||||||
document.body
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
@ -659,16 +604,8 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
{/* Portal을 사용하여 드롭다운을 document.body에 렌더링 */}
|
{isOpen && !isDesignMode && (
|
||||||
{isOpen && !isDesignMode && typeof document !== "undefined" && createPortal(
|
<div className="absolute z-[99999] mt-1 w-full rounded-md border border-gray-300 bg-white shadow-lg">
|
||||||
<div
|
|
||||||
className="fixed z-[99999] rounded-md border border-gray-300 bg-white shadow-lg"
|
|
||||||
style={{
|
|
||||||
top: dropdownPosition.top,
|
|
||||||
left: dropdownPosition.left,
|
|
||||||
width: dropdownPosition.width,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={searchQuery}
|
value={searchQuery}
|
||||||
|
|
@ -693,8 +630,7 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>,
|
</div>
|
||||||
document.body
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
@ -711,12 +647,7 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
|
||||||
!isDesignMode && "hover:border-orange-400",
|
!isDesignMode && "hover:border-orange-400",
|
||||||
isSelected && "ring-2 ring-orange-500",
|
isSelected && "ring-2 ring-orange-500",
|
||||||
)}
|
)}
|
||||||
onClick={() => {
|
onClick={() => !isDesignMode && setIsOpen(true)}
|
||||||
if (!isDesignMode) {
|
|
||||||
updateDropdownPosition();
|
|
||||||
setIsOpen(true);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
style={{
|
style={{
|
||||||
pointerEvents: isDesignMode ? "none" : "auto",
|
pointerEvents: isDesignMode ? "none" : "auto",
|
||||||
height: "100%"
|
height: "100%"
|
||||||
|
|
@ -749,30 +680,22 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
|
||||||
<span className="text-gray-500">{placeholder}</span>
|
<span className="text-gray-500">{placeholder}</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{/* Portal을 사용하여 드롭다운을 document.body에 렌더링 */}
|
{isOpen && !isDesignMode && (
|
||||||
{isOpen && !isDesignMode && typeof document !== "undefined" && createPortal(
|
<div className="absolute z-[99999] mt-1 max-h-60 w-full overflow-auto rounded-md border border-gray-300 bg-white shadow-lg">
|
||||||
<div
|
|
||||||
className="fixed z-[99999] max-h-60 overflow-auto rounded-md border border-gray-300 bg-white shadow-lg"
|
|
||||||
style={{
|
|
||||||
top: dropdownPosition.top,
|
|
||||||
left: dropdownPosition.left,
|
|
||||||
width: dropdownPosition.width,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{(isLoadingCodes || isLoadingCategories) ? (
|
{(isLoadingCodes || isLoadingCategories) ? (
|
||||||
<div className="bg-white px-3 py-2 text-gray-900">로딩 중...</div>
|
<div className="bg-white px-3 py-2 text-gray-900">로딩 중...</div>
|
||||||
) : allOptions.length > 0 ? (
|
) : allOptions.length > 0 ? (
|
||||||
allOptions.map((option, index) => {
|
allOptions.map((option, index) => {
|
||||||
const isOptionSelected = selectedValues.includes(option.value);
|
const isSelected = selectedValues.includes(option.value);
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={`${option.value}-${index}`}
|
key={`${option.value}-${index}`}
|
||||||
className={cn(
|
className={cn(
|
||||||
"cursor-pointer px-3 py-2 text-gray-900 hover:bg-gray-100",
|
"cursor-pointer px-3 py-2 text-gray-900 hover:bg-gray-100",
|
||||||
isOptionSelected && "bg-blue-50 font-medium"
|
isSelected && "bg-blue-50 font-medium"
|
||||||
)}
|
)}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const newVals = isOptionSelected
|
const newVals = isSelected
|
||||||
? selectedValues.filter((v) => v !== option.value)
|
? selectedValues.filter((v) => v !== option.value)
|
||||||
: [...selectedValues, option.value];
|
: [...selectedValues, option.value];
|
||||||
setSelectedValues(newVals);
|
setSelectedValues(newVals);
|
||||||
|
|
@ -785,7 +708,7 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={isOptionSelected}
|
checked={isSelected}
|
||||||
onChange={() => {}}
|
onChange={() => {}}
|
||||||
className="h-4 w-4"
|
className="h-4 w-4"
|
||||||
/>
|
/>
|
||||||
|
|
@ -797,8 +720,7 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
|
||||||
) : (
|
) : (
|
||||||
<div className="bg-white px-3 py-2 text-gray-900">옵션이 없습니다</div>
|
<div className="bg-white px-3 py-2 text-gray-900">옵션이 없습니다</div>
|
||||||
)}
|
)}
|
||||||
</div>,
|
</div>
|
||||||
document.body
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
@ -827,16 +749,8 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
{/* Portal을 사용하여 드롭다운을 document.body에 렌더링 */}
|
{isOpen && !isDesignMode && (
|
||||||
{isOpen && !isDesignMode && typeof document !== "undefined" && createPortal(
|
<div className="absolute z-[99999] mt-1 max-h-60 w-full overflow-auto rounded-md border border-gray-300 bg-white shadow-lg">
|
||||||
<div
|
|
||||||
className="fixed z-[99999] max-h-60 overflow-auto rounded-md border border-gray-300 bg-white shadow-lg"
|
|
||||||
style={{
|
|
||||||
top: dropdownPosition.top,
|
|
||||||
left: dropdownPosition.left,
|
|
||||||
width: dropdownPosition.width,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{isLoadingCodes ? (
|
{isLoadingCodes ? (
|
||||||
<div className="bg-white px-3 py-2 text-gray-900">로딩 중...</div>
|
<div className="bg-white px-3 py-2 text-gray-900">로딩 중...</div>
|
||||||
) : allOptions.length > 0 ? (
|
) : allOptions.length > 0 ? (
|
||||||
|
|
@ -852,8 +766,7 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
|
||||||
) : (
|
) : (
|
||||||
<div className="bg-white px-3 py-2 text-gray-900">옵션이 없습니다</div>
|
<div className="bg-white px-3 py-2 text-gray-900">옵션이 없습니다</div>
|
||||||
)}
|
)}
|
||||||
</div>,
|
</div>
|
||||||
document.body
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue