@robot-admin/layout 2.3.2 → 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 +153 -0
- package/LICENSE +21 -0
- package/README.md +156 -65
- package/dist/core/index.cjs +310 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.cts +121 -0
- package/dist/core/index.d.ts +121 -0
- package/dist/core/index.js +273 -0
- package/dist/core/index.js.map +1 -0
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.cts +1939 -0
- package/dist/index.d.ts +1001 -127
- package/dist/index.js +1518 -1337
- package/dist/index.js.map +1 -1
- package/package.json +39 -14
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/core/index.ts
|
|
21
|
+
var core_exports = {};
|
|
22
|
+
__export(core_exports, {
|
|
23
|
+
BORDER_RADIUS_MAP: () => BORDER_RADIUS_MAP,
|
|
24
|
+
COLOR_SWATCHES: () => COLOR_SWATCHES,
|
|
25
|
+
DEFAULT_SETTINGS: () => DEFAULT_SETTINGS,
|
|
26
|
+
LAYOUT_MODES: () => LAYOUT_MODES,
|
|
27
|
+
PRESET_COLORS: () => PRESET_COLORS,
|
|
28
|
+
SETTINGS_CONFIG_SCHEMA_VERSION: () => SETTINGS_CONFIG_SCHEMA_VERSION,
|
|
29
|
+
THEME_PRESETS: () => THEME_PRESETS,
|
|
30
|
+
TRANSITION_MAP: () => TRANSITION_MAP,
|
|
31
|
+
adjustColor: () => adjustColor,
|
|
32
|
+
sanitizeLayoutSettingsConfig: () => sanitizeLayoutSettingsConfig,
|
|
33
|
+
sanitizeSettingsPatch: () => sanitizeSettingsPatch
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(core_exports);
|
|
36
|
+
|
|
37
|
+
// src/core/settings.ts
|
|
38
|
+
var ENUM_SETTINGS = {
|
|
39
|
+
themeMode: /* @__PURE__ */ new Set(["light", "dark", "system"]),
|
|
40
|
+
borderRadius: /* @__PURE__ */ new Set(["small", "medium", "large"]),
|
|
41
|
+
transitionType: /* @__PURE__ */ new Set(["fade", "slide", "zoom", "none"]),
|
|
42
|
+
layoutMode: /* @__PURE__ */ new Set([
|
|
43
|
+
"side",
|
|
44
|
+
"top",
|
|
45
|
+
"mix",
|
|
46
|
+
"mix-top",
|
|
47
|
+
"reverse-horizontal-mix",
|
|
48
|
+
"card-layout"
|
|
49
|
+
]),
|
|
50
|
+
menuExpandMode: /* @__PURE__ */ new Set(["inline", "panel"]),
|
|
51
|
+
tagsViewStyle: /* @__PURE__ */ new Set(["default", "card", "smart"])
|
|
52
|
+
};
|
|
53
|
+
var BOOLEAN_SETTINGS = /* @__PURE__ */ new Set([
|
|
54
|
+
"enableTransition",
|
|
55
|
+
"collapsed",
|
|
56
|
+
"fixedHeader",
|
|
57
|
+
"showBreadcrumb",
|
|
58
|
+
"showBreadcrumbIcon",
|
|
59
|
+
"showTagsView",
|
|
60
|
+
"showFooter",
|
|
61
|
+
"enableHotkeys"
|
|
62
|
+
]);
|
|
63
|
+
var NUMBER_RANGES = {
|
|
64
|
+
tagsViewHeight: [24, 100],
|
|
65
|
+
sidebarWidth: [120, 480],
|
|
66
|
+
sidebarCollapsedWidth: [32, 160],
|
|
67
|
+
headerHeight: [32, 160]
|
|
68
|
+
};
|
|
69
|
+
var SETTINGS_CONFIG_SCHEMA_VERSION = 1;
|
|
70
|
+
function sanitizeSettingsPatch(input) {
|
|
71
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
72
|
+
throw new TypeError("settings \u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
73
|
+
}
|
|
74
|
+
const source = input;
|
|
75
|
+
const result = {};
|
|
76
|
+
const assign = (key, value) => {
|
|
77
|
+
result[key] = value;
|
|
78
|
+
};
|
|
79
|
+
for (const [key, allowed] of Object.entries(ENUM_SETTINGS)) {
|
|
80
|
+
const value = source[key];
|
|
81
|
+
if (value === void 0) continue;
|
|
82
|
+
if (typeof value !== "string" || !allowed.has(value)) {
|
|
83
|
+
throw new RangeError(`\u65E0\u6548\u7684\u8BBE\u7F6E\u9879 ${key}: ${String(value)}`);
|
|
84
|
+
}
|
|
85
|
+
assign(key, value);
|
|
86
|
+
}
|
|
87
|
+
for (const key of BOOLEAN_SETTINGS) {
|
|
88
|
+
const value = source[key];
|
|
89
|
+
if (value === void 0) continue;
|
|
90
|
+
if (typeof value !== "boolean") {
|
|
91
|
+
throw new TypeError(`\u8BBE\u7F6E\u9879 ${key} \u5FC5\u987B\u662F\u5E03\u5C14\u503C`);
|
|
92
|
+
}
|
|
93
|
+
assign(key, value);
|
|
94
|
+
}
|
|
95
|
+
for (const [key, range] of Object.entries(NUMBER_RANGES)) {
|
|
96
|
+
const value = source[key];
|
|
97
|
+
if (value === void 0) continue;
|
|
98
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < range[0] || value > range[1]) {
|
|
99
|
+
throw new RangeError(`\u8BBE\u7F6E\u9879 ${key} \u8D85\u51FA\u5141\u8BB8\u8303\u56F4`);
|
|
100
|
+
}
|
|
101
|
+
assign(key, value);
|
|
102
|
+
}
|
|
103
|
+
if (source.primaryColor !== void 0) {
|
|
104
|
+
if (typeof source.primaryColor !== "string" || !/^#[0-9a-fA-F]{6}$/.test(source.primaryColor)) {
|
|
105
|
+
throw new RangeError("primaryColor \u5FC5\u987B\u662F #rrggbb \u683C\u5F0F");
|
|
106
|
+
}
|
|
107
|
+
result.primaryColor = source.primaryColor;
|
|
108
|
+
}
|
|
109
|
+
if (source.version !== void 0) {
|
|
110
|
+
if (typeof source.version !== "string" || source.version.length > 50) {
|
|
111
|
+
throw new TypeError("version \u5FC5\u987B\u662F\u957F\u5EA6\u4E0D\u8D85\u8FC7 50 \u7684\u5B57\u7B26\u4E32");
|
|
112
|
+
}
|
|
113
|
+
result.version = source.version;
|
|
114
|
+
}
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
function sanitizeLayoutSettingsConfig(input) {
|
|
118
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
119
|
+
throw new TypeError("\u914D\u7F6E\u6587\u4EF6\u6839\u8282\u70B9\u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
120
|
+
}
|
|
121
|
+
const source = input;
|
|
122
|
+
const result = {};
|
|
123
|
+
if (source.schemaVersion !== void 0) {
|
|
124
|
+
if (typeof source.schemaVersion !== "number" || !Number.isInteger(source.schemaVersion) || source.schemaVersion < 1 || source.schemaVersion > SETTINGS_CONFIG_SCHEMA_VERSION) {
|
|
125
|
+
throw new RangeError("\u4E0D\u652F\u6301\u7684\u914D\u7F6E\u683C\u5F0F\u7248\u672C");
|
|
126
|
+
}
|
|
127
|
+
result.schemaVersion = source.schemaVersion;
|
|
128
|
+
}
|
|
129
|
+
if (source.settings !== void 0) {
|
|
130
|
+
result.settings = sanitizeSettingsPatch(source.settings);
|
|
131
|
+
}
|
|
132
|
+
for (const key of ["gray", "colorWeak"]) {
|
|
133
|
+
const value = source[key];
|
|
134
|
+
if (value === void 0) continue;
|
|
135
|
+
if (typeof value !== "boolean") {
|
|
136
|
+
throw new TypeError(`${key} \u5FC5\u987B\u662F\u5E03\u5C14\u503C`);
|
|
137
|
+
}
|
|
138
|
+
result[key] = value;
|
|
139
|
+
}
|
|
140
|
+
if (source.watermark !== void 0) {
|
|
141
|
+
if (!source.watermark || typeof source.watermark !== "object" || Array.isArray(source.watermark)) {
|
|
142
|
+
throw new TypeError("watermark \u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
143
|
+
}
|
|
144
|
+
const watermark = source.watermark;
|
|
145
|
+
if (typeof watermark.enabled !== "boolean" || typeof watermark.text !== "string" || watermark.text.length > 200) {
|
|
146
|
+
throw new TypeError("watermark \u914D\u7F6E\u65E0\u6548");
|
|
147
|
+
}
|
|
148
|
+
result.watermark = {
|
|
149
|
+
enabled: watermark.enabled,
|
|
150
|
+
text: watermark.text
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
return result;
|
|
154
|
+
}
|
|
155
|
+
function adjustColor(color, amount) {
|
|
156
|
+
if (typeof color !== "string") return "#000000";
|
|
157
|
+
if (!Number.isFinite(amount)) return color;
|
|
158
|
+
const normalizedAmount = Math.round(amount);
|
|
159
|
+
const trimmedColor = color.trim();
|
|
160
|
+
let hex = trimmedColor.startsWith("#") ? trimmedColor.slice(1) : trimmedColor;
|
|
161
|
+
if (hex.length === 3) {
|
|
162
|
+
hex = hex.split("").map((character) => character + character).join("");
|
|
163
|
+
}
|
|
164
|
+
if (!/^[0-9a-fA-F]{6}$/.test(hex)) return color;
|
|
165
|
+
const value = parseInt(hex, 16);
|
|
166
|
+
const red = Math.min(255, Math.max(0, (value >> 16) + normalizedAmount));
|
|
167
|
+
const green = Math.min(
|
|
168
|
+
255,
|
|
169
|
+
Math.max(0, (value >> 8 & 255) + normalizedAmount)
|
|
170
|
+
);
|
|
171
|
+
const blue = Math.min(
|
|
172
|
+
255,
|
|
173
|
+
Math.max(0, (value & 255) + normalizedAmount)
|
|
174
|
+
);
|
|
175
|
+
return `#${(red << 16 | green << 8 | blue).toString(16).padStart(6, "0")}`;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// src/constants/index.ts
|
|
179
|
+
var PRESET_COLORS = [
|
|
180
|
+
{ name: "\u62C2\u6653\u84DD", value: "#409eff" },
|
|
181
|
+
{ name: "\u8584\u66AE\u7EA2", value: "#f5222d" },
|
|
182
|
+
{ name: "\u706B\u5C71\u6A59", value: "#fa541c" },
|
|
183
|
+
{ name: "\u65E5\u66AE\u9EC4", value: "#faad14" },
|
|
184
|
+
{ name: "\u6781\u5149\u7EFF", value: "#52c41a" },
|
|
185
|
+
{ name: "\u660E\u9752", value: "#13c2c2" },
|
|
186
|
+
{ name: "\u6781\u5BA2\u84DD", value: "#2f54eb" },
|
|
187
|
+
{ name: "\u9171\u7D2B", value: "#722ed1" }
|
|
188
|
+
];
|
|
189
|
+
var THEME_PRESETS = [
|
|
190
|
+
{
|
|
191
|
+
name: "\u79D1\u6280\u84DD",
|
|
192
|
+
icon: "\u{1F499}",
|
|
193
|
+
primaryColor: "#409eff"
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
name: "\u6E05\u65B0\u7EFF",
|
|
197
|
+
icon: "\u{1F49A}",
|
|
198
|
+
primaryColor: "#52c41a"
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
name: "\u5546\u52A1\u7070",
|
|
202
|
+
icon: "\u{1F5A4}",
|
|
203
|
+
primaryColor: "#595959"
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
name: "\u6D3B\u529B\u6A59",
|
|
207
|
+
icon: "\u{1F9E1}",
|
|
208
|
+
primaryColor: "#fa8c16"
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
name: "\u4F18\u96C5\u7D2B",
|
|
212
|
+
icon: "\u{1F49C}",
|
|
213
|
+
primaryColor: "#722ed1"
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
name: "\u7ECF\u5178\u7EA2",
|
|
217
|
+
icon: "\u2764\uFE0F",
|
|
218
|
+
primaryColor: "#f5222d"
|
|
219
|
+
}
|
|
220
|
+
];
|
|
221
|
+
var LAYOUT_MODES = [
|
|
222
|
+
{
|
|
223
|
+
mode: "side",
|
|
224
|
+
label: "\u5DE6\u4FA7\u83DC\u5355",
|
|
225
|
+
description: "\u7ECF\u5178\u7684\u5DE6\u4FA7\u5BFC\u822A\u5E03\u5C40",
|
|
226
|
+
icon: "i-mdi:page-layout-sidebar-left"
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
mode: "top",
|
|
230
|
+
label: "\u9876\u90E8\u83DC\u5355",
|
|
231
|
+
description: "\u9876\u90E8\u6C34\u5E73\u5BFC\u822A\u5E03\u5C40",
|
|
232
|
+
icon: "i-mdi:page-layout-header"
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
mode: "mix",
|
|
236
|
+
label: "\u6DF7\u5408\u83DC\u5355",
|
|
237
|
+
description: "\u9876\u90E8 + \u4FA7\u8FB9\u6DF7\u5408\u5E03\u5C40",
|
|
238
|
+
icon: "i-mdi:view-dashboard-outline"
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
mode: "mix-top",
|
|
242
|
+
label: "\u9876\u90E8\u6DF7\u5408",
|
|
243
|
+
description: "\u4FA7\u8FB9\u4F18\u5148\u7684\u6DF7\u5408\u5E03\u5C40",
|
|
244
|
+
icon: "i-mdi:view-dashboard-variant-outline"
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
mode: "reverse-horizontal-mix",
|
|
248
|
+
label: "\u53CD\u8F6C\u6DF7\u5408",
|
|
249
|
+
description: "\u53CD\u8F6C\u7684\u6C34\u5E73\u6DF7\u5408\u5E03\u5C40",
|
|
250
|
+
icon: "i-mdi:page-layout-header-footer"
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
mode: "card-layout",
|
|
254
|
+
label: "\u5361\u7247\u5E03\u5C40",
|
|
255
|
+
description: "\u5361\u7247\u5F0F\u5E03\u5C40\u98CE\u683C",
|
|
256
|
+
icon: "i-mdi:card-outline"
|
|
257
|
+
}
|
|
258
|
+
];
|
|
259
|
+
var BORDER_RADIUS_MAP = {
|
|
260
|
+
small: "4px",
|
|
261
|
+
medium: "6px",
|
|
262
|
+
large: "8px"
|
|
263
|
+
};
|
|
264
|
+
var TRANSITION_MAP = {
|
|
265
|
+
fade: "fade-transform",
|
|
266
|
+
slide: "fade-slide",
|
|
267
|
+
zoom: "fade-zoom",
|
|
268
|
+
none: ""
|
|
269
|
+
};
|
|
270
|
+
var DEFAULT_SETTINGS = {
|
|
271
|
+
// 外观
|
|
272
|
+
themeMode: "light",
|
|
273
|
+
primaryColor: "#409eff",
|
|
274
|
+
borderRadius: "medium",
|
|
275
|
+
transitionType: "slide",
|
|
276
|
+
enableTransition: true,
|
|
277
|
+
// 布局
|
|
278
|
+
layoutMode: "side",
|
|
279
|
+
menuExpandMode: "inline",
|
|
280
|
+
collapsed: false,
|
|
281
|
+
fixedHeader: true,
|
|
282
|
+
showBreadcrumb: true,
|
|
283
|
+
showBreadcrumbIcon: true,
|
|
284
|
+
showTagsView: true,
|
|
285
|
+
tagsViewHeight: 44,
|
|
286
|
+
tagsViewStyle: "default",
|
|
287
|
+
showFooter: true,
|
|
288
|
+
sidebarWidth: 220,
|
|
289
|
+
sidebarCollapsedWidth: 64,
|
|
290
|
+
headerHeight: 56,
|
|
291
|
+
// 高级
|
|
292
|
+
enableHotkeys: true,
|
|
293
|
+
version: "3.1.0"
|
|
294
|
+
};
|
|
295
|
+
var COLOR_SWATCHES = PRESET_COLORS.map((c) => c.value);
|
|
296
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
297
|
+
0 && (module.exports = {
|
|
298
|
+
BORDER_RADIUS_MAP,
|
|
299
|
+
COLOR_SWATCHES,
|
|
300
|
+
DEFAULT_SETTINGS,
|
|
301
|
+
LAYOUT_MODES,
|
|
302
|
+
PRESET_COLORS,
|
|
303
|
+
SETTINGS_CONFIG_SCHEMA_VERSION,
|
|
304
|
+
THEME_PRESETS,
|
|
305
|
+
TRANSITION_MAP,
|
|
306
|
+
adjustColor,
|
|
307
|
+
sanitizeLayoutSettingsConfig,
|
|
308
|
+
sanitizeSettingsPatch
|
|
309
|
+
});
|
|
310
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +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.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":[]}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/** 与具体主题实现无关的标准主题模式。 */
|
|
2
|
+
type ThemeMode = "light" | "dark" | "system";
|
|
3
|
+
/** 内置布局模式。 */
|
|
4
|
+
type LayoutMode = "side" | "top" | "mix" | "mix-top" | "reverse-horizontal-mix" | "card-layout";
|
|
5
|
+
/** 菜单展开方式。 */
|
|
6
|
+
type MenuExpandMode = "inline" | "panel";
|
|
7
|
+
/** 页面动画类型。 */
|
|
8
|
+
type TransitionType = "fade" | "slide" | "zoom" | "none";
|
|
9
|
+
/** 圆角大小。 */
|
|
10
|
+
type BorderRadiusSize = "small" | "medium" | "large";
|
|
11
|
+
/** 标签页风格。 */
|
|
12
|
+
type TagsViewStyle = "default" | "card" | "smart";
|
|
13
|
+
/** UI 无关的布局设置协议。 */
|
|
14
|
+
interface SettingsState {
|
|
15
|
+
themeMode: ThemeMode;
|
|
16
|
+
primaryColor: string;
|
|
17
|
+
borderRadius: BorderRadiusSize;
|
|
18
|
+
transitionType: TransitionType;
|
|
19
|
+
enableTransition: boolean;
|
|
20
|
+
layoutMode: LayoutMode;
|
|
21
|
+
menuExpandMode: MenuExpandMode;
|
|
22
|
+
collapsed: boolean;
|
|
23
|
+
fixedHeader: boolean;
|
|
24
|
+
showBreadcrumb: boolean;
|
|
25
|
+
showBreadcrumbIcon: boolean;
|
|
26
|
+
showTagsView: boolean;
|
|
27
|
+
tagsViewHeight: number;
|
|
28
|
+
tagsViewStyle: TagsViewStyle;
|
|
29
|
+
showFooter: boolean;
|
|
30
|
+
sidebarWidth: number;
|
|
31
|
+
sidebarCollapsedWidth: number;
|
|
32
|
+
headerHeight: number;
|
|
33
|
+
enableHotkeys: boolean;
|
|
34
|
+
version: string;
|
|
35
|
+
}
|
|
36
|
+
/** 主题预设方案。 */
|
|
37
|
+
interface ThemePreset {
|
|
38
|
+
name: string;
|
|
39
|
+
description?: string;
|
|
40
|
+
icon: string;
|
|
41
|
+
primaryColor: string;
|
|
42
|
+
settings?: Partial<Omit<SettingsState, "themeMode" | "layoutMode" | "primaryColor">>;
|
|
43
|
+
}
|
|
44
|
+
/** Settings Store 初始化选项。 */
|
|
45
|
+
interface SettingsStoreOptions {
|
|
46
|
+
id?: string;
|
|
47
|
+
defaults?: Partial<SettingsState>;
|
|
48
|
+
onThemeModeChange?: (mode: ThemeMode) => void | Promise<void>;
|
|
49
|
+
}
|
|
50
|
+
/** 由宿主应用实现的高副作用操作。 */
|
|
51
|
+
interface SettingsDrawerActions {
|
|
52
|
+
clearCache?: () => void | Promise<void>;
|
|
53
|
+
reloadPage?: () => void;
|
|
54
|
+
}
|
|
55
|
+
/** 布局模式展示信息。 */
|
|
56
|
+
interface LayoutInfo {
|
|
57
|
+
mode: LayoutMode;
|
|
58
|
+
label: string;
|
|
59
|
+
description: string;
|
|
60
|
+
icon: string;
|
|
61
|
+
}
|
|
62
|
+
/** 预设颜色。 */
|
|
63
|
+
interface PresetColor {
|
|
64
|
+
name: string;
|
|
65
|
+
value: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** 当前导入导出配置格式版本。 */
|
|
69
|
+
declare const SETTINGS_CONFIG_SCHEMA_VERSION: 1;
|
|
70
|
+
interface LayoutVisualEffects {
|
|
71
|
+
gray?: boolean;
|
|
72
|
+
colorWeak?: boolean;
|
|
73
|
+
watermark?: {
|
|
74
|
+
enabled: boolean;
|
|
75
|
+
text: string;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/** 经校验后可原子应用的布局配置。 */
|
|
79
|
+
interface LayoutSettingsConfig extends LayoutVisualEffects {
|
|
80
|
+
schemaVersion?: number;
|
|
81
|
+
settings?: Partial<SettingsState>;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* 校验来自配置文件等不可信来源的设置。
|
|
85
|
+
* 未知键为向前兼容而忽略;已知键的非法值会让整次导入失败。
|
|
86
|
+
*/
|
|
87
|
+
declare function sanitizeSettingsPatch(input: unknown): Partial<SettingsState>;
|
|
88
|
+
/**
|
|
89
|
+
* 一次性校验完整导入文件。此函数不修改任何响应式状态或浏览器 API,
|
|
90
|
+
* 消费方可以在成功返回后再原子应用结果。
|
|
91
|
+
*/
|
|
92
|
+
declare function sanitizeLayoutSettingsConfig(input: unknown): LayoutSettingsConfig;
|
|
93
|
+
/**
|
|
94
|
+
* 调整颜色亮度。
|
|
95
|
+
* @returns 调整后的 #rrggbb;输入非法时原样返回。
|
|
96
|
+
*/
|
|
97
|
+
declare function adjustColor(color: string, amount: number): string;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* 布局和设置系统 - 常量定义
|
|
101
|
+
*/
|
|
102
|
+
|
|
103
|
+
declare const PRESET_COLORS: PresetColor[];
|
|
104
|
+
declare const THEME_PRESETS: ThemePreset[];
|
|
105
|
+
declare const LAYOUT_MODES: LayoutInfo[];
|
|
106
|
+
declare const BORDER_RADIUS_MAP: {
|
|
107
|
+
readonly small: "4px";
|
|
108
|
+
readonly medium: "6px";
|
|
109
|
+
readonly large: "8px";
|
|
110
|
+
};
|
|
111
|
+
declare const TRANSITION_MAP: {
|
|
112
|
+
readonly fade: "fade-transform";
|
|
113
|
+
readonly slide: "fade-slide";
|
|
114
|
+
readonly zoom: "fade-zoom";
|
|
115
|
+
readonly none: "";
|
|
116
|
+
};
|
|
117
|
+
declare const DEFAULT_SETTINGS: SettingsState;
|
|
118
|
+
/** Color swatches for color picker */
|
|
119
|
+
declare const COLOR_SWATCHES: string[];
|
|
120
|
+
|
|
121
|
+
export { BORDER_RADIUS_MAP, type BorderRadiusSize, COLOR_SWATCHES, DEFAULT_SETTINGS, LAYOUT_MODES, type LayoutInfo, type LayoutMode, type LayoutSettingsConfig, type LayoutVisualEffects, type MenuExpandMode, PRESET_COLORS, type PresetColor, SETTINGS_CONFIG_SCHEMA_VERSION, type SettingsDrawerActions, type SettingsState, type SettingsStoreOptions, THEME_PRESETS, TRANSITION_MAP, type TagsViewStyle, type ThemeMode, type ThemePreset, type TransitionType, adjustColor, sanitizeLayoutSettingsConfig, sanitizeSettingsPatch };
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/** 与具体主题实现无关的标准主题模式。 */
|
|
2
|
+
type ThemeMode = "light" | "dark" | "system";
|
|
3
|
+
/** 内置布局模式。 */
|
|
4
|
+
type LayoutMode = "side" | "top" | "mix" | "mix-top" | "reverse-horizontal-mix" | "card-layout";
|
|
5
|
+
/** 菜单展开方式。 */
|
|
6
|
+
type MenuExpandMode = "inline" | "panel";
|
|
7
|
+
/** 页面动画类型。 */
|
|
8
|
+
type TransitionType = "fade" | "slide" | "zoom" | "none";
|
|
9
|
+
/** 圆角大小。 */
|
|
10
|
+
type BorderRadiusSize = "small" | "medium" | "large";
|
|
11
|
+
/** 标签页风格。 */
|
|
12
|
+
type TagsViewStyle = "default" | "card" | "smart";
|
|
13
|
+
/** UI 无关的布局设置协议。 */
|
|
14
|
+
interface SettingsState {
|
|
15
|
+
themeMode: ThemeMode;
|
|
16
|
+
primaryColor: string;
|
|
17
|
+
borderRadius: BorderRadiusSize;
|
|
18
|
+
transitionType: TransitionType;
|
|
19
|
+
enableTransition: boolean;
|
|
20
|
+
layoutMode: LayoutMode;
|
|
21
|
+
menuExpandMode: MenuExpandMode;
|
|
22
|
+
collapsed: boolean;
|
|
23
|
+
fixedHeader: boolean;
|
|
24
|
+
showBreadcrumb: boolean;
|
|
25
|
+
showBreadcrumbIcon: boolean;
|
|
26
|
+
showTagsView: boolean;
|
|
27
|
+
tagsViewHeight: number;
|
|
28
|
+
tagsViewStyle: TagsViewStyle;
|
|
29
|
+
showFooter: boolean;
|
|
30
|
+
sidebarWidth: number;
|
|
31
|
+
sidebarCollapsedWidth: number;
|
|
32
|
+
headerHeight: number;
|
|
33
|
+
enableHotkeys: boolean;
|
|
34
|
+
version: string;
|
|
35
|
+
}
|
|
36
|
+
/** 主题预设方案。 */
|
|
37
|
+
interface ThemePreset {
|
|
38
|
+
name: string;
|
|
39
|
+
description?: string;
|
|
40
|
+
icon: string;
|
|
41
|
+
primaryColor: string;
|
|
42
|
+
settings?: Partial<Omit<SettingsState, "themeMode" | "layoutMode" | "primaryColor">>;
|
|
43
|
+
}
|
|
44
|
+
/** Settings Store 初始化选项。 */
|
|
45
|
+
interface SettingsStoreOptions {
|
|
46
|
+
id?: string;
|
|
47
|
+
defaults?: Partial<SettingsState>;
|
|
48
|
+
onThemeModeChange?: (mode: ThemeMode) => void | Promise<void>;
|
|
49
|
+
}
|
|
50
|
+
/** 由宿主应用实现的高副作用操作。 */
|
|
51
|
+
interface SettingsDrawerActions {
|
|
52
|
+
clearCache?: () => void | Promise<void>;
|
|
53
|
+
reloadPage?: () => void;
|
|
54
|
+
}
|
|
55
|
+
/** 布局模式展示信息。 */
|
|
56
|
+
interface LayoutInfo {
|
|
57
|
+
mode: LayoutMode;
|
|
58
|
+
label: string;
|
|
59
|
+
description: string;
|
|
60
|
+
icon: string;
|
|
61
|
+
}
|
|
62
|
+
/** 预设颜色。 */
|
|
63
|
+
interface PresetColor {
|
|
64
|
+
name: string;
|
|
65
|
+
value: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** 当前导入导出配置格式版本。 */
|
|
69
|
+
declare const SETTINGS_CONFIG_SCHEMA_VERSION: 1;
|
|
70
|
+
interface LayoutVisualEffects {
|
|
71
|
+
gray?: boolean;
|
|
72
|
+
colorWeak?: boolean;
|
|
73
|
+
watermark?: {
|
|
74
|
+
enabled: boolean;
|
|
75
|
+
text: string;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/** 经校验后可原子应用的布局配置。 */
|
|
79
|
+
interface LayoutSettingsConfig extends LayoutVisualEffects {
|
|
80
|
+
schemaVersion?: number;
|
|
81
|
+
settings?: Partial<SettingsState>;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* 校验来自配置文件等不可信来源的设置。
|
|
85
|
+
* 未知键为向前兼容而忽略;已知键的非法值会让整次导入失败。
|
|
86
|
+
*/
|
|
87
|
+
declare function sanitizeSettingsPatch(input: unknown): Partial<SettingsState>;
|
|
88
|
+
/**
|
|
89
|
+
* 一次性校验完整导入文件。此函数不修改任何响应式状态或浏览器 API,
|
|
90
|
+
* 消费方可以在成功返回后再原子应用结果。
|
|
91
|
+
*/
|
|
92
|
+
declare function sanitizeLayoutSettingsConfig(input: unknown): LayoutSettingsConfig;
|
|
93
|
+
/**
|
|
94
|
+
* 调整颜色亮度。
|
|
95
|
+
* @returns 调整后的 #rrggbb;输入非法时原样返回。
|
|
96
|
+
*/
|
|
97
|
+
declare function adjustColor(color: string, amount: number): string;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* 布局和设置系统 - 常量定义
|
|
101
|
+
*/
|
|
102
|
+
|
|
103
|
+
declare const PRESET_COLORS: PresetColor[];
|
|
104
|
+
declare const THEME_PRESETS: ThemePreset[];
|
|
105
|
+
declare const LAYOUT_MODES: LayoutInfo[];
|
|
106
|
+
declare const BORDER_RADIUS_MAP: {
|
|
107
|
+
readonly small: "4px";
|
|
108
|
+
readonly medium: "6px";
|
|
109
|
+
readonly large: "8px";
|
|
110
|
+
};
|
|
111
|
+
declare const TRANSITION_MAP: {
|
|
112
|
+
readonly fade: "fade-transform";
|
|
113
|
+
readonly slide: "fade-slide";
|
|
114
|
+
readonly zoom: "fade-zoom";
|
|
115
|
+
readonly none: "";
|
|
116
|
+
};
|
|
117
|
+
declare const DEFAULT_SETTINGS: SettingsState;
|
|
118
|
+
/** Color swatches for color picker */
|
|
119
|
+
declare const COLOR_SWATCHES: string[];
|
|
120
|
+
|
|
121
|
+
export { BORDER_RADIUS_MAP, type BorderRadiusSize, COLOR_SWATCHES, DEFAULT_SETTINGS, LAYOUT_MODES, type LayoutInfo, type LayoutMode, type LayoutSettingsConfig, type LayoutVisualEffects, type MenuExpandMode, PRESET_COLORS, type PresetColor, SETTINGS_CONFIG_SCHEMA_VERSION, type SettingsDrawerActions, type SettingsState, type SettingsStoreOptions, THEME_PRESETS, TRANSITION_MAP, type TagsViewStyle, type ThemeMode, type ThemePreset, type TransitionType, adjustColor, sanitizeLayoutSettingsConfig, sanitizeSettingsPatch };
|