瀏覽代碼

[doc]New site project by sveltekit

dufu1991 1 年之前
父節點
當前提交
654265bd35
共有 100 個文件被更改,包括 3105 次插入3037 次删除
  1. 1 1
      docs/mds/guide/compatibility.md
  2. 1 1
      docs/mds/guide/compatibility_en.md
  3. 4 0
      docs/site/.prettierignore
  4. 34 0
      docs/site/eslint.config.js
  5. 0 24
      docs/site/index.html
  6. 0 32
      docs/site/jsconfig.json
  7. 28 13
      docs/site/package.json
  8. 0 7
      docs/site/postcss.config.cjs
  9. 6 0
      docs/site/postcss.config.js
  10. 0 1
      docs/site/public/ads.txt
  11. 0 0
      docs/site/public/assets/3d/process.js
  12. 0 0
      docs/site/public/assets/3d/viewer.js
  13. 0 0
      docs/site/public/highlight.min.js
  14. 0 1
      docs/site/public/highlight.svelte.min.js
  15. 0 66
      docs/site/src/App.svelte
  16. 3 3
      docs/site/src/app.css
  17. 13 0
      docs/site/src/app.d.ts
  18. 10 11
      docs/site/src/app.html
  19. 0 1
      docs/site/src/assets/svgs/ri-chrome-fill.svg
  20. 0 1
      docs/site/src/assets/svgs/ri-close-line.svg
  21. 0 1
      docs/site/src/assets/svgs/ri-riding-line.svg
  22. 0 1
      docs/site/src/assets/svgs/ri-spy-fill.svg
  23. 0 1
      docs/site/src/assets/svgs/ri-star-fill.svg
  24. 0 1
      docs/site/src/assets/svgs/ri-switch-fill.svg
  25. 0 1
      docs/site/src/assets/svgs/ri-volume-down-line.svg
  26. 0 37
      docs/site/src/components/menu/Menu.svelte
  27. 0 24
      docs/site/src/components/switch/Index.svelte
  28. 0 183
      docs/site/src/components/tab/Tab.svelte
  29. 20 10
      docs/site/src/data/color.ts
  30. 11 7
      docs/site/src/data/themes/azurePink.ts
  31. 11 7
      docs/site/src/data/themes/camelliaRed.ts
  32. 11 7
      docs/site/src/data/themes/chameleon.ts
  33. 0 78
      docs/site/src/data/themes/index.js
  34. 82 0
      docs/site/src/data/themes/index.ts
  35. 11 7
      docs/site/src/data/themes/nintendo.ts
  36. 11 7
      docs/site/src/data/themes/smartLive.ts
  37. 1 0
      docs/site/src/global.d.ts
  38. 100 92
      docs/site/src/lib/cmdk/CmdK.svelte
  39. 4 4
      docs/site/src/lib/colorCard/ColorCard.svelte
  40. 57 49
      docs/site/src/lib/fund/Fund.svelte
  41. 55 62
      docs/site/src/lib/header/Header.svelte
  42. 1 0
      docs/site/src/lib/index.ts
  43. 39 0
      docs/site/src/lib/menu/Menu.svelte
  44. 36 35
      docs/site/src/lib/modeSwitch/ModeSwitch.svelte
  45. 5 10
      docs/site/src/lib/modeSwitch/darkMode.ts
  46. 180 0
      docs/site/src/lib/tab/Tab.svelte
  47. 26 24
      docs/site/src/lib/themeSwitch/ThemeSwitch.svelte
  48. 0 82
      docs/site/src/main.js
  49. 0 678
      docs/site/src/pages/Home.svelte
  50. 0 13
      docs/site/src/pages/components/Component.svelte
  51. 0 335
      docs/site/src/pages/components/Components.svelte
  52. 0 19
      docs/site/src/pages/guide/About.svelte
  53. 0 18
      docs/site/src/pages/guide/Compatibility.svelte
  54. 0 20
      docs/site/src/pages/guide/Contribution.svelte
  55. 0 22
      docs/site/src/pages/guide/Create.svelte
  56. 0 18
      docs/site/src/pages/guide/Faq.svelte
  57. 0 20
      docs/site/src/pages/guide/Future.svelte
  58. 0 257
      docs/site/src/pages/guide/Guide.svelte
  59. 0 18
      docs/site/src/pages/guide/Icon.svelte
  60. 0 22
      docs/site/src/pages/guide/IconPlugin.svelte
  61. 0 18
      docs/site/src/pages/guide/Internation.svelte
  62. 0 19
      docs/site/src/pages/guide/Milestone.svelte
  63. 0 18
      docs/site/src/pages/guide/Theme.svelte
  64. 0 18
      docs/site/src/pages/guide/Vscode.svelte
  65. 0 16
      docs/site/src/routers.js
  66. 108 0
      docs/site/src/routes/+layout.svelte
  67. 3 0
      docs/site/src/routes/+layout.ts
  68. 626 0
      docs/site/src/routes/+page.svelte
  69. 337 0
      docs/site/src/routes/components/+page.svelte
  70. 14 12
      docs/site/src/routes/components/Api.svelte
  71. 7 0
      docs/site/src/routes/components/Component.svelte
  72. 14 10
      docs/site/src/routes/components/FAQ.svelte
  73. 17 13
      docs/site/src/routes/components/Guide.svelte
  74. 20 16
      docs/site/src/routes/components/Version.svelte
  75. 210 0
      docs/site/src/routes/guide/+layout.svelte
  76. 4 5
      docs/site/src/routes/guide/+page.svelte
  77. 21 0
      docs/site/src/routes/guide/Create.svelte
  78. 20 0
      docs/site/src/routes/guide/about/+page.svelte
  79. 24 42
      docs/site/src/routes/guide/changelog/+page.svelte
  80. 12 0
      docs/site/src/routes/guide/color/+page.svelte
  81. 146 112
      docs/site/src/routes/guide/color/Color.svelte
  82. 147 109
      docs/site/src/routes/guide/color/Color_en.svelte
  83. 19 0
      docs/site/src/routes/guide/compatibility/+page.svelte
  84. 19 0
      docs/site/src/routes/guide/contribution/+page.svelte
  85. 21 0
      docs/site/src/routes/guide/create/+page.svelte
  86. 19 0
      docs/site/src/routes/guide/faq/+page.svelte
  87. 19 0
      docs/site/src/routes/guide/future/+page.svelte
  88. 242 147
      docs/site/src/routes/guide/generator/+page.svelte
  89. 132 125
      docs/site/src/routes/guide/generator/Calendar.svelte
  90. 17 17
      docs/site/src/routes/guide/generator/GeneratorPreview.svelte
  91. 21 0
      docs/site/src/routes/guide/icon-plugin/+page.svelte
  92. 19 0
      docs/site/src/routes/guide/icon/+page.svelte
  93. 19 0
      docs/site/src/routes/guide/internation/+page.svelte
  94. 1 1
      docs/site/src/routes/guide/logo/+page.svelte
  95. 20 0
      docs/site/src/routes/guide/milestone/+page.svelte
  96. 4 4
      docs/site/src/routes/guide/shortkey/+page.svelte
  97. 19 0
      docs/site/src/routes/guide/theme/+page.svelte
  98. 19 0
      docs/site/src/routes/guide/vscode/+page.svelte
  99. 2 1
      docs/site/src/store.ts
  100. 2 2
      docs/site/src/utils/code-group-svg-data.js

+ 1 - 1
docs/mds/guide/compatibility.md

@@ -1,4 +1,4 @@
-取决于 Svelte 和 Tailwind CSS 的兼容性
+> STDF v1.x 基于 Svelte 5.x 与 Tailwind CSS 4.x 
 
 ## Svelte
 

+ 1 - 1
docs/mds/guide/compatibility_en.md

@@ -1,4 +1,4 @@
-STDF's compatibility depends on Svelte and Tailwind CSS.
+> STDF v1.x based on Svelte 5.x and Tailwind CSS 4.x.
 
 ## Svelte
 

+ 4 - 0
docs/site/.prettierignore

@@ -0,0 +1,4 @@
+# Package Managers
+package-lock.json
+pnpm-lock.yaml
+yarn.lock

+ 34 - 0
docs/site/eslint.config.js

@@ -0,0 +1,34 @@
+import prettier from 'eslint-config-prettier';
+import js from '@eslint/js';
+import { includeIgnoreFile } from '@eslint/compat';
+import svelte from 'eslint-plugin-svelte';
+import globals from 'globals';
+import { fileURLToPath } from 'node:url';
+import ts from 'typescript-eslint';
+const gitignorePath = fileURLToPath(new URL('./.gitignore', import.meta.url));
+
+export default ts.config(
+	includeIgnoreFile(gitignorePath),
+	js.configs.recommended,
+	...ts.configs.recommended,
+	...svelte.configs['flat/recommended'],
+	prettier,
+	...svelte.configs['flat/prettier'],
+	{
+		languageOptions: {
+			globals: {
+				...globals.browser,
+				...globals.node
+			}
+		}
+	},
+	{
+		files: ['**/*.svelte'],
+
+		languageOptions: {
+			parserOptions: {
+				parser: ts.parser
+			}
+		}
+	}
+);

+ 0 - 24
docs/site/index.html

@@ -1,24 +0,0 @@
-<!doctype html>
-<html lang="zh-CN">
-	<head>
-		<meta charset="utf-8" />
-		<meta name="viewport" content="width=device-width,initial-scale=1" />
-		<meta name="theme-color" content="#F2F2F3" media="(prefers-color-scheme: light)" />
-		<meta name="theme-color" content="#191101" media="(prefers-color-scheme: dark)" />
-		<meta itemprop="name" content="STDF" />
-		<meta name="description" itemprop="description" content="Mobile web component library based on Svelte and Tailwind" />
-		<meta itemprop="image" content="./assets/images/logo.png" />
-		<title>STDF - 移动 web 组件库</title>
-		<link href="favicon.ico" rel="icon" media="(prefers-color-scheme: light)" />
-		<link href="favicon_black.ico" rel="icon" media="(prefers-color-scheme: dark)" />
-		<link rel="stylesheet" href="./global.css?_=1682692608001.4514" />
-		<script src="./highlight.min.js"></script>
-		<script src="./highlight.svelte.min.js"></script>
-		<script type="module" src="/assets/3d/viewer.js"></script>
-	</head>
-
-	<body class="selection:bg-primary selection:text-white dark:selection:bg-dark dark:selection:text-black">
-		<div id="app"></div>
-		<script type="module" src="/src/main.js"></script>
-	</body>
-</html>

+ 0 - 32
docs/site/jsconfig.json

@@ -1,32 +0,0 @@
-{
-	"compilerOptions": {
-		"moduleResolution": "bundler",
-		"target": "ESNext",
-		"module": "ESNext",
-		/**
-		 * svelte-preprocess cannot figure out whether you have
-		 * a value or a type, so tell TypeScript to enforce using
-		 * `import type` instead of `import` for Types.
-		 */
-		"verbatimModuleSyntax": true,
-		"isolatedModules": true,
-		"resolveJsonModule": true,
-		/**
-		 * To have warnings / errors of the Svelte compiler at the
-		 * correct position, enable source maps by default.
-		 */
-		"sourceMap": true,
-		"esModuleInterop": true,
-		"skipLibCheck": true,
-		/**
-		 * Typecheck JS in `.svelte` and `.js` files by default.
-		 * Disable this if you'd like to use dynamic types.
-		 */
-		"checkJs": true
-	},
-	/**
-	 * Use global.d.ts instead of compilerOptions.types
-	 * to avoid limiting type declarations.
-	 */
-	"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"]
-}

+ 28 - 13
docs/site/package.json

@@ -1,32 +1,47 @@
 {
 	"name": "site",
-	"private": true,
-	"version": "0.0.0",
+	"version": "0.0.1",
 	"type": "module",
 	"scripts": {
 		"env": "bun run scripts/env.js",
-		"dev": "bun run env && vite",
+		"dev": "bun run env && vite dev",
 		"bu": "vite build",
 		"preview": "vite preview",
 		"bp": "bun run build && bun run preview",
 		"miniglobal": "cleancss -o dist/global.css dist/global.css",
-		"build": "bun run env && vite build"
+		"build": "bun run env && vite build",
+		"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
+		"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
+		"format": "prettier --write .",
+		"lint": "prettier --check . && eslint ."
 	},
 	"devDependencies": {
+		"@eslint/compat": "^1.2.4",
+		"@sveltejs/adapter-static": "^3.0.6",
+		"@sveltejs/kit": "^2.9.0",
 		"@sveltejs/vite-plugin-svelte": "^5.0.1",
+		"@types/color": "^4.2.0",
 		"@tailwindcss/typography": "^0.5.15",
 		"autoprefixer": "^10.4.20",
 		"beautify-qrcode": "^1.0.3",
 		"clipboard": "^2.0.11",
 		"color": "^4.2.3",
-		"postcss": "^8.4.49",
-		"rollup-plugin-md": "^1.0.1",
-		"rollup-plugin-stdf-icon": "^0.0.15",
-		"stdf":"file:../../packages/stdf",
-		"svelte": "^5.3.0",
-		"svelte-confetti": "^2.2.0",
-		"svelte-spa-router": "^4.0.1",
-		"tailwindcss": "^3.4.15",
-		"vite": "^6.0.1"
+		"eslint": "^9.16.0",
+		"eslint-config-prettier": "^9.1.0",
+		"eslint-plugin-svelte": "^2.46.1",
+		"globals": "^15.13.0",
+		"highlight.js": "^11.10.0",
+		"highlightjs-svelte": "^1.0.6",
+		"prettier": "^3.4.2",
+		"prettier-plugin-svelte": "^3.3.2",
+		"prettier-plugin-tailwindcss": "^0.6.9",
+		"rollup-plugin-md-ts": "file:../../packages/rollup-plugin-md-ts",
+		"stdf": "file:../../packages/stdf",
+		"svelte": "^5.7.1",
+		"svelte-check": "^4.1.1",
+		"tailwindcss": "^3.4.16",
+		"typescript": "^5.7.2",
+		"typescript-eslint": "^8.17.0",
+		"vite": "^6.0.3"
 	}
 }

+ 0 - 7
docs/site/postcss.config.cjs

@@ -1,7 +0,0 @@
-import tailwind from 'tailwindcss';
-import tailwindConfig from './tailwind.config.cjs';
-import autoprefixer from 'autoprefixer';
-
-export default {
-	plugins: [tailwind(tailwindConfig), autoprefixer],
-};

+ 6 - 0
docs/site/postcss.config.js

@@ -0,0 +1,6 @@
+export default {
+	plugins: {
+		tailwindcss: {},
+		autoprefixer: {}
+	}
+};

+ 0 - 1
docs/site/public/ads.txt

@@ -1 +0,0 @@
-google.com, pub-7513664453496981, DIRECT, f08c47fec0942fa0

文件差異過大導致無法顯示
+ 0 - 0
docs/site/public/assets/3d/process.js


文件差異過大導致無法顯示
+ 0 - 0
docs/site/public/assets/3d/viewer.js


文件差異過大導致無法顯示
+ 0 - 0
docs/site/public/highlight.min.js


+ 0 - 1
docs/site/public/highlight.svelte.min.js

@@ -1 +0,0 @@
-!(function () { 'use strict'; hljs.registerLanguage('svelte', function (e) { return { subLanguage: 'xml', contains: [ e.COMMENT('\x3c!--', '--\x3e', { relevance: 10 }), { begin: /^(\s*)(<script(\s*context="module")?>)/gm, end: /^(\s*)(<\/script>)/gm, subLanguage: 'javascript', excludeBegin: !0, excludeEnd: !0, contains: [{ begin: /^(\s*)(\$:)/gm, end: /(\s*)/gm, className: 'keyword' }], }, { begin: /^(\s*)(<style.*>)/gm, end: /^(\s*)(<\/style>)/gm, subLanguage: 'css', excludeBegin: !0, excludeEnd: !0 }, { begin: /\{/gm, end: /\}/gm, subLanguage: 'javascript', contains: [ { begin: /[\{]/, end: /[\}]/, skip: !0 }, { begin: /([#:\/@])(if|else|each|await|then|catch|debug|html)/gm, className: 'keyword', relevance: 10 }, ], }, ], }; }); })();

+ 0 - 66
docs/site/src/App.svelte

@@ -1,66 +0,0 @@
-<script>
-	import { afterUpdate, onMount } from 'svelte';
-	import { location } from 'svelte-spa-router';
-	import Router from 'svelte-spa-router';
-	import routes from './routers';
-	import Header from './components/header/Header.svelte';
-	import Fund from './components/fund/Fund.svelte';
-	import CmdK from './components/cmdk/CmdK.svelte';
-	import { isCmdKStore, isShowFundStore } from './store';
-	import { delParamsUrl } from './utils/index';
-
-	let showLeftNav = false; //是否显示左侧导航
-	//路由改变时,更新左侧导航
-	afterUpdate(() => {
-		showLeftNav = $location.startsWith('/guide') || $location === '/components';
-	});
-	$: isHome = $location === '/' || $location === '';
-
-	const isZh = localStorage.getItem('lang') === 'zh_CN';
-	// 修改HTML 上的lang
-	document.documentElement.lang = isZh ? 'zh-CN' : 'en-US';
-
-	onMount(() => {
-		// 根据 params 判断当前 URL 是否含有 fund 参数,如果有则显示赞赏弹窗
-		let urlLang = window.location.href.split('?')[1];
-		let urlParams = new URLSearchParams(urlLang);
-		const isFund = urlParams.has('fund');
-		if (isFund) {
-			isShowFundStore.set(true);
-			// 去除 URL 中的 fund 参数
-			setTimeout(() => {
-				window.history.replaceState({}, '', delParamsUrl(window.location.href, 'fund'));
-			}, 10);
-		}
-	});
-
-	// 点击顶部菜单事件
-	const headerCmdKFun = () => {
-		isCmdKStore.set(true);
-	};
-</script>
-
-<svelte:head>
-	<title>STDF - {isZh ? '移动 web 组件库' : 'Mobile web component library'}</title>
-</svelte:head>
-
-<main class="bg-primaryWhite dark:bg-darkBlack relative min-h-screen text-justify text-black antialiased dark:text-white">
-	<!-- main -> next -->
-	{#if $location === '' || $location === '/'}
-		<div class="bg-primary dark:bg-dark px-2 py-1 text-center text-xs text-white dark:text-black">
-			{#if isZh}
-				这是 v1.0.0@next 文档,v0.x 请访问 <a href="https://stdf.design" class="underline" target="_blank">stdf.design</a>
-			{:else}
-				This is the v1.0.0@next documentation, please visit <a href="https://stdf.design" class="underline" target="_blank">stdf.design</a> for
-				v0.x
-			{/if}
-		</div>
-	{/if}
-	<Header {showLeftNav} showBottonLine={!isHome} on:clickCmdK={headerCmdKFun} />
-	<Router {routes} />
-	<CmdK />
-	<!-- 赞赏 -->
-	{#if $isShowFundStore}
-		<Fund />
-	{/if}
-</main>

+ 3 - 3
docs/site/src/app.css

@@ -1,6 +1,6 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
+@import 'tailwindcss/base';
+@import 'tailwindcss/components';
+@import 'tailwindcss/utilities';
 
 @layer base {
 	:root {

+ 13 - 0
docs/site/src/app.d.ts

@@ -0,0 +1,13 @@
+// See https://svelte.dev/docs/kit/types#app.d.ts
+// for information about these interfaces
+declare global {
+	namespace App {
+		// interface Error {}
+		// interface Locals {}
+		// interface PageData {}
+		// interface PageState {}
+		// interface Platform {}
+	}
+}
+
+export {};

+ 10 - 11
docs/site/public/index.html → docs/site/src/app.html

@@ -9,16 +9,15 @@
 		<meta name="description" itemprop="description" content="Mobile web component library based on Svelte and Tailwind" />
 		<meta itemprop="image" content="./assets/images/logo.png" />
 		<title>STDF - 移动 web 组件库</title>
-
-		<link rel="icon" href="./favicon.ico" />
-		<link rel="stylesheet" href="./global.css?_=1682692608001.4514" />
-		<link rel="stylesheet" href="./output.css?_=1682692608001.4514" />
-
-		<script src="./highlight.min.js"></script>
-		<script src="./highlight.svelte.min.js"></script>
-		<script defer src="./build/bundle.js?_=1682692608001.4514"></script>
-		<script type="module" src="./assets/3d/viewer.js"></script>
+		<link href="favicon.ico" rel="icon" media="(prefers-color-scheme: light)" />
+		<link href="favicon_black.ico" rel="icon" media="(prefers-color-scheme: dark)" />
+		<link rel="stylesheet" href="/global.css" />
+		%sveltekit.head%
 	</head>
-
-	<body></body>
+	<body
+		data-sveltekit-preload-data="hover"
+		class="selection:bg-primary selection:text-white dark:selection:bg-dark dark:selection:text-black"
+	>
+		<div style="display: contents">%sveltekit.body%</div>
+	</body>
 </html>

+ 0 - 1
docs/site/src/assets/svgs/ri-chrome-fill.svg

@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.82726 21.7633C5.34912 20.7712 2 16.7767 2 12C2 10.1779 2.48734 8.46958 3.33878 6.99834L7.62189 14.4169C8.47396 15.9571 10.1152 17 12 17C12.2023 17 12.4018 16.988 12.5978 16.9646L9.82726 21.7633ZM12 22L16.2868 14.5751C16.7396 13.8229 17 12.9419 17 12C17 10.8744 16.6281 9.83566 16.0004 9H21.5422C21.8396 9.94704 22 10.9548 22 12C22 17.5228 17.5228 22 12 22ZM14.5721 13.545C14.0473 14.4168 13.0917 15 12 15C10.8897 15 9.92024 14.3968 9.40149 13.5002L9.37313 13.4501C9.13535 13.0203 9 12.526 9 12C9 10.3431 10.3431 9 12 9C13.6569 9 15 10.3431 15 12C15 12.5465 14.8539 13.0589 14.5985 13.5002L14.5721 13.545ZM4.6322 5.23859C6.46008 3.24783 9.08432 2 12 2C15.7014 2 18.9331 4.01099 20.6622 7H12C9.93635 7 8.1647 8.25019 7.40112 10.0345L4.6322 5.23859Z"></path></svg>

+ 0 - 1
docs/site/src/assets/svgs/ri-close-line.svg

@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12.0007 10.5865L16.9504 5.63672L18.3646 7.05093L13.4149 12.0007L18.3646 16.9504L16.9504 18.3646L12.0007 13.4149L7.05093 18.3646L5.63672 16.9504L10.5865 12.0007L5.63672 7.05093L7.05093 5.63672L12.0007 10.5865Z"></path></svg>

+ 0 - 1
docs/site/src/assets/svgs/ri-riding-line.svg

@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M5.5 21C3.01472 21 1 18.9853 1 16.5C1 14.0147 3.01472 12 5.5 12C7.98528 12 10 14.0147 10 16.5C10 18.9853 7.98528 21 5.5 21ZM5.5 19C6.88071 19 8 17.8807 8 16.5C8 15.1193 6.88071 14 5.5 14C4.11929 14 3 15.1193 3 16.5C3 17.8807 4.11929 19 5.5 19ZM18.5 21C16.0147 21 14 18.9853 14 16.5C14 14.0147 16.0147 12 18.5 12C20.9853 12 23 14.0147 23 16.5C23 18.9853 20.9853 21 18.5 21ZM18.5 19C19.8807 19 21 17.8807 21 16.5C21 15.1193 19.8807 14 18.5 14C17.1193 14 16 15.1193 16 16.5C16 17.8807 17.1193 19 18.5 19ZM11.023 10.3054L13 12V18H11V13L8.28117 10.7343C8.18221 10.6661 8.08802 10.588 8 10.5C7.21895 9.71895 7.21895 8.45262 8 7.67157L10.8284 4.84315C11.6095 4.0621 12.8758 4.0621 13.6569 4.84315L15.0711 6.25736C16.1746 7.36086 17.5548 8.01891 18.9884 8.23151L18.978 10.2474C17.0335 10.0218 15.1485 9.16323 13.6569 7.67157L11.023 10.3054ZM16 5C14.8954 5 14 4.10457 14 3C14 1.89543 14.8954 1 16 1C17.1046 1 18 1.89543 18 3C18 4.10457 17.1046 5 16 5Z"></path></svg>

+ 0 - 1
docs/site/src/assets/svgs/ri-spy-fill.svg

@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17 13C19.2091 13 21 14.7909 21 17C21 19.2091 19.2091 21 17 21C14.8578 21 13 19.21 13 17H11C11 19.2091 9.20914 21 7 21C4.79086 21 3 19.2091 3 17C3 14.7909 4.79086 13 7 13C8.48052 13 9.77317 13.8043 10.4648 14.9999H13.5352C14.2268 13.8043 15.5195 13 17 13ZM2 12V10H4V7C4 4.79086 5.79086 3 8 3H16C18.2091 3 20 4.79086 20 7V10H22V12H2Z"></path></svg>

+ 0 - 1
docs/site/src/assets/svgs/ri-star-fill.svg

@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12.0006 18.26L4.94715 22.2082L6.52248 14.2799L0.587891 8.7918L8.61493 7.84006L12.0006 0.5L15.3862 7.84006L23.4132 8.7918L17.4787 14.2799L19.054 22.2082L12.0006 18.26Z"></path></svg>

+ 0 - 1
docs/site/src/assets/svgs/ri-switch-fill.svg

@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13.62 21C13.5351 21 13.4786 20.9434 13.4927 20.8727V3.12726C13.4927 3.0707 13.5351 3.01414 13.6058 3.01414H16.3914C18.9366 3.01414 21.001 5.07855 21.001 7.62372V16.3904C21.001 18.9356 18.9366 21 16.3914 21H13.62ZM17.0418 11.0738C16.0379 11.0738 15.2178 11.894 15.2178 12.8979C15.2178 13.9018 16.0379 14.7219 17.0418 14.7219C18.0458 14.7219 18.8659 13.9018 18.8659 12.8979C18.8659 11.894 18.0458 11.0738 17.0418 11.0738ZM5.80066 8.40141C5.80066 7.46819 6.56421 6.70463 7.49744 6.70463C8.43067 6.70463 9.19422 7.46819 9.19422 8.40141C9.19422 9.33464 8.43067 10.0982 7.49744 10.0982C6.56421 10.0982 5.80066 9.33464 5.80066 8.40141ZM11.5414 3C11.6263 3 11.6828 3.05656 11.6687 3.12726V20.8586C11.6687 20.9293 11.6121 20.9859 11.5414 20.9859H7.61056C5.06539 20.9859 3.00098 18.9214 3.00098 16.3763V7.60958C3.00098 5.06441 5.06539 3 7.61056 3H11.5414ZM10.2264 19.5436V4.44226H7.61056C6.76217 4.44226 5.97034 4.78162 5.37647 5.37549C4.76846 5.96936 4.44324 6.76119 4.44324 7.60958V16.3763C4.44324 17.2247 4.78259 18.0165 5.37647 18.6104C5.97034 19.2184 6.76217 19.5436 7.61056 19.5436H10.2264Z"></path></svg>

+ 0 - 1
docs/site/src/assets/svgs/ri-volume-down-line.svg

@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 7.22056L9.60282 10.0001H6V14.0001H9.60282L13 16.7796V7.22056ZM8.88889 16.0001H5C4.44772 16.0001 4 15.5524 4 15.0001V9.00007C4 8.44778 4.44772 8.00007 5 8.00007H8.88889L14.1834 3.66821C14.3971 3.49335 14.7121 3.52485 14.887 3.73857C14.9601 3.8279 15 3.93977 15 4.05519V19.9449C15 20.2211 14.7761 20.4449 14.5 20.4449C14.3846 20.4449 14.2727 20.405 14.1834 20.3319L8.88889 16.0001ZM18.8631 16.5911L17.4411 15.1691C18.3892 14.4376 19 13.2902 19 12.0001C19 10.5697 18.2493 9.31476 17.1203 8.60766L18.5589 7.16906C20.0396 8.26166 21 10.0187 21 12.0001C21 13.8422 20.1698 15.4905 18.8631 16.5911Z"></path></svg>

+ 0 - 37
docs/site/src/components/menu/Menu.svelte

@@ -1,37 +0,0 @@
-<script>
-	// @ts-nocheck
-	import { createEventDispatcher } from 'svelte';
-
-	const dispatch = createEventDispatcher();
-	export let currentNav = '';
-	export let showNum = true;
-	const setClick = menu => {
-		currentNav = menu.nav;
-		dispatch('MenuClick', menu);
-	};
-	export let menuList = [];
-	const isZh = localStorage.getItem('lang') === 'zh_CN';
-</script>
-
-<div class="flex flex-col px-2 py-4">
-	<span class="text-gray-500 text-xs pb-3">
-		{isZh ? '最近更新:' : 'Last update:'}
-		<br />
-		{isZh ? import.meta.env.VITE_BUILD_TIME_ZH : import.meta.env.VITE_BUILD_TIME_EN}
-	</span>
-	{#each menuList as menu}
-		<div class="text-xs">{isZh ? menu.class : menu.class_en}{showNum ? `(${menu.childs.length})` : ''}</div>
-		<div class="flex flex-col ml-1 pr-0 my-2">
-			{#each menu.childs as child, i}
-				<button
-					on:click|preventDefault|self={() => setClick(child)}
-					class={`cursor-pointer transition-all pl-2 py-2 text-left hover:font-bold border-l-2 text-sm box-content ${
-						child.nav === currentNav ? 'border-primary dark:border-dark font-bold text-primary dark:text-dark' : ''
-					}`}
-				>
-					{isZh ? child.title : child.title_en}
-				</button>
-			{/each}
-		</div>
-	{/each}
-</div>

+ 0 - 24
docs/site/src/components/switch/Index.svelte

@@ -1,24 +0,0 @@
-<script>
-	export let open = false;
-
-	let isClick = false;
-
-	const toggleFun = () => {
-		isClick = true;
-		setTimeout(() => {
-			isClick = false;
-		}, 150);
-		open = !open;
-	};
-</script>
-
-<!-- svelte-ignore a11y-click-events-have-key-events -->
-<!-- svelte-ignore a11y-no-static-element-interactions -->
-<div class="w-12 h-6 rounded-full relative ring-1 ring-gray-400 dark:ring-gray-300 cursor-pointer" on:click={toggleFun}>
-	<div
-		class="absolute {open
-			? 'left-[26px] bg-primary dark:bg-dark'
-			: 'left-0.5 bg-gray-300 dark:bg-gray-600'} top-0.5 w-5 h-5 transition-all duration-300 rounded-full"
-		style="transform:scaleX({isClick ? '1.3' : '1'});})"
-	></div>
-</div>

+ 0 - 183
docs/site/src/components/tab/Tab.svelte

@@ -1,183 +0,0 @@
-<script>
-    import { createEventDispatcher } from 'svelte';
-    import { fade } from 'svelte/transition';
-    import { querystring } from 'svelte-spa-router';
-    import { currentThemeStore } from '../../store';
-    // @ts-ignore
-    import { encodeData, rendererLine } from 'beautify-qrcode';
-
-    export let currentTab = 0;
-    const dispatch = createEventDispatcher();
-    const tabList = [
-        { zh: '示例', en: 'Demo' },
-        { zh: 'API', en: 'API' },
-        { zh: '指南', en: 'Guide' },
-        { zh: 'FAQ', en: 'FAQ' },
-        { zh: '版本', en: 'Version' },
-    ];
-    const changeIndexFun = i => {
-        currentTab = i;
-        dispatch('TabClick', i);
-    };
-    const isZh = localStorage.getItem('lang') === 'zh_CN';
-    let showQr = false;
-    let QRValue = '';
-    let A_a1Svg;
-
-    const mouseenterFun = () => {
-        const params = new URLSearchParams('?' + $querystring);
-        QRValue =
-            // main -> next
-            // @ts-ignore
-            (import.meta.env.DEV ? location.protocol + '//' + location.hostname + ':8888/' : 'https://next-demo.stdf.design/') +
-            params.get('nav') +
-            (isZh ? '/zh_CN' : '/en_US');
-        showQr = true;
-        /**
-         * A_a1
-         * @param {Object} qrcode
-         * @param {Object} options
-         * @param {String} [options.type]  连线方向 0=>左右 1=>上下 2=>纵横 3=>回环 4=>左上—右下 5=>右上—左下 6=>交叉"
-         * @param {String} [options.size] 连线粗细
-         * @param {String} [options.opacity] 连线不透明度
-         * @param {String} [options.posType] 定位点样式  0=>矩形 1=>圆形 2=>行星 3=>圆角矩形
-         * @param {String} [options.otherColor] 连线颜色
-         * @param {String} [options.posColor] 定位点颜色
-         */
-        const qrcode = encodeData({
-            text: QRValue,
-            isSpace: false,
-        });
-        const color = $currentThemeStore === 'dark' ? 'rgb(var(--theme-color-dark))' : 'rgb(var(--theme-color-primary))';
-        A_a1Svg = rendererLine(qrcode, {
-            posType: 2,
-            otherColor: color,
-            posColor: color,
-        });
-    };
-
-    let showStackblitz = false;
-    let stackblitzValue = '';
-    const showStackblitzFunc = () => {
-        const nav = $querystring.split('&')[0].split('=')[1];
-        // main -> next
-        stackblitzValue = `https://stackblitz.com/github/any-tdf/next-demo-stdf?file=src%2Froutes%2F${
-            isZh ? 'zh_CN' : 'en_US'
-        }%2F${nav}%2F%2Bpage.svelte&startScript=${nav}${isZh ? '' : '_en'}`;
-        showStackblitz = true;
-    };
-
-    let showCode = false;
-    let codeValue = '';
-    const showCodeFunc = () => {
-        const nav = $querystring.split('&')[0].split('=')[1];
-        // 将nav首字母大写
-        const navFirst = nav.slice(0, 1).toUpperCase() + nav.slice(1);
-        // main -> next
-        codeValue = `https://github.com/any-tdf/stdf/blob/next/packages/stdf/src/lib/components/${nav}/${navFirst}.svelte`;
-        showCode = true;
-    };
-</script>
-
-<div class="relative top-14 w-82 md:w-102">
-    <div class="relative rounded p-1 bg-gray-100 dark:bg-gray-700">
-        <!--滑块-->
-        <div
-            class="absolute top-1 w-16 md:w-20 h-10 rounded bg-white dark:bg-black shadow-md dark:shadow-white/10 transition-all duration-300"
-            class:left-1={currentTab === 0}
-            class:left-17={currentTab === 1}
-            class:md:left-21={currentTab === 1}
-            class:left-33={currentTab === 2}
-            class:md:left-41={currentTab === 2}
-            class:left-49={currentTab === 3}
-            class:md:left-61={currentTab === 3}
-            class:left-65={currentTab === 4}
-            class:md:left-81={currentTab === 4}
-        ></div>
-        <!--二维码-->
-        <a href={QRValue} target="_blank">
-            <!-- svelte-ignore a11y-no-static-element-interactions -->
-            <div
-                on:mouseleave={() => (showQr = false)}
-                on:mouseenter={mouseenterFun}
-                class="hidden md:block absolute top-0 bg-gray-100 dark:bg-gray-700 rounded p-3 left-106 h-12 w-12"
-            >
-                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" style="fill: currentColor">
-                    <path fill="none" d="M0 0h24v24H0z" />
-                    <path
-                        d="M16 17v-1h-3v-3h3v2h2v2h-1v2h-2v2h-2v-3h2v-1h1zm5 4h-4v-2h2v-2h2v4zM3 3h8v8H3V3zm2 2v4h4V5H5zm8-2h8v8h-8V3zm2 2v4h4V5h-4zM3 13h8v8H3v-8zm2 2v4h4v-4H5zm13-2h3v2h-3v-2zM6 6h2v2H6V6zm0 10h2v2H6v-2zM16 6h2v2h-2V6z"
-                    />
-                </svg>
-                {#if showQr}
-                    <div
-                        class="w-60 rounded bg-black absolute z-50 top-14 left-0 p-6 shadow-lg hidden dark:block"
-                        transition:fade={{ duration: 200 }}
-                    >
-                        <span>{@html A_a1Svg}</span>
-                    </div>
-                {/if}
-                {#if showQr}
-                    <div
-                        class="w-60 rounded bg-white absolute z-50 top-14 left-0 p-6 shadow-lg block dark:hidden"
-                        transition:fade={{ duration: 200 }}
-                    >
-                        <span>{@html A_a1Svg}</span>
-                    </div>
-                {/if}
-            </div>
-        </a>
-        <!--StackBlitz-->
-        <a href={stackblitzValue} target="_blank">
-            <!-- svelte-ignore a11y-no-static-element-interactions -->
-            <div
-                on:mouseleave={() => (showStackblitz = false)}
-                on:mouseenter={showStackblitzFunc}
-                class="hidden md:block absolute top-0 bg-gray-100 dark:bg-gray-700 rounded p-3 left-[34.5rem] h-12 w-12"
-            >
-                <svg viewBox="0 0 28 28" height="24">
-                    <path fill="#3275e7" d="M12.747 16.273h-7.46L18.925 1.5l-3.671 10.227h7.46L9.075 26.5l3.671-10.227z" />
-                </svg>
-                {#if showStackblitz}
-                    <div
-                        class="w-44 h-12 leading-[1.5rem] text-center rounded bg-gray-700 text-white absolute z-50 top-14 left-0 py-3 shadow-lg"
-                        transition:fade={{ duration: 200 }}
-                    >
-                        {isZh ? '在 StackBlitz 中打开' : 'Open in StackBlitz'}
-                    </div>
-                {/if}
-            </div>
-        </a>
-        <!--组件源码-->
-        <a href={codeValue} target="_blank">
-            <!-- svelte-ignore a11y-no-static-element-interactions -->
-            <div
-                on:mouseleave={() => (showCode = false)}
-                on:mouseenter={showCodeFunc}
-                class="hidden md:block absolute top-0 bg-gray-100 dark:bg-gray-700 rounded p-3 left-[30.5rem] h-12 w-12"
-            >
-                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" style="fill: currentColor">
-                    <path
-                        d="M3 3H21C21.5523 3 22 3.44772 22 4V20C22 20.5523 21.5523 21 21 21H3C2.44772 21 2 20.5523 2 20V4C2 3.44772 2.44772 3 3 3ZM4 5V19H20V5H4ZM20 12L16.4645 15.5355L15.0503 14.1213L17.1716 12L15.0503 9.87868L16.4645 8.46447L20 12ZM6.82843 12L8.94975 14.1213L7.53553 15.5355L4 12L7.53553 8.46447L8.94975 9.87868L6.82843 12ZM11.2443 17H9.11597L12.7557 7H14.884L11.2443 17Z"
-                    />
-                </svg>
-                {#if showCode}
-                    <div
-                        class="{isZh
-                            ? 'w-28'
-                            : 'w-52'} h-12 leading-[1.5rem] text-center rounded bg-gray-700 text-white absolute z-50 top-14 left-0 py-3 shadow-lg"
-                        transition:fade={{ duration: 200 }}
-                    >
-                        {isZh ? '组件源码' : 'Component source code'}
-                    </div>
-                {/if}
-            </div>
-        </a>
-        <div class="flex relative">
-            {#each tabList as item, index}
-                <button on:click={() => changeIndexFun(index)} class="cursor-pointer py-2 w-16 md:w-20 text-center rounded">
-                    {isZh ? item.zh : item.en}
-                </button>
-            {/each}
-        </div>
-    </div>
-</div>

+ 20 - 10
docs/site/src/data/color.js → docs/site/src/data/color.ts

@@ -2093,18 +2093,28 @@ const colors = [
 	['4b2e2b', '玫瑰灰'],
 	['ed4845', '淡菽红'],
 	['ed3333', '枸枢红'],
-	['5d3131', '貂紫'],
+	['5d3131', '貂紫']
 ];
 
 // 传入 hsl(0, 0%, 0%) 格式的颜色,返回 h s l 的值组成的数组
-const hslFunc = color => {
-	let hslArr = color.match(/\d+/g);
+const hslFunc = (color: string) => {
+	const hslArr = color.match(/\d+/g);
 	return hslArr;
 };
 
 // 将 colors 转为 rgb 和 hsl 格式,每一项包含 name hex rgb hsl,colorConvertFunc 为转换函数
-let colorList = [];
-colors.forEach(item => {
+type colorObj = {
+	name: string;
+	hex: string;
+	rgb: string[];
+	hsl: string[];
+	hsl_h: string | null;
+	hsl_s: string | null;
+	hsl_l: string | null;
+	mode: string;
+};
+let colorList: colorObj[] = [];
+colors.forEach((item) => {
 	const hex = '#' + item[0];
 	const obj = {
 		name: item[1],
@@ -2112,16 +2122,16 @@ colors.forEach(item => {
 		rgb: colorConvertFunc(hex).rgb,
 		hsl: colorConvertFunc(hex).hsl,
 		// hslArr: hslFunc(colorConvertFunc(hex).hsl),
-		hsl_h: hslFunc(colorConvertFunc(hex).hsl)[0],
-		hsl_s: hslFunc(colorConvertFunc(hex).hsl)[1],
-		hsl_l: hslFunc(colorConvertFunc(hex).hsl)[2],
-		mode: hslFunc(colorConvertFunc(hex).hsl)[2] > 50 ? 'light' : 'dark',
+		hsl_h: hslFunc(colorConvertFunc(hex).hsl)?.[0],
+		hsl_s: hslFunc(colorConvertFunc(hex).hsl)?.[1],
+		hsl_l: hslFunc(colorConvertFunc(hex).hsl)?.[2],
+		mode: hslFunc(colorConvertFunc(hex).hsl)?.[2] !== undefined && Number(hslFunc(colorConvertFunc(hex).hsl)?.[2]) > 50 ? 'light' : 'dark'
 	};
 	colorList.push(obj);
 });
 
 // 过滤出 hsl_l 在 20-45 和 55-80 之间的颜色,区分明显
-colorList = colorList.filter(item => {
+colorList = colorList.filter((item) => {
 	return (item.hsl_l >= 20 && item.hsl_l < 45) || (item.hsl_l > 55 && item.hsl_l <= 80);
 });
 

+ 11 - 7
docs/site/src/data/themes/azurePink.js → docs/site/src/data/themes/azurePink.ts

@@ -1,4 +1,6 @@
-export default {
+import type { ThemeProps } from 'stdf/theme';
+
+const AzurePink: ThemeProps = {
 	name: 'AzurePink',
 	color: {
 		primary: {
@@ -12,7 +14,7 @@ export default {
 			700: '8, 8, 143', // #08088F
 			800: '9, 5, 121', // #090579
 			900: '8, 2, 99', // #080263
-			950: '8, 0, 77', // #08004D
+			950: '8, 0, 77' // #08004D
 		},
 		dark: {
 			50: '255, 245, 248', // #FFF5F8
@@ -25,7 +27,7 @@ export default {
 			700: '195, 21, 117', // #C31575
 			800: '156, 11, 95', // #9C0B5F
 			900: '116, 4, 73', // #740449
-			950: '77, 0, 50', // #4D0032
+			950: '77, 0, 50' // #4D0032
 		},
 		primaryBlack: '1, 1, 25', // #010119
 		primaryWhite: '242, 242, 243', // #F2F2F3
@@ -35,12 +37,14 @@ export default {
 			success: '43, 164, 23', // #2ba417
 			warning: '227, 115, 24', // #e37318
 			error: '213, 73, 65', // #d54941
-			info: '0, 82, 217', // #0052d9
+			info: '0, 82, 217' // #0052d9
 		},
 		extend: [
 			{ color: '20, 40, 160', alias: 'Samsung' }, // #1428A0
 			{ color: '253, 73, 0', alias: 'Xiaomi' }, // #fd4900
-			{ color: '4, 106, 56', alias: 'OPPO' }, // ##046a38
-		],
-	},
+			{ color: '4, 106, 56', alias: 'OPPO' } // ##046a38
+		]
+	}
 };
+
+export default AzurePink;

+ 11 - 7
docs/site/src/data/themes/camelliaRed.js → docs/site/src/data/themes/camelliaRed.ts

@@ -1,4 +1,6 @@
-export default {
+import type { ThemeProps } from 'stdf/theme';
+
+const CamelliaRed: ThemeProps = {
 	name: 'CamelliaRed',
 	color: {
 		primary: {
@@ -12,7 +14,7 @@ export default {
 			700: '198, 39, 58', // #C6273A
 			800: '157, 21, 41', // #9D1529
 			900: '117, 8, 28', // #75081C
-			950: '77, 0, 17', // #4D0011
+			950: '77, 0, 17' // #4D0011
 		},
 		dark: {
 			50: '254, 250, 255', // #FEFAFF
@@ -25,7 +27,7 @@ export default {
 			700: '164, 88, 210', // #A458D2
 			800: '116, 46, 166', // #742EA6
 			900: '74, 17, 121', // #4A1179
-			950: '40, 0, 77', // #28004D
+			950: '40, 0, 77' // #28004D
 		},
 		primaryBlack: '25, 1, 3', // #190103
 		primaryWhite: '243, 242, 242', // #F3F2F2
@@ -35,12 +37,14 @@ export default {
 			success: '82, 196, 26', // #52c41a
 			warning: '250, 173, 20', // #faad14
 			error: '255, 77, 79', // #ff4d4f
-			info: '22, 119, 255', // #1677ff
+			info: '22, 119, 255' // #1677ff
 		},
 		extend: [
 			{ color: '59, 89, 152', alias: 'Facebook' }, // #3b5998
 			{ color: '237, 28, 22', alias: 'CocaCola' }, // #ed1c16
-			{ color: '0, 104, 181', alias: 'Intel' }, // #0068b5
-		],
-	},
+			{ color: '0, 104, 181', alias: 'Intel' } // #0068b5
+		]
+	}
 };
+
+export default CamelliaRed;

+ 11 - 7
docs/site/src/data/themes/chameleon.js → docs/site/src/data/themes/chameleon.ts

@@ -1,4 +1,6 @@
-export default {
+import type { ThemeProps } from 'stdf/theme';
+
+const Chameleon: ThemeProps = {
 	name: 'Chameleon',
 	color: {
 		primary: {
@@ -12,7 +14,7 @@ export default {
 			700: '1, 141, 73', // #018D49
 			800: '1, 119, 66', // #017742
 			900: '0, 98, 57', // #006239
-			950: '0, 77, 47', // #004D2F
+			950: '0, 77, 47' // #004D2F
 		},
 		dark: {
 			50: '255, 245, 252', // #FFF5FC
@@ -25,7 +27,7 @@ export default {
 			700: '193, 64, 189', // #C140BD
 			800: '154, 34, 154', // #9A229A
 			900: '112, 13, 115', // #700D73
-			950: '71, 0, 77', // #47004D
+			950: '71, 0, 77' // #47004D
 		},
 		primaryBlack: '1, 25, 12', // #01190C
 		primaryWhite: '242, 243, 242', // #F2F3F2
@@ -35,12 +37,14 @@ export default {
 			success: '103, 194, 58', // #67c23a
 			warning: '230, 162, 60', // #e6a23c
 			error: '245, 108, 108', // #f56c6c
-			info: '144, 147, 153', // #909399
+			info: '144, 147, 153' // #909399
 		},
 		extend: [
 			{ color: '56, 189, 248', alias: 'Tailwind' }, // #38bdf8
 			{ color: '194, 12, 12', alias: 'NetEaseCloudMusic' }, // #c20c0c
-			{ color: '65, 95, 255', alias: 'vivo' }, // #415fff
-		],
-	},
+			{ color: '65, 95, 255', alias: 'vivo' } // #415fff
+		]
+	}
 };
+
+export default Chameleon;

+ 0 - 78
docs/site/src/data/themes/index.js

@@ -1,78 +0,0 @@
-import { STDFTheme } from 'stdf/theme';
-import Chameleon from './chameleon';
-import AzurePink from './azurePink';
-import SmartLive from './smartLive';
-import CamelliaRed from './camelliaRed';
-import Nintendo from './nintendo';
-
-/**
- * 传入 rgb 格式 255, 255, 255 的颜色值,返回 hex 格式的颜色值
- * Pass in the color value of rgb format 255, 255, 255 and return the color value of hex format
- * @param {string} rgb
- * @returns {string}
- */
-const rgbToHex = rgb => {
-    // 如果传入的是 hex 格式的颜色值,直接返回
-    // If the color value passed in is in hex format, return directly
-    if (rgb.includes('#')) {
-        return rgb;
-    }
-    const rgbArr = rgb.split(',');
-    let hex = '#';
-    rgbArr.forEach(item => {
-        const num = parseInt(item);
-        hex += num.toString(16).padStart(2, '0');
-    });
-    return hex;
-};
-
-/**
- * 将 theme 对象中所有的 rgb 格式 255, 255, 255 转换为 hex 格式 #ffffff
- * Let all rgb formats 255, 255, 255 in the theme object be converted to hex format #ffffff
- * @param {Object} theme
- * @returns {Object}
- */
-const rgbToHexFunc = theme => {
-    const obj = theme.color;
-    const primary = obj.primary;
-    for (const key in primary) {
-        if (Object.hasOwnProperty.call(primary, key)) {
-            const element = primary[key];
-            if (typeof element === 'string' && element.includes(',')) {
-                primary[key] = rgbToHex(element);
-            }
-        }
-    }
-    const dark = obj.dark;
-    for (const key in dark) {
-        if (Object.hasOwnProperty.call(dark, key)) {
-            const element = dark[key];
-            if (typeof element === 'string' && element.includes(',')) {
-                dark[key] = rgbToHex(element);
-            }
-        }
-    }
-    obj.functional.success = rgbToHex(obj.functional.success);
-    obj.functional.warning = rgbToHex(obj.functional.warning);
-    obj.functional.error = rgbToHex(obj.functional.error);
-    obj.functional.info = rgbToHex(obj.functional.info);
-    const extend = obj.extend;
-    extend.forEach(item => {
-        item.color = rgbToHex(item.color);
-    });
-    obj.primaryBlack = rgbToHex(obj.primaryBlack);
-    obj.primaryWhite = rgbToHex(obj.primaryWhite);
-    obj.darkBlack = rgbToHex(obj.darkBlack);
-    obj.darkWhite = rgbToHex(obj.darkWhite);
-    theme.color = obj;
-    return theme;
-};
-
-export default [
-    { name_CN: 'STDF', name: STDFTheme.name, theme: rgbToHexFunc(STDFTheme) },
-    { name_CN: '任天堂', name: Nintendo.name, theme: rgbToHexFunc(Nintendo) },
-    { name_CN: '蔚蓝粉', name: AzurePink.name, theme: rgbToHexFunc(AzurePink) },
-    { name_CN: '变色龙', name: Chameleon.name, theme: rgbToHexFunc(Chameleon) },
-    { name_CN: '慧活力', name: SmartLive.name, theme: rgbToHexFunc(SmartLive) },
-    { name_CN: '山茶红', name: CamelliaRed.name, theme: rgbToHexFunc(CamelliaRed) },
-];

+ 82 - 0
docs/site/src/data/themes/index.ts

@@ -0,0 +1,82 @@
+import { STDFTheme, type ThemeProps } from 'stdf/theme';
+import Chameleon from './chameleon.js';
+import AzurePink from './azurePink.js';
+import SmartLive from './smartLive.js';
+import CamelliaRed from './camelliaRed.js';
+import Nintendo from './nintendo.js';
+
+/**
+ * 传入 rgb 格式 255, 255, 255 的颜色值,返回 hex 格式的颜色值
+ * Pass in the color value of rgb format 255, 255, 255 and return the color value of hex format
+ * @param {string} rgb
+ * @returns {string}
+ */
+const rgbToHex = (rgb: string) => {
+	// 如果传入的是 hex 格式的颜色值,直接返回
+	// If the color value passed in is in hex format, return directly
+	if (rgb.includes('#')) {
+		return rgb;
+	}
+	const rgbArr = rgb.split(',');
+	let hex = '#';
+	rgbArr.forEach((item) => {
+		const num = parseInt(item);
+		hex += num.toString(16).padStart(2, '0');
+	});
+	return hex;
+};
+
+/**
+ * 将 theme 对象中所有的 rgb 格式 255, 255, 255 转换为 hex 格式 #ffffff
+ * Let all rgb formats 255, 255, 255 in the theme object be converted to hex format #ffffff
+ * @param {Object} theme
+ * @returns {Object}
+ */
+const rgbToHexFunc = (theme: ThemeProps) => {
+	const obj = theme.color;
+	const primary = obj.primary;
+	for (const key in primary) {
+		if (Object.hasOwnProperty.call(primary, key)) {
+			const element = primary[key as keyof typeof primary];
+			if (typeof element === 'string' && element.includes(',')) {
+				primary[key as keyof typeof primary] = rgbToHex(element);
+			}
+		}
+	}
+	const dark = obj.dark;
+	for (const key in dark) {
+		if (Object.hasOwnProperty.call(dark, key)) {
+			const element = dark[key as keyof typeof dark];
+			if (typeof element === 'string' && element.includes(',')) {
+				dark[key as keyof typeof dark] = rgbToHex(element);
+			}
+		}
+	}
+	obj.functional.success = rgbToHex(obj.functional.success);
+	obj.functional.warning = rgbToHex(obj.functional.warning);
+	obj.functional.error = rgbToHex(obj.functional.error);
+	obj.functional.info = rgbToHex(obj.functional.info);
+	const extend = obj.extend;
+	extend.forEach((item) => {
+		item.color = rgbToHex(item.color);
+	});
+	obj.primaryBlack = rgbToHex(obj.primaryBlack);
+	obj.primaryWhite = rgbToHex(obj.primaryWhite);
+	obj.darkBlack = rgbToHex(obj.darkBlack);
+	obj.darkWhite = rgbToHex(obj.darkWhite);
+	theme.color = obj;
+	return theme;
+};
+
+export type ThemeItem = { name: string; name_CN: string; theme: ThemeProps };
+
+const themes: ThemeItem[] = [
+	{ name_CN: 'STDF', name: STDFTheme.name, theme: rgbToHexFunc(STDFTheme) },
+	{ name_CN: '任天堂', name: Nintendo.name, theme: rgbToHexFunc(Nintendo) },
+	{ name_CN: '蔚蓝粉', name: AzurePink.name, theme: rgbToHexFunc(AzurePink) },
+	{ name_CN: '变色龙', name: Chameleon.name, theme: rgbToHexFunc(Chameleon) },
+	{ name_CN: '慧活力', name: SmartLive.name, theme: rgbToHexFunc(SmartLive) },
+	{ name_CN: '山茶红', name: CamelliaRed.name, theme: rgbToHexFunc(CamelliaRed) }
+];
+
+export default themes;

+ 11 - 7
docs/site/src/data/themes/nintendo.js → docs/site/src/data/themes/nintendo.ts

@@ -1,4 +1,6 @@
-export default {
+import type { ThemeProps } from 'stdf/theme';
+
+const Nintendo: ThemeProps = {
 	name: 'Nintendo',
 	color: {
 		primary: {
@@ -12,7 +14,7 @@ export default {
 			700: '192, 0, 22', // #C00016
 			800: '153, 0, 23', // #990017
 			900: '115, 0, 21', // #730015
-			950: '77, 0, 17', // #4D0011
+			950: '77, 0, 17' // #4D0011
 		},
 		dark: {
 			50: '245, 255, 254', // #F5FFFE
@@ -25,7 +27,7 @@ export default {
 			700: '0, 158, 189', // #009EBD
 			800: '0, 121, 152', // #007998
 			900: '0, 87, 114', // #005772
-			950: '0, 56, 77', // #00384D
+			950: '0, 56, 77' // #00384D
 		},
 		primaryBlack: '25, 1, 3', // #190103
 		primaryWhite: '243, 242, 242', // #F3F2F2
@@ -35,12 +37,14 @@ export default {
 			success: '0, 180, 42', // #00b42a
 			warning: '255, 125, 0', // #ff7d00
 			error: '245, 63, 63', // #f53f3f
-			info: '22, 93, 255', // #165dff
+			info: '22, 93, 255' // #165dff
 		},
 		extend: [
 			{ color: '0, 82, 217', alias: 'Tencent' }, // #0052d9
 			{ color: '26, 173, 25', alias: 'WeChat' }, // #1aad19
-			{ color: '243, 112, 33', alias: 'Hermès' }, // #f37021
-		],
-	},
+			{ color: '243, 112, 33', alias: 'Hermès' } // #f37021
+		]
+	}
 };
+
+export default Nintendo;

+ 11 - 7
docs/site/src/data/themes/smartLive.js → docs/site/src/data/themes/smartLive.ts

@@ -1,4 +1,6 @@
-export default {
+import type { ThemeProps } from 'stdf/theme';
+
+const SmartLive: ThemeProps = {
 	name: 'SmartLive',
 	color: {
 		primary: {
@@ -12,7 +14,7 @@ export default {
 			700: '52, 19, 87', // #341357
 			800: '44, 12, 84', // #2C0C54
 			900: '37, 6, 80', // #250650
-			950: '29, 0, 77', // #1D004D
+			950: '29, 0, 77' // #1D004D
 		},
 		dark: {
 			50: '253, 255, 245', // #FDFFF5
@@ -25,7 +27,7 @@ export default {
 			700: '210, 197, 45', // #D2C52D
 			800: '166, 149, 23', // #A69517
 			900: '121, 104, 9', // #796809
-			950: '77, 62, 0', // #4D3E00
+			950: '77, 62, 0' // #4D3E00
 		},
 		primaryBlack: '13, 1, 25', // #0D0119
 		primaryWhite: '242, 242, 243', // #F2F2F3
@@ -35,12 +37,14 @@ export default {
 			success: '21, 91, 54', // #155b36
 			warning: '208, 126, 11', // #d07e0b
 			error: '218, 20, 20', // #da1414
-			info: '99, 176, 227', // #63b0e3
+			info: '99, 176, 227' // #63b0e3
 		},
 		extend: [
 			{ color: '118, 185, 0', alias: 'NVIDIA' }, // #76b900
 			{ color: '251, 114, 153', alias: 'bilibili' }, // #fb7299
-			{ color: '22, 119, 255', alias: 'AliPay' }, // #1677ff
-		],
-	},
+			{ color: '22, 119, 255', alias: 'AliPay' } // #1677ff
+		]
+	}
 };
+
+export default SmartLive;

+ 1 - 0
docs/site/src/global.d.ts

@@ -0,0 +1 @@
+/// <reference types="vite-plugin-md-to-html/types" />

+ 100 - 92
docs/site/src/components/cmdk/CmdK.svelte → docs/site/src/lib/cmdk/CmdK.svelte

@@ -1,37 +1,40 @@
-<script>
+<script lang="ts">
 	import { onMount } from 'svelte';
 	import { fly, fade } from 'svelte/transition';
-	import { location, push, querystring } from 'svelte-spa-router';
-	import { menuList } from '../../data/menuList';
+	import { menuList, type MenuList, type MenuListChild } from '../../data/menuList';
+	import { page } from '$app/stores';
 
 	import { isCmdKStore } from '../../store';
+	import { goto } from '$app/navigation';
 
-	let menuChildList = []; //展开的菜单列表
-	let cmdKValue = ''; //cmd+k搜索框的值
-	let currentIndex = 0; //当前选中的索引
-	let currentTab = 0; //当前选中的tab
-	let cmdFocus = false; //cmd+k搜索框是否获取焦点
-	let cmdKInput = null; //cmd+k搜索框的dom
-	let latelyList = []; //最近使用的列表
-	let isDemoShake = false; //是否显示demo抖动动画
-	let isGuideShake = false; //是否显示guide抖动动画
+	let menuChildList: MenuListChild[] = $state([]); //展开的菜单列表
+	let cmdKValue = $state(''); //cmd+k 搜索框的值
+	let currentIndex = $state(0); //当前选中的索引
+	let currentTab: number = $state(0); //当前选中的 tab
+	let cmdFocus = $state(false); //cmd+k 搜索框是否获取焦点
+	let cmdKInput: HTMLInputElement | null = $state(null); //cmd+k 搜索框的 dom
+	let latelyList: MenuListChild[] = $state([]); //最近使用的列表
+	let isDemoShake = $state(false); //是否显示 demo 抖动动画
+	let isGuideShake = $state(false); //是否显示 guide 抖动动画
 
 	const isZh = localStorage.getItem('lang') === 'zh_CN';
 
-	let params = new URLSearchParams('?' + $querystring);
+	const params = new URLSearchParams('?');
 
-	$: cmdKList = cmdKValue === '' ? latelyList : menuChildList.filter(item => item.alias.indexOf(cmdKValue.toLowerCase()) > -1); //cmd+k搜索框的列表
-	$: currentMenu = cmdKList[currentIndex]; //当前选中的菜单
-
-	//cmd+k搜索框的事件
-	const cmdKFun = e => {
-		// 判断是Windows还是Mac,cmd+k在Windows下是ctrl+k,监听e.ctrlKey,Mac监听 metaKey
+	let cmdKList = $derived(
+		cmdKValue === '' ? latelyList : menuChildList.filter((item: any) => item.alias.indexOf(cmdKValue.toLowerCase()) > -1)
+	); //cmd+k 搜索框的列表
+	let currentMenu = $derived(cmdKList[currentIndex]); //当前选中的菜单
+	//cmd+k 搜索框的事件
+	const cmdKFun = (e: KeyboardEvent) => {
+		// 判断是 Windows 还是 Mac,cmd+k 在 Windows 下是 ctrl+k,监听 e.ctrlKey,Mac 监听 metaKey
 		const isMac = /macintosh|mac os x/i.test(navigator.userAgent);
 		const isWindows = /windows|win32/i.test(navigator.userAgent);
 
-		//按下cmd+k触发事件
-		if (e.keyCode === 75 && ((isMac && e.metaKey) || (isWindows && e.ctrlKey))) {
-			latelyList = JSON.parse(localStorage.getItem('latelyList')) || [];
+		//按下 cmd+k 触发事件
+		if (e.key === 'k' && ((isMac && e.metaKey) || (isWindows && e.ctrlKey))) {
+			const latelyListStr = localStorage.getItem('latelyList');
+			latelyList = latelyListStr ? JSON.parse(latelyListStr) : [];
 			if ($isCmdKStore) {
 				isCmdKStore.set(false);
 				cmdFocus = false;
@@ -42,21 +45,21 @@
 				currentIndex = 0;
 				currentTab = 0;
 				setTimeout(() => {
-					cmdKInput.focus();
+					cmdKInput?.focus();
 				}, 0);
 			}
 			e.preventDefault();
 		}
-		//按下esc触发事件
-		if ($isCmdKStore && e.keyCode === 27) {
+		//按下 esc 触发事件
+		if ($isCmdKStore && e.key === 'Escape') {
 			// 阻止默认事件
 			e.preventDefault();
-			//如果搜索框没有获取焦点,按下esc获取焦点并选定搜索框的值
+			//如果搜索框没有获取焦点,按下 esc 获取焦点并选定搜索框的值
 			if (!cmdFocus) {
 				cmdFocus = true;
 				setTimeout(() => {
-					cmdKInput.focus();
-					cmdKInput.select();
+					cmdKInput?.focus();
+					cmdKInput?.select();
 				}, 0);
 			} else {
 				isCmdKStore.set(false);
@@ -64,13 +67,13 @@
 			}
 		}
 
-		//显示cmd+k搜索框时,按下上下键触发事件
-		if ($isCmdKStore && (e.keyCode === 38 || e.keyCode === 40)) {
+		//显示 cmd+k 搜索框时,按下上下键触发事件
+		if ($isCmdKStore && (e.key === 'ArrowUp' || e.key === 'ArrowDown')) {
 			//阻止默认事件,防止下层滚动
 			e.preventDefault();
 			cmdFocus = false;
-			cmdKInput.blur();
-			if (e.keyCode === 38) {
+			cmdKInput?.blur();
+			if (e.key === 'ArrowUp') {
 				if (currentIndex === 0 && currentTab === 0) {
 					isDemoShake = true;
 					setTimeout(() => {
@@ -85,7 +88,7 @@
 					currentTab--;
 				}
 			}
-			if (e.keyCode === 40) {
+			if (e.key === 'ArrowDown') {
 				if (currentIndex === cmdKList.length - 1 && currentTab === 2) {
 					isGuideShake = true;
 					setTimeout(() => {
@@ -101,13 +104,11 @@
 				}
 			}
 		}
-		//显示cmd+k搜索框时,按下回车键触发事件
-		if ($isCmdKStore && e.keyCode === 13) {
-			//将当前选中的菜单添加到最近使用的列表中,并存储到localStorage中,最多存储5条
-			if (latelyList.length === 0) {
-				latelyList.push(currentMenu);
-			} else {
-				let index = latelyList.findIndex(item => item.alias === currentMenu.alias);
+		//显示 cmd+k 搜索框时,按下回车键触发事件
+		if ($isCmdKStore && e.key === 'Enter') {
+			//将当前选中的菜单添加到最近使用的列表中,并存储到 localStorage 中,最多存储 3 条
+			if (latelyList.length > 0 && latelyList[0]?.nav) {
+				let index = latelyList.findIndex((item) => item.alias === currentMenu.alias);
 				if (index > -1) {
 					latelyList.splice(index, 1);
 				}
@@ -115,17 +116,22 @@
 				if (latelyList.length > 3) {
 					latelyList.pop();
 				}
+			} else {
+				latelyList.push(currentMenu);
+			}
+			if (latelyList.length > 0 && latelyList[0]?.nav) {
+				// 去重
+				latelyList = Array.from(new Set(latelyList));
+				localStorage.setItem('latelyList', JSON.stringify(latelyList));
 			}
-			localStorage.setItem('latelyList', JSON.stringify(latelyList));
 
 			isCmdKStore.set(false);
 			cmdFocus = false;
 			cmdKValue = '';
 			params.set('nav', currentMenu.nav);
-			// @ts-ignore
-			params.set('tab', currentTab);
-			push(`/components?nav=${currentMenu.nav}&tab=${currentTab}`);
-			if ($location === '/components') {
+			params.set('tab', currentTab.toString());
+			goto(`/components?nav=${currentMenu.nav}&tab=${currentTab}`);
+			if ($page.url.pathname.includes('/components')) {
 				setTimeout(() => {
 					window.location.reload();
 				}, 0);
@@ -133,12 +139,12 @@
 		}
 	};
 	//点击搜索框的事件
-	const clickCmdKFun = (item, index) => {
-		//将当前选中的菜单添加到最近使用的列表中,并存储到localStorage中,最多存储5条
+	const clickCmdKFun = (item: MenuListChild, index: number) => {
+		//将当前选中的菜单添加到最近使用的列表中,并存储到 localStorage 中,最多存储 5 
 		if (latelyList.length === 0) {
 			latelyList.push(item);
 		} else {
-			let index = latelyList.findIndex(item => item.alias === item.alias);
+			let index = latelyList.findIndex((item) => item.alias === item.alias);
 			if (index > -1) {
 				latelyList.splice(index, 1);
 			}
@@ -153,33 +159,35 @@
 		cmdFocus = false;
 		cmdKValue = '';
 		params.set('nav', item.nav);
-		params.set('tab', index);
-		push(`/components?nav=${item.nav}&tab=${index}`);
-		if ($location === '/components') {
+		params.set('tab', index.toString());
+		if ($page.url.pathname === '/components') {
 			setTimeout(() => {
 				window.location.reload();
 			}, 0);
 		}
 	};
-	//关闭cmd+k搜索框
+	//关闭 cmd+k 搜索框
 	const closeCmdKFun = () => {
 		isCmdKStore.set(false);
 		cmdFocus = false;
 	};
-	$: {
+	$effect(() => {
 		if ($isCmdKStore) {
-			latelyList = JSON.parse(localStorage.getItem('latelyList')) || [];
+			const latelyListStr = localStorage.getItem('latelyList');
+			console.log(8978, latelyListStr);
+
+			latelyList = latelyListStr ? JSON.parse(latelyListStr) : [];
 			isCmdKStore.set(true);
 			cmdFocus = true;
 			currentIndex = 0;
 			currentTab = 0;
 			setTimeout(() => {
-				cmdKInput.focus();
+				cmdKInput?.focus();
 			}, 0);
 		}
-	}
+	});
 	//数组二级组成新数组
-	const ArrChildFun = arr => {
+	const ArrChildFun = (arr: MenuList[]) => {
 		let newArr = [];
 		for (let e = 0; e < arr.length; e++) {
 			newArr.push(...arr[e].childs);
@@ -191,22 +199,22 @@
 	});
 </script>
 
-<svelte:window on:keydown={cmdKFun} />
-<!-- svelte-ignore a11y-click-events-have-key-events -->
-<!-- svelte-ignore a11y-no-static-element-interactions -->
+<svelte:window onkeydown={cmdKFun} />
+<!-- svelte-ignore a11y_click_events_have_key_events -->
+<!-- svelte-ignore a11y_no_static_element_interactions -->
 {#if $isCmdKStore}
 	<div
 		transition:fade={{ duration: 50 }}
-		class="fixed top-0 left-0 w-screen h-screen backdrop-blur bg-black/20 flex flex-col pt-20"
+		class="fixed left-0 top-0 flex h-screen w-screen flex-col bg-black/20 pt-20 text-left backdrop-blur"
 		style="z-index: 10000"
-		on:click={closeCmdKFun}
+		onclick={closeCmdKFun}
 	>
 		<div
 			in:fly={{ y: 100, duration: 300, delay: 50 }}
-			class="bg-white dark:bg-black shadow-lg rounded-xl mx-auto w-1/2"
-			on:click|stopPropagation
+			class="mx-auto w-1/2 rounded-xl bg-white shadow-lg dark:bg-black"
+			onclick={(e: Event) => e.stopPropagation()}
 		>
-			<div class="flex items-center text-sm text-gray-500 py-3 px-4 border-b border-black/10 dark:border-white/10">
+			<div class="flex items-center border-b border-black/10 px-4 py-3 text-sm text-gray-500 dark:border-white/10">
 				<div class="">
 					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" style="fill: currentColor;">
 						<path fill="none" d="M0 0h24v24H0z" />
@@ -219,16 +227,16 @@
 					<input
 						bind:this={cmdKInput}
 						bind:value={cmdKValue}
-						class="w-full dark:bg-black focus:outline-none focus:ring-b caret-primary dark:caret-dark placeholder:text-black/20 dark:placeholder:text-white/10"
+						class="focus:ring-b w-full caret-primary placeholder:text-black/20 focus:outline-none dark:bg-black dark:caret-dark dark:placeholder:text-white/10"
 						type="text"
 						placeholder={isZh ? '请输入组件关键字' : 'Please enter the component keyword'}
 					/>
 				</div>
-				<div class="border border-black/10 dark:border-white/10 py-1 px-2 rounded text-xs font-bold">ESC</div>
+				<div class="rounded border border-black/10 px-2 py-1 text-xs font-bold dark:border-white/10">ESC</div>
 			</div>
-			<div class="px-6 pb-6 overflow-y-auto" style="max-height: {(document.documentElement.clientHeight * 3) / 4}px">
+			<div class="overflow-y-auto px-6 pb-6" style="max-height: {(document.documentElement.clientHeight * 3) / 4}px">
 				{#if cmdKValue === ''}
-					<div class="text-xs mt-2 text-black/50 dark:text-white/30">
+					<div class="mt-2 text-xs text-black/50 dark:text-white/30">
 						{#if latelyList.length === 0}
 							{isZh ? `最近无搜索,请输入关键字搜索。` : `No recent searches, please enter a keyword to search.`}
 						{:else}
@@ -238,11 +246,11 @@
 				{/if}
 				{#if cmdKValue !== ''}
 					{#if cmdKList.length === 0}
-						<div class="text-xs mt-2 text-black/50 dark:text-white/30">
+						<div class="mt-2 text-xs text-black/50 dark:text-white/30">
 							{isZh ? '没有搜索到结果' : 'No results found'}
 						</div>
 					{:else}
-						<div class="text-xs mt-2 text-black/50 dark:text-white/30">
+						<div class="mt-2 text-xs text-black/50 dark:text-white/30">
 							{isZh
 								? `搜索到包含 "${cmdKValue}" 的 ${cmdKList.length} 条结果`
 								: `Found ${cmdKList.length} results containing "${cmdKValue}"`}
@@ -251,19 +259,19 @@
 				{/if}
 				{#each cmdKList as item, index}
 					<div>
-						<div class="font-bold text-lg py-2 mt-4">{isZh ? item.title : item.title_en}</div>
-						<div class="border-l border-black/10 dark:border-white/10 pl-3">
+						<div class="mt-4 py-2 text-lg font-bold">{isZh ? item?.title : item?.title_en}</div>
+						<div class="border-l border-black/10 pl-3 dark:border-white/10">
 							<button
-								class="w-full py-2 pl-4 my-2 flex justify-between rounded cursor-pointer border {index === currentIndex && currentTab === 0
-									? 'border-primary dark:border-dark bg-primary dark:bg-dark text-white dark:text-black'
-									: 'border-primary-50 dark:border-dark-950 text-balck dark:text-white'}"
+								class="my-2 flex w-full cursor-pointer justify-between rounded border py-2 pl-4 {index === currentIndex && currentTab === 0
+									? 'border-primary bg-primary text-white dark:border-dark dark:bg-dark dark:text-black'
+									: 'text-balck border-primary-50 dark:border-dark-950 dark:text-white'}"
 								class:animate-shake={isDemoShake && index === 0}
-								on:click={() => clickCmdKFun(item, 0)}
+								onclick={() => clickCmdKFun(item, 0)}
 							>
 								<div>{isZh ? '示例' : 'Demo'}</div>
 								<div>
 									<svg
-										class={`${index === currentIndex && currentTab === 0 ? 'fill-white dark:fill-black' : 'fill-gray-500'}`}
+										class={index === currentIndex && currentTab === 0 ? 'fill-white dark:fill-black' : 'fill-gray-500'}
 										xmlns="http://www.w3.org/2000/svg"
 										viewBox="0 0 24 24"
 										width="24"
@@ -275,15 +283,15 @@
 								</div>
 							</button>
 							<button
-								class="w-full py-2 pl-4 my-2 flex justify-between rounded cursor-pointer border {index === currentIndex && currentTab === 1
-									? 'border-primary dark:border-dark bg-primary dark:bg-dark text-white dark:text-black'
-									: 'border-primary-50 dark:border-dark-950 text-balck dark:text-white'}"
-								on:click={() => clickCmdKFun(item, 1)}
+								class="my-2 flex w-full cursor-pointer justify-between rounded border py-2 pl-4 {index === currentIndex && currentTab === 1
+									? 'border-primary bg-primary text-white dark:border-dark dark:bg-dark dark:text-black'
+									: 'text-balck border-primary-50 dark:border-dark-950 dark:text-white'}"
+								onclick={() => clickCmdKFun(item, 1)}
 							>
 								<div>API</div>
 								<div>
 									<svg
-										class={`${index === currentIndex && currentTab === 1 ? 'fill-white dark:fill-black' : 'fill-gray-500'}`}
+										class={index === currentIndex && currentTab === 1 ? 'fill-white dark:fill-black' : 'fill-gray-500'}
 										xmlns="http://www.w3.org/2000/svg"
 										viewBox="0 0 24 24"
 										width="24"
@@ -295,16 +303,16 @@
 								</div>
 							</button>
 							<button
-								class="w-full py-2 pl-4 my-2 flex justify-between rounded cursor-pointer border {index === currentIndex && currentTab === 2
-									? 'border-primary dark:border-dark bg-primary dark:bg-dark text-white dark:text-black'
-									: 'border-primary-50 dark:border-dark-950 text-balck dark:text-white'}"
+								class="my-2 flex w-full cursor-pointer justify-between rounded border py-2 pl-4 {index === currentIndex && currentTab === 2
+									? 'border-primary bg-primary text-white dark:border-dark dark:bg-dark dark:text-black'
+									: 'text-balck border-primary-50 dark:border-dark-950 dark:text-white'}"
 								class:animate-shake={isGuideShake && index === cmdKList.length - 1}
-								on:click={() => clickCmdKFun(item, 2)}
+								onclick={() => clickCmdKFun(item, 2)}
 							>
 								<div>{isZh ? '指南' : 'Guide'}</div>
 								<div>
 									<svg
-										class={`${index === currentIndex && currentTab === 2 ? 'fill-white dark:fill-black' : 'fill-gray-500'}`}
+										class={index === currentIndex && currentTab === 2 ? 'fill-white dark:fill-black' : 'fill-gray-500'}
 										xmlns="http://www.w3.org/2000/svg"
 										viewBox="0 0 24 24"
 										width="24"
@@ -319,9 +327,9 @@
 					</div>
 				{/each}
 			</div>
-			<div class="flex gap-4 px-4 py-2 text-xs opacity-60 border-t border-black/10 dark:border-white/10">
+			<div class="flex gap-4 border-t border-black/10 px-4 py-2 text-xs opacity-60 dark:border-white/10">
 				<div class="flex gap-1">
-					<div class="w-4 h-4">
+					<div class="h-4 w-4">
 						<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="fill-black dark:fill-white">
 							<path
 								d="M19.0003 13.9999L19.0004 5.00003L17.0004 5L17.0003 11.9999L6.82845 12L10.7782 8.05027L9.36396 6.63606L3 13L9.36396 19.364L10.7782 17.9498L6.8284 14L19.0003 13.9999Z"
@@ -331,7 +339,7 @@
 					{isZh ? '选择' : 'Select'}
 				</div>
 				<div class="flex gap-1">
-					<div class="w-4 h-4">
+					<div class="h-4 w-4">
 						<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="fill-black dark:fill-white"
 							><path
 								d="M12.9999 16.1716L18.3638 10.8076L19.778 12.2218L11.9999 20L4.22168 12.2218L5.63589 10.8076L10.9999 16.1716V4H12.9999V16.1716Z"
@@ -341,7 +349,7 @@
 					{isZh ? '向下' : 'Down'}
 				</div>
 				<div class="flex gap-1">
-					<div class="w-4 h-4">
+					<div class="h-4 w-4">
 						<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="fill-black dark:fill-white"
 							><path
 								d="M12.9999 7.82843V20H10.9999V7.82843L5.63589 13.1924L4.22168 11.7782L11.9999 4L19.778 11.7782L18.3638 13.1924L12.9999 7.82843Z"

+ 4 - 4
docs/site/src/components/colorCard/ColorCard.svelte → docs/site/src/lib/colorCard/ColorCard.svelte

@@ -1,9 +1,9 @@
-<script>
+<script lang="ts">
 	import Color from 'color';
 	let { colorList = [] } = $props();
 
 	// 传入 hsl(222, 100%, 98%) 这种字符,将其中的数字四舍五入取整后返回字符
-	const getHslFunc = str => {
+	const getHslFunc = (str: string) => {
 		const arr = str.split(',');
 		const h = Math.round(Number(arr[0].split('(')[1]));
 		const s = Math.round(Number(arr[1].split('%')[0]));
@@ -14,13 +14,13 @@
 
 {#each colorList as color, index}
 	<div
-		class="flex-1 flex justify-between self-center w-full px-4 md:py-0 transition hover:scale-105 hover:rounded {index > 5
+		class="flex w-full flex-1 justify-between self-center px-4 transition hover:scale-105 hover:rounded md:py-0 {index > 5
 			? 'text-white'
 			: 'text-black'}"
 		style="background-color: {color.hex};"
 	>
 		<div class="flex flex-col justify-center text-sm">{color.key}</div>
-		<div class="mt-2 flex flex-col justify-center text-right py-1 text-xs">
+		<div class="mt-2 flex flex-col justify-center py-1 text-right text-xs">
 			<div>{color.hex || ''}</div>
 			<div>{Color(color.hex).rgb().string()}</div>
 			<div>{getHslFunc(Color(color.hex).hsl().string())}</div>

+ 57 - 49
docs/site/src/components/fund/Fund.svelte → docs/site/src/lib/fund/Fund.svelte

@@ -1,11 +1,11 @@
-<script>
+<script lang="ts">
 	import { fly, fade } from 'svelte/transition';
 	import { isShowFundStore } from '../../store';
 
 	const isZh = localStorage.getItem('lang') === 'zh_CN';
 
-	let showWeChatPay = false;
-	let showAlipayPay = false;
+	let showWeChatPay = $state(false);
+	let showAlipayPay = $state(false);
 
 	// 判断是否是桌面设备
 	const isDeskDeviceFunc = () => {
@@ -14,20 +14,20 @@
 	const isDeskDevice = isDeskDeviceFunc();
 </script>
 
-<!-- svelte-ignore a11y-click-events-have-key-events -->
-<!-- svelte-ignore a11y-no-static-element-interactions -->
+<!-- svelte-ignore a11y_click_events_have_key_events -->
+<!-- svelte-ignore a11y_no_static_element_interactions -->
 <div
 	transition:fade
-	class="fixed top-0 left-0 w-screen h-screen backdrop-blur bg-black/20 flex flex-col justify-center"
+	class="fixed left-0 top-0 flex h-screen w-screen flex-col justify-center bg-black/20 backdrop-blur"
 	style="z-index: 1000"
-	on:click={() => {
+	onclick={() => {
 		isShowFundStore.set(false);
 	}}
 >
 	<div
 		in:fly={{ y: -400 }}
-		class="bg-white dark:bg-gray-950 shadow-lg rounded-xl mx-auto w-full md:w-[800px] p-4 md:p-8"
-		on:click|stopPropagation
+		class="mx-auto w-full rounded-xl bg-white p-4 shadow-lg dark:bg-gray-950 md:w-[800px] md:p-8"
+		onclick={(e: Event) => e.stopPropagation()}
 	>
 		<div class="flex justify-between">
 			<div class="text-xl font-bold">{isZh ? '支持' : 'Support'}</div>
@@ -38,34 +38,34 @@
 			</div>
 		</div>
 		{#if isDeskDevice || (!showWeChatPay && !showAlipayPay)}
-			<div class="mt-2 md:mt-8 text-xs text-gray-500">
+			<div class="mt-2 text-xs text-gray-500 md:mt-8">
 				<p>
 					{isZh
 						? 'STDF 是一个免费开源、使用简单但很用心的组件库,在组件设计与开发、配套工具的提供、文档站点运营等方面投入了大量的时间、物力和精力。如果 STDF 确实给您带去了方便,希望您不吝啬您的喜爱之情支持 STDF 的工作,给一个 star 或打赏,非常感谢!'
 						: 'STDF is a free and open source, easy to use but very attentive component library, which has invested a lot of time, material and energy in component design and development, supporting tool provision, document site operation, etc. If STDF does bring you convenience, I hope you will not hesitate to support STDF work with your love, give a star or reward, thank you very much!'}
 				</p>
-				<p class="mt-2 text-md font-bold">
+				<p class="text-md mt-2 font-bold">
 					{isZh ? '无论如何,STDF 都会出于热爱并继续努力!' : 'In any case, STDF will continue to work hard out of love!'}
 				</p>
 			</div>
 		{/if}
-		<div class="grid {showWeChatPay || showAlipayPay ? 'grid-cols-1' : 'grid-cols-2'}  md:grid-cols-4 gap-2 mt-4 md:mt-10 text-center">
+		<div class="grid {showWeChatPay || showAlipayPay ? 'grid-cols-1' : 'grid-cols-2'}  mt-4 gap-2 text-center md:mt-10 md:grid-cols-4">
 			<!-- coffee -->
 			{#if isDeskDevice || (!showWeChatPay && !showAlipayPay)}
 				<div
-					class="border border-black/10 dark:border-white/10 rounded-lg w-full md:w-40 flex flex-col justify-center py-1 md:py-12 group md:relative"
+					class="group flex w-full flex-col justify-center rounded-lg border border-black/10 py-1 dark:border-white/10 md:relative md:w-40 md:py-12"
 				>
-					<div class="h-8 w-6 mx-auto">
-						<img class="w-full h-full object-cover" src="/assets/fund/coffee.svg" alt="coffee" />
+					<div class="mx-auto h-8 w-6">
+						<img class="h-full w-full object-cover" src="/assets/fund/coffee.svg" alt="coffee" />
 					</div>
-					<a class="block md:hidden mx-2" href="https://www.buymeacoffee.com/dufu1991" target="_blank">
+					<a class="mx-2 block md:hidden" href="https://www.buymeacoffee.com/dufu1991" target="_blank">
 						<div class="text-center font-bold after:content-['_↗']">Buy Me a Coffee</div>
 						<div class="mt-1 text-xs text-gray-500">
 							{isZh ? '推荐非中国地区使用' : 'Recommended for Non-China Regions'}
 						</div>
 					</a>
 					<a
-						class="hidden md:block absolute inset-1 bg-white dark:bg-gray-950 w-[95%] h-[95%] px-1 py-12 transition-all duration-500 opacity-0 group-hover:opacity-95"
+						class="absolute inset-1 hidden h-[95%] w-[95%] bg-white px-1 py-12 opacity-0 transition-all duration-500 group-hover:opacity-95 dark:bg-gray-950 md:block"
 						href="https://www.buymeacoffee.com/dufu1991"
 						target="_blank"
 					>
@@ -79,19 +79,19 @@
 			<!-- paypal -->
 			{#if isDeskDevice || (!showWeChatPay && !showAlipayPay)}
 				<div
-					class="border border-black/10 dark:border-white/10 rounded-lg w-full md:w-40 flex flex-col justify-center py-1 md:py-12 group md:relative"
+					class="group flex w-full flex-col justify-center rounded-lg border border-black/10 py-1 dark:border-white/10 md:relative md:w-40 md:py-12"
 				>
-					<div class="h-8 w-8 mx-auto">
-						<img class="w-full h-full object-cover" src="/assets/fund/paypal.svg" alt="paypal" />
+					<div class="mx-auto h-8 w-8">
+						<img class="h-full w-full object-cover" src="/assets/fund/paypal.svg" alt="paypal" />
 					</div>
-					<a class="block md:hidden mx-2" href="https://paypal.me/dufu1991" target="_blank">
+					<a class="mx-2 block md:hidden" href="https://paypal.me/dufu1991" target="_blank">
 						<div class="text-center font-bold after:content-['_↗']">PayPal</div>
 						<div class="mt-1 text-xs text-gray-500">
 							{isZh ? '推荐非中国地区使用' : 'Recommended for Non-China Regions'}
 						</div>
 					</a>
 					<a
-						class="hidden md:block absolute inset-1 bg-white dark:bg-gray-950 w-[95%] h-[95%] px-1 py-12 transition-all duration-500 opacity-0 group-hover:opacity-95"
+						class="absolute inset-1 hidden h-[95%] w-[95%] bg-white px-1 py-12 opacity-0 transition-all duration-500 group-hover:opacity-95 dark:bg-gray-950 md:block"
 						href="https://paypal.me/dufu1991"
 						target="_blank"
 					>
@@ -105,47 +105,51 @@
 			<!-- wechat -->
 			{#if isDeskDevice || !showAlipayPay}
 				<div
-					class="border border-black/10 dark:border-white/10 rounded-lg w-full md:w-40 flex flex-col justify-center py-1 md:py-12 group md:relative"
+					class="group flex w-full flex-col justify-center rounded-lg border border-black/10 py-1 dark:border-white/10 md:relative md:w-40 md:py-12"
 				>
-					<div class="h-8 w-10 mx-auto" class:hidden={showWeChatPay}>
-						<img class="w-full h-full object-cover" src="/assets/fund/wechat_pay.svg" alt="wechat" />
+					<div class="mx-auto h-8 w-10" class:hidden={showWeChatPay}>
+						<img class="h-full w-full object-cover" src="/assets/fund/wechat_pay.svg" alt="wechat" />
 					</div>
 					<div
-						class="block md:hidden mx-2"
-						on:click={() => {
+						class="mx-2 block md:hidden"
+						onclick={() => {
 							showWeChatPay = !showWeChatPay;
 						}}
 					>
 						{#if showWeChatPay}
 							<div class="mt-1">
-								<img class="w-3/5 mx-auto object-cover" src="/assets/fund/wp_code.png" alt="wechat" />
+								<img class="mx-auto w-3/5 object-cover" src="/assets/fund/wp_code.png" alt="wechat" />
 							</div>
-							<div class="text-xs text-gray-500 mt-1">
+							<div class="mt-1 text-xs text-gray-500">
 								{isZh ? '微信扫一扫' : 'WeChat Scan'}
 							</div>
 						{:else}
-							<div class="text-center font-bold after:content-['_↗']">{isZh ? '微信赞赏' : 'WeChat Reward'}</div>
+							<div class="text-center font-bold after:content-['_↗']">
+								{isZh ? '微信赞赏' : 'WeChat Reward'}
+							</div>
 							<div class="mt-1 text-xs text-gray-500">
 								{isZh ? '推荐中国地区使用' : 'Recommended for China Regions'}
 							</div>
 						{/if}
 					</div>
 					<button
-						on:click={() => {
+						onclick={() => {
 							showWeChatPay = !showWeChatPay;
 						}}
-						class="hidden md:block absolute cursor-pointer inset-1 bg-white dark:bg-gray-950 w-[95%] h-[95%] px-1 transition-all duration-500 opacity-0 group-hover:opacity-95"
+						class="absolute inset-1 hidden h-[95%] w-[95%] cursor-pointer bg-white px-1 opacity-0 transition-all duration-500 group-hover:opacity-95 dark:bg-gray-950 md:block"
 						class:opacity-95={showWeChatPay}
 					>
 						{#if showWeChatPay}
 							<div class="mt-0.5">
-								<img class="w-[70%] mx-auto object-cover" src="/assets/fund/wp_code.png" alt="wechat" />
+								<img class="mx-auto w-[70%] object-cover" src="/assets/fund/wp_code.png" alt="wechat" />
 							</div>
-							<div class="text-xs text-gray-500 mt-0.5">
+							<div class="mt-0.5 text-xs text-gray-500">
 								{isZh ? '微信扫一扫' : 'WeChat Scan'}
 							</div>
 						{:else}
-							<div class="text-center font-bold after:content-['_↗'] mt-12">{isZh ? '微信赞赏' : 'WeChat Reward'}</div>
+							<div class="mt-12 text-center font-bold after:content-['_↗']">
+								{isZh ? '微信赞赏' : 'WeChat Reward'}
+							</div>
 							<div class="mt-1 text-xs text-gray-500">
 								{isZh ? '推荐中国地区使用' : 'Recommended for China Regions'}
 							</div>
@@ -156,47 +160,51 @@
 			<!-- alipay -->
 			{#if isDeskDevice || !showWeChatPay}
 				<div
-					class="border border-black/10 dark:border-white/10 rounded-lg w-full mx-auto md:w-40 flex flex-col justify-center py-1 md:py-12 group md:relative"
+					class="group mx-auto flex w-full flex-col justify-center rounded-lg border border-black/10 py-1 dark:border-white/10 md:relative md:w-40 md:py-12"
 				>
-					<div class="h-8 w-8 mx-auto" class:hidden={showAlipayPay}>
-						<img class="w-full h-full object-cover" src="/assets/fund/alipay.svg" alt="alipay" />
+					<div class="mx-auto h-8 w-8" class:hidden={showAlipayPay}>
+						<img class="h-full w-full object-cover" src="/assets/fund/alipay.svg" alt="alipay" />
 					</div>
 					<div
-						class="block md:hidden mx-2"
-						on:click={() => {
+						class="mx-2 block md:hidden"
+						onclick={() => {
 							showAlipayPay = !showAlipayPay;
 						}}
 					>
 						{#if showAlipayPay}
 							<div class="m-1">
-								<img class="w-3/5 mx-auto object-cover" src="/assets/fund/ap_code.png" alt="alipay" />
+								<img class="mx-auto w-3/5 object-cover" src="/assets/fund/ap_code.png" alt="alipay" />
 							</div>
-							<div class="text-xs text-gray-500 mt-1">
+							<div class="mt-1 text-xs text-gray-500">
 								{isZh ? '支付宝扫一扫' : 'Alipay Scan'}
 							</div>
 						{:else}
-							<div class="text-center font-bold after:content-['_↗']">{isZh ? '支付宝收款' : 'Alipay Payment'}</div>
+							<div class="text-center font-bold after:content-['_↗']">
+								{isZh ? '支付宝收款' : 'Alipay Payment'}
+							</div>
 							<div class="mt-1 text-xs text-gray-500">
 								{isZh ? '推荐中国地区使用' : 'Recommended for China Regions'}
 							</div>
 						{/if}
 					</div>
 					<button
-						on:click={() => {
+						onclick={() => {
 							showAlipayPay = !showAlipayPay;
 						}}
-						class="hidden md:block absolute cursor-pointer inset-1 bg-white dark:bg-gray-950 w-[95%] h-[95%] px-1 transition-all duration-500 opacity-0 group-hover:opacity-95"
+						class="absolute inset-1 hidden h-[95%] w-[95%] cursor-pointer bg-white px-1 opacity-0 transition-all duration-500 group-hover:opacity-95 dark:bg-gray-950 md:block"
 						class:opacity-95={showAlipayPay}
 					>
 						{#if showAlipayPay}
 							<div class="mt-0.5">
-								<img class="w-[70%] mx-auto object-cover" src="/assets/fund/ap_code.png" alt="wechat" />
+								<img class="mx-auto w-[70%] object-cover" src="/assets/fund/ap_code.png" alt="wechat" />
 							</div>
-							<div class="text-xs text-gray-500 mt-0.5">
+							<div class="mt-0.5 text-xs text-gray-500">
 								{isZh ? '支付宝扫一扫' : 'Alipay Scan'}
 							</div>
 						{:else}
-							<div class="text-center font-bold after:content-['_↗'] mt-12">{isZh ? '支付宝收款' : 'Alipay Payment'}</div>
+							<div class="mt-12 text-center font-bold after:content-['_↗']">
+								{isZh ? '支付宝收款' : 'Alipay Payment'}
+							</div>
 							<div class="mt-1 text-xs text-gray-500">
 								{isZh ? '推荐中国地区使用' : 'Recommended for China Regions'}
 							</div>
@@ -205,7 +213,7 @@
 				</div>
 			{/if}
 		</div>
-		<div class="mt-4 md:mt-8 text-xs text-gray-500">
+		<div class="mt-4 text-xs text-gray-500 md:mt-8">
 			{isZh
 				? '如果愿意的话,捐赠留言请注明 GitHub 或其他社交账号或相关链接地址,STDF 将在仓库与站点展示并感谢您们!'
 				: 'If you are willing, please leave a message for donation with your GitHub or other social account or related link address. STDF will display and thank you in the warehouse and website!'}

+ 55 - 62
docs/site/src/components/header/Header.svelte → docs/site/src/lib/header/Header.svelte

@@ -1,29 +1,28 @@
-<script>
-	import { afterUpdate, createEventDispatcher } from 'svelte';
+<script lang="ts">
 	import { slide } from 'svelte/transition';
-	import { location } from 'svelte-spa-router';
 	import ModeSwitch from '../modeSwitch/ModeSwitch.svelte';
 	import ThemeSwitch from '../themeSwitch/ThemeSwitch.svelte';
 	import { isShowNavStore, isShowFundStore, showThemeSwitchStore } from '../../store';
+	import { page } from '$app/stores';
 
-	let currentRoute = '/guide';
-	afterUpdate(() => {
-		currentRoute = $location;
+	let { showLeftNav = false, showBottonLine = false, onclickCmdK } = $props();
+
+	let currentRoute = $state('/guide');
+	$effect(() => {
+		currentRoute = $page.url.pathname;
 	});
-	export let showLeftNav = false; //是否显示左侧导航
-	export let showBottonLine = false;
-	let showNav = false; //是否显示导航
+	let showNav = $state(false); //是否显示导航
 	const toggleNavFun = () => {
 		isShowNavStore.set(!$isShowNavStore);
 	};
-	//判断是Mac系统
+	//判断是 Mac 系统
 	const isMac = navigator.userAgent.toUpperCase().indexOf('MAC') >= 0;
 	const cmdkey = isMac ? '⌘' : 'Ctrl';
 	const isZh = localStorage.getItem('lang') === 'zh_CN';
 
-	const dispatch = createEventDispatcher(); //创建事件派发器
+	// const dispatch = createEventDispatcher(); //创建事件派发器
 	const clickCmdKFun = () => {
-		dispatch('clickCmdK');
+		onclickCmdK?.();
 	};
 	// 切换语言
 	const toggleLangFunc = () => {
@@ -35,7 +34,7 @@
 		window.location.href = `${currentUrl}${hasQuery ? '&' : '?'}lang=${isZh ? 'en_US' : 'zh_CN'}`;
 		setTimeout(() => {
 			window.location.reload();
-		}, 120);
+		}, 300);
 	};
 	// 切换支持
 	const toggleFundFunc = () => {
@@ -45,25 +44,22 @@
 	const showThemeFunc = () => {
 		showThemeSwitchStore.set(!$showThemeSwitchStore);
 	};
-	let ThemeSwitchDom = null;
-	// 监听window点击事件,如果点击的不是 ThemeSwitchDom,则隐藏主题切换
-	window.addEventListener('click', (e) => {
-		if (ThemeSwitchDom && !ThemeSwitchDom.contains(e.target)) {
+	let ThemeSwitchDom: HTMLButtonElement | null = $state(null);
+	// 监听 window 点击事件,如果点击的不是 ThemeSwitchDom,则隐藏主题切换
+	window.addEventListener('click', (e: MouseEvent) => {
+		if (ThemeSwitchDom && !ThemeSwitchDom.contains(e.target as Node)) {
 			showThemeSwitchStore.set(false);
 		}
 	});
 </script>
 
 <div
-	class={`${
-		showBottonLine ? 'border-b border-black/10 dark:border-white/10 ' : ''
-	}flex sticky top-0 z-[100] h-14 items-center justify-between backdrop-blur`}
-	aria-label="Global"
+	class="{showBottonLine
+		? 'border-b border-black/10 dark:border-white/10 '
+		: ''}flex sticky top-0 z-[100] h-14 items-center justify-between backdrop-blur"
 >
 	{#if showLeftNav}
-		<!-- svelte-ignore a11y-click-events-have-key-events -->
-		<!-- svelte-ignore a11y-no-static-element-interactions -->
-		<div class="cursor-pointer p-4 md:hidden" on:click={toggleNavFun}>
+		<button class="cursor-pointer p-4 md:hidden" onclick={toggleNavFun}>
 			{#if !$isShowNavStore}
 				<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
 					<path d="M21.0001 4.50004L7.50007 4.5L7.50006 6L21.0001 6.00004V4.50004Z" fill="currentColor" />
@@ -81,12 +77,12 @@
 					/>
 				</svg>
 			{/if}
-		</div>
+		</button>
 	{/if}
 	<!-- main -> next -->
 	<div class="flex items-end">
-		<a href="#/" class="flex items-center justify-between py-2 pl-6" aria-label={isZh ? '首页' : 'Home'}>
-			<div class="fill-primary flex h-8 w-16 flex-col items-center justify-center" title={isZh ? '首页' : 'Home'}>
+		<a href="/" class="flex items-center justify-between py-2 pl-6" aria-label={isZh ? '首页' : 'Home'}>
+			<div class="flex h-8 w-16 flex-col items-center justify-center fill-primary" title={isZh ? '首页' : 'Home'}>
 				<svg viewBox="0 0 90 80">
 					<path
 						class="fill-primary dark:fill-dark"
@@ -96,17 +92,11 @@
 				</svg>
 			</div>
 		</a>
-		<span class="text-primary dark:text-dark text-sm">v1.0.0@next</span>
+		<span class="text-sm text-primary dark:text-dark">v1.0.0@next</span>
 	</div>
 	<div>
 		<div class="cursor-pointer p-4 md:hidden">
-			<!-- svelte-ignore a11y-click-events-have-key-events -->
-			<!-- svelte-ignore a11y-no-static-element-interactions -->
-			<div
-				on:click={() => {
-					showNav = !showNav;
-				}}
-			>
+			<button onclick={() => (showNav = !showNav)}>
 				{#if !showNav}
 					<svg width="24" height="24" fill="none" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
 						<path
@@ -125,29 +115,27 @@
 						/>
 					</svg>
 				{/if}
-			</div>
+			</button>
 			{#if showNav}
 				<!-- 移动端 -->
 				<div
 					class="absolute right-2 top-16 flex flex-col space-y-4 rounded border border-black/10 bg-white p-1 pt-4 text-center font-bold shadow-lg backdrop-blur dark:border-white/20 dark:bg-gray-950 dark:shadow-white/20"
 				>
 					<a
-						href="#/guide"
+						href="/guide"
 						class="rounded px-4 py-1 hover:bg-gray-100 dark:hover:bg-gray-700"
 						class:bg-gray-100={currentRoute === '/guide'}
 						class:dark:bg-gray-500={currentRoute === '/guide'}>{isZh ? '指南' : 'Guide'}</a
 					>
 					<a
-						href="#/components?nav=button&tab=0"
+						href="/components?nav=button&tab=0"
 						class="rounded px-4 py-1 hover:bg-gray-100 dark:hover:bg-gray-700"
 						class:bg-gray-100={currentRoute === '/components'}
 						class:dark:bg-gray-500={currentRoute === '/components'}>{isZh ? '组件' : 'Components'}</a
 					>
-					<!-- svelte-ignore a11y-click-events-have-key-events -->
-					<!-- svelte-ignore a11y-no-static-element-interactions -->
 					<button
 						class="relative rounded px-4 py-1 hover:bg-gray-100 dark:hover:bg-gray-700"
-						on:click={showThemeFunc}
+						onclick={showThemeFunc}
 						bind:this={ThemeSwitchDom}
 					>
 						{isZh ? '主题' : 'Theme'}
@@ -161,16 +149,16 @@
 							</div>
 						{/if}
 					</button>
-					<!-- svelte-ignore a11y-click-events-have-key-events -->
-					<!-- svelte-ignore a11y-no-static-element-interactions -->
-					<div class="rounded px-4 py-1 text-center hover:bg-gray-100 dark:hover:bg-gray-700" on:click={toggleFundFunc}>
+					<button class="rounded px-4 py-1 text-center hover:bg-gray-100 dark:hover:bg-gray-700" onclick={toggleFundFunc}>
 						{isZh ? '支持' : 'Support'}
-					</div>
+					</button>
 
 					<!-- 语言切换 -->
-					<!-- svelte-ignore a11y-click-events-have-key-events -->
-					<!-- svelte-ignore a11y-no-static-element-interactions -->
-					<div class="rounded px-4 py-1 text-center hover:bg-gray-100 dark:hover:bg-gray-700" on:click={toggleLangFunc}>
+					<button
+						aria-label={isZh ? '切换语言' : 'Switch Language'}
+						class="rounded px-4 py-1 text-center hover:bg-gray-100 dark:hover:bg-gray-700"
+						onclick={toggleLangFunc}
+					>
 						<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" class="inline-block">
 							<path fill="none" d="M0 0h24v24H0z" />
 							<path
@@ -178,13 +166,14 @@
 								d="M5 15v2a2 2 0 0 0 1.85 1.995L7 19h3v2H7a4 4 0 0 1-4-4v-2h2zm13-5l4.4 11h-2.155l-1.201-3h-4.09l-1.199 3h-2.154L16 10h2zm-1 2.885L15.753 16h2.492L17 12.885zM8 2v2h4v7H8v3H6v-3H2V4h4V2h2zm9 1a4 4 0 0 1 4 4v2h-2V7a2 2 0 0 0-2-2h-3V3h3zM6 6H4v3h2V6zm4 0H8v3h2V6z"
 							/>
 						</svg>
-					</div>
+					</button>
 					<!-- GitHub -->
 					<!-- main -> next -->
 					<a
 						href="https://github.com/any-tdf/stdf/tree/next"
 						class="rounded px-4 py-1 text-center hover:bg-gray-100 dark:hover:bg-gray-700"
 						target="_blank"
+						aria-label={isZh ? '跳转至 GitHub' : 'Jump to GitHub'}
 					>
 						<svg width="20" height="20" viewBox="0 0 24 24" class="inline-block" xmlns="http://www.w3.org/2000/svg">
 							<path
@@ -203,7 +192,7 @@
 			<button
 				class="flex cursor-pointer rounded border border-black/10 px-2 text-sm font-normal text-black/40 transition-all hover:border-black/20 dark:border-white/10 dark:text-white/40 dark:hover:border-white/20"
 				style="padding-top: 0.3125rem;padding-bottom: 0.3125rem;"
-				on:click={clickCmdKFun}
+				onclick={clickCmdKFun}
 			>
 				<div class="mr-1.5 flex flex-col justify-center">
 					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" style="fill: currentColor;">
@@ -213,29 +202,31 @@
 						/>
 					</svg>
 				</div>
-				<div class="mr-4 flex flex-col justify-center text-xs">{isZh ? '快速搜索...' : 'Quick search...'}</div>
+				<div class="mr-4 flex flex-col justify-center text-xs">
+					{isZh ? '快速搜索...' : 'Quick search...'}
+				</div>
 				<div class="mr-1 rounded bg-black/5 px-1 font-bold dark:bg-white/5">{cmdkey}</div>
 				<div class="rounded bg-black/5 px-1.5 font-bold dark:bg-white/5">K</div>
 			</button>
 			<a
-				href="#/guide"
-				class={`rounded px-4 py-1 transition-all ${
-					currentRoute === '/guide' ? 'bg-primary dark:bg-dark text-white dark:text-black' : 'hover:bg-black/5 dark:hover:bg-white/5'
-				}`}
+				href="/guide"
+				class="rounded px-4 py-1 transition-all {currentRoute === '/guide'
+					? 'bg-primary text-white dark:bg-dark dark:text-black'
+					: 'hover:bg-black/5 dark:hover:bg-white/5'}"
 			>
 				{isZh ? '指南' : 'Guide'}
 			</a>
 			<a
-				href="#/components?nav=button&tab=0"
-				class={`inline-block rounded px-4 py-1 text-center transition-all ${
-					currentRoute === '/components' ? 'bg-primary dark:bg-dark text-white dark:text-black' : 'hover:bg-black/5 dark:hover:bg-white/5'
-				}`}
+				href="/components?nav=button&tab=0"
+				class="inline-block rounded px-4 py-1 text-center transition-all {currentRoute === '/components'
+					? 'bg-primary text-white dark:bg-dark dark:text-black'
+					: 'hover:bg-black/5 dark:hover:bg-white/5'}"
 			>
 				{isZh ? '组件' : 'Components'}
 			</a>
 			<button
 				class="relative cursor-pointer rounded px-4 py-1 text-center transition-all hover:bg-black/5 dark:hover:bg-white/5"
-				on:click={showThemeFunc}
+				onclick={showThemeFunc}
 				bind:this={ThemeSwitchDom}
 			>
 				{isZh ? '主题' : 'Theme'}
@@ -252,14 +243,15 @@
 			<button
 				class="cursor-pointer rounded px-4 py-1 text-center transition-all hover:bg-black/5 dark:hover:bg-white/5"
 				title={isZh ? '支持' : 'Support'}
-				on:click={toggleFundFunc}
+				onclick={toggleFundFunc}
 			>
 				{isZh ? '支持' : 'Support'}
 			</button>
 			<!-- 语言切换 -->
 			<button
-				on:click={toggleLangFunc}
+				onclick={toggleLangFunc}
 				title={isZh ? '切换语言' : 'Switch languages'}
+				aria-label={isZh ? '切换语言' : 'Switch languages'}
 				class="cursor-pointer rounded px-4 py-1 text-center transition-all hover:bg-black/5 dark:hover:bg-white/5"
 			>
 				<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" class="inline-block">
@@ -276,6 +268,7 @@
 				href="https://github.com/any-tdf/stdf/tree/next"
 				class="inline-block rounded px-4 py-1 transition-all hover:bg-black/5 dark:hover:bg-white/5"
 				target="_blank"
+				aria-label={isZh ? '跳转至 GitHub' : 'Jump to GitHub'}
 				title={isZh ? '跳转至 GitHub' : 'Jump to GitHub'}
 			>
 				<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline-block">

+ 1 - 0
docs/site/src/lib/index.ts

@@ -0,0 +1 @@
+// place files you want to import through the `$lib` alias in this folder.

+ 39 - 0
docs/site/src/lib/menu/Menu.svelte

@@ -0,0 +1,39 @@
+<script lang="ts">
+	let { currentNav = $bindable(''), showNum = true, menuList = [], onclickMenu } = $props();
+	import type { MenuListChild } from '../../data/menuList.js';
+
+	const setClick = (menu: MenuListChild) => {
+		currentNav = menu.nav;
+		onclickMenu(menu);
+	};
+	const isZh = localStorage.getItem('lang') === 'zh_CN';
+</script>
+
+<div class="flex flex-col px-2 py-4">
+	<span class="pb-3 text-xs text-gray-500">
+		{isZh ? '最近更新:' : 'Last update:'}
+		<br />
+		{isZh ? import.meta.env.VITE_BUILD_TIME_ZH : import.meta.env.VITE_BUILD_TIME_EN}
+	</span>
+	{#each menuList as menu}
+		<div class="text-xs">
+			{isZh ? menu.class : menu.class_en}{showNum ? `(${menu.childs.length})` : ''}
+		</div>
+		<div class="my-2 ml-1 flex flex-col pr-0">
+			{#each menu.childs as child}
+				<button
+					onclick={(e: MouseEvent) => {
+						e.preventDefault();
+						// e.self();
+						setClick(child);
+					}}
+					class="box-content border-l-2 py-2 pl-2 text-left text-sm transition-all hover:font-bold {child.nav === currentNav
+						? 'border-primary font-bold text-primary dark:border-dark dark:text-dark'
+						: ''}"
+				>
+					{isZh ? child.title : child.title_en}
+				</button>
+			{/each}
+		</div>
+	{/each}
+</div>

+ 36 - 35
docs/site/src/components/modeSwitch/ModeSwitch.svelte → docs/site/src/lib/modeSwitch/ModeSwitch.svelte

@@ -1,9 +1,9 @@
-<script>
+<script lang="ts">
 	import darkMode from './darkMode';
 	import { themeStore, sysThemeStore, currentThemeStore } from '../../store';
-	let isClick = false;
+	let isClick = $state(false);
 	//手动切换主题
-	const toggleFun = e => {
+	const toggleFun = (e: MouseEvent) => {
 		// 阻止冒泡
 		e.stopPropagation();
 		isClick = true;
@@ -11,13 +11,13 @@
 			isClick = false;
 		}, 150);
 		if ($themeStore === 'light') {
-			// 切换到dark
+			// 切换到 dark
 			themeStore.set('dark');
 			currentThemeStore.set('dark');
 			localStorage.setItem('theme', 'dark');
 			darkMode(true, e);
 		} else if ($themeStore === 'dark') {
-			// 切换到auto
+			// 切换到 auto
 			themeStore.set('auto');
 			localStorage.setItem('theme', 'auto');
 			if ($sysThemeStore === 'dark') {
@@ -29,7 +29,7 @@
 				currentThemeStore.set('light');
 			}
 		} else {
-			// 切换到light
+			// 切换到 light
 			themeStore.set('light');
 			currentThemeStore.set('light');
 			localStorage.setItem('theme', 'light');
@@ -37,16 +37,16 @@
 		}
 	};
 	//auto 时,监听系统主题
-	const mql = window.matchMedia('(prefers-color-scheme: dark)');
-	mql.addEventListener('change', e => {
+	const mql: MediaQueryList = window.matchMedia('(prefers-color-scheme: dark)');
+	mql.addEventListener('change', (e: MediaQueryListEvent) => {
 		if ($themeStore === 'auto') {
 			if (e.matches) {
 				// 系统是暗模式
-				darkMode(true, e);
+				darkMode(true, e as unknown as MouseEvent);
 				sysThemeStore.set('dark');
 				currentThemeStore.set('dark');
 			} else {
-				darkMode(false, e);
+				darkMode(false, e as unknown as MouseEvent);
 				sysThemeStore.set('light');
 				currentThemeStore.set('light');
 			}
@@ -55,27 +55,28 @@
 	const isZh = localStorage.getItem('lang') === 'zh_CN';
 </script>
 
-<!-- svelte-ignore a11y-click-events-have-key-events -->
-<!-- svelte-ignore a11y-no-static-element-interactions -->
 <button
-	class="flex justify-between cursor-pointer rounded p-0.5 bg-black/5 dark:bg-white/10 text-center w-28 mx-auto"
+	class="mx-auto flex w-28 cursor-pointer justify-between rounded bg-black/5 p-0.5 text-center dark:bg-white/10"
 	title={isZh
 		? `${$themeStore === 'light' ? '亮模式' : $themeStore === 'dark' ? '暗模式' : '跟随系统'}`
 		: `${$themeStore === 'light' ? 'Light' : $themeStore === 'dark' ? 'Dark' : 'System'}`}
-	on:click={toggleFun}
+	onclick={toggleFun}
+	aria-label={isZh
+		? `${$themeStore === 'light' ? '亮模式' : $themeStore === 'dark' ? '暗模式' : '跟随系统'}`
+		: `${$themeStore === 'light' ? 'Light' : $themeStore === 'dark' ? 'Dark' : 'System'}`}
 >
 	<div
 		class:scale-75={isClick}
-		class={`min-h-full p-0.5 transition-all duration-150 px-2 rounded${$themeStore === 'light' ? ' bg-white/80 shadow-sm' : ''}`}
+		class="min-h-full p-0.5 px-2 transition-all duration-150 rounded{$themeStore === 'light' ? ' bg-white/80 shadow-sm' : ''}"
 		style="color:{$sysThemeStore === 'dark'
 			? $themeStore === 'light'
 				? '#ff3f2e'
 				: '#646464'
 			: $themeStore === 'light'
-			? '#ff3f2e'
-			: $themeStore === 'dark'
-			? '#646464'
-			: '#cecece'}"
+				? '#ff3f2e'
+				: $themeStore === 'dark'
+					? '#646464'
+					: '#cecece'}"
 	>
 		<svg width="20" height="20" viewBox="0 0 20 24" fill="none" style="display: inline;" xmlns="http://www.w3.org/2000/svg">
 			<path
@@ -118,18 +119,18 @@
 	</div>
 	<div
 		class:scale-75={isClick}
-		class={`min-h-full p-0.5 px-2 transition-all duration-150 rounded${$themeStore === 'dark' ? ' bg-black/50 shadow-sm' : ''}`}
+		class="min-h-full p-0.5 px-2 transition-all duration-150 rounded{$themeStore === 'dark' ? ' bg-black/50 shadow-sm' : ''}"
 		style="color:{$sysThemeStore === 'light'
 			? $themeStore === 'auto'
 				? '#cecece'
 				: $themeStore === 'dark'
-				? '#fff'
-				: '#cecece'
+					? '#fff'
+					: '#cecece'
 			: $themeStore === 'light'
-			? '#cecece'
-			: $themeStore === 'auto'
-			? '#646464'
-			: '#fff'}"
+				? '#cecece'
+				: $themeStore === 'auto'
+					? '#646464'
+					: '#fff'}"
 	>
 		<svg width="20" height="20" style="display: inline;position:relative;top:-1px" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
 			<path
@@ -139,18 +140,18 @@
 		</svg>
 	</div>
 	<div
-		class={`min-h-full p-0.5 px-2 transition-all duration-150 rounded${
-			$themeStore === 'auto' && $sysThemeStore === 'light' ? ' bg-white/80' : ''
-		}${$themeStore === 'auto' && $sysThemeStore === 'dark' ? ' bg-black/50' : ''}${
-			$themeStore === 'auto' && $sysThemeStore === 'light' ? ' shadow-sm' : ''
-		}`}
+		class="min-h-full p-0.5 px-2 transition-all duration-150 rounded{$themeStore === 'auto' && $sysThemeStore === 'light'
+			? ' bg-white/80'
+			: ''}{$themeStore === 'auto' && $sysThemeStore === 'dark' ? ' bg-black/50' : ''}{$themeStore === 'auto' && $sysThemeStore === 'light'
+			? ' shadow-sm'
+			: ''}"
 		style="color:{$themeStore === 'light'
 			? '#cecece'
 			: $themeStore === 'dark'
-			? '#646464'
-			: $themeStore === 'auto' && $sysThemeStore === 'light'
-			? '#ff3f2e'
-			: '#fff'};background-size: 30%;"
+				? '#646464'
+				: $themeStore === 'auto' && $sysThemeStore === 'light'
+					? '#ff3f2e'
+					: '#fff'};background-size: 30%;"
 	>
 		<svg xmlns="http://www.w3.org/2000/svg" style="display: inline;" viewBox="0 0 24 28" width="20" height="20">
 			<path

+ 5 - 10
docs/site/src/components/modeSwitch/darkMode.js → docs/site/src/lib/modeSwitch/darkMode.ts

@@ -5,26 +5,21 @@
  * @returns {void}
  * @example
  */
-// @ts-ignore
-export default (isDark = true, ev) => {
+export default (isDark = true, ev: MouseEvent) => {
 	document.documentElement.style.setProperty('--x', ev.clientX + 'px');
 	document.documentElement.style.setProperty('--y', ev.clientY + 'px');
 
 	if (isDark) {
-		// @ts-ignore
-		if (document.startViewTransition) {
-			// @ts-ignore
-			document.startViewTransition(() => {
+		if ('startViewTransition' in document) {
+			(document as Document & { startViewTransition: (callback: () => void) => void }).startViewTransition(() => {
 				document.documentElement.classList.add('dark');
 			});
 		} else {
 			document.documentElement.classList.add('dark');
 		}
 	} else {
-		// @ts-ignore
-		if (document.startViewTransition) {
-			// @ts-ignore
-			document.startViewTransition(() => {
+		if ('startViewTransition' in document) {
+			(document as Document & { startViewTransition: (callback: () => void) => void }).startViewTransition(() => {
 				document.documentElement.classList.remove('dark');
 			});
 		} else {

+ 180 - 0
docs/site/src/lib/tab/Tab.svelte

@@ -0,0 +1,180 @@
+<script lang="ts">
+	import { fade } from 'svelte/transition';
+	import { currentThemeStore } from '../../store';
+	// @ts-expect-error - beautify-qrcode 缺少类型定义
+	import { encodeData, rendererLine } from 'beautify-qrcode';
+	import { page } from '$app/stores';
+
+	let { currentTab = 0, onclickTab } = $props();
+
+	const tabList = [
+		{ zh: '示例', en: 'Demo' },
+		{ zh: 'API', en: 'API' },
+		{ zh: '指南', en: 'Guide' },
+		{ zh: 'FAQ', en: 'FAQ' },
+		{ zh: '版本', en: 'Version' }
+	];
+	const changeIndexFun = (i: number) => {
+		currentTab = i;
+		onclickTab?.(i);
+	};
+	const isZh = localStorage.getItem('lang') === 'zh_CN';
+	let showQr = $state(false);
+	let QRValue = $state('');
+	let A_a1Svg = $state('');
+
+	const mouseenterFun = () => {
+		const params = new URLSearchParams('?' + $page.url.searchParams);
+		QRValue =
+			// main -> next
+			(import.meta.env.DEV ? location.protocol + '//' + location.hostname + ':8888/' : 'https://next-demo.stdf.design/') +
+			params.get('nav') +
+			(isZh ? '/zh_CN' : '/en_US');
+		showQr = true;
+		/**
+		 * A_a1
+		 * @param {Object} qrcode
+		 * @param {Object} options
+		 * @param {String} [options.type]  连线方向 0=>左右 1=>上下 2=>纵横 3=>回环 4=>左上—右下 5=>右上—左下 6=>交叉"
+		 * @param {String} [options.size] 连线粗细
+		 * @param {String} [options.opacity] 连线不透明度
+		 * @param {String} [options.posType] 定位点样式  0=>矩形 1=>圆形 2=>行星 3=>圆角矩形
+		 * @param {String} [options.otherColor] 连线颜色
+		 * @param {String} [options.posColor] 定位点颜色
+		 */
+		const qrcode = encodeData({
+			text: QRValue,
+			isSpace: false
+		});
+		const color = $currentThemeStore === 'dark' ? 'rgb(var(--theme-color-dark))' : 'rgb(var(--theme-color-primary))';
+		A_a1Svg = rendererLine(qrcode, {
+			posType: 2,
+			otherColor: color,
+			posColor: color
+		});
+	};
+
+	let showStackblitz = $state(false);
+	let stackblitzValue = $state('');
+	const showStackblitzFunc = () => {
+		const nav = $page.url.searchParams.get('nav');
+		// main -> next
+		stackblitzValue = `https://stackblitz.com/github/any-tdf/next-demo-stdf?file=src%2Froutes%2F${
+			isZh ? 'zh_CN' : 'en_US'
+		}%2F${nav}%2F%2Bpage.svelte&startScript=${nav}${isZh ? '' : '_en'}`;
+		showStackblitz = true;
+	};
+
+	let showCode = $state(false);
+	let codeValue = $state('');
+	const showCodeFunc = () => {
+		const nav = $page.url.searchParams.get('nav');
+		// 将nav首字母大写
+		const navFirst = nav ? nav.slice(0, 1).toUpperCase() + nav.slice(1) : '';
+		// main -> next
+		codeValue = `https://github.com/any-tdf/stdf/blob/next/packages/stdf/src/lib/components/${nav}/${navFirst}.svelte`;
+		showCode = true;
+	};
+</script>
+
+<div class="relative top-14 w-82 md:w-102">
+	<div class="relative rounded bg-gray-100 p-1 dark:bg-gray-700">
+		<!--滑块-->
+		<div
+			class="absolute top-1 h-10 w-16 rounded bg-white shadow-md transition-all duration-300 dark:bg-black dark:shadow-white/10 md:w-20"
+			class:left-1={currentTab === 0}
+			class:left-17={currentTab === 1}
+			class:md:left-21={currentTab === 1}
+			class:left-33={currentTab === 2}
+			class:md:left-41={currentTab === 2}
+			class:left-49={currentTab === 3}
+			class:md:left-61={currentTab === 3}
+			class:left-65={currentTab === 4}
+			class:md:left-81={currentTab === 4}
+		></div>
+		<!--二维码-->
+		<a href={QRValue} target="_blank">
+			<button
+				onmouseleave={() => (showQr = false)}
+				onmouseenter={mouseenterFun}
+				class="absolute left-106 top-0 hidden h-12 w-12 rounded bg-gray-100 p-3 dark:bg-gray-700 md:block"
+			>
+				<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" style="fill: currentColor">
+					<path fill="none" d="M0 0h24v24H0z" />
+					<path
+						d="M16 17v-1h-3v-3h3v2h2v2h-1v2h-2v2h-2v-3h2v-1h1zm5 4h-4v-2h2v-2h2v4zM3 3h8v8H3V3zm2 2v4h4V5H5zm8-2h8v8h-8V3zm2 2v4h4V5h-4zM3 13h8v8H3v-8zm2 2v4h4v-4H5zm13-2h3v2h-3v-2zM6 6h2v2H6V6zm0 10h2v2H6v-2zM16 6h2v2h-2V6z"
+					/>
+				</svg>
+				{#if showQr}
+					<div
+						class="absolute left-0 top-14 z-50 hidden w-60 rounded bg-black p-6 shadow-lg dark:block"
+						transition:fade={{ duration: 200 }}
+					>
+						<!-- eslint-disable-next-line svelte/no-at-html-tags -->
+						<span>{@html A_a1Svg}</span>
+					</div>
+				{/if}
+				{#if showQr}
+					<div
+						class="absolute left-0 top-14 z-50 block w-60 rounded bg-white p-6 shadow-lg dark:hidden"
+						transition:fade={{ duration: 200 }}
+					>
+						<!-- eslint-disable-next-line svelte/no-at-html-tags -->
+						<span>{@html A_a1Svg}</span>
+					</div>
+				{/if}
+			</button>
+		</a>
+		<!--StackBlitz-->
+		<a href={stackblitzValue} target="_blank">
+			<button
+				onmouseleave={() => (showStackblitz = false)}
+				onmouseenter={showStackblitzFunc}
+				class="absolute left-[34.5rem] top-0 hidden h-12 w-12 rounded bg-gray-100 p-3 dark:bg-gray-700 md:block"
+			>
+				<svg viewBox="0 0 28 28" height="24">
+					<path fill="#3275e7" d="M12.747 16.273h-7.46L18.925 1.5l-3.671 10.227h7.46L9.075 26.5l3.671-10.227z" />
+				</svg>
+				{#if showStackblitz}
+					<div
+						class="absolute left-0 top-14 z-50 h-12 w-44 rounded bg-gray-700 py-3 text-center leading-[1.5rem] text-white shadow-lg"
+						transition:fade={{ duration: 200 }}
+					>
+						{isZh ? '在 StackBlitz 中打开' : 'Open in StackBlitz'}
+					</div>
+				{/if}
+			</button>
+		</a>
+		<!--组件源码-->
+		<a href={codeValue} target="_blank">
+			<button
+				onmouseleave={() => (showCode = false)}
+				onmouseenter={showCodeFunc}
+				class="absolute left-[30.5rem] top-0 hidden h-12 w-12 rounded bg-gray-100 p-3 dark:bg-gray-700 md:block"
+			>
+				<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" style="fill: currentColor">
+					<path
+						d="M3 3H21C21.5523 3 22 3.44772 22 4V20C22 20.5523 21.5523 21 21 21H3C2.44772 21 2 20.5523 2 20V4C2 3.44772 2.44772 3 3 3ZM4 5V19H20V5H4ZM20 12L16.4645 15.5355L15.0503 14.1213L17.1716 12L15.0503 9.87868L16.4645 8.46447L20 12ZM6.82843 12L8.94975 14.1213L7.53553 15.5355L4 12L7.53553 8.46447L8.94975 9.87868L6.82843 12ZM11.2443 17H9.11597L12.7557 7H14.884L11.2443 17Z"
+					/>
+				</svg>
+				{#if showCode}
+					<div
+						class="{isZh
+							? 'w-28'
+							: 'w-52'} absolute left-0 top-14 z-50 h-12 rounded bg-gray-700 py-3 text-center leading-[1.5rem] text-white shadow-lg"
+						transition:fade={{ duration: 200 }}
+					>
+						{isZh ? '组件源码' : 'Component source code'}
+					</div>
+				{/if}
+			</button>
+		</a>
+		<div class="relative flex">
+			{#each tabList as item, index}
+				<button onclick={() => changeIndexFun(index)} class="w-16 cursor-pointer rounded py-2 text-center md:w-20">
+					{isZh ? item.zh : item.en}
+				</button>
+			{/each}
+		</div>
+	</div>
+</div>

+ 26 - 24
docs/site/src/components/themeSwitch/ThemeSwitch.svelte → docs/site/src/lib/themeSwitch/ThemeSwitch.svelte

@@ -1,14 +1,16 @@
-<script>
-	import { switchTheme } from 'stdf/theme';
-	import themes from '../../data/themes';
-	import { currentColorStore } from '../../store';
+<script lang="ts">
+	import { switchTheme, type ThemeProps } from 'stdf/theme';
+	import themes from '../../data/themes/index.js';
+	import { currentColorStore } from '../../store.js';
+
+	type ThemeItem = { name: string; name_CN: string; theme: ThemeProps };
 
 	// 横排还是竖排
 	export let vertical = false;
 
 	const isZh = localStorage.getItem('lang') === 'zh_CN';
 
-	const selectColorFunc = (e, item) => {
+	const selectColorFunc = (e: MouseEvent, item: ThemeItem) => {
 		// 阻止冒泡
 		e.stopPropagation();
 		currentColorStore.set(item.name);
@@ -30,20 +32,20 @@
 			darkMeta.setAttribute('content', safariDark);
 		}
 	};
-	const bgFunc = str => {
+	const bgFunc = (str: string) => {
 		return str.charAt(0) === '#' ? str : `rgb(${str})`;
 	};
 </script>
 
-<div class="flex {vertical ? 'flex-col' : 'flex-row'} gap-2 flex-wrap my-4">
+<div class="flex {vertical ? 'flex-col' : 'flex-row'} my-4 flex-wrap gap-2">
 	{#each themes as item}
 		<button
-			class="flex p-2 gap-2 justify-between items-center border {$currentColorStore === item.name
+			class="flex items-center justify-between gap-2 border p-2 {$currentColorStore === item.name
 				? 'border-primary dark:border-dark'
-				: 'border-gray-100 dark:border-gray-700'} rounded-md cursor-pointer"
-			on:click={e => selectColorFunc(e, item)}
+				: 'border-gray-100 dark:border-gray-700'} cursor-pointer rounded-md"
+			on:click={(e) => selectColorFunc(e, item)}
 		>
-			<div class="w-5 h-5 {$currentColorStore === item.name ? 'fill-primary dark:fill-dark' : 'fill-gray-300 dark:fill-gray-700'}">
+			<div class="h-5 w-5 {$currentColorStore === item.name ? 'fill-primary dark:fill-dark' : 'fill-gray-300 dark:fill-gray-700'}">
 				<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
 					<path
 						d="M12 2C17.5222 2 22 5.97778 22 10.8889C22 13.9556 19.5111 16.4444 16.4444 16.4444H14.4778C13.5556 16.4444 12.8111 17.1889 12.8111 18.1111C12.8111 18.5333 12.9778 18.9222 13.2333 19.2111C13.5 19.5111 13.6667 19.9 13.6667 20.3333C13.6667 21.2556 12.9 22 12 22C6.47778 22 2 17.5222 2 12C2 6.47778 6.47778 2 12 2ZM7.5 12C8.32843 12 9 11.3284 9 10.5C9 9.67157 8.32843 9 7.5 9C6.67157 9 6 9.67157 6 10.5C6 11.3284 6.67157 12 7.5 12ZM16.5 12C17.3284 12 18 11.3284 18 10.5C18 9.67157 17.3284 9 16.5 9C15.6716 9 15 9.67157 15 10.5C15 11.3284 15.6716 12 16.5 12ZM12 9C12.8284 9 13.5 8.32843 13.5 7.5C13.5 6.67157 12.8284 6 12 6C11.1716 6 10.5 6.67157 10.5 7.5C10.5 8.32843 11.1716 9 12 9Z"
@@ -52,24 +54,24 @@
 				</svg>
 			</div>
 			<div class="whitespace-nowrap">{isZh ? item.name_CN : item.name}</div>
-			<div class="flex gap-2 justify-between">
+			<div class="flex justify-between gap-2">
 				<!-- theme  -->
-				<div class="flex rounded-sm overflow-hidden">
-					<div class="w-6 bg-primary" style="background-color: {bgFunc(item.theme.color.primary.default)};"></div>
-					<div class="w-6 bg-dark" style="background-color: {bgFunc(item.theme.color.dark.default)};"></div>
+				<div class="flex overflow-hidden rounded-sm">
+					<div class="bg-primary w-6" style="background-color: {bgFunc(item.theme.color.primary.default)};"></div>
+					<div class="bg-dark w-6" style="background-color: {bgFunc(item.theme.color.dark.default)};"></div>
 				</div>
 				<div class="flex flex-col justify-between gap-1">
 					<!-- Functional -->
 					<div class="flex gap-0.5">
-						<div class="w-3 h-3 rounded-sm" style="background-color: {bgFunc(item.theme.color.functional.success)};"></div>
-						<div class="w-3 h-3 rounded-sm" style="background-color: {bgFunc(item.theme.color.functional.warning)};"></div>
-						<div class="w-3 h-3 rounded-sm" style="background-color: {bgFunc(item.theme.color.functional.error)};"></div>
-						<div class="w-3 h-3 rounded-sm" style="background-color: {bgFunc(item.theme.color.functional.info)};"></div>
+						<div class="h-3 w-3 rounded-sm" style="background-color: {bgFunc(item.theme.color.functional.success)};"></div>
+						<div class="h-3 w-3 rounded-sm" style="background-color: {bgFunc(item.theme.color.functional.warning)};"></div>
+						<div class="h-3 w-3 rounded-sm" style="background-color: {bgFunc(item.theme.color.functional.error)};"></div>
+						<div class="h-3 w-3 rounded-sm" style="background-color: {bgFunc(item.theme.color.functional.info)};"></div>
 					</div>
 					<!-- Extended -->
-					<div class="flex gap-0.5 justify-between">
+					<div class="flex justify-between gap-0.5">
 						{#each item.theme.color.extend as child}
-							<div class="w-3 h-3 rounded-sm" style="background-color: {bgFunc(child.color)};"></div>
+							<div class="h-3 w-3 rounded-sm" style="background-color: {bgFunc(child.color)};"></div>
 						{/each}
 					</div>
 				</div>
@@ -78,11 +80,11 @@
 	{/each}
 	{#if vertical}
 		<a
-			href="/#/guide/generator"
+			href="/guide/generator"
 			target="_blank"
-			class="border border-gray-100 dark:border-gray-700 hover:border-primary dark:hover:border-dark group rounded py-2 text-primary dark:text-dark transition-all duration-300 flex justify-center gap-2 items-center"
+			class="text-primary hover:border-primary dark:text-dark dark:hover:border-dark group flex items-center justify-center gap-2 rounded border border-gray-100 py-2 transition-all duration-300 dark:border-gray-700"
 		>
-			<svg class="w-5 h-5 group-hover:scale-95 transition-all duration-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
+			<svg class="h-5 w-5 transition-all duration-300 group-hover:scale-95" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
 				<path
 					class="fill-primary dark:fill-dark"
 					d="M15.1986 9.94435C14.7649 9.53358 14.4859 8.98601 14.4085 8.39371L14.0056 5.31126L11.275 6.79711C10.7503 7.08262 10.1433 7.17876 9.55608 7.06936L6.49998 6.50003L7.06931 9.55612C7.17871 10.1434 7.08257 10.7503 6.79707 11.275L5.31121 14.0056L8.39367 14.4085C8.98596 14.4859 9.53353 14.7649 9.94431 15.1986L12.0821 17.4555L13.4178 14.6485C13.6745 14.1091 14.109 13.6745 14.6484 13.4179L17.4555 12.0821L15.1986 9.94435ZM15.2238 15.5078L13.0111 20.1579C12.8687 20.4572 12.5107 20.5843 12.2115 20.4419C12.1448 20.4102 12.0845 20.3664 12.0337 20.3127L8.49229 16.574C8.39749 16.4739 8.27113 16.4095 8.13445 16.3917L3.02816 15.7242C2.69958 15.6812 2.46804 15.3801 2.51099 15.0515C2.52056 14.9782 2.54359 14.9074 2.5789 14.8425L5.04031 10.3191C5.1062 10.198 5.12839 10.0579 5.10314 9.92241L4.16 4.85979C4.09931 4.53402 4.3142 4.22074 4.63997 4.16005C4.7126 4.14652 4.78711 4.14652 4.85974 4.16005L9.92237 5.10319C10.0579 5.12843 10.198 5.10625 10.319 5.04036L14.8424 2.57895C15.1335 2.42056 15.4979 2.52812 15.6562 2.81919C15.6916 2.88409 15.7146 2.95495 15.7241 3.02821L16.3916 8.13449C16.4095 8.27118 16.4739 8.39754 16.5739 8.49233L20.3127 12.0337C20.5533 12.2616 20.5636 12.6414 20.3357 12.8819C20.2849 12.9356 20.2246 12.9794 20.1579 13.0111L15.5078 15.2238C15.3833 15.2831 15.283 15.3833 15.2238 15.5078ZM16.0206 17.4349L17.4348 16.0207L21.6775 20.2633L20.2633 21.6775L16.0206 17.4349Z"

+ 0 - 82
docs/site/src/main.js

@@ -1,82 +0,0 @@
-// @ts-ignore
-import App from './App.svelte';
-import './app.css';
-import { delParamsUrl } from './utils/index';
-import { switchTheme } from 'stdf/theme';
-import themes from './data/themes/index.js';
-
-const currentTheme = localStorage.getItem('theme_color') || 'STDF';
-// 设置默认主题色
-themes.forEach(item => {
-    if (item.name === currentTheme) {
-        const theme = item.theme;
-        switchTheme(theme);
-        // 修改 HTML 的 meta name="theme-color" 属性,适配 Safari 的 tab 背景色,需要设置 light 和 dark 两种颜色
-        const safariLight = theme.color.primaryWhite;
-        const safariDark = theme.color.darkBlack;
-        // 查找 meta 标签,name="theme-color" 且 media="(prefers-color-scheme: light)"
-        const lightMeta = document.querySelector('meta[name="theme-color"][media="(prefers-color-scheme: light)"]');
-        // 查找 meta 标签,name="theme-color" 且 media="(prefers-color-scheme: dark)"
-        const darkMeta = document.querySelector('meta[name="theme-color"][media="(prefers-color-scheme: dark)"]');
-        // 如果找到了,就修改它的 content 属性
-        if (lightMeta) {
-            lightMeta.setAttribute('content', safariLight);
-        }
-        if (darkMeta) {
-            darkMeta.setAttribute('content', safariDark);
-        }
-    }
-});
-
-let urlLang = window.location.href.split('?')[1];
-if (!urlLang || (urlLang && !urlLang.includes('lang'))) {
-    if (!localStorage.getItem('lang')) {
-        //获取浏览器语言前两位
-        const lang = navigator.language.substring(0, 2);
-        if (lang === 'en') {
-            localStorage.setItem('lang', 'en_US');
-        } else {
-            localStorage.setItem('lang', 'zh_CN');
-        }
-    }
-} else {
-    let urlParams = new URLSearchParams(urlLang);
-    localStorage.setItem('lang', urlParams.get('lang'));
-    setTimeout(() => {
-        // window.location.href = window.location.href.replace(/(\?|#)[^'"]*/, '');//去除参数
-        // @ts-ignore
-        window.history.pushState({}, 0, delParamsUrl(window.location.href, 'lang')); //刷新页面
-    }, 10);
-}
-if (localStorage.getItem('theme') === 'dark') {
-    document.documentElement.classList.add('dark');
-} else if (localStorage.getItem('theme') === 'light') {
-    document.documentElement.classList.remove('dark');
-} else {
-    if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
-        document.documentElement.classList.add('dark');
-    } else {
-        document.documentElement.classList.remove('dark');
-    }
-}
-
-// 根据亮暗模式动态切换 favicon
-// const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
-// handleDarkmode(darkModeMediaQuery);
-// function handleDarkmode(e) {
-//     var darkModeOn = e.matches;
-//     var favicon = document.querySelector('link[rel="icon"]'); // 获取声明中含 rel="icon" 的元素,你可以根据需要添加更多
-//     if (!favicon) {
-//         return;
-//     }
-//     if (darkModeOn) {
-//         favicon.href = '/favicon_black.ico'; //黑暗模式下的 favicon
-//     } else {
-//         favicon.href = '/favicon.ico'; //其它时候的 favicon
-//     }
-// }
-// darkModeMediaQuery.addEventListener('change', handleDarkmode);
-
-const app = new App({
-    target: document.body,
-});

+ 0 - 678
docs/site/src/pages/Home.svelte

@@ -1,678 +0,0 @@
-<script>
-    // @ts-nocheck
-    import { onMount, onDestroy } from 'svelte';
-    import { link } from 'svelte-spa-router';
-    import { fade } from 'svelte/transition';
-    import { Confetti } from 'svelte-confetti';
-    import { currentThemeStore, currentColorStore } from '../store';
-    import { encodeData, rendererLine } from 'beautify-qrcode';
-
-    const descList = [
-        {
-            title: 'Simple',
-            titleZh: '简 单',
-            desc: '使用 Svelte 语法编码简洁迅速。组件源码逻辑清晰、简单易懂、中英注释详细,查看源码、修改逻辑也可以得心应手。',
-            descEn: 'Coding with Svelte syntax is simple and fast. The component source code logic is clear, simple and easy to understand, and the English and Chinese comments are detailed. You can also get used to it by viewing the source code and modifying the logic yourself.',
-            icon: '/assets/images/3D-simple.png',
-            iconDark: '/assets/images/3D-simple-dark.png',
-            shwTip: false,
-        },
-        {
-            title: 'Thin',
-            titleZh: '轻 量',
-            desc: '源码体积小巧,无三方依赖。基于 Svelte 与 Tailwind 编译出的代码在体积上也优势明显,这在移动端显得尤为重要。',
-            descEn: 'The source code is small and has no third-party dependencies. The code compiled based on Svelte and Tailwind also has obvious advantages in terms of volume, which is particularly important in mobile terminals.',
-            icon: '/assets/images/3D-thin.png',
-            iconDark: '/assets/images/3D-thin-dark.png',
-            shwTip: true,
-        },
-        {
-            title: 'Design',
-            titleZh: '设 计',
-            desc: '针对移动设备优化设计与交互,使用友好、高效、灵活。支持通过简单配置定制颜色系统、圆角风格、亮暗模式等。',
-            descEn: 'Optimized design and interaction for mobile devices, user-friendly, efficient, and flexible. Support customizing color system, corner style, light and dark mode, etc. through simple configuration.',
-            icon: '/assets/images/3D-design.png',
-            iconDark: '/assets/images/3D-design-dark.png',
-            shwTip: false,
-        },
-        {
-            title: 'Fast',
-            titleZh: '快 速',
-            desc: '无运行时,无虚拟 DOM,无烦杂的 CSS 代码,状态管理简单轻快。编码过程、编译处理、线上运行全都快起来了。',
-            descEn: 'No runtime, no virtual DOM, no cumbersome CSS code, simple and fast state management. The coding process, compilation processing, and online running are all faster.',
-            icon: '/assets/images/3D-fast.png',
-            iconDark: '/assets/images/3D-fast-dark.png',
-            shwTip: false,
-        },
-    ];
-    const dominant = {
-        title: '💪 优势 & 目标',
-        title_en: '💪 Advantages & Goals',
-        data: [
-            {
-                icon: 'svelte',
-                p: '补充 Svelte 生态,让开发者可以更快速更舒服地开发出高质量的应用。',
-                p_en: 'Supplement the Svelte ecosystem so that developers can develop high-quality applications faster and more comfortably.',
-            },
-            {
-                icon: 'css3-line',
-                p: '避免写繁琐的 CSS 代码,让开发者专注于业务逻辑,提高开发效率。',
-                p_en: 'Avoid writing tedious CSS code, allowing developers to focus on business logic and improve development efficiency.',
-            },
-            {
-                icon: 'contrast-2-line',
-                p: '支持暗黑模式与主题配置,方便开发者直接适配,让应用更加现代化。',
-                p_en: 'Supports dark mode and theme configuration, making it easy for developers to adapt directly and make applications more modern.',
-            },
-            {
-                icon: 'paint-brush-line',
-                p: '普适性较强。移动端组件库多用于 C 端,对比 B 端更加需要注重 UI 的灵活性。',
-                p_en: 'It has strong versatility. Mobile component libraries are mostly used in C-end scenarios where UI flexibility is more important than B-end.',
-            },
-            {
-                icon: 'clockwise-line',
-                p: '注重交互与体验。适当的过渡动画与合理的交互设计,希望给你更好的用户体验。',
-                p_en: 'Emphasis on interaction and experience. Appropriate transition animations and reasonable interaction design hope to give you a better user experience.',
-            },
-            {
-                icon: 'article-line',
-                p: '站点文档、示例、源码注释都支持中英双语,且不再中英混杂,一目了然。',
-                p_en: 'Site documentation, examples, and source code comments all support bilingual Chinese and English, making it clear at a glance.',
-            },
-            {
-                icon: 'file-copy-2-line',
-                p: '示例代码丰富,方便直接复制使用,配备脚手架、插件等工具,对开发者友好。',
-                p_en: 'The example code is extensive and convenient for direct copying and usage. It is equipped with scaffolding, plugins, etc. making it developer-friendly.',
-            },
-            {
-                icon: 'planet-line',
-                p: '组件支持国际化(目前 60+ 语言),让应用轻松实现多语言支持。',
-                p_en: 'Component supports internationalization (currently 60+ languages), making it easy for applications to achieve multilingual support.',
-            },
-        ],
-    };
-    const ugly = {
-        title: '🔔 提前警告',
-        title_en: '🔔 Early Warning',
-        data: [
-            {
-                icon: 'medal-line',
-                p: 'STDF 不体现任何「价值观」,更加不能为您「赋能」,只希望能给您更好的开发体验,很简单很朴实。',
-                p_en: 'STDF does not reflect any "values", and cannot "empower" you. We only hope to provide you with a better development experience, which is simple and straightforward.',
-            },
-            {
-                icon: 'service-line',
-                p: 'Svelte 生态相对 Vue 和 React 还很薄弱,如果您有兴趣,请积极参与和丰富 Svelte 生态。',
-                p_en: 'The Svelte ecosystem is still relatively weak compared to Vue and React. If you are interested, please actively participate in and enrich the Svelte ecosystem.',
-            },
-            {
-                icon: 'bard-line',
-                p: 'STDF 也适用于 Svelte 生态的其他工程,比如 SvelteKit 等,使用前请确保知晓它们的基础原理。',
-                p_en: 'STDF also applies to other projects in the Svelte ecosystem, such as SvelteKit, etc. When using them, please ensure that you understand their basic principles.',
-            },
-            {
-                icon: 'git-close-pull-request-line',
-                p: 'STDF 也适用于 Tailwind CSS 的类库,如 UnoCSS 等,使用它们请确保您知晓它们的基础原理。',
-                p_en: 'STDF also applies to class libraries of Tailwind CSS, such as UnoCSS, etc. When using them, please ensure that you understand their basic principles.',
-            },
-        ],
-    };
-    const isZh = localStorage.getItem('lang') === 'zh_CN';
-
-    // 赞助人员
-    const thinkGithub = [{ name: 'yuedanlabs', amount: 10 }];
-
-    const bottomInfo = [
-        {
-            title: '相关',
-            title_en: 'Related',
-            list: [
-                {
-                    title: 'Svelte',
-                    title_en: 'Svelte',
-                    link: 'https://svelte.dev',
-                    _blank: true,
-                },
-                {
-                    title: 'Tailwind',
-                    title_en: 'Tailwind',
-                    link: 'https://tailwindcss.com',
-                    _blank: true,
-                },
-                { title: 'Remix Icon', title_en: 'Remix Icon', link: 'https://remixicon.com', _blank: true },
-                // { title: 'RTDF(计划中)', title_en: 'RTDF(intend)', link: '', _blank: false },
-                // { title: 'VTDF(计划中)', title_en: 'VTDF(intend)', link: '', _blank: false },
-            ],
-        },
-        {
-            title: '工具',
-            title_en: 'Tools',
-            list: [
-                {
-                    title: 'create-stdf',
-                    title_en: 'create-stdf',
-                    link: 'https://www.npmjs.com/package/create-stdf',
-                    _blank: true,
-                },
-                {
-                    title: 'rollup-plugin-stdf-icon',
-                    title_en: 'rollup-plugin-stdf-icon',
-                    link: 'https://www.npmjs.com/package/rollup-plugin-stdf-icon',
-                    _blank: true,
-                },
-                {
-                    title: 'STDF for VS Code',
-                    title_en: 'STDF for VS Code',
-                    link: 'https://marketplace.visualstudio.com/items?itemName=STDF.stdf-vscode-extension',
-                    _blank: true,
-                },
-            ],
-        },
-        {
-            title: '帮助',
-            title_en: 'Help',
-            list: [
-                { title: '关于', title_en: 'About', link: '#/guide/about', _blank: false },
-                { title: '常见问题', title_en: 'FAQ', link: '#/guide/faq', _blank: false },
-                { title: '更新日志', title_en: 'Changelog', link: '#/guide/changelog', _blank: false },
-                { title: '开源许可', title_en: 'License', link: 'https://github.com/any-tdf/stdf/blob/main/LICENSE', _blank: true },
-            ],
-        },
-        {
-            title: '社区',
-            title_en: 'Community',
-            list: [
-                // { title: 'GitHub', title_en: 'GitHub', link: 'https://github.com/any-tdf/stdf' },
-                {
-                    title: 'QQ 群',
-                    title_en: 'QQ Group',
-                    link: 'https://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=U8ZlXJ3KVpTI9oZzs1jBnyWc3gVA0h6Y&authKey=ScWu0nU9g8BqNsC7o2eYkESwgVDVz9vzGNZEb17MrEAay9%2F7bTkXDiLJRIzo2vrg&noverify=0&group_code=581073686',
-                    _blank: true,
-                },
-                // { title: '钉钉群', title_en: 'DingTalk Group', link: '', _blank: true },
-                { title: 'Discord', title_en: 'Discord', link: 'https://discord.gg/DMkHu8GGre', _blank: true },
-                { title: 'QQ 频道', title_en: 'QQ Discord', link: 'https://pd.qq.com/s/fdd8incyr', _blank: true },
-                { title: 'Discussions', title_en: 'Discussions', link: 'https://github.com/any-tdf/stdf/discussions', _blank: true },
-            ],
-        },
-    ];
-    let showQr = false;
-    let show3D = !(localStorage.getItem('show3D') === '0');
-
-    const change3DFunc = () => {
-        show3D = !show3D;
-        localStorage.setItem('show3D', show3D ? '1' : '0');
-    };
-
-    const io = new IntersectionObserver(entries => {
-        entries.forEach(item => {
-            // isIntersecting是一个Boolean值,判断目标元素当前是否可见
-            if (item.isIntersecting) {
-                item.target.style.opacity = 1;
-                item.target.style.transform = 'translateY(0)';
-                setTimeout(() => {
-                    item.target.style.transitionDuration = '300ms';
-                }, 1000);
-            } else {
-                // item.target.style.opacity = 0;
-                // item.target.style.transform = 'translateY(200px)';
-            }
-        });
-    });
-    let A_a1Svg;
-    const mouseenterFun = () => {
-        /**
-         * A_a1
-         * @param {Object} qrcode
-         * @param {Object} options
-         * @param {String} [options.type]  连线方向 0=>左右 1=>上下 2=>纵横 3=>回环 4=>左上—右下 5=>右上—左下 6=>交叉"
-         * @param {String} [options.size] 连线粗细
-         * @param {String} [options.opacity] 连线不透明度
-         * @param {String} [options.posType] 定位点样式  0=>矩形 1=>圆形 2=>行星 3=>圆角矩形
-         * @param {String} [options.otherColor] 连线颜色
-         * @param {String} [options.posColor] 定位点颜色
-         */
-        const qrcode = encodeData({
-            // main -> next
-            text: 'https://next-demo.stdf.design?lang=' + (isZh ? 'zh_CN' : 'en_US'),
-            isSpace: false,
-        });
-        const color = $currentThemeStore === 'dark' ? 'rgb(var(--theme-color-dark))' : 'rgb(var(--theme-color-primary))';
-        A_a1Svg = rendererLine(qrcode, { posType: 2, otherColor: color, posColor: color });
-        showQr = true;
-    };
-    onMount(() => {
-        const intersectionList = document.querySelectorAll('.intersection');
-        intersectionList.forEach(item => {
-            // 开始时 opacity 为 0,不可见, transform 为 translateY(200px)
-            item.style.opacity = 0;
-            item.style.transform = 'translateY(200px)';
-            item.style.transitionDuration = '1s';
-            io.observe(item);
-        });
-    });
-    const unsubscribe = currentColorStore.subscribe(value => {
-        show3D = false;
-        setTimeout(() => {
-            show3D = localStorage.getItem('show3D') === '1';
-        }, 0);
-    });
-    onDestroy(() => {
-        unsubscribe();
-    });
-</script>
-
-<div class="max-w-[2000px] mx-auto">
-    <div class="lg:flex flex-row-reverse justify-center">
-        {#if show3D}
-            <div class="basis-1/2 mt-10 md:mt-0 overflow-hidden relative group">
-                <spline-viewer
-                    class="aspect-[4/3] md:aspect-auto scale-110 md:scale-100"
-                    url="/assets/3d/scene.splinecode"
-                    background={$currentThemeStore === 'dark'
-                        ? `rgb(${getComputedStyle(document.documentElement).getPropertyValue('--theme-color-darkBlack')})`
-                        : `rgb(${getComputedStyle(document.documentElement).getPropertyValue('--theme-color-primaryWhite')})`}
-                />
-                <!-- background="rgb(242, 242, 243)" -->
-                <!-- background={backgroundColor} -->
-                <!-- background="rgb(255, 0, 0)" -->
-                <button
-                    on:click={() => {
-                        show3D = false;
-                        localStorage.setItem('show3D', '0');
-                    }}
-                    class="absolute hidden md:block scale-0 group-hover:scale-100 transition-all duration-500 bg-black/5 dark:bg-white/10 px-2 py-1 cursor-pointer rounded text-black/80 dark:text-white/90 text-xs top-10 left-10"
-                >
-                    {isZh ? '隐藏 3D LOGO' : 'Hidden 3D LOGO'}
-                </button>
-            </div>
-        {:else}
-            <!-- 图片 -->
-            <div class="basis-1/2 mt-10 md:mt-0 overflow-hidden flex flex-col justify-center relative group">
-                <img src="/assets/3d/dark.png" alt="" class="w-full object-cover hidden dark:block" />
-                <img src="/assets/3d/light.png" alt="" class="w-full object-cover block dark:hidden" />
-                <button
-                    on:click={() => {
-                        show3D = true;
-                        localStorage.setItem('show3D', '1');
-                    }}
-                    class="absolute hidden md:block scale-0 group-hover:scale-100 transition-all duration-300 bg-black/5 dark:bg-white/10 px-2 py-1 cursor-pointer rounded text-black/80 dark:text-white/90 text-xs top-10 left-10"
-                >
-                    {isZh ? '显示 3D LOGO' : 'Show 3D LOGO'}
-                </button>
-            </div>
-        {/if}
-        <div class="flex flex-col justify-center basis-2/5 text-center py-16 md:py-20">
-            <div class="hidden md:flex h-20 md:h-28 mt-16 mb-20 flex-col justify-center items-center relative">
-                <div class="absolute rounded-full opacity-50 md:opacity-100 animate-dynamicsBg blur-xl md:blur-3xl">
-                    <svg viewBox="0 0 100 100">
-                        <path
-                            fill-rule="evenodd"
-                            clip-rule="evenodd"
-                            d="M50 0V100C22.3858 100 0 77.6142 0 50C0 22.3858 22.3858 0 50 0Z"
-                            class="fill-dark"
-                        />
-                        <path
-                            fill-rule="evenodd"
-                            clip-rule="evenodd"
-                            d="M50 100V0C77.6142 0 100 22.3858 100 50C100 77.6142 77.6142 100 50 100Z"
-                            class="fill-primary"
-                        />
-                        <circle cx="50" cy="25" r="25" class="fill-primary" />
-                        <circle cx="50" cy="75" r="25" class="fill-dark" />
-                        <circle cx="50.25" cy="25.25" r="6.25" class="fill-dark" />
-                        <circle cx="50.25" cy="75.25" r="6.25" class="fill-primary" />
-                    </svg>
-                </div>
-                <div
-                    class="absolute w-28 md:w-36 h-full"
-                    style="filter: drop-shadow(0 10px 8px rgb(0 0 0 / 0.05)) drop-shadow(0 4px 3px rgb(0 0 0 / 0.1));"
-                >
-                    <svg viewBox="0 0 90 80" class="group">
-                        <path
-                            class="fill-primary dark:fill-dark"
-                            d="M0 0H20H40H50C64.8056 0 77.7325 8.04398 84.6487 20H50H40V22.6757V30H50C55.5229 30 60 34.4771 60 40C60 45.5229 55.5229 50 50 50H40V57.3243V78.7398V80H20V66.4583V20H15.3513H0V0ZM50 80C72.0914 80 90 62.0914 90 40C90 36.547 89.5625 33.1962 88.7398 30H67.3244C69.0261 32.9417 70 36.3571 70 40C70 51.0457 61.0457 60 50 60V80Z"
-                        />
-                        <path
-                            style="stroke-dasharray: 400;stroke-dashoffset: 400;"
-                            class="fill-dark dark:fill-primary stroke-dark dark:stroke-primary text-dark dark:text-primary stroke-1 group-hover:animate-path"
-                            d="M20 30V0L0 50H20V80L40 30H20Z"
-                        />
-                    </svg>
-                </div>
-            </div>
-            <div class="text-5xl md:text-8xl font-medium">S T D F</div>
-            <div class="mt-4 md:text-xl px-4">
-                {#if isZh}
-                    基于
-                    <a
-                        href="https://svelte.dev"
-                        class="transition-all underline underline-offset-2 decoration-svelte hover:text-svelte"
-                        target="_blank"
-                        title={isZh ? '打开 Svelte 官方站点' : 'Open Svelte official website'}
-                    >
-                        Svelte
-                    </a>
-                    与
-                    <a
-                        href="https://tailwindcss.com/"
-                        class="transition-all underline underline-offset-2 decoration-tailwind hover:text-tailwind"
-                        target="_blank"
-                        title={isZh ? '打开 Tailwind CSS 官方站点' : 'Open Tailwind CSS official website'}
-                    >
-                        Tailwind
-                    </a>
-                    的移动 web 组件库
-                {:else}
-                    Mobile web component
-                    <br class="md:hidden" />
-                    library based on
-                    <a
-                        href="https://svelte.dev"
-                        class="transition-all underline underline-offset-2 decoration-svelte hover:text-svelte"
-                        target="_blank"
-                    >
-                        Svelte
-                    </a>
-                    and
-                    <a
-                        href="https://tailwindcss.com/"
-                        class="transition-all underline underline-offset-2 decoration-tailwind hover:text-tailwind"
-                        target="_blank"
-                    >
-                        Tailwind
-                    </a>
-                {/if}
-            </div>
-            <div class="flex justify-center gap-4 mt-8 mb-8 md:mt-16 md:mb-10 space-x-8">
-                <a
-                    href="#/guide"
-                    class="relative bg-primary dark:bg-dark py-2 px-6 text-white dark:text-black rounded hover:bg-primary/80 hover:dark:bg-dark/80 transition-all group"
-                >
-                    {isZh ? '开始使用' : 'Get Started'}
-                    <span class="absolute left-1/2 top-0 hidden group-hover:block">
-                        <Confetti infinite rounded />
-                    </span>
-                </a>
-                <a
-                    href="/"
-                    use:link
-                    on:mouseleave={() => (showQr = false)}
-                    on:mouseenter={mouseenterFun}
-                    class="border-solid border border-primary dark:border-dark py-2 px-6 rounded transition-all hidden md:block relative"
-                >
-                    {isZh ? '扫码示例' : 'QR Demo'}
-                    {#if showQr}
-                        <div
-                            class="w-52 rounded-lg absolute z-10 top-0 left-full -translate-y-1/3 border border-black/5 translate-x-2 p-2 shadow-lg block dark:hidden"
-                            in:fade={{ duration: 300 }}
-                            out:fade={{ duration: 0 }}
-                        >
-                            <span>{@html A_a1Svg}</span>
-                            <!-- <QrCode value="https://demo.stdf.design/#/" size={200} color="#fff" background="#23262B" /> -->
-                        </div>
-                        <div
-                            class="w-52 rounded-lg absolute z-10 top-0 left-full bg-black -translate-y-1/3 border border-white/5 translate-x-2 p-2 shadow-lg hidden dark:block"
-                            in:fade={{ duration: 300 }}
-                            out:fade={{ duration: 0 }}
-                        >
-                            <span>{@html A_a1Svg}</span>
-                            <!-- <QrCode value="https://demo.stdf.design/#/" size={200} color="#fff" background="#24262b" /> -->
-                        </div>
-                    {/if}
-                </a>
-                <!-- main -> next -->
-                <a
-                    href={'https://next-demo.stdf.design?lang=' + (isZh ? 'zh_CN' : 'en_US')}
-                    target="_blank"
-                    class="border-solid border border-primary dark:border-dark py-2 px-6 rounded transition-all block md:hidden"
-                >
-                    {isZh ? '查看示例' : 'Examples'}
-                </a>
-            </div>
-        </div>
-    </div>
-    <div class="flex flex-wrap xl:flex-nowrap justify-around gap-8 px-8">
-        {#each descList as desc}
-            <div
-                class="intersection ease-out group flex flex-col space-y-5 overflow-hidden items-center w-full pb-8 sm:w-2/3 md:w-80 lg:w-96 border-black/5 dark:border-white/5 rounded-xl dark:hover:shadow-white/5 transition-all duration-300"
-            >
-                <div class="overflow-hidden">
-                    <img
-                        class="block dark:hidden object-cover scale-100 group-hover:scale-[1.6] transition-all duration-500"
-                        src={desc.icon}
-                        alt=""
-                    />
-                    <img
-                        class="hidden dark:block object-cover scale-100 group-hover:scale-[1.6] transition-all duration-500"
-                        src={desc.iconDark}
-                        alt=""
-                    />
-                </div>
-                {#if isZh}
-                    <div class="text-3xl font-medium py-4">{isZh ? desc.titleZh : desc.title}</div>
-                {/if}
-                <div class={`text-black/70 dark:text-white/60 text-sm ${isZh ? 'text-justify' : 'text-left pt-10'}`}>
-                    {isZh ? desc.desc : desc.descEn}
-                </div>
-            </div>
-        {/each}
-    </div>
-
-    <div class="px-4 md:px-12 pb-10 md:pb-20" class:text-left={!isZh}>
-        <div class="mt-40">
-            <div class="intersection transition-all ease-out my-10 md:my-20 font-bold text-2xl md:text-4xl text-center">
-                {isZh ? dominant.title : dominant.title_en}
-            </div>
-            <div class="grid grid-cols-1 md:grid-cols-4 gap-10">
-                {#each dominant.data as item}
-                    <div
-                        class="intersection p-0.5 rounded-lg border border-px dark:border-white/5 border-black/5 overflow-hidden transition-all ease-out group relative"
-                    >
-                        <div
-                            class="hidden group-hover:block absolute -left-1/2 top-1/3 w-[200%] h-1/2 bg-primary {$currentThemeStore ===
-                            'dark'
-                                ? 'animate-spin-line-dark'
-                                : 'animate-spin-line'}"
-                        ></div>
-                        <div class="px-8 py-10 h-full w-full rounded-lg relative bg-primaryWhite dark:bg-darkBlack">
-                            <div class="w-8 h-8 flex-none text-primary dark:text-dark transition-all ease-out group-hover:scale-90">
-                                <svg style="fill: currentColor;display: inline;" viewBox="0 0 24 24">
-                                    <use xlink:href="/assets/fonts/home.symbol.svg#{item.icon}" />
-                                </svg>
-                            </div>
-                            <p class="text-sm opacity-90 mt-6">{isZh ? item.p : item.p_en}</p>
-                        </div>
-                    </div>
-                {/each}
-            </div>
-        </div>
-        <div class="mt-32 md:mt-48">
-            <div class="intersection transition-all ease-out my-10 md:my-20 font-bold text-2xl md:text-4xl text-center">
-                {isZh ? ugly.title : ugly.title_en}
-            </div>
-            <div class="grid grid-cols-1 md:grid-cols-4 gap-10">
-                {#each ugly.data as item}
-                    <div
-                        class="intersection p-0.5 rounded-lg border border-px dark:border-white/5 border-black/5 overflow-hidden transition-all ease-out group relative"
-                    >
-                        <div
-                            class="hidden group-hover:block absolute -left-1/2 top-1/3 w-[200%] h-1/2 bg-primary {$currentThemeStore ===
-                            'dark'
-                                ? 'animate-spin-line-dark'
-                                : 'animate-spin-line'}"
-                        ></div>
-                        <div class="px-8 py-10 h-full w-full rounded-lg relative bg-primaryWhite dark:bg-darkBlack">
-                            <div class="w-8 h-8 flex-none text-primary dark:text-dark transition-all ease-out group-hover:scale-90">
-                                <svg style="fill: currentColor;display: inline;" viewBox="0 0 24 24">
-                                    <use xlink:href="/assets/fonts/home.symbol.svg#{item.icon}" />
-                                </svg>
-                            </div>
-                            <p class="text-sm opacity-90 mt-6">{isZh ? item.p : item.p_en}</p>
-                        </div>
-                    </div>
-                {/each}
-            </div>
-
-            <!-- <div class="space-y-10">
-            {#each isZh ? ugly.p : ugly.p_en as item, i}
-                <p>{item}</p>
-            {/each}
-        </div> -->
-        </div>
-    </div>
-
-    <!-- <div class="hidden md:flex justify-center mb-20">
-    <article class={`prose dark:prose-invert max-w-none text-xs overflow-auto`} style="height:{500}px">
-        <pre><code class="hljs">{@html highlightedCode}</code></pre>
-    </article>
-    <div class=" ml-2 border border-black/10 dark:border-gray-400 w-[392px] grow-0 shrink-0 overflow-auto" style="height:{500}px">
-        <img src="/assets/images/home/zh/9.png" alt="" class='w-full' />
-    </div>
-</div> -->
-
-    <div class="text-center px-4 md:px-12 pb-10 md:pb-20">
-        <div class="intersection transition-all ease-out my-5 md:my-10 font-bold text-2xl md:text-4xl">
-            🎖 {isZh ? '贡献者' : 'Contributors'}
-        </div>
-        <div class="intersection flex justify-center">
-            <a href="https://github.com/any-tdf/stdf/graphs/contributors" target="_blank">
-                <img src="https://contrib.rocks/image?repo=any-tdf/stdf" title={isZh ? '贡献者' : 'Contributors'} alt="" />
-            </a>
-        </div>
-    </div>
-
-    <!-- 赞助者 -->
-    <div class="text-center px-4 md:px-12 pb-20 md:pb-40">
-        <div class="intersection transition-all ease-out my-5 md:my-10 font-bold text-2xl md:text-4xl">
-            🙏 {isZh ? '赞助者' : 'Sponsors'}
-        </div>
-        <div class="">
-            <div class="intersection mb-4">GitHub</div>
-            <div class="flex justify-center gap-4 flex-wrap">
-                {#each thinkGithub as item}
-                    <a class="intersection" href={'https://github.com/' + item.name} target="_blank">
-                        <img
-                            class="w-16 h-16 rounded-full overflow-hidden"
-                            src={'https://avatars.githubusercontent.com/' + item.name}
-                            title={(isZh ? '感谢 ' : 'Thanks ') + item.name}
-                            alt=""
-                        />
-                    </a>
-                {/each}
-            </div>
-        </div>
-    </div>
-
-    <!-- <div class="pb-4">
-		<p class="flex justify-center gap-4">
-			<a href="https://www.npmjs.com/package/stdf" rel="nofollow">
-				<img
-					src="https://camo.githubusercontent.com/13967f6092f0e143b32d68749e50fab68dc6442cb5dc82713dee33f462d73bb8/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f737464663f6c6f676f3d6e706d266c6162656c3d73746466267374796c653d666c61742d737175617265"
-					alt="npm"
-				/>
-			</a>
-			<a href="https://www.npmjs.com/package/stdf" rel="nofollow">
-				<img
-					src="https://camo.githubusercontent.com/1657ded382705222b8310d638f8dadec731094d53a2e28e30f73a741c7ab6a83/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f64742f737464663f6c6f676f3d6e706d266c6162656c3d696e7374616c6c73267374796c653d666c61742d737175617265"
-					alt="npm"
-					data-canonical-src="https://img.shields.io/npm/dt/stdf?logo=npm&amp;label=installs&amp;style=flat-square"
-					style="max-width: 100%;"
-				/>
-			</a>
-			<a href="https://www.npmjs.com/package/stdf" rel="nofollow">
-				<img
-					src="https://camo.githubusercontent.com/5ad203b3cf7281ba18010c465b4a434ce95f24b3273772db67737b21c7d92491/68747470733a2f2f696d672e736869656c64732e696f2f62756e646c6570686f6269612f6d696e7a69702f737464663f6c6f676f3d6e706d266c6162656c3d6d696e7a6970267374796c653d666c61742d737175617265"
-					alt="npm bundle size"
-					data-canonical-src="https://img.shields.io/bundlephobia/minzip/stdf?logo=npm&amp;label=minzip&amp;style=flat-square"
-					style="max-width: 100%;"
-				/>
-			</a>
-			<a href="https://github.com/any-tdf/stdf">
-				<img
-					src="https://camo.githubusercontent.com/d9bb38904bee18db8ce348502fa0037c2767d01b2c0650834842b5eb4683b6fd/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f64756675313939312f737464663f6c6f676f3d676974687562266c6162656c3d7374617273267374796c653d666c61742d737175617265"
-					alt="GitHub stars"
-					data-canonical-src="https://img.shields.io/github/stars/any-tdf/stdf?logo=github&amp;label=stars&amp;style=flat-square"
-					style="max-width: 100%;"
-				/>
-			</a>
-			<a href="https://github.com/any-tdf/stdf">
-				<img
-					src="https://camo.githubusercontent.com/911de612402842a474a987a4a8d68531db71eeb2755d741cac46566770da5dc6/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f64756675313939312f737464663f6c6f676f3d676974687562267374796c653d666c61742d737175617265"
-					alt="GitHub license"
-					data-canonical-src="https://img.shields.io/github/license/any-tdf/stdf?logo=github&amp;style=flat-square"
-					style="max-width: 100%;"
-				/>
-			</a>
-			<a href="https://www.npmjs.com/package/create-stdf" rel="nofollow">
-				<img
-					src="https://camo.githubusercontent.com/063c8aa873c7143e4fd491532ef29e8cf435ef967218993041ec49d3ebfdd403/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f6372656174652d737464663f6c6f676f3d6e706d266c6162656c3d637265617465267374796c653d666c61742d737175617265"
-					alt="npm"
-					data-canonical-src="https://img.shields.io/npm/v/create-stdf?logo=npm&amp;label=create&amp;style=flat-square"
-					style="max-width: 100%;"
-				/>
-			</a>
-			<a href="https://www.npmjs.com/package/rollup-plugin-stdf-icon" rel="nofollow">
-				<img
-					src="https://camo.githubusercontent.com/4e7b90519654646d3fb30a5bac83b04374a3abd05a837688bae5e05dc256a2a4/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f726f6c6c75702d706c7567696e2d737464662d69636f6e3f6c6f676f3d6e706d266c6162656c3d69636f6e267374796c653d666c61742d737175617265"
-					alt="npm"
-					data-canonical-src="https://img.shields.io/npm/v/rollup-plugin-stdf-icon?logo=npm&amp;label=icon&amp;style=flat-square"
-					style="max-width: 100%;"
-				/>
-			</a>
-			<a href="https://marketplace.visualstudio.com/items?itemName=STDF.stdf-vscode-extension" rel="nofollow">
-				<img
-					src="https://camo.githubusercontent.com/e83b95d19002c3dec1e38d3994342e23b735977bc386199e75892a99a6bffbe0/68747470733a2f2f696d672e736869656c64732e696f2f76697375616c2d73747564696f2d6d61726b6574706c6163652f762f535444462e737464662d7673636f64652d657874656e73696f6e3f6c6f676f3d76697375616c73747564696f636f6465266c6162656c3d657874656e73696f6e267374796c653d666c61742d737175617265"
-					alt="Visual Studio Marketplace Version (including pre-releases)"
-					data-canonical-src="https://img.shields.io/visual-studio-marketplace/v/STDF.stdf-vscode-extension?logo=visualstudiocode&amp;label=extension&amp;style=flat-square"
-					style="max-width: 100%;"
-				/>
-			</a>
-		</p>
-	</div> -->
-</div>
-<div class="bg-white dark:bg-black grid grid-cols-2 md:grid-cols-4 gap-10 pt-20 pb-16 px-4 md:px-10 text-center">
-    {#each bottomInfo as item}
-        <div>
-            <div class="text-lg font-bold mb-2">{isZh ? item.title : item.title_en}</div>
-            <div class="flex flex-col gap-1">
-                {#each item.list as i}
-                    <a href={i.link} target={i._blank ? '_blank' : '_self'} title={i.link} class="text-sm">{isZh ? i.title : i.title_en}</a>
-                {/each}
-            </div>
-        </div>
-    {/each}
-</div>
-
-<div class="bg-white dark:bg-black text-xs text-center py-4 border-t border-black/10 dark:border-white/10">
-    <div class="text-sm mb-3" title={isZh ? '如果页面卡顿,请关闭 3D 模型。' : 'If the page is stuck, please turn off the 3D model.'}>
-        <button class="cursor-pointer text-primary dark:text-dark" on:click={change3DFunc}>
-            {show3D ? (isZh ? '隐藏' : 'Hidden') : isZh ? '显示' : 'Show'}
-            3D LOGO
-        </button>
-    </div>
-    <div class="flex justify-center gap-1">
-        <div>STDF DESIGN • MADE BY DUFU</div>
-        <div>
-            {#if isZh}
-                • <a href="https://beian.miit.gov.cn" target="_blank">滇ICP备17004037号-4</a>
-            {/if}
-        </div>
-    </div>
-</div>
-
-<style>
-    @keyframes spin-line {
-        to {
-            transform: rotate(360deg);
-        }
-    }
-    .animate-spin-line {
-        animation: spin-line 6s linear infinite;
-        background: conic-gradient(transparent 50deg, rgba(var(--theme-color-primary), 0.4) 80deg, transparent 90deg);
-    }
-    .animate-spin-line-dark {
-        animation: spin-line 6s linear infinite;
-        background: conic-gradient(transparent 50deg, rgba(var(--theme-color-dark), 0.6) 80deg, transparent 90deg);
-    }
-</style>

+ 0 - 13
docs/site/src/pages/components/Component.svelte

@@ -1,13 +0,0 @@
-<script>
-	/**
-	 * @typedef {Object} Props
-	 * @property {string} [highlightedCode]
-	 */
-
-	/** @type {Props} */
-	let { highlightedCode = '' } = $props();
-</script>
-
-<article class={`prose dark:prose-invert max-w-none text-sm`}>
-	<pre><code class="hljs">{@html highlightedCode}</code></pre>
-</article>

+ 0 - 335
docs/site/src/pages/components/Components.svelte

@@ -1,335 +0,0 @@
-<script>
-    // @ts-nocheck
-    import { onMount } from 'svelte';
-    import { fly } from 'svelte/transition';
-    import { querystring, push } from 'svelte-spa-router';
-    import { isShowNavStore, isCmdKStore } from '../../store';
-    import { menuList } from '../../data/menuList';
-
-    import Menu from '../../components/menu/Menu.svelte';
-    import Tab from '../../components/tab/Tab.svelte';
-
-    import Component from './Component.svelte';
-    import Guide from './Guide.svelte';
-    import Api from './Api.svelte';
-    import FAQ from './FAQ.svelte';
-    import Version from './Version.svelte';
-
-    // let Guide;
-    // let Api;
-    // let FAQ;
-    // let Version;
-    // let Component;
-
-    let loading = true;
-
-    const isZh = localStorage.getItem('lang') === 'zh_CN';
-
-    let params = new URLSearchParams('?' + $querystring);
-    //数组二级组成新数组
-    const ArrChildFun = arr => {
-        let newArr = [];
-        for (let e = 0; e < arr.length; e++) {
-            newArr.push(...arr[e].childs);
-        }
-        return newArr;
-    };
-    $: menuChildList = ArrChildFun(menuList);
-    let currentNav = {};
-    let currentTab = 0;
-    let titleDom = null;
-    let demoHeight = 0;
-    let highlightedCode = '';
-    let titleWidth = 0;
-    let visible = true;
-    let isShowIframe = true;
-    let navBarHeight = 0;
-
-    // 动态导入组件字符串
-    const getComponentStrFunc = async name => {
-        const rawObj = await import(`../../../../../packages/stdf/src/routes/${name}/${isZh ? 'zh_CN' : 'en_US'}/+page.svelte?raw`);
-        // 将 componentStr 中所有的 from '$lib/index.js' 替换为 from 'stdf'
-        // 将 componentStr 中所有的 from '$lib/types/index.js' 替换为 from 'stdf/types'
-        return rawObj.default
-            .replace(/from ['"]\$lib\/index\.js['"]/g, "from 'stdf'")
-            .replace(/from ['"]\$lib\/types\/index\.js['"]/g, "from 'stdf/types'");
-    };
-
-    const getDemoHeightFun = () => {
-        demoHeight = document.documentElement.clientHeight - 70 - titleDom.offsetHeight - 100;
-        navBarHeight = document.documentElement.clientHeight - 56;
-    };
-    onMount(async () => {
-        // Component = (await import('./Component.svelte')).default;
-        // Guide = (await import('./Guide.svelte')).default;
-        // Api = (await import('./Api.svelte')).default;
-        // FAQ = (await import('./FAQ.svelte')).default;
-        // Version = (await import('./Version.svelte')).default;
-
-        demoHeight = document.documentElement.clientHeight - 70 - titleDom.offsetHeight - 100;
-        navBarHeight = document.documentElement.clientHeight - 56;
-        window.addEventListener('resize', getDemoHeightFun);
-        if (params.get('tab')) {
-            currentTab = Number(params.get('tab'));
-        }
-        if (params.get('nav')) {
-            currentNav = menuChildList.filter(item => item.nav === params.get('nav'))[0];
-        } else {
-            currentNav = menuList[0].childs[1];
-        }
-        loading = true;
-        const componentStr = await getComponentStrFunc(currentNav.nav);
-        loading = false;
-        highlightedCode = hljs.highlight(componentStr, { language: 'svelte', ignoreIllegals: true }).value;
-        // highlightedCode = hljs.highlight(map[currentNav.nav], { language: 'svelte', ignoreIllegals: true }).value;
-        return () => {
-            window.removeEventListener('resize', getDemoHeightFun);
-        };
-    });
-
-    //监听箭头按键,方便键盘操作
-    const handleKeydown = event => {
-        if ($isCmdKStore) {
-            return;
-        }
-        //左右箭头切换Tab
-        if (event.code === 'ArrowLeft') {
-            if (currentTab > 0) {
-                isShowIframe = false;
-                setTimeout(() => {
-                    isShowIframe = true;
-                }, 100);
-                currentTab--;
-                params.set('tab', currentTab.toString());
-                push(`/components?nav=${params.get('nav') ? params.get('nav') : 'button'}&tab=${currentTab}`);
-            }
-        }
-        if (event.code === 'ArrowRight') {
-            if (currentTab < 4) {
-                isShowIframe = false;
-                setTimeout(() => {
-                    isShowIframe = true;
-                }, 100);
-                currentTab++;
-                params.set('tab', currentTab.toString());
-                push(`/components?nav=${params.get('nav') ? params.get('nav') : 'button'}&tab=${currentTab}`);
-            }
-        }
-        //上下箭头切换组件
-        if (event.code === 'ArrowUp') {
-            let currentMenuIndex = menuChildList.findIndex(item => item.nav === currentNav.nav);
-            if (currentMenuIndex > 0) {
-                visible = false;
-                setTimeout(async () => {
-                    visible = true;
-                    currentNav = menuChildList[currentMenuIndex - 1];
-                    params.set('nav', currentNav.nav);
-                    push(`/components?nav=${currentNav.nav}&tab=${currentTab}`);
-                    const componentStr = await getComponentStrFunc(currentNav.nav);
-                    highlightedCode = hljs.highlight(componentStr, { language: 'svelte', ignoreIllegals: true }).value;
-                    // @ts-ignore
-                    // highlightedCode = hljs.highlight(map[currentNav.nav], { language: 'svelte', ignoreIllegals: true }).value;
-                }, 10);
-            }
-        }
-        if (event.code === 'ArrowDown') {
-            let currentMenuIndex = menuChildList.findIndex(item => item.nav === currentNav.nav);
-            if (currentMenuIndex < menuChildList.length - 1) {
-                visible = false;
-                setTimeout(async () => {
-                    visible = true;
-                    currentNav = menuChildList[currentMenuIndex + 1];
-                    params.set('nav', currentNav.nav);
-                    push(`/components?nav=${currentNav.nav}&tab=${currentTab}`);
-                    const componentStr = await getComponentStrFunc(currentNav.nav);
-                    highlightedCode = hljs.highlight(componentStr, { language: 'svelte', ignoreIllegals: true }).value;
-                    // @ts-ignore
-                    // highlightedCode = hljs.highlight(map[currentNav.nav], { language: 'svelte', ignoreIllegals: true }).value;
-                }, 10);
-            }
-        }
-    };
-    const menuClickFun = currentMenu => {
-        $isShowNavStore && ($isShowNavStore = false);
-        visible = false;
-        setTimeout(async () => {
-            visible = true;
-            currentNav = currentMenu.detail;
-            params.set('nav', currentMenu.detail.nav);
-            push(`/components?nav=${currentMenu.detail.nav}&tab=${params.get('tab') ? params.get('tab') : '0'}`);
-            const componentStr = await getComponentStrFunc(currentNav.nav);
-            highlightedCode = hljs.highlight(componentStr, { language: 'svelte', ignoreIllegals: true }).value;
-        }, 10);
-    };
-
-    const tabClickFun = i => {
-        isShowIframe = false;
-        setTimeout(() => {
-            isShowIframe = true;
-        }, 100);
-        currentTab = i.detail;
-        params.set('tab', currentTab.toString());
-        push(`/components?nav=${params.get('nav') ? params.get('nav') : 'button'}&tab=${currentTab}`);
-    };
-    // main -> next
-    $: QRValue =
-        (import.meta.env.DEV ? location.protocol + '//' + location.hostname + ':8888/' : 'https://next-demo.stdf.design/') +
-        currentNav.nav +
-        (isZh ? '/zh_CN' : '/en_US');
-</script>
-
-<svelte:window on:keydown={handleKeydown} />
-
-<div class="flex">
-    <div
-        class="fixed -left-52 md:left-0 top-14 w-52 overflow-y-scroll transition-all duration-300 z-[100] bg-white dark:bg-black md:bg-transparent dark:md:bg-transparent border-r border-black/10 dark:border-white/20"
-        class:left-0={$isShowNavStore}
-        class:-left-52={!$isShowNavStore}
-        style="height:{navBarHeight + 'px'}"
-    >
-        <Menu {menuList} currentNav={currentNav.nav} on:MenuClick={menuClickFun} />
-    </div>
-    {#if visible}
-        <div class="md:pl-48 flex flex-col w-full" in:fly={{ x: 100, duration: 500 }} out:fly={{ x: 100, duration: 100 }}>
-            <div class="px-4 pt-4 md:px-8 md:flex md:space-x-4 relative z-20" bind:this={titleDom}>
-                {#if loading}
-                    {isZh ? '请等待...' : 'Please wait...'}
-                {:else}
-                    <div class="font-bold text-2xl md:text-4xl flex items-center">
-                        <div>
-                            {isZh ? currentNav.title : currentNav.title_en}
-                        </div>
-                        <a href={QRValue} target="_blank" aria-label={isZh ? '扫码预览' : 'Scan to preview'}>
-                            <div class="md:hidden bg-gray-100 dark:bg-gray-700 text-gray-500 rounded h-8 w-8 ml-2 p-1">
-                                <svg
-                                    xmlns="http://www.w3.org/2000/svg"
-                                    viewBox="0 0 24 24"
-                                    width="24"
-                                    height="24"
-                                    style="fill: currentColor"
-                                >
-                                    <path fill="none" d="M0 0h24v24H0z" />
-                                    <path
-                                        d="M13 21v2h-2v-2H3a1 1 0 0 1-1-1V6h20v14a1 1 0 0 1-1 1h-8zm-9-2h16V8H4v11zm9-9h5v2h-5v-2zm0 4h5v2h-5v-2zm-4-4v3h3a3 3 0 1 1-3-3zM2 3h20v2H2V3z"
-                                    />
-                                </svg>
-                            </div>
-                        </a>
-                    </div>
-                    <div class="mt-4 text-xs md:text-sm text-gray-500">{isZh ? currentNav.tip : currentNav.tip_en}</div>
-                {/if}
-            </div>
-            <div class="p-4 md:px-8 md:py-4 -mt-14 relative z-10" bind:clientWidth={titleWidth}>
-                <Tab {currentTab} on:TabClick={tabClickFun} />
-            </div>
-            <div class="my-4 ml-4">
-                <div class="h-px bg-black/10 dark:bg-white/20"></div>
-            </div>
-            <div>
-                <!-- <div class="relative overflow-hidden" style="width:{titleWidth}px;"> -->
-                <!-- <div class="relative flex" style="width:{titleWidth * 3}px;left:-{currentTab * titleWidth}px;"> -->
-                <!-- 示例 -->
-                {#if currentTab === 0}
-                    <div
-                        in:fly={{ y: 100, duration: 500 }}
-                        out:fly={{ y: 100, duration: 100 }}
-                        class="flex-1 flex py-4 mt-2 md:pl-8 md:pr-4 justify-around"
-                        style="width:{titleWidth}px;"
-                    >
-                        <div class="grow overflow-y-scroll rounded bg-codeLight dark:bg-codeDark" style="height:{demoHeight}px;">
-                            <svelte:component this={Component} {highlightedCode} />
-                        </div>
-                        <div
-                            class="hidden ml-2 md:block border border-black/10 dark:border-white/10 w-[392px] grow-0 shrink-0"
-                            style="height:{demoHeight}px"
-                        >
-                            {#if currentNav.nav}
-                                {#if isShowIframe}
-                                    <!-- main -> next -->
-                                    <iframe
-                                        title="Demo"
-                                        id="iframe-id"
-                                        src={import.meta.env.DEV
-                                            ? `http://localhost:8888/${currentNav.nav}/${isZh ? 'zh_CN' : 'en_US'}?channel=iframe`
-                                            : `https://next-demo.stdf.design/${currentNav.nav}/${isZh ? 'zh_CN' : 'en_US'}?channel=iframe`}
-                                        height={demoHeight - 2}
-                                        width="390"
-                                    ></iframe>
-                                {:else}
-                                    <div
-                                        class="flex justify-center flex-col text-primary dark:text-dark"
-                                        style="width:390px;height:{demoHeight - 2}px;"
-                                    >
-                                        <div>
-                                            <svg
-                                                class="animate-spin my-1 mx-auto h-10 w-10"
-                                                xmlns="http://www.w3.org/2000/svg"
-                                                fill="none"
-                                                viewBox="0 0 24 24"
-                                            >
-                                                <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" />
-                                                <path
-                                                    class="opacity-75"
-                                                    fill="currentColor"
-                                                    d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
-                                                />
-                                            </svg>
-                                        </div>
-                                    </div>
-                                {/if}
-                            {/if}
-                        </div>
-                    </div>
-                {/if}
-                {#if currentTab === 1}
-                    <!-- api -->
-                    <div
-                        in:fly={{ y: 100, duration: 500 }}
-                        out:fly={{ y: 100, duration: 100 }}
-                        class={` flex-1 left-full p-4 mt-4 md:px-8 md:py-4`}
-                        style="width:{titleWidth}px;"
-                    >
-                        <svelte:component this={Api} api={currentNav.nav} />
-                        <!-- <Api api={currentNav.nav} /> -->
-                    </div>
-                {/if}
-                {#if currentTab === 2}
-                    <!-- 指南 -->
-                    <div
-                        in:fly={{ y: 100, duration: 500 }}
-                        out:fly={{ y: 100, duration: 100 }}
-                        class={`flex-1 p-4 mt-4 md:px-8 md:py-4 rounded `}
-                        style="width:{titleWidth}px;"
-                    >
-                        <svelte:component this={Guide} guide={currentNav.nav} />
-                        <!-- <Guide guide={currentNav.nav} /> -->
-                    </div>
-                {/if}
-                {#if currentTab === 3}
-                    <!-- FAQ -->
-                    <div
-                        in:fly={{ y: 100, duration: 500 }}
-                        out:fly={{ y: 100, duration: 100 }}
-                        class={`flex-1 p-4 mt-4 md:px-8 md:py-4 rounded `}
-                        style="width:{titleWidth}px;"
-                    >
-                        <svelte:component this={FAQ} guide={currentNav.nav} />
-                        <!-- <FAQ guide={currentNav.nav} /> -->
-                    </div>
-                {/if}
-                {#if currentTab === 4}
-                    <!-- Version -->
-                    <div
-                        in:fly={{ y: 100, duration: 500 }}
-                        out:fly={{ y: 100, duration: 100 }}
-                        class={`flex-1 p-4 mt-4 md:px-8 md:py-4 rounded `}
-                        style="width:{titleWidth}px;"
-                    >
-                        <svelte:component this={Version} guide={currentNav.nav} />
-                        <!-- <Version guide={currentNav.nav} /> -->
-                    </div>
-                {/if}
-            </div>
-        </div>
-    {/if}
-</div>

+ 0 - 19
docs/site/src/pages/guide/About.svelte

@@ -1,19 +0,0 @@
-<script>
-	import { mdTextToHljs } from '../../utils/index';
-	import { isWideScreenStore } from '../../store';
-
-	import text from '../../../../mds/guide/about.md';
-	import text_en from '../../../../mds/guide/about_en.md';
-
-	const isZh = localStorage.getItem('lang') === 'zh_CN';
-
-	const hljsText = mdTextToHljs((isZh ? text : text_en).replace(/<a href="/g, '<a target="_blank" href="'));
-</script>
-
-<article
-	class="prose prose-strong:text-primary dark:prose-strong:text-dark dark:prose-invert pb-12 {$isWideScreenStore
-		? 'max-w-full'
-		: 'max-w-5xl'}"
->
-	{@html hljsText}
-</article>

+ 0 - 18
docs/site/src/pages/guide/Compatibility.svelte

@@ -1,18 +0,0 @@
-<script>
-	import { mdTextToHljs } from '../../utils/index';
-	import { isWideScreenStore } from '../../store';
-
-	import text from '../../../../mds/guide/compatibility.md';
-	import text_en from '../../../../mds/guide/compatibility_en.md';
-
-	const isZh = localStorage.getItem('lang') === 'zh_CN';
-	const hljsText = mdTextToHljs((isZh ? text : text_en).replace(/<a href="/g, '<a target="_blank" href="'));
-</script>
-
-<article
-	class="prose prose-strong:text-primary dark:prose-strong:text-dark dark:prose-invert pb-12 {$isWideScreenStore
-		? 'max-w-full'
-		: 'max-w-5xl'}"
->
-	{@html hljsText}
-</article>

+ 0 - 20
docs/site/src/pages/guide/Contribution.svelte

@@ -1,20 +0,0 @@
-<script>
-	import { mdTextToHljs, groupIconMdPlugin } from '../../utils/index';
-	import { isWideScreenStore } from '../../store';
-
-	// @ts-ignore
-	import text from '../../../../mds/guide/contribution.md';
-	// @ts-ignore
-	import text_en from '../../../../mds/guide/contribution_en.md';
-
-	const isZh = localStorage.getItem('lang') === 'zh_CN';
-	const hljsText = groupIconMdPlugin(mdTextToHljs(isZh ? text : text_en).replace(/<a href="/g, '<a target="_blank" href="'));
-</script>
-
-<article
-	class="prose prose-strong:text-primary dark:prose-strong:text-dark dark:prose-invert pb-12 {$isWideScreenStore
-		? 'max-w-full'
-		: 'max-w-5xl'}"
->
-	{@html hljsText}
-</article>

+ 0 - 22
docs/site/src/pages/guide/Create.svelte

@@ -1,22 +0,0 @@
-<script>
-	import { mdTextToHljs, groupIconMdPlugin } from '../../utils/index';
-	import { isWideScreenStore } from '../../store';
-
-	// @ts-ignore
-	import createText from '../../../../../packages/create-stdf/README_CN.md';
-	// @ts-ignore
-	import createText_en from '../../../../../packages/create-stdf/README.md';
-
-	const isZh = localStorage.getItem('lang') === 'zh_CN';
-	const text = groupIconMdPlugin(
-		(isZh ? mdTextToHljs(createText) : mdTextToHljs(createText_en)).replace(/<a href="/g, '<a target="_blank" href="'),
-	);
-</script>
-
-<article
-	class="prose prose-strong:text-primary dark:prose-strong:text-dark dark:prose-invert pb-12 {$isWideScreenStore
-		? 'max-w-full'
-		: 'max-w-5xl'}"
->
-	{@html text}
-</article>

+ 0 - 18
docs/site/src/pages/guide/Faq.svelte

@@ -1,18 +0,0 @@
-<script>
-	import { mdTextToHljs } from '../../utils/index';
-	import { isWideScreenStore } from '../../store';
-
-	import text from '../../../../mds/guide/faq.md';
-	import text_en from '../../../../mds/guide/faq_en.md';
-
-	const isZh = localStorage.getItem('lang') === 'zh_CN';
-	const hljsText = mdTextToHljs((isZh ? text : text_en).replace(/<a href="/g, '<a target="_blank" href="'));
-</script>
-
-<article
-	class="prose prose-strong:text-primary dark:prose-strong:text-dark dark:prose-invert pb-12 {$isWideScreenStore
-		? 'max-w-full'
-		: 'max-w-5xl'}"
->
-	{@html hljsText}
-</article>

+ 0 - 20
docs/site/src/pages/guide/Future.svelte

@@ -1,20 +0,0 @@
-<script>
-	import { mdTextToHljs } from '../../utils/index';
-	import { isWideScreenStore } from '../../store';
-
-	// @ts-ignore
-	import text from '../../../../mds/guide/future.md';
-	// @ts-ignore
-	import text_en from '../../../../mds/guide/future_en.md';
-
-	const isZh = localStorage.getItem('lang') === 'zh_CN';
-	const hljsText = mdTextToHljs((isZh ? text : text_en).replace(/<a href="/g, '<a target="_blank" href="'));
-</script>
-
-<article
-	class="prose prose-strong:text-primary dark:prose-strong:text-dark dark:prose-invert pb-12 {$isWideScreenStore
-		? 'max-w-full'
-		: 'max-w-5xl'}"
->
-	{@html hljsText}
-</article>

+ 0 - 257
docs/site/src/pages/guide/Guide.svelte

@@ -1,257 +0,0 @@
-<script>
-	// @ts-nocheck
-	import { onMount } from 'svelte';
-	import Router, { querystring, push, location } from 'svelte-spa-router';
-	import { isShowNavStore, isWideScreenStore } from '../../store';
-	import Menu from '../../components/menu/Menu.svelte';
-
-	import QuickStart from './QuickStart.svelte';
-	import Theme from './Theme.svelte';
-	import Faq from './Faq.svelte';
-	import Color from './Color.svelte';
-	import Color_en from './Color_en.svelte';
-	import Icon from './Icon.svelte';
-	import Internation from './Internation.svelte';
-	import Compatibility from './Compatibility.svelte';
-	import Logo from './Logo.svelte';
-	import About from './About.svelte';
-	import Changelog from './Changelog.svelte';
-	import Future from './Future.svelte';
-	import Shortkey from './Shortkey.svelte';
-	import Contribution from './Contribution.svelte';
-	import Milestone from './Milestone.svelte';
-	import Vscode from './Vscode.svelte';
-	import Generator from './Generator.svelte';
-	import Create from './Create.svelte';
-	import IconPlugin from './IconPlugin.svelte';
-
-	const isZh = localStorage.getItem('lang') === 'zh_CN';
-
-	const guideRoutes = {
-		'/quick-start': QuickStart,
-		'/theme': Theme,
-		'/faq': Faq,
-		'/color': isZh ? Color : Color_en,
-		'/icon': Icon,
-		'/internation': Internation,
-		'/compatibility': Compatibility,
-		'/logo': Logo,
-		'/about': About,
-		'/changelog': Changelog,
-		'/future': Future,
-		'/shortkey': Shortkey,
-		'/contribution': Contribution,
-		'/milestone': Milestone,
-		'/vscode': Vscode,
-		'/generator': Generator,
-		'/create': Create,
-		'/icon-plugin': IconPlugin,
-		'/': QuickStart
-	};
-
-	let params = new URLSearchParams('?' + $querystring);
-	const menuList = [
-		{
-			class: '常规',
-			class_en: 'General',
-			childs: [
-				{ title: '快速上手', title_en: 'Quick start', nav: 'quick-start', doc: 'quickStart' },
-				{ title: '主题配置', title_en: 'Theme', nav: 'theme', doc: 'theme' },
-				{ title: '图标', title_en: 'Icon', nav: 'icon', doc: 'icon' },
-				{ title: '国际化', title_en: 'Internationalization', nav: 'internation', doc: 'internation' },
-				{ title: '更新日志', title_en: 'Changelog', nav: 'changelog', doc: 'changelog' },
-				{ title: '常见问题', title_en: 'FAQ', nav: 'faq', doc: 'faq' },
-				{ title: '贡献指南', title_en: 'Contribution Guide', nav: 'contribution', doc: 'contribution' },
-				{ title: '兼容性', title_en: 'Compatibility', nav: 'compatibility', doc: 'compatibility' }
-			]
-		},
-		{
-			class: '设计',
-			class_en: 'Design',
-			childs: [
-				{ title: '色彩', title_en: 'Color', nav: 'color' },
-				{ title: 'LOGO', title_en: 'LOGO', nav: 'logo' }
-			]
-		},
-		{
-			class: '工具',
-			class_en: 'Tools',
-			childs: [
-				{ title: '主题生成器', title_en: 'Theme generator', nav: 'generator' },
-				{ title: 'IDE 插件', title_en: 'IDE plugin', nav: 'vscode', doc: 'vscode' },
-				{ title: '脚手架', title_en: 'Create cli', nav: 'create' },
-				{ title: '图标插件', title_en: 'Icon plugin', nav: 'icon-plugin' },
-				{ title: '快捷键', title_en: 'Shortcut key', nav: 'shortkey' }
-			]
-		},
-		{
-			class: '其他',
-			class_en: 'Other',
-			childs: [
-				{ title: '关于', title_en: 'About', nav: 'about', doc: 'about' },
-				{ title: '里程碑', title_en: 'Milestone', nav: 'milestone', doc: 'milestone' },
-				{ title: '计划', title_en: 'Future', nav: 'future', doc: 'future' }
-			]
-		}
-	];
-	//扁平 menuList
-	const flatMenuList = [];
-	for (let e = 0; e < menuList.length; e++) {
-		flatMenuList.push(...menuList[e].childs);
-	}
-	let currentNav = menuList[0].childs[0];
-	let menuHeight = 0;
-	const getMenuHeightFun = () => {
-		menuHeight = document.documentElement.clientHeight - 56;
-	};
-	const menuClickFun = (currentMenu) => {
-		if ($isShowNavStore) {
-			isShowNavStore.set;
-		}
-		currentNav = currentMenu.detail;
-		params.set('com', currentMenu.detail.nav);
-		// push(`/guide?nav=${currentMenu.detail.nav}`);
-		push(`/guide/${currentMenu.detail.nav}`);
-	};
-	onMount(() => {
-		menuHeight = document.documentElement.clientHeight - 56;
-		window.addEventListener('resize', getMenuHeightFun);
-		// @ts-ignore
-		hljs.highlightAll();
-		// 获取路由
-		// const currentRoute = window.location.href.split('#')[1];
-		// 如果 $location 以 /guide 开头,去掉 /guide 保存到 location
-		const locationNoGuide = $location.startsWith('/guide') ? $location.replace('/guide', '') : $location;
-		// locationNoGuide 是否在 guideRoutes 中
-		let isHave = false;
-		for (let key in guideRoutes) {
-			if (key === locationNoGuide) {
-				isHave = true;
-				break;
-			}
-		}
-		if (isHave) {
-			let arr = [];
-			for (let e = 0; e < menuList.length; e++) {
-				arr.push(...menuList[e].childs);
-			}
-			// 去掉 locationNoGuide 开头的 /
-			const locationNoGuideNoSlash = locationNoGuide.replace('/', '');
-			currentNav = arr.filter((item) => item.nav === locationNoGuideNoSlash)[0];
-		}
-		return () => {
-			window.removeEventListener('resize', getMenuHeightFun);
-		};
-	});
-	// 全屏
-	const changeFullFunc = () => {
-		if ($isWideScreenStore) {
-			isWideScreenStore.set(false);
-			localStorage.setItem('isFull', 'notFull');
-		} else {
-			isWideScreenStore.set(true);
-			localStorage.setItem('isFull', 'full');
-		}
-	};
-	// 编辑地址处理
-	const editUrlFn = (nav) => {
-		// main -> next
-		if (nav === 'create') {
-			return 'https://github.com/any-tdf/stdf/edit/next/packages/create-stdf/README' + (isZh ? '_CN' : '') + '.md';
-		}
-		if (nav === 'icon-plugin') {
-			return 'https://github.com/any-tdf/stdf/edit/next/packages/rollup-plugin-stdf-icon/README' + (isZh ? '_CN' : '') + '.md';
-		}
-		return `https://github.com/any-tdf/stdf/edit/next/docs/mds/guide/${flatMenuList.filter((item) => item.nav === nav)[0]?.doc}${
-			isZh ? '' : '_en'
-		}.md`;
-	};
-</script>
-
-<div class="flex">
-	<div
-		class="fixed -left-52 top-14 z-[100] w-48 overflow-y-scroll border-r border-black/10 bg-white transition-all duration-300 md:left-0 md:bg-transparent dark:border-white/20 dark:bg-black dark:md:bg-transparent"
-		class:left-0={$isShowNavStore}
-		class:-left-52={!$isShowNavStore}
-		style="height:{menuHeight + 'px'}"
-	>
-		<Menu {menuList} currentNav={currentNav.nav} on:MenuClick={menuClickFun} showNum={false} />
-	</div>
-	<div class="w-screen md:pl-48">
-		{#if currentNav.nav !== 'generator'}
-			<div class="px-4 py-12 md:px-8 md:py-4">
-				<div class="text-4xl font-bold">
-					{isZh ? currentNav.title : currentNav.title_en}
-				</div>
-			</div>
-			<div class="h-px bg-black/10 dark:bg-white/20"></div>
-		{/if}
-		<div class="px-4 pt-4 {currentNav.nav === 'generator' ? 'md:px-4 md:pt-4' : 'md:px-8 md:pt-12'}">
-			<Router routes={guideRoutes} prefix="/guide" />
-		</div>
-		{#if currentNav.nav != 'color' && currentNav.nav != 'logo' && currentNav.nav != 'shortkey' && currentNav.nav != 'generator'}
-			<div class="flex gap-2 px-4 pb-8 text-xs md:px-8">
-				<a href={editUrlFn(currentNav.nav)} class="text-primary dark:text-dark flex w-full" target="_blank">
-					<span class="mr-1 h-4 w-4">
-						<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="h-4 w-4" style="fill: currentColor;">
-							<path
-								d="M12.8995 6.85431L17.1421 11.0969L7.24264 20.9964H3V16.7538L12.8995 6.85431ZM14.3137 5.44009L16.435 3.31877C16.8256 2.92825 17.4587 2.92825 17.8492 3.31877L20.6777 6.1472C21.0682 6.53772 21.0682 7.17089 20.6777 7.56141L18.5563 9.68273L14.3137 5.44009Z"
-							/>
-						</svg>
-					</span>
-					{isZh ? '在 GitHub 上编辑' : 'Edit on GitHub'}
-				</a>
-			</div>
-		{/if}
-	</div>
-</div>
-
-{#if !$location.includes('generator')}
-	<button
-		class="bg-primary dark:bg-dark shadow-primary/50 dark:shadow-dark/50 fixed bottom-4 right-2 z-50 hidden h-8 w-8 rounded-full p-1.5 text-white shadow-md md:block dark:text-black"
-		on:click={changeFullFunc}
-	>
-		{#if $isWideScreenStore}
-			<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
-				><path
-					d="M20 3C20.5523 3 21 3.44772 21 4V20C21 20.5523 20.5523 21 20 21H4C3.44772 21 3 20.5523 3 20V4C3 3.44772 3.44772 3 4 3H20ZM11 5H5V19H11V15H13V19H19V5H13V9H11V5ZM15 9L18 12L15 15V13H9V15L6 12L9 9V11H15V9Z"
-					fill="currentColor"
-				></path></svg
-			>
-		{:else}
-			<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
-				><path
-					d="M20 3C20.5523 3 21 3.44772 21 4V20C21 20.5523 20.5523 21 20 21H4C3.44772 21 3 20.5523 3 20V4C3 3.44772 3.44772 3 4 3H20ZM11 5H5V10.999H7V9L10 12L7 15V13H5V19H11V17H13V19H19V13H17V15L14 12L17 9V10.999H19V5H13V7H11V5ZM13 13V15H11V13H13ZM13 9V11H11V9H13Z"
-					fill="currentColor"
-				></path></svg
-			>
-		{/if}
-	</button>
-{/if}
-<!-- 为 code-groups 预先编译 tailwind -->
-<div
-	class="peer-checked/tab-0-0:border-primary dark:peer-checked/tab-0-0:border-dark peer-checked/tab-0-1:border-primary dark:peer-checked/tab-0-1:border-dark peer-checked/tab-0-2:border-primary dark:peer-checked/tab-0-2:border-dark
-peer-checked/tab-0-3:border-primary dark:peer-checked/tab-0-3:border-dark peer-checked/tab-0-4:border-primary
-dark:peer-checked/tab-0-4:border-dark peer-checked/tab-0-5:border-primary dark:peer-checked/tab-0-5:border-dark
-peer-checked/tab-1-0:border-primary dark:peer-checked/tab-1-0:border-dark peer-checked/tab-1-1:border-primary
-dark:peer-checked/tab-1-1:border-dark peer-checked/tab-1-2:border-primary dark:peer-checked/tab-1-2:border-dark
-peer-checked/tab-1-3:border-primary dark:peer-checked/tab-1-3:border-dark peer-checked/tab-1-4:border-primary
-dark:peer-checked/tab-1-4:border-dark peer-checked/tab-1-5:border-primary dark:peer-checked/tab-1-5:border-dark
-peer-checked/tab-2-0:border-primary dark:peer-checked/tab-2-0:border-dark peer-checked/tab-2-1:border-primary
-dark:peer-checked/tab-2-1:border-dark peer-checked/tab-2-2:border-primary dark:peer-checked/tab-2-2:border-dark
-peer-checked/tab-2-3:border-primary dark:peer-checked/tab-2-3:border-dark peer-checked/tab-2-4:border-primary
-dark:peer-checked/tab-2-4:border-dark peer-checked/tab-2-5:border-primary dark:peer-checked/tab-2-5:border-dark
-peer-checked/tab-3-0:border-primary dark:peer-checked/tab-3-0:border-dark peer-checked/tab-3-1:border-primary
-dark:peer-checked/tab-3-1:border-dark peer-checked/tab-3-2:border-primary dark:peer-checked/tab-3-2:border-dark
-peer-checked/tab-3-3:border-primary dark:peer-checked/tab-3-3:border-dark peer-checked/tab-3-4:border-primary
-dark:peer-checked/tab-3-4:border-dark peer-checked/tab-3-5:border-primary dark:peer-checked/tab-3-5:border-dark
-hidden border-b-2 border-black/10 peer-checked/tab-0-0:block
-peer-checked/tab-0-1:block peer-checked/tab-0-2:block peer-checked/tab-0-3:block
-peer-checked/tab-0-4:block peer-checked/tab-0-5:block peer-checked/tab-1-0:block
-peer-checked/tab-1-1:block peer-checked/tab-1-2:block peer-checked/tab-1-3:block
-peer-checked/tab-1-4:block peer-checked/tab-1-5:block peer-checked/tab-2-0:block
-peer-checked/tab-2-1:block peer-checked/tab-2-2:block peer-checked/tab-2-3:block
-peer-checked/tab-2-4:block peer-checked/tab-2-5:block peer-checked/tab-3-0:block
-peer-checked/tab-3-1:block peer-checked/tab-3-2:block peer-checked/tab-3-3:block
-peer-checked/tab-3-4:block peer-checked/tab-3-5:block dark:border-white/10 dark:bg-[#202020]"
-></div>

+ 0 - 18
docs/site/src/pages/guide/Icon.svelte

@@ -1,18 +0,0 @@
-<script>
-	import { mdTextToHljs } from '../../utils/index';
-	import { isWideScreenStore } from '../../store';
-
-	import text from '../../../../mds/guide/icon.md';
-	import text_en from '../../../../mds/guide/icon_en.md';
-
-	const isZh = localStorage.getItem('lang') === 'zh_CN';
-	const hljsText = mdTextToHljs((isZh ? text : text_en).replace(/<a href="/g, '<a target="_blank" href="'));
-</script>
-
-<article
-	class="prose prose-strong:text-primary dark:prose-strong:text-dark dark:prose-invert pb-12 {$isWideScreenStore
-		? 'max-w-full'
-		: 'max-w-5xl'}"
->
-	{@html hljsText}
-</article>

+ 0 - 22
docs/site/src/pages/guide/IconPlugin.svelte

@@ -1,22 +0,0 @@
-<script>
-	import { mdTextToHljs, groupIconMdPlugin } from '../../utils/index';
-	import { isWideScreenStore } from '../../store';
-
-	// @ts-ignore
-	import iconPluginText from '../../../../../packages/rollup-plugin-stdf-icon/README_CN.md';
-	// @ts-ignore
-	import iconPluginText_en from '../../../../../packages/rollup-plugin-stdf-icon/README.md';
-
-	const isZh = localStorage.getItem('lang') === 'zh_CN';
-	const text = mdTextToHljs(
-		(isZh ? groupIconMdPlugin(iconPluginText) : groupIconMdPlugin(iconPluginText_en)).replace(/<a href="/g, '<a target="_blank" href="'),
-	);
-</script>
-
-<article
-	class="prose prose-strong:text-primary dark:prose-strong:text-dark dark:prose-invert pb-12 {$isWideScreenStore
-		? 'max-w-full'
-		: 'max-w-5xl'}"
->
-	{@html text}
-</article>

+ 0 - 18
docs/site/src/pages/guide/Internation.svelte

@@ -1,18 +0,0 @@
-<script>
-	import { mdTextToHljs } from '../../utils/index';
-	import { isWideScreenStore } from '../../store';
-
-	import text from '../../../../mds/guide/internation.md';
-	import text_en from '../../../../mds/guide/internation_en.md';
-
-	const isZh = localStorage.getItem('lang') === 'zh_CN';
-	const hljsText = mdTextToHljs((isZh ? text : text_en).replace(/<a href="/g, '<a target="_blank" href="'));
-</script>
-
-<article
-	class="prose prose-strong:text-primary dark:prose-strong:text-dark dark:prose-invert pb-12 {$isWideScreenStore
-		? 'max-w-full'
-		: 'max-w-5xl'}"
->
-	{@html hljsText}
-</article>

+ 0 - 19
docs/site/src/pages/guide/Milestone.svelte

@@ -1,19 +0,0 @@
-<script>
-	import { mdTextToHljs } from '../../utils/index';
-	import { isWideScreenStore } from '../../store';
-
-	import text from '../../../../mds/guide/milestone.md';
-	import text_en from '../../../../mds/guide/milestone_en.md';
-
-	const isZh = localStorage.getItem('lang') === 'zh_CN';
-
-	const hljsText = mdTextToHljs((isZh ? text : text_en).replace(/<a href="/g, '<a target="_blank" href="'));
-</script>
-
-<article
-	class="prose prose-strong:text-primary dark:prose-strong:text-dark dark:prose-invert pb-12 {$isWideScreenStore
-		? 'max-w-full'
-		: 'max-w-5xl'}"
->
-	{@html hljsText}
-</article>

+ 0 - 18
docs/site/src/pages/guide/Theme.svelte

@@ -1,18 +0,0 @@
-<script>
-	import { mdTextToHljs } from '../../utils/index';
-	import { isWideScreenStore } from '../../store';
-
-	import theme from '../../../../mds/guide/theme.md';
-	import theme_en from '../../../../mds/guide/theme_en.md';
-
-	const isZh = localStorage.getItem('lang') === 'zh_CN';
-	const text = mdTextToHljs((isZh ? theme : theme_en).replace(/<a href="/g, '<a target="_blank" href="'));
-</script>
-
-<article
-	class="prose prose-strong:text-primary dark:prose-strong:text-dark dark:prose-invert pb-12 {$isWideScreenStore
-		? 'max-w-full'
-		: 'max-w-5xl'}"
->
-	{@html text}
-</article>

+ 0 - 18
docs/site/src/pages/guide/Vscode.svelte

@@ -1,18 +0,0 @@
-<script>
-	import { mdTextToHljs } from '../../utils/index';
-	import { isWideScreenStore } from '../../store';
-
-	import text from '../../../../mds/guide/vscode.md';
-	import text_en from '../../../../mds/guide/vscode_en.md';
-
-	const isZh = localStorage.getItem('lang') === 'zh_CN';
-	const hljsText = mdTextToHljs((isZh ? text : text_en).replace(/<a href="/g, '<a target="_blank" href="'));
-</script>
-
-<article
-	class="prose prose-strong:text-primary dark:prose-strong:text-dark dark:prose-invert pb-12 {$isWideScreenStore
-		? 'max-w-full'
-		: 'max-w-5xl'}"
->
-	{@html hljsText}
-</article>

+ 0 - 16
docs/site/src/routers.js

@@ -1,16 +0,0 @@
-// @ts-ignore
-import Home from './pages/Home.svelte';
-// @ts-ignore
-import Guide from './pages/guide/Guide.svelte';
-// @ts-ignore
-import Components from './pages/components/Components.svelte';
-
-const routes = {
-	'/': Home,
-	'/guide/*': Guide,
-	'/guide': Guide,
-	'/components': Components,
-	'*': Home,
-};
-
-export default routes;

+ 108 - 0
docs/site/src/routes/+layout.svelte

@@ -0,0 +1,108 @@
+<script lang="ts">
+	import themes from '../data/themes/index.js';
+	import { switchTheme } from 'stdf/theme';
+	import Header from '$lib/header/Header.svelte';
+	import CmdK from '$lib/cmdk/CmdK.svelte';
+	import Fund from '$lib/fund/Fund.svelte';
+	import { page } from '$app/stores';
+	import { isCmdKStore, isShowFundStore } from '../store.js';
+	import '../app.css';
+
+	let { children } = $props();
+
+	let showLeftNav = $state(false); //是否显示左侧导航
+	let isHome = $page.url.pathname === '/' || $page.url.pathname === '';
+
+	//路由改变时,更新左侧导航
+	$effect(() => {
+		showLeftNav = $page.url.pathname.startsWith('/guide') || $page.url.pathname === '/components';
+	});
+	// 点击顶部菜单事件
+	const headerCmdKFun = () => {
+		isCmdKStore.set(true);
+	};
+
+	const currentTheme = localStorage.getItem('theme_color') || 'STDF';
+	// 设置默认主题色
+	themes.forEach((item) => {
+		if (item.name === currentTheme) {
+			const theme = item.theme;
+			switchTheme(theme);
+			// 修改 HTML 的 meta name="theme-color" 属性,适配 Safari 的 tab 背景色,需要设置 light 和 dark 两种颜色
+			const safariLight = theme.color.primaryWhite;
+			const safariDark = theme.color.darkBlack;
+			// 查找 meta 标签,name="theme-color" 且 media="(prefers-color-scheme: light)"
+			const lightMeta = document.querySelector('meta[name="theme-color"][media="(prefers-color-scheme: light)"]');
+			// 查找 meta 标签,name="theme-color" 且 media="(prefers-color-scheme: dark)"
+			const darkMeta = document.querySelector('meta[name="theme-color"][media="(prefers-color-scheme: dark)"]');
+			// 如果找到了,就修改它的 content 属性
+			if (lightMeta) {
+				lightMeta.setAttribute('content', safariLight);
+			}
+			if (darkMeta) {
+				darkMeta.setAttribute('content', safariDark);
+			}
+		}
+	});
+
+	let urlLang = window.location.href.split('?')[1];
+	if (!urlLang || (urlLang && !urlLang.includes('lang'))) {
+		if (!localStorage.getItem('lang')) {
+			//获取浏览器语言前两位
+			const lang = navigator.language.substring(0, 2);
+			if (lang === 'en') {
+				localStorage.setItem('lang', 'en_US');
+			} else {
+				localStorage.setItem('lang', 'zh_CN');
+			}
+		}
+	} else {
+		let urlParams = new URLSearchParams(urlLang);
+		localStorage.setItem('lang', urlParams.get('lang') || '');
+		setTimeout(() => {
+			// window.location.href = window.location.href.replace(/(\?|#)[^'"]*/, '');//去除参数
+			const url = new URL(window.location.href);
+			url.searchParams.delete('lang');
+			window.history.pushState({}, '', url.toString()); //刷新页面
+		}, 10);
+	}
+	if (localStorage.getItem('theme') === 'dark') {
+		document.documentElement.classList.add('dark');
+	} else if (localStorage.getItem('theme') === 'light') {
+		document.documentElement.classList.remove('dark');
+	} else {
+		if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
+			document.documentElement.classList.add('dark');
+		} else {
+			document.documentElement.classList.remove('dark');
+		}
+	}
+	const isZh = localStorage.getItem('lang') === 'zh_CN';
+</script>
+
+<svelte:head>
+	<title>STDF - {isZh ? '移动 web 组件库' : 'Mobile web component library'}</title>
+</svelte:head>
+
+<main class="relative min-h-screen bg-primaryWhite text-justify text-black antialiased dark:bg-darkBlack dark:text-white">
+	<!-- main -> next -->
+	{#if $page.url.pathname === '' || $page.url.pathname === '/'}
+		<div class="bg-primary px-2 py-1 text-center text-xs text-white dark:bg-dark dark:text-black">
+			{#if isZh}
+				这是 v1.0.0@next 文档,v0.x 请访问 <a href="https://stdf.design" class="underline" target="_blank">stdf.design</a>
+			{:else}
+				This is the v1.0.0@next documentation, please visit <a href="https://stdf.design" class="underline" target="_blank">stdf.design</a> for
+				v0.x
+			{/if}
+		</div>
+	{/if}
+	<Header {showLeftNav} showBottonLine={!isHome} onclickCmdK={headerCmdKFun} />
+	<!-- <Router {routes} /> -->
+	{@render children()}
+
+	<CmdK />
+	<!-- 赞赏 -->
+	{#if $isShowFundStore}
+		<Fund />
+	{/if}
+</main>

+ 3 - 0
docs/site/src/routes/+layout.ts

@@ -0,0 +1,3 @@
+// 修改 ssr 为 false,使其不再使用服务端渲染,而是使用客户端渲染
+// Change ssr to false to use client-side rendering instead of server-side rendering
+export const ssr = false;

+ 626 - 0
docs/site/src/routes/+page.svelte

@@ -0,0 +1,626 @@
+<script lang="ts">
+	import { onMount, onDestroy } from 'svelte';
+	// import { link } from 'svelte-spa-router';
+	import { fade } from 'svelte/transition';
+	import { Confetti } from 'svelte-confetti';
+	import { currentThemeStore, currentColorStore } from '../store';
+	import { encodeData, rendererLine } from 'beautify-qrcode';
+
+	const descList = [
+		{
+			title: 'Simple',
+			titleZh: '简 单',
+			desc: '使用 Svelte 语法编码简洁迅速。组件源码逻辑清晰、简单易懂、中英注释详细,查看源码、修改逻辑也可以得心应手。',
+			descEn:
+				'Coding with Svelte syntax is simple and fast. The component source code logic is clear, simple and easy to understand, and the English and Chinese comments are detailed. You can also get used to it by viewing the source code and modifying the logic yourself.',
+			icon: '/assets/images/3D-simple.png',
+			iconDark: '/assets/images/3D-simple-dark.png',
+			shwTip: false
+		},
+		{
+			title: 'Thin',
+			titleZh: '轻 量',
+			desc: '源码体积小巧,无三方依赖。基于 Svelte 与 Tailwind 编译出的代码在体积上也优势明显,这在移动端显得尤为重要。',
+			descEn:
+				'The source code is small and has no third-party dependencies. The code compiled based on Svelte and Tailwind also has obvious advantages in terms of volume, which is particularly important in mobile terminals.',
+			icon: '/assets/images/3D-thin.png',
+			iconDark: '/assets/images/3D-thin-dark.png',
+			shwTip: true
+		},
+		{
+			title: 'Design',
+			titleZh: '设 计',
+			desc: '针对移动设备优化设计与交互,使用友好、高效、灵活。支持通过简单配置定制颜色系统、圆角风格、亮暗模式等。',
+			descEn:
+				'Optimized design and interaction for mobile devices, user-friendly, efficient, and flexible. Support customizing color system, corner style, light and dark mode, etc. through simple configuration.',
+			icon: '/assets/images/3D-design.png',
+			iconDark: '/assets/images/3D-design-dark.png',
+			shwTip: false
+		},
+		{
+			title: 'Fast',
+			titleZh: '快 速',
+			desc: '无运行时,无虚拟 DOM,无烦杂的 CSS 代码,状态管理简单轻快。编码过程、编译处理、线上运行全都快起来了。',
+			descEn:
+				'No runtime, no virtual DOM, no cumbersome CSS code, simple and fast state management. The coding process, compilation processing, and online running are all faster.',
+			icon: '/assets/images/3D-fast.png',
+			iconDark: '/assets/images/3D-fast-dark.png',
+			shwTip: false
+		}
+	];
+	const dominant = {
+		title: '💪 优势 & 目标',
+		title_en: '💪 Advantages & Goals',
+		data: [
+			{
+				icon: 'svelte',
+				p: '补充 Svelte 生态,让开发者可以更快速更舒服地开发出高质量的应用。',
+				p_en: 'Supplement the Svelte ecosystem so that developers can develop high-quality applications faster and more comfortably.'
+			},
+			{
+				icon: 'css3-line',
+				p: '避免写繁琐的 CSS 代码,让开发者专注于业务逻辑,提高开发效率。',
+				p_en: 'Avoid writing tedious CSS code, allowing developers to focus on business logic and improve development efficiency.'
+			},
+			{
+				icon: 'contrast-2-line',
+				p: '支持暗黑模式与主题配置,方便开发者直接适配,让应用更加现代化。',
+				p_en: 'Supports dark mode and theme configuration, making it easy for developers to adapt directly and make applications more modern.'
+			},
+			{
+				icon: 'paint-brush-line',
+				p: '普适性较强。移动端组件库多用于 C 端,对比 B 端更加需要注重 UI 的灵活性。',
+				p_en: 'It has strong versatility. Mobile component libraries are mostly used in C-end scenarios where UI flexibility is more important than B-end.'
+			},
+			{
+				icon: 'clockwise-line',
+				p: '注重交互与体验。适当的过渡动画与合理的交互设计,希望给你更好的用户体验。',
+				p_en: 'Emphasis on interaction and experience. Appropriate transition animations and reasonable interaction design hope to give you a better user experience.'
+			},
+			{
+				icon: 'article-line',
+				p: '站点文档、示例、源码注释都支持中英双语,且不再中英混杂,一目了然。',
+				p_en: 'Site documentation, examples, and source code comments all support bilingual Chinese and English, making it clear at a glance.'
+			},
+			{
+				icon: 'file-copy-2-line',
+				p: '示例代码丰富,方便直接复制使用,配备脚手架、插件等工具,对开发者友好。',
+				p_en: 'The example code is extensive and convenient for direct copying and usage. It is equipped with scaffolding, plugins, etc. making it developer-friendly.'
+			},
+			{
+				icon: 'planet-line',
+				p: '组件支持国际化(目前 60+ 语言),让应用轻松实现多语言支持。',
+				p_en: 'Component supports internationalization (currently 60+ languages), making it easy for applications to achieve multilingual support.'
+			}
+		]
+	};
+	const ugly = {
+		title: '🔔 提前警告',
+		title_en: '🔔 Early Warning',
+		data: [
+			{
+				icon: 'medal-line',
+				p: 'STDF 不体现任何「价值观」,更加不能为您「赋能」,只希望能给您更好的开发体验,很简单很朴实。',
+				p_en: 'STDF does not reflect any "values", and cannot "empower" you. We only hope to provide you with a better development experience, which is simple and straightforward.'
+			},
+			{
+				icon: 'service-line',
+				p: 'Svelte 生态相对 Vue 和 React 还很薄弱,如果您有兴趣,请积极参与和丰富 Svelte 生态。',
+				p_en: 'The Svelte ecosystem is still relatively weak compared to Vue and React. If you are interested, please actively participate in and enrich the Svelte ecosystem.'
+			},
+			{
+				icon: 'bard-line',
+				p: 'STDF 也适用于 Svelte 生态的其他工程,比如 SvelteKit 等,使用前请确保知晓它们的基础原理。',
+				p_en: 'STDF also applies to other projects in the Svelte ecosystem, such as SvelteKit, etc. When using them, please ensure that you understand their basic principles.'
+			},
+			{
+				icon: 'git-close-pull-request-line',
+				p: 'STDF 也适用于 Tailwind CSS 的类库,如 UnoCSS 等,使用它们请确保您知晓它们的基础原理。',
+				p_en: 'STDF also applies to class libraries of Tailwind CSS, such as UnoCSS, etc. When using them, please ensure that you understand their basic principles.'
+			}
+		]
+	};
+	const isZh = localStorage.getItem('lang') === 'zh_CN';
+
+	// 赞助人员
+	const thinkGithub = [{ name: 'yuedanlabs', amount: 10 }];
+
+	const bottomInfo = [
+		{
+			title: '相关',
+			title_en: 'Related',
+			list: [
+				{ title: 'Svelte', title_en: 'Svelte', link: 'https://svelte.dev', _blank: true },
+				{ title: 'Tailwind', title_en: 'Tailwind', link: 'https://tailwindcss.com', _blank: true },
+				{ title: 'Remix Icon', title_en: 'Remix Icon', link: 'https://remixicon.com', _blank: true }
+				// { title: 'RTDF(计划中)', title_en: 'RTDF(intend)', link: '', _blank: false },
+				// { title: 'VTDF(计划中)', title_en: 'VTDF(intend)', link: '', _blank: false },
+			]
+		},
+		{
+			title: '工具',
+			title_en: 'Tools',
+			list: [
+				{
+					title: 'create-stdf',
+					title_en: 'create-stdf',
+					link: 'https://www.npmjs.com/package/create-stdf',
+					_blank: true
+				},
+				{
+					title: 'rollup-plugin-stdf-icon',
+					title_en: 'rollup-plugin-stdf-icon',
+					link: 'https://www.npmjs.com/package/rollup-plugin-stdf-icon',
+					_blank: true
+				},
+				{
+					title: 'STDF for VS Code',
+					title_en: 'STDF for VS Code',
+					link: 'https://marketplace.visualstudio.com/items?itemName=STDF.stdf-vscode-extension',
+					_blank: true
+				}
+			]
+		},
+		{
+			title: '帮助',
+			title_en: 'Help',
+			list: [
+				{ title: '关于', title_en: 'About', link: '/guide/about', _blank: false },
+				{ title: '常见问题', title_en: 'FAQ', link: '/guide/faq', _blank: false },
+				{ title: '更新日志', title_en: 'Changelog', link: '/guide/changelog', _blank: false },
+				{
+					title: '开源许可',
+					title_en: 'License',
+					link: 'https://github.com/any-tdf/stdf/blob/main/LICENSE',
+					_blank: true
+				}
+			]
+		},
+		{
+			title: '社区',
+			title_en: 'Community',
+			list: [
+				// { title: 'GitHub', title_en: 'GitHub', link: 'https://github.com/any-tdf/stdf' },
+				{
+					title: 'QQ 群',
+					title_en: 'QQ Group',
+					link: 'https://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=U8ZlXJ3KVpTI9oZzs1jBnyWc3gVA0h6Y&authKey=ScWu0nU9g8BqNsC7o2eYkESwgVDVz9vzGNZEb17MrEAay9%2F7bTkXDiLJRIzo2vrg&noverify=0&group_code=581073686',
+					_blank: true
+				},
+				// { title: '钉钉群', title_en: 'DingTalk Group', link: '', _blank: true },
+				{
+					title: 'Discord',
+					title_en: 'Discord',
+					link: 'https://discord.gg/DMkHu8GGre',
+					_blank: true
+				},
+				{
+					title: 'QQ 频道',
+					title_en: 'QQ Discord',
+					link: 'https://pd.qq.com/s/fdd8incyr',
+					_blank: true
+				},
+				{
+					title: 'Discussions',
+					title_en: 'Discussions',
+					link: 'https://github.com/any-tdf/stdf/discussions',
+					_blank: true
+				}
+			]
+		}
+	];
+	let showQr = $state(false);
+	let show3D = $state(!(localStorage.getItem('show3D') === '0'));
+
+	const change3DFunc = () => {
+		show3D = !show3D;
+		localStorage.setItem('show3D', show3D ? '1' : '0');
+	};
+
+	const io = new IntersectionObserver((entries: IntersectionObserverEntry[]) => {
+		entries.forEach((item) => {
+			// isIntersecting 是一个 Boolean 值,判断目标元素当前是否可见
+			if (item.isIntersecting) {
+				const target = item.target as HTMLElement;
+				target.style.opacity = '1';
+				target.style.transform = 'translateY(0)';
+				setTimeout(() => {
+					target.style.transitionDuration = '300ms';
+				}, 1000);
+			} else {
+				// item.target.style.opacity = 0;
+				// item.target.style.transform = 'translateY(200px)';
+			}
+		});
+	});
+	let A_a1Svg = $state();
+	const mouseenterFun = () => {
+		/**
+		 * A_a1
+		 * @param {Object} qrcode
+		 * @param {Object} options
+		 * @param {String} [options.type]  连线方向 0=>左右 1=>上下 2=>纵横 3=>回环 4=>左上—右下 5=>右上—左下 6=>交叉"
+		 * @param {String} [options.size] 连线粗细
+		 * @param {String} [options.opacity] 连线不透明度
+		 * @param {String} [options.posType] 定位点样式  0=>矩形 1=>圆形 2=>行星 3=>圆角矩形
+		 * @param {String} [options.otherColor] 连线颜色
+		 * @param {String} [options.posColor] 定位点颜色
+		 */
+		const qrcode = encodeData({
+			// main -> next
+			text: 'https://next-demo.stdf.design?lang=' + (isZh ? 'zh_CN' : 'en_US'),
+			isSpace: false
+		});
+		const color = $currentThemeStore === 'dark' ? 'rgb(var(--theme-color-dark))' : 'rgb(var(--theme-color-primary))';
+		A_a1Svg = rendererLine(qrcode, { posType: 2, otherColor: color, posColor: color });
+		showQr = true;
+	};
+	onMount(() => {
+		const intersectionList = document.querySelectorAll('.intersection');
+		intersectionList.forEach((item) => {
+			// 开始时 opacity 为 0,不可见,transform 为 translateY(200px)
+			const target = item as HTMLElement;
+			target.style.opacity = '0';
+			target.style.transform = 'translateY(200px)';
+			target.style.transitionDuration = '1s';
+			io.observe(item);
+		});
+	});
+	const unsubscribe = currentColorStore.subscribe(() => {
+		show3D = false;
+		setTimeout(() => {
+			show3D = localStorage.getItem('show3D') === '1';
+		}, 0);
+	});
+	onDestroy(() => {
+		unsubscribe();
+	});
+</script>
+
+<div class="mx-auto max-w-[2000px]">
+	<div class="flex-row-reverse justify-center lg:flex">
+		{#if show3D}
+			<div class="group relative mt-10 basis-1/2 overflow-hidden md:mt-0">
+				<spline-viewer
+					class="aspect-[4/3] scale-110 md:aspect-auto md:scale-100"
+					url="/assets/3d/scene.splinecode"
+					background={$currentThemeStore === 'dark'
+						? `rgb(${getComputedStyle(document.documentElement).getPropertyValue('--theme-color-darkBlack')})`
+						: `rgb(${getComputedStyle(document.documentElement).getPropertyValue('--theme-color-primaryWhite')})`}
+				></spline-viewer>
+				<!-- background="rgb(242, 242, 243)" -->
+				<!-- background={backgroundColor} -->
+				<!-- background="rgb(255, 0, 0)" -->
+				<button
+					onclick={() => {
+						show3D = false;
+						localStorage.setItem('show3D', '0');
+					}}
+					class="absolute left-10 top-10 hidden scale-0 cursor-pointer rounded bg-black/5 px-2 py-1 text-xs text-black/80 transition-all duration-500 group-hover:scale-100 dark:bg-white/10 dark:text-white/90 md:block"
+				>
+					{isZh ? '隐藏 3D LOGO' : 'Hidden 3D LOGO'}
+				</button>
+			</div>
+		{:else}
+			<!-- 图片 -->
+			<div class="group relative mt-10 flex basis-1/2 flex-col justify-center overflow-hidden md:mt-0">
+				<img src="/assets/3d/dark.png" alt="" class="hidden w-full object-cover dark:block" />
+				<img src="/assets/3d/light.png" alt="" class="block w-full object-cover dark:hidden" />
+				<button
+					onclick={() => {
+						show3D = true;
+						localStorage.setItem('show3D', '1');
+					}}
+					class="absolute left-10 top-10 hidden scale-0 cursor-pointer rounded bg-black/5 px-2 py-1 text-xs text-black/80 transition-all duration-300 group-hover:scale-100 dark:bg-white/10 dark:text-white/90 md:block"
+				>
+					{isZh ? '显示 3D LOGO' : 'Show 3D LOGO'}
+				</button>
+			</div>
+		{/if}
+		<div class="flex basis-2/5 flex-col justify-center py-16 text-center md:py-20">
+			<div class="relative mb-20 mt-16 hidden h-20 flex-col items-center justify-center md:flex md:h-28">
+				<div class="absolute animate-dynamicsBg rounded-full opacity-50 blur-xl md:opacity-100 md:blur-3xl">
+					<svg viewBox="0 0 100 100">
+						<path
+							fill-rule="evenodd"
+							clip-rule="evenodd"
+							d="M50 0V100C22.3858 100 0 77.6142 0 50C0 22.3858 22.3858 0 50 0Z"
+							class="fill-dark"
+						/>
+						<path
+							fill-rule="evenodd"
+							clip-rule="evenodd"
+							d="M50 100V0C77.6142 0 100 22.3858 100 50C100 77.6142 77.6142 100 50 100Z"
+							class="fill-primary"
+						/>
+						<circle cx="50" cy="25" r="25" class="fill-primary" />
+						<circle cx="50" cy="75" r="25" class="fill-dark" />
+						<circle cx="50.25" cy="25.25" r="6.25" class="fill-dark" />
+						<circle cx="50.25" cy="75.25" r="6.25" class="fill-primary" />
+					</svg>
+				</div>
+				<div
+					class="absolute h-full w-28 md:w-36"
+					style="filter: drop-shadow(0 10px 8px rgb(0 0 0 / 0.05)) drop-shadow(0 4px 3px rgb(0 0 0 / 0.1));"
+				>
+					<svg viewBox="0 0 90 80" class="group">
+						<path
+							class="fill-primary dark:fill-dark"
+							d="M0 0H20H40H50C64.8056 0 77.7325 8.04398 84.6487 20H50H40V22.6757V30H50C55.5229 30 60 34.4771 60 40C60 45.5229 55.5229 50 50 50H40V57.3243V78.7398V80H20V66.4583V20H15.3513H0V0ZM50 80C72.0914 80 90 62.0914 90 40C90 36.547 89.5625 33.1962 88.7398 30H67.3244C69.0261 32.9417 70 36.3571 70 40C70 51.0457 61.0457 60 50 60V80Z"
+						/>
+						<path
+							style="stroke-dasharray: 400;stroke-dashoffset: 400;"
+							class="fill-dark stroke-dark stroke-1 text-dark group-hover:animate-path dark:fill-primary dark:stroke-primary dark:text-primary"
+							d="M20 30V0L0 50H20V80L40 30H20Z"
+						/>
+					</svg>
+				</div>
+			</div>
+			<div class="text-5xl font-medium md:text-8xl">S T D F</div>
+			<div class="mt-4 px-4 md:text-xl">
+				{#if isZh}
+					基于
+					<a
+						href="https://svelte.dev"
+						class="underline decoration-svelte underline-offset-2 transition-all hover:text-svelte"
+						target="_blank"
+						title={isZh ? '打开 Svelte 官方站点' : 'Open Svelte official website'}
+					>
+						Svelte
+					</a>
+					与
+					<a
+						href="https://tailwindcss.com/"
+						class="underline decoration-tailwind underline-offset-2 transition-all hover:text-tailwind"
+						target="_blank"
+						title={isZh ? '打开 Tailwind CSS 官方站点' : 'Open Tailwind CSS official website'}
+					>
+						Tailwind
+					</a>
+					的移动 web 组件库
+				{:else}
+					Mobile web component
+					<br class="md:hidden" />
+					library based on
+					<a
+						href="https://svelte.dev"
+						class="underline decoration-svelte underline-offset-2 transition-all hover:text-svelte"
+						target="_blank"
+					>
+						Svelte
+					</a>
+					and
+					<a
+						href="https://tailwindcss.com/"
+						class="underline decoration-tailwind underline-offset-2 transition-all hover:text-tailwind"
+						target="_blank"
+					>
+						Tailwind
+					</a>
+				{/if}
+			</div>
+			<div class="mb-8 mt-8 flex justify-center gap-4 space-x-8 md:mb-10 md:mt-16">
+				<a
+					href="/guide"
+					class="group relative rounded bg-primary px-6 py-2 text-white transition-all hover:bg-primary/80 dark:bg-dark dark:text-black hover:dark:bg-dark/80"
+				>
+					{isZh ? '开始使用' : 'Get Started'}
+					<span class="absolute left-1/2 top-0 hidden group-hover:block">
+						<Confetti infinite rounded />
+					</span>
+				</a>
+				<!-- use:link -->
+				<a
+					href="/"
+					onmouseleave={() => (showQr = false)}
+					onmouseenter={mouseenterFun}
+					class="relative hidden rounded border border-solid border-primary px-6 py-2 transition-all dark:border-dark md:block"
+				>
+					{isZh ? '扫码示例' : 'QR Demo'}
+					{#if showQr}
+						<div
+							class="absolute left-full top-0 z-10 block w-52 -translate-y-1/3 translate-x-2 rounded-lg border border-black/5 p-2 shadow-lg dark:hidden"
+							in:fade={{ duration: 300 }}
+							out:fade={{ duration: 0 }}
+						>
+							<!-- eslint-disable-next-line svelte/no-at-html-tags -->
+							<span>{@html A_a1Svg}</span>
+							<!-- <QrCode value="https://demo.stdf.design/#/" size={200} color="#fff" background="#23262B" /> -->
+						</div>
+						<div
+							class="absolute left-full top-0 z-10 hidden w-52 -translate-y-1/3 translate-x-2 rounded-lg border border-white/5 bg-black p-2 shadow-lg dark:block"
+							in:fade={{ duration: 300 }}
+							out:fade={{ duration: 0 }}
+						>
+							<!-- eslint-disable-next-line svelte/no-at-html-tags -->
+							<span>{@html A_a1Svg}</span>
+							<!-- <QrCode value="https://demo.stdf.design/#/" size={200} color="#fff" background="#24262b" /> -->
+						</div>
+					{/if}
+				</a>
+				<!-- main -> next -->
+				<a
+					href={'https://next-demo.stdf.design?lang=' + (isZh ? 'zh_CN' : 'en_US')}
+					target="_blank"
+					class="block rounded border border-solid border-primary px-6 py-2 transition-all dark:border-dark md:hidden"
+				>
+					{isZh ? '查看示例' : 'Examples'}
+				</a>
+			</div>
+		</div>
+	</div>
+	<div class="flex flex-wrap justify-around gap-8 px-8 xl:flex-nowrap">
+		{#each descList as desc}
+			<div
+				class="intersection group flex w-full flex-col items-center space-y-5 overflow-hidden rounded-xl border-black/5 pb-8 transition-all duration-300 ease-out dark:border-white/5 dark:hover:shadow-white/5 sm:w-2/3 md:w-80 lg:w-96"
+			>
+				<div class="overflow-hidden">
+					<img
+						class="block scale-100 object-cover transition-all duration-500 group-hover:scale-[1.6] dark:hidden"
+						src={desc.icon}
+						alt=""
+					/>
+					<img
+						class="hidden scale-100 object-cover transition-all duration-500 group-hover:scale-[1.6] dark:block"
+						src={desc.iconDark}
+						alt=""
+					/>
+				</div>
+				{#if isZh}
+					<div class="py-4 text-3xl font-medium">{isZh ? desc.titleZh : desc.title}</div>
+				{/if}
+				<div class="text-sm text-black/70 dark:text-white/60 {isZh ? 'text-justify' : 'pt-10 text-left'}">
+					{isZh ? desc.desc : desc.descEn}
+				</div>
+			</div>
+		{/each}
+	</div>
+
+	<div class="px-4 pb-10 md:px-12 md:pb-20" class:text-left={!isZh}>
+		<div class="mt-40">
+			<div class="intersection my-10 text-center text-2xl font-bold transition-all ease-out md:my-20 md:text-4xl">
+				{isZh ? dominant.title : dominant.title_en}
+			</div>
+			<div class="grid grid-cols-1 gap-10 md:grid-cols-4">
+				{#each dominant.data as item}
+					<div
+						class="intersection border-px group relative overflow-hidden rounded-lg border border-black/5 p-0.5 transition-all ease-out dark:border-white/5"
+					>
+						<div
+							class="absolute -left-1/2 top-1/3 hidden h-1/2 w-[200%] bg-primary group-hover:block {$currentThemeStore === 'dark'
+								? 'animate-spin-line-dark'
+								: 'animate-spin-line'}"
+						></div>
+						<div class="relative h-full w-full rounded-lg bg-primaryWhite px-8 py-10 dark:bg-darkBlack">
+							<div class="h-8 w-8 flex-none text-primary transition-all ease-out group-hover:scale-90 dark:text-dark">
+								<svg style="fill: currentColor;display: inline;" viewBox="0 0 24 24">
+									<use xlink:href="/assets/fonts/home.symbol.svg#{item.icon}" />
+								</svg>
+							</div>
+							<p class="mt-6 text-sm opacity-90">{isZh ? item.p : item.p_en}</p>
+						</div>
+					</div>
+				{/each}
+			</div>
+		</div>
+		<div class="mt-32 md:mt-48">
+			<div class="intersection my-10 text-center text-2xl font-bold transition-all ease-out md:my-20 md:text-4xl">
+				{isZh ? ugly.title : ugly.title_en}
+			</div>
+			<div class="grid grid-cols-1 gap-10 md:grid-cols-4">
+				{#each ugly.data as item}
+					<div
+						class="intersection border-px group relative overflow-hidden rounded-lg border border-black/5 p-0.5 transition-all ease-out dark:border-white/5"
+					>
+						<div
+							class="absolute -left-1/2 top-1/3 hidden h-1/2 w-[200%] bg-primary group-hover:block {$currentThemeStore === 'dark'
+								? 'animate-spin-line-dark'
+								: 'animate-spin-line'}"
+						></div>
+						<div class="relative h-full w-full rounded-lg bg-primaryWhite px-8 py-10 dark:bg-darkBlack">
+							<div class="h-8 w-8 flex-none text-primary transition-all ease-out group-hover:scale-90 dark:text-dark">
+								<svg style="fill: currentColor;display: inline;" viewBox="0 0 24 24">
+									<use xlink:href="/assets/fonts/home.symbol.svg#{item.icon}" />
+								</svg>
+							</div>
+							<p class="mt-6 text-sm opacity-90">{isZh ? item.p : item.p_en}</p>
+						</div>
+					</div>
+				{/each}
+			</div>
+
+			<!-- <div class="space-y-10">
+            {#each isZh ? ugly.p : ugly.p_en as item, i}
+                <p>{item}</p>
+            {/each}
+        </div> -->
+		</div>
+	</div>
+
+	<!-- <div class="hidden md:flex justify-center mb-20">
+    <article class={`prose dark:prose-invert max-w-none text-xs overflow-auto`} style="height:{500}px">
+        <pre><code class="hljs">{@html highlightedCode}</code></pre>
+    </article>
+    <div class=" ml-2 border border-black/10 dark:border-gray-400 w-[392px] grow-0 shrink-0 overflow-auto" style="height:{500}px">
+        <img src="/assets/images/home/zh/9.png" alt="" class='w-full' />
+    </div>
+</div> -->
+
+	<div class="px-4 pb-10 text-center md:px-12 md:pb-20">
+		<div class="intersection my-5 text-2xl font-bold transition-all ease-out md:my-10 md:text-4xl">
+			🎖 {isZh ? '贡献者' : 'Contributors'}
+		</div>
+		<div class="intersection flex justify-center">
+			<a href="https://github.com/any-tdf/stdf/graphs/contributors" target="_blank">
+				<img src="https://contrib.rocks/image?repo=any-tdf/stdf" title={isZh ? '贡献者' : 'Contributors'} alt="" />
+			</a>
+		</div>
+	</div>
+
+	<!-- 赞助者 -->
+	<div class="px-4 pb-20 text-center md:px-12 md:pb-40">
+		<div class="intersection my-5 text-2xl font-bold transition-all ease-out md:my-10 md:text-4xl">
+			🙏 {isZh ? '赞助者' : 'Sponsors'}
+		</div>
+		<div class="">
+			<div class="intersection mb-4">GitHub</div>
+			<div class="flex flex-wrap justify-center gap-4">
+				{#each thinkGithub as item}
+					<a class="intersection" href={'https://github.com/' + item.name} target="_blank">
+						<img
+							class="h-16 w-16 overflow-hidden rounded-full"
+							src={'https://avatars.githubusercontent.com/' + item.name}
+							title={(isZh ? '感谢 ' : 'Thanks ') + item.name}
+							alt=""
+						/>
+					</a>
+				{/each}
+			</div>
+		</div>
+	</div>
+</div>
+<div class="grid grid-cols-2 gap-10 bg-white px-4 pb-16 pt-20 text-center dark:bg-black md:grid-cols-4 md:px-10">
+	{#each bottomInfo as item}
+		<div>
+			<div class="mb-2 text-lg font-bold">{isZh ? item.title : item.title_en}</div>
+			<div class="flex flex-col gap-1">
+				{#each item.list as i}
+					<a href={i.link} target={i._blank ? '_blank' : '_self'} title={i.link} class="text-sm">{isZh ? i.title : i.title_en}</a>
+				{/each}
+			</div>
+		</div>
+	{/each}
+</div>
+
+<div class="border-t border-black/10 bg-white py-4 text-center text-xs dark:border-white/10 dark:bg-black">
+	<div class="mb-3 text-sm" title={isZh ? '如果页面卡顿,请关闭 3D 模型。' : 'If the page is stuck, please turn off the 3D model.'}>
+		<button class="cursor-pointer text-primary dark:text-dark" onclick={change3DFunc}>
+			{show3D ? (isZh ? '隐藏' : 'Hidden') : isZh ? '显示' : 'Show'}
+			3D LOGO
+		</button>
+	</div>
+	<div class="flex justify-center gap-1">
+		<div>STDF DESIGN • MADE BY DUFU</div>
+		<div>
+			{#if isZh}
+				• <a href="https://beian.miit.gov.cn" target="_blank">滇 ICP 备 17004037 号 -4</a>
+			{/if}
+		</div>
+	</div>
+</div>
+
+<style>
+	@keyframes spin-line {
+		to {
+			transform: rotate(360deg);
+		}
+	}
+	.animate-spin-line {
+		animation: spin-line 6s linear infinite;
+		background: conic-gradient(transparent 50deg, rgba(var(--theme-color-primary), 0.4) 80deg, transparent 90deg);
+	}
+	.animate-spin-line-dark {
+		animation: spin-line 6s linear infinite;
+		background: conic-gradient(transparent 50deg, rgba(var(--theme-color-dark), 0.6) 80deg, transparent 90deg);
+	}
+</style>

+ 337 - 0
docs/site/src/routes/components/+page.svelte

@@ -0,0 +1,337 @@
+<script lang="ts">
+	import { onMount } from 'svelte';
+	import { fly } from 'svelte/transition';
+	import { isShowNavStore, isCmdKStore } from '../../store';
+	import { menuList, type MenuList } from '../../data/menuList';
+	import { page } from '$app/stores';
+	import hljs from 'highlight.js';
+	import type { MenuListChild } from '../../data/menuList.js';
+	import Menu from '$lib/menu/Menu.svelte';
+	import Tab from '$lib/tab/Tab.svelte';
+	import { goto } from '$app/navigation';
+
+	import Component from './Component.svelte';
+	import Guide from './Guide.svelte';
+	import Api from './Api.svelte';
+	import FAQ from './FAQ.svelte';
+	import Version from './Version.svelte';
+
+	let loading = $state(true);
+
+	const isZh = localStorage.getItem('lang') === 'zh_CN';
+
+	const params = $page.url.searchParams;
+
+	//数组二级组成新数组
+	const ArrChildFun = (arr: MenuList[]) => {
+		let newArr = [];
+		for (let e = 0; e < arr.length; e++) {
+			newArr.push(...arr[e].childs);
+		}
+		return newArr;
+	};
+	let menuChildList = $derived(ArrChildFun(menuList));
+	let currentNav = $state<MenuListChild | null>(null);
+	let currentTab = $state(0);
+	let titleDom: HTMLElement | null = $state(null);
+	let demoHeight = $state(0);
+	let highlightedCode = $state('');
+	let titleWidth = $state(0);
+	let visible = $state(true);
+	let isShowIframe = $state(true);
+	let navBarHeight = $state(0);
+	let menuChange = $state(true);
+
+	// 动态导入组件字符串
+	const getComponentStrFunc = async (name: string) => {
+		const rawObj = await import(`../../../../../packages/stdf/src/routes/${name}/${isZh ? 'zh_CN' : 'en_US'}/+page.svelte?raw`);
+		// 将 componentStr 中所有的 from '$lib/index.js' 替换为 from 'stdf'
+		// 将 componentStr 中所有的 from '$lib/types/index.js' 替换为 from 'stdf/types'
+		return rawObj.default
+			.replace(/from ['"]\$lib\/index\.js['"]/g, "from 'stdf'")
+			.replace(/from ['"]\$lib\/types\/index\.js['"]/g, "from 'stdf/types'");
+	};
+	const getDemoHeightFun = () => {
+		if (titleDom) {
+			demoHeight = document.documentElement.clientHeight - 70 - titleDom.offsetHeight - 100;
+			navBarHeight = document.documentElement.clientHeight - 56;
+		}
+	};
+	const initFn = async () => {
+		if (params.get('tab')) {
+			currentTab = Number(params.get('tab'));
+		}
+		if (params.get('nav')) {
+			currentNav = menuChildList.filter((item) => item.nav === params.get('nav'))[0];
+		} else {
+			currentNav = menuList[0].childs[1];
+		}
+		loading = true;
+
+		const componentStr = await getComponentStrFunc(currentNav.nav);
+		loading = false;
+		highlightedCode = hljs.highlight(componentStr, {
+			language: 'svelte',
+			ignoreIllegals: true
+		}).value;
+	};
+	onMount(() => {
+		if (titleDom) {
+			demoHeight = document.documentElement.clientHeight - 70 - titleDom.offsetHeight - 100;
+			navBarHeight = document.documentElement.clientHeight - 56;
+		}
+		window.addEventListener('resize', getDemoHeightFun);
+		initFn();
+		return () => {
+			window.removeEventListener('resize', getDemoHeightFun);
+		};
+	});
+
+	//监听箭头按键,方便键盘操作
+	const handleKeydown = (event: KeyboardEvent) => {
+		if ($isCmdKStore) {
+			return;
+		}
+		//左右箭头切换Tab
+		if (event.code === 'ArrowLeft') {
+			if (currentTab > 0) {
+				isShowIframe = false;
+				setTimeout(() => {
+					isShowIframe = true;
+				}, 100);
+				currentTab--;
+				params.set('tab', currentTab.toString());
+				goto(`/components?nav=${params.get('nav') ? params.get('nav') : 'button'}&tab=${currentTab}`);
+			}
+		}
+		if (event.code === 'ArrowRight') {
+			if (currentTab < 4) {
+				isShowIframe = false;
+				setTimeout(() => {
+					isShowIframe = true;
+				}, 100);
+				currentTab++;
+				params.set('tab', currentTab.toString());
+				goto(`/components?nav=${params.get('nav') ? params.get('nav') : 'button'}&tab=${currentTab}`);
+			}
+		}
+		//上下箭头切换组件
+		if (event.code === 'ArrowUp') {
+			let currentMenuIndex = menuChildList.findIndex((item) => item.nav === currentNav?.nav);
+			if (currentMenuIndex > 0) {
+				visible = false;
+				menuChange = false;
+				setTimeout(async () => {
+					visible = true;
+					currentNav = menuChildList[currentMenuIndex - 1];
+					params.set('nav', currentNav.nav);
+					goto(`/components?nav=${currentNav.nav}&tab=${currentTab}`);
+					const componentStr = await getComponentStrFunc(currentNav.nav);
+					highlightedCode = hljs.highlight(componentStr, {
+						language: 'svelte',
+						ignoreIllegals: true
+					}).value;
+					menuChange = true;
+				}, 10);
+			}
+		}
+		if (event.code === 'ArrowDown') {
+			let currentMenuIndex = menuChildList.findIndex((item) => item.nav === currentNav?.nav);
+			if (currentMenuIndex < menuChildList.length - 1) {
+				visible = false;
+				setTimeout(async () => {
+					visible = true;
+					menuChange = false;
+					currentNav = menuChildList[currentMenuIndex + 1];
+					params.set('nav', currentNav.nav);
+					goto(`/components?nav=${currentNav.nav}&tab=${currentTab}`);
+					const componentStr = await getComponentStrFunc(currentNav.nav);
+					highlightedCode = hljs.highlight(componentStr, {
+						language: 'svelte',
+						ignoreIllegals: true
+					}).value;
+					menuChange = true;
+				}, 10);
+			}
+		}
+	};
+	const menuClickFun = (currentMenu: MenuListChild) => {
+		$isShowNavStore && ($isShowNavStore = false);
+		visible = false;
+		menuChange = false;
+		setTimeout(async () => {
+			visible = true;
+			currentNav = currentMenu;
+			params.set('nav', currentMenu.nav);
+			goto(`/components?nav=${currentMenu.nav}&tab=${params.get('tab') ? params.get('tab') : '0'}`);
+			const componentStr = await getComponentStrFunc(currentMenu.nav);
+			highlightedCode = hljs.highlight(componentStr, {
+				language: 'svelte',
+				ignoreIllegals: true
+			}).value;
+			menuChange = true;
+		}, 10);
+	};
+
+	const tabClickFun = (i: number) => {
+		isShowIframe = false;
+		setTimeout(() => {
+			isShowIframe = true;
+		}, 10);
+		currentTab = i;
+		params.set('tab', currentTab.toString());
+		goto(`/components?nav=${params.get('nav') ? params.get('nav') : 'button'}&tab=${currentTab}`);
+	};
+	// main -> next
+	let QRValue = $derived(
+		(import.meta.env.DEV ? location.protocol + '//' + location.hostname + ':8888/' : 'https://next-demo.stdf.design/') +
+			currentNav?.nav +
+			(isZh ? '/zh_CN' : '/en_US')
+	);
+</script>
+
+<svelte:window onkeydown={handleKeydown} />
+
+<div class="flex">
+	<div
+		class="fixed -left-52 top-14 z-[100] w-52 overflow-y-scroll border-r border-black/10 bg-white transition-all duration-300 dark:border-white/20 dark:bg-black md:left-0 md:bg-transparent dark:md:bg-transparent"
+		class:left-0={$isShowNavStore}
+		class:-left-52={!$isShowNavStore}
+		style="height:{navBarHeight + 'px'}"
+	>
+		<Menu {menuList} currentNav={currentNav?.nav} onclickMenu={menuClickFun} />
+	</div>
+	{#if visible}
+		<div class="flex w-full flex-col md:pl-48" in:fly={{ x: 100, duration: 500 }} out:fly={{ x: 100, duration: 100 }}>
+			<div class="relative z-20 px-4 pt-4 md:flex md:space-x-4 md:px-8" bind:this={titleDom}>
+				{#if loading}
+					{isZh ? '请等待...' : 'Please wait...'}
+				{:else}
+					<div class="flex items-center text-2xl font-bold md:text-4xl">
+						<div>
+							{isZh ? currentNav?.title : currentNav?.title_en}
+						</div>
+						<a href={QRValue} target="_blank" aria-label={isZh ? '扫码预览' : 'Scan to preview'}>
+							<div class="ml-2 h-8 w-8 rounded bg-gray-100 p-1 text-gray-500 dark:bg-gray-700 md:hidden">
+								<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" style="fill: currentColor">
+									<path fill="none" d="M0 0h24v24H0z" />
+									<path
+										d="M13 21v2h-2v-2H3a1 1 0 0 1-1-1V6h20v14a1 1 0 0 1-1 1h-8zm-9-2h16V8H4v11zm9-9h5v2h-5v-2zm0 4h5v2h-5v-2zm-4-4v3h3a3 3 0 1 1-3-3zM2 3h20v2H2V3z"
+									/>
+								</svg>
+							</div>
+						</a>
+					</div>
+					<div class="mt-4 text-xs text-gray-500 md:text-sm">
+						{isZh ? currentNav?.tip : currentNav?.tip_en}
+					</div>
+				{/if}
+			</div>
+			<div class="relative z-10 -mt-14 p-4 md:px-8 md:py-4" bind:clientWidth={titleWidth}>
+				<Tab {currentTab} onclickTab={tabClickFun} />
+			</div>
+			<div class="my-4 ml-4">
+				<div class="h-px bg-black/10 dark:bg-white/20"></div>
+			</div>
+			<div>
+				<!-- 示例 -->
+				{#if currentTab === 0}
+					<div
+						in:fly={{ y: 100, duration: 500 }}
+						out:fly={{ y: 100, duration: 100 }}
+						class="mt-2 flex flex-1 justify-around py-4 md:pl-8 md:pr-4"
+						style="width:{titleWidth}px;"
+					>
+						<div class="bg-codeLight dark:bg-codeDark grow overflow-y-scroll rounded" style="height:{demoHeight}px;">
+							<Component {highlightedCode} />
+						</div>
+						<div
+							class="ml-2 hidden w-[392px] shrink-0 grow-0 border border-black/10 dark:border-white/10 md:block"
+							style="height:{demoHeight}px"
+						>
+							{#if currentNav?.nav}
+								{#if isShowIframe}
+									<!-- main -> next -->
+									<iframe
+										title="Demo"
+										id="iframe-id"
+										src={import.meta.env.DEV
+											? `http://localhost:8888/${currentNav?.nav}/${isZh ? 'zh_CN' : 'en_US'}?channel=iframe`
+											: `https://next-demo.stdf.design/${currentNav?.nav}/${isZh ? 'zh_CN' : 'en_US'}?channel=iframe`}
+										height={demoHeight - 2}
+										width="390"
+									></iframe>
+								{:else}
+									<div class="flex flex-col justify-center text-primary dark:text-dark" style="width:390px;height:{demoHeight - 2}px;">
+										<div>
+											<svg class="mx-auto my-1 h-10 w-10 animate-spin" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
+												<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" />
+												<path
+													class="opacity-75"
+													fill="currentColor"
+													d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
+												/>
+											</svg>
+										</div>
+									</div>
+								{/if}
+							{/if}
+						</div>
+					</div>
+				{/if}
+				{#if currentTab === 1}
+					<!-- api -->
+					{#if menuChange}
+						<div
+							in:fly={{ y: 100, duration: 500 }}
+							out:fly={{ y: 100, duration: 100 }}
+							class={` left-full mt-4 flex-1 p-4 md:px-8 md:py-4`}
+							style="width:{titleWidth}px;"
+						>
+							<Api api={currentNav?.nav} />
+						</div>
+					{/if}
+				{/if}
+				{#if currentTab === 2}
+					<!-- 指南 -->
+					{#if menuChange}
+						<div
+							in:fly={{ y: 100, duration: 500 }}
+							out:fly={{ y: 100, duration: 100 }}
+							class={`mt-4 flex-1 rounded p-4 md:px-8 md:py-4 `}
+							style="width:{titleWidth}px;"
+						>
+							<Guide guide={currentNav?.nav} />
+						</div>
+					{/if}
+				{/if}
+				{#if currentTab === 3}
+					<!-- FAQ -->
+					{#if menuChange}
+						<div
+							in:fly={{ y: 100, duration: 500 }}
+							out:fly={{ y: 100, duration: 100 }}
+							class={`mt-4 flex-1 rounded p-4 md:px-8 md:py-4 `}
+							style="width:{titleWidth}px;"
+						>
+							<FAQ guide={currentNav?.nav} />
+						</div>
+					{/if}
+				{/if}
+				{#if currentTab === 4}
+					<!-- Version -->
+					{#if menuChange}
+						<div
+							in:fly={{ y: 100, duration: 500 }}
+							out:fly={{ y: 100, duration: 100 }}
+							class={`mt-4 flex-1 rounded p-4 md:px-8 md:py-4 `}
+							style="width:{titleWidth}px;"
+						>
+							<Version guide={currentNav?.nav} />
+						</div>
+					{/if}
+				{/if}
+			</div>
+		</div>
+	{/if}
+</div>

+ 14 - 12
docs/site/src/pages/components/Api.svelte → docs/site/src/routes/components/Api.svelte

@@ -1,28 +1,30 @@
-<script>
-	// @ts-nocheck
-
+<script lang="ts">
+	import { onMount } from 'svelte';
 	import { mdTextToHljs } from './../../utils/index';
 
-	export let api = 'button';
+	interface Props {
+		api?: string;
+	}
+
+	let { api = 'button' }: Props = $props();
 	const isZh = localStorage.getItem('lang') === 'zh_CN';
 
-	let loading = true;
-	const getMdStrFunc = async (nav) => {
+	let loading = $state(true);
+	const getMdStrFunc = async (nav: string) => {
 		loading = true;
-		// const rawObj = await import(`../../../../doc/components/${nav}/api${isZh ? '' : '_en'}.md`);
 		const rawObj = await import(`../../../../mds/components/${nav}/api${isZh ? '' : '_en'}.md`);
 		const mdStr = rawObj.default;
 		loading = false;
 		return mdTextToHljs(mdStr.replace(/<a href="/g, '<a target="_blank" href="'));
 	};
-	$: apiText = getMdStrFunc(api).then((res) => {
-		// @ts-ignore
-		apiText = res;
+	let apiText: string | null = $state(null);
+	onMount(async () => {
+		apiText = await getMdStrFunc(api);
 	});
 </script>
 
 <article
-	class="prose dark:prose-invert prose-table:break-all prose-td:whitespace-nowrap md:prose-td:whitespace-normal max-w-none overflow-x-auto pb-12"
+	class="prose max-w-none overflow-x-auto pb-12 dark:prose-invert prose-table:break-all prose-td:whitespace-nowrap md:prose-td:whitespace-normal"
 >
 	{#if loading}
 		{isZh ? '请等待...' : 'Please wait...'}
@@ -35,7 +37,7 @@
 	<a
 		href={'https://github.com/any-tdf/stdf/edit/next/docs/mds/components/' + api + '/api' + (isZh ? '' : '_en') + '.md'}
 		target="_blank"
-		class="text-primary dark:text-dark flex"
+		class="flex text-primary dark:text-dark"
 	>
 		<span class="mr-1 h-4 w-4">
 			<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="h-4 w-4" style="fill: currentColor;">

+ 7 - 0
docs/site/src/routes/components/Component.svelte

@@ -0,0 +1,7 @@
+<script lang="ts">
+	let { highlightedCode = '' } = $props();
+</script>
+
+<article class={`prose max-w-none text-sm dark:prose-invert`}>
+	<pre><code class="hljs">{@html highlightedCode}</code></pre>
+</article>

+ 14 - 10
docs/site/src/pages/components/FAQ.svelte → docs/site/src/routes/components/FAQ.svelte

@@ -1,22 +1,26 @@
-<script>
-	// @ts-nocheck
+<script lang="ts">
+	import { onMount } from 'svelte';
 
 	import { mdTextToHljs } from '../../utils/index';
 
-	export let guide = 'button';
+	interface Props {
+		guide?: string;
+	}
+
+	let { guide = 'button' }: Props = $props();
 	const isZh = localStorage.getItem('lang') === 'zh_CN';
 
-	let loading = true;
-	const getMdStrFunc = async (nav) => {
+	let loading = $state(true);
+	const getMdStrFunc = async (nav: string) => {
 		loading = true;
 		const rawObj = await import(`../../../../mds/components/${nav}/FAQ${isZh ? '' : '_en'}.md`);
 		const mdStr = rawObj.default;
 		loading = false;
 		return mdTextToHljs(mdStr.replace(/<a href="/g, '<a target="_blank" href="'));
 	};
-	$: guideText = getMdStrFunc(guide).then((res) => {
-		// @ts-ignore
-		guideText = res;
+	let guideText: string | null = $state(null);
+	onMount(async () => {
+		guideText = await getMdStrFunc(guide);
 	});
 </script>
 
@@ -26,7 +30,7 @@
 		: 'Note: Please raise any issues or ideas encountered in development to GitHub Issue, and then select representative issues to organize here.'}
 </p>
 <article
-	class="prose dark:prose-invert prose-table:break-all prose-td:whitespace-nowrap md:prose-td:whitespace-normal max-w-none overflow-x-auto pb-12"
+	class="prose max-w-none overflow-x-auto pb-12 dark:prose-invert prose-table:break-all prose-td:whitespace-nowrap md:prose-td:whitespace-normal"
 >
 	{#if loading}
 		{isZh ? '请等待...' : 'Please wait...'}
@@ -39,7 +43,7 @@
 	<a
 		href={'https://github.com/any-tdf/stdf/edit/next/docs/mds/components/' + guide + '/FAQ' + (isZh ? '' : '_en') + '.md'}
 		target="_blank"
-		class="text-primary dark:text-dark flex"
+		class="flex text-primary dark:text-dark"
 	>
 		<span class="mr-1 h-4 w-4">
 			<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="h-4 w-4" style="fill: currentColor;">

+ 17 - 13
docs/site/src/pages/components/Guide.svelte → docs/site/src/routes/components/Guide.svelte

@@ -1,15 +1,18 @@
-<script>
-	// @ts-nocheck
-
+<script lang="ts">
+	import { onMount } from 'svelte';
 	import { mdTextToHljs } from './../../utils/index';
 	import { themeStore, sysThemeStore, isWideScreenStore } from '../../store';
 
-	export let guide = 'button';
+	interface Props {
+		guide?: string;
+	}
+
+	let { guide = 'button' }: Props = $props();
 
 	const isZh = localStorage.getItem('lang') === 'zh_CN';
-	let loading = true;
-	$: theme = $themeStore === 'auto' ? ($sysThemeStore === 'dark' ? 'dark' : 'light') : $themeStore;
-	const getMdStrFunc = async (nav) => {
+	let loading = $state(true);
+	let theme = $derived($themeStore === 'auto' ? ($sysThemeStore === 'dark' ? 'dark' : 'light') : $themeStore);
+	const getMdStrFunc = async (nav: string) => {
 		loading = true;
 		const rawObj = await import(`../../../../mds/components/${nav}/guide${isZh ? '' : '_en'}.md`);
 		const mdStr = rawObj.default;
@@ -20,8 +23,9 @@
 				.replace(/<a href="/g, '<a target="_blank" href="')
 		);
 	};
-	$: guideText = getMdStrFunc(guide).then((res) => {
-		guideText = res;
+	let guideText: string | null = $state(null);
+	onMount(async () => {
+		guideText = await getMdStrFunc(guide);
 	});
 
 	// 全屏
@@ -37,7 +41,7 @@
 </script>
 
 <article
-	class="prose prose-strong:text-primary dark:prose-strong:text-dark dark:prose-invert pb-12 {$isWideScreenStore
+	class="prose pb-12 dark:prose-invert prose-strong:text-primary dark:prose-strong:text-dark {$isWideScreenStore
 		? 'max-w-full'
 		: 'max-w-5xl'}"
 >
@@ -53,7 +57,7 @@
 	<a
 		href={'https://github.com/any-tdf/stdf/edit/next/docs/mds/components/' + guide + '/guide' + (isZh ? '' : '_en') + '.md'}
 		target="_blank"
-		class="text-primary dark:text-dark flex"
+		class="flex text-primary dark:text-dark"
 	>
 		<span class="mr-1 h-4 w-4">
 			<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="h-4 w-4" style="fill: currentColor;">
@@ -67,8 +71,8 @@
 </div>
 
 <button
-	class="bg-primary dark:bg-dark shadow-primary/50 dark:shadow-dark/50 fixed bottom-4 right-2 z-50 hidden h-8 w-8 rounded-full p-1.5 text-white shadow-md md:block dark:text-black"
-	on:click={changeFullFunc}
+	class="fixed bottom-4 right-2 z-50 hidden h-8 w-8 rounded-full bg-primary p-1.5 text-white shadow-md shadow-primary/50 dark:bg-dark dark:text-black dark:shadow-dark/50 md:block"
+	onclick={changeFullFunc}
 >
 	{#if $isWideScreenStore}
 		<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"

+ 20 - 16
docs/site/src/pages/components/Version.svelte → docs/site/src/routes/components/Version.svelte

@@ -1,30 +1,33 @@
-<script>
-	// @ts-nocheck
-
+<script lang="ts">
+	import { onMount } from 'svelte';
 	import { mdTextToHljs } from '../../utils/index';
 
-	export let guide = 'button';
+	interface Props {
+		guide?: string;
+	}
+
+	let { guide = 'button' }: Props = $props();
 	const isZh = localStorage.getItem('lang') === 'zh_CN';
 
-	let loading = true;
+	let loading = $state(true);
 
 	//提取字符中以‘[!tag’开头且以‘]’结尾的所有字符串,组成数组,并返回数组
-	const getTags = (str) => {
+	const getTags = (str: string) => {
 		return str.match(/\[!tag[^\]]+\]/g);
 	};
 
 	//提取字符中以‘[!issue‘开头且以‘]’结尾的所有字符串,组成数组,并返回数组
-	const getIssues = (str) => {
+	const getIssues = (str: string) => {
 		return str.match(/\[!issue[^\]]+\]/g);
 	};
 
 	//提取字符中以‘[!contribute‘开头且以‘]’结尾的所有字符串,组成数组,并返回数组
-	const getContributes = (str) => {
+	const getContributes = (str: string) => {
 		return str.match(/\[!contribute[^\]]+\]/g);
 	};
 
 	// 传入 tag 类型和 index,返回对应的 emoji
-	const spanTextFun = (type, index) => {
+	const spanTextFun = (type: string, index: string) => {
 		if (type === 'O') {
 			return '👏';
 		}
@@ -43,7 +46,7 @@
 		}
 	};
 	//替换Markdown中的标签
-	const mdTextToHljsFun = (string) => {
+	const mdTextToHljsFun = (string: string) => {
 		//替换tag
 		const tagList = getTags(string);
 		if (tagList) {
@@ -83,16 +86,17 @@
 		return string;
 	};
 
-	const getMdStrFunc = async (nav) => {
+	const getMdStrFunc = async (nav: string) => {
 		loading = true;
 		const rawObj = await import(`../../../../mds/components/${nav}/version${isZh ? '' : '_en'}.md`);
 		const mdStr = rawObj.default;
 		loading = false;
 		return mdTextToHljs(mdStr.replace(/<a href="/g, '<a target="_blank" href="'));
 	};
-	$: guideText = getMdStrFunc(guide).then((res) => {
-		// @ts-ignore
-		guideText = mdTextToHljsFun(res);
+	let guideText: string | null = $state(null);
+	onMount(async () => {
+		const guideTextStr = await getMdStrFunc(guide);
+		guideText = mdTextToHljsFun(guideTextStr);
 	});
 </script>
 
@@ -102,7 +106,7 @@
 		: 'Note: 👊, ✊, and 👎 represent three levels of severity for bugs, with 👊 being the most severe and 👎 the least severe. 👏 means optimization, and 💪 means new feature. The avatar after the description represents the proposer or contributor of the item. We thank them for their contributions. '}
 </div>
 <article
-	class="prose dark:prose-invert prose-table:break-all prose-td:whitespace-nowrap md:prose-td:whitespace-normal max-w-none overflow-x-auto pb-12"
+	class="prose max-w-none overflow-x-auto pb-12 dark:prose-invert prose-table:break-all prose-td:whitespace-nowrap md:prose-td:whitespace-normal"
 >
 	{#if loading}
 		{isZh ? '请等待...' : 'Please wait...'}
@@ -114,7 +118,7 @@
 	<!-- main -> next -->
 	<a
 		href={'https://github.com/any-tdf/stdf/edit/next/docs/mds/components/' + guide + '/version' + (isZh ? '' : '_en') + '.md'}
-		class="text-primary dark:text-dark flex"
+		class="flex text-primary dark:text-dark"
 		target="_blank"
 	>
 		<span class="mr-1 h-4 w-4">

+ 210 - 0
docs/site/src/routes/guide/+layout.svelte

@@ -0,0 +1,210 @@
+<script lang="ts">
+	import { onMount } from 'svelte';
+	import { isShowNavStore, isWideScreenStore } from '../../store';
+	import Menu from '$lib/menu/Menu.svelte';
+	import { page } from '$app/stores';
+	import type { MenuListChild } from '../../data/menuList.js';
+	import { goto } from '$app/navigation';
+
+	let { children } = $props();
+
+	const isZh = localStorage.getItem('lang') === 'zh_CN';
+
+	type menuListChildsProps = { title: string; title_en: string; nav: string; doc?: string };
+	type menuListProps = { class: string; class_en: string; childs: menuListChildsProps[] };
+	const menuList: menuListProps[] = [
+		{
+			class: '常规',
+			class_en: 'General',
+			childs: [
+				{ title: '快速上手', title_en: 'Quick start', nav: 'quick-start', doc: 'quickStart' },
+				{ title: '主题配置', title_en: 'Theme', nav: 'theme', doc: 'theme' },
+				{ title: '图标', title_en: 'Icon', nav: 'icon', doc: 'icon' },
+				{
+					title: '国际化',
+					title_en: 'Internationalization',
+					nav: 'internation',
+					doc: 'internation'
+				},
+				{ title: '更新日志', title_en: 'Changelog', nav: 'changelog', doc: 'changelog' },
+				{ title: '常见问题', title_en: 'FAQ', nav: 'faq', doc: 'faq' },
+				{
+					title: '贡献指南',
+					title_en: 'Contribution Guide',
+					nav: 'contribution',
+					doc: 'contribution'
+				},
+				{ title: '兼容性', title_en: 'Compatibility', nav: 'compatibility', doc: 'compatibility' }
+			]
+		},
+		{
+			class: '设计',
+			class_en: 'Design',
+			childs: [
+				{ title: '色彩', title_en: 'Color', nav: 'color' },
+				{ title: 'LOGO', title_en: 'LOGO', nav: 'logo' }
+			]
+		},
+		{
+			class: '工具',
+			class_en: 'Tools',
+			childs: [
+				{ title: '主题生成器', title_en: 'Theme generator', nav: 'generator' },
+				{ title: 'IDE 插件', title_en: 'IDE plugin', nav: 'vscode', doc: 'vscode' },
+				{ title: '脚手架', title_en: 'Create cli', nav: 'create' },
+				{ title: '图标插件', title_en: 'Icon plugin', nav: 'icon-plugin' },
+				{ title: '快捷键', title_en: 'Shortcut key', nav: 'shortkey' }
+			]
+		},
+		{
+			class: '其他',
+			class_en: 'Other',
+			childs: [
+				{ title: '关于', title_en: 'About', nav: 'about', doc: 'about' },
+				{ title: '里程碑', title_en: 'Milestone', nav: 'milestone', doc: 'milestone' },
+				{ title: '计划', title_en: 'Future', nav: 'future', doc: 'future' }
+			]
+		}
+	];
+	//扁平 menuList
+	const flatMenuList: menuListChildsProps[] = [];
+	for (let e = 0; e < menuList.length; e++) {
+		flatMenuList.push(...menuList[e].childs);
+	}
+	let currentNav = $state(menuList[0].childs[0]);
+	let menuHeight = $state(0);
+	const getMenuHeightFun = () => {
+		menuHeight = document.documentElement.clientHeight - 56;
+	};
+	const menuClickFun = (currentMenu: MenuListChild) => {
+		if ($isShowNavStore) {
+			isShowNavStore.set(false);
+		}
+		currentNav = currentMenu;
+		// 将当前点击的 currentMenu 设置 url 参数
+		// window.location.href = '/guide?nav=' + currentMenu.nav;
+		goto(`/guide${currentMenu.nav === 'quick-start' ? '' : `/${currentMenu.nav}`}`);
+	};
+
+	onMount(() => {
+		menuHeight = document.documentElement.clientHeight - 56;
+		window.addEventListener('resize', getMenuHeightFun);
+
+		// 根据 $page.url.pathname 获取 currentNav
+		const urlNav = flatMenuList.find((item) => ($page.url.pathname.includes(item.nav) ? item : null));
+		currentNav = urlNav || flatMenuList[0];
+
+		return () => {
+			window.removeEventListener('resize', getMenuHeightFun);
+		};
+	});
+	// 全屏
+	const changeFullFunc = () => {
+		if ($isWideScreenStore) {
+			isWideScreenStore.set(false);
+			localStorage.setItem('isFull', 'notFull');
+		} else {
+			isWideScreenStore.set(true);
+			localStorage.setItem('isFull', 'full');
+		}
+	};
+	// 编辑地址处理
+	const editUrlFn = (nav: string) => {
+		// main -> next
+		const baseUrl = 'https://github.com/any-tdf/stdf/edit/next/';
+		if (nav === 'create') {
+			return baseUrl + 'packages/create-stdf/README' + (isZh ? '_CN' : '') + '.md';
+		}
+		if (nav === 'icon-plugin') {
+			return baseUrl + 'packages/rollup-plugin-stdf-icon/README' + (isZh ? '_CN' : '') + '.md';
+		}
+		return baseUrl + `docs/mds/guide/${flatMenuList.filter((item) => item.nav === nav)[0]?.doc}${isZh ? '' : '_en'}.md`;
+	};
+</script>
+
+<div class="flex">
+	<div
+		class="fixed -left-52 top-14 z-[100] w-48 overflow-y-scroll border-r border-black/10 bg-white transition-all duration-300 dark:border-white/20 dark:bg-black md:left-0 md:bg-transparent dark:md:bg-transparent"
+		class:left-0={$isShowNavStore}
+		class:-left-52={!$isShowNavStore}
+		style="height:{menuHeight + 'px'}"
+	>
+		<Menu {menuList} currentNav={currentNav.nav} onclickMenu={menuClickFun} showNum={false} />
+	</div>
+	<div class="w-screen md:pl-48">
+		{#if !$page.url.pathname.includes('generator')}
+			<div class="px-4 py-12 md:px-8 md:py-4">
+				<div class="text-4xl font-bold">
+					{isZh ? currentNav.title : currentNav.title_en}
+				</div>
+			</div>
+			<div class="h-px bg-black/10 dark:bg-white/20"></div>
+		{/if}
+		<div class="px-4 pt-4 {$page.url.pathname.includes('generator') ? 'md:px-4 md:pt-4' : 'md:px-8 md:pt-12'}">
+			{@render children()}
+		</div>
+		{#if !$page.url.pathname.includes('generator') && currentNav.nav != 'color' && currentNav.nav != 'logo' && currentNav.nav != 'shortkey'}
+			<div class="flex gap-2 px-4 pb-8 text-xs md:px-8">
+				<a href={editUrlFn(currentNav.nav)} class="flex w-full text-primary dark:text-dark" target="_blank">
+					<span class="mr-1 h-4 w-4">
+						<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="h-4 w-4" style="fill: currentColor;">
+							<path
+								d="M12.8995 6.85431L17.1421 11.0969L7.24264 20.9964H3V16.7538L12.8995 6.85431ZM14.3137 5.44009L16.435 3.31877C16.8256 2.92825 17.4587 2.92825 17.8492 3.31877L20.6777 6.1472C21.0682 6.53772 21.0682 7.17089 20.6777 7.56141L18.5563 9.68273L14.3137 5.44009Z"
+							/>
+						</svg>
+					</span>
+					{isZh ? '在 GitHub 上编辑' : 'Edit on GitHub'}
+				</a>
+			</div>
+		{/if}
+	</div>
+</div>
+{#if !$page.url.pathname.includes('generator')}
+	<button
+		class="fixed bottom-4 right-2 z-50 hidden h-8 w-8 rounded-full bg-primary p-1.5 text-white shadow-md shadow-primary/50 dark:bg-dark dark:text-black dark:shadow-dark/50 md:block"
+		onclick={changeFullFunc}
+	>
+		{#if $isWideScreenStore}
+			<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
+				><path
+					d="M20 3C20.5523 3 21 3.44772 21 4V20C21 20.5523 20.5523 21 20 21H4C3.44772 21 3 20.5523 3 20V4C3 3.44772 3.44772 3 4 3H20ZM11 5H5V19H11V15H13V19H19V5H13V9H11V5ZM15 9L18 12L15 15V13H9V15L6 12L9 9V11H15V9Z"
+					fill="currentColor"
+				></path></svg
+			>
+		{:else}
+			<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
+				><path
+					d="M20 3C20.5523 3 21 3.44772 21 4V20C21 20.5523 20.5523 21 20 21H4C3.44772 21 3 20.5523 3 20V4C3 3.44772 3.44772 3 4 3H20ZM11 5H5V10.999H7V9L10 12L7 15V13H5V19H11V17H13V19H19V13H17V15L14 12L17 9V10.999H19V5H13V7H11V5ZM13 13V15H11V13H13ZM13 9V11H11V9H13Z"
+					fill="currentColor"
+				></path></svg
+			>
+		{/if}
+	</button>
+{/if}
+<!-- 为 code-groups 预先编译 tailwind -->
+<div
+	class="hidden border-b-2 border-black/10 peer-checked/tab-0-0:block peer-checked/tab-0-1:block peer-checked/tab-0-2:block
+peer-checked/tab-0-3:block peer-checked/tab-0-4:block peer-checked/tab-0-5:block
+peer-checked/tab-1-0:block peer-checked/tab-1-1:block peer-checked/tab-1-2:block
+peer-checked/tab-1-3:block peer-checked/tab-1-4:block peer-checked/tab-1-5:block
+peer-checked/tab-2-0:block peer-checked/tab-2-1:block peer-checked/tab-2-2:block
+peer-checked/tab-2-3:block peer-checked/tab-2-4:block peer-checked/tab-2-5:block
+peer-checked/tab-3-0:block peer-checked/tab-3-1:block peer-checked/tab-3-2:block
+peer-checked/tab-3-3:block peer-checked/tab-3-4:block peer-checked/tab-3-5:block
+peer-checked/tab-0-0:border-primary peer-checked/tab-0-1:border-primary peer-checked/tab-0-2:border-primary
+peer-checked/tab-0-3:border-primary peer-checked/tab-0-4:border-primary peer-checked/tab-0-5:border-primary
+peer-checked/tab-1-0:border-primary peer-checked/tab-1-1:border-primary peer-checked/tab-1-2:border-primary
+peer-checked/tab-1-3:border-primary peer-checked/tab-1-4:border-primary peer-checked/tab-1-5:border-primary
+peer-checked/tab-2-0:border-primary peer-checked/tab-2-1:border-primary peer-checked/tab-2-2:border-primary
+peer-checked/tab-2-3:border-primary peer-checked/tab-2-4:border-primary peer-checked/tab-2-5:border-primary
+peer-checked/tab-3-0:border-primary peer-checked/tab-3-1:border-primary peer-checked/tab-3-2:border-primary
+peer-checked/tab-3-3:border-primary peer-checked/tab-3-4:border-primary peer-checked/tab-3-5:border-primary dark:border-white/10
+dark:bg-[#202020] dark:peer-checked/tab-0-0:border-dark dark:peer-checked/tab-0-1:border-dark
+dark:peer-checked/tab-0-2:border-dark dark:peer-checked/tab-0-3:border-dark dark:peer-checked/tab-0-4:border-dark
+dark:peer-checked/tab-0-5:border-dark dark:peer-checked/tab-1-0:border-dark dark:peer-checked/tab-1-1:border-dark
+dark:peer-checked/tab-1-2:border-dark dark:peer-checked/tab-1-3:border-dark dark:peer-checked/tab-1-4:border-dark
+dark:peer-checked/tab-1-5:border-dark dark:peer-checked/tab-2-0:border-dark dark:peer-checked/tab-2-1:border-dark
+dark:peer-checked/tab-2-2:border-dark dark:peer-checked/tab-2-3:border-dark dark:peer-checked/tab-2-4:border-dark
+dark:peer-checked/tab-2-5:border-dark dark:peer-checked/tab-3-0:border-dark dark:peer-checked/tab-3-1:border-dark
+dark:peer-checked/tab-3-2:border-dark dark:peer-checked/tab-3-3:border-dark dark:peer-checked/tab-3-4:border-dark dark:peer-checked/tab-3-5:border-dark"
+></div>

+ 4 - 5
docs/site/src/pages/guide/QuickStart.svelte → docs/site/src/routes/guide/+page.svelte

@@ -1,22 +1,21 @@
-<script>
+<script lang="ts">
 	import { mdTextToHljs, groupIconMdPlugin } from '../../utils/index';
 	import { isWideScreenStore } from '../../store';
 
-	// @ts-ignore
 	import quickStartText from '../../../../mds/guide/quickStart.md';
-	// @ts-ignore
 	import quickStartText_en from '../../../../mds/guide/quickStart_en.md';
 
 	const isZh = localStorage.getItem('lang') === 'zh_CN';
 	const text = groupIconMdPlugin(
-		mdTextToHljs(isZh ? quickStartText : quickStartText_en).replace(/<a href="/g, '<a target="_blank" href="'),
+		mdTextToHljs(isZh ? quickStartText : quickStartText_en).replace(/<a href="/g, '<a target="_blank" href="')
 	);
 </script>
 
 <article
-	class="prose prose-strong:text-primary dark:prose-strong:text-dark dark:prose-invert pb-12 {$isWideScreenStore
+	class="prose pb-12 dark:prose-invert prose-strong:text-primary dark:prose-strong:text-dark {$isWideScreenStore
 		? 'max-w-full'
 		: 'max-w-5xl'}"
 >
+	<!-- eslint-disable-next-line svelte/no-at-html-tags -->
 	{@html text}
 </article>

+ 21 - 0
docs/site/src/routes/guide/Create.svelte

@@ -0,0 +1,21 @@
+<script>
+	import { mdTextToHljs, groupIconMdPlugin } from '../../utils/index.js';
+	import { isWideScreenStore } from '../../store.js';
+
+	import createText from '../../../../../../packages/create-stdf/README_CN.md';
+	import createText_en from '../../../../../../packages/create-stdf/README.md';
+
+	const isZh = localStorage.getItem('lang') === 'zh_CN';
+	const text = groupIconMdPlugin(
+		(isZh ? mdTextToHljs(createText) : mdTextToHljs(createText_en)).replace(/<a href="/g, '<a target="_blank" href="')
+	);
+</script>
+
+<article
+	class="prose pb-12 dark:prose-invert prose-strong:text-primary dark:prose-strong:text-dark {$isWideScreenStore
+		? 'max-w-full'
+		: 'max-w-5xl'}"
+>
+	<!-- eslint-disable-next-line svelte/no-at-html-tags -->
+	{@html text}
+</article>

+ 20 - 0
docs/site/src/routes/guide/about/+page.svelte

@@ -0,0 +1,20 @@
+<script lang="ts">
+	import { mdTextToHljs } from '../../../utils/index';
+	import { isWideScreenStore } from '../../../store';
+
+	import text from '../../../../../mds/guide/about.md';
+	import text_en from '../../../../../mds/guide/about_en.md';
+
+	const isZh = localStorage.getItem('lang') === 'zh_CN';
+
+	const hljsText = mdTextToHljs((isZh ? text : text_en).replace(/<a href="/g, '<a target="_blank" href="'));
+</script>
+
+<article
+	class="prose pb-12 dark:prose-invert prose-strong:text-primary dark:prose-strong:text-dark {$isWideScreenStore
+		? 'max-w-full'
+		: 'max-w-5xl'}"
+>
+	<!-- eslint-disable-next-line svelte/no-at-html-tags -->
+	{@html hljsText}
+</article>

+ 24 - 42
docs/site/src/pages/guide/Changelog.svelte → docs/site/src/routes/guide/changelog/+page.svelte

@@ -1,57 +1,38 @@
-<script>
-	import { mdTextToHljs } from '../../utils/index';
-	import { isWideScreenStore } from '../../store';
+<script lang="ts">
+	import { mdTextToHljs } from '../../../utils/index';
+	import { isWideScreenStore } from '../../../store';
 
-	// @ts-ignore
-	import text from '../../../../mds/guide/changelog.md';
-	// @ts-ignore
-	import text_en from '../../../../mds/guide/changelog_en.md';
+	import text from '../../../../../mds/guide/changelog.md';
+	import text_en from '../../../../../mds/guide/changelog_en.md';
 
 	const isZh = localStorage.getItem('lang') === 'zh_CN';
 	//提取字符中以‘[!tag’开头且以‘]’结尾的所有字符串,组成数组,并返回数组
-	const getTags = (str) => {
-		return str.match(/\[!tag[^\]]+\]/g);
-	};
-
+	const getTags = (str: string) => str.match(/\[!tag[^\]]+\]/g);
 	//提取字符中以‘[!issue‘开头且以‘]’结尾的所有字符串,组成数组,并返回数组
-	const getIssues = (str) => {
-		return str.match(/\[!issue[^\]]+\]/g);
-	};
+	const getIssues = (str: string) => str.match(/\[!issue[^\]]+\]/g);
 	//提取字符中以‘[!contribute‘开头且以‘]’结尾的所有字符串,组成数组,并返回数组
-	const getContributes = (str) => {
-		return str.match(/\[!contribute[^\]]+\]/g);
-	};
-	const spanTextFun = (type, index) => {
-		if (type === 'O') {
-			return '👏';
-		}
-		if (type === 'A') {
-			return '💪';
-		}
-		switch (index) {
-			case '1':
-				return '👊';
-			case '2':
-				return '✊';
-			case '3':
-				return '👎';
-			default:
-				return '👎';
+	const getContributes = (str: string) => str.match(/\[!contribute[^\]]+\]/g);
+	const spanTextFun = (type: 'A' | 'B' | 'O', index: '1' | '2' | '3') => {
+		const typeMap = { A: '💪', O: '👌' };
+		const indexMap = { '1': '👊', '2': '✊', '3': '👎' };
+		if (type === 'O' || type === 'A') {
+			return typeMap[type];
+		} else {
+			return indexMap[index];
 		}
 	};
-	//替换Markdown中的标签
-	const mdTextToHljsFun = (string) => {
-		//替换tag
+	//替换 Markdown 中的标签
+	const mdTextToHljsFun = (string: string) => {
+		//替换 tag
 		const tagList = getTags(string);
 		if (tagList) {
 			tagList.forEach((item) => {
-				const arr = item.split('|');
-				// const span = `<span class="w-2 h-2 text-xs inline-block rounded-full mr-1 ${bgClassFun(arr[1], arr[2])}"></span>`;
-				const span = `<span class="mr-1">${spanTextFun(arr[1], arr[2])}</span>`;
+				const arr: string[] = item.split('|');
+				const span = `<span class="mr-1">${spanTextFun(arr[1] as 'A' | 'B' | 'O', arr[2] as '1' | '2' | '3')}</span>`;
 				string = string.replace(item, span);
 			});
 		}
-		//替换issue
+		//替换 issue
 		const issueList = getIssues(string);
 		if (issueList) {
 			issueList.forEach((item) => {
@@ -64,7 +45,7 @@
 				string = string.replace(item, span);
 			});
 		}
-		//替换contribute
+		//替换 contribute
 		const contributeList = getContributes(string);
 		if (contributeList) {
 			contributeList.forEach((item) => {
@@ -83,7 +64,7 @@
 </script>
 
 <article
-	class="prose prose-strong:text-primary dark:prose-strong:text-dark dark:prose-invert pb-12 {$isWideScreenStore
+	class="prose pb-12 dark:prose-invert prose-strong:text-primary dark:prose-strong:text-dark {$isWideScreenStore
 		? 'max-w-full'
 		: 'max-w-5xl'}"
 >
@@ -92,5 +73,6 @@
 			? '注:此处仅展示站点更新说明或总体概述,具体组件更新内容请查看组件内部更新日志。描述后面的头像表示此项的提出者或贡献者,感谢他们。发布时间格式均为 GMT+8。'
 			: 'Note: Only the site update instructions or general overview are displayed here. For the specific component update content, please refer to the update log inside the component. The avatars after the description represent the submitter or contributor, thank them for their contribution. The release time format is GMT+8.'}
 	</p>
+	<!-- eslint-disable-next-line svelte/no-at-html-tags -->
 	{@html mdTextToHljsFun(hljsText)}
 </article>

+ 12 - 0
docs/site/src/routes/guide/color/+page.svelte

@@ -0,0 +1,12 @@
+<script lang="ts">
+	import Color from './Color.svelte';
+	import ColorEn from './Color_en.svelte';
+
+	const isZh = localStorage.getItem('lang') === 'zh_CN';
+</script>
+
+{#if isZh}
+	<Color />
+{:else}
+	<ColorEn />
+{/if}

+ 146 - 112
docs/site/src/pages/guide/Color.svelte → docs/site/src/routes/guide/color/Color.svelte

@@ -1,11 +1,13 @@
-<script>
+<script lang="ts">
 	import { onMount, onDestroy } from 'svelte';
-	import ColorCard from '../../components/colorCard/ColorCard.svelte';
-	import ModeSwitch from '../../components/modeSwitch/ModeSwitch.svelte';
-	import ThemeSwitch from '../../components/themeSwitch/ThemeSwitch.svelte';
-	import themes from '../../data/themes';
-	import { currentColorStore, isWideScreenStore } from '../../store';
-	import { generatePalette, generateThemeBlack, generateThemeWhite, colorConvertFunc } from '../../utils';
+	import ColorCard from '$lib/colorCard/ColorCard.svelte';
+	import ModeSwitch from '$lib/modeSwitch/ModeSwitch.svelte';
+	import ThemeSwitch from '$lib/themeSwitch/ThemeSwitch.svelte';
+	import themes from '../../../data/themes';
+	import { currentColorStore, isWideScreenStore } from '../../../store';
+	import { generatePalette, generateThemeBlack, generateThemeWhite, colorConvertFunc } from '../../../utils';
+	import hljs from 'highlight.js';
+	import { type ThemeProps } from 'stdf/theme';
 
 	const colorGrayList = [
 		{ key: 'gray-50', hex: '#f2f2f2' },
@@ -18,47 +20,77 @@
 		{ key: 'gray-700', hex: '#4D4D4D' },
 		{ key: 'gray-800', hex: '#333333' },
 		{ key: 'gray-900', hex: '#1A1A1A' },
-		{ key: 'gray-950', hex: '#0D0D0D' },
+		{ key: 'gray-950', hex: '#0D0D0D' }
 	];
-	// @ts-ignore
 	onMount(() => hljs.highlightAll());
 
-	let currentColorObj = {};
-	let primaryColors = [];
-	let darkColors = [];
-	let themeBlack = {};
-	let themeWhite = {};
-	let stateColor = {};
-	let extendList = [];
+	let currentColorObj: ThemeProps | undefined = undefined;
+	let primaryColors: { n: number; hex: string; rgb: string; hsl: string }[] | undefined = undefined;
+	let darkColors: { n: number; hex: string; rgb: string; hsl: string }[] | undefined = undefined;
+	let themeBlack:
+		| {
+				primary: { hex: string; rgb: string; hsl: string };
+				dark: { hex: string; rgb: string; hsl: string };
+		  }
+		| undefined = undefined;
+	let themeWhite:
+		| {
+				primary: { hex: string; rgb: string; hsl: string };
+				dark: { hex: string; rgb: string; hsl: string };
+		  }
+		| undefined = undefined;
+	let stateColor: { success: string; warning: string; error: string; info: string } | undefined = undefined;
+	let extendList: { color: string; alias: string }[] | undefined = undefined;
 
-	const unsubscribe = currentColorStore.subscribe(value => {
+	const unsubscribe = currentColorStore.subscribe((value) => {
 		// 根据 $currentColorStore 从 themes 中获取对应的颜色对象
-		currentColorObj = themes.find(item => item.name === value).theme;
+		currentColorObj = themes.find((item) => item.name === value)?.theme;
 		// 传入数组,按照 Tailwind 规则生成颜色列表
-		const createTWColorFunc = colorList => {
+		const createTWColorFunc = (colorList: string[]) => {
 			if (colorList.length !== 11) {
 				console.error('颜色列表长度必须为11');
 				return;
 			}
-			const colorArr = [];
+			const colorArr: { n: number; hex: string; rgb: string; hsl: string }[] = [];
 			colorList.forEach((item, index) => {
 				// 第 0 项和最后一项的 key 为 50 和 950 ,其他项为 100-900,颜色有 hex、rgb、hsl 三种格式,注意 hsl 保留整数
-				let colorObj = {};
+				let colorObj: { n: number; hex: string; rgb: string; hsl: string } = {
+					n: 0,
+					hex: '',
+					rgb: '',
+					hsl: ''
+				};
 				if (index === 0) {
-					colorObj = { n: 50, hex: item, rgb: colorConvertFunc(item).rgb, hsl: colorConvertFunc(item).hsl };
+					colorObj = {
+						n: 50,
+						hex: item,
+						rgb: colorConvertFunc(item).rgb,
+						hsl: colorConvertFunc(item).hsl
+					};
 				} else if (index === 10) {
-					colorObj = { n: 950, hex: item, rgb: colorConvertFunc(item).rgb, hsl: colorConvertFunc(item).hsl };
+					colorObj = {
+						n: 950,
+						hex: item,
+						rgb: colorConvertFunc(item).rgb,
+						hsl: colorConvertFunc(item).hsl
+					};
 				} else {
-					colorObj = { n: 100 * index, hex: item, rgb: colorConvertFunc(item).rgb, hsl: colorConvertFunc(item).hsl };
+					colorObj = {
+						n: 100 * index,
+						hex: item,
+						rgb: colorConvertFunc(item).rgb,
+						hsl: colorConvertFunc(item).hsl
+					};
 				}
 				colorArr.push(colorObj);
 			});
 			return colorArr;
 		};
+		if (!currentColorObj) return;
 		const primaryColorList = generatePalette(currentColorObj.color.primary.default);
 		const darkColorList = generatePalette(currentColorObj.color.dark.default);
-		primaryColors = createTWColorFunc(primaryColorList);
-		darkColors = createTWColorFunc(darkColorList);
+		primaryColors = createTWColorFunc(primaryColorList as string[]);
+		darkColors = createTWColorFunc(darkColorList as string[]);
 		// 根据主题色生成主题黑和白
 		const primaryColorB = generateThemeBlack(currentColorObj.color.primary.default);
 		const darkColorB = generateThemeBlack(currentColorObj.color.dark.default);
@@ -92,18 +124,18 @@
 </script>
 
 <article
-	class="prose prose-strong:text-primary dark:prose-strong:text-dark dark:prose-invert pb-12 {$isWideScreenStore
+	class="prose dark:prose-invert prose-strong:text-primary dark:prose-strong:text-dark pb-12 {$isWideScreenStore
 		? 'max-w-full'
 		: 'max-w-5xl'}"
 >
 	<blockquote>
-		切换亮暗模式,选择下列内置主题可查看配色。到<a href="#/guide/generator" target="_blank">主题生成器</a
-		>可快速配置颜色系统并生成配置文件。具体使用方法请参考<a href="#/guide/theme" target="_blank">主题配置</a>。
+		切换亮暗模式,选择下列内置主题可查看配色。到<a href="/guide/generator" target="_blank">主题生成器</a
+		>可快速配置颜色系统并生成配置文件。具体使用方法请参考<a href="/guide/theme" target="_blank">主题配置</a>。
 	</blockquote>
-	<div class="inline-flex gap-4 items-center">
+	<div class="inline-flex items-center gap-4">
 		<ModeSwitch />
 	</div>
-	<div class="flex gap-4 items-center">
+	<div class="flex items-center gap-4">
 		<ThemeSwitch />
 	</div>
 	<h2>概述</h2>
@@ -120,26 +152,26 @@
 	<p>
 		一般情况,会使用区别于主色的另一种颜色适配暗模式,一种做法是不改变色相,只是将主色变浅提亮使其突出显现在暗背景下;另一种做法是完全取另一种色相,STDF
 		推荐使用后者,以便暗模式下的主色更加明显。所以 STDF 内置的主题色分为亮暗模式。当然,如果你需要将亮暗模式都设置为相同色相也是可以的,STDF
-		提供的<a href="#/guide/generator" target="_blank"> 主题生成器 </a>支持随意配置。
+		提供的<a href="/guide/generator" target="_blank"> 主题生成器 </a>支持随意配置。
 	</p>
-	<div class="md:flex justify-between md:space-x-8">
-		<div class="flex-1 h-40 p-4 rounded text-white flex flex-col justify-between" style="background-color: {primaryColors[6].hex};">
+	<div class="justify-between md:flex md:space-x-8">
+		<div class="flex h-40 flex-1 flex-col justify-between rounded p-4 text-white" style="background-color: {primaryColors?.[6]?.hex};">
 			<div class="font-bold">primary(亮模式)</div>
 			<div class="text-sm">
-				<div>{primaryColors[6].hex}</div>
-				<div class="text-xs">{primaryColors[6].rgb}</div>
-				<div class="text-xs">{primaryColors[6].hsl}</div>
+				<div>{primaryColors?.[6]?.hex}</div>
+				<div class="text-xs">{primaryColors?.[6]?.rgb}</div>
+				<div class="text-xs">{primaryColors?.[6]?.hsl}</div>
 			</div>
 		</div>
 		<div
-			class="flex-1 mt-4 md:mt-0 h-40 p-4 rounded text-black flex flex-col justify-between"
-			style="background-color: {darkColors[6].hex};"
+			class="mt-4 flex h-40 flex-1 flex-col justify-between rounded p-4 text-black md:mt-0"
+			style="background-color: {darkColors?.[6]?.hex};"
 		>
 			<div class="font-bold">dark(暗模式)</div>
 			<div class="text-sm">
-				<div>{darkColors[6].hex}</div>
-				<div class="text-xs">{darkColors[6].rgb}</div>
-				<div class="text-xs">{darkColors[6].hsl}</div>
+				<div>{darkColors?.[6]?.hex}</div>
+				<div class="text-xs">{darkColors?.[6]?.rgb}</div>
+				<div class="text-xs">{darkColors?.[6]?.hsl}</div>
 			</div>
 		</div>
 	</div>
@@ -149,16 +181,16 @@
 		>,但这并不能满足自定义的主题色,STDF 参照 Tailwind 的调色板命名规则,使用一套内置算法动态地将主题色计算出 11 种颜色组成梯度色板。其中
 		600 号色作为默认颜色【省略 600 编号】,实际业务中使用淡颜色的场景会多一些,故淡颜色会多一些选择。
 	</p>
-	<div class="md:flex justify-between md:space-x-8 space-y-8 md:space-y-0">
-		<div class="flex-1 flex flex-col justify-between rounded text-sm bg-white">
-			{#each primaryColors as color, index}
+	<div class="justify-between space-y-8 md:flex md:space-x-8 md:space-y-0">
+		<div class="flex flex-1 flex-col justify-between rounded bg-white text-sm">
+			{#each primaryColors ?? [] as color, index}
 				<div
 					class="p-4 transition hover:scale-105 hover:rounded {index >= 5 ? 'text-white' : 'text-black'}"
 					style="background-color: {color.hex};"
 				>
-					<div class="flex justify-between items-center">
+					<div class="flex items-center justify-between">
 						<div class="flex-1 text-left font-bold">primary{index === 6 ? '' : `-${color.n}`}</div>
-						<div class="text-xs text-right">
+						<div class="text-right text-xs">
 							<div>{color.hex}</div>
 							<div>{color.rgb}</div>
 							<div>{color.hsl}</div>
@@ -167,15 +199,15 @@
 				</div>
 			{/each}
 		</div>
-		<div class="flex-1 flex flex-col justify-between rounded text-sm bg-white">
-			{#each darkColors as color, index}
+		<div class="flex flex-1 flex-col justify-between rounded bg-white text-sm">
+			{#each darkColors ?? [] as color, index}
 				<div
 					class="p-4 transition hover:scale-105 hover:rounded {index >= 7 ? 'text-white' : 'text-black'}"
 					style="background-color: {color.hex};"
 				>
-					<div class="flex justify-between items-center">
+					<div class="flex items-center justify-between">
 						<div class="flex-1 text-left font-bold">dark{index === 6 ? '' : `-${color.n}`}</div>
-						<div class="text-xs text-right">
+						<div class="text-right text-xs">
 							<div>{color.hex}</div>
 							<div>{color.rgb}</div>
 							<div>{color.hsl}</div>
@@ -187,28 +219,28 @@
 	</div>
 	<h3>透明度</h3>
 	<p>某些应用场景中,需要使用到主题色的透明度。注意这与上述梯度色板的差异。</p>
-	<div class="md:flex justify-between md:space-x-8 space-y-8 md:space-y-0 transparent-background">
-		<div class="flex-1 rounded flex flex-col justify-between text-black">
+	<div class="transparent-background justify-between space-y-8 md:flex md:space-x-8 md:space-y-0">
+		<div class="flex flex-1 flex-col justify-between rounded text-black">
 			{#each [0.5, 1, 2, 2.5, 3, 4, 5, 6, 7, 7.5, 8, 9, 9.5] as color}
-				<div class="p-4 transition hover:scale-105 hover:rounded" style="background-color: {rgbaFunc(primaryColors[6].rgb, color)};">
-					<div class="flex justify-between items-center text-sm">
-						<div class="bg-white py-1 px-2 rounded">primary/{color * 10}</div>
-						<div class="bg-white py-1 px-2 rounded text-xs text-right">
-							<div>{rgbaFunc(primaryColors[6].rgb, color)}</div>
-							<div>{hslaFunc(primaryColors[6].hsl, color)}</div>
+				<div class="p-4 transition hover:scale-105 hover:rounded" style="background-color: {rgbaFunc(primaryColors?.[6]?.rgb, color)};">
+					<div class="flex items-center justify-between text-sm">
+						<div class="rounded bg-white px-2 py-1">primary/{color * 10}</div>
+						<div class="rounded bg-white px-2 py-1 text-right text-xs">
+							<div>{rgbaFunc(primaryColors?.[6]?.rgb, color)}</div>
+							<div>{hslaFunc(primaryColors?.[6]?.hsl, color)}</div>
 						</div>
 					</div>
 				</div>
 			{/each}
 		</div>
-		<div class="flex-1 rounded flex flex-col justify-between text-black">
+		<div class="flex flex-1 flex-col justify-between rounded text-black">
 			{#each [0.5, 1, 2, 2.5, 3, 4, 5, 6, 7, 7.5, 8, 9, 9.5] as color}
-				<div class="p-4 transition hover:scale-105 hover:rounded" style="background-color: {rgbaFunc(darkColors[6].rgb, color)};">
-					<div class="flex justify-between text-sm items-center">
-						<div class="bg-white py-1 px-2 rounded">dark/{color * 10}</div>
-						<div class="bg-white py-1 px-2 rounded text-xs text-right">
-							<div>{rgbaFunc(darkColors[6].rgb, color)}</div>
-							<div>{hslaFunc(darkColors[6].hsl, color)}</div>
+				<div class="p-4 transition hover:scale-105 hover:rounded" style="background-color: {rgbaFunc(darkColors?.[6]?.rgb, color)};">
+					<div class="flex items-center justify-between text-sm">
+						<div class="rounded bg-white px-2 py-1">dark/{color * 10}</div>
+						<div class="rounded bg-white px-2 py-1 text-right text-xs">
+							<div>{rgbaFunc(darkColors?.[6]?.rgb, color)}</div>
+							<div>{hslaFunc(darkColors?.[6]?.hsl, color)}</div>
 						</div>
 					</div>
 				</div>
@@ -220,19 +252,21 @@
 		通常情况下,设计中应避免大面积使用纯黑色【#000000】,使用接近纯黑的颜色。同时 STDF
 		会根据算法计算出两个接近纯黑但是带有主题色的黑色,方便设计搭配。同样也会计算出两个接近纯白但是带有主题色的白色。一般可用于多套主题搭配时的文字颜色,亮暗背景颜色等场景。
 	</p>
-	<div class="md:flex flex-wrap justify-around md:space-x-4 space-y-4 md:space-y-0">
-		{#each [themeBlack.primary, themeBlack.dark, themeWhite.primary, themeWhite.dark] as item, i}
+	<div class="flex-wrap justify-around space-y-4 md:flex md:space-x-4 md:space-y-0">
+		{#each [themeBlack?.primary, themeBlack?.dark, themeWhite?.primary, themeWhite?.dark] as item, i}
 			<div
-				class="h-32 p-4 rounded flex flex-col justify-between flex-1 border {i === 0 || i === 1
-					? 'text-white border-gray-700'
-					: 'text-black border-gray-300'}"
-				style="background-color: {item.hex};"
+				class="flex h-32 flex-1 flex-col justify-between rounded border p-4 {i === 0 || i === 1
+					? 'border-gray-700 text-white'
+					: 'border-gray-300 text-black'}"
+				style="background-color: {item?.hex};"
 			>
-				<div class="font-bold">{i === 0 ? 'primaryBlack' : i === 1 ? 'darkBlack' : i === 2 ? 'primaryWhite' : 'darkWhite'}</div>
+				<div class="font-bold">
+					{i === 0 ? 'primaryBlack' : i === 1 ? 'darkBlack' : i === 2 ? 'primaryWhite' : 'darkWhite'}
+				</div>
 				<div class="text-xs">
-					<div>{item.hex}</div>
-					<div>{item.rgb}</div>
-					<div>{item.hsl}</div>
+					<div>{item?.hex}</div>
+					<div>{item?.rgb}</div>
+					<div>{item?.hsl}</div>
 				</div>
 			</div>
 		{/each}
@@ -240,37 +274,37 @@
 
 	<h2>功能色</h2>
 	<p>功能色是指用于特定场景、特定状态等特殊语义的颜色,通常包含成功、警告、错误、信息四种。当然也都支持类似主题色的透明度写法。</p>
-	<div class="md:flex flex-wrap justify-around md:space-x-4 space-y-4 md:space-y-0">
-		<div class="h-32 p-4 rounded text-white flex flex-col justify-between flex-1 bg-success">
+	<div class="flex-wrap justify-around space-y-4 md:flex md:space-x-4 md:space-y-0">
+		<div class="bg-success flex h-32 flex-1 flex-col justify-between rounded p-4 text-white">
 			<div class="font-bold">success</div>
 			<div class="text-xs">
-				<div>{stateColor.success}</div>
-				<div>{colorConvertFunc(stateColor.success).rgb}</div>
-				<div>{colorConvertFunc(stateColor.success).hsl}</div>
+				<div>{stateColor?.success}</div>
+				<div>{colorConvertFunc(stateColor?.success).rgb}</div>
+				<div>{colorConvertFunc(stateColor?.success).hsl}</div>
 			</div>
 		</div>
-		<div class="h-32 p-4 rounded text-white flex flex-col justify-between flex-1 bg-warning">
+		<div class="bg-warning flex h-32 flex-1 flex-col justify-between rounded p-4 text-white">
 			<div class="font-bold">warning</div>
 			<div class="text-xs">
-				<div>{stateColor.warning}</div>
-				<div>{colorConvertFunc(stateColor.warning).rgb}</div>
-				<div>{colorConvertFunc(stateColor.warning).hsl}</div>
+				<div>{stateColor?.warning}</div>
+				<div>{colorConvertFunc(stateColor?.warning).rgb}</div>
+				<div>{colorConvertFunc(stateColor?.warning).hsl}</div>
 			</div>
 		</div>
-		<div class="h-32 p-4 rounded text-white flex flex-col justify-between flex-1 bg-error">
+		<div class="bg-error flex h-32 flex-1 flex-col justify-between rounded p-4 text-white">
 			<div class="font-bold">error</div>
 			<div class="text-xs">
-				<div>{stateColor.error}</div>
-				<div>{colorConvertFunc(stateColor.error).rgb}</div>
-				<div>{colorConvertFunc(stateColor.error).hsl}</div>
+				<div>{stateColor?.error}</div>
+				<div>{colorConvertFunc(stateColor?.error).rgb}</div>
+				<div>{colorConvertFunc(stateColor?.error).hsl}</div>
 			</div>
 		</div>
-		<div class="h-32 p-4 rounded text-white flex flex-col justify-between flex-1 bg-info">
+		<div class="bg-info flex h-32 flex-1 flex-col justify-between rounded p-4 text-white">
 			<div class="font-bold">info</div>
 			<div class="text-xs">
-				<div>{stateColor.info}</div>
-				<div>{colorConvertFunc(stateColor.info).rgb}</div>
-				<div>{colorConvertFunc(stateColor.info).hsl}</div>
+				<div>{stateColor?.info}</div>
+				<div>{colorConvertFunc(stateColor?.info).rgb}</div>
+				<div>{colorConvertFunc(stateColor?.info).hsl}</div>
 			</div>
 		</div>
 	</div>
@@ -280,13 +314,15 @@
 	<p class="text-xs">
 		注:当下层为纯色时,带透明度的黑白色与灰色可能看起来一样但实际不一样,请注意区分使用。虽然灰色也可以使用透明度,但是需要透明度的地方一般通过黑白色配合透明度值使用。
 	</p>
-	<div class="md:flex justify-between md:space-x-8 space-y-8 md:space-y-0 text-black">
-		<div class="flex-1 flex flex-col justify-between rounded text-sm transparent-background">
+	<div class="justify-between space-y-8 text-black md:flex md:space-x-8 md:space-y-0">
+		<div class="transparent-background flex flex-1 flex-col justify-between rounded text-sm">
 			{#each [0.5, 1, 2, 2.5, 3, 4, 5, 6, 7, 7.5, 8, 9, 9.5, 10] as color}
 				<div class="p-4 transition hover:scale-105 hover:rounded" style="background-color: rgba(0, 0, 0, {color / 10});">
-					<div class="flex justify-between items-center">
-						<div class="text-left bg-white py-1 px-2 rounded">black{color === 10 ? '' : `/${color * 10}`}</div>
-						<div class="bg-white py-1 px-2 rounded text-xs">
+					<div class="flex items-center justify-between">
+						<div class="rounded bg-white px-2 py-1 text-left">
+							black{color === 10 ? '' : `/${color * 10}`}
+						</div>
+						<div class="rounded bg-white px-2 py-1 text-xs">
 							<div class="flex-1 text-right">rgba(0, 0, 0, {color / 10})</div>
 							<div class="flex-1 text-right">hsla(0, 0%, 0%, {color / 10})</div>
 						</div>
@@ -294,12 +330,14 @@
 				</div>
 			{/each}
 		</div>
-		<div class="flex-1 flex flex-col justify-between rounded text-sm transparent-background">
+		<div class="transparent-background flex flex-1 flex-col justify-between rounded text-sm">
 			{#each [0.5, 1, 2, 2.5, 3, 4, 5, 6, 7, 7.5, 8, 9, 9.5, 10] as color}
 				<div class="p-4 transition hover:scale-105 hover:rounded" style="background-color: rgba(255, 255, 255, {color / 10});">
-					<div class="flex justify-between items-center">
-						<div class="text-left bg-white py-1 px-2 rounded">white{color === 10 ? '' : `/${color * 10}`}</div>
-						<div class="bg-white py-1 px-2 rounded text-xs">
+					<div class="flex items-center justify-between">
+						<div class="rounded bg-white px-2 py-1 text-left">
+							white{color === 10 ? '' : `/${color * 10}`}
+						</div>
+						<div class="rounded bg-white px-2 py-1 text-xs">
 							<div class="flex-1 text-right">rgba(255, 255, 255, {color / 10})</div>
 							<div class="flex-1 text-right">hsla(0, 100%, 0%, {color / 10})</div>
 						</div>
@@ -307,7 +345,7 @@
 				</div>
 			{/each}
 		</div>
-		<div class="flex-1 flex flex-col justify-between rounded">
+		<div class="flex flex-1 flex-col justify-between rounded">
 			<ColorCard colorList={colorGrayList} />
 		</div>
 	</div>
@@ -322,16 +360,12 @@
 	<p>
 		写扩展色类名时使用 extend0、extend1...
 		这种方式不方便记忆,推荐使用颜色的别名。别名的命名规则不限,如颜色名称、品牌、情绪、场景、编号、关联事物......皆可。如下面的
-		extend0、extend1、extend2 分别对应当前主题【{themes.find(item => item.name === $currentColorStore).name_CN}】的三个扩展色。STDF 提供的<a
-			href="#/guide/generator"
-			target="_blank"
-		>
-			主题生成器
-		</a>也支持配置别名。
+		extend0、extend1、extend2 分别对应当前主题【{themes.find((item) => item.name === $currentColorStore)?.name_CN}】的三个扩展色。STDF
+		提供的<a href="/guide/generator" target="_blank"> 主题生成器 </a>也支持配置别名。
 	</p>
-	<div class="md:flex flex-wrap justify-around md:space-x-4 space-y-4 md:space-y-0">
-		{#each extendList as extend}
-			<div class="h-32 p-4 rounded text-white flex flex-col justify-between flex-1" style="background-color: {extend.color};">
+	<div class="flex-wrap justify-around space-y-4 md:flex md:space-x-4 md:space-y-0">
+		{#each extendList ?? [] as extend}
+			<div class="flex h-32 flex-1 flex-col justify-between rounded p-4 text-white" style="background-color: {extend.color};">
 				<div class="font-bold">{extend.alias}</div>
 				<div class="text-xs">
 					<div>{extend.color}</div>

+ 147 - 109
docs/site/src/pages/guide/Color_en.svelte → docs/site/src/routes/guide/color/Color_en.svelte

@@ -1,11 +1,13 @@
-<script>
+<script lang="ts">
 	import { onMount, onDestroy } from 'svelte';
-	import ColorCard from '../../components/colorCard/ColorCard.svelte';
-	import ModeSwitch from '../../components/modeSwitch/ModeSwitch.svelte';
-	import ThemeSwitch from '../../components/themeSwitch/ThemeSwitch.svelte';
-	import themes from '../../data/themes';
-	import { currentColorStore, isWideScreenStore } from '../../store';
-	import { generatePalette, generateThemeBlack, generateThemeWhite, colorConvertFunc } from '../../utils';
+	import ColorCard from '$lib/colorCard/ColorCard.svelte';
+	import ModeSwitch from '$lib/modeSwitch/ModeSwitch.svelte';
+	import ThemeSwitch from '$lib/themeSwitch/ThemeSwitch.svelte';
+	import themes from '../../../data/themes';
+	import { currentColorStore, isWideScreenStore } from '../../../store';
+	import { generatePalette, generateThemeBlack, generateThemeWhite, colorConvertFunc } from '../../../utils';
+	import hljs from 'highlight.js';
+	import { type ThemeProps } from 'stdf/theme';
 
 	const colorGrayList = [
 		{ key: 'gray-50', hex: '#f2f2f2' },
@@ -18,47 +20,77 @@
 		{ key: 'gray-700', hex: '#4D4D4D' },
 		{ key: 'gray-800', hex: '#333333' },
 		{ key: 'gray-900', hex: '#1A1A1A' },
-		{ key: 'gray-950', hex: '#0D0D0D' },
+		{ key: 'gray-950', hex: '#0D0D0D' }
 	];
-	// @ts-ignore
 	onMount(() => hljs.highlightAll());
 
-	let currentColorObj = {};
-	let primaryColors = [];
-	let darkColors = [];
-	let themeBlack = {};
-	let themeWhite = {};
-	let stateColor = {};
-	let extendList = [];
+	let currentColorObj: ThemeProps | undefined = undefined;
+	let primaryColors: { n: number; hex: string; rgb: string; hsl: string }[] | undefined = undefined;
+	let darkColors: { n: number; hex: string; rgb: string; hsl: string }[] | undefined = undefined;
+	let themeBlack:
+		| {
+				primary: { hex: string; rgb: string; hsl: string };
+				dark: { hex: string; rgb: string; hsl: string };
+		  }
+		| undefined = undefined;
+	let themeWhite:
+		| {
+				primary: { hex: string; rgb: string; hsl: string };
+				dark: { hex: string; rgb: string; hsl: string };
+		  }
+		| undefined = undefined;
+	let stateColor: { success: string; warning: string; error: string; info: string } | undefined = undefined;
+	let extendList: { color: string; alias: string }[] | undefined = undefined;
 
-	const unsubscribe = currentColorStore.subscribe(value => {
+	const unsubscribe = currentColorStore.subscribe((value) => {
 		// 根据 $currentColorStore 从 themes 中获取对应的颜色对象
-		currentColorObj = themes.find(item => item.name === value).theme;
+		currentColorObj = themes.find((item) => item.name === value)?.theme;
 		// 传入数组,按照 Tailwind 规则生成颜色列表
-		const createTWColorFunc = colorList => {
+		const createTWColorFunc = (colorList: string[]) => {
 			if (colorList.length !== 11) {
 				console.error('Coloe list length must be 11');
 				return;
 			}
-			const colorArr = [];
+			const colorArr: { n: number; hex: string; rgb: string; hsl: string }[] = [];
 			colorList.forEach((item, index) => {
 				// 第 0 项和最后一项的 key 为 50 和 950 ,其他项为 100-900,颜色有 hex、rgb、hsl 三种格式,注意 hsl 保留整数
-				let colorObj = {};
+				let colorObj: { n: number; hex: string; rgb: string; hsl: string } = {
+					n: 0,
+					hex: '',
+					rgb: '',
+					hsl: ''
+				};
 				if (index === 0) {
-					colorObj = { n: 50, hex: item, rgb: colorConvertFunc(item).rgb, hsl: colorConvertFunc(item).hsl };
+					colorObj = {
+						n: 50,
+						hex: item,
+						rgb: colorConvertFunc(item).rgb,
+						hsl: colorConvertFunc(item).hsl
+					};
 				} else if (index === 10) {
-					colorObj = { n: 950, hex: item, rgb: colorConvertFunc(item).rgb, hsl: colorConvertFunc(item).hsl };
+					colorObj = {
+						n: 950,
+						hex: item,
+						rgb: colorConvertFunc(item).rgb,
+						hsl: colorConvertFunc(item).hsl
+					};
 				} else {
-					colorObj = { n: 100 * index, hex: item, rgb: colorConvertFunc(item).rgb, hsl: colorConvertFunc(item).hsl };
+					colorObj = {
+						n: 100 * index,
+						hex: item,
+						rgb: colorConvertFunc(item).rgb,
+						hsl: colorConvertFunc(item).hsl
+					};
 				}
 				colorArr.push(colorObj);
 			});
 			return colorArr;
 		};
+		if (!currentColorObj) return;
 		const primaryColorList = generatePalette(currentColorObj.color.primary.default);
 		const darkColorList = generatePalette(currentColorObj.color.dark.default);
-		primaryColors = createTWColorFunc(primaryColorList);
-		darkColors = createTWColorFunc(darkColorList);
+		primaryColors = createTWColorFunc(primaryColorList as string[]);
+		darkColors = createTWColorFunc(darkColorList as string[]);
 		// 根据主题色生成主题黑和白
 		const primaryColorB = generateThemeBlack(currentColorObj.color.primary.default);
 		const darkColorB = generateThemeBlack(currentColorObj.color.dark.default);
@@ -92,19 +124,19 @@
 </script>
 
 <article
-	class="prose prose-strong:text-primary dark:prose-strong:text-dark dark:prose-invert pb-12 {$isWideScreenStore
+	class="prose dark:prose-invert prose-strong:text-primary dark:prose-strong:text-dark pb-12 {$isWideScreenStore
 		? 'max-w-full'
 		: 'max-w-5xl'}"
 >
 	<blockquote>
 		Switch light and dark mode, select the following built-in themes to view the color matching. You can quickly configure the color system
-		and generate a configuration file at <a href="#/guide/generator" target="_blank">Theme Generator</a>. Please refer to
-		<a href="#/guide/theme" target="_blank">Theme Configuration</a> for specific usage.
+		and generate a configuration file at <a href="/guide/generator" target="_blank">Theme Generator</a>. Please refer to
+		<a href="/guide/theme" target="_blank">Theme Configuration</a> for specific usage.
 	</blockquote>
-	<div class="inline-flex gap-4 items-center">
+	<div class="inline-flex items-center gap-4">
 		<ModeSwitch />
 	</div>
-	<div class="flex gap-4 items-center">
+	<div class="flex items-center gap-4">
 		<ThemeSwitch />
 	</div>
 	<h2>Overview</h2>
@@ -132,26 +164,26 @@
 		hue, but to make the main color lighter and brighter to make it stand out on the dark background; the other approach is to completely
 		take another hue. STDF recommends the latter, so that the main color in the dark color is more obvious. Therefore, the built-in theme
 		color of STDF is divided into light and dark colors. Of course, if you need to set the light and dark modes to the same hue, it is also
-		possible. STDF provides a <a href="#/guide/generator" target="_blank">Theme Generator</a> that supports arbitrary configuration.
+		possible. STDF provides a <a href="/guide/generator" target="_blank">Theme Generator</a> that supports arbitrary configuration.
 	</p>
-	<div class="md:flex justify-between md:space-x-8">
-		<div class="flex-1 h-40 p-4 rounded text-white flex flex-col justify-between" style="background-color: {primaryColors[6].hex};">
+	<div class="justify-between md:flex md:space-x-8">
+		<div class="flex h-40 flex-1 flex-col justify-between rounded p-4 text-white" style="background-color: {primaryColors?.[6]?.hex};">
 			<div class="font-bold">primary(Light mode)</div>
 			<div class="text-sm">
-				<div>{primaryColors[6].hex}</div>
-				<div class="text-xs">{primaryColors[6].rgb}</div>
-				<div class="text-xs">{primaryColors[6].hsl}</div>
+				<div>{primaryColors?.[6]?.hex}</div>
+				<div class="text-xs">{primaryColors?.[6]?.rgb}</div>
+				<div class="text-xs">{primaryColors?.[6]?.hsl}</div>
 			</div>
 		</div>
 		<div
-			class="flex-1 mt-4 md:mt-0 h-40 p-4 rounded text-black flex flex-col justify-between"
-			style="background-color: {darkColors[6].hex};"
+			class="mt-4 flex h-40 flex-1 flex-col justify-between rounded p-4 text-black md:mt-0"
+			style="background-color: {darkColors?.[6]?.hex};"
 		>
 			<div class="font-bold">dark(Dark mode)</div>
 			<div class="text-sm">
-				<div>{darkColors[6].hex}</div>
-				<div class="text-xs">{darkColors[6].rgb}</div>
-				<div class="text-xs">{darkColors[6].hsl}</div>
+				<div>{darkColors?.[6]?.hex}</div>
+				<div class="text-xs">{darkColors?.[6]?.rgb}</div>
+				<div class="text-xs">{darkColors?.[6]?.hsl}</div>
 			</div>
 		</div>
 	</div>
@@ -163,16 +195,16 @@
 		[omitting the 600 number]. In actual business, there will be more scenarios using light colors, so there will be more choices for light
 		colors.
 	</p>
-	<div class="md:flex justify-between md:space-x-8 space-y-8 md:space-y-0">
-		<div class="flex-1 flex flex-col justify-between rounded text-sm bg-white">
-			{#each primaryColors as color, index}
+	<div class="justify-between space-y-8 md:flex md:space-x-8 md:space-y-0">
+		<div class="flex flex-1 flex-col justify-between rounded bg-white text-sm">
+			{#each primaryColors ?? [] as color, index}
 				<div
 					class="p-4 transition hover:scale-105 hover:rounded {index >= 5 ? 'text-white' : 'text-black'}"
 					style="background-color: {color.hex};"
 				>
-					<div class="flex justify-between items-center">
+					<div class="flex items-center justify-between">
 						<div class="flex-1 text-left font-bold">primary{index === 6 ? '' : `-${color.n}`}</div>
-						<div class="text-xs text-right">
+						<div class="text-right text-xs">
 							<div>{color.hex}</div>
 							<div>{color.rgb}</div>
 							<div>{color.hsl}</div>
@@ -181,15 +213,15 @@
 				</div>
 			{/each}
 		</div>
-		<div class="flex-1 flex flex-col justify-between rounded text-sm bg-white">
-			{#each darkColors as color, index}
+		<div class="flex flex-1 flex-col justify-between rounded bg-white text-sm">
+			{#each darkColors ?? [] as color, index}
 				<div
 					class="p-4 transition hover:scale-105 hover:rounded {index >= 7 ? 'text-white' : 'text-black'}"
 					style="background-color: {color.hex};"
 				>
-					<div class="flex justify-between items-center">
+					<div class="flex items-center justify-between">
 						<div class="flex-1 text-left font-bold">dark{index === 6 ? '' : `-${color.n}`}</div>
-						<div class="text-xs text-right">
+						<div class="text-right text-xs">
 							<div>{color.hex}</div>
 							<div>{color.rgb}</div>
 							<div>{color.hsl}</div>
@@ -203,28 +235,28 @@
 	<p>
 		In some application scenarios, the transparency of the theme color is required. Note the difference from the gradient color palette.
 	</p>
-	<div class="md:flex justify-between md:space-x-8 space-y-8 md:space-y-0 transparent-background">
-		<div class="flex-1 rounded flex flex-col justify-between text-black">
+	<div class="transparent-background justify-between space-y-8 md:flex md:space-x-8 md:space-y-0">
+		<div class="flex flex-1 flex-col justify-between rounded text-black">
 			{#each [0.5, 1, 2, 2.5, 3, 4, 5, 6, 7, 7.5, 8, 9, 9.5] as color}
-				<div class="p-4 transition hover:scale-105 hover:rounded" style="background-color: {rgbaFunc(primaryColors[6].rgb, color)};">
-					<div class="flex justify-between items-center text-sm">
-						<div class="bg-white py-1 px-2 rounded">primary/{color * 10}</div>
-						<div class="bg-white py-1 px-2 rounded text-xs text-right">
-							<div>{rgbaFunc(primaryColors[6].rgb, color)}</div>
-							<div>{hslaFunc(primaryColors[6].hsl, color)}</div>
+				<div class="p-4 transition hover:scale-105 hover:rounded" style="background-color: {rgbaFunc(primaryColors?.[6]?.rgb, color)};">
+					<div class="flex items-center justify-between text-sm">
+						<div class="rounded bg-white px-2 py-1">primary/{color * 10}</div>
+						<div class="rounded bg-white px-2 py-1 text-right text-xs">
+							<div>{rgbaFunc(primaryColors?.[6]?.rgb, color)}</div>
+							<div>{hslaFunc(primaryColors?.[6]?.hsl, color)}</div>
 						</div>
 					</div>
 				</div>
 			{/each}
 		</div>
-		<div class="flex-1 rounded flex flex-col justify-between text-black">
+		<div class="flex flex-1 flex-col justify-between rounded text-black">
 			{#each [0.5, 1, 2, 2.5, 3, 4, 5, 6, 7, 7.5, 8, 9, 9.5] as color}
-				<div class="p-4 transition hover:scale-105 hover:rounded" style="background-color: {rgbaFunc(darkColors[6].rgb, color)};">
-					<div class="flex justify-between text-sm items-center">
-						<div class="bg-white py-1 px-2 rounded">dark/{color * 10}</div>
-						<div class="bg-white py-1 px-2 rounded text-xs text-right">
-							<div>{rgbaFunc(darkColors[6].rgb, color)}</div>
-							<div>{hslaFunc(darkColors[6].hsl, color)}</div>
+				<div class="p-4 transition hover:scale-105 hover:rounded" style="background-color: {rgbaFunc(darkColors?.[6]?.rgb, color)};">
+					<div class="flex items-center justify-between text-sm">
+						<div class="rounded bg-white px-2 py-1">dark/{color * 10}</div>
+						<div class="rounded bg-white px-2 py-1 text-right text-xs">
+							<div>{rgbaFunc(darkColors?.[6]?.rgb, color)}</div>
+							<div>{hslaFunc(darkColors?.[6]?.hsl, color)}</div>
 						</div>
 					</div>
 				</div>
@@ -238,19 +270,21 @@
 		matching. Similarly, two white colors close to pure white but with theme colors will also be calculated. Generally, it can be used in
 		scenarios such as text color, light and dark background color when matching multiple themes.
 	</p>
-	<div class="md:flex flex-wrap justify-around md:space-x-4 space-y-4 md:space-y-0">
-		{#each [themeBlack.primary, themeBlack.dark, themeWhite.primary, themeWhite.dark] as item, i}
+	<div class="flex-wrap justify-around space-y-4 md:flex md:space-x-4 md:space-y-0">
+		{#each [themeBlack?.primary, themeBlack?.dark, themeWhite?.primary, themeWhite?.dark] as item, i}
 			<div
-				class="h-32 p-4 rounded flex flex-col justify-between flex-1 border {i === 0 || i === 1
-					? 'text-white border-gray-700'
-					: 'text-black border-gray-300'}"
-				style="background-color: {item.hex};"
+				class="flex h-32 flex-1 flex-col justify-between rounded border p-4 {i === 0 || i === 1
+					? 'border-gray-700 text-white'
+					: 'border-gray-300 text-black'}"
+				style="background-color: {item?.hex};"
 			>
-				<div class="font-bold">{i === 0 ? 'primaryBlack' : i === 1 ? 'darkBlack' : i === 2 ? 'primaryWhite' : 'darkWhite'}</div>
+				<div class="font-bold">
+					{i === 0 ? 'primaryBlack' : i === 1 ? 'darkBlack' : i === 2 ? 'primaryWhite' : 'darkWhite'}
+				</div>
 				<div class="text-xs">
-					<div>{item.hex}</div>
-					<div>{item.rgb}</div>
-					<div>{item.hsl}</div>
+					<div>{item?.hex}</div>
+					<div>{item?.rgb}</div>
+					<div>{item?.hsl}</div>
 				</div>
 			</div>
 		{/each}
@@ -262,37 +296,37 @@
 		four types: success, warning, error, and information. Of course, it also supports the transparency writing method similar to the theme
 		color.
 	</p>
-	<div class="md:flex flex-wrap justify-around md:space-x-4 space-y-4 md:space-y-0">
-		<div class="h-32 p-4 rounded text-white flex flex-col justify-between flex-1 bg-success">
+	<div class="flex-wrap justify-around space-y-4 md:flex md:space-x-4 md:space-y-0">
+		<div class="bg-success flex h-32 flex-1 flex-col justify-between rounded p-4 text-white">
 			<div class="font-bold">success</div>
 			<div class="text-xs">
-				<div>{stateColor.success}</div>
-				<div>{colorConvertFunc(stateColor.success).rgb}</div>
-				<div>{colorConvertFunc(stateColor.success).hsl}</div>
+				<div>{stateColor?.success}</div>
+				<div>{colorConvertFunc(stateColor?.success).rgb}</div>
+				<div>{colorConvertFunc(stateColor?.success).hsl}</div>
 			</div>
 		</div>
-		<div class="h-32 p-4 rounded text-white flex flex-col justify-between flex-1 bg-warning">
+		<div class="bg-warning flex h-32 flex-1 flex-col justify-between rounded p-4 text-white">
 			<div class="font-bold">warning</div>
 			<div class="text-xs">
-				<div>{stateColor.warning}</div>
-				<div>{colorConvertFunc(stateColor.warning).rgb}</div>
-				<div>{colorConvertFunc(stateColor.warning).hsl}</div>
+				<div>{stateColor?.warning}</div>
+				<div>{colorConvertFunc(stateColor?.warning).rgb}</div>
+				<div>{colorConvertFunc(stateColor?.warning).hsl}</div>
 			</div>
 		</div>
-		<div class="h-32 p-4 rounded text-white flex flex-col justify-between flex-1 bg-error">
+		<div class="bg-error flex h-32 flex-1 flex-col justify-between rounded p-4 text-white">
 			<div class="font-bold">error</div>
 			<div class="text-xs">
-				<div>{stateColor.error}</div>
-				<div>{colorConvertFunc(stateColor.error).rgb}</div>
-				<div>{colorConvertFunc(stateColor.error).hsl}</div>
+				<div>{stateColor?.error}</div>
+				<div>{colorConvertFunc(stateColor?.error).rgb}</div>
+				<div>{colorConvertFunc(stateColor?.error).hsl}</div>
 			</div>
 		</div>
-		<div class="h-32 p-4 rounded text-white flex flex-col justify-between flex-1 bg-info">
+		<div class="bg-info flex h-32 flex-1 flex-col justify-between rounded p-4 text-white">
 			<div class="font-bold">info</div>
 			<div class="text-xs">
-				<div>{stateColor.info}</div>
-				<div>{colorConvertFunc(stateColor.info).rgb}</div>
-				<div>{colorConvertFunc(stateColor.info).hsl}</div>
+				<div>{stateColor?.info}</div>
+				<div>{colorConvertFunc(stateColor?.info).rgb}</div>
+				<div>{colorConvertFunc(stateColor?.info).hsl}</div>
 			</div>
 		</div>
 	</div>
@@ -305,13 +339,15 @@
 	<p class="text-xs">
 		Note: When the lower layer is a solid color, the black and white colors with transparency and gray may look the same but are actually
 	</p>
-	<div class="md:flex justify-between md:space-x-8 space-y-8 md:space-y-0 text-black">
-		<div class="flex-1 flex flex-col justify-between rounded text-sm transparent-background">
+	<div class="justify-between space-y-8 text-black md:flex md:space-x-8 md:space-y-0">
+		<div class="transparent-background flex flex-1 flex-col justify-between rounded text-sm">
 			{#each [0.5, 1, 2, 2.5, 3, 4, 5, 6, 7, 7.5, 8, 9, 9.5, 10] as color}
 				<div class="p-4 transition hover:scale-105 hover:rounded" style="background-color: rgba(0, 0, 0, {color / 10});">
-					<div class="flex justify-between items-center">
-						<div class="text-left bg-white py-1 px-2 rounded">black{color === 10 ? '' : `/${color * 10}`}</div>
-						<div class="bg-white py-1 px-2 rounded text-xs">
+					<div class="flex items-center justify-between">
+						<div class="rounded bg-white px-2 py-1 text-left">
+							black{color === 10 ? '' : `/${color * 10}`}
+						</div>
+						<div class="rounded bg-white px-2 py-1 text-xs">
 							<div class="flex-1 text-right">rgba(0, 0, 0, {color / 10})</div>
 							<div class="flex-1 text-right">hsla(0, 0%, 0%, {color / 10})</div>
 						</div>
@@ -319,12 +355,14 @@
 				</div>
 			{/each}
 		</div>
-		<div class="flex-1 flex flex-col justify-between rounded text-sm transparent-background">
+		<div class="transparent-background flex flex-1 flex-col justify-between rounded text-sm">
 			{#each [0.5, 1, 2, 2.5, 3, 4, 5, 6, 7, 7.5, 8, 9, 9.5, 10] as color}
 				<div class="p-4 transition hover:scale-105 hover:rounded" style="background-color: rgba(255, 255, 255, {color / 10});">
-					<div class="flex justify-between items-center">
-						<div class="text-left bg-white py-1 px-2 rounded">white{color === 10 ? '' : `/${color * 10}`}</div>
-						<div class="bg-white py-1 px-2 rounded text-xs">
+					<div class="flex items-center justify-between">
+						<div class="rounded bg-white px-2 py-1 text-left">
+							white{color === 10 ? '' : `/${color * 10}`}
+						</div>
+						<div class="rounded bg-white px-2 py-1 text-xs">
 							<div class="flex-1 text-right">rgba(255, 255, 255, {color / 10})</div>
 							<div class="flex-1 text-right">hsla(0, 100%, 0%, {color / 10})</div>
 						</div>
@@ -332,7 +370,7 @@
 				</div>
 			{/each}
 		</div>
-		<div class="flex-1 flex flex-col justify-between rounded">
+		<div class="flex flex-1 flex-col justify-between rounded">
 			<ColorCard colorList={colorGrayList} />
 		</div>
 	</div>
@@ -350,13 +388,13 @@
 	<p>
 		When writing the extended color class name, use extend0, extend1... This method is not convenient to remember, it is recommended to use
 		the alias of the color. The naming rules of the alias are not limited, such as color name, brand, emotion, scene, number, associated
-		things... are all available. As the following extend0, extend1, extend2 correspond to the three extended colors of the current theme [{themes.find(
-			item => item.name === $currentColorStore,
-		).name}]. STDF provides a <a href="#/guide/generator" target="_blank"> Theme Generator </a> also supports configuration aliases.
+		things... are all available. As the following extend0, extend1, extend2 correspond to the three extended colors of the current theme [{themes?.find(
+			(item) => item.name === $currentColorStore
+		)?.name}]. STDF provides a <a href="/guide/generator" target="_blank"> Theme Generator </a> also supports configuration aliases.
 	</p>
-	<div class="md:flex flex-wrap justify-around md:space-x-4 space-y-4 md:space-y-0">
-		{#each extendList as extend}
-			<div class="h-32 p-4 rounded text-white flex flex-col justify-between flex-1" style="background-color: {extend.color};">
+	<div class="flex-wrap justify-around space-y-4 md:flex md:space-x-4 md:space-y-0">
+		{#each extendList ?? [] as extend}
+			<div class="flex h-32 flex-1 flex-col justify-between rounded p-4 text-white" style="background-color: {extend.color};">
 				<div class="font-bold">{extend.alias}</div>
 				<div class="text-xs">
 					<div>{extend.color}</div>

+ 19 - 0
docs/site/src/routes/guide/compatibility/+page.svelte

@@ -0,0 +1,19 @@
+<script lang="ts">
+	import { mdTextToHljs } from '../../../utils/index';
+	import { isWideScreenStore } from '../../../store';
+
+	import text from '../../../../../mds/guide/compatibility.md';
+	import text_en from '../../../../../mds/guide/compatibility_en.md';
+
+	const isZh = localStorage.getItem('lang') === 'zh_CN';
+	const hljsText = mdTextToHljs((isZh ? text : text_en).replace(/<a href="/g, '<a target="_blank" href="'));
+</script>
+
+<article
+	class="prose pb-12 dark:prose-invert prose-strong:text-primary dark:prose-strong:text-dark {$isWideScreenStore
+		? 'max-w-full'
+		: 'max-w-5xl'}"
+>
+	<!-- eslint-disable-next-line svelte/no-at-html-tags -->
+	{@html hljsText}
+</article>

+ 19 - 0
docs/site/src/routes/guide/contribution/+page.svelte

@@ -0,0 +1,19 @@
+<script lang="ts">
+	import { mdTextToHljs, groupIconMdPlugin } from '../../../utils/index';
+	import { isWideScreenStore } from '../../../store';
+
+	import text from '../../../../../mds/guide/contribution.md';
+	import text_en from '../../../../../mds/guide/contribution_en.md';
+
+	const isZh = localStorage.getItem('lang') === 'zh_CN';
+	const hljsText = groupIconMdPlugin(mdTextToHljs(isZh ? text : text_en).replace(/<a href="/g, '<a target="_blank" href="'));
+</script>
+
+<article
+	class="prose pb-12 dark:prose-invert prose-strong:text-primary dark:prose-strong:text-dark {$isWideScreenStore
+		? 'max-w-full'
+		: 'max-w-5xl'}"
+>
+	<!-- eslint-disable-next-line svelte/no-at-html-tags -->
+	{@html hljsText}
+</article>

+ 21 - 0
docs/site/src/routes/guide/create/+page.svelte

@@ -0,0 +1,21 @@
+<script lang="ts">
+	import { mdTextToHljs, groupIconMdPlugin } from '../../../utils/index';
+	import { isWideScreenStore } from '../../../store';
+
+	import createText from '../../../../../../packages/create-stdf/README_CN.md';
+	import createText_en from '../../../../../../packages/create-stdf/README.md';
+
+	const isZh = localStorage.getItem('lang') === 'zh_CN';
+	const text = groupIconMdPlugin(
+		(isZh ? mdTextToHljs(createText) : mdTextToHljs(createText_en)).replace(/<a href="/g, '<a target="_blank" href="')
+	);
+</script>
+
+<article
+	class="prose pb-12 dark:prose-invert prose-strong:text-primary dark:prose-strong:text-dark {$isWideScreenStore
+		? 'max-w-full'
+		: 'max-w-5xl'}"
+>
+	<!-- eslint-disable-next-line svelte/no-at-html-tags -->
+	{@html text}
+</article>

+ 19 - 0
docs/site/src/routes/guide/faq/+page.svelte

@@ -0,0 +1,19 @@
+<script lang="ts">
+	import { mdTextToHljs } from '../../../utils/index';
+	import { isWideScreenStore } from '../../../store';
+
+	import text from '../../../../../mds/guide/faq.md';
+	import text_en from '../../../../../mds/guide/faq_en.md';
+
+	const isZh = localStorage.getItem('lang') === 'zh_CN';
+	const hljsText = mdTextToHljs((isZh ? text : text_en).replace(/<a href="/g, '<a target="_blank" href="'));
+</script>
+
+<article
+	class="prose pb-12 dark:prose-invert prose-strong:text-primary dark:prose-strong:text-dark {$isWideScreenStore
+		? 'max-w-full'
+		: 'max-w-5xl'}"
+>
+	<!-- eslint-disable-next-line svelte/no-at-html-tags -->
+	{@html hljsText}
+</article>

+ 19 - 0
docs/site/src/routes/guide/future/+page.svelte

@@ -0,0 +1,19 @@
+<script lang="ts">
+	import { mdTextToHljs } from '../../../utils/index';
+	import { isWideScreenStore } from '../../../store';
+
+	import text from '../../../../../mds/guide/future.md';
+	import text_en from '../../../../../mds/guide/future_en.md';
+
+	const isZh = localStorage.getItem('lang') === 'zh_CN';
+	const hljsText = mdTextToHljs((isZh ? text : text_en).replace(/<a href="/g, '<a target="_blank" href="'));
+</script>
+
+<article
+	class="prose pb-12 dark:prose-invert prose-strong:text-primary dark:prose-strong:text-dark {$isWideScreenStore
+		? 'max-w-full'
+		: 'max-w-5xl'}"
+>
+	<!-- eslint-disable-next-line svelte/no-at-html-tags -->
+	{@html hljsText}
+</article>

+ 242 - 147
docs/site/src/pages/guide/Generator.svelte → docs/site/src/routes/guide/generator/+page.svelte

@@ -1,31 +1,30 @@
-<script>
-	// @ts-nocheck
+<script lang="ts">
 	import { onDestroy, onMount } from 'svelte';
 	import { fly } from 'svelte/transition';
 	import ClipboardJS from 'clipboard';
-	import ModeSwitch from '../../components/modeSwitch/ModeSwitch.svelte';
-	// import SwitchSite from '../../components/switch/Index.svelte';
-	import { currentColorStore } from '../../store';
-	import themes from '../../data/themes';
-	import { generatePalette, generateThemeBlack, generateThemeWhite, colorConvertFunc, throttle, hexToRgb } from '../../utils';
-	import colorList from '../../data/color';
+	import ModeSwitch from '$lib/modeSwitch/ModeSwitch.svelte';
+	import { currentColorStore } from '../../../store';
+	import themes, { type ThemeItem } from '../../../data/themes';
+	import { generatePalette, generateThemeBlack, generateThemeWhite, colorConvertFunc, throttle, hexToRgb } from '../../../utils';
+	import colorList from '../../../data/color';
 	import GeneratorPreview from './GeneratorPreview.svelte';
+	import hljs from 'highlight.js';
 
 	const isZh = localStorage.getItem('lang') === 'zh_CN';
 
-	let showTip = true;
-	let windowWidth = 0;
-	let windowHeight = 0;
-	const initTheme = themes.find(item => item.name === $currentColorStore);
+	let showTip = $state(true);
+	let windowWidth = $state(0);
+	let windowHeight = $state(0);
+	const initTheme = themes.find((item) => item.name === $currentColorStore) as ThemeItem;
 
-	const setPropertyFunc = (name, value) => {
+	const setPropertyFunc = (name: string, value: string) => {
 		const rgbStr = hexToRgb(value);
 		document.documentElement.style.setProperty(name, rgbStr);
 	};
 	// 使用 extendList 返回 extendListStr
-	const extendListStrFunc = extendList => {
+	const extendListStrFunc = (extendList: { color: string; alias: string }[]) => {
 		let extendListStr = '	{';
-		extendList.forEach(item => {
+		extendList.forEach((item) => {
 			extendListStr += `
 			color: '${hexToRgb(item.color)}', // ${item.color} ${colorConvertFunc(item.color).hsl}
 			alias: "${item.alias}",
@@ -39,7 +38,7 @@
 		return extendListStr;
 	};
 	// 使用 extendList 返回 extendListStr2
-	const extendListStrFunc2 = extendList => {
+	const extendListStrFunc2 = (extendList: { color: string; alias: string }[]) => {
 		let extendListStr = '';
 		extendList.forEach((item, index) => {
 			extendListStr += `--theme-color-extend${index}: ${hexToRgb(item.color)};
@@ -51,30 +50,47 @@
 		return extendListStr;
 	};
 	const numbers = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
-	let colors = [
+	let colors = $state([
 		{ type: 'primary', color: initTheme.theme.color.primary.default },
 		{ type: 'dark', color: initTheme.theme.color.dark.default },
 		{ type: 'success', color: initTheme.theme.color.functional.success },
 		{ type: 'warning', color: initTheme.theme.color.functional.warning },
 		{ type: 'error', color: initTheme.theme.color.functional.error },
-		{ type: 'info', color: initTheme.theme.color.functional.info },
-	];
-	let currentColorObj = {};
-	let primaryColors = [];
-	let darkColors = [];
-	let themeBlack = {};
-	let themeWhite = {};
-	let stateColor = {};
-	let extendList = initTheme.theme.color.extend;
-	let name = initTheme.name;
-	let showCopyTip = false;
-	let showCopyTip2 = false;
-	$: extendListStr = extendListStrFunc(extendList);
-	$: extendListStr2 = extendListStrFunc2(extendList);
+		{ type: 'info', color: initTheme.theme.color.functional.info }
+	]);
+	let currentColorObj = {
+		name: '',
+		color: {
+			primary: { default: '' },
+			dark: { default: '' },
+			functional: { success: '', warning: '', error: '', info: '' },
+			extend: [{ color: '', alias: '' }]
+		}
+	};
+	let primaryColors: { hex: string; hsl: string; n: number; rgb: string }[] = $state([]);
+	let darkColors: { hex: string; hsl: string; n: number; rgb: string }[] = $state([]);
+	let themeBlack = $state({
+		primary: { hex: '', hsl: '', rgb: '' },
+		dark: { hex: '', hsl: '', rgb: '' }
+	});
+	let themeWhite = $state({
+		primary: { hex: '', hsl: '', rgb: '' },
+		dark: { hex: '', hsl: '', rgb: '' }
+	});
+	let stateColor = $state({ success: '', warning: '', error: '', info: '' });
+	let extendList: { color: string; alias: string }[] = $state(initTheme.theme.color.extend);
+	let name = $state(initTheme.name);
+	let showCopyTip = $state(false);
+	let showCopyTip2 = $state(false);
+	let extendListStr;
+	$effect(() => {
+		extendListStr = extendListStrFunc(extendList);
+	});
+	let extendListStr2 = $derived(extendListStrFunc2(extendList));
 
-	// @ts-ignore
-	$: configStr = hljs.highlight(
-		`// ${isZh ? '主题配置' : 'Theme configuration'}
+	let configStr = $derived(
+		hljs.highlight(
+			`// ${isZh ? '主题配置' : 'Theme configuration'}
 name: '${name}',
 color: {
 	primary: {
@@ -117,12 +133,13 @@ color: {
 	${extendListStr}
 	],
 },`,
-		{ language: 'javascript', ignoreIllegals: true },
-	).value;
+			{ language: 'javascript', ignoreIllegals: true }
+		).value
+	);
 
-	// @ts-ignore
-	$: configStr2 = hljs.highlight(
-		`/* ${isZh ? '初始 CSS 变量' : 'Initial CSS variables'} */
+	let configStr2 = $derived(
+		hljs.highlight(
+			`/* ${isZh ? '初始 CSS 变量' : 'Initial CSS variables'} */
 --theme-color-primary-50: ${hexToRgb(primaryColors[0].hex)};
 --theme-color-primary-100: ${hexToRgb(primaryColors[1].hex)};
 --theme-color-primary-200: ${hexToRgb(primaryColors[2].hex)};
@@ -154,36 +171,68 @@ color: {
 --theme-color-functional-error: ${hexToRgb(stateColor.error)};
 --theme-color-functional-info: ${hexToRgb(stateColor.info)};
 ${extendListStr2}`,
-		{ language: 'css', ignoreIllegals: true },
-	).value;
+			{ language: 'css', ignoreIllegals: true }
+		).value
+	);
 
 	// 统一生成颜色
 	const generateFunc = () => {
 		// 传入数组,按照 Tailwind 规则生成颜色列表
-		const createTWColorFunc = colorList => {
+		const createTWColorFunc = (colorList: string[]) => {
 			if (colorList.length !== 11) {
-				console.error('颜色列表长度必须为11');
+				console.error('颜色列表长度必须为 11');
 				return;
 			}
-			const colorArr = [];
+			const colorArr: { hex: string; hsl: string; n: number; rgb: string }[] = [];
 			colorList.forEach((item, index) => {
-				// 第 0 项和最后一项的 key 为 50 和 950 ,其他项为 100-900,颜色有 hex、rgb、hsl 三种格式,注意 hsl 保留整数
-				let colorObj = {};
+				// 第 0 项和最后一项的 key 为 50 和 950,其他项为 100-900,颜色有 hex、rgb、hsl 三种格式,注意 hsl 保留整数
+				let colorObj: { hex: string; hsl: string; n: number; rgb: string } = {
+					hex: '',
+					hsl: '',
+					n: 0,
+					rgb: ''
+				};
 				if (index === 0) {
-					colorObj = { n: 50, hex: item, rgb: colorConvertFunc(item).rgb, hsl: colorConvertFunc(item).hsl };
+					colorObj = {
+						n: 50,
+						hex: item,
+						rgb: colorConvertFunc(item).rgb,
+						hsl: colorConvertFunc(item).hsl
+					};
 				} else if (index === 10) {
-					colorObj = { n: 950, hex: item, rgb: colorConvertFunc(item).rgb, hsl: colorConvertFunc(item).hsl };
+					colorObj = {
+						n: 950,
+						hex: item,
+						rgb: colorConvertFunc(item).rgb,
+						hsl: colorConvertFunc(item).hsl
+					};
 				} else {
-					colorObj = { n: 100 * index, hex: item, rgb: colorConvertFunc(item).rgb, hsl: colorConvertFunc(item).hsl };
+					colorObj = {
+						n: 100 * index,
+						hex: item,
+						rgb: colorConvertFunc(item).rgb,
+						hsl: colorConvertFunc(item).hsl
+					};
 				}
 				colorArr.push(colorObj);
 			});
 			return colorArr;
 		};
-		const primaryColorList = generatePalette(currentColorObj.color.primary.default);
-		const darkColorList = generatePalette(currentColorObj.color.dark.default);
-		primaryColors = createTWColorFunc(primaryColorList);
-		darkColors = createTWColorFunc(darkColorList);
+		const primaryColorList = generatePalette(currentColorObj.color.primary.default) as string[];
+		const darkColorList = generatePalette(currentColorObj.color.dark.default) as string[];
+		primaryColors = createTWColorFunc(primaryColorList) as {
+			hex: string;
+			hsl: string;
+			n: number;
+			rgb: string;
+		}[];
+
+		darkColors = createTWColorFunc(darkColorList) as {
+			hex: string;
+			hsl: string;
+			n: number;
+			rgb: string;
+		}[];
 
 		// 根据主题色生成主题黑和白
 		const primaryColorB = generateThemeBlack(currentColorObj.color.primary.default);
@@ -195,6 +244,7 @@ ${extendListStr2}`,
 			darkMeta.setAttribute('content', darkColorB.hex);
 		}
 		themeBlack = { primary: primaryColorB, dark: darkColorB };
+
 		const primaryColorW = generateThemeWhite(currentColorObj.color.primary.default);
 		// 查找 meta 标签,name="theme-color" 且 media="(prefers-color-scheme: light)"
 		const lightMeta = document.querySelector('meta[name="theme-color"][media="(prefers-color-scheme: light)"]');
@@ -205,6 +255,7 @@ ${extendListStr2}`,
 		const darkColorW = generateThemeWhite(currentColorObj.color.dark.default);
 		themeWhite = { primary: primaryColorW, dark: darkColorW };
 		stateColor = currentColorObj.color.functional;
+
 		primaryColorList.forEach((item, i) => {
 			setPropertyFunc(i === 6 ? '--theme-color-primary' : `--theme-color-primary-${i === 0 ? '50' : i === 10 ? '950' : i + '00'}`, item);
 		});
@@ -216,45 +267,69 @@ ${extendListStr2}`,
 		setPropertyFunc('--theme-color-darkBlack', darkColorB.hex);
 		setPropertyFunc('--theme-color-darkWhite', darkColorW.hex);
 	};
-	const changeFunc = (type = 'primary', e, value) => {
-		const colorValue = e ? e.target.value : value;
+	const changeFunc = (type = 'primary', e: null | Event, value: string) => {
+		const colorValue = e ? (e.target as HTMLInputElement).value : value;
 		const primaryObj = currentColorObj.color.primary;
 		const darkObj = currentColorObj.color.dark;
 		const functionalObj = currentColorObj.color.functional;
 		const newColors = [...colors];
-		newColors.find(item => item.type === type).color = colorValue;
+		const item = newColors.find((item) => item.type === type);
+		if (item) {
+			item.color = colorValue;
+		}
 		colors = newColors;
 		if (type === 'primary') {
-			numbers.forEach(item => {
-				primaryObj[item === 600 ? 'default' : item] = colorValue;
+			numbers.forEach((item) => {
+				if (item === 600) {
+					primaryObj['default'] = colorValue;
+				} else {
+					(primaryObj as unknown as Record<string, string>)[item] = colorValue;
+				}
 			});
 		} else if (type === 'dark') {
-			numbers.forEach(item => {
-				darkObj[item === 600 ? 'default' : item] = colorValue;
+			numbers.forEach((item) => {
+				if (item === 600) {
+					darkObj['default'] = colorValue;
+				} else {
+					(darkObj as unknown as Record<string, string>)[item] = colorValue;
+				}
 			});
 		} else {
 			setPropertyFunc(`--theme-color-functional-${type}`, colorValue);
-			functionalObj[type] = colorValue;
+			(functionalObj as unknown as Record<string, string>)[type] = colorValue;
 		}
 		currentColorObj = {
-			color: { primary: primaryObj, dark: darkObj, functional: functionalObj },
+			name: name,
+			color: {
+				primary: primaryObj,
+				dark: darkObj,
+				functional: functionalObj,
+				extend: extendList
+			}
 		};
 		generateFunc();
 	};
-	const unsubscribe = currentColorStore.subscribe(value => {
+	const unsubscribe = currentColorStore.subscribe((value) => {
 		// 根据 $currentColorStore 从 themes 中获取对应的颜色对象
-		currentColorObj = themes.find(item => item.name === value).theme;
+		const theme = themes.find((item) => item.name === value);
+		if (!theme) {
+			return;
+		}
+		currentColorObj = theme.theme;
 		generateFunc();
 
 		// 根据 currentColorObj 设置 colors
 		const newColors = [...colors];
-		newColors.forEach(item => {
+		newColors.forEach((item) => {
 			if (item.type === 'primary') {
 				item.color = currentColorObj.color.primary.default;
 			} else if (item.type === 'dark') {
 				item.color = currentColorObj.color.dark.default;
 			} else {
-				item.color = currentColorObj.color.functional[item.type];
+				// 确保 item.type 是 functional 对象中的有效键
+				if (item.type in currentColorObj.color.functional) {
+					item.color = currentColorObj.color.functional[item.type as keyof typeof currentColorObj.color.functional];
+				}
 			}
 		});
 		colors = newColors;
@@ -267,12 +342,12 @@ ${extendListStr2}`,
 	});
 	// 随机事件
 	const randomFunc = () => {
-		// 从 colorList 中随机取出一个 mode 为dark的颜色,再随机取出一个 mode 为 light 的颜色
-		const randomDarkColor = colorList.filter(item => item.mode === 'dark')[
-			Math.floor(Math.random() * colorList.filter(item => item.mode === 'dark').length)
+		// 从 colorList 中随机取出一个 mode 为 dark 的颜色,再随机取出一个 mode 为 light 的颜色
+		const randomDarkColor = colorList.filter((item) => item.mode === 'dark')[
+			Math.floor(Math.random() * colorList.filter((item) => item.mode === 'dark').length)
 		];
-		const randomLightColor = colorList.filter(item => item.mode === 'light')[
-			Math.floor(Math.random() * colorList.filter(item => item.mode === 'light').length)
+		const randomLightColor = colorList.filter((item) => item.mode === 'light')[
+			Math.floor(Math.random() * colorList.filter((item) => item.mode === 'light').length)
 		];
 		name = `${randomDarkColor.name}/${randomLightColor.name}`;
 		// 根据随机颜色生成主题
@@ -280,13 +355,13 @@ ${extendListStr2}`,
 		changeFunc('dark', null, randomLightColor.hex);
 		// 获取当前 extendList 的长度
 		const extendListLength = extendList.length;
-		// 从 colorList 中随机取出 extendListLength 个 mode 为dark的颜色,作为扩展色
+		// 从 colorList 中随机取出 extendListLength 个 mode 为 dark 的颜色,作为扩展色
 		const randomExtendList = colorList
-			.filter(item => item.mode === 'dark')
+			.filter((item) => item.mode === 'dark')
 			.sort(() => Math.random() - 0.5)
 			.slice(0, extendListLength);
 		let newExtendList = [];
-		newExtendList = randomExtendList.map(item => {
+		newExtendList = randomExtendList.map((item) => {
 			return { color: item.hex, alias: item.name };
 		});
 		extendList = newExtendList;
@@ -298,23 +373,23 @@ ${extendListStr2}`,
 		window.location.reload();
 	};
 	// 删除扩展色
-	const deleteFunc = i => {
+	const deleteFunc = (i: number) => {
 		let newExtendList = [...extendList];
 		newExtendList.splice(i, 1);
 		extendList = newExtendList;
 		extendListStr = extendListStrFunc(extendList);
 	};
 	// 选择 extendList 的颜色
-	const changeExtendFunc = (e, i) => {
-		const colorValue = e.target.value;
+	const changeExtendFunc = (e: Event, i: number) => {
+		const colorValue = (e.target as HTMLInputElement).value;
 		let newExtendList = [...extendList];
 		newExtendList[i].color = colorValue;
 		extendList = newExtendList;
 		extendListStr = extendListStrFunc(extendList);
 	};
 	// 输入 extendList 的别名
-	const inputExtendFunc = (e, i) => {
-		const aliasValue = e.target.value;
+	const inputExtendFunc = (e: Event, i: number) => {
+		const aliasValue = (e.target as HTMLInputElement).value;
 		let newExtendList = [...extendList];
 		newExtendList[i].alias = aliasValue;
 		extendList = newExtendList;
@@ -339,33 +414,33 @@ ${extendListStr2}`,
 
 		// 复制
 		const clipboard = new ClipboardJS('#copyButton', {
-			target: function (trigger) {
-				return document.querySelector('#myCodeBlock');
-			},
+			target: () => {
+				return document.querySelector('#myCodeBlock')!;
+			}
 		});
-		clipboard.on('success', function (e) {
+		clipboard.on('success', function () {
 			showCopyTip = true;
 			setTimeout(() => {
 				showCopyTip = false;
 			}, 2000);
 		});
-		clipboard.on('error', function (e) {
+		clipboard.on('error', function () {
 			console.error('无法将内容复制到剪贴板');
 		});
 
 		// 复制
 		const clipboard2 = new ClipboardJS('#copyButton2', {
-			target: function (trigger) {
-				return document.querySelector('#myCodeBlock2');
-			},
+			target: () => {
+				return document.querySelector('#myCodeBlock2')!;
+			}
 		});
-		clipboard2.on('success', function (e) {
+		clipboard2.on('success', function () {
 			showCopyTip2 = true;
 			setTimeout(() => {
 				showCopyTip2 = false;
 			}, 2000);
 		});
-		clipboard2.on('error', function (e) {
+		clipboard2.on('error', function () {
 			console.error('无法将内容复制到剪贴板');
 		});
 	});
@@ -375,57 +450,61 @@ ${extendListStr2}`,
 </script>
 
 <div class="block md:hidden">{isZh ? '请在桌面端使用!' : 'Please use it on the desktop!'}</div>
-<div class="hidden md:flex justify-between">
+<div class="hidden justify-between md:flex">
 	<div>
-		<div class="text-center mb-2 font-bold">{isZh ? '配置' : 'Configure'}</div>
-		<div class="text-center flex flex-col gap-1">
+		<div class="mb-2 text-center font-bold">{isZh ? '配置' : 'Configure'}</div>
+		<div class="flex flex-col gap-1 text-center">
 			<div class="text-left">{isZh ? '主题名称' : 'Theme name'}</div>
 			<div class="flex-1">
 				<input
-					class="bg-transparent w-full outline outline-1 outline-black/10 dark:outline-white/20 rounded-sm text-sm px-1 py-1 focus:outline-primary dark:focus:outline-dark focus:outline-none"
+					class="w-full rounded-sm bg-transparent px-1 py-1 text-sm outline outline-1 outline-black/10 focus:outline-none focus:outline-primary dark:outline-white/20 dark:focus:outline-dark"
 					type="text"
 					bind:value={name}
 					placeholder={isZh ? '请输入主题名称' : 'Please enter theme name'}
 				/>
 			</div>
 		</div>
-		<div class="flex gap-2 mt-4">
+		<div class="mt-4 flex gap-2">
 			<div class="flex flex-col gap-4 text-center">
 				<!-- 输入框 -->
 				{#each colors as item, i}
-					<div class="flex gap-2 justify-end {i === 2 ? 'mt-6' : 'mt-0'} relative">
+					<div class="flex justify-end gap-2 {i === 2 ? 'mt-6' : 'mt-0'} relative">
 						<div class="flex-1 text-right">{item.type}</div>
 						<input
 							type="color"
 							bind:value={item.color}
-							on:input={e => throttle(changeFunc(item.type, e))}
-							class="w-6 h-6 flex-none cursor-pointer"
+							oninput={(e) => throttle(() => changeFunc(item.type, e, item.color), 100)()}
+							class="h-6 w-6 flex-none cursor-pointer"
 							style="background-color: {item.color};"
-							on:click={() => (showTip = false)}
+							onclick={() => (showTip = false)}
 						/>
-						<div class="text-left text-sm leading-6 w-20 flex-none overflow-hidden">{item.color}</div>
+						<div class="w-20 flex-none overflow-hidden text-left text-sm leading-6">
+							{item.color}
+						</div>
 						{#if i === 0 && showTip}
-							<div class="absolute right-[4.4rem] rotate-[135deg] pointer-events-none">
+							<div class="pointer-events-none absolute right-[4.4rem] rotate-[135deg]">
 								<div class="animate-bounce text-3xl">👇</div>
 							</div>
 						{/if}
 					</div>
 				{/each}
-				<div class="flex flex-col gap-4 overflow-y-auto p-1 mt-6" style="height: {windowHeight - 480}px;">
+				<div class="mt-6 flex flex-col gap-4 overflow-y-auto p-1" style="height: {windowHeight - 480}px;">
 					{#each extendList as item, i}
 						<div class="flex flex-col gap-2">
-							<div class="flex gap-2 justify-end">
+							<div class="flex justify-end gap-2">
 								<div class="flex-1 text-right">extend{i}</div>
 								<input
 									type="color"
 									bind:value={item.color}
-									class="w-6 h-6 flex-none"
+									class="h-6 w-6 flex-none"
 									style="background-color: {item.color};"
-									on:input={e => throttle(changeExtendFunc(e, i))}
+									oninput={(e) => throttle(() => changeExtendFunc(e, i))}
 								/>
-								<div class="text-left text-sm leading-6 w-16 flex-none overflow-hidden">{item.color}</div>
-								<button class="bg-black/5 dark:bg-white/10 px-1 rounded" on:click={() => deleteFunc(i)}>
-									<svg class="w-6 h-4 hover:scale-90 transition-all" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
+								<div class="w-16 flex-none overflow-hidden text-left text-sm leading-6">
+									{item.color}
+								</div>
+								<button aria-label="delete" class="rounded bg-black/5 px-1 dark:bg-white/10" onclick={() => deleteFunc(i)}>
+									<svg class="h-4 w-6 transition-all hover:scale-90" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
 										<path
 											class="fill-error"
 											d="M17 6H22V8H20V21C20 21.5523 19.5523 22 19 22H5C4.44772 22 4 21.5523 4 21V8H2V6H7V3C7 2.44772 7.44772 2 8 2H16C16.5523 2 17 2.44772 17 3V6ZM18 8H6V20H18V8ZM9 11H11V17H9V11ZM13 11H15V17H13V11ZM9 4V6H15V4H9Z"
@@ -436,22 +515,22 @@ ${extendListStr2}`,
 							</div>
 							<div class="flex">
 								<input
-									class="h-6 w-full bg-transparent outline outline-1 outline-black/10 dark:outline-white/20 rounded-sm text-xs px-1 py-1 focus:outline-primary dark:focus:outline-dark focus:outline-none"
+									class="h-6 w-full rounded-sm bg-transparent px-1 py-1 text-xs outline outline-1 outline-black/10 focus:outline-none focus:outline-primary dark:outline-white/20 dark:focus:outline-dark"
 									type="text"
 									bind:value={item.alias}
 									placeholder={isZh ? `请输入 extend${i} 别名` : `Please enter extend${i} alias`}
-									on:input={e => throttle(inputExtendFunc(e, i))}
+									oninput={(e) => throttle(() => inputExtendFunc(e, i))}
 								/>
 							</div>
 						</div>
 					{/each}
 					<div>
 						<button
-							class="border border-primary dark:border-dark w-full dark:text-white text-black py-1.5 rounded text-sm flex justify-center gap-2 items-centers"
-							on:click={addExtendFunc}
+							class="items-centers flex w-full justify-center gap-2 rounded border border-primary py-1.5 text-sm text-black dark:border-dark dark:text-white"
+							onclick={addExtendFunc}
 						>
 							<span>
-								<svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
+								<svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
 									<path class="fill-black dark:fill-white" d="M11 11V5H13V11H19V13H13V19H11V13H5V11H11Z"></path>
 								</svg>
 							</span>
@@ -463,55 +542,61 @@ ${extendListStr2}`,
 		</div>
 	</div>
 	<div class="flex-1">
-		<div class="text-center mb-4 font-bold">{isZh ? '色板 & 配置文件' : 'Palette & Profiles'}</div>
-		<div class="flex flex-col px-4 text-xs text-center">
-			<div class="flex-1 flex justify-between gap-1 mb-1">
+		<div class="mb-4 text-center font-bold">{isZh ? '色板 & 配置文件' : 'Palette & Profiles'}</div>
+		<div class="flex flex-col px-4 text-center text-xs">
+			<div class="mb-1 flex flex-1 justify-between gap-1">
 				{#each primaryColors as color, index}
 					<div
 						class="h-12 rounded {index >= 5 ? 'text-primaryWhite' : 'text-primaryBlack'}"
 						style="background-color: {color.hex};flex: {index === 6 ? '2' : '1'}"
 					>
-						<div class="flex flex-col justify-between items-center">
-							<div class="flex-1 leading-10 mt-1{index === 6 ? ' text-xl font-bold' : ''}">{index === 6 ? 'primary' : `${color.n}`}</div>
+						<div class="flex flex-col items-center justify-between">
+							<div class="flex-1 leading-10 mt-1{index === 6 ? ' text-xl font-bold' : ''}">
+								{index === 6 ? 'primary' : `${color.n}`}
+							</div>
 						</div>
 					</div>
 				{/each}
 			</div>
-			<div class="flex-1 flex justify-between gap-1">
+			<div class="flex flex-1 justify-between gap-1">
 				{#each darkColors as color, index}
 					<div
 						class="h-12 rounded {index <= 6 ? 'text-darkBlack' : 'text-darkWhite'}"
 						style="background-color: {color.hex};flex: {index === 6 ? '2' : '1'};"
 					>
-						<div class="flex justify-between items-center">
-							<div class="flex-1 leading-10 mt-1{index === 6 ? ' text-xl font-bold' : ''}">{index === 6 ? 'dark' : `${color.n}`}</div>
+						<div class="flex items-center justify-between">
+							<div class="flex-1 leading-10 mt-1{index === 6 ? ' text-xl font-bold' : ''}">
+								{index === 6 ? 'dark' : `${color.n}`}
+							</div>
 						</div>
 					</div>
 				{/each}
 			</div>
 		</div>
-		<div class="flex justify-between gap-1 px-4 mt-1 text-xs text-center">
+		<div class="mt-1 flex justify-between gap-1 px-4 text-center text-xs">
 			{#each [themeBlack.primary, themeBlack.dark, themeWhite.primary, themeWhite.dark] as item, i}
 				<div
-					class="flex-1 h-12 rounded pt-4 border {i === 0 || i === 1 ? 'text-white border-gray-700' : 'text-black border-gray-300'}"
+					class="h-12 flex-1 rounded border pt-4 {i === 0 || i === 1 ? 'border-gray-700 text-white' : 'border-gray-300 text-black'}"
 					style="background-color: {item.hex};"
 				>
-					<div>{i === 0 ? 'primaryBlack' : i === 1 ? 'darkBlack' : i === 2 ? 'primaryWhite' : 'darkWhite'}</div>
+					<div>
+						{i === 0 ? 'primaryBlack' : i === 1 ? 'darkBlack' : i === 2 ? 'primaryWhite' : 'darkWhite'}
+					</div>
 				</div>
 			{/each}
 		</div>
 		<!-- 功能色 -->
-		<div class="flex justify-between gap-1 px-4 mt-1 text-center text-white text-xs">
-			<div class="flex-1 h-12 rounded pt-4" style="background-color: {stateColor.success};">success</div>
-			<div class="flex-1 h-12 rounded pt-4" style="background-color: {stateColor.warning};">warning</div>
-			<div class="flex-1 h-12 rounded pt-4" style="background-color: {stateColor.error};">error</div>
-			<div class="flex-1 h-12 rounded pt-4" style="background-color: {stateColor.info};">info</div>
+		<div class="mt-1 flex justify-between gap-1 px-4 text-center text-xs text-white">
+			<div class="h-12 flex-1 rounded pt-4" style="background-color: {stateColor.success};">success</div>
+			<div class="h-12 flex-1 rounded pt-4" style="background-color: {stateColor.warning};">warning</div>
+			<div class="h-12 flex-1 rounded pt-4" style="background-color: {stateColor.error};">error</div>
+			<div class="h-12 flex-1 rounded pt-4" style="background-color: {stateColor.info};">info</div>
 		</div>
 		<!-- 扩展色 -->
-		<div class="flex justify-between gap-1 px-4 mt-1 h-12 text-center text-white text-xs">
+		<div class="mt-1 flex h-12 justify-between gap-1 px-4 text-center text-xs text-white">
 			{#if extendList}
 				{#each extendList as item, i}
-					<div class="flex-1 h-12 py-1 rounded flex flex-col justify-center gap-1" style="background-color: {item.color};">
+					<div class="flex h-12 flex-1 flex-col justify-center gap-1 rounded py-1" style="background-color: {item.color};">
 						<div class="text-xs">extend{i}</div>
 						<div>{item.alias}</div>
 					</div>
@@ -519,15 +604,20 @@ ${extendListStr2}`,
 			{/if}
 		</div>
 		<!-- 配置文件 -->
-		<div class="flex mx-4 mt-1" style="height:{windowHeight - 388}px;width:{windowWidth - 858}px">
-			<div class="grow bg-codeLight dark:bg-codeDark relative mr-1">
+		<div class="mx-4 mt-1 flex" style="height:{windowHeight - 388}px;width:{windowWidth - 858}px">
+			<div class="bg-codeLight dark:bg-codeDark relative mr-1 grow">
 				<div class="overflow-auto rounded" style="height:{windowHeight - 388}px;width:{((windowWidth - 858) / 5) * 3 - 6}px">
-					<article class="prose dark:prose-invert max-w-none text-xs">
+					<article class="prose max-w-none text-xs dark:prose-invert">
+						<!-- eslint-disable-next-line svelte/no-at-html-tags -->
 						<pre><code class="hljs" id="myCodeBlock">{@html configStr}</code></pre>
 					</article>
 				</div>
-				<button class="absolute right-0 top-0 py-2 px-3 rounded-bl bg-black/5 dark:bg-white/10 text-sm hover:opacity-80" id="copyButton">
-					<svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
+				<button
+					aria-label="copy"
+					class="absolute right-0 top-0 rounded-bl bg-black/5 px-3 py-2 text-sm hover:opacity-80 dark:bg-white/10"
+					id="copyButton"
+				>
+					<svg class="h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
 						<path
 							class="fill-gray-700 dark:fill-gray-300"
 							d="M6 4V8H18V4H20.0066C20.5552 4 21 4.44495 21 4.9934V21.0066C21 21.5552 20.5551 22 20.0066 22H3.9934C3.44476 22 3 21.5551 3 21.0066V4.9934C3 4.44476 3.44495 4 3.9934 4H6ZM8 2H16V6H8V2Z"
@@ -535,19 +625,24 @@ ${extendListStr2}`,
 					</svg>
 				</button>
 				{#if showCopyTip}
-					<div in:fly={{ x: 50, duration: 500 }} out:fly={{ x: 50, duration: 300 }} class="absolute top-1 text-sm right-14">
+					<div in:fly={{ x: 50, duration: 500 }} out:fly={{ x: 50, duration: 300 }} class="absolute right-14 top-1 text-sm">
 						{isZh ? '已复制!' : 'Copied!'}
 					</div>
 				{/if}
 			</div>
-			<div class="grow bg-codeLight dark:bg-codeDark relative">
+			<div class="bg-codeLight dark:bg-codeDark relative grow">
 				<div class="overflow-auto rounded" style="height:{windowHeight - 388}px;width:{((windowWidth - 858) / 5) * 2 + 4}px">
-					<article class="prose dark:prose-invert max-w-none text-xs">
+					<article class="prose max-w-none text-xs dark:prose-invert">
+						<!-- eslint-disable-next-line svelte/no-at-html-tags -->
 						<pre><code class="hljs" id="myCodeBlock2">{@html configStr2}</code></pre>
 					</article>
 				</div>
-				<button class="absolute right-0 top-0 py-2 px-3 rounded-bl bg-black/5 dark:bg-white/10 text-sm hover:opacity-80" id="copyButton2">
-					<svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
+				<button
+					aria-label="copy"
+					class="absolute right-0 top-0 rounded-bl bg-black/5 px-3 py-2 text-sm hover:opacity-80 dark:bg-white/10"
+					id="copyButton2"
+				>
+					<svg class="h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
 						<path
 							class="fill-gray-700 dark:fill-gray-300"
 							d="M6 4V8H18V4H20.0066C20.5552 4 21 4.44495 21 4.9934V21.0066C21 21.5552 20.5551 22 20.0066 22H3.9934C3.44476 22 3 21.5551 3 21.0066V4.9934C3 4.44476 3.44495 4 3.9934 4H6ZM8 2H16V6H8V2Z"
@@ -555,26 +650,26 @@ ${extendListStr2}`,
 					</svg>
 				</button>
 				{#if showCopyTip2}
-					<div in:fly={{ x: 50, duration: 500 }} out:fly={{ x: 50, duration: 300 }} class="absolute top-1 text-sm right-14">
+					<div in:fly={{ x: 50, duration: 500 }} out:fly={{ x: 50, duration: 300 }} class="absolute right-14 top-1 text-sm">
 						{isZh ? '已复制!' : 'Copied!'}
 					</div>
 				{/if}
 			</div>
 		</div>
 	</div>
-	<div class="flex gap-4 w-[390px]">
+	<div class="flex w-[390px] gap-4">
 		<div>
 			<div class="flex w-full justify-between pb-2">
 				<div>
 					<button
-						class="bg-primary dark:bg-dark text-white dark:text-black rounded px-4 py-2 text-xs hover:opacity-90"
-						on:click={randomFunc}
+						class="rounded bg-primary px-4 py-2 text-xs text-white hover:opacity-90 dark:bg-dark dark:text-black"
+						onclick={randomFunc}
 					>
 						{isZh ? '随机主题' : 'Random theme'}
 					</button>
 					<button
-						class="border border-primary dark:border-dark dark:text-white text-black rounded px-4 py-2 text-xs hover:opacity-90 ml-2"
-						on:click={resetFunc}
+						class="ml-2 rounded border border-primary px-4 py-2 text-xs text-black hover:opacity-90 dark:border-dark dark:text-white"
+						onclick={resetFunc}
 					>
 						{isZh ? '重置' : 'Reset'}
 					</button>
@@ -584,7 +679,7 @@ ${extendListStr2}`,
 				</div>
 			</div>
 			<div
-				class="bg-primaryWhite dark:bg-darkBlack border border-primary/20 dark:border-dark/20 w-[392px] dark:border-gray-700 h-96 overflow-auto"
+				class="h-96 w-[392px] overflow-auto border border-primary/20 bg-primaryWhite dark:border-dark/20 dark:border-gray-700 dark:bg-darkBlack"
 				style="height:{windowHeight - 130}px"
 			>
 				<GeneratorPreview />

+ 132 - 125
docs/site/src/pages/guide/Calendar.svelte → docs/site/src/routes/guide/generator/Calendar.svelte

@@ -1,6 +1,6 @@
-<script>
+<script lang="ts">
 	import { getNowBeforeOrAfterMonth, getCalendarData, getMonthListRange, getDateRange } from 'stdf/utils';
-	import {zh_CN,en_US}from 'stdf/lang';
+	import { zh_CN, en_US } from 'stdf/lang';
 
 	const isZh = localStorage.getItem('lang') === 'zh_CN';
 
@@ -9,57 +9,52 @@
 	const currentLang = isZh ? zh_CN : en_US;
 	const calendarLang = currentLang.calendar;
 
-	// 传入的开始月,默认为当前月前6个月
-	// The start month passed in, default is 6 months before the current month
-	export let startMonth = getNowBeforeOrAfterMonth(0);
-
-	// 传入的结束月,默认为当前月后6个月
-	// The end month passed in, default is 6 months after the current month
-	export let endMonth = getNowBeforeOrAfterMonth(0);
-
+	// 传入的开始月,默认为当前月前 6 个月
+	// 传入的结束月,默认为当前月后 6 个月
 	// 选择模式,single 单选,multiple 多选,range 范围选择
-	// Selection mode, single single selection, multiple multiple selection, range range selection
-	export let mode = 'range';
-
 	// 是否从周日开始
-	// Whether to start from Sunday
-	export let startSunday = false;
-
 	// 周末文字是否标红
-	// Whether the weekend text is marked red
-	export let weekendRed = false;
-
 	// 月数据是否使用卡片样式
-	// Whether to use the card style for the month data
-	export let monthCard = true;
-
 	// 是否显示月份水印
-	// Whether to show the month watermark
-	export let monthMark = false;
-
 	// 月份水印文字大小
-	// Month watermark text size
-	export let monthMarkSize = 'xl';
-
 	// 显示信息的日期
-	// Date to display information
-	export let infoDates = [];
-
 	// 不允许选择日期集合
-	// Collection of dates not allowed to be selected
-	export let disabledDates = [];
-
 	// 圆角风格
-	// Rounded style
-	export let radius = 'xl';
-
 	// 自动滚动到某个月时,是否使用动画
-	// Whether to use animation when automatically scrolling to a month
-	export let useAnimation = true;
-
 	// 高亮显示今天
-	// Highlight today
-	export let highlightToday = true;
+	/**
+	 * @typedef {Object} Props
+	 * @property {any} [startMonth]
+	 * @property {any} [endMonth]
+	 * @property {string} [mode]
+	 * @property {boolean} [startSunday]
+	 * @property {boolean} [weekendRed]
+	 * @property {boolean} [monthCard]
+	 * @property {boolean} [monthMark]
+	 * @property {string} [monthMarkSize]
+	 * @property {any} [infoDates]
+	 * @property {any} [disabledDates]
+	 * @property {string} [radius]
+	 * @property {boolean} [useAnimation]
+	 * @property {boolean} [highlightToday]
+	 */
+
+	/** @type {Props} */
+	let {
+		startMonth = getNowBeforeOrAfterMonth(0),
+		endMonth = getNowBeforeOrAfterMonth(0),
+		mode = 'range',
+		startSunday = false,
+		weekendRed = false,
+		monthCard = true,
+		monthMark = false,
+		monthMarkSize = 'xl',
+		infoDates = [],
+		disabledDates = [],
+		radius = 'xl',
+		useAnimation = true,
+		highlightToday = true
+	} = $props();
 
 	// 圆角风格样式
 	// Rounded style style
@@ -67,7 +62,7 @@
 		base: 'rounded',
 		xl: 'rounded-xl',
 		'2xl': 'rounded-2xl',
-		none: 'rounded-none',
+		none: 'rounded-none'
 	};
 
 	// 月份水印文字大小样式
@@ -79,10 +74,10 @@
 		'6xl': 'text-6xl',
 		'7xl': 'text-7xl',
 		'8xl': 'text-8xl',
-		'9xl': 'text-9xl',
+		'9xl': 'text-9xl'
 	};
 
-	// 当天日期字符串,YYYYMMDD,日和天不足两位时前面补0
+	// 当天日期字符串,YYYYMMDD,日和天不足两位时前面补 0
 	// Today's date string, YYYYMMDD, day and day are not less than two digits, and 0 is filled in front
 	const now = new Date();
 	const nowYear = now.getFullYear();
@@ -100,7 +95,7 @@
 
 	// 传入 startSunday 和位于周的索引,返回是否是周末
 	// Pass in startSunday and the index of the week, and return whether it is a weekend
-	const isWeekendFunc = (startSunday, index) => {
+	const isWeekendFunc = (startSunday: boolean, index: number) => {
 		if (startSunday) {
 			return index === 0 || index === 6;
 		} else {
@@ -114,21 +109,32 @@
 
 	// 循环 monthList,根据每个月份的数据,生成全部的日历数据,其中 month 为当前月,year 为年,data 为日期数组
 	// Loop monthList, generate all calendar data according to the data of each month, where month is the current month, year is the year, and data is the date array
-	const allMonthData = monthList.map(monthStr => {
+	const allMonthData: {
+		year: string;
+		month: string;
+		data: { text: string; info?: string; disabled?: boolean; start?: boolean; end?: boolean }[];
+	}[] = monthList.map((monthStr) => {
 		return {
 			year: monthStr.slice(0, 4),
 			month: monthStr.slice(4),
-			data: getCalendarData(monthStr, startSunday),
+			data: getCalendarData(monthStr, startSunday).map((item) => ({
+				text: item,
+				info: '',
+				disabled: false,
+				start: false,
+				end: false
+			}))
 		};
 	});
+	console.log(444, allMonthData);
 
 	// 如果 infoDates 不为空,循环 allMonthData,循环 data,循环 infoDates,如果 infoDates 中的日期和 data 中的日期相同,将 infoDates 中的 info 赋值给 data 中的 info
 	// If infoDates is not empty, loop allMonthData, loop data, loop infoDates, if the date in infoDates is the same as the date in data, assign the info in infoDates to the info in data
 	if (infoDates.length > 0) {
-		allMonthData.forEach(monthData => {
-			monthData.data.forEach(data => {
-				infoDates.forEach(info => {
-					if (info.date === monthData.year + monthData.month + data.day) {
+		allMonthData.forEach((item) => {
+			item.data.forEach((data) => {
+				infoDates.forEach((info) => {
+					if (info.date === item.year + item.month + data.text) {
 						data.info = info.info;
 					}
 				});
@@ -139,10 +145,10 @@
 	// 如果 disabledDates 不为空,循环 allMonthData,循环 data,循环 disabledDates,如果 disabledDates 中的日期和 data 中的日期相同,将 disabledDates 中的 disabled 赋值给 data 中的 disabled
 	// If disabledDates is not empty, loop allMonthData, loop data, loop disabledDates, if the date in disabledDates is the same as the date in data, assign the disabled in disabledDates to the disabled in data
 	if (disabledDates.length > 0) {
-		allMonthData.forEach(monthData => {
-			monthData.data.forEach(data => {
-				disabledDates.forEach(disabled => {
-					if (disabled === monthData.year + monthData.month + data.day) {
+		allMonthData.forEach((item) => {
+			item.data.forEach((data) => {
+				disabledDates.forEach((disabled) => {
+					if (disabled === item.year + item.month + data.text) {
 						data.disabled = true;
 					}
 				});
@@ -158,38 +164,43 @@
 	// From the current month, find randomDayNum consecutive days at random as the initial value of selectedDate, such as ['20231108', '20231109', '20231110', '20231111', '20231112']
 	// 先获取当前月份所有日期,再获取当前月份所有日期中的连续 randomDayNum 天
 	// First get all the dates of the current month, and then get randomDayNum consecutive days in all the dates of the current month
-	let currentMonthAllDays = [];
+	let currentMonthAllDays: string[] = [];
 	const currentMonth = new Date().getMonth() + 1;
 	const currentYear = new Date().getFullYear();
 	const currentMonthData = getCalendarData(`${currentYear}${currentMonth < 10 ? '0' + currentMonth : currentMonth}`, startSunday);
-	const currentMonthDays = currentMonthData.filter(item => item.day).map(item => item.day);
-	currentMonthDays.forEach((item, index) => {
+
+	const currentMonthDays = currentMonthData.filter((item) => item).map((item) => item);
+	currentMonthDays.forEach((item) => {
 		currentMonthAllDays.push(`${currentYear}${currentMonth < 10 ? '0' + currentMonth : currentMonth}${item}`);
 	});
 	// 从 currentMonthAllDays 随机找到连续的 5 天
 	// Find 5 consecutive days at random from currentMonthAllDays
 	const randomIndex = Math.floor(Math.random() * (currentMonthAllDays.length - randomDayNum));
-	let selectedDate = currentMonthAllDays.slice(randomIndex, randomIndex + randomDayNum);
+	let selectedDate = $state(currentMonthAllDays.slice(randomIndex, randomIndex + randomDayNum));
 
 	// 范围选择时,点击的开始与结束
 	// When range selection is clicked, the beginning and end are clicked
-	let rangeArr = [];
+	let rangeArr: string[] = [];
 
 	// selectedDate 字符串
 	// selectedDate string
-	$: selectedDateStr = selectedDate.join(',');
+	let selectedDateStr = $derived(selectedDate.join(','));
 
 	// 点击日期事件
 	// Click date event
-	const clickDayFunc = (year, month, dayData) => {
-		if (!dayData.day) {
+	const clickDayFunc = (
+		year: string,
+		month: string,
+		dayData: { text: string; info?: string; disabled?: boolean; start?: boolean; end?: boolean }
+	) => {
+		if (!dayData.text) {
 			return;
 		}
 		if (isQuickSelect) {
 			isQuickSelect = false;
 			selectedDate = [];
 		}
-		rangeArr.push(`${year}${month}${dayData.day}`);
+		rangeArr.push(`${year}${month}${dayData.text}`);
 		if (rangeArr.length === 2) {
 			// 将 rangeArr 排序,保证第一个日期小于第二个日期
 			// Sort rangeArr to ensure that the first date is less than the second date
@@ -211,118 +222,114 @@
 </script>
 
 <div>
-	<div class=" z-10 top-0 left-0 w-full">
-		<div class="flex justify-around items-center text-center gap-1 px-6 h-10 leading-10">
+	<div class="left-0 top-0 z-10 w-full">
+		<div class="flex h-10 items-center justify-around gap-1 px-6 text-center leading-10">
 			{#each weekTexts as item, index}
-				<div class={`flex-1 font-bold${weekendRed && isWeekendFunc(startSunday, index) ? ' text-error' : ''}`}>
+				<div class="flex-1 font-bold{weekendRed && isWeekendFunc(startSunday, index) ? ' text-error' : ''}">
 					{item}
 				</div>
 			{/each}
 		</div>
 	</div>
-	<div class={` py-2 px-4 flex flex-col gap-4 overflow-y-auto calendar-container ${useAnimation ? 'scroll-smooth' : 'scroll-auto'}`}>
+	<div class="calendar-container flex flex-col gap-4 overflow-y-auto px-4 py-2 {useAnimation ? 'scroll-smooth' : 'scroll-auto'}">
 		{#each allMonthData as item}
-			<div class={`${monthCard ? 'bg-white dark:bg-black shadow-md dark:shadow-white/5 rounded-xl ' : ''}relative`}>
+			<div class="{monthCard ? 'rounded-xl bg-white shadow-md dark:bg-black dark:shadow-white/5 ' : ''}relative">
 				<div class="px-4 pt-4 text-xl text-black/30 dark:text-white/30">
-					<span class="font-bold text-black dark:text-white mr-2">
+					<span class="mr-2 font-bold text-black dark:text-white">
 						{calendarLang.monthTextList[Number(item.month) - 1]}
 					</span>
 					{item.year}
 				</div>
-				<div class={`grid grid-cols-7 gap-y-1 text-center p-2`}>
+				<div class="grid grid-cols-7 gap-y-1 p-2 text-center">
 					{#each item.data as i}
-						<!-- svelte-ignore a11y-click-events-have-key-events -->
-						<!-- svelte-ignore a11y-no-static-element-interactions -->
-						<div
-							class={`p-px cursor-pointer${i.day ? ' bg-primary/10 dark:bg-dark/20' : ''}`}
-							on:click={() => {
+						<button
+							class="p-px cursor-pointer{i.text ? ' bg-primary/10 dark:bg-dark/20' : ''}"
+							onclick={() => {
 								if (!i.disabled) clickDayFunc(item.year, item.month, i);
 							}}
-							class:!bg-transparent={!selectedDateStr.includes(`${item.year}${item.month}${i.day}`)}
+							class:!bg-transparent={!selectedDateStr.includes(`${item.year}${item.month}${i.text}`)}
 							class:!rounded-l-xl={radius === 'xl' &&
 								mode === 'range' &&
-								(selectedDateStr.indexOf(`${item.year}${item.month}${i.day}`) === 0 || i.start)}
+								(selectedDateStr.indexOf(`${item.year}${item.month}${i.text}`) === 0 || i.start)}
 							class:!rounded-r-xl={radius === 'xl' &&
 								mode === 'range' &&
-								(selectedDateStr.indexOf(`${item.year}${item.month}${i.day}`) === selectedDateStr.length - 8 || i.end)}
+								(selectedDateStr.indexOf(`${item.year}${item.month}${i.text}`) === selectedDateStr.length - 8 || i.end)}
 							class:!rounded-xl={radius === 'xl' && mode !== 'range'}
 							class:!rounded-l-2xl={radius === '2xl' &&
 								mode === 'range' &&
-								(selectedDateStr.indexOf(`${item.year}${item.month}${i.day}`) === 0 || i.start)}
+								(selectedDateStr.indexOf(`${item.year}${item.month}${i.text}`) === 0 || i.start)}
 							class:!rounded-r-2xl={radius === '2xl' &&
 								mode === 'range' &&
-								(selectedDateStr.indexOf(`${item.year}${item.month}${i.day}`) === selectedDateStr.length - 8 || i.end)}
+								(selectedDateStr.indexOf(`${item.year}${item.month}${i.text}`) === selectedDateStr.length - 8 || i.end)}
 							class:!rounded-2xl={radius === '2xl' && mode !== 'range'}
 							class:!rounded-l-none={radius === 'none' &&
 								mode === 'range' &&
-								(selectedDateStr.indexOf(`${item.year}${item.month}${i.day}`) === 0 || i.start)}
+								(selectedDateStr.indexOf(`${item.year}${item.month}${i.text}`) === 0 || i.start)}
 							class:!rounded-r-none={radius === 'none' &&
 								mode === 'range' &&
-								(selectedDateStr.indexOf(`${item.year}${item.month}${i.day}`) === selectedDateStr.length - 8 || i.end)}
+								(selectedDateStr.indexOf(`${item.year}${item.month}${i.text}`) === selectedDateStr.length - 8 || i.end)}
 							class:!rounded-none={radius === 'none' && mode !== 'range'}
 							class:!rounded-l={radius === 'base' &&
 								mode === 'range' &&
-								(selectedDateStr.indexOf(`${item.year}${item.month}${i.day}`) === 0 || i.start)}
+								(selectedDateStr.indexOf(`${item.year}${item.month}${i.text}`) === 0 || i.start)}
 							class:!rounded-r={radius === 'base' &&
 								mode === 'range' &&
-								(selectedDateStr.indexOf(`${item.year}${item.month}${i.day}`) === selectedDateStr.length - 8 || i.end)}
+								(selectedDateStr.indexOf(`${item.year}${item.month}${i.text}`) === selectedDateStr.length - 8 || i.end)}
 							class:!rounded={radius === 'base' && mode !== 'range'}
 						>
 							<div
-								class={`${radiusClass[radius] || 'rounded-xl'} relative w-full h-full flex flex-col justify-center ${
-									i.info ? 'py-1' : 'py-2'
-								}`}
-								class:bg-primary={(i.day && mode !== 'range' && selectedDateStr.includes(`${item.year}${item.month}${i.day}`)) ||
-									(i.day &&
-										selectedDateStr.includes(`${item.year}${item.month}${i.day}`) &&
+								class="{radiusClass[radius as keyof typeof radiusClass] ||
+									'rounded-xl'} relative flex h-full w-full flex-col justify-center {i.info ? 'py-1' : 'py-2'}"
+								class:bg-primary={(i.text && mode !== 'range' && selectedDateStr.includes(`${item.year}${item.month}${i.text}`)) ||
+									(i.text &&
+										selectedDateStr.includes(`${item.year}${item.month}${i.text}`) &&
 										mode === 'range' &&
-										(selectedDateStr.indexOf(`${item.year}${item.month}${i.day}`) === 0 ||
-											selectedDateStr.indexOf(`${item.year}${item.month}${i.day}`) === selectedDateStr.length - 8))}
-								class:dark:bg-dark={(i.day && mode !== 'range' && selectedDateStr.includes(`${item.year}${item.month}${i.day}`)) ||
-									(i.day &&
-										selectedDateStr.includes(`${item.year}${item.month}${i.day}`) &&
+										(selectedDateStr.indexOf(`${item.year}${item.month}${i.text}`) === 0 ||
+											selectedDateStr.indexOf(`${item.year}${item.month}${i.text}`) === selectedDateStr.length - 8))}
+								class:dark:bg-dark={(i.text && mode !== 'range' && selectedDateStr.includes(`${item.year}${item.month}${i.text}`)) ||
+									(i.text &&
+										selectedDateStr.includes(`${item.year}${item.month}${i.text}`) &&
 										mode === 'range' &&
-										(selectedDateStr.indexOf(`${item.year}${item.month}${i.day}`) === 0 ||
-											selectedDateStr.indexOf(`${item.year}${item.month}${i.day}`) === selectedDateStr.length - 8))}
-								class:text-white={(i.day && mode !== 'range' && selectedDateStr.includes(`${item.year}${item.month}${i.day}`)) ||
-									(i.day &&
-										selectedDateStr.includes(`${item.year}${item.month}${i.day}`) &&
+										(selectedDateStr.indexOf(`${item.year}${item.month}${i.text}`) === 0 ||
+											selectedDateStr.indexOf(`${item.year}${item.month}${i.text}`) === selectedDateStr.length - 8))}
+								class:text-white={(i.text && mode !== 'range' && selectedDateStr.includes(`${item.year}${item.month}${i.text}`)) ||
+									(i.text &&
+										selectedDateStr.includes(`${item.year}${item.month}${i.text}`) &&
 										mode === 'range' &&
-										(selectedDateStr.indexOf(`${item.year}${item.month}${i.day}`) === 0 ||
-											selectedDateStr.indexOf(`${item.year}${item.month}${i.day}`) === selectedDateStr.length - 8))}
-								class:dark:text-black={(i.day && mode !== 'range' && selectedDateStr.includes(`${item.year}${item.month}${i.day}`)) ||
-									(i.day &&
-										selectedDateStr.includes(`${item.year}${item.month}${i.day}`) &&
+										(selectedDateStr.indexOf(`${item.year}${item.month}${i.text}`) === 0 ||
+											selectedDateStr.indexOf(`${item.year}${item.month}${i.text}`) === selectedDateStr.length - 8))}
+								class:dark:text-black={(i.text && mode !== 'range' && selectedDateStr.includes(`${item.year}${item.month}${i.text}`)) ||
+									(i.text &&
+										selectedDateStr.includes(`${item.year}${item.month}${i.text}`) &&
 										mode === 'range' &&
-										(selectedDateStr.indexOf(`${item.year}${item.month}${i.day}`) === 0 ||
-											selectedDateStr.indexOf(`${item.year}${item.month}${i.day}`) === selectedDateStr.length - 8))}
+										(selectedDateStr.indexOf(`${item.year}${item.month}${i.text}`) === 0 ||
+											selectedDateStr.indexOf(`${item.year}${item.month}${i.text}`) === selectedDateStr.length - 8))}
 								class:text-primary={mode === 'range' &&
-									selectedDateStr.includes(`${item.year}${item.month}${i.day}`) &&
-									selectedDateStr.indexOf(`${item.year}${item.month}${i.day}`) !== 0 &&
-									selectedDateStr.indexOf(`${item.year}${item.month}${i.day}`) !== selectedDateStr.length - 8}
+									selectedDateStr.includes(`${item.year}${item.month}${i.text}`) &&
+									selectedDateStr.indexOf(`${item.year}${item.month}${i.text}`) !== 0 &&
+									selectedDateStr.indexOf(`${item.year}${item.month}${i.text}`) !== selectedDateStr.length - 8}
 								class:dark:text-dark={mode === 'range' &&
-									selectedDateStr.includes(`${item.year}${item.month}${i.day}`) &&
-									selectedDateStr.indexOf(`${item.year}${item.month}${i.day}`) !== 0 &&
-									selectedDateStr.indexOf(`${item.year}${item.month}${i.day}`) !== selectedDateStr.length - 8}
-								class:border={item.year + item.month + i.day === todayStr && highlightToday}
-								class:border-primary={item.year + item.month + i.day === todayStr && highlightToday}
-								class:dark:border-dark={item.year + item.month + i.day === todayStr && highlightToday}
+									selectedDateStr.includes(`${item.year}${item.month}${i.text}`) &&
+									selectedDateStr.indexOf(`${item.year}${item.month}${i.text}`) !== 0 &&
+									selectedDateStr.indexOf(`${item.year}${item.month}${i.text}`) !== selectedDateStr.length - 8}
+								class:border={item.year + item.month + i.text === todayStr && highlightToday}
+								class:border-primary={item.year + item.month + i.text === todayStr && highlightToday}
+								class:dark:border-dark={item.year + item.month + i.text === todayStr && highlightToday}
 							>
 								<div class="font-bold">
-									{i.day ? Number(i.day) : ''}
+									{i.text ? Number(i.text) : ''}
 								</div>
 								<div class="text-xs opacity-50">{i.info || ''}</div>
 							</div>
-						</div>
+						</button>
 					{/each}
 				</div>
 				{#if monthMark}
 					<div
-						class={`absolute pointer-events-none w-full ${
-							monthMarkSizeClass[monthMarkSize] || 'text-7xl'
-						} text-center top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 font-bold text-black/5 ${
-							monthCard ? 'dark:text-white/10' : 'dark:text-white/5'
-						}`}
+						class="pointer-events-none absolute w-full {monthMarkSizeClass[monthMarkSize as keyof typeof monthMarkSizeClass] ??
+							'text-7xl'} left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 text-center font-bold text-black/5 {monthCard
+							? 'dark:text-white/10'
+							: 'dark:text-white/5'}"
 					>
 						{calendarLang.monthTextList[Number(item.month) - 1]}
 					</div>

+ 17 - 17
docs/site/src/pages/guide/GeneratorPreview.svelte → docs/site/src/routes/guide/generator/GeneratorPreview.svelte

@@ -1,12 +1,12 @@
-<script>
+<script lang="ts">
 	import { Button, Switch, Progress, ProgressLoop, Loading, NoticeBar, Icon, Slider } from 'stdf';
 	import Calendar from './Calendar.svelte';
-	import { currentThemeStore } from '../../store';
+	import { currentThemeStore } from '../../../store';
 
 	const isZh = localStorage.getItem('lang') === 'zh_CN';
 	const icons = ['ri-spy-fill', 'ri-chrome-fill', 'ri-riding-line', 'ri-switch-fill'];
-	$: textList = ['请配置您喜欢的颜色主题!', '这是第一条测试通告!'];
-	$: textList_en = ['Please configure the color theme you like!', 'This is the first test notice!'];
+	let textList = $derived(['请配置您喜欢的颜色主题!', '这是第一条测试通告!']);
+	let textList_en = $derived(['Please configure the color theme you like!', 'This is the first test notice!']);
 </script>
 
 <NoticeBar textList={isZh ? textList : textList_en} />
@@ -308,7 +308,7 @@
 		<rect class="cls-2" width="614" height="383.76" />
 		<!-- 太阳 -->
 		<circle
-			class="cls-3 dark:translate-y-full transition-all duration-1000"
+			class="cls-3 transition-all duration-1000 dark:translate-y-full"
 			cx="348.85"
 			cy="246.41"
 			r="32.45"
@@ -316,7 +316,7 @@
 		/>
 		<!-- 月亮 -->
 		<path
-			class="cls-moon translate-y-full dark:translate-y-0 transition-all duration-1000"
+			class="cls-moon translate-y-full transition-all duration-1000 dark:translate-y-0"
 			d="M311.533 177.529C308.429 178.533 305.117 179.075 301.679 179.075C284.01 179.075 269.687 164.752 269.687 147.083C269.687 141.22 271.265 135.725 274.018 131C260.177 134.77 250 147.428 250 162.464C250 180.472 264.599 195.071 282.607 195.071C295.181 195.071 306.092 187.954 311.533 177.529Z"
 		/>
 
@@ -551,22 +551,22 @@
 		<circle class="cls-moon-light hidden dark:block" cx="353.5" cy="241.44" r="179" transform="translate(-135.18 262.55) rotate(-45)" />
 		<!-- star -->
 		<path
-			class="animate-starTwinkle hidden dark:block"
+			class="hidden animate-starTwinkle dark:block"
 			d="M102 27.5C102 34.0667 105.441 39.5384 110 40.75C105.441 41.9616 102 47.4333 102 54C102 47.4333 98.5591 41.9616 94 40.75C98.5591 39.5384 102 34.0667 102 27.5Z"
 			fill="#fff"
 		/>
 		<path
-			class="animate-starTwinkle2 hidden dark:block"
+			class="hidden animate-starTwinkle2 dark:block"
 			d="M555 21.4444C555 27.2815 558.011 32.1452 562 33.2222C558.011 34.2992 555 39.1629 555 45C555 39.1629 551.989 34.2992 548 33.2222C551.989 32.1452 555 27.2815 555 21.4444Z"
 			fill="#fff"
 		/>
 		<path
-			class="animate-starTwinkle3 hidden dark:block"
+			class="hidden animate-starTwinkle3 dark:block"
 			d="M366 27.3333C366 31.7112 368.151 35.3589 371 36.1667C368.151 36.9744 366 40.6222 366 45C366 40.6222 363.849 36.9744 361 36.1667C363.849 35.3589 366 31.7112 366 27.3333Z"
 			fill="#fff"
 		/>
 		<path
-			class="animate-starTwinkle4 hidden dark:block"
+			class="hidden animate-starTwinkle4 dark:block"
 			d="M534 94.3333C534 98.7112 536.151 102.359 539 103.167C536.151 103.974 534 107.622 534 112C534 107.622 531.849 103.974 529 103.167C531.849 102.359 534 98.7112 534 94.3333Z"
 			fill="#fff"
 		/>
@@ -574,29 +574,29 @@
 	<!-- </g> -->
 </svg>
 
-<div class="flex p-4 justify-between gap-4">
+<div class="flex justify-between gap-4 p-4">
 	<div class="w-1/3">
 		<ProgressLoop />
 	</div>
-	<div class="flex flex-col justify-between flex-1 py-2">
+	<div class="flex flex-1 flex-col justify-between py-2">
 		<div class="flex justify-around">
 			<Loading theme />
 			<Loading theme type="1_30" />
 			<Loading theme type="1_13" />
 		</div>
 		<div class="flex justify-around">
-			<Switch check></Switch>
-			<Switch check injClass="bg-success dark:bg-success" />
-			<Switch check injClass="!bg-error dark:!bg-error" />
+			<Switch active />
+			<Switch active injClass="bg-success dark:bg-success" />
+			<Switch active injClass="!bg-error dark:!bg-error" />
 		</div>
 	</div>
 </div>
 <div class="flex flex-col gap-4 p-4">
-	<Progress></Progress>
+	<Progress />
 </div>
 <div class="flex flex-wrap justify-between">
 	{#each icons as icon}
-		<div class="py-2 text-center flex-1">
+		<div class="flex-1 py-2 text-center">
 			<Icon name={icon} theme />
 		</div>
 	{/each}

+ 21 - 0
docs/site/src/routes/guide/icon-plugin/+page.svelte

@@ -0,0 +1,21 @@
+<script lang="ts">
+	import { mdTextToHljs, groupIconMdPlugin } from '../../../utils/index';
+	import { isWideScreenStore } from '../../../store';
+
+	import iconPluginText from '../../../../../../packages/rollup-plugin-stdf-icon/README_CN.md';
+	import iconPluginText_en from '../../../../../../packages/rollup-plugin-stdf-icon/README.md';
+
+	const isZh = localStorage.getItem('lang') === 'zh_CN';
+	const text = mdTextToHljs(
+		(isZh ? groupIconMdPlugin(iconPluginText) : groupIconMdPlugin(iconPluginText_en)).replace(/<a href="/g, '<a target="_blank" href="')
+	);
+</script>
+
+<article
+	class="prose pb-12 dark:prose-invert prose-strong:text-primary dark:prose-strong:text-dark {$isWideScreenStore
+		? 'max-w-full'
+		: 'max-w-5xl'}"
+>
+	<!-- eslint-disable-next-line svelte/no-at-html-tags -->
+	{@html text}
+</article>

+ 19 - 0
docs/site/src/routes/guide/icon/+page.svelte

@@ -0,0 +1,19 @@
+<script lang="ts">
+	import { mdTextToHljs } from '../../../utils/index';
+	import { isWideScreenStore } from '../../../store';
+
+	import text from '../../../../../mds/guide/icon.md';
+	import text_en from '../../../../../mds/guide/icon_en.md';
+
+	const isZh = localStorage.getItem('lang') === 'zh_CN';
+	const hljsText = mdTextToHljs((isZh ? text : text_en).replace(/<a href="/g, '<a target="_blank" href="'));
+</script>
+
+<article
+	class="prose pb-12 dark:prose-invert prose-strong:text-primary dark:prose-strong:text-dark {$isWideScreenStore
+		? 'max-w-full'
+		: 'max-w-5xl'}"
+>
+	<!-- eslint-disable-next-line svelte/no-at-html-tags -->
+	{@html hljsText}
+</article>

+ 19 - 0
docs/site/src/routes/guide/internation/+page.svelte

@@ -0,0 +1,19 @@
+<script lang="ts">
+	import { mdTextToHljs } from '../../../utils/index';
+	import { isWideScreenStore } from '../../../store';
+
+	import text from '../../../../../mds/guide/internation.md';
+	import text_en from '../../../../../mds/guide/internation_en.md';
+
+	const isZh = localStorage.getItem('lang') === 'zh_CN';
+	const hljsText = mdTextToHljs((isZh ? text : text_en).replace(/<a href="/g, '<a target="_blank" href="'));
+</script>
+
+<article
+	class="prose pb-12 dark:prose-invert prose-strong:text-primary dark:prose-strong:text-dark {$isWideScreenStore
+		? 'max-w-full'
+		: 'max-w-5xl'}"
+>
+	<!-- eslint-disable-next-line svelte/no-at-html-tags -->
+	{@html hljsText}
+</article>

+ 1 - 1
docs/site/src/pages/guide/Logo.svelte → docs/site/src/routes/guide/logo/+page.svelte

@@ -1,4 +1,4 @@
-<div class="flex text-9xl font-bold gap-3 md:gap-10 mb-4 justify-around md:justify-start">
+<div class="mb-4 flex justify-around gap-3 text-9xl font-bold md:justify-start md:gap-10">
 	<div class="text-dark dark:text-primary">S</div>
 	<div class="text-primary dark:text-dark">T</div>
 	<div class="text-primary dark:text-dark">D</div>

+ 20 - 0
docs/site/src/routes/guide/milestone/+page.svelte

@@ -0,0 +1,20 @@
+<script lang="ts">
+	import { mdTextToHljs } from '../../../utils/index';
+	import { isWideScreenStore } from '../../../store';
+
+	import text from '../../../../../mds/guide/milestone.md';
+	import text_en from '../../../../../mds/guide/milestone_en.md';
+
+	const isZh = localStorage.getItem('lang') === 'zh_CN';
+
+	const hljsText = mdTextToHljs((isZh ? text : text_en).replace(/<a href="/g, '<a target="_blank" href="'));
+</script>
+
+<article
+	class="prose pb-12 dark:prose-invert prose-strong:text-primary dark:prose-strong:text-dark {$isWideScreenStore
+		? 'max-w-full'
+		: 'max-w-5xl'}"
+>
+	<!-- eslint-disable-next-line svelte/no-at-html-tags -->
+	{@html hljsText}
+</article>

+ 4 - 4
docs/site/src/pages/guide/Shortkey.svelte → docs/site/src/routes/guide/shortkey/+page.svelte

@@ -1,11 +1,11 @@
-<script>
-	import { isWideScreenStore } from '../../store';
+<script lang="ts">
+	import { isWideScreenStore } from '../../../store';
 
 	const isZh = localStorage.getItem('lang') === 'zh_CN';
 </script>
 
 <article
-	class="hidden md:block prose prose-strong:text-primary dark:prose-strong:text-dark dark:prose-invert pb-12 {$isWideScreenStore
+	class="prose hidden pb-12 dark:prose-invert prose-strong:text-primary dark:prose-strong:text-dark md:block {$isWideScreenStore
 		? 'max-w-full'
 		: 'max-w-5xl'}"
 >
@@ -35,7 +35,7 @@
 	{/if}
 </article>
 
-<article class="block md:hidden prose prose-strong:text-primary dark:prose-strong:text-dark dark:prose-invert pb-12 max-w-5xl">
+<article class="prose block max-w-5xl pb-12 dark:prose-invert prose-strong:text-primary dark:prose-strong:text-dark md:hidden">
 	{#if isZh}
 		<p>快捷键仅用于桌面端。</p>
 	{:else}

+ 19 - 0
docs/site/src/routes/guide/theme/+page.svelte

@@ -0,0 +1,19 @@
+<script lang="ts">
+	import { mdTextToHljs } from '../../../utils/index';
+	import { isWideScreenStore } from '../../../store';
+
+	import theme from '../../../../../mds/guide/theme.md';
+	import theme_en from '../../../../../mds/guide/theme_en.md';
+
+	const isZh = localStorage.getItem('lang') === 'zh_CN';
+	const text = mdTextToHljs((isZh ? theme : theme_en).replace(/<a href="/g, '<a target="_blank" href="'));
+</script>
+
+<article
+	class="prose pb-12 dark:prose-invert prose-strong:text-primary dark:prose-strong:text-dark {$isWideScreenStore
+		? 'max-w-full'
+		: 'max-w-5xl'}"
+>
+	<!-- eslint-disable-next-line svelte/no-at-html-tags -->
+	{@html text}
+</article>

+ 19 - 0
docs/site/src/routes/guide/vscode/+page.svelte

@@ -0,0 +1,19 @@
+<script lang="ts">
+	import { mdTextToHljs } from '../../../utils/index';
+	import { isWideScreenStore } from '../../../store';
+
+	import text from '../../../../../mds/guide/vscode.md';
+	import text_en from '../../../../../mds/guide/vscode_en.md';
+
+	const isZh = localStorage.getItem('lang') === 'zh_CN';
+	const hljsText = mdTextToHljs((isZh ? text : text_en).replace(/<a href="/g, '<a target="_blank" href="'));
+</script>
+
+<article
+	class="prose pb-12 dark:prose-invert prose-strong:text-primary dark:prose-strong:text-dark {$isWideScreenStore
+		? 'max-w-full'
+		: 'max-w-5xl'}"
+>
+	<!-- eslint-disable-next-line svelte/no-at-html-tags -->
+	{@html hljsText}
+</article>

+ 2 - 1
docs/site/src/store.js → docs/site/src/store.ts

@@ -1,5 +1,6 @@
 import { writable } from 'svelte/store';
 
+// 是否显示导航
 export const isShowNavStore = writable(false);
 // 文档 theme 模式,dark、light、auto。
 export const themeStore = writable(localStorage.getItem('theme') || 'auto');
@@ -13,7 +14,7 @@ const currentTheme =
 			: 'light'
 		: localStorage.getItem('theme') || 'auto';
 export const currentThemeStore = writable(currentTheme);
-// 是否开启cmdK
+// 是否开启 cmdK
 export const isCmdKStore = writable(false);
 // 是否显示赞赏
 export const isShowFundStore = writable(false);

文件差異過大導致無法顯示
+ 2 - 2
docs/site/src/utils/code-group-svg-data.js


部分文件因文件數量過多而無法顯示