Skip to content

Commit f82d56c

Browse files
authored
Merge pull request #52 from dotoritos-kim/feat/plugin-settings-conditional-visibility
feat: 플러그인 설정 스키마에 조건부 표시(visible) 지원
2 parents c0aabbf + 9a42ccd commit f82d56c

File tree

4 files changed

+69
-6
lines changed

4 files changed

+69
-6
lines changed

src/renderer/components/main/Grid/PropertiesPanel.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1983,6 +1983,16 @@ const PropertiesPanel: React.FC<PropertiesPanelProps> = ({
19831983
const wrap = options?.wrap !== false;
19841984
const rows = Object.entries(schema).map(([key, setting]) => {
19851985
const schemaValue = setting as PluginSettingSchema;
1986+
1987+
// ── 조건부 visibility ──
1988+
if (schemaValue.visible !== undefined) {
1989+
const vis =
1990+
typeof schemaValue.visible === "function"
1991+
? schemaValue.visible(values)
1992+
: schemaValue.visible;
1993+
if (!vis) return null;
1994+
}
1995+
19861996
if (schemaValue.type === "divider") {
19871997
return <SectionDivider key={`divider-${key}`} />;
19881998
}
@@ -2099,11 +2109,13 @@ const PropertiesPanel: React.FC<PropertiesPanelProps> = ({
20992109
);
21002110
});
21012111

2112+
const filtered = rows.filter(Boolean);
2113+
21022114
if (!wrap) {
2103-
return <>{rows}</>;
2115+
return <>{filtered}</>;
21042116
}
21052117

2106-
return <div className="flex flex-col gap-[12px]">{rows}</div>;
2118+
return <div className="flex flex-col gap-[12px]">{filtered}</div>;
21072119
},
21082120
[locale, panelElement, t],
21092121
);

src/renderer/plugins/runtime/api/defineElement.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,10 +241,31 @@ export const createDefineElement = (deps: DefineElementDependencies) => {
241241
let htmlContent =
242242
'<div class="flex flex-col gap-[19px] w-full text-left">';
243243

244+
const _evalVisible = (
245+
visible: boolean | ((settings: Record<string, any>) => boolean) | undefined,
246+
settings: Record<string, any>,
247+
): boolean => {
248+
if (visible === undefined) return true;
249+
return typeof visible === "function" ? visible(settings) : visible;
250+
};
251+
252+
const _updateVisibility = () => {
253+
if (!definition.settings) return;
254+
for (const [k, s] of Object.entries(definition.settings)) {
255+
if (s.visible === undefined) continue;
256+
const el = document.querySelector(
257+
`[data-setting-key="${k}"]`,
258+
) as HTMLElement | null;
259+
if (el)
260+
el.style.display = _evalVisible(s.visible, currentSettings) ? "" : "none";
261+
}
262+
};
263+
244264
if (definition.settings) {
245265
for (const [key, schema] of Object.entries(definition.settings)) {
266+
const _vis = _evalVisible(schema.visible, currentSettings);
246267
if (schema.type === "divider") {
247-
htmlContent += `<div class="w-full h-[1px] bg-[#3A3943]"></div>`;
268+
htmlContent += `<div data-setting-key="${key}" style="${_vis ? "" : "display:none"}" class="w-full h-[1px] bg-[#3A3943]"></div>`;
248269
} else {
249270
const value =
250271
currentSettings[key] !== undefined
@@ -264,6 +285,7 @@ export const createDefineElement = (deps: DefineElementDependencies) => {
264285
window.api.ui.displayElement.update(instanceId, {
265286
settings: newSettings,
266287
});
288+
_updateVisibility();
267289
};
268290

269291
const wrappedChange = wrapFunctionWithContext(handleChange);
@@ -366,7 +388,7 @@ export const createDefineElement = (deps: DefineElementDependencies) => {
366388
}
367389

368390
htmlContent += `
369-
<div class="flex justify-between w-full items-center">
391+
<div data-setting-key="${key}" style="${_vis ? "" : "display:none"}" class="flex justify-between w-full items-center">
370392
<p class="text-white text-style-2">${labelText}</p>
371393
${componentHtml}
372394
</div>

src/renderer/plugins/runtime/api/defineSettings.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,13 +156,35 @@ export const createDefineSettings = (deps: DefineSettingsDependencies) => {
156156
notifyOverlay(currentSettings);
157157
};
158158

159+
// ── 조건부 visibility 헬퍼 ──
160+
const _evalVisible = (
161+
visible: boolean | ((settings: Record<string, any>) => boolean) | undefined,
162+
settings: Record<string, any>,
163+
): boolean => {
164+
if (visible === undefined) return true;
165+
return typeof visible === "function" ? visible(settings) : visible;
166+
};
167+
168+
const _updateVisibility = () => {
169+
if (!definition.settings) return;
170+
for (const [k, s] of Object.entries(definition.settings)) {
171+
if (s.visible === undefined) continue;
172+
const el = document.querySelector(
173+
`[data-setting-key="${k}"]`,
174+
) as HTMLElement | null;
175+
if (el)
176+
el.style.display = _evalVisible(s.visible, dialogSettings) ? "" : "none";
177+
}
178+
};
179+
159180
let htmlContent =
160181
'<div class="flex flex-col gap-[19px] w-full text-left">';
161182

162183
if (definition.settings && Object.keys(definition.settings).length > 0) {
163184
for (const [key, schema] of Object.entries(definition.settings)) {
185+
const _vis = _evalVisible(schema.visible, dialogSettings);
164186
if (schema.type === "divider") {
165-
htmlContent += `<div class="w-full h-[1px] bg-[#3A3943]"></div>`;
187+
htmlContent += `<div data-setting-key="${key}" style="${_vis ? "" : "display:none"}" class="w-full h-[1px] bg-[#3A3943]"></div>`;
166188
} else {
167189
const value =
168190
dialogSettings[key] !== undefined
@@ -183,6 +205,7 @@ export const createDefineSettings = (deps: DefineSettingsDependencies) => {
183205
dialogSettings[key] = newValue;
184206
// 실시간 미리보기 적용
185207
applyPreview(dialogSettings);
208+
_updateVisibility();
186209
} finally {
187210
(window as any).__dmn_current_plugin_id = prev;
188211
}
@@ -289,7 +312,7 @@ export const createDefineSettings = (deps: DefineSettingsDependencies) => {
289312
}
290313

291314
htmlContent += `
292-
<div class="flex justify-between w-full items-center">
315+
<div data-setting-key="${key}" style="${_vis ? "" : "display:none"}" class="flex justify-between w-full items-center">
293316
<p class="text-white text-style-2">${labelText}</p>
294317
${componentHtml}
295318
</div>

src/types/api.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,9 @@ export type PluginSettingSchema =
405405
| {
406406
type: "divider";
407407
label?: string;
408+
visible?:
409+
| boolean
410+
| ((settings: Record<string, any>) => boolean);
408411
}
409412
| {
410413
type: Exclude<PluginSettingType, "divider">;
@@ -415,6 +418,9 @@ export type PluginSettingSchema =
415418
step?: number; // for number
416419
options?: { label: string; value: any }[]; // for select
417420
placeholder?: string; // for string/number
421+
visible?:
422+
| boolean
423+
| ((settings: Record<string, any>) => boolean);
418424
};
419425

420426
export interface PluginDefinitionHookContext {

0 commit comments

Comments
 (0)