126 lines
3.9 KiB
TypeScript
126 lines
3.9 KiB
TypeScript
import type { GlassMaterialSettings, NodedcTheme } from "@nodedc/ui-core";
|
|
import type { ToolbarPlacement } from "@nodedc/ui-react";
|
|
import type { FaviconAssetUrls } from "./favicon.js";
|
|
import type { MapPageLayout, MapPageSettings } from "./MapFixturePreview.js";
|
|
import type { MapPresentationProfile } from "./mapPresentationProfile.js";
|
|
|
|
export type MaterialDraft = {
|
|
panelHex: string;
|
|
panelOpacity: number;
|
|
fieldHex: string;
|
|
fieldOpacity: number;
|
|
nestedHex: string;
|
|
};
|
|
|
|
export type MapDesignProfileFragment = {
|
|
schemaVersion: 1;
|
|
templateId: "map";
|
|
templateVersion: string;
|
|
settings: MapPageSettings;
|
|
presentationProfiles: MapPresentationProfile[];
|
|
};
|
|
|
|
export type DesignProfilePageFragment = MapDesignProfileFragment;
|
|
|
|
export interface StoredLayout {
|
|
theme?: NodedcTheme;
|
|
accentHex?: string;
|
|
materialByTheme?: Record<NodedcTheme, MaterialDraft>;
|
|
environment?: {
|
|
lightColor?: string;
|
|
brightness?: number;
|
|
glowDistance?: number;
|
|
connectionType?: string;
|
|
connectionColor?: string;
|
|
usePortColors?: boolean;
|
|
fillColor?: string;
|
|
fillOpacity?: number;
|
|
strokeColor?: string;
|
|
strokeOpacity?: number;
|
|
};
|
|
media?: {
|
|
source?: "file" | "url";
|
|
url?: string;
|
|
fileName?: string;
|
|
fileSrc?: string;
|
|
visible?: boolean;
|
|
logoSource?: "file" | "url";
|
|
logoUrl?: string;
|
|
logoFileName?: string;
|
|
logoFileSrc?: string;
|
|
faviconFileName?: string;
|
|
faviconAssets?: FaviconAssetUrls;
|
|
};
|
|
glass?: GlassMaterialSettings;
|
|
toolbar?: {
|
|
placement?: ToolbarPlacement;
|
|
background?: string;
|
|
border?: string;
|
|
outline?: string;
|
|
minSize?: number;
|
|
maxSize?: number;
|
|
lensCount?: number;
|
|
autoHide?: boolean;
|
|
};
|
|
/** Design fragments are keyed by a registered Page Library type/version. */
|
|
pageTypes?: Record<string, DesignProfilePageFragment>;
|
|
}
|
|
|
|
export type MapDesignOverrides = {
|
|
settings?: Partial<MapPageSettings>;
|
|
presentationProfiles?: MapPresentationProfile[];
|
|
};
|
|
|
|
export const mapDesignProfileKey = (templateVersion: string) => `map@${templateVersion}`;
|
|
|
|
export function mapDesignFragmentFromLayout(layout: MapPageLayout, templateVersion: string): MapDesignProfileFragment {
|
|
return {
|
|
schemaVersion: 1,
|
|
templateId: "map",
|
|
templateVersion,
|
|
settings: structuredClone(layout.settings),
|
|
presentationProfiles: structuredClone(layout.presentationProfiles),
|
|
};
|
|
}
|
|
|
|
export function mapDesignFragmentForLayout(layout: StoredLayout | null | undefined, templateVersion: string) {
|
|
const fragment = layout?.pageTypes?.[mapDesignProfileKey(templateVersion)];
|
|
return fragment?.templateId === "map" ? fragment : null;
|
|
}
|
|
|
|
export function resolveMapDesignLayout(
|
|
base: MapPageLayout | null | undefined,
|
|
fragment: MapDesignProfileFragment | null | undefined,
|
|
overrides?: MapDesignOverrides,
|
|
) {
|
|
if (!base) return null;
|
|
if (!fragment) return base;
|
|
return {
|
|
...base,
|
|
settings: {
|
|
...base.settings,
|
|
...fragment.settings,
|
|
...overrides?.settings,
|
|
},
|
|
presentationProfiles: structuredClone(overrides?.presentationProfiles ?? fragment.presentationProfiles),
|
|
} satisfies MapPageLayout;
|
|
}
|
|
|
|
export function mapDesignOverridesFromResolved(
|
|
resolved: MapPageLayout,
|
|
fragment: MapDesignProfileFragment | null | undefined,
|
|
): MapDesignOverrides | undefined {
|
|
if (!fragment) return undefined;
|
|
const settings = Object.fromEntries(Object.entries(resolved.settings).filter(([key, value]) => (
|
|
fragment.settings[key as keyof MapPageSettings] !== value
|
|
))) as Partial<MapPageSettings>;
|
|
const presentationProfiles = JSON.stringify(resolved.presentationProfiles) === JSON.stringify(fragment.presentationProfiles)
|
|
? undefined
|
|
: structuredClone(resolved.presentationProfiles);
|
|
if (Object.keys(settings).length === 0 && !presentationProfiles) return undefined;
|
|
return {
|
|
...(Object.keys(settings).length > 0 ? { settings } : {}),
|
|
...(presentationProfiles ? { presentationProfiles } : {}),
|
|
};
|
|
}
|