@robot-admin/layout 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/README.md +85 -25
- package/dist/core/index.cjs +1 -1
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.cts +214 -25
- package/dist/index.d.ts +214 -25
- package/dist/index.js +48 -6
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Add `createLayoutContext()` and `provideLayout()` to derive the complete reactive layout contract from a settings Store, menus, dark state, brand data, and an optional icon component.
|
|
8
|
+
- Keep the advanced `LayoutContext` API intact while formally deprecating the legacy `C_*Layout` aliases for removal in 4.0.
|
|
9
|
+
- Add browser interaction coverage for SettingsDrawer providers, atomic imports, reset rollback, host-owned cache clearing, and global visual-effect cleanup.
|
|
10
|
+
- Correct integration prerequisites, host-owned setting semantics, migration guidance, architecture diagrams, and stale version references without changing existing layout visuals or interactions.
|
|
11
|
+
|
|
3
12
|
## 3.0.0
|
|
4
13
|
|
|
5
14
|
### Major Changes
|
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/@robot-admin/layout)
|
|
6
6
|
[](https://github.com/ChenyCHENYU/robot-admin-packages/blob/main/LICENSE)
|
|
7
7
|
|
|
8
|
-
当前版本:`3.
|
|
8
|
+
当前版本:`3.1.0`。
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
- 🧩 **开箱即用** - 提供 SettingsDrawer 设置抽屉,覆盖外观 / 布局 / 功能配置
|
|
18
18
|
- 🧭 **菜单展开方式** - 内置传统展开 / 右侧面板两种菜单展开模式配置
|
|
19
19
|
- 🔌 **插槽系统** - 灵活的 slot 机制,主项目仅关注业务组件
|
|
20
|
+
- 🪄 **精简适配** - `provideLayout()` 从最小宿主输入自动创建完整响应式上下文
|
|
20
21
|
- 🎨 **CSS 变量同步** - 配置变更自动同步到 CSS 变量,样式实时响应
|
|
21
22
|
- ♿ **键盘与焦点可访问性** - 抽屉/菜单支持 Escape、方向键、焦点恢复与语义属性
|
|
22
23
|
- 🛡️ **安全设置导入** - 对枚举、布尔值、数值范围与主题色进行运行时校验
|
|
@@ -35,7 +36,7 @@
|
|
|
35
36
|
│ LayoutContext (provide/inject)
|
|
36
37
|
▼
|
|
37
38
|
┌──────────────────────────────────────┐
|
|
38
|
-
│ @robot-admin/layout
|
|
39
|
+
│ @robot-admin/layout(Vue + Naive UI)│
|
|
39
40
|
│ ├─ C_LayoutContainer (智能容器) │
|
|
40
41
|
│ │ └─ 根据 layoutMode 自动调度 │
|
|
41
42
|
│ ├─ layouts/ (6 种布局骨架) │
|
|
@@ -47,6 +48,12 @@
|
|
|
47
48
|
│ │ └─ CardLayout │
|
|
48
49
|
│ └─ SettingsDrawer (设置 UI) │
|
|
49
50
|
└──────────────────────────────────────┘
|
|
51
|
+
|
|
52
|
+
┌──────────────────────────────────────┐
|
|
53
|
+
│ @robot-admin/layout/core │
|
|
54
|
+
│ 设置协议、运行时校验、常量和纯函数 │
|
|
55
|
+
│ 不依赖 Vue / Pinia / UI 框架 │
|
|
56
|
+
└──────────────────────────────────────┘
|
|
50
57
|
```
|
|
51
58
|
|
|
52
59
|
---
|
|
@@ -57,6 +64,10 @@
|
|
|
57
64
|
src/
|
|
58
65
|
├── index.ts # 主入口(统一导出)
|
|
59
66
|
├── setup.ts # 一键初始化 setupLayout()
|
|
67
|
+
├── core/ # 无框架设置协议、校验与纯函数
|
|
68
|
+
│ ├── index.ts
|
|
69
|
+
│ ├── settings.ts
|
|
70
|
+
│ └── types.ts
|
|
60
71
|
├── components/
|
|
61
72
|
│ ├── C_LayoutContainer/ # 智能布局容器(主入口组件)
|
|
62
73
|
│ │ └── index.vue
|
|
@@ -91,6 +102,7 @@ src/
|
|
|
91
102
|
│ └── MenuTrigger/ # 菜单触发区域
|
|
92
103
|
├── composables/
|
|
93
104
|
│ ├── useLayoutContext.ts # LayoutContext provide/inject
|
|
105
|
+
│ ├── createLayoutContext.ts # 最小宿主输入适配助手
|
|
94
106
|
│ ├── useLayoutCache.ts # 页面缓存管理
|
|
95
107
|
│ └── useMenuSplit.ts # 菜单拆分(一级/二级分离)
|
|
96
108
|
├── stores/
|
|
@@ -147,10 +159,9 @@ setupLayout(app, {
|
|
|
147
159
|
app.mount("#app");
|
|
148
160
|
```
|
|
149
161
|
|
|
150
|
-
### 2.
|
|
162
|
+
### 2. 提供宿主数据并使用布局容器
|
|
151
163
|
|
|
152
164
|
```vue
|
|
153
|
-
<!-- src/components/C_Layout/index.vue -->
|
|
154
165
|
<template>
|
|
155
166
|
<C_LayoutContainer>
|
|
156
167
|
<template #logo><AppLogo /></template>
|
|
@@ -164,15 +175,36 @@ app.mount("#app");
|
|
|
164
175
|
</template>
|
|
165
176
|
|
|
166
177
|
<script setup lang="ts">
|
|
167
|
-
import {
|
|
178
|
+
import {
|
|
179
|
+
C_LayoutContainer,
|
|
180
|
+
provideLayout,
|
|
181
|
+
useSettingsStore,
|
|
182
|
+
type MenuOptions,
|
|
183
|
+
} from "@robot-admin/layout";
|
|
184
|
+
|
|
185
|
+
const props = defineProps<{
|
|
186
|
+
menus: MenuOptions[];
|
|
187
|
+
isDark: boolean;
|
|
188
|
+
}>();
|
|
189
|
+
|
|
190
|
+
provideLayout({
|
|
191
|
+
settings: useSettingsStore(),
|
|
192
|
+
menus: () => props.menus,
|
|
193
|
+
isDark: () => props.isDark,
|
|
194
|
+
brand: { name: "My Admin", homePath: "/home" },
|
|
195
|
+
});
|
|
168
196
|
</script>
|
|
169
197
|
```
|
|
170
198
|
|
|
199
|
+
`provideLayout()` 会自动桥接布局模式、折叠状态、尺寸、动画和显示开关。只有需要完全
|
|
200
|
+
自定义响应式来源时,才直接构造 `LayoutContext` 并调用 `provideLayoutContext()`。
|
|
201
|
+
|
|
171
202
|
### 3. 添加设置抽屉
|
|
172
203
|
|
|
173
204
|
```vue
|
|
174
205
|
<script setup lang="ts">
|
|
175
206
|
import { ref } from "vue";
|
|
207
|
+
import { NDialogProvider, NMessageProvider } from "naive-ui";
|
|
176
208
|
import { SettingsDrawer } from "@robot-admin/layout";
|
|
177
209
|
|
|
178
210
|
const visible = ref(false);
|
|
@@ -183,14 +215,21 @@ const settingsActions = {
|
|
|
183
215
|
|
|
184
216
|
<template>
|
|
185
217
|
<button @click="visible = true">⚙️ 设置</button>
|
|
186
|
-
<
|
|
187
|
-
<
|
|
188
|
-
<
|
|
189
|
-
|
|
190
|
-
|
|
218
|
+
<NDialogProvider>
|
|
219
|
+
<NMessageProvider>
|
|
220
|
+
<SettingsDrawer v-model:show="visible" :actions="settingsActions">
|
|
221
|
+
<template #appearance-prepend>
|
|
222
|
+
<AppThemeExtension />
|
|
223
|
+
</template>
|
|
224
|
+
</SettingsDrawer>
|
|
225
|
+
</NMessageProvider>
|
|
226
|
+
</NDialogProvider>
|
|
191
227
|
</template>
|
|
192
228
|
```
|
|
193
229
|
|
|
230
|
+
`SettingsDrawer` 使用 Naive UI 的 Message/Dialog API,因此必须位于
|
|
231
|
+
`NMessageProvider` 和 `NDialogProvider` 下;应用根部已有 Provider 时无需重复包裹。
|
|
232
|
+
|
|
194
233
|
`SettingsDrawer` 不再自行清空 `localStorage` / `sessionStorage`。缓存清理由宿主通过
|
|
195
234
|
`actions.clearCache` 明确实现,避免误删登录态、语言和业务数据。可用扩展插槽:
|
|
196
235
|
`appearance-prepend/append`、`layout-prepend/after-mode/append`、
|
|
@@ -249,21 +288,31 @@ settings.resetSettings();
|
|
|
249
288
|
|
|
250
289
|
### 设置属性一览
|
|
251
290
|
|
|
252
|
-
| 属性 |
|
|
253
|
-
| ----------------------- |
|
|
254
|
-
| `themeMode` | `
|
|
255
|
-
| `primaryColor` | `
|
|
256
|
-
| `
|
|
257
|
-
| `
|
|
258
|
-
| `
|
|
259
|
-
| `
|
|
260
|
-
| `
|
|
261
|
-
| `
|
|
262
|
-
| `
|
|
263
|
-
| `
|
|
264
|
-
| `
|
|
265
|
-
| `
|
|
266
|
-
| `
|
|
291
|
+
| 属性 | 默认值 | 作用方 | 说明 |
|
|
292
|
+
| ----------------------- | ----------- | ----------- | ---------------------------- |
|
|
293
|
+
| `themeMode` | `'light'` | 宿主回调 | 标准主题模式 |
|
|
294
|
+
| `primaryColor` | `'#409eff'` | 包内 | 主题色与派生 CSS 变量 |
|
|
295
|
+
| `borderRadius` | `'medium'` | 包内 | 圆角 CSS 变量 |
|
|
296
|
+
| `transitionType` | `'slide'` | 包内 | 页面动画类型 |
|
|
297
|
+
| `enableTransition` | `true` | 包内 | 是否启用页面动画 |
|
|
298
|
+
| `layoutMode` | `'side'` | 包内 | 当前布局模式 |
|
|
299
|
+
| `menuExpandMode` | `'inline'` | 宿主菜单 | 菜单展开方式 |
|
|
300
|
+
| `collapsed` | `false` | 包内/宿主 | 共享侧栏折叠状态 |
|
|
301
|
+
| `fixedHeader` | `true` | 宿主头部 | 固定头部策略 |
|
|
302
|
+
| `showBreadcrumb` | `true` | 宿主头部 | 显示面包屑 |
|
|
303
|
+
| `showBreadcrumbIcon` | `true` | 宿主头部 | 显示面包屑图标 |
|
|
304
|
+
| `showTagsView` | `true` | 包内 | 显示标签页 |
|
|
305
|
+
| `tagsViewHeight` | `44` | 包内 | 标签页高度 (px) |
|
|
306
|
+
| `tagsViewStyle` | `'default'` | 宿主标签页 | 标签页风格 |
|
|
307
|
+
| `showFooter` | `true` | 包内 | 显示页脚 |
|
|
308
|
+
| `sidebarWidth` | `220` | 包内 | 侧边栏宽度 (px) |
|
|
309
|
+
| `sidebarCollapsedWidth` | `64` | 包内 | 折叠宽度 (px) |
|
|
310
|
+
| `headerHeight` | `56` | 包内/宿主 | 头部高度 (px) |
|
|
311
|
+
| `enableHotkeys` | `true` | 宿主扩展 | 是否启用宿主快捷键 |
|
|
312
|
+
| `version` | `'3.1.0'` | 配置元数据 | 当前默认配置来源版本 |
|
|
313
|
+
|
|
314
|
+
“宿主”字段由 Store 和导入导出协议统一维护,但布局包不会越权修改宿主业务组件;这种边界
|
|
315
|
+
避免重复实现面包屑、快捷键和标签页等业务能力。
|
|
267
316
|
|
|
268
317
|
### CSS 变量
|
|
269
318
|
|
|
@@ -369,6 +418,14 @@ settings.$patch(safePatch);
|
|
|
369
418
|
`useLayoutCache()` 默认不会输出开发日志,也不会向 `window` 暴露调试函数;仅在
|
|
370
419
|
受控的本地开发场景显式设置 `enableDevLog` / `exposeToWindow`。
|
|
371
420
|
|
|
421
|
+
### 3.1 升级说明
|
|
422
|
+
|
|
423
|
+
- 新增 `createLayoutContext()` 与 `provideLayout()`,用于精简普通项目的上下文桥接代码。
|
|
424
|
+
- 原有 `LayoutContext`、`provideLayoutContext()` 和所有组件/插槽继续兼容。
|
|
425
|
+
- `C_SideLayout` 等旧别名已正式标记为废弃,3.x 仍保留,计划在 4.0 移除;请改用
|
|
426
|
+
`SideLayout`、`TopLayout`、`MixLayout`、`MixTopLayout`、
|
|
427
|
+
`ReverseHorizontalMixLayout`、`CardLayout`。
|
|
428
|
+
|
|
372
429
|
### 3.0 升级说明
|
|
373
430
|
|
|
374
431
|
- 现有根入口、6 种布局、组件名、slot 名和 CSS 入口保持兼容。
|
|
@@ -378,6 +435,9 @@ settings.$patch(safePatch);
|
|
|
378
435
|
- 缓存清理改为宿主白名单动作;从 2.x 升级时请传入 `actions.clearCache`。
|
|
379
436
|
- `@robot-admin/theme` 不再是 peer dependency;需要主题联动时使用 `onThemeModeChange`。
|
|
380
437
|
|
|
438
|
+
多 Store 实例可以拥有独立状态,但默认 CSS 变量和设置抽屉的灰度、色弱、水印属于页面级
|
|
439
|
+
视觉效果;同一页面应由一个布局宿主统一管理,避免多个应用同时争用 `document` 根节点。
|
|
440
|
+
|
|
381
441
|
### 单独使用布局骨架
|
|
382
442
|
|
|
383
443
|
```typescript
|
package/dist/core/index.cjs
CHANGED
|
@@ -290,7 +290,7 @@ var DEFAULT_SETTINGS = {
|
|
|
290
290
|
headerHeight: 56,
|
|
291
291
|
// 高级
|
|
292
292
|
enableHotkeys: true,
|
|
293
|
-
version: "3.
|
|
293
|
+
version: "3.1.0"
|
|
294
294
|
};
|
|
295
295
|
var COLOR_SWATCHES = PRESET_COLORS.map((c) => c.value);
|
|
296
296
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/core/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/index.ts","../../src/core/settings.ts","../../src/constants/index.ts"],"sourcesContent":["export {\n adjustColor,\n sanitizeLayoutSettingsConfig,\n sanitizeSettingsPatch,\n SETTINGS_CONFIG_SCHEMA_VERSION,\n} from \"./settings\";\nexport type { LayoutSettingsConfig, LayoutVisualEffects } from \"./settings\";\n\nexport {\n BORDER_RADIUS_MAP,\n COLOR_SWATCHES,\n DEFAULT_SETTINGS,\n LAYOUT_MODES,\n PRESET_COLORS,\n THEME_PRESETS,\n TRANSITION_MAP,\n} from \"../constants\";\n\nexport type {\n BorderRadiusSize,\n LayoutInfo,\n LayoutMode,\n MenuExpandMode,\n PresetColor,\n SettingsDrawerActions,\n SettingsState,\n SettingsStoreOptions,\n TagsViewStyle,\n ThemeMode,\n ThemePreset,\n TransitionType,\n} from \"./types\";\n","import type { SettingsState } from \"./types\";\n\nconst ENUM_SETTINGS = {\n themeMode: new Set([\"light\", \"dark\", \"system\"]),\n borderRadius: new Set([\"small\", \"medium\", \"large\"]),\n transitionType: new Set([\"fade\", \"slide\", \"zoom\", \"none\"]),\n layoutMode: new Set([\n \"side\",\n \"top\",\n \"mix\",\n \"mix-top\",\n \"reverse-horizontal-mix\",\n \"card-layout\",\n ]),\n menuExpandMode: new Set([\"inline\", \"panel\"]),\n tagsViewStyle: new Set([\"default\", \"card\", \"smart\"]),\n} as const;\n\nconst BOOLEAN_SETTINGS: ReadonlySet<keyof SettingsState> = new Set([\n \"enableTransition\",\n \"collapsed\",\n \"fixedHeader\",\n \"showBreadcrumb\",\n \"showBreadcrumbIcon\",\n \"showTagsView\",\n \"showFooter\",\n \"enableHotkeys\",\n]);\n\nconst NUMBER_RANGES: Partial<\n Record<keyof SettingsState, readonly [number, number]>\n> = {\n tagsViewHeight: [24, 100],\n sidebarWidth: [120, 480],\n sidebarCollapsedWidth: [32, 160],\n headerHeight: [32, 160],\n};\n\n/** 当前导入导出配置格式版本。 */\nexport const SETTINGS_CONFIG_SCHEMA_VERSION = 1 as const;\n\nexport interface LayoutVisualEffects {\n gray?: boolean;\n colorWeak?: boolean;\n watermark?: {\n enabled: boolean;\n text: string;\n };\n}\n\n/** 经校验后可原子应用的布局配置。 */\nexport interface LayoutSettingsConfig extends LayoutVisualEffects {\n schemaVersion?: number;\n settings?: Partial<SettingsState>;\n}\n\n/**\n * 校验来自配置文件等不可信来源的设置。\n * 未知键为向前兼容而忽略;已知键的非法值会让整次导入失败。\n */\nexport function sanitizeSettingsPatch(input: unknown): Partial<SettingsState> {\n if (!input || typeof input !== \"object\" || Array.isArray(input)) {\n throw new TypeError(\"settings 必须是对象\");\n }\n\n const source = input as Record<string, unknown>;\n const result: Partial<SettingsState> = {};\n const assign = (key: keyof SettingsState, value: unknown) => {\n (result as Record<string, unknown>)[key] = value;\n };\n\n for (const [key, allowed] of Object.entries(ENUM_SETTINGS)) {\n const value = source[key];\n if (value === undefined) continue;\n if (typeof value !== \"string\" || !allowed.has(value as never)) {\n throw new RangeError(`无效的设置项 ${key}: ${String(value)}`);\n }\n assign(key as keyof SettingsState, value);\n }\n\n for (const key of BOOLEAN_SETTINGS) {\n const value = source[key];\n if (value === undefined) continue;\n if (typeof value !== \"boolean\") {\n throw new TypeError(`设置项 ${key} 必须是布尔值`);\n }\n assign(key, value);\n }\n\n for (const [key, range] of Object.entries(NUMBER_RANGES)) {\n const value = source[key];\n if (value === undefined) continue;\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value) ||\n value < range[0] ||\n value > range[1]\n ) {\n throw new RangeError(`设置项 ${key} 超出允许范围`);\n }\n assign(key as keyof SettingsState, value);\n }\n\n if (source.primaryColor !== undefined) {\n if (\n typeof source.primaryColor !== \"string\" ||\n !/^#[0-9a-fA-F]{6}$/.test(source.primaryColor)\n ) {\n throw new RangeError(\"primaryColor 必须是 #rrggbb 格式\");\n }\n result.primaryColor = source.primaryColor;\n }\n\n if (source.version !== undefined) {\n if (typeof source.version !== \"string\" || source.version.length > 50) {\n throw new TypeError(\"version 必须是长度不超过 50 的字符串\");\n }\n result.version = source.version;\n }\n\n return result;\n}\n\n/**\n * 一次性校验完整导入文件。此函数不修改任何响应式状态或浏览器 API,\n * 消费方可以在成功返回后再原子应用结果。\n */\nexport function sanitizeLayoutSettingsConfig(\n input: unknown,\n): LayoutSettingsConfig {\n if (!input || typeof input !== \"object\" || Array.isArray(input)) {\n throw new TypeError(\"配置文件根节点必须是对象\");\n }\n\n const source = input as Record<string, unknown>;\n const result: LayoutSettingsConfig = {};\n\n if (source.schemaVersion !== undefined) {\n if (\n typeof source.schemaVersion !== \"number\" ||\n !Number.isInteger(source.schemaVersion) ||\n source.schemaVersion < 1 ||\n source.schemaVersion > SETTINGS_CONFIG_SCHEMA_VERSION\n ) {\n throw new RangeError(\"不支持的配置格式版本\");\n }\n result.schemaVersion = source.schemaVersion;\n }\n\n if (source.settings !== undefined) {\n result.settings = sanitizeSettingsPatch(source.settings);\n }\n\n for (const key of [\"gray\", \"colorWeak\"] as const) {\n const value = source[key];\n if (value === undefined) continue;\n if (typeof value !== \"boolean\") {\n throw new TypeError(`${key} 必须是布尔值`);\n }\n result[key] = value;\n }\n\n if (source.watermark !== undefined) {\n if (\n !source.watermark ||\n typeof source.watermark !== \"object\" ||\n Array.isArray(source.watermark)\n ) {\n throw new TypeError(\"watermark 必须是对象\");\n }\n const watermark = source.watermark as Record<string, unknown>;\n if (\n typeof watermark.enabled !== \"boolean\" ||\n typeof watermark.text !== \"string\" ||\n watermark.text.length > 200\n ) {\n throw new TypeError(\"watermark 配置无效\");\n }\n result.watermark = {\n enabled: watermark.enabled,\n text: watermark.text,\n };\n }\n\n return result;\n}\n\n/**\n * 调整颜色亮度。\n * @returns 调整后的 #rrggbb;输入非法时原样返回。\n */\nexport function adjustColor(color: string, amount: number): string {\n if (typeof color !== \"string\") return \"#000000\";\n if (!Number.isFinite(amount)) return color;\n const normalizedAmount = Math.round(amount);\n const trimmedColor = color.trim();\n let hex = trimmedColor.startsWith(\"#\") ? trimmedColor.slice(1) : trimmedColor;\n if (hex.length === 3) {\n hex = hex\n .split(\"\")\n .map((character) => character + character)\n .join(\"\");\n }\n if (!/^[0-9a-fA-F]{6}$/.test(hex)) return color;\n\n const value = parseInt(hex, 16);\n const red = Math.min(255, Math.max(0, (value >> 16) + normalizedAmount));\n const green = Math.min(\n 255,\n Math.max(0, ((value >> 8) & 0x00ff) + normalizedAmount),\n );\n const blue = Math.min(\n 255,\n Math.max(0, (value & 0x0000ff) + normalizedAmount),\n );\n return `#${((red << 16) | (green << 8) | blue).toString(16).padStart(6, \"0\")}`;\n}\n","/**\n * 布局和设置系统 - 常量定义\n */\n\nimport type {\n ThemePreset,\n SettingsState,\n LayoutInfo,\n PresetColor,\n} from \"../core/types\";\n\n// ============ 主题色预设 ============\nexport const PRESET_COLORS: PresetColor[] = [\n { name: \"拂晓蓝\", value: \"#409eff\" },\n { name: \"薄暮红\", value: \"#f5222d\" },\n { name: \"火山橙\", value: \"#fa541c\" },\n { name: \"日暮黄\", value: \"#faad14\" },\n { name: \"极光绿\", value: \"#52c41a\" },\n { name: \"明青\", value: \"#13c2c2\" },\n { name: \"极客蓝\", value: \"#2f54eb\" },\n { name: \"酱紫\", value: \"#722ed1\" },\n] as const;\n\n// ============ 主题预设方案 ============\nexport const THEME_PRESETS: ThemePreset[] = [\n {\n name: \"科技蓝\",\n icon: \"💙\",\n primaryColor: \"#409eff\",\n },\n {\n name: \"清新绿\",\n icon: \"💚\",\n primaryColor: \"#52c41a\",\n },\n {\n name: \"商务灰\",\n icon: \"🖤\",\n primaryColor: \"#595959\",\n },\n {\n name: \"活力橙\",\n icon: \"🧡\",\n primaryColor: \"#fa8c16\",\n },\n {\n name: \"优雅紫\",\n icon: \"💜\",\n primaryColor: \"#722ed1\",\n },\n {\n name: \"经典红\",\n icon: \"❤️\",\n primaryColor: \"#f5222d\",\n },\n];\n\n// ============ 布局模式信息 ============\nexport const LAYOUT_MODES: LayoutInfo[] = [\n {\n mode: \"side\",\n label: \"左侧菜单\",\n description: \"经典的左侧导航布局\",\n icon: \"i-mdi:page-layout-sidebar-left\",\n },\n {\n mode: \"top\",\n label: \"顶部菜单\",\n description: \"顶部水平导航布局\",\n icon: \"i-mdi:page-layout-header\",\n },\n {\n mode: \"mix\",\n label: \"混合菜单\",\n description: \"顶部 + 侧边混合布局\",\n icon: \"i-mdi:view-dashboard-outline\",\n },\n {\n mode: \"mix-top\",\n label: \"顶部混合\",\n description: \"侧边优先的混合布局\",\n icon: \"i-mdi:view-dashboard-variant-outline\",\n },\n {\n mode: \"reverse-horizontal-mix\",\n label: \"反转混合\",\n description: \"反转的水平混合布局\",\n icon: \"i-mdi:page-layout-header-footer\",\n },\n {\n mode: \"card-layout\",\n label: \"卡片布局\",\n description: \"卡片式布局风格\",\n icon: \"i-mdi:card-outline\",\n },\n];\n\n// ============ 圆角映射 ============\nexport const BORDER_RADIUS_MAP = {\n small: \"4px\",\n medium: \"6px\",\n large: \"8px\",\n} as const;\n\n// ============ 动画映射 ============\nexport const TRANSITION_MAP = {\n fade: \"fade-transform\",\n slide: \"fade-slide\",\n zoom: \"fade-zoom\",\n none: \"\",\n} as const;\n\n// ============ 默认配置 ============\nexport const DEFAULT_SETTINGS: SettingsState = {\n // 外观\n themeMode: \"light\",\n primaryColor: \"#409eff\",\n borderRadius: \"medium\",\n transitionType: \"slide\",\n enableTransition: true,\n\n // 布局\n layoutMode: \"side\",\n menuExpandMode: \"inline\",\n collapsed: false,\n fixedHeader: true,\n showBreadcrumb: true,\n showBreadcrumbIcon: true,\n showTagsView: true,\n tagsViewHeight: 44,\n tagsViewStyle: \"default\",\n showFooter: true,\n sidebarWidth: 220,\n sidebarCollapsedWidth: 64,\n headerHeight: 56,\n\n // 高级\n enableHotkeys: true,\n version: \"3.0.0\",\n};\n\n// ============ 其他常量 ============\n\n/** Color swatches for color picker */\nexport const COLOR_SWATCHES = PRESET_COLORS.map((c) => c.value);\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/core/index.ts","../../src/core/settings.ts","../../src/constants/index.ts"],"sourcesContent":["export {\n adjustColor,\n sanitizeLayoutSettingsConfig,\n sanitizeSettingsPatch,\n SETTINGS_CONFIG_SCHEMA_VERSION,\n} from \"./settings\";\nexport type { LayoutSettingsConfig, LayoutVisualEffects } from \"./settings\";\n\nexport {\n BORDER_RADIUS_MAP,\n COLOR_SWATCHES,\n DEFAULT_SETTINGS,\n LAYOUT_MODES,\n PRESET_COLORS,\n THEME_PRESETS,\n TRANSITION_MAP,\n} from \"../constants\";\n\nexport type {\n BorderRadiusSize,\n LayoutInfo,\n LayoutMode,\n MenuExpandMode,\n PresetColor,\n SettingsDrawerActions,\n SettingsState,\n SettingsStoreOptions,\n TagsViewStyle,\n ThemeMode,\n ThemePreset,\n TransitionType,\n} from \"./types\";\n","import type { SettingsState } from \"./types\";\n\nconst ENUM_SETTINGS = {\n themeMode: new Set([\"light\", \"dark\", \"system\"]),\n borderRadius: new Set([\"small\", \"medium\", \"large\"]),\n transitionType: new Set([\"fade\", \"slide\", \"zoom\", \"none\"]),\n layoutMode: new Set([\n \"side\",\n \"top\",\n \"mix\",\n \"mix-top\",\n \"reverse-horizontal-mix\",\n \"card-layout\",\n ]),\n menuExpandMode: new Set([\"inline\", \"panel\"]),\n tagsViewStyle: new Set([\"default\", \"card\", \"smart\"]),\n} as const;\n\nconst BOOLEAN_SETTINGS: ReadonlySet<keyof SettingsState> = new Set([\n \"enableTransition\",\n \"collapsed\",\n \"fixedHeader\",\n \"showBreadcrumb\",\n \"showBreadcrumbIcon\",\n \"showTagsView\",\n \"showFooter\",\n \"enableHotkeys\",\n]);\n\nconst NUMBER_RANGES: Partial<\n Record<keyof SettingsState, readonly [number, number]>\n> = {\n tagsViewHeight: [24, 100],\n sidebarWidth: [120, 480],\n sidebarCollapsedWidth: [32, 160],\n headerHeight: [32, 160],\n};\n\n/** 当前导入导出配置格式版本。 */\nexport const SETTINGS_CONFIG_SCHEMA_VERSION = 1 as const;\n\nexport interface LayoutVisualEffects {\n gray?: boolean;\n colorWeak?: boolean;\n watermark?: {\n enabled: boolean;\n text: string;\n };\n}\n\n/** 经校验后可原子应用的布局配置。 */\nexport interface LayoutSettingsConfig extends LayoutVisualEffects {\n schemaVersion?: number;\n settings?: Partial<SettingsState>;\n}\n\n/**\n * 校验来自配置文件等不可信来源的设置。\n * 未知键为向前兼容而忽略;已知键的非法值会让整次导入失败。\n */\nexport function sanitizeSettingsPatch(input: unknown): Partial<SettingsState> {\n if (!input || typeof input !== \"object\" || Array.isArray(input)) {\n throw new TypeError(\"settings 必须是对象\");\n }\n\n const source = input as Record<string, unknown>;\n const result: Partial<SettingsState> = {};\n const assign = (key: keyof SettingsState, value: unknown) => {\n (result as Record<string, unknown>)[key] = value;\n };\n\n for (const [key, allowed] of Object.entries(ENUM_SETTINGS)) {\n const value = source[key];\n if (value === undefined) continue;\n if (typeof value !== \"string\" || !allowed.has(value as never)) {\n throw new RangeError(`无效的设置项 ${key}: ${String(value)}`);\n }\n assign(key as keyof SettingsState, value);\n }\n\n for (const key of BOOLEAN_SETTINGS) {\n const value = source[key];\n if (value === undefined) continue;\n if (typeof value !== \"boolean\") {\n throw new TypeError(`设置项 ${key} 必须是布尔值`);\n }\n assign(key, value);\n }\n\n for (const [key, range] of Object.entries(NUMBER_RANGES)) {\n const value = source[key];\n if (value === undefined) continue;\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value) ||\n value < range[0] ||\n value > range[1]\n ) {\n throw new RangeError(`设置项 ${key} 超出允许范围`);\n }\n assign(key as keyof SettingsState, value);\n }\n\n if (source.primaryColor !== undefined) {\n if (\n typeof source.primaryColor !== \"string\" ||\n !/^#[0-9a-fA-F]{6}$/.test(source.primaryColor)\n ) {\n throw new RangeError(\"primaryColor 必须是 #rrggbb 格式\");\n }\n result.primaryColor = source.primaryColor;\n }\n\n if (source.version !== undefined) {\n if (typeof source.version !== \"string\" || source.version.length > 50) {\n throw new TypeError(\"version 必须是长度不超过 50 的字符串\");\n }\n result.version = source.version;\n }\n\n return result;\n}\n\n/**\n * 一次性校验完整导入文件。此函数不修改任何响应式状态或浏览器 API,\n * 消费方可以在成功返回后再原子应用结果。\n */\nexport function sanitizeLayoutSettingsConfig(\n input: unknown,\n): LayoutSettingsConfig {\n if (!input || typeof input !== \"object\" || Array.isArray(input)) {\n throw new TypeError(\"配置文件根节点必须是对象\");\n }\n\n const source = input as Record<string, unknown>;\n const result: LayoutSettingsConfig = {};\n\n if (source.schemaVersion !== undefined) {\n if (\n typeof source.schemaVersion !== \"number\" ||\n !Number.isInteger(source.schemaVersion) ||\n source.schemaVersion < 1 ||\n source.schemaVersion > SETTINGS_CONFIG_SCHEMA_VERSION\n ) {\n throw new RangeError(\"不支持的配置格式版本\");\n }\n result.schemaVersion = source.schemaVersion;\n }\n\n if (source.settings !== undefined) {\n result.settings = sanitizeSettingsPatch(source.settings);\n }\n\n for (const key of [\"gray\", \"colorWeak\"] as const) {\n const value = source[key];\n if (value === undefined) continue;\n if (typeof value !== \"boolean\") {\n throw new TypeError(`${key} 必须是布尔值`);\n }\n result[key] = value;\n }\n\n if (source.watermark !== undefined) {\n if (\n !source.watermark ||\n typeof source.watermark !== \"object\" ||\n Array.isArray(source.watermark)\n ) {\n throw new TypeError(\"watermark 必须是对象\");\n }\n const watermark = source.watermark as Record<string, unknown>;\n if (\n typeof watermark.enabled !== \"boolean\" ||\n typeof watermark.text !== \"string\" ||\n watermark.text.length > 200\n ) {\n throw new TypeError(\"watermark 配置无效\");\n }\n result.watermark = {\n enabled: watermark.enabled,\n text: watermark.text,\n };\n }\n\n return result;\n}\n\n/**\n * 调整颜色亮度。\n * @returns 调整后的 #rrggbb;输入非法时原样返回。\n */\nexport function adjustColor(color: string, amount: number): string {\n if (typeof color !== \"string\") return \"#000000\";\n if (!Number.isFinite(amount)) return color;\n const normalizedAmount = Math.round(amount);\n const trimmedColor = color.trim();\n let hex = trimmedColor.startsWith(\"#\") ? trimmedColor.slice(1) : trimmedColor;\n if (hex.length === 3) {\n hex = hex\n .split(\"\")\n .map((character) => character + character)\n .join(\"\");\n }\n if (!/^[0-9a-fA-F]{6}$/.test(hex)) return color;\n\n const value = parseInt(hex, 16);\n const red = Math.min(255, Math.max(0, (value >> 16) + normalizedAmount));\n const green = Math.min(\n 255,\n Math.max(0, ((value >> 8) & 0x00ff) + normalizedAmount),\n );\n const blue = Math.min(\n 255,\n Math.max(0, (value & 0x0000ff) + normalizedAmount),\n );\n return `#${((red << 16) | (green << 8) | blue).toString(16).padStart(6, \"0\")}`;\n}\n","/**\n * 布局和设置系统 - 常量定义\n */\n\nimport type {\n ThemePreset,\n SettingsState,\n LayoutInfo,\n PresetColor,\n} from \"../core/types\";\n\n// ============ 主题色预设 ============\nexport const PRESET_COLORS: PresetColor[] = [\n { name: \"拂晓蓝\", value: \"#409eff\" },\n { name: \"薄暮红\", value: \"#f5222d\" },\n { name: \"火山橙\", value: \"#fa541c\" },\n { name: \"日暮黄\", value: \"#faad14\" },\n { name: \"极光绿\", value: \"#52c41a\" },\n { name: \"明青\", value: \"#13c2c2\" },\n { name: \"极客蓝\", value: \"#2f54eb\" },\n { name: \"酱紫\", value: \"#722ed1\" },\n] as const;\n\n// ============ 主题预设方案 ============\nexport const THEME_PRESETS: ThemePreset[] = [\n {\n name: \"科技蓝\",\n icon: \"💙\",\n primaryColor: \"#409eff\",\n },\n {\n name: \"清新绿\",\n icon: \"💚\",\n primaryColor: \"#52c41a\",\n },\n {\n name: \"商务灰\",\n icon: \"🖤\",\n primaryColor: \"#595959\",\n },\n {\n name: \"活力橙\",\n icon: \"🧡\",\n primaryColor: \"#fa8c16\",\n },\n {\n name: \"优雅紫\",\n icon: \"💜\",\n primaryColor: \"#722ed1\",\n },\n {\n name: \"经典红\",\n icon: \"❤️\",\n primaryColor: \"#f5222d\",\n },\n];\n\n// ============ 布局模式信息 ============\nexport const LAYOUT_MODES: LayoutInfo[] = [\n {\n mode: \"side\",\n label: \"左侧菜单\",\n description: \"经典的左侧导航布局\",\n icon: \"i-mdi:page-layout-sidebar-left\",\n },\n {\n mode: \"top\",\n label: \"顶部菜单\",\n description: \"顶部水平导航布局\",\n icon: \"i-mdi:page-layout-header\",\n },\n {\n mode: \"mix\",\n label: \"混合菜单\",\n description: \"顶部 + 侧边混合布局\",\n icon: \"i-mdi:view-dashboard-outline\",\n },\n {\n mode: \"mix-top\",\n label: \"顶部混合\",\n description: \"侧边优先的混合布局\",\n icon: \"i-mdi:view-dashboard-variant-outline\",\n },\n {\n mode: \"reverse-horizontal-mix\",\n label: \"反转混合\",\n description: \"反转的水平混合布局\",\n icon: \"i-mdi:page-layout-header-footer\",\n },\n {\n mode: \"card-layout\",\n label: \"卡片布局\",\n description: \"卡片式布局风格\",\n icon: \"i-mdi:card-outline\",\n },\n];\n\n// ============ 圆角映射 ============\nexport const BORDER_RADIUS_MAP = {\n small: \"4px\",\n medium: \"6px\",\n large: \"8px\",\n} as const;\n\n// ============ 动画映射 ============\nexport const TRANSITION_MAP = {\n fade: \"fade-transform\",\n slide: \"fade-slide\",\n zoom: \"fade-zoom\",\n none: \"\",\n} as const;\n\n// ============ 默认配置 ============\nexport const DEFAULT_SETTINGS: SettingsState = {\n // 外观\n themeMode: \"light\",\n primaryColor: \"#409eff\",\n borderRadius: \"medium\",\n transitionType: \"slide\",\n enableTransition: true,\n\n // 布局\n layoutMode: \"side\",\n menuExpandMode: \"inline\",\n collapsed: false,\n fixedHeader: true,\n showBreadcrumb: true,\n showBreadcrumbIcon: true,\n showTagsView: true,\n tagsViewHeight: 44,\n tagsViewStyle: \"default\",\n showFooter: true,\n sidebarWidth: 220,\n sidebarCollapsedWidth: 64,\n headerHeight: 56,\n\n // 高级\n enableHotkeys: true,\n version: \"3.1.0\",\n};\n\n// ============ 其他常量 ============\n\n/** Color swatches for color picker */\nexport const COLOR_SWATCHES = PRESET_COLORS.map((c) => c.value);\n"],"mappings":"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","names":[]}
|
package/dist/core/index.js
CHANGED
package/dist/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/settings.ts","../../src/constants/index.ts"],"sourcesContent":["import type { SettingsState } from \"./types\";\n\nconst ENUM_SETTINGS = {\n themeMode: new Set([\"light\", \"dark\", \"system\"]),\n borderRadius: new Set([\"small\", \"medium\", \"large\"]),\n transitionType: new Set([\"fade\", \"slide\", \"zoom\", \"none\"]),\n layoutMode: new Set([\n \"side\",\n \"top\",\n \"mix\",\n \"mix-top\",\n \"reverse-horizontal-mix\",\n \"card-layout\",\n ]),\n menuExpandMode: new Set([\"inline\", \"panel\"]),\n tagsViewStyle: new Set([\"default\", \"card\", \"smart\"]),\n} as const;\n\nconst BOOLEAN_SETTINGS: ReadonlySet<keyof SettingsState> = new Set([\n \"enableTransition\",\n \"collapsed\",\n \"fixedHeader\",\n \"showBreadcrumb\",\n \"showBreadcrumbIcon\",\n \"showTagsView\",\n \"showFooter\",\n \"enableHotkeys\",\n]);\n\nconst NUMBER_RANGES: Partial<\n Record<keyof SettingsState, readonly [number, number]>\n> = {\n tagsViewHeight: [24, 100],\n sidebarWidth: [120, 480],\n sidebarCollapsedWidth: [32, 160],\n headerHeight: [32, 160],\n};\n\n/** 当前导入导出配置格式版本。 */\nexport const SETTINGS_CONFIG_SCHEMA_VERSION = 1 as const;\n\nexport interface LayoutVisualEffects {\n gray?: boolean;\n colorWeak?: boolean;\n watermark?: {\n enabled: boolean;\n text: string;\n };\n}\n\n/** 经校验后可原子应用的布局配置。 */\nexport interface LayoutSettingsConfig extends LayoutVisualEffects {\n schemaVersion?: number;\n settings?: Partial<SettingsState>;\n}\n\n/**\n * 校验来自配置文件等不可信来源的设置。\n * 未知键为向前兼容而忽略;已知键的非法值会让整次导入失败。\n */\nexport function sanitizeSettingsPatch(input: unknown): Partial<SettingsState> {\n if (!input || typeof input !== \"object\" || Array.isArray(input)) {\n throw new TypeError(\"settings 必须是对象\");\n }\n\n const source = input as Record<string, unknown>;\n const result: Partial<SettingsState> = {};\n const assign = (key: keyof SettingsState, value: unknown) => {\n (result as Record<string, unknown>)[key] = value;\n };\n\n for (const [key, allowed] of Object.entries(ENUM_SETTINGS)) {\n const value = source[key];\n if (value === undefined) continue;\n if (typeof value !== \"string\" || !allowed.has(value as never)) {\n throw new RangeError(`无效的设置项 ${key}: ${String(value)}`);\n }\n assign(key as keyof SettingsState, value);\n }\n\n for (const key of BOOLEAN_SETTINGS) {\n const value = source[key];\n if (value === undefined) continue;\n if (typeof value !== \"boolean\") {\n throw new TypeError(`设置项 ${key} 必须是布尔值`);\n }\n assign(key, value);\n }\n\n for (const [key, range] of Object.entries(NUMBER_RANGES)) {\n const value = source[key];\n if (value === undefined) continue;\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value) ||\n value < range[0] ||\n value > range[1]\n ) {\n throw new RangeError(`设置项 ${key} 超出允许范围`);\n }\n assign(key as keyof SettingsState, value);\n }\n\n if (source.primaryColor !== undefined) {\n if (\n typeof source.primaryColor !== \"string\" ||\n !/^#[0-9a-fA-F]{6}$/.test(source.primaryColor)\n ) {\n throw new RangeError(\"primaryColor 必须是 #rrggbb 格式\");\n }\n result.primaryColor = source.primaryColor;\n }\n\n if (source.version !== undefined) {\n if (typeof source.version !== \"string\" || source.version.length > 50) {\n throw new TypeError(\"version 必须是长度不超过 50 的字符串\");\n }\n result.version = source.version;\n }\n\n return result;\n}\n\n/**\n * 一次性校验完整导入文件。此函数不修改任何响应式状态或浏览器 API,\n * 消费方可以在成功返回后再原子应用结果。\n */\nexport function sanitizeLayoutSettingsConfig(\n input: unknown,\n): LayoutSettingsConfig {\n if (!input || typeof input !== \"object\" || Array.isArray(input)) {\n throw new TypeError(\"配置文件根节点必须是对象\");\n }\n\n const source = input as Record<string, unknown>;\n const result: LayoutSettingsConfig = {};\n\n if (source.schemaVersion !== undefined) {\n if (\n typeof source.schemaVersion !== \"number\" ||\n !Number.isInteger(source.schemaVersion) ||\n source.schemaVersion < 1 ||\n source.schemaVersion > SETTINGS_CONFIG_SCHEMA_VERSION\n ) {\n throw new RangeError(\"不支持的配置格式版本\");\n }\n result.schemaVersion = source.schemaVersion;\n }\n\n if (source.settings !== undefined) {\n result.settings = sanitizeSettingsPatch(source.settings);\n }\n\n for (const key of [\"gray\", \"colorWeak\"] as const) {\n const value = source[key];\n if (value === undefined) continue;\n if (typeof value !== \"boolean\") {\n throw new TypeError(`${key} 必须是布尔值`);\n }\n result[key] = value;\n }\n\n if (source.watermark !== undefined) {\n if (\n !source.watermark ||\n typeof source.watermark !== \"object\" ||\n Array.isArray(source.watermark)\n ) {\n throw new TypeError(\"watermark 必须是对象\");\n }\n const watermark = source.watermark as Record<string, unknown>;\n if (\n typeof watermark.enabled !== \"boolean\" ||\n typeof watermark.text !== \"string\" ||\n watermark.text.length > 200\n ) {\n throw new TypeError(\"watermark 配置无效\");\n }\n result.watermark = {\n enabled: watermark.enabled,\n text: watermark.text,\n };\n }\n\n return result;\n}\n\n/**\n * 调整颜色亮度。\n * @returns 调整后的 #rrggbb;输入非法时原样返回。\n */\nexport function adjustColor(color: string, amount: number): string {\n if (typeof color !== \"string\") return \"#000000\";\n if (!Number.isFinite(amount)) return color;\n const normalizedAmount = Math.round(amount);\n const trimmedColor = color.trim();\n let hex = trimmedColor.startsWith(\"#\") ? trimmedColor.slice(1) : trimmedColor;\n if (hex.length === 3) {\n hex = hex\n .split(\"\")\n .map((character) => character + character)\n .join(\"\");\n }\n if (!/^[0-9a-fA-F]{6}$/.test(hex)) return color;\n\n const value = parseInt(hex, 16);\n const red = Math.min(255, Math.max(0, (value >> 16) + normalizedAmount));\n const green = Math.min(\n 255,\n Math.max(0, ((value >> 8) & 0x00ff) + normalizedAmount),\n );\n const blue = Math.min(\n 255,\n Math.max(0, (value & 0x0000ff) + normalizedAmount),\n );\n return `#${((red << 16) | (green << 8) | blue).toString(16).padStart(6, \"0\")}`;\n}\n","/**\n * 布局和设置系统 - 常量定义\n */\n\nimport type {\n ThemePreset,\n SettingsState,\n LayoutInfo,\n PresetColor,\n} from \"../core/types\";\n\n// ============ 主题色预设 ============\nexport const PRESET_COLORS: PresetColor[] = [\n { name: \"拂晓蓝\", value: \"#409eff\" },\n { name: \"薄暮红\", value: \"#f5222d\" },\n { name: \"火山橙\", value: \"#fa541c\" },\n { name: \"日暮黄\", value: \"#faad14\" },\n { name: \"极光绿\", value: \"#52c41a\" },\n { name: \"明青\", value: \"#13c2c2\" },\n { name: \"极客蓝\", value: \"#2f54eb\" },\n { name: \"酱紫\", value: \"#722ed1\" },\n] as const;\n\n// ============ 主题预设方案 ============\nexport const THEME_PRESETS: ThemePreset[] = [\n {\n name: \"科技蓝\",\n icon: \"💙\",\n primaryColor: \"#409eff\",\n },\n {\n name: \"清新绿\",\n icon: \"💚\",\n primaryColor: \"#52c41a\",\n },\n {\n name: \"商务灰\",\n icon: \"🖤\",\n primaryColor: \"#595959\",\n },\n {\n name: \"活力橙\",\n icon: \"🧡\",\n primaryColor: \"#fa8c16\",\n },\n {\n name: \"优雅紫\",\n icon: \"💜\",\n primaryColor: \"#722ed1\",\n },\n {\n name: \"经典红\",\n icon: \"❤️\",\n primaryColor: \"#f5222d\",\n },\n];\n\n// ============ 布局模式信息 ============\nexport const LAYOUT_MODES: LayoutInfo[] = [\n {\n mode: \"side\",\n label: \"左侧菜单\",\n description: \"经典的左侧导航布局\",\n icon: \"i-mdi:page-layout-sidebar-left\",\n },\n {\n mode: \"top\",\n label: \"顶部菜单\",\n description: \"顶部水平导航布局\",\n icon: \"i-mdi:page-layout-header\",\n },\n {\n mode: \"mix\",\n label: \"混合菜单\",\n description: \"顶部 + 侧边混合布局\",\n icon: \"i-mdi:view-dashboard-outline\",\n },\n {\n mode: \"mix-top\",\n label: \"顶部混合\",\n description: \"侧边优先的混合布局\",\n icon: \"i-mdi:view-dashboard-variant-outline\",\n },\n {\n mode: \"reverse-horizontal-mix\",\n label: \"反转混合\",\n description: \"反转的水平混合布局\",\n icon: \"i-mdi:page-layout-header-footer\",\n },\n {\n mode: \"card-layout\",\n label: \"卡片布局\",\n description: \"卡片式布局风格\",\n icon: \"i-mdi:card-outline\",\n },\n];\n\n// ============ 圆角映射 ============\nexport const BORDER_RADIUS_MAP = {\n small: \"4px\",\n medium: \"6px\",\n large: \"8px\",\n} as const;\n\n// ============ 动画映射 ============\nexport const TRANSITION_MAP = {\n fade: \"fade-transform\",\n slide: \"fade-slide\",\n zoom: \"fade-zoom\",\n none: \"\",\n} as const;\n\n// ============ 默认配置 ============\nexport const DEFAULT_SETTINGS: SettingsState = {\n // 外观\n themeMode: \"light\",\n primaryColor: \"#409eff\",\n borderRadius: \"medium\",\n transitionType: \"slide\",\n enableTransition: true,\n\n // 布局\n layoutMode: \"side\",\n menuExpandMode: \"inline\",\n collapsed: false,\n fixedHeader: true,\n showBreadcrumb: true,\n showBreadcrumbIcon: true,\n showTagsView: true,\n tagsViewHeight: 44,\n tagsViewStyle: \"default\",\n showFooter: true,\n sidebarWidth: 220,\n sidebarCollapsedWidth: 64,\n headerHeight: 56,\n\n // 高级\n enableHotkeys: true,\n version: \"3.0.0\",\n};\n\n// ============ 其他常量 ============\n\n/** Color swatches for color picker */\nexport const COLOR_SWATCHES = PRESET_COLORS.map((c) => c.value);\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/core/settings.ts","../../src/constants/index.ts"],"sourcesContent":["import type { SettingsState } from \"./types\";\n\nconst ENUM_SETTINGS = {\n themeMode: new Set([\"light\", \"dark\", \"system\"]),\n borderRadius: new Set([\"small\", \"medium\", \"large\"]),\n transitionType: new Set([\"fade\", \"slide\", \"zoom\", \"none\"]),\n layoutMode: new Set([\n \"side\",\n \"top\",\n \"mix\",\n \"mix-top\",\n \"reverse-horizontal-mix\",\n \"card-layout\",\n ]),\n menuExpandMode: new Set([\"inline\", \"panel\"]),\n tagsViewStyle: new Set([\"default\", \"card\", \"smart\"]),\n} as const;\n\nconst BOOLEAN_SETTINGS: ReadonlySet<keyof SettingsState> = new Set([\n \"enableTransition\",\n \"collapsed\",\n \"fixedHeader\",\n \"showBreadcrumb\",\n \"showBreadcrumbIcon\",\n \"showTagsView\",\n \"showFooter\",\n \"enableHotkeys\",\n]);\n\nconst NUMBER_RANGES: Partial<\n Record<keyof SettingsState, readonly [number, number]>\n> = {\n tagsViewHeight: [24, 100],\n sidebarWidth: [120, 480],\n sidebarCollapsedWidth: [32, 160],\n headerHeight: [32, 160],\n};\n\n/** 当前导入导出配置格式版本。 */\nexport const SETTINGS_CONFIG_SCHEMA_VERSION = 1 as const;\n\nexport interface LayoutVisualEffects {\n gray?: boolean;\n colorWeak?: boolean;\n watermark?: {\n enabled: boolean;\n text: string;\n };\n}\n\n/** 经校验后可原子应用的布局配置。 */\nexport interface LayoutSettingsConfig extends LayoutVisualEffects {\n schemaVersion?: number;\n settings?: Partial<SettingsState>;\n}\n\n/**\n * 校验来自配置文件等不可信来源的设置。\n * 未知键为向前兼容而忽略;已知键的非法值会让整次导入失败。\n */\nexport function sanitizeSettingsPatch(input: unknown): Partial<SettingsState> {\n if (!input || typeof input !== \"object\" || Array.isArray(input)) {\n throw new TypeError(\"settings 必须是对象\");\n }\n\n const source = input as Record<string, unknown>;\n const result: Partial<SettingsState> = {};\n const assign = (key: keyof SettingsState, value: unknown) => {\n (result as Record<string, unknown>)[key] = value;\n };\n\n for (const [key, allowed] of Object.entries(ENUM_SETTINGS)) {\n const value = source[key];\n if (value === undefined) continue;\n if (typeof value !== \"string\" || !allowed.has(value as never)) {\n throw new RangeError(`无效的设置项 ${key}: ${String(value)}`);\n }\n assign(key as keyof SettingsState, value);\n }\n\n for (const key of BOOLEAN_SETTINGS) {\n const value = source[key];\n if (value === undefined) continue;\n if (typeof value !== \"boolean\") {\n throw new TypeError(`设置项 ${key} 必须是布尔值`);\n }\n assign(key, value);\n }\n\n for (const [key, range] of Object.entries(NUMBER_RANGES)) {\n const value = source[key];\n if (value === undefined) continue;\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value) ||\n value < range[0] ||\n value > range[1]\n ) {\n throw new RangeError(`设置项 ${key} 超出允许范围`);\n }\n assign(key as keyof SettingsState, value);\n }\n\n if (source.primaryColor !== undefined) {\n if (\n typeof source.primaryColor !== \"string\" ||\n !/^#[0-9a-fA-F]{6}$/.test(source.primaryColor)\n ) {\n throw new RangeError(\"primaryColor 必须是 #rrggbb 格式\");\n }\n result.primaryColor = source.primaryColor;\n }\n\n if (source.version !== undefined) {\n if (typeof source.version !== \"string\" || source.version.length > 50) {\n throw new TypeError(\"version 必须是长度不超过 50 的字符串\");\n }\n result.version = source.version;\n }\n\n return result;\n}\n\n/**\n * 一次性校验完整导入文件。此函数不修改任何响应式状态或浏览器 API,\n * 消费方可以在成功返回后再原子应用结果。\n */\nexport function sanitizeLayoutSettingsConfig(\n input: unknown,\n): LayoutSettingsConfig {\n if (!input || typeof input !== \"object\" || Array.isArray(input)) {\n throw new TypeError(\"配置文件根节点必须是对象\");\n }\n\n const source = input as Record<string, unknown>;\n const result: LayoutSettingsConfig = {};\n\n if (source.schemaVersion !== undefined) {\n if (\n typeof source.schemaVersion !== \"number\" ||\n !Number.isInteger(source.schemaVersion) ||\n source.schemaVersion < 1 ||\n source.schemaVersion > SETTINGS_CONFIG_SCHEMA_VERSION\n ) {\n throw new RangeError(\"不支持的配置格式版本\");\n }\n result.schemaVersion = source.schemaVersion;\n }\n\n if (source.settings !== undefined) {\n result.settings = sanitizeSettingsPatch(source.settings);\n }\n\n for (const key of [\"gray\", \"colorWeak\"] as const) {\n const value = source[key];\n if (value === undefined) continue;\n if (typeof value !== \"boolean\") {\n throw new TypeError(`${key} 必须是布尔值`);\n }\n result[key] = value;\n }\n\n if (source.watermark !== undefined) {\n if (\n !source.watermark ||\n typeof source.watermark !== \"object\" ||\n Array.isArray(source.watermark)\n ) {\n throw new TypeError(\"watermark 必须是对象\");\n }\n const watermark = source.watermark as Record<string, unknown>;\n if (\n typeof watermark.enabled !== \"boolean\" ||\n typeof watermark.text !== \"string\" ||\n watermark.text.length > 200\n ) {\n throw new TypeError(\"watermark 配置无效\");\n }\n result.watermark = {\n enabled: watermark.enabled,\n text: watermark.text,\n };\n }\n\n return result;\n}\n\n/**\n * 调整颜色亮度。\n * @returns 调整后的 #rrggbb;输入非法时原样返回。\n */\nexport function adjustColor(color: string, amount: number): string {\n if (typeof color !== \"string\") return \"#000000\";\n if (!Number.isFinite(amount)) return color;\n const normalizedAmount = Math.round(amount);\n const trimmedColor = color.trim();\n let hex = trimmedColor.startsWith(\"#\") ? trimmedColor.slice(1) : trimmedColor;\n if (hex.length === 3) {\n hex = hex\n .split(\"\")\n .map((character) => character + character)\n .join(\"\");\n }\n if (!/^[0-9a-fA-F]{6}$/.test(hex)) return color;\n\n const value = parseInt(hex, 16);\n const red = Math.min(255, Math.max(0, (value >> 16) + normalizedAmount));\n const green = Math.min(\n 255,\n Math.max(0, ((value >> 8) & 0x00ff) + normalizedAmount),\n );\n const blue = Math.min(\n 255,\n Math.max(0, (value & 0x0000ff) + normalizedAmount),\n );\n return `#${((red << 16) | (green << 8) | blue).toString(16).padStart(6, \"0\")}`;\n}\n","/**\n * 布局和设置系统 - 常量定义\n */\n\nimport type {\n ThemePreset,\n SettingsState,\n LayoutInfo,\n PresetColor,\n} from \"../core/types\";\n\n// ============ 主题色预设 ============\nexport const PRESET_COLORS: PresetColor[] = [\n { name: \"拂晓蓝\", value: \"#409eff\" },\n { name: \"薄暮红\", value: \"#f5222d\" },\n { name: \"火山橙\", value: \"#fa541c\" },\n { name: \"日暮黄\", value: \"#faad14\" },\n { name: \"极光绿\", value: \"#52c41a\" },\n { name: \"明青\", value: \"#13c2c2\" },\n { name: \"极客蓝\", value: \"#2f54eb\" },\n { name: \"酱紫\", value: \"#722ed1\" },\n] as const;\n\n// ============ 主题预设方案 ============\nexport const THEME_PRESETS: ThemePreset[] = [\n {\n name: \"科技蓝\",\n icon: \"💙\",\n primaryColor: \"#409eff\",\n },\n {\n name: \"清新绿\",\n icon: \"💚\",\n primaryColor: \"#52c41a\",\n },\n {\n name: \"商务灰\",\n icon: \"🖤\",\n primaryColor: \"#595959\",\n },\n {\n name: \"活力橙\",\n icon: \"🧡\",\n primaryColor: \"#fa8c16\",\n },\n {\n name: \"优雅紫\",\n icon: \"💜\",\n primaryColor: \"#722ed1\",\n },\n {\n name: \"经典红\",\n icon: \"❤️\",\n primaryColor: \"#f5222d\",\n },\n];\n\n// ============ 布局模式信息 ============\nexport const LAYOUT_MODES: LayoutInfo[] = [\n {\n mode: \"side\",\n label: \"左侧菜单\",\n description: \"经典的左侧导航布局\",\n icon: \"i-mdi:page-layout-sidebar-left\",\n },\n {\n mode: \"top\",\n label: \"顶部菜单\",\n description: \"顶部水平导航布局\",\n icon: \"i-mdi:page-layout-header\",\n },\n {\n mode: \"mix\",\n label: \"混合菜单\",\n description: \"顶部 + 侧边混合布局\",\n icon: \"i-mdi:view-dashboard-outline\",\n },\n {\n mode: \"mix-top\",\n label: \"顶部混合\",\n description: \"侧边优先的混合布局\",\n icon: \"i-mdi:view-dashboard-variant-outline\",\n },\n {\n mode: \"reverse-horizontal-mix\",\n label: \"反转混合\",\n description: \"反转的水平混合布局\",\n icon: \"i-mdi:page-layout-header-footer\",\n },\n {\n mode: \"card-layout\",\n label: \"卡片布局\",\n description: \"卡片式布局风格\",\n icon: \"i-mdi:card-outline\",\n },\n];\n\n// ============ 圆角映射 ============\nexport const BORDER_RADIUS_MAP = {\n small: \"4px\",\n medium: \"6px\",\n large: \"8px\",\n} as const;\n\n// ============ 动画映射 ============\nexport const TRANSITION_MAP = {\n fade: \"fade-transform\",\n slide: \"fade-slide\",\n zoom: \"fade-zoom\",\n none: \"\",\n} as const;\n\n// ============ 默认配置 ============\nexport const DEFAULT_SETTINGS: SettingsState = {\n // 外观\n themeMode: \"light\",\n primaryColor: \"#409eff\",\n borderRadius: \"medium\",\n transitionType: \"slide\",\n enableTransition: true,\n\n // 布局\n layoutMode: \"side\",\n menuExpandMode: \"inline\",\n collapsed: false,\n fixedHeader: true,\n showBreadcrumb: true,\n showBreadcrumbIcon: true,\n showTagsView: true,\n tagsViewHeight: 44,\n tagsViewStyle: \"default\",\n showFooter: true,\n sidebarWidth: 220,\n sidebarCollapsedWidth: 64,\n headerHeight: 56,\n\n // 高级\n enableHotkeys: true,\n version: \"3.1.0\",\n};\n\n// ============ 其他常量 ============\n\n/** Color swatches for color picker */\nexport const COLOR_SWATCHES = PRESET_COLORS.map((c) => c.value);\n"],"mappings":"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","names":[]}
|