next.js 버전 15.4.8
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user