next.js 버전 15.4.8

This commit is contained in:
kjs
2025-12-04 10:39:07 +09:00
parent 4d9f010ac5
commit 3ab32820e9
4 changed files with 88 additions and 71 deletions

View File

@@ -52,6 +52,10 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
menuObjid, // 🆕 메뉴 OBJID
...props
}) => {
// 🆕 읽기전용/비활성화 상태 확인
const isReadonly = (component as any).readonly || (props as any).readonly || componentConfig?.readonly || false;
const isDisabled = (component as any).disabled || (props as any).disabled || componentConfig?.disabled || false;
const isFieldDisabled = isDesignMode || isReadonly || isDisabled;
// 화면 컨텍스트 (데이터 제공자로 등록)
const screenContext = useScreenContextOptional();
@@ -327,7 +331,7 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
// 클릭 이벤트 핸들러 (React Query로 간소화)
const handleToggle = () => {
if (isDesignMode) return;
if (isFieldDisabled) return; // 🆕 읽기전용/비활성화 상태에서는 토글 불가
// React Query가 자동으로 캐시 관리하므로 수동 새로고침 불필요
setIsOpen(!isOpen);
@@ -425,7 +429,7 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
value={option.value}
checked={selectedValue === option.value}
onChange={() => handleOptionSelect(option.value, option.label)}
disabled={isDesignMode}
disabled={isFieldDisabled}
className="border-input text-primary focus:ring-ring h-4 w-4"
/>
<span className="text-sm">{option.label}</span>
@@ -456,12 +460,14 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
placeholder="코드 또는 코드명 입력..."
className={cn(
"h-10 w-full rounded-lg border border-gray-300 bg-white px-3 py-2 transition-all outline-none",
!isDesignMode && "hover:border-orange-400 focus:border-orange-500 focus:ring-2 focus:ring-orange-200",
!isFieldDisabled && "hover:border-orange-400 focus:border-orange-500 focus:ring-2 focus:ring-orange-200",
isSelected && "ring-2 ring-orange-500",
isFieldDisabled && "bg-gray-100 cursor-not-allowed",
)}
readOnly={isDesignMode}
readOnly={isFieldDisabled}
disabled={isFieldDisabled}
/>
{isOpen && !isDesignMode && filteredOptions.length > 0 && (
{isOpen && !isFieldDisabled && filteredOptions.length > 0 && (
<div className="absolute z-[99999] mt-1 max-h-60 w-full overflow-auto rounded-md border border-gray-300 bg-white shadow-lg">
{filteredOptions.map((option, index) => (
<div
@@ -490,13 +496,14 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
<div className="w-full">
<div
className={cn(
"flex h-10 w-full cursor-pointer items-center justify-between rounded-lg border border-gray-300 bg-white px-3 py-2",
!isDesignMode && "hover:border-orange-400",
"flex h-10 w-full items-center justify-between rounded-lg border border-gray-300 bg-white px-3 py-2",
!isFieldDisabled && "cursor-pointer hover:border-orange-400",
isSelected && "ring-2 ring-orange-500",
isOpen && "border-orange-500",
isFieldDisabled && "bg-gray-100 cursor-not-allowed",
)}
onClick={handleToggle}
style={{ pointerEvents: isDesignMode ? "none" : "auto" }}
style={{ pointerEvents: isFieldDisabled ? "none" : "auto" }}
>
<span className={selectedLabel ? "text-gray-900" : "text-gray-500"}>{selectedLabel || placeholder}</span>
<svg
@@ -508,7 +515,7 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
</div>
{isOpen && !isDesignMode && (
{isOpen && !isFieldDisabled && (
<div className="absolute z-[99999] mt-1 max-h-60 w-full overflow-auto rounded-md border border-gray-300 bg-white shadow-lg">
{isLoadingCodes ? (
<div className="bg-white px-3 py-2 text-gray-900"> ...</div>
@@ -538,8 +545,9 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
<div
className={cn(
"box-border flex h-full w-full flex-wrap gap-2 rounded-lg border border-gray-300 bg-white px-3 py-2",
!isDesignMode && "hover:border-orange-400",
!isFieldDisabled && "hover:border-orange-400",
isSelected && "ring-2 ring-orange-500",
isFieldDisabled && "bg-gray-100 cursor-not-allowed",
)}
>
{selectedValues.map((val, idx) => {
@@ -567,8 +575,9 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
type="text"
placeholder={selectedValues.length > 0 ? "" : placeholder}
className="min-w-[100px] flex-1 border-none bg-transparent outline-none"
onClick={() => setIsOpen(true)}
readOnly={isDesignMode}
onClick={() => !isFieldDisabled && setIsOpen(true)}
readOnly={isFieldDisabled}
disabled={isFieldDisabled}
/>
</div>
</div>
@@ -589,19 +598,22 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
type="text"
value={searchQuery}
onChange={(e) => {
if (isFieldDisabled) return;
setSearchQuery(e.target.value);
setIsOpen(true);
}}
onFocus={() => setIsOpen(true)}
onFocus={() => !isFieldDisabled && setIsOpen(true)}
placeholder={placeholder}
className={cn(
"h-10 w-full rounded-lg border border-gray-300 bg-white px-3 py-2 transition-all outline-none",
!isDesignMode && "hover:border-orange-400 focus:border-orange-500 focus:ring-2 focus:ring-orange-200",
!isFieldDisabled && "hover:border-orange-400 focus:border-orange-500 focus:ring-2 focus:ring-orange-200",
isSelected && "ring-2 ring-orange-500",
isFieldDisabled && "bg-gray-100 cursor-not-allowed",
)}
readOnly={isDesignMode}
readOnly={isFieldDisabled}
disabled={isFieldDisabled}
/>
{isOpen && !isDesignMode && filteredOptions.length > 0 && (
{isOpen && !isFieldDisabled && filteredOptions.length > 0 && (
<div className="absolute z-[99999] mt-1 max-h-60 w-full overflow-auto rounded-md border border-gray-300 bg-white shadow-lg">
{filteredOptions.map((option, index) => (
<div
@@ -632,13 +644,14 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
<div className="w-full">
<div
className={cn(
"flex h-10 w-full cursor-pointer items-center justify-between rounded-lg border border-gray-300 bg-white px-3 py-2",
!isDesignMode && "hover:border-orange-400",
"flex h-10 w-full items-center justify-between rounded-lg border border-gray-300 bg-white px-3 py-2",
!isFieldDisabled && "cursor-pointer hover:border-orange-400",
isSelected && "ring-2 ring-orange-500",
isOpen && "border-orange-500",
isFieldDisabled && "bg-gray-100 cursor-not-allowed",
)}
onClick={handleToggle}
style={{ pointerEvents: isDesignMode ? "none" : "auto" }}
style={{ pointerEvents: isFieldDisabled ? "none" : "auto" }}
>
<span className={selectedLabel ? "text-gray-900" : "text-gray-500"}>{selectedLabel || placeholder}</span>
<svg
@@ -650,7 +663,7 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
</div>
{isOpen && !isDesignMode && (
{isOpen && !isFieldDisabled && (
<div className="absolute z-[99999] mt-1 w-full rounded-md border border-gray-300 bg-white shadow-lg">
<input
type="text"
@@ -690,12 +703,13 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
<div
className={cn(
"box-border flex w-full flex-wrap items-center gap-2 rounded-lg border border-gray-300 bg-white px-3 py-2",
!isDesignMode && "hover:border-orange-400",
!isFieldDisabled && "hover:border-orange-400",
isSelected && "ring-2 ring-orange-500",
isFieldDisabled && "bg-gray-100 cursor-not-allowed",
)}
onClick={() => !isDesignMode && setIsOpen(true)}
onClick={() => !isFieldDisabled && setIsOpen(true)}
style={{
pointerEvents: isDesignMode ? "none" : "auto",
pointerEvents: isFieldDisabled ? "none" : "auto",
height: "100%"
}}
>
@@ -726,7 +740,7 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
<span className="text-gray-500">{placeholder}</span>
)}
</div>
{isOpen && !isDesignMode && (
{isOpen && !isFieldDisabled && (
<div className="absolute z-[99999] mt-1 max-h-60 w-full overflow-auto rounded-md border border-gray-300 bg-white shadow-lg">
{(isLoadingCodes || isLoadingCategories) ? (
<div className="bg-white px-3 py-2 text-gray-900"> ...</div>
@@ -789,13 +803,14 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
<div className="w-full">
<div
className={cn(
"flex h-10 w-full cursor-pointer items-center justify-between rounded-lg border border-gray-300 bg-white px-3 py-2",
!isDesignMode && "hover:border-orange-400",
"flex h-10 w-full items-center justify-between rounded-lg border border-gray-300 bg-white px-3 py-2",
!isFieldDisabled && "cursor-pointer hover:border-orange-400",
isSelected && "ring-2 ring-orange-500",
isOpen && "border-orange-500",
isFieldDisabled && "bg-gray-100 cursor-not-allowed",
)}
onClick={handleToggle}
style={{ pointerEvents: isDesignMode ? "none" : "auto" }}
style={{ pointerEvents: isFieldDisabled ? "none" : "auto" }}
>
<span className={selectedLabel ? "text-gray-900" : "text-gray-500"}>{selectedLabel || placeholder}</span>
<svg
@@ -807,7 +822,7 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
</div>
{isOpen && !isDesignMode && (
{isOpen && !isFieldDisabled && (
<div className="absolute z-[99999] mt-1 max-h-60 w-full overflow-auto rounded-md border border-gray-300 bg-white shadow-lg">
{isLoadingCodes ? (
<div className="bg-white px-3 py-2 text-gray-900"> ...</div>