feat(ui): theme 契约(类型+默认值+合并+Provider)
子游戏只写要改的字段, 缺省集中在 DEFAULT_THEME 一处(spec §4.3, 第二准则的唯一例外)。ThemeProvider 未 init 即读抛错, 不兜底。 皮肤构建期定死, 故静态读取不做响应式。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
import type { ResolvedTheme } from './types.ts';
|
||||
|
||||
/**
|
||||
* 主题缺省值的**唯一来源**(spec §4.3)。
|
||||
* 这是 CLAUDE.md 第二准则明文列出的唯一例外——缺省集中在来源处,下游子游戏零兜底。
|
||||
* 不得以此为先例:协议数据缺失仍须显式暴露,不得 ?? 抹平。
|
||||
*/
|
||||
export const DEFAULT_THEME: ResolvedTheme = {
|
||||
colors: {
|
||||
primary: '#1E7A46',
|
||||
accent: '#F2B233',
|
||||
textPrimary: '#FFFFFF',
|
||||
textSecondary: '#C8D6CE',
|
||||
disabled: '#8A8A8A',
|
||||
warning: '#D94F3D',
|
||||
},
|
||||
fonts: {
|
||||
familyPath: null,
|
||||
sizeTitle: 32,
|
||||
sizeBody: 24,
|
||||
sizeCaption: 20,
|
||||
},
|
||||
layout: {
|
||||
myInfoAnchorX: 130,
|
||||
nicknameMaxChars: 8,
|
||||
infoNicknameMaxChars: 16,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "5f3f9c00-dd28-4c44-91c2-b747b751595c",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import type { ResolvedTheme, ThemeConfig } from './types.ts';
|
||||
import { DEFAULT_THEME } from './default-theme.ts';
|
||||
|
||||
/** 把子游戏的部分主题配置合并到默认主题上。分组独立合并,不改动 DEFAULT_THEME。 */
|
||||
export function resolveTheme(game: ThemeConfig = {}): ResolvedTheme {
|
||||
return {
|
||||
colors: { ...DEFAULT_THEME.colors, ...game.colors },
|
||||
fonts: { ...DEFAULT_THEME.fonts, ...game.fonts },
|
||||
layout: { ...DEFAULT_THEME.layout, ...game.layout },
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "86f0162e-5db7-47c9-9fe0-a31d1e9dd643",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { ResolvedTheme } from './types.ts';
|
||||
|
||||
let current: ResolvedTheme | null = null;
|
||||
|
||||
/**
|
||||
* 主题持有者。皮肤在构建期即定死,运行时不变,故为静态读取、**不做响应式**(spec §4.5)。
|
||||
* 子游戏在启动时调 init 注册自己的主题——框架不 import 子游戏(零耦合规则)。
|
||||
*/
|
||||
export const ThemeProvider = {
|
||||
init(theme: ResolvedTheme): void {
|
||||
current = theme;
|
||||
},
|
||||
get(): ResolvedTheme {
|
||||
if (!current) {
|
||||
throw new Error('ThemeProvider 未初始化:请在启动时调用 ThemeProvider.init(resolveTheme(theme))');
|
||||
}
|
||||
return current;
|
||||
},
|
||||
/** 仅供测试复位 */
|
||||
reset(): void {
|
||||
current = null;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "105e374f-7644-4114-9ced-5082cc129939",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* 主题契约。见 spec `2026-08-27-ui-asset-and-skin-design.md` §4。
|
||||
* 字段集不预先穷举——随框架 UI 抽象逐项浮现;加字段非破坏性,删字段/改语义为 breaking change。
|
||||
*/
|
||||
export interface ThemeColors {
|
||||
primary: string;
|
||||
accent: string;
|
||||
textPrimary: string;
|
||||
textSecondary: string;
|
||||
disabled: string;
|
||||
warning: string;
|
||||
}
|
||||
|
||||
export interface ThemeFonts {
|
||||
/** 字体资源逻辑路径;null = 用引擎默认字体 */
|
||||
familyPath: string | null;
|
||||
sizeTitle: number;
|
||||
sizeBody: number;
|
||||
sizeCaption: number;
|
||||
}
|
||||
|
||||
export interface ThemeLayout {
|
||||
/** 自己信息的对齐点 x(旧 Game_Config.Info.myPosition) */
|
||||
myInfoAnchorX: number;
|
||||
/** 主界面昵称最大字符数(旧 Game_Config.Info.Mainnickname) */
|
||||
nicknameMaxChars: number;
|
||||
/** 个人信息页昵称最大字符数(旧 Game_Config.Info.Infonickname) */
|
||||
infoNicknameMaxChars: number;
|
||||
}
|
||||
|
||||
/** 子游戏声明用:各组均可只写要改的字段 */
|
||||
export interface ThemeConfig {
|
||||
colors?: Partial<ThemeColors>;
|
||||
fonts?: Partial<ThemeFonts>;
|
||||
layout?: Partial<ThemeLayout>;
|
||||
}
|
||||
|
||||
/** 合并后的完整主题,框架内部消费 */
|
||||
export interface ResolvedTheme {
|
||||
colors: ThemeColors;
|
||||
fonts: ThemeFonts;
|
||||
layout: ThemeLayout;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "3974f701-a0a3-4590-ba45-db688cf5a672",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
Reference in New Issue
Block a user