diff --git a/src/lib/components/tree/ConfigTree.ts b/src/lib/components/tree/ConfigTree.ts index f9e1d87..0693b82 100644 --- a/src/lib/components/tree/ConfigTree.ts +++ b/src/lib/components/tree/ConfigTree.ts @@ -18,6 +18,7 @@ import { } from "./TreeNode.svelte"; import { v4 as uuidv4 } from "uuid"; import { ElementType, grid, ModuleType } from "@intechstudio/grid-protocol"; +import { isModuleTypeCompatible } from "../../utils"; export namespace Tree { export interface Options { @@ -98,33 +99,29 @@ export namespace Tree { } function isCompatible(config: Config, types: string[]) { - if (config.type === ModuleType.VSN1L || config.type === ModuleType.VSN1R) { - return ( - types.includes(ModuleType.VSN1L) || types.includes(ModuleType.VSN1R) - ); - } else { - switch (config.configType) { - case "profile": { - const moduleTypes = types.filter((t): t is ModuleType => - isModuleType(t), - ); - return moduleTypes.includes(config.type as ModuleType); - } - case "preset": { - const elementTypes = types.filter((t): t is ElementType => - isElementType(t), - ); - const leftCompatible = elementTypes.some((e) => - grid.is_element_compatible_with(e, config.type as ElementType), - ); - const rightCompatible = elementTypes.some((e) => - grid.is_element_compatible_with(config.type as ElementType, e), - ); - return leftCompatible || rightCompatible; - } - case "snippet": { - return true; - } + switch (config.configType) { + case "profile": { + const moduleTypes = types.filter((t): t is ModuleType => + isModuleType(t), + ); + return moduleTypes.some((t) => + isModuleTypeCompatible(config.type as ModuleType, t), + ); + } + case "preset": { + const elementTypes = types.filter((t): t is ElementType => + isElementType(t), + ); + const leftCompatible = elementTypes.some((e) => + grid.is_element_compatible_with(e, config.type as ElementType), + ); + const rightCompatible = elementTypes.some((e) => + grid.is_element_compatible_with(config.type as ElementType, e), + ); + return leftCompatible || rightCompatible; + } + case "snippet": { + return true; } } } diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 06fc244..13d4a42 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -1,9 +1,25 @@ import type { EditorReturnType } from "./types"; +import { ModuleType } from "@intechstudio/grid-protocol"; export function applyFocus(el: HTMLElement) { el.focus(); } +/** + * Module-type-level compatibility, e.g. for profile overwrite/load and the + * config tree's module grouping. VSN1L and VSN1R share a profile format and + * are treated as interchangeable; every other module type must match exactly. + * Not for element/preset compatibility - use grid.is_element_compatible_with + * for that, since a module match doesn't imply per-element event support. + */ +export function isModuleTypeCompatible(a: ModuleType, b: ModuleType): boolean { + const vsn1Modules = [ModuleType.VSN1L, ModuleType.VSN1R]; + if (vsn1Modules.includes(a)) { + return vsn1Modules.includes(b); + } + return a === b; +} + export async function parentIframeCommunication({ windowPostMessageName, dataForParent, diff --git a/src/routes/EditorLayout.svelte b/src/routes/EditorLayout.svelte index bc3eda3..64ce86a 100644 --- a/src/routes/EditorLayout.svelte +++ b/src/routes/EditorLayout.svelte @@ -25,7 +25,10 @@ } from "../lib/schemas"; import { fade } from "svelte/transition"; import { Toggle } from "@intechstudio/grid-uikit"; - import { parentIframeCommunication } from "../lib/utils"; + import { + parentIframeCommunication, + isModuleTypeCompatible, + } from "../lib/utils"; import { createConfigManager, updateLocalConfigs, @@ -261,7 +264,12 @@ files: editorConfig?.files, }; - if (newConfig.type !== config.type) { + if ( + !isModuleTypeCompatible( + newConfig.type as ModuleType, + config.type as ModuleType, + ) + ) { parentIframeCommunication({ windowPostMessageName: "sendLogMessage", dataForParent: {