feat: add nested panel selection support in dynamic components
- Introduced a new callback `onNestedPanelSelect` to handle selections of components within nested split panels. - Updated the `RealtimePreviewDynamic`, `DynamicComponentRenderer`, and `TabsDesignEditor` components to support the new nested selection functionality. - Enhanced the layout management logic in `ScreenDesigner` to accommodate updates for nested structures, improving the overall user experience when interacting with nested components. Made-with: Cursor
This commit is contained in:
@@ -6744,15 +6744,6 @@ export default function ScreenDesigner({
|
||||
const { splitPanelId, panelSide } = selectedPanelComponentInfo;
|
||||
const panelKey = panelSide === "left" ? "leftPanel" : "rightPanel";
|
||||
|
||||
console.log("🔧 updatePanelComponentProperty 호출:", {
|
||||
componentId,
|
||||
path,
|
||||
value,
|
||||
splitPanelId,
|
||||
panelSide,
|
||||
});
|
||||
|
||||
// 🆕 안전한 깊은 경로 업데이트 헬퍼 함수
|
||||
const setNestedValue = (obj: any, pathStr: string, val: any): any => {
|
||||
const result = JSON.parse(JSON.stringify(obj));
|
||||
const parts = pathStr.split(".");
|
||||
@@ -6769,9 +6760,27 @@ export default function ScreenDesigner({
|
||||
return result;
|
||||
};
|
||||
|
||||
// 중첩 구조 포함 분할패널 찾기 헬퍼
|
||||
const findSplitPanelInLayout = (components: any[]): { found: any; path: "top" | "nested"; parentTabId?: string; parentTabTabId?: string } | null => {
|
||||
const direct = components.find((c) => c.id === splitPanelId);
|
||||
if (direct) return { found: direct, path: "top" };
|
||||
for (const comp of components) {
|
||||
const ct = (comp as any)?.componentType || (comp as any)?.overrides?.type;
|
||||
const cfg = (comp as any)?.componentConfig || (comp as any)?.overrides || {};
|
||||
if (ct === "tabs-widget" || ct === "v2-tabs-widget") {
|
||||
for (const tab of (cfg.tabs || [])) {
|
||||
const nested = (tab.components || []).find((c: any) => c.id === splitPanelId);
|
||||
if (nested) return { found: nested, path: "nested", parentTabId: comp.id, parentTabTabId: tab.id };
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
setLayout((prevLayout) => {
|
||||
const splitPanelComponent = prevLayout.components.find((c) => c.id === splitPanelId);
|
||||
if (!splitPanelComponent) return prevLayout;
|
||||
const result = findSplitPanelInLayout(prevLayout.components);
|
||||
if (!result) return prevLayout;
|
||||
const splitPanelComponent = result.found;
|
||||
|
||||
const currentConfig = (splitPanelComponent as any).componentConfig || {};
|
||||
const panelConfig = currentConfig[panelKey] || {};
|
||||
@@ -6807,17 +6816,37 @@ export default function ScreenDesigner({
|
||||
},
|
||||
};
|
||||
|
||||
// selectedPanelComponentInfo 업데이트
|
||||
setSelectedPanelComponentInfo((prev) =>
|
||||
prev ? { ...prev, component: updatedComp } : null,
|
||||
);
|
||||
|
||||
return {
|
||||
...prevLayout,
|
||||
components: prevLayout.components.map((c) =>
|
||||
c.id === splitPanelId ? updatedComponent : c,
|
||||
),
|
||||
// 중첩 구조 반영
|
||||
const applyUpdatedSplitPanel = (layout: any, updated: any, info: any) => {
|
||||
if (info.path === "top") {
|
||||
return { ...layout, components: layout.components.map((c: any) => c.id === splitPanelId ? updated : c) };
|
||||
}
|
||||
return {
|
||||
...layout,
|
||||
components: layout.components.map((c: any) => {
|
||||
if (c.id !== info.parentTabId) return c;
|
||||
const cfgKey = c.componentConfig?.tabs ? "componentConfig" : "overrides";
|
||||
const cfg = c[cfgKey] || {};
|
||||
return {
|
||||
...c,
|
||||
[cfgKey]: {
|
||||
...cfg,
|
||||
tabs: (cfg.tabs || []).map((t: any) =>
|
||||
t.id === info.parentTabTabId
|
||||
? { ...t, components: (t.components || []).map((tc: any) => tc.id === splitPanelId ? updated : tc) }
|
||||
: t,
|
||||
),
|
||||
},
|
||||
};
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
return applyUpdatedSplitPanel(prevLayout, updatedComponent, result);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -6827,8 +6856,23 @@ export default function ScreenDesigner({
|
||||
const panelKey = panelSide === "left" ? "leftPanel" : "rightPanel";
|
||||
|
||||
setLayout((prevLayout) => {
|
||||
const splitPanelComponent = prevLayout.components.find((c) => c.id === splitPanelId);
|
||||
if (!splitPanelComponent) return prevLayout;
|
||||
const findResult = (() => {
|
||||
const direct = prevLayout.components.find((c: any) => c.id === splitPanelId);
|
||||
if (direct) return { found: direct, path: "top" as const };
|
||||
for (const comp of prevLayout.components) {
|
||||
const ct = (comp as any)?.componentType || (comp as any)?.overrides?.type;
|
||||
const cfg = (comp as any)?.componentConfig || (comp as any)?.overrides || {};
|
||||
if (ct === "tabs-widget" || ct === "v2-tabs-widget") {
|
||||
for (const tab of (cfg.tabs || [])) {
|
||||
const nested = (tab.components || []).find((c: any) => c.id === splitPanelId);
|
||||
if (nested) return { found: nested, path: "nested" as const, parentTabId: comp.id, parentTabTabId: tab.id };
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
})();
|
||||
if (!findResult) return prevLayout;
|
||||
const splitPanelComponent = findResult.found;
|
||||
|
||||
const currentConfig = (splitPanelComponent as any).componentConfig || {};
|
||||
const panelConfig = currentConfig[panelKey] || {};
|
||||
@@ -6849,11 +6893,27 @@ export default function ScreenDesigner({
|
||||
|
||||
setSelectedPanelComponentInfo(null);
|
||||
|
||||
if (findResult.path === "top") {
|
||||
return { ...prevLayout, components: prevLayout.components.map((c: any) => c.id === splitPanelId ? updatedComponent : c) };
|
||||
}
|
||||
return {
|
||||
...prevLayout,
|
||||
components: prevLayout.components.map((c) =>
|
||||
c.id === splitPanelId ? updatedComponent : c,
|
||||
),
|
||||
components: prevLayout.components.map((c: any) => {
|
||||
if (c.id !== findResult.parentTabId) return c;
|
||||
const cfgKey = c.componentConfig?.tabs ? "componentConfig" : "overrides";
|
||||
const cfg = c[cfgKey] || {};
|
||||
return {
|
||||
...c,
|
||||
[cfgKey]: {
|
||||
...cfg,
|
||||
tabs: (cfg.tabs || []).map((t: any) =>
|
||||
t.id === findResult.parentTabTabId
|
||||
? { ...t, components: (t.components || []).map((tc: any) => tc.id === splitPanelId ? updatedComponent : tc) }
|
||||
: t,
|
||||
),
|
||||
},
|
||||
};
|
||||
}),
|
||||
};
|
||||
});
|
||||
};
|
||||
@@ -7457,6 +7517,7 @@ export default function ScreenDesigner({
|
||||
onSelectPanelComponent={(panelSide, compId, comp) =>
|
||||
handleSelectPanelComponent(component.id, panelSide, compId, comp)
|
||||
}
|
||||
onNestedPanelSelect={handleSelectPanelComponent}
|
||||
selectedPanelComponentId={
|
||||
selectedPanelComponentInfo?.splitPanelId === component.id
|
||||
? selectedPanelComponentInfo.componentId
|
||||
|
||||
Reference in New Issue
Block a user