Merge branch 'mhkim-node' of http://39.117.244.52:3000/kjs/ERP-node into jskim-node
This commit is contained in:
commit
2cf5c8de32
|
|
@ -563,8 +563,20 @@ export const EditModal: React.FC<EditModalProps> = ({ className }) => {
|
||||||
if (screenInfo && layoutData) {
|
if (screenInfo && layoutData) {
|
||||||
const components = layoutData.components || [];
|
const components = layoutData.components || [];
|
||||||
|
|
||||||
// 화면의 실제 크기 계산
|
// 화면 관리에서 설정한 해상도 우선 사용 (ScreenModal과 동일)
|
||||||
const dimensions = calculateScreenDimensions(components);
|
const screenResolution = (layoutData as any).screenResolution || (screenInfo as any).screenResolution;
|
||||||
|
|
||||||
|
let dimensions;
|
||||||
|
if (screenResolution && screenResolution.width && screenResolution.height) {
|
||||||
|
dimensions = {
|
||||||
|
width: screenResolution.width,
|
||||||
|
height: screenResolution.height,
|
||||||
|
offsetX: 0,
|
||||||
|
offsetY: 0,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
dimensions = calculateScreenDimensions(components);
|
||||||
|
}
|
||||||
setScreenDimensions(dimensions);
|
setScreenDimensions(dimensions);
|
||||||
|
|
||||||
setScreenData({
|
setScreenData({
|
||||||
|
|
@ -1547,31 +1559,25 @@ export const EditModal: React.FC<EditModalProps> = ({ className }) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 모달 크기 설정 - 화면관리 설정 크기 + 헤더
|
// 모달 크기 설정 - ScreenModal과 동일한 방식 (maxHeight로 유연 처리)
|
||||||
const getModalStyle = () => {
|
const getModalStyle = () => {
|
||||||
if (!screenDimensions) {
|
if (!screenDimensions) {
|
||||||
return {
|
return {
|
||||||
className: "w-fit min-w-[400px] max-w-4xl max-h-[90vh] overflow-hidden p-0",
|
className: "w-fit min-w-[400px] max-w-4xl overflow-hidden",
|
||||||
style: undefined, // undefined로 변경 - defaultWidth/defaultHeight 사용
|
style: { padding: 0, gap: 0, maxHeight: "calc(100dvh - 8px)" },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 화면관리에서 설정한 크기 = 컨텐츠 영역 크기
|
const finalWidth = Math.min(screenDimensions.width, window.innerWidth * 0.98);
|
||||||
// 실제 모달 크기 = 컨텐츠 + 헤더 + gap + padding + 라벨 공간
|
|
||||||
const headerHeight = 52; // DialogHeader (타이틀 + border-b + py-3)
|
|
||||||
const dialogGap = 16; // DialogContent gap-4
|
|
||||||
const extraPadding = 24; // 추가 여백 (안전 마진)
|
|
||||||
const labelSpace = 30; // 입력 필드 위 라벨 공간 (-top-6 = 24px + 여유)
|
|
||||||
|
|
||||||
const totalHeight = screenDimensions.height + headerHeight + dialogGap + extraPadding + labelSpace;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
className: "overflow-hidden p-0",
|
className: "overflow-hidden p-0",
|
||||||
style: {
|
style: {
|
||||||
width: `${Math.min(screenDimensions.width + 48, window.innerWidth * 0.98)}px`, // 좌우 패딩 추가
|
width: `${finalWidth}px`,
|
||||||
height: `${Math.min(totalHeight, window.innerHeight * 0.95)}px`,
|
maxHeight: "calc(100dvh - 8px)",
|
||||||
maxWidth: "98vw",
|
maxWidth: "98vw",
|
||||||
maxHeight: "95vh",
|
padding: 0,
|
||||||
|
gap: 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -1593,7 +1599,7 @@ export const EditModal: React.FC<EditModalProps> = ({ className }) => {
|
||||||
</div>
|
</div>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
<div className="[&::-webkit-scrollbar-thumb]:bg-muted/60 flex flex-1 justify-center overflow-y-auto [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-track]:bg-transparent">
|
<div className="flex-1 min-h-0 flex items-start justify-center overflow-auto">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div className="flex h-full items-center justify-center">
|
<div className="flex h-full items-center justify-center">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
|
|
@ -1608,42 +1614,41 @@ export const EditModal: React.FC<EditModalProps> = ({ className }) => {
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
data-screen-runtime="true"
|
data-screen-runtime="true"
|
||||||
className="bg-card relative m-auto"
|
className="relative bg-white"
|
||||||
style={{
|
style={{
|
||||||
width: screenDimensions?.width || 800,
|
width: `${screenDimensions?.width || 800}px`,
|
||||||
// 조건부 레이어가 활성화되면 높이 자동 확장
|
minHeight: `${screenDimensions?.height || 600}px`,
|
||||||
height: (() => {
|
height: (() => {
|
||||||
const baseHeight = (screenDimensions?.height || 600) + 30;
|
const baseHeight = screenDimensions?.height || 600;
|
||||||
if (activeConditionalComponents.length > 0) {
|
if (activeConditionalComponents.length > 0) {
|
||||||
// 조건부 레이어 컴포넌트 중 가장 아래 위치 계산
|
|
||||||
const offsetY = screenDimensions?.offsetY || 0;
|
const offsetY = screenDimensions?.offsetY || 0;
|
||||||
let maxBottom = 0;
|
let maxBottom = 0;
|
||||||
activeConditionalComponents.forEach((comp) => {
|
activeConditionalComponents.forEach((comp) => {
|
||||||
const y = parseFloat(comp.position?.y?.toString() || "0") - offsetY + 30;
|
const y = parseFloat(comp.position?.y?.toString() || "0") - offsetY;
|
||||||
const h = parseFloat(comp.size?.height?.toString() || "40");
|
const h = parseFloat(comp.size?.height?.toString() || "40");
|
||||||
maxBottom = Math.max(maxBottom, y + h);
|
maxBottom = Math.max(maxBottom, y + h);
|
||||||
});
|
});
|
||||||
return Math.max(baseHeight, maxBottom + 20); // 20px 여백
|
return `${Math.max(baseHeight, maxBottom + 20)}px`;
|
||||||
}
|
}
|
||||||
return baseHeight;
|
return `${baseHeight}px`;
|
||||||
})(),
|
})(),
|
||||||
transformOrigin: "center center",
|
overflow: "visible",
|
||||||
maxWidth: "100%",
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* 기본 레이어 컴포넌트 렌더링 */}
|
{/* 기본 레이어 컴포넌트 렌더링 */}
|
||||||
{screenData.components.map((component) => {
|
{screenData.components.map((component) => {
|
||||||
// 컴포넌트 위치를 offset만큼 조정
|
|
||||||
const offsetX = screenDimensions?.offsetX || 0;
|
const offsetX = screenDimensions?.offsetX || 0;
|
||||||
const offsetY = screenDimensions?.offsetY || 0;
|
const offsetY = screenDimensions?.offsetY || 0;
|
||||||
const labelSpace = 30; // 라벨 공간 (입력 필드 위 -top-6 라벨용)
|
// screenResolution이 있으면 offsetY=0이므로 디자이너 좌표 그대로 사용
|
||||||
|
// offsetY > 0 (자동 계산)일 때만 라벨 공간 보정
|
||||||
|
const labelSpace = offsetY > 0 ? 30 : 0;
|
||||||
|
|
||||||
const adjustedComponent = {
|
const adjustedComponent = {
|
||||||
...component,
|
...component,
|
||||||
position: {
|
position: {
|
||||||
...component.position,
|
...component.position,
|
||||||
x: parseFloat(component.position?.x?.toString() || "0") - offsetX,
|
x: parseFloat(component.position?.x?.toString() || "0") - offsetX,
|
||||||
y: parseFloat(component.position?.y?.toString() || "0") - offsetY + labelSpace, // 라벨 공간 추가
|
y: parseFloat(component.position?.y?.toString() || "0") - offsetY + labelSpace,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1709,11 +1714,11 @@ export const EditModal: React.FC<EditModalProps> = ({ className }) => {
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
||||||
{/* 🆕 조건부 레이어 컴포넌트 렌더링 */}
|
{/* 조건부 레이어 컴포넌트 렌더링 */}
|
||||||
{activeConditionalComponents.map((component) => {
|
{activeConditionalComponents.map((component) => {
|
||||||
const offsetX = screenDimensions?.offsetX || 0;
|
const offsetX = screenDimensions?.offsetX || 0;
|
||||||
const offsetY = screenDimensions?.offsetY || 0;
|
const offsetY = screenDimensions?.offsetY || 0;
|
||||||
const labelSpace = 30;
|
const labelSpace = offsetY > 0 ? 30 : 0;
|
||||||
|
|
||||||
const adjustedComponent = {
|
const adjustedComponent = {
|
||||||
...component,
|
...component,
|
||||||
|
|
|
||||||
|
|
@ -89,12 +89,12 @@ function formatTel(value: string): string {
|
||||||
return `${digits.slice(0, 4)}-${digits.slice(4, 8)}`;
|
return `${digits.slice(0, 4)}-${digits.slice(4, 8)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 서울: 02 → 2-4-4
|
// 서울: 02 → 9자리 2-3-4, 10자리 2-4-4
|
||||||
if (digits.startsWith("02")) {
|
if (digits.startsWith("02")) {
|
||||||
if (digits.length <= 2) return digits;
|
if (digits.length <= 2) return digits;
|
||||||
if (digits.length <= 6) return `${digits.slice(0, 2)}-${digits.slice(2)}`;
|
if (digits.length <= 5) return `${digits.slice(0, 2)}-${digits.slice(2)}`;
|
||||||
if (digits.length <= 10) return `${digits.slice(0, 2)}-${digits.slice(2, 6)}-${digits.slice(6)}`;
|
const mid = digits.length >= 10 ? 4 : 3;
|
||||||
return `${digits.slice(0, 2)}-${digits.slice(2, 6)}-${digits.slice(6, 10)}`;
|
return `${digits.slice(0, 2)}-${digits.slice(2, 2 + mid)}-${digits.slice(2 + mid, 2 + mid + 4)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 안심번호: 050x → 4-4-4
|
// 안심번호: 050x → 4-4-4
|
||||||
|
|
@ -1228,7 +1228,7 @@ export const V2Input = forwardRef<HTMLDivElement, V2InputProps>((props, ref) =>
|
||||||
ref={ref}
|
ref={ref}
|
||||||
id={id}
|
id={id}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex gap-1",
|
"flex",
|
||||||
labelPos === "left" ? "flex-row items-center" : "flex-row-reverse items-center",
|
labelPos === "left" ? "flex-row items-center" : "flex-row-reverse items-center",
|
||||||
)}
|
)}
|
||||||
style={{
|
style={{
|
||||||
|
|
|
||||||
|
|
@ -1291,7 +1291,7 @@ export const V2Select = forwardRef<HTMLDivElement, V2SelectProps>((props, ref) =
|
||||||
ref={ref}
|
ref={ref}
|
||||||
id={id}
|
id={id}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex gap-1",
|
"flex",
|
||||||
labelPos === "left" ? "flex-row items-center" : "flex-row-reverse items-center",
|
labelPos === "left" ? "flex-row items-center" : "flex-row-reverse items-center",
|
||||||
isDesignMode && "pointer-events-none",
|
isDesignMode && "pointer-events-none",
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -808,12 +808,10 @@ export const DynamicComponentRenderer: React.FC<DynamicComponentRendererProps> =
|
||||||
? component.style?.labelText || (component as any).label || component.componentConfig?.label
|
? component.style?.labelText || (component as any).label || component.componentConfig?.label
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
// 🔧 수평 라벨(left/right) 감지 → 런타임에서만 외부 flex 컨테이너로 라벨 처리
|
// 🔧 수평 라벨(left/right) 감지 → 외부 absolute 래퍼로 라벨 처리 (카테고리 셀렉트와 동일 방식)
|
||||||
// 디자인 모드에서는 V2 컴포넌트가 자체적으로 라벨을 렌더링 (height 체인 문제 방지)
|
|
||||||
const labelPosition = component.style?.labelPosition;
|
const labelPosition = component.style?.labelPosition;
|
||||||
const isV2Component = componentType?.startsWith("v2-");
|
const isV2Component = componentType?.startsWith("v2-");
|
||||||
const needsExternalHorizLabel = !!(
|
const needsExternalHorizLabel = !!(
|
||||||
!props.isDesignMode &&
|
|
||||||
isV2Component &&
|
isV2Component &&
|
||||||
effectiveLabel &&
|
effectiveLabel &&
|
||||||
(labelPosition === "left" || labelPosition === "right")
|
(labelPosition === "left" || labelPosition === "right")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue