create-secra 0.1.11 → 1.0.2

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.
Files changed (133) hide show
  1. package/README.md +15 -5
  2. package/README.zh-CN.md +15 -4
  3. package/antd-adapter-template/README.md +24 -0
  4. package/antd-adapter-template/index.html +16 -0
  5. package/antd-adapter-template/package-lock.json +3420 -0
  6. package/antd-adapter-template/package.json +20 -47
  7. package/antd-adapter-template/src/app/App.tsx +7 -0
  8. package/antd-adapter-template/src/app/layouts/AppLayout.tsx +163 -0
  9. package/antd-adapter-template/src/app/router.ts +26 -0
  10. package/antd-adapter-template/src/app/routes/RouteTitleSync.tsx +26 -0
  11. package/antd-adapter-template/src/app/routes/dynamic-routes.ts +52 -0
  12. package/antd-adapter-template/src/app/routes/route-modules.ts +4 -0
  13. package/antd-adapter-template/src/app/routes/static-routes.tsx +110 -0
  14. package/antd-adapter-template/src/app/routes/types.ts +9 -0
  15. package/antd-adapter-template/src/features/auth/api/auth-api.ts +61 -0
  16. package/antd-adapter-template/src/features/auth/auth-store.ts +125 -0
  17. package/antd-adapter-template/src/features/auth/auth-types.ts +29 -0
  18. package/antd-adapter-template/src/features/auth/authorization.ts +46 -0
  19. package/antd-adapter-template/src/features/auth/use-auth.ts +10 -0
  20. package/antd-adapter-template/src/main.tsx +79 -0
  21. package/antd-adapter-template/src/pages/dashboard/DashboardPage.tsx +105 -0
  22. package/antd-adapter-template/src/pages/errors/ForbiddenPage.tsx +36 -0
  23. package/antd-adapter-template/src/pages/errors/NotFoundPage.tsx +36 -0
  24. package/antd-adapter-template/src/pages/home/HomePage.tsx +129 -0
  25. package/antd-adapter-template/src/pages/login/LoginPage.tsx +128 -0
  26. package/antd-adapter-template/src/pages/permission-test/PermissionTestPage.tsx +55 -0
  27. package/antd-adapter-template/src/pages/restricted/RestrictedDemoPage.tsx +17 -0
  28. package/antd-adapter-template/src/shared/kernel/app-kernel.ts +10 -0
  29. package/antd-adapter-template/src/shared/request/client.ts +46 -0
  30. package/antd-adapter-template/src/shared/request/contracts.ts +6 -0
  31. package/antd-adapter-template/src/shared/request/kv-adapter.ts +14 -0
  32. package/antd-adapter-template/src/shared/request/kv-backend.ts +244 -0
  33. package/antd-adapter-template/src/shared/request/ky-browser-stub.ts +6 -0
  34. package/antd-adapter-template/src/shared/request/undici-browser-stub.ts +4 -0
  35. package/antd-adapter-template/src/styles/global.css +185 -0
  36. package/antd-adapter-template/src/vite-env.d.ts +2 -0
  37. package/antd-adapter-template/tsconfig.app.json +10 -13
  38. package/antd-adapter-template/tsconfig.json +7 -2
  39. package/antd-adapter-template/tsconfig.node.json +6 -16
  40. package/antd-adapter-template/vite.config.ts +24 -0
  41. package/bin/index.mjs +32 -14
  42. package/package.json +2 -2
  43. package/{antd-adapter-template/apps/core → template}/index.html +2 -3
  44. package/template/package.json +14 -46
  45. package/template/src/App.tsx +48 -0
  46. package/template/src/main.tsx +36 -0
  47. package/template/src/styles.css +163 -0
  48. package/template/src/vite-env.d.ts +1 -0
  49. package/template/tsconfig.app.json +0 -5
  50. package/template/tsconfig.node.json +0 -5
  51. package/template/vite.config.ts +6 -0
  52. package/antd-adapter-template/apps/core/package.json +0 -18
  53. package/antd-adapter-template/apps/core/public/favicon.ico +0 -1
  54. package/antd-adapter-template/apps/core/public/favicon.svg +0 -1
  55. package/antd-adapter-template/apps/core/public/logo.svg +0 -1
  56. package/antd-adapter-template/apps/core/src/api/auth.ts +0 -49
  57. package/antd-adapter-template/apps/core/src/assets/react.svg +0 -1
  58. package/antd-adapter-template/apps/core/src/components/AntdGlobalProvider.tsx +0 -87
  59. package/antd-adapter-template/apps/core/src/components/AntdRootLayout.tsx +0 -10
  60. package/antd-adapter-template/apps/core/src/components/layout.tsx +0 -387
  61. package/antd-adapter-template/apps/core/src/guards/auth-route-guard.ts +0 -45
  62. package/antd-adapter-template/apps/core/src/main.tsx +0 -65
  63. package/antd-adapter-template/apps/core/src/pages/auth/components/account-login-fields.tsx +0 -60
  64. package/antd-adapter-template/apps/core/src/pages/auth/components/phone-login-fields.tsx +0 -60
  65. package/antd-adapter-template/apps/core/src/pages/auth/login.tsx +0 -169
  66. package/antd-adapter-template/apps/core/src/pages/index.tsx +0 -156
  67. package/antd-adapter-template/apps/core/src/router.ts +0 -42
  68. package/antd-adapter-template/apps/core/src/shims/use-sync-external-store-shim.ts +0 -3
  69. package/antd-adapter-template/apps/core/src/theme/theme.css +0 -48
  70. package/antd-adapter-template/apps/core/src/types/crypto-js.d.ts +0 -5
  71. package/antd-adapter-template/apps/core/src/utils/index.ts +0 -12
  72. package/antd-adapter-template/apps/core/src/utils/md5.ts +0 -6
  73. package/antd-adapter-template/apps/core/tsconfig.app.json +0 -11
  74. package/antd-adapter-template/apps/core/tsconfig.json +0 -13
  75. package/antd-adapter-template/apps/core/tsconfig.node.json +0 -7
  76. package/antd-adapter-template/apps/core/vite.config.ts +0 -118
  77. package/antd-adapter-template/eslint.config.js +0 -23
  78. package/antd-adapter-template/packages/sdk/.swcrc +0 -18
  79. package/antd-adapter-template/packages/sdk/package.json +0 -52
  80. package/antd-adapter-template/packages/sdk/src/build/index.ts +0 -28
  81. package/antd-adapter-template/packages/sdk/src/build/plugins/auto-import.ts +0 -46
  82. package/antd-adapter-template/packages/sdk/src/build/plugins/bundle-analyzer.ts +0 -33
  83. package/antd-adapter-template/packages/sdk/src/build/plugins/remove-console.ts +0 -23
  84. package/antd-adapter-template/packages/sdk/src/build/plugins/unocss.ts +0 -202
  85. package/antd-adapter-template/packages/sdk/src/build/plugins/unplugin-icon.ts +0 -43
  86. package/antd-adapter-template/packages/sdk/src/components/i18n-switch-dropdown.tsx +0 -139
  87. package/antd-adapter-template/packages/sdk/src/components/index.ts +0 -2
  88. package/antd-adapter-template/packages/sdk/src/components/theme-switch-dropdown.tsx +0 -131
  89. package/antd-adapter-template/packages/sdk/src/hooks/auth/core.ts +0 -101
  90. package/antd-adapter-template/packages/sdk/src/hooks/auth/index.ts +0 -139
  91. package/antd-adapter-template/packages/sdk/src/hooks/auth/with-auth.tsx +0 -41
  92. package/antd-adapter-template/packages/sdk/src/hooks/index.ts +0 -1
  93. package/antd-adapter-template/packages/sdk/src/i18n/index.ts +0 -150
  94. package/antd-adapter-template/packages/sdk/src/index.ts +0 -11
  95. package/antd-adapter-template/packages/sdk/src/request/index.ts +0 -436
  96. package/antd-adapter-template/packages/sdk/src/storage/README.md +0 -30
  97. package/antd-adapter-template/packages/sdk/src/storage/index.ts +0 -57
  98. package/antd-adapter-template/packages/sdk/src/styles/reset.css +0 -111
  99. package/antd-adapter-template/packages/sdk/src/theme/index.ts +0 -466
  100. package/antd-adapter-template/packages/sdk/tsconfig.json +0 -16
  101. package/antd-adapter-template/pnpm-workspace.yaml +0 -3
  102. package/antd-adapter-template/turbo.json +0 -17
  103. package/template/apps/core/index.html +0 -13
  104. package/template/apps/core/package.json +0 -18
  105. package/template/apps/core/public/favicon.ico +0 -1
  106. package/template/apps/core/public/favicon.svg +0 -1
  107. package/template/apps/core/public/logo.svg +0 -1
  108. package/template/apps/core/src/assets/react.svg +0 -1
  109. package/template/apps/core/src/main.tsx +0 -14
  110. package/template/apps/core/src/pages/index.tsx +0 -84
  111. package/template/apps/core/src/router.ts +0 -19
  112. package/template/apps/core/src/types/auto-imports.d.ts +0 -130
  113. package/template/apps/core/tsconfig.app.json +0 -7
  114. package/template/apps/core/tsconfig.json +0 -7
  115. package/template/apps/core/tsconfig.node.json +0 -7
  116. package/template/apps/core/vite.config.ts +0 -86
  117. package/template/eslint.config.js +0 -23
  118. package/template/packages/sdk/.swcrc +0 -18
  119. package/template/packages/sdk/package-lock.json +0 -1621
  120. package/template/packages/sdk/package.json +0 -32
  121. package/template/packages/sdk/src/build/index.ts +0 -33
  122. package/template/packages/sdk/src/build/plugins/auto-import.ts +0 -47
  123. package/template/packages/sdk/src/build/plugins/bundle-analyzer.ts +0 -35
  124. package/template/packages/sdk/src/build/plugins/remove-console.ts +0 -21
  125. package/template/packages/sdk/src/build/plugins/unocss.ts +0 -113
  126. package/template/packages/sdk/src/build/plugins/unplugin-icon.ts +0 -43
  127. package/template/packages/sdk/src/index.ts +0 -1
  128. package/template/packages/sdk/src/request/index.ts +0 -341
  129. package/template/packages/sdk/src/styles/reset.css +0 -111
  130. package/template/packages/sdk/tsconfig.json +0 -16
  131. package/template/pnpm-lock.yaml +0 -8055
  132. package/template/pnpm-workspace.yaml +0 -3
  133. package/template/turbo.json +0 -17
@@ -1,23 +0,0 @@
1
- import js from '@eslint/js'
2
- import globals from 'globals'
3
- import reactHooks from 'eslint-plugin-react-hooks'
4
- import reactRefresh from 'eslint-plugin-react-refresh'
5
- import tseslint from 'typescript-eslint'
6
- import { defineConfig, globalIgnores } from 'eslint/config'
7
-
8
- export default defineConfig([
9
- globalIgnores(['dist']),
10
- {
11
- files: ['**/*.{ts,tsx}'],
12
- extends: [
13
- js.configs.recommended,
14
- tseslint.configs.recommended,
15
- reactHooks.configs.flat.recommended,
16
- reactRefresh.configs.vite,
17
- ],
18
- languageOptions: {
19
- ecmaVersion: 2020,
20
- globals: globals.browser,
21
- },
22
- },
23
- ])
@@ -1,18 +0,0 @@
1
- {
2
- "jsc": {
3
- "target": "es2022",
4
- "parser": {
5
- "syntax": "typescript",
6
- "tsx": true
7
- },
8
- "transform": {
9
- "react": {
10
- "runtime": "automatic"
11
- }
12
- }
13
- },
14
- "module": {
15
- "type": "es6"
16
- },
17
- "sourceMaps": true
18
- }
@@ -1,52 +0,0 @@
1
- {
2
- "name": "@vlian/sdk",
3
- "version": "1.0.15",
4
- "description": "",
5
- "main": "dist/index.js",
6
- "type": "module",
7
- "types": "dist/types/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "types": "./dist/types/index.d.ts",
11
- "import": "./dist/index.js",
12
- "default": "./dist/index.js"
13
- },
14
- "./request": {
15
- "types": "./dist/types/request/index.d.ts",
16
- "import": "./dist/request/index.js",
17
- "default": "./dist/request/index.js"
18
- },
19
- "./build": {
20
- "types": "./dist/types/build/index.d.ts",
21
- "import": "./dist/build/index.js",
22
- "default": "./dist/build/index.js"
23
- },
24
- "./i18n": {
25
- "types": "./dist/types/i18n/index.d.ts",
26
- "import": "./dist/i18n/index.js",
27
- "default": "./dist/i18n/index.js"
28
- },
29
- "./hooks": {
30
- "types": "./dist/types/hooks/index.d.ts",
31
- "import": "./dist/hooks/index.js",
32
- "default": "./dist/hooks/index.js"
33
- },
34
- "./hooks/auth": {
35
- "types": "./dist/types/hooks/auth/index.d.ts",
36
- "import": "./dist/hooks/auth/index.js",
37
- "default": "./dist/hooks/auth/index.js"
38
- },
39
- "./reset.css": "./dist/styles/reset.css"
40
- },
41
- "scripts": {
42
- "build": "pnpm run build:js && pnpm run build:types && pnpm run build:assets",
43
- "build:js": "swc src -d dist --config-file .swcrc --source-maps --strip-leading-paths",
44
- "build:types": "tsc -p tsconfig.json --emitDeclarationOnly --declaration --declarationMap --outDir dist/types",
45
- "build:assets": "mkdir -p dist/styles && cp src/styles/reset.css dist/styles/reset.css"
46
- },
47
- "devDependencies": {
48
- "@swc/cli": "^0.7.3",
49
- "@swc/core": "^1.13.5"
50
- },
51
- "private": true
52
- }
@@ -1,28 +0,0 @@
1
- /**
2
- * @vlian/sdk/build
3
- * 构建工具和配置共享包
4
- *
5
- * 通过子路径 @vlian/sdk/build 暴露,避免污染根入口运行时依赖。
6
- */
7
-
8
- // 导出版本
9
- export const version = '0.0.1';
10
-
11
- // 插件导出
12
- export { setupAutoImport } from './plugins/auto-import.js';
13
- export { setupUnocss } from './plugins/unocss.js';
14
- export { setupUnPluginIcon } from './plugins/unplugin-icon.js';
15
- export { setupRemoveConsole } from './plugins/remove-console.js';
16
- export { setupBundleAnalyzer } from './plugins/bundle-analyzer.js';
17
-
18
- // 依赖优化列表(用于 optimizeDeps.include)
19
- export const include = [
20
- 'ahooks',
21
- 'i18next',
22
- 'lodash',
23
- 'immer',
24
- 'react-i18next',
25
- ] as const;
26
-
27
- // 类型导出
28
- export type { UserConfig } from '@unocss/core';
@@ -1,46 +0,0 @@
1
- import AutoImport from 'unplugin-auto-import/vite';
2
- import IconsResolver from 'unplugin-icons/resolver';
3
-
4
- /**
5
- * 自动导入配置
6
- *
7
- * 功能:
8
- * - 自动导入 React、React Router、ahooks 等常用库
9
- * - 自动导入图标组件
10
- * - 自动导入自定义 hooks 和组件
11
- */
12
- export function setupAutoImport() {
13
- return AutoImport({
14
- // 扫描目录,自动导入 hooks 和组件
15
- dirs: ['src/hooks/**', 'src/components/**'],
16
-
17
- // 自动导入类型声明文件
18
- dts: 'src/types/auto-imports.d.ts',
19
-
20
- // 自动导入的库
21
- imports: [
22
- 'react',
23
- 'react-router-dom',
24
- 'react-i18next',
25
- 'ahooks',
26
- // React 类型导入
27
- { from: 'react', imports: ['FC', 'ReactNode', 'ComponentType'], type: true },
28
- ],
29
-
30
- // 匹配的文件
31
- include: [/\.[tj]sx?$/],
32
-
33
- // 排除的文件(排除文档文件和其他非代码文件)
34
- exclude: [/\.md$/, /\.d\.ts$/, /\.test\.(ts|tsx)$/, /\.spec\.(ts|tsx)$/],
35
-
36
- // 解析器
37
- resolvers: [
38
- // 图标解析器
39
- IconsResolver({
40
- customCollections: ['local'],
41
- extension: 'tsx',
42
- prefix: 'icon',
43
- }),
44
- ],
45
- });
46
- }
@@ -1,33 +0,0 @@
1
- import { visualizer } from 'rollup-plugin-visualizer';
2
-
3
- /**
4
- * 打包分析插件
5
- *
6
- * 功能:
7
- * - 生成打包分析报告
8
- * - 可视化 bundle 大小
9
- * - 帮助优化打包体积
10
- *
11
- * @param options - 配置选项
12
- * @returns Vite 插件
13
- */
14
- export function setupBundleAnalyzer(options?: {
15
- /** 输出文件名(默认: stats.html) */
16
- filename?: string;
17
- /** 是否自动打开浏览器 */
18
- open?: boolean;
19
- /** 输出格式(默认: html) */
20
- template?: 'treemap' | 'sunburst' | 'network';
21
- /** 是否 gzip 压缩 */
22
- gzipSize?: boolean;
23
- /** 是否 brotli 压缩 */
24
- brotliSize?: boolean;
25
- }) {
26
- return visualizer({
27
- filename: options?.filename || 'dist/stats.html',
28
- open: options?.open ?? false,
29
- template: options?.template || 'treemap',
30
- gzipSize: options?.gzipSize ?? true,
31
- brotliSize: options?.brotliSize ?? true,
32
- });
33
- }
@@ -1,23 +0,0 @@
1
- import removeConsole from 'vite-plugin-remove-console';
2
-
3
- /**
4
- * 移除 console 插件
5
- *
6
- * 功能:
7
- * - 生产环境自动移除 console 语句
8
- * - 提升生产环境性能
9
- *
10
- * @param options - 配置选项
11
- * @returns Vite 插件
12
- */
13
- export function setupRemoveConsole(options?: {
14
- /** 需要移除的 console 方法(兼容旧字段 include) */
15
- methods?: string[];
16
- /** @deprecated 请改用 methods */
17
- include?: string[];
18
- }) {
19
- const methods = options?.methods ?? options?.include ?? ['log', 'info', 'debug', 'warn'];
20
- return removeConsole({
21
- external: methods,
22
- });
23
- }
@@ -1,202 +0,0 @@
1
- import { FileSystemIconLoader } from '@iconify/utils/lib/loader/node-loaders';
2
- import presetAttributify from '@unocss/preset-attributify';
3
- import presetIcons from '@unocss/preset-icons';
4
- import presetUno from '@unocss/preset-uno';
5
- import transformerDirectives from '@unocss/transformer-directives';
6
- import transformerVariantGroup from '@unocss/transformer-variant-group';
7
- import unocss from '@unocss/vite';
8
- import type { UserConfig } from '@unocss/core';
9
-
10
- type ShortcutMap = Record<string, string>;
11
-
12
- const DEFAULT_BREAKPOINTS = {
13
- xs: '320px',
14
- sm: '640px',
15
- md: '768px',
16
- lg: '1024px',
17
- xl: '1280px',
18
- '2xl': '1536px',
19
- } as const;
20
-
21
- const DEFAULT_SHORTCUTS: ShortcutMap = {
22
- btn: 'px-4 py-2 rounded font-semibold transition-colors duration-200',
23
- 'btn-primary': 'btn bg-primary-500 text-white hover:bg-primary-600 active:bg-primary-700',
24
- 'btn-secondary': 'btn bg-gray-500 text-white hover:bg-gray-600 active:bg-gray-700',
25
- 'btn-success': 'btn bg-success-500 text-white hover:bg-success-600 active:bg-success-700',
26
- 'btn-warning': 'btn bg-warning-500 text-white hover:bg-warning-600 active:bg-warning-700',
27
- 'btn-error': 'btn bg-error-500 text-white hover:bg-error-600 active:bg-error-700',
28
- 'btn-outline': 'btn border-2 bg-transparent hover:bg-gray-100',
29
- 'btn-ghost': 'btn bg-transparent hover:bg-gray-100',
30
- container: 'mx-auto px-4 sm:px-6 lg:px-8',
31
- 'container-sm': 'mx-auto px-4 sm:px-6 max-w-screen-sm',
32
- 'container-md': 'mx-auto px-4 sm:px-6 max-w-screen-md',
33
- 'container-lg': 'mx-auto px-4 sm:px-6 max-w-screen-lg',
34
- 'container-xl': 'mx-auto px-4 sm:px-6 max-w-screen-xl',
35
- card: 'bg-white rounded-lg shadow-sm border border-gray-200',
36
- 'card-header': 'px-6 py-4 border-b border-gray-200',
37
- 'card-body': 'px-6 py-4',
38
- 'card-footer': 'px-6 py-4 border-t border-gray-200',
39
- input: 'px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent',
40
- 'input-error': 'input border-error-500 focus:ring-error-500',
41
- 'flex-center': 'flex items-center justify-center',
42
- 'flex-between': 'flex items-center justify-between',
43
- 'flex-start': 'flex items-center justify-start',
44
- 'flex-end': 'flex items-center justify-end',
45
- };
46
-
47
- export interface SetupUnocssOptions {
48
- userConfig?: Partial<UserConfig>;
49
- enableTheme?: boolean;
50
- enableShortcuts?: boolean;
51
- enableIconPreset?: boolean;
52
- }
53
-
54
- const isPlainRecord = (value: unknown): value is Record<string, unknown> => {
55
- if (!value || typeof value !== 'object') {
56
- return false;
57
- }
58
- return Object.prototype.toString.call(value) === '[object Object]';
59
- };
60
-
61
- const isSetupUnocssOptions = (value: unknown): value is SetupUnocssOptions => {
62
- if (!isPlainRecord(value)) {
63
- return false;
64
- }
65
- return (
66
- 'userConfig' in value ||
67
- 'enableTheme' in value ||
68
- 'enableShortcuts' in value ||
69
- 'enableIconPreset' in value
70
- );
71
- };
72
-
73
- const mergeTheme = (
74
- userTheme: UserConfig['theme'] | undefined,
75
- enableTheme: boolean,
76
- ): UserConfig['theme'] | undefined => {
77
- if (!enableTheme) {
78
- return userTheme;
79
- }
80
-
81
- const userThemeRecord = isPlainRecord(userTheme) ? userTheme : {};
82
- const userColors = isPlainRecord(userThemeRecord.colors) ? userThemeRecord.colors : {};
83
- const userBreakpoints = isPlainRecord(userThemeRecord.breakpoints) ? userThemeRecord.breakpoints : {};
84
-
85
- return {
86
- ...userThemeRecord,
87
- colors: {
88
- ...userColors,
89
- },
90
- breakpoints: {
91
- ...DEFAULT_BREAKPOINTS,
92
- ...userBreakpoints,
93
- },
94
- } as UserConfig['theme'];
95
- };
96
-
97
- const mergeShortcuts = (
98
- userShortcuts: UserConfig['shortcuts'] | undefined,
99
- enableShortcuts: boolean,
100
- ): UserConfig['shortcuts'] | undefined => {
101
- if (!enableShortcuts) {
102
- return userShortcuts;
103
- }
104
- if (!userShortcuts) {
105
- return DEFAULT_SHORTCUTS;
106
- }
107
- if (Array.isArray(userShortcuts)) {
108
- return [DEFAULT_SHORTCUTS, ...userShortcuts];
109
- }
110
- if (isPlainRecord(userShortcuts)) {
111
- return {
112
- ...DEFAULT_SHORTCUTS,
113
- ...userShortcuts,
114
- };
115
- }
116
- return userShortcuts;
117
- };
118
-
119
- /**
120
- * UnoCSS 配置
121
- *
122
- * 功能:
123
- * - 集成 UnoCSS
124
- * - 支持本地 SVG 图标
125
- * - 包含完整的预设和转换器
126
- * - 支持属性化模式(Attributify)
127
- *
128
- * @param localIconPath - 本地图标路径
129
- * @param unocssConfig - UnoCSS 配置(可选,用于合并其他配置)
130
- */
131
- export function setupUnocss(
132
- localIconPath: string,
133
- unocssConfig?: Partial<UserConfig> | SetupUnocssOptions
134
- ): ReturnType<typeof unocss> {
135
- const options = isSetupUnocssOptions(unocssConfig) ? unocssConfig : { userConfig: unocssConfig };
136
- const enableTheme = options.enableTheme ?? true;
137
- const enableShortcuts = options.enableShortcuts ?? true;
138
- const enableIconPreset = options.enableIconPreset ?? true;
139
- const userConfig = options.userConfig ?? {};
140
- const {
141
- presets: userPresets,
142
- transformers: userTransformers,
143
- theme: userTheme,
144
- shortcuts: userShortcuts,
145
- ...restUserConfig
146
- } = userConfig;
147
-
148
- return unocss({
149
- // Disable auto-loading `uno.config.*` from cwd to avoid noisy
150
- // "Config file not found" logs in template apps without standalone config files.
151
- configFile: false,
152
- presets: [
153
- // 基础预设 - 包含 Tailwind CSS 兼容的工具类
154
- presetUno(),
155
- // 属性化模式 - 支持 <div bg="blue-400" /> 语法
156
- presetAttributify(),
157
- // 图标预设 - 支持本地 SVG 图标
158
- ...(enableIconPreset
159
- ? [
160
- presetIcons({
161
- collections: {
162
- // 本地图标集合
163
- local: FileSystemIconLoader(localIconPath, (svg) =>
164
- svg.replace(/^<svg\s/, '<svg width="1em" height="1em" ')
165
- ),
166
- },
167
- extraProperties: {
168
- display: 'inline-block',
169
- },
170
- prefix: 'icon-',
171
- scale: 1,
172
- warn: true,
173
- }),
174
- ]
175
- : []),
176
- ...(userPresets ?? []),
177
- ],
178
- // 转换器
179
- transformers: [
180
- transformerDirectives(), // 支持 @apply、@screen 等指令
181
- transformerVariantGroup(), // 支持 variant groups (hover:bg-gray-400 hover:text-white)
182
- ...(userTransformers ?? []),
183
- ],
184
- // 主题配置
185
- theme: mergeTheme(userTheme, enableTheme),
186
- // 快捷方式 - 组合多个工具类
187
- shortcuts: mergeShortcuts(userShortcuts, enableShortcuts),
188
- // 自定义规则
189
- rules: [
190
- // 可以在这里添加项目特定的工具类
191
- // 示例:['custom-rule', { color: 'red' }],
192
- ],
193
- // 安全列表 - 确保这些类名始终被生成(即使没有被扫描到)
194
- safelist: [
195
- // 可以添加动态生成的类名
196
- // 例如:'bg-red-500', 'bg-blue-500',
197
- // 或者使用正则:/^bg-(red|blue|green)-\d+$/,
198
- ],
199
- // 合并用户自定义配置(通过拆分字段避免覆盖默认合并策略)
200
- ...restUserConfig,
201
- });
202
- }
@@ -1,43 +0,0 @@
1
- import { FileSystemIconLoader } from 'unplugin-icons/loaders';
2
- import Icons from 'unplugin-icons/vite';
3
- import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
4
-
5
- /**
6
- * 图标插件配置
7
- *
8
- * 功能:
9
- * - SVG 图标支持(vite-plugin-svg-icons)
10
- * - 图标组件自动导入(unplugin-icons)
11
- * - 支持本地 SVG 图标
12
- *
13
- * @param localIconPath - 本地图标路径
14
- * @param customDomId - 自定义 DOM ID(默认: __SVG_ICON_LOCAL__)
15
- * @returns 插件数组
16
- */
17
- export function setupUnPluginIcon(
18
- localIconPath: string,
19
- customDomId = '__SVG_ICON_LOCAL__'
20
- ): Array<ReturnType<typeof createSvgIconsPlugin> | ReturnType<typeof Icons>> {
21
- return [
22
- // SVG 图标插件 - 用于 <svg><use xlink:href="#icon-local-xxx" /></svg> 方式
23
- createSvgIconsPlugin({
24
- customDomId,
25
- iconDirs: [localIconPath],
26
- inject: 'body-last',
27
- symbolId: 'icon-local-[dir]-[name]',
28
- }),
29
-
30
- // 图标组件插件 - 用于 <IconLocalXxx /> 组件方式
31
- Icons({
32
- compiler: 'jsx',
33
- customCollections: {
34
- local: FileSystemIconLoader(localIconPath, (svg) =>
35
- svg.replace(/^<svg\s/, '<svg width="1em" height="1em" ')
36
- ),
37
- },
38
- defaultClass: 'inline-block',
39
- jsx: 'react',
40
- scale: 1,
41
- }),
42
- ];
43
- }
@@ -1,139 +0,0 @@
1
- import { TranslationOutlined } from "@ant-design/icons";
2
- import { Button, Dropdown, Space, type MenuProps } from "antd";
3
- import { useLocale } from "@vlian/framework/core";
4
- import { LocaleSwitch } from "@vlian/framework/components";
5
- import { useCallback, useEffect, useMemo } from "react";
6
- import type { SdkLang } from "../i18n/index.js";
7
- import { cache, type StorageStrategy } from "../storage/index.js";
8
-
9
- const LANG_LABEL: Record<SdkLang, string> = {
10
- "en-US": "English",
11
- "zh-CN": "简体中文",
12
- };
13
-
14
- const isSdkLang = (lang: string): lang is SdkLang => {
15
- return lang === "en-US" || lang === "zh-CN";
16
- };
17
-
18
- const normalizeLang = (lang?: string): SdkLang => {
19
- if (lang === "en-US") {
20
- return "en-US";
21
- }
22
- return "zh-CN";
23
- };
24
-
25
- export interface I18nSwitchDropdownProps {
26
- storageType?: StorageStrategy;
27
- storageKey?: string;
28
- }
29
-
30
- export const I18nSwitchDropdown = ({
31
- storageType = "localstorage",
32
- storageKey = "sdk-lang",
33
- }: I18nSwitchDropdownProps) => {
34
- const { setLocale } = useLocale();
35
-
36
- useEffect(() => {
37
- if (storageType !== "indexeddb") {
38
- return;
39
- }
40
-
41
- let disposed = false;
42
-
43
- const restoreLang = async () => {
44
- const nextLang = await cache.indexeddb.get<SdkLang>(storageKey);
45
- if (disposed || !nextLang || !isSdkLang(nextLang)) {
46
- return;
47
- }
48
- setLocale(nextLang);
49
- };
50
-
51
- void restoreLang();
52
- return () => {
53
- disposed = true;
54
- };
55
- }, [setLocale, storageKey, storageType]);
56
-
57
- const persistence = useMemo(() => {
58
- if (typeof window === "undefined") {
59
- return { enabled: false, key: storageKey };
60
- }
61
-
62
- if (storageType === "localstorage") {
63
- return { key: storageKey, storage: window.localStorage };
64
- }
65
-
66
- if (storageType === "sessionStorage") {
67
- return { key: storageKey, storage: window.sessionStorage };
68
- }
69
-
70
- return { enabled: false, key: storageKey };
71
- }, [storageKey, storageType]);
72
-
73
- const handleChange = useCallback(
74
- (locale: SdkLang) => {
75
- if (storageType === "indexeddb") {
76
- void cache.indexeddb.set(storageKey, locale, -1);
77
- }
78
- },
79
- [storageKey, storageType],
80
- );
81
-
82
- const renderDropdown = useCallback(
83
- ({
84
- locale,
85
- locales,
86
- setLocale: setLocaleValue,
87
- isChanging,
88
- labels,
89
- }: {
90
- locale: SdkLang;
91
- locales: SdkLang[];
92
- setLocale: (nextLocale: SdkLang) => void;
93
- isChanging: boolean;
94
- labels: Record<SdkLang, string>;
95
- }) => {
96
- const menu: MenuProps = {
97
- selectedKeys: [normalizeLang(locale)],
98
- onClick: ({ key }) => {
99
- if (!isSdkLang(key)) {
100
- return;
101
- }
102
- setLocaleValue(key);
103
- },
104
- items: locales.map((item) => ({
105
- key: item,
106
- label: (
107
- <Space size={8}>
108
- {labels[item]}
109
- </Space>
110
- ),
111
- })),
112
- };
113
-
114
- return (
115
- <Dropdown menu={menu} trigger={["click"]}>
116
- <Button
117
- type="text"
118
- size="small"
119
- shape={"circle"}
120
- aria-label="切换语言"
121
- loading={isChanging}
122
- >
123
- <TranslationOutlined />
124
- </Button>
125
- </Dropdown>
126
- );
127
- },
128
- [],
129
- );
130
-
131
- return (
132
- <LocaleSwitch
133
- labels={LANG_LABEL}
134
- persistence={persistence}
135
- onChange={handleChange}
136
- render={renderDropdown}
137
- />
138
- );
139
- };
@@ -1,2 +0,0 @@
1
- export * from "./theme-switch-dropdown.js";
2
- export * from "./i18n-switch-dropdown.js";