@windrun-huaiin/third-ui 30.0.0 → 31.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/README.md +109 -143
  2. package/dist/ai/ai-prompt-textarea.js +5 -5
  3. package/dist/ai/ai-prompt-textarea.mjs +5 -5
  4. package/dist/clerk/clerk-auth-appearance.d.ts +13 -0
  5. package/dist/clerk/clerk-auth-appearance.js +19 -0
  6. package/dist/clerk/clerk-auth-appearance.mjs +15 -0
  7. package/dist/clerk/clerk-auth-modal-appearance.d.ts +12 -0
  8. package/dist/clerk/clerk-auth-modal-appearance.js +17 -0
  9. package/dist/clerk/clerk-auth-modal-appearance.mjs +14 -0
  10. package/dist/clerk/clerk-page-context-generator.js +3 -3
  11. package/dist/clerk/clerk-page-context-generator.mjs +3 -3
  12. package/dist/clerk/clerk-page-generator.js +4 -4
  13. package/dist/clerk/clerk-page-generator.mjs +4 -4
  14. package/dist/clerk/clerk-user-client.js +2 -1
  15. package/dist/clerk/clerk-user-client.mjs +2 -1
  16. package/dist/clerk/fingerprint/fingerprint-client.d.ts +10 -10
  17. package/dist/clerk/fingerprint/fingerprint-client.js +20 -20
  18. package/dist/clerk/fingerprint/fingerprint-client.mjs +20 -20
  19. package/dist/clerk/fingerprint/fingerprint-provider.d.ts +3 -3
  20. package/dist/clerk/fingerprint/fingerprint-provider.js +8 -8
  21. package/dist/clerk/fingerprint/fingerprint-provider.mjs +8 -8
  22. package/dist/clerk/fingerprint/fingerprint-server.d.ts +12 -12
  23. package/dist/clerk/fingerprint/fingerprint-server.js +17 -17
  24. package/dist/clerk/fingerprint/fingerprint-server.mjs +17 -17
  25. package/dist/clerk/fingerprint/fingerprint-shared.d.ts +3 -3
  26. package/dist/clerk/fingerprint/fingerprint-shared.js +10 -10
  27. package/dist/clerk/fingerprint/fingerprint-shared.mjs +10 -10
  28. package/dist/clerk/fingerprint/types.d.ts +0 -1
  29. package/dist/clerk/fingerprint/use-fingerprint.js +7 -7
  30. package/dist/clerk/fingerprint/use-fingerprint.mjs +7 -7
  31. package/dist/clerk/signin-with-fingerprint-client.d.ts +2 -2
  32. package/dist/clerk/signin-with-fingerprint-client.js +7 -6
  33. package/dist/clerk/signin-with-fingerprint-client.mjs +7 -6
  34. package/dist/clerk/signup-button-with-fingerprint-client.js +6 -4
  35. package/dist/clerk/signup-button-with-fingerprint-client.mjs +6 -4
  36. package/dist/clerk/signup-with-fingerprint-client.d.ts +2 -2
  37. package/dist/clerk/signup-with-fingerprint-client.js +7 -6
  38. package/dist/clerk/signup-with-fingerprint-client.mjs +7 -6
  39. package/dist/fuma/fuma-page-genarator.d.ts +2 -6
  40. package/dist/fuma/fuma-page-genarator.js +3 -2
  41. package/dist/fuma/fuma-page-genarator.mjs +3 -2
  42. package/dist/fuma/heavy/mermaid.js +1 -1
  43. package/dist/fuma/heavy/mermaid.mjs +1 -1
  44. package/dist/fuma/site-x.js +0 -1
  45. package/dist/fuma/site-x.mjs +0 -1
  46. package/dist/main/404-page.d.ts +12 -0
  47. package/dist/main/404-page.js +66 -0
  48. package/dist/main/404-page.mjs +64 -0
  49. package/dist/main/anime/anime-404-page.d.ts +14 -0
  50. package/dist/main/anime/anime-404-page.js +197 -0
  51. package/dist/main/anime/anime-404-page.mjs +195 -0
  52. package/dist/main/anime/anime-not-found-page.d.ts +7 -0
  53. package/dist/main/anime/anime-not-found-page.js +142 -0
  54. package/dist/main/anime/anime-not-found-page.mjs +140 -0
  55. package/dist/main/anime/index.d.ts +1 -0
  56. package/dist/main/anime/index.js +2 -0
  57. package/dist/main/anime/index.mjs +1 -0
  58. package/dist/main/calendar/calendar-date-range-input.js +1 -1
  59. package/dist/main/calendar/calendar-date-range-input.mjs +1 -1
  60. package/dist/main/credit/types.d.ts +8 -8
  61. package/dist/main/index.d.ts +1 -0
  62. package/dist/main/index.js +2 -0
  63. package/dist/main/index.mjs +1 -0
  64. package/dist/main/money-price/index.d.ts +1 -1
  65. package/dist/main/money-price/money-price-button.js +10 -10
  66. package/dist/main/money-price/money-price-button.mjs +10 -10
  67. package/dist/main/money-price/money-price-config-util.d.ts +30 -30
  68. package/dist/main/money-price/money-price-config-util.js +48 -48
  69. package/dist/main/money-price/money-price-config-util.mjs +48 -48
  70. package/dist/main/money-price/money-price-interactive.js +30 -18
  71. package/dist/main/money-price/money-price-interactive.mjs +30 -18
  72. package/dist/main/money-price/money-price-types.d.ts +7 -1
  73. package/dist/main/money-price/money-price-types.js +2 -2
  74. package/dist/main/money-price/money-price-types.mjs +2 -2
  75. package/dist/main/money-price/server.d.ts +1 -1
  76. package/dist/main/motion/creative-left-panel.d.ts +7 -0
  77. package/dist/main/motion/creative-left-panel.js +11 -0
  78. package/dist/main/motion/creative-left-panel.mjs +9 -0
  79. package/dist/main/motion/creative-right-panel.d.ts +7 -0
  80. package/dist/main/motion/creative-right-panel.js +11 -0
  81. package/dist/main/motion/creative-right-panel.mjs +9 -0
  82. package/dist/main/pill-select/x-pill-select.js +2 -2
  83. package/dist/main/pill-select/x-pill-select.mjs +2 -2
  84. package/dist/main/server.d.ts +1 -1
  85. package/dist/main/snake-loading-frame.js +1 -0
  86. package/dist/main/snake-loading-frame.mjs +1 -0
  87. package/package.json +13 -7
  88. package/src/ai/ai-prompt-textarea.tsx +6 -6
  89. package/src/clerk/clerk-auth-appearance.ts +16 -0
  90. package/src/clerk/clerk-page-context-generator.tsx +3 -5
  91. package/src/clerk/clerk-page-generator.tsx +9 -8
  92. package/src/clerk/clerk-user-client.tsx +14 -5
  93. package/src/clerk/fingerprint/fingerprint-client.ts +20 -20
  94. package/src/clerk/fingerprint/fingerprint-provider.tsx +11 -11
  95. package/src/clerk/fingerprint/fingerprint-server.ts +17 -17
  96. package/src/clerk/fingerprint/fingerprint-shared.ts +10 -10
  97. package/src/clerk/fingerprint/types.ts +0 -1
  98. package/src/clerk/fingerprint/use-fingerprint.ts +7 -7
  99. package/src/clerk/signin-with-fingerprint-client.tsx +7 -7
  100. package/src/clerk/signup-button-with-fingerprint-client.tsx +7 -5
  101. package/src/clerk/signup-with-fingerprint-client.tsx +7 -7
  102. package/src/fuma/base/custom-home-layout.tsx +4 -4
  103. package/src/fuma/fuma-page-genarator.tsx +2 -22
  104. package/src/fuma/heavy/mermaid.tsx +1 -1
  105. package/src/fuma/site-x.tsx +0 -1
  106. package/src/main/404-page.tsx +162 -0
  107. package/src/main/anime/anime-404-page.tsx +344 -0
  108. package/src/main/anime/index.ts +1 -0
  109. package/src/main/calendar/calendar-date-range-input.tsx +1 -1
  110. package/src/main/credit/types.ts +8 -8
  111. package/src/main/gallery/gallery-mobile-swiper.tsx +0 -1
  112. package/src/main/gallery/gallery-server.tsx +2 -2
  113. package/src/main/index.ts +1 -0
  114. package/src/main/money-price/index.ts +2 -0
  115. package/src/main/money-price/money-price-button.tsx +10 -10
  116. package/src/main/money-price/money-price-config-util.ts +49 -49
  117. package/src/main/money-price/money-price-interactive.tsx +40 -20
  118. package/src/main/money-price/money-price-types.ts +21 -14
  119. package/src/main/money-price/server.ts +2 -0
  120. package/src/main/pill-select/x-pill-select.tsx +2 -2
  121. package/src/main/server.ts +3 -1
  122. package/src/styles/third-ui.css +8 -0
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Fingerprint Client Utilities
3
- * 客户端专用的指纹生成和管理逻辑
4
- * 只能在浏览器环境中使用
3
+ * Client-only fingerprint generation and management logic.
4
+ * Must be used only in browser environments.
5
5
  */
6
6
 
7
7
  import FingerprintJS from '@fingerprintjs/fingerprintjs';
@@ -41,24 +41,24 @@ type FirstTouchData = {
41
41
  };
42
42
 
43
43
  /**
44
- * 检查浏览器存储(localStorage cookie)中的指纹 ID
45
- * 返回有效的 ID null
44
+ * Check fingerprint ID in browser storage, including localStorage and cookies.
45
+ * Returns a valid ID or null.
46
46
  */
47
47
  function checkStoredFingerprintId(): string | null {
48
48
  if (typeof window === 'undefined') {
49
49
  return null;
50
50
  }
51
51
 
52
- // 优先检查 localStorage
52
+ // Prefer localStorage.
53
53
  const localStorageId = getLocalStorageValue(FINGERPRINT_STORAGE_KEY);
54
54
  if (localStorageId && isValidFingerprintId(localStorageId)) {
55
55
  return localStorageId;
56
56
  }
57
57
 
58
- // 检查 cookie
58
+ // Check cookies.
59
59
  const cookieId = getCookieValue(FINGERPRINT_COOKIE_NAME);
60
60
  if (cookieId && isValidFingerprintId(cookieId)) {
61
- // 同步到 localStorage
61
+ // Sync back to localStorage.
62
62
  setLocalStorageValue(FINGERPRINT_STORAGE_KEY, cookieId);
63
63
  return cookieId;
64
64
  }
@@ -203,34 +203,34 @@ export function getOrCreateFirstTouchData(): FirstTouchData | null {
203
203
  }
204
204
 
205
205
  /**
206
- * 生成基于真实浏览器特征的fingerprint ID
207
- * 使用 FingerprintJS 收集浏览器特征并生成唯一标识
206
+ * Generate a fingerprint ID from real browser characteristics.
207
+ * Uses FingerprintJS to collect browser signals and create a stable identifier.
208
208
  */
209
209
  export async function generateFingerprintId(): Promise<string> {
210
210
  if (typeof window === 'undefined') {
211
211
  throw new Error('generateFingerprintId can only be used in browser environment');
212
212
  }
213
213
 
214
- // 检查现有 ID
214
+ // Check for an existing ID.
215
215
  const existingId = checkStoredFingerprintId();
216
216
  if (existingId) {
217
217
  return existingId;
218
218
  }
219
219
 
220
220
  try {
221
- // 使用 FingerprintJS 生成指纹
221
+ // Generate a fingerprint with FingerprintJS.
222
222
  const fp = await FingerprintJS.load();
223
223
  const result = await fp.get();
224
224
  const fingerprintId = `fp_${result.visitorId}`;
225
225
 
226
- // 存储到 localStorage cookie
226
+ // Store in localStorage and cookies.
227
227
  setLocalStorageValue(FINGERPRINT_STORAGE_KEY, fingerprintId);
228
228
  setCookie(FINGERPRINT_COOKIE_NAME, fingerprintId, 365);
229
229
 
230
230
  return fingerprintId;
231
231
  } catch (error) {
232
232
  console.warn('Failed to generate fingerprint with FingerprintJS:', error);
233
- // 降级方案:生成基于时间戳和随机数的 ID
233
+ // Fallback: generate an ID from timestamp and randomness.
234
234
  const fallbackId = `fp_fallback_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
235
235
  setLocalStorageValue(FINGERPRINT_STORAGE_KEY, fallbackId);
236
236
  setCookie(FINGERPRINT_COOKIE_NAME, fallbackId, 365);
@@ -240,14 +240,14 @@ export async function generateFingerprintId(): Promise<string> {
240
240
  }
241
241
 
242
242
  /**
243
- * 获取当前的fingerprint ID
243
+ * Get the current fingerprint ID.
244
244
  */
245
245
  export function getFingerprintId(): string | null {
246
246
  return checkStoredFingerprintId();
247
247
  }
248
248
 
249
249
  /**
250
- * 设置fingerprint ID到存储
250
+ * Store a fingerprint ID.
251
251
  */
252
252
  export function setFingerprintId(fingerprintId: string): void {
253
253
  if (typeof window === 'undefined') {
@@ -263,7 +263,7 @@ export function setFingerprintId(fingerprintId: string): void {
263
263
  }
264
264
 
265
265
  /**
266
- * 清除fingerprint ID
266
+ * Clear the fingerprint ID.
267
267
  */
268
268
  export function clearFingerprintId(): void {
269
269
  if (typeof window === 'undefined') {
@@ -275,8 +275,8 @@ export function clearFingerprintId(): void {
275
275
  }
276
276
 
277
277
  /**
278
- * 获取或生成fingerprint ID
279
- * 如果不存在则自动生成新的
278
+ * Get or generate a fingerprint ID.
279
+ * Automatically creates one when none exists.
280
280
  */
281
281
  export async function getOrGenerateFingerprintId(): Promise<string> {
282
282
  const existingId = checkStoredFingerprintId();
@@ -288,7 +288,7 @@ export async function getOrGenerateFingerprintId(): Promise<string> {
288
288
  }
289
289
 
290
290
  /**
291
- * 创建包含fingerprint ID的fetch headers
291
+ * Create fetch headers containing the fingerprint ID.
292
292
  */
293
293
  export async function createFingerprintHeaders(): Promise<Record<string, string>> {
294
294
  const fingerprintId = await getOrGenerateFingerprintId();
@@ -330,7 +330,7 @@ export function createFingerprintFetch() {
330
330
  };
331
331
  }
332
332
 
333
- // Cookie 辅助函数 (私有)
333
+ // Private cookie helpers.
334
334
  function getCookieValue(name: string): string | null {
335
335
  if (typeof document === 'undefined') {
336
336
  return null;
@@ -109,7 +109,7 @@ function useFingerprintStatusTranslations(): FingerprintStatusTranslations {
109
109
 
110
110
  /**
111
111
  * Fingerprint Provider Component
112
- * 为应用提供fingerprint和匿名用户管理功能
112
+ * Provides fingerprint and anonymous user management for the application.
113
113
  */
114
114
  export function FingerprintProvider({
115
115
  children,
@@ -137,7 +137,7 @@ export function useFingerprintContext(): FingerprintContextType {
137
137
 
138
138
  /**
139
139
  * Safe hook to use fingerprint context - returns null if no provider
140
- * 安全版本的fingerprint context hook - 如果没有Provider则返回null
140
+ * Returns null when no provider is available.
141
141
  */
142
142
  export function useFingerprintContextSafe(): FingerprintContextType | null {
143
143
  const context = useContext(FingerprintContext);
@@ -162,7 +162,7 @@ export function withFingerprint<P extends object>(
162
162
  }
163
163
 
164
164
  /**
165
- * 组件:显示用户状态和积分信息(用于调试)
165
+ * Component for displaying user status and credit information for debugging.
166
166
  */
167
167
  export function FingerprintStatus() {
168
168
  const translations = useFingerprintStatusTranslations();
@@ -400,7 +400,7 @@ export function FingerprintStatus() {
400
400
 
401
401
  return (
402
402
  <>
403
- {/* 灯泡按钮 */}
403
+ {/* Lightbulb button */}
404
404
  {!isOpen && (
405
405
  <button
406
406
  onClick={handleToggle}
@@ -417,7 +417,7 @@ export function FingerprintStatus() {
417
417
  </button>
418
418
  )}
419
419
 
420
- {/* 面板 */}
420
+ {/* Panel */}
421
421
  {isOpen && (
422
422
  <>
423
423
  <div onClick={handleBackdropClick} className="fixed inset-0 z-9998 bg-black/60 backdrop-blur-sm" />
@@ -622,9 +622,9 @@ export function FingerprintStatus() {
622
622
  }
623
623
 
624
624
 
625
- /* ==================== 新增辅助组件 ==================== */
625
+ /* ==================== Helper Components ==================== */
626
626
 
627
- // 标题行:左侧图标+标题,右侧信息(右对齐)
627
+ // Header row with icon and title on the left, right-aligned metadata on the right.
628
628
  function PanelHeader({ icon, title, rightInfo }: { icon: React.ReactNode; title: string; rightInfo: React.ReactNode }) {
629
629
  return (
630
630
  <div className="flex items-center justify-between mb-3">
@@ -643,7 +643,7 @@ function PanelHeader({ icon, title, rightInfo }: { icon: React.ReactNode; title:
643
643
  );
644
644
  }
645
645
 
646
- // 复用:普通 PanelSection 支持右侧信息
646
+ // Reusable PanelSection with optional right-side metadata.
647
647
  interface PanelSectionProps {
648
648
  icon: React.ReactNode;
649
649
  title: string;
@@ -727,19 +727,19 @@ function StatusTag({
727
727
  const normalized = value.toLowerCase();
728
728
 
729
729
  const colorMap: Record<string, string> = {
730
- // 绿色:正常/活跃
730
+ // Green: normal or active.
731
731
  registered: 'bg-green-100 text-green-700 dark:bg-green-500/20 dark:text-green-300',
732
732
  active: 'bg-green-100 text-green-700 dark:bg-green-500/20 dark:text-green-300',
733
733
  trialing: 'bg-green-100 text-green-700 dark:bg-green-500/20 dark:text-green-300',
734
734
 
735
- // 灰色:失效/删除
735
+ // Gray: inactive or deleted.
736
736
  canceled: 'bg-slate-100 text-slate-600 dark:bg-slate-700 dark:text-slate-400',
737
737
  frozen: 'bg-slate-100 text-slate-600 dark:bg-slate-700 dark:text-slate-400',
738
738
  deleted: 'bg-slate-100 text-slate-600 dark:bg-slate-700 dark:text-slate-400',
739
739
  expired: 'bg-slate-100 text-slate-600 dark:bg-slate-700 dark:text-slate-400',
740
740
  past_due: 'bg-slate-100 text-slate-600 dark:bg-slate-700 dark:text-slate-400',
741
741
 
742
- // 橙色:待处理/异常
742
+ // Amber: pending or exceptional states.
743
743
  pending: 'bg-amber-100 text-amber-700 dark:bg-amber-500/20 dark:text-amber-300',
744
744
  failed: 'bg-amber-100 text-amber-700 dark:bg-amber-500/20 dark:text-amber-300',
745
745
  unpaid: 'bg-amber-100 text-amber-700 dark:bg-amber-500/20 dark:text-amber-300',
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Fingerprint Server Utilities
3
- * 服务端专用的指纹ID提取和验证逻辑
4
- * 可以安全地在服务端使用,不依赖浏览器API或FingerprintJS
3
+ * Server-only fingerprint ID extraction and validation logic.
4
+ * Safe for server usage without browser APIs or FingerprintJS.
5
5
  */
6
6
 
7
7
  import {
@@ -11,16 +11,16 @@ import {
11
11
  } from './fingerprint-shared';
12
12
 
13
13
  /**
14
- * 从请求中提取fingerprint ID
15
- * 优先级:header > cookie > query参数
16
- * 可以安全地在服务端使用
14
+ * Extract fingerprint ID from a request.
15
+ * Priority: header > cookie > query parameter.
16
+ * Safe to use on the server.
17
17
  */
18
18
  export function extractFingerprintId(
19
19
  headers: Headers | Record<string, string>,
20
20
  cookies?: Record<string, string>,
21
21
  query?: Record<string, string | undefined>
22
22
  ): string | null {
23
- // 1. header中获取
23
+ // 1. Read from header.
24
24
  const headerValue = headers instanceof Headers
25
25
  ? headers.get(FINGERPRINT_HEADER_NAME)
26
26
  : headers[FINGERPRINT_HEADER_NAME];
@@ -29,7 +29,7 @@ export function extractFingerprintId(
29
29
  return headerValue;
30
30
  }
31
31
 
32
- // 2. cookie中获取
32
+ // 2. Read from cookie.
33
33
  if (cookies) {
34
34
  const cookieValue = cookies[FINGERPRINT_COOKIE_NAME];
35
35
  if (cookieValue && isValidFingerprintId(cookieValue)) {
@@ -37,7 +37,7 @@ export function extractFingerprintId(
37
37
  }
38
38
  }
39
39
 
40
- // 3. query参数中获取
40
+ // 3. Read from query parameters.
41
41
  if (query) {
42
42
  const queryValue = query.fingerprint_id || query.fp_id;
43
43
  if (queryValue && isValidFingerprintId(queryValue)) {
@@ -49,22 +49,22 @@ export function extractFingerprintId(
49
49
  }
50
50
 
51
51
  /**
52
- * 生成服务端降级fingerprint ID
53
- * 当客户端无法生成fingerprint时使用
54
- * 可以安全地在服务端使用
52
+ * Generate a server-side fallback fingerprint ID.
53
+ * Used when the client cannot generate a fingerprint.
54
+ * Safe to use on the server.
55
55
  */
56
56
  export function generateServerFingerprintId(): string {
57
57
  return `fp_server_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
58
58
  }
59
59
 
60
60
  /**
61
- * Next.js Request对象中提取fingerprint ID
62
- * 便捷方法,适用于Next.js API路由
61
+ * Extract fingerprint ID from a Next.js Request object.
62
+ * Convenience helper for Next.js API routes.
63
63
  */
64
64
  export function extractFingerprintFromNextRequest(request: Request): string | null {
65
65
  const headers = request.headers;
66
66
 
67
- // 尝试从cookies获取(需要解析cookie header
67
+ // Try cookies by parsing the cookie header.
68
68
  const cookieHeader = headers.get('cookie');
69
69
  const cookies: Record<string, string> = {};
70
70
 
@@ -77,7 +77,7 @@ export function extractFingerprintFromNextRequest(request: Request): string | nu
77
77
  });
78
78
  }
79
79
 
80
- // 尝试从URL query参数获取
80
+ // Try URL query parameters.
81
81
  const url = new URL(request.url);
82
82
  const query: Record<string, string> = {};
83
83
  url.searchParams.forEach((value, key) => {
@@ -93,8 +93,8 @@ type NextCookiesLike = {
93
93
  };
94
94
 
95
95
  /**
96
- * Next.js runtime提供的headers/cookies实例里提取fingerprint ID
97
- * App Router服务端组件和Server Actions直接复用
96
+ * Extract fingerprint ID from Next.js runtime headers/cookies stores.
97
+ * Reusable in App Router server components and Server Actions.
98
98
  */
99
99
  export function extractFingerprintFromNextStores(params: {
100
100
  headers: NextHeadersLike;
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Fingerprint Shared Utilities
3
- * 客户端和服务端共享的常量、类型和验证逻辑
3
+ * Shared constants, types, and validation logic for client and server.
4
4
  */
5
5
 
6
- // Fingerprint ID的存储键和header
6
+ // Storage keys and header names for fingerprint IDs.
7
7
  export const FINGERPRINT_STORAGE_KEY = '__x_fingerprint_id';
8
8
  export const FINGERPRINT_DEBUG_OVERRIDE_STORAGE_KEY = '__x_fingerprint_debug_override';
9
9
  export const FINGERPRINT_HEADER_NAME = 'x-fingerprint-id-v8';
@@ -15,16 +15,16 @@ export const FINGERPRINT_FIRST_TOUCH_HEADER = 'x-first-touch';
15
15
  export const FINGERPRINT_DEBUG_PREFIX = 'fp_test_dbg_';
16
16
 
17
17
  /**
18
- * 验证fingerprint ID格式
19
- * 可以在客户端和服务端使用
18
+ * Validate fingerprint ID format.
19
+ * Safe to use on both client and server.
20
20
  */
21
21
  export function isValidFingerprintId(fingerprintId: string): boolean {
22
22
  if (!fingerprintId) return false;
23
- // 支持多种格式:
24
- // - fp_ + FingerprintJS visitorId (变长字符串)
25
- // - fp_fallback_ + 时间戳_随机字符串 (客户端降级方案)
26
- // - fp_server_ + 时间戳_随机字符串 (服务端降级)
27
- // - fp_test_dbg_ + 时间戳_随机字符串 (调试并发测试)
23
+ // Supported formats:
24
+ // - fp_ + FingerprintJS visitorId with variable length.
25
+ // - fp_fallback_ + timestamp + random string for client fallback.
26
+ // - fp_server_ + timestamp + random string for server fallback.
27
+ // - fp_test_dbg_ + timestamp + random string for debug concurrency tests.
28
28
  return /^fp(_fallback|_server|_test_dbg)?_[a-zA-Z0-9_]+$/.test(fingerprintId);
29
29
  }
30
30
 
@@ -36,7 +36,7 @@ export function isDebugFingerprintId(fingerprintId: string | null | undefined):
36
36
  return fingerprintId.startsWith(FINGERPRINT_DEBUG_PREFIX);
37
37
  }
38
38
 
39
- // 常量导出
39
+ // Exported constants.
40
40
  export const FINGERPRINT_CONSTANTS = {
41
41
  STORAGE_KEY: FINGERPRINT_STORAGE_KEY,
42
42
  DEBUG_OVERRIDE_STORAGE_KEY: FINGERPRINT_DEBUG_OVERRIDE_STORAGE_KEY,
@@ -1,6 +1,5 @@
1
1
  /**
2
2
  * Fingerprint System Types
3
- * 指纹识别系统的类型定义
4
3
  */
5
4
 
6
5
  export interface XUser {
@@ -21,7 +21,7 @@ import { FINGERPRINT_SOURCE_REFER, isDebugFingerprintId, isValidFingerprintId }
21
21
  * Accepts configuration to customize API endpoint and behavior
22
22
  */
23
23
  export function useFingerprint(config: FingerprintConfig): UseFingerprintResult {
24
- // 服务端渲染检查
24
+ // Server-side rendering guard.
25
25
  if (typeof window === 'undefined') {
26
26
  return {
27
27
  fingerprintId: null,
@@ -51,7 +51,7 @@ export function useFingerprint(config: FingerprintConfig): UseFingerprintResult
51
51
  }, []);
52
52
 
53
53
  /**
54
- * 第一阶段:初始化fingerprint ID
54
+ * Phase 1: initialize fingerprint ID.
55
55
  */
56
56
  const initializeFingerprintId = useCallback(async () => {
57
57
  try {
@@ -68,7 +68,7 @@ export function useFingerprint(config: FingerprintConfig): UseFingerprintResult
68
68
  }, []);
69
69
 
70
70
  /**
71
- * 第二阶段:初始化匿名用户
71
+ * Phase 2: initialize anonymous user.
72
72
  */
73
73
  const initializeAnonymousUser = useCallback(async () => {
74
74
  if (!fingerprintId) {
@@ -140,7 +140,7 @@ export function useFingerprint(config: FingerprintConfig): UseFingerprintResult
140
140
  }, [fingerprintId, config.apiEndpoint, isInitialized]);
141
141
 
142
142
  /**
143
- * 刷新用户数据 - 使用POST请求(后端支持upsert逻辑)
143
+ * Refresh user data with a POST request; the backend supports upsert semantics.
144
144
  */
145
145
  const refreshUserData = useCallback(async () => {
146
146
  if (!fingerprintId) {
@@ -180,7 +180,7 @@ export function useFingerprint(config: FingerprintConfig): UseFingerprintResult
180
180
  }
181
181
  }, [fingerprintId, config.apiEndpoint]);
182
182
 
183
- // 第一阶段:页面加载完成后生成指纹ID
183
+ // Phase 1: generate fingerprint ID after page load.
184
184
  useEffect(() => {
185
185
  const initFingerprint = async () => {
186
186
  setIsLoading(true);
@@ -191,11 +191,11 @@ export function useFingerprint(config: FingerprintConfig): UseFingerprintResult
191
191
  initFingerprint();
192
192
  }, [initializeFingerprintId]);
193
193
 
194
- // 第二阶段:有指纹ID后直接初始化用户(后端支持upsert逻辑)
194
+ // Phase 2: initialize the user once a fingerprint ID is available; the backend supports upsert semantics.
195
195
  useEffect(() => {
196
196
  if (!fingerprintId || isInitialized || isLoading || error || config.autoInitialize === false) return;
197
197
 
198
- // 直接使用 POST 请求,后端会处理查询-不存在则创建的逻辑
198
+ // Use POST directly; the backend handles lookup and create-if-missing behavior.
199
199
  initializeAnonymousUser();
200
200
  }, [fingerprintId, isInitialized, isLoading, error, initializeAnonymousUser, config.autoInitialize]);
201
201
 
@@ -2,17 +2,18 @@
2
2
 
3
3
  import { SignIn } from '@clerk/nextjs';
4
4
  import { useEffect } from 'react';
5
+ import { clerkAuthPageAppearance } from './clerk-auth-appearance';
5
6
  import { useFingerprintContextSafe } from './fingerprint/fingerprint-provider';
6
7
 
7
8
  /**
8
9
  * SignIn component with fingerprint awareness
9
- * 如果没有FingerprintProvider,会优雅降级为普通SignIn组件
10
- * 如果有FingerprintProvider,会处理fingerprint相关逻辑
10
+ * Falls back to the standard SignIn component when FingerprintProvider is absent.
11
+ * Handles fingerprint-related metadata when FingerprintProvider is available.
11
12
  */
12
13
  export function SignInWithFingerprint() {
13
14
  const fingerprintContext = useFingerprintContextSafe();
14
15
 
15
- // 如果没有fingerprint context,使用默认值
16
+ // Use defaults when fingerprint context is unavailable.
16
17
  const {
17
18
  fingerprintId = null,
18
19
  xUser = null,
@@ -20,19 +21,18 @@ export function SignInWithFingerprint() {
20
21
  initializeAnonymousUser = async () => {}
21
22
  } = fingerprintContext || {};
22
23
 
23
- // 准备传递给Clerkmetadata,包含匿名用户信息
24
+ // Prepare Clerk metadata with anonymous user information.
24
25
  const unsafeMetadata = {
25
26
  user_id: xUser?.userId || null,
26
27
  fingerprint_id: fingerprintId || null,
27
28
  };
28
29
 
29
- // 确保匿名用户已初始化
30
+ // Ensure the anonymous user has been initialized.
30
31
  useEffect(() => {
31
32
  if (!isInitialized && fingerprintId) {
32
33
  initializeAnonymousUser();
33
34
  }
34
35
  }, [fingerprintId, isInitialized, initializeAnonymousUser]);
35
36
 
36
- return <SignIn unsafeMetadata={unsafeMetadata} />;
37
+ return <SignIn appearance={clerkAuthPageAppearance} unsafeMetadata={unsafeMetadata} />;
37
38
  }
38
-
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { SignUpButton, useClerk } from '@clerk/nextjs';
4
4
  import { useEffect } from 'react';
5
+ import { clerkAuthModalAppearance } from './clerk-auth-appearance';
5
6
  import { useFingerprintContextSafe } from './fingerprint/fingerprint-provider';
6
7
 
7
8
  interface SignUpButtonWithFingerprintProps {
@@ -15,7 +16,7 @@ export function SignUpButtonWithFingerprint({
15
16
  }: SignUpButtonWithFingerprintProps) {
16
17
  if (mode === 'redirect') {
17
18
  return (
18
- // 重定向模式则直接跳转到自定义注册页面
19
+ // Redirect mode navigates directly to the custom sign-up page.
19
20
  <SignUpButton>
20
21
  <button
21
22
  className="w-16 sm:w-20 h-8 sm:h-9 px-1.5 sm:px-2 border border-gray-300 rounded-full hover:bg-gray-100 dark:border-gray-600 dark:hover:bg-gray-800 text-center text-xs sm:text-sm whitespace-nowrap"
@@ -26,10 +27,10 @@ export function SignUpButtonWithFingerprint({
26
27
  )
27
28
  }
28
29
 
29
- // 弹框模式则需要自定义注册按钮
30
+ // Modal mode requires a custom sign-up button.
30
31
  const fingerprintContext = useFingerprintContextSafe();
31
32
 
32
- // 如果没有fingerprint context,使用默认值
33
+ // Use defaults when fingerprint context is unavailable.
33
34
  const {
34
35
  fingerprintId = null,
35
36
  xUser = null,
@@ -43,7 +44,7 @@ export function SignUpButtonWithFingerprint({
43
44
  fingerprint_id: fingerprintId || null,
44
45
  };
45
46
 
46
- // 确保匿名用户已初始化
47
+ // Ensure the anonymous user has been initialized.
47
48
  useEffect(() => {
48
49
  if (!isInitialized && fingerprintId) {
49
50
  initializeAnonymousUser();
@@ -55,6 +56,7 @@ export function SignUpButtonWithFingerprint({
55
56
 
56
57
  const handleClick = () => {
57
58
  openSignUp({
59
+ appearance: clerkAuthModalAppearance,
58
60
  unsafeMetadata,
59
61
  });
60
62
  };
@@ -67,4 +69,4 @@ export function SignUpButtonWithFingerprint({
67
69
  {signUp}
68
70
  </button>
69
71
  );
70
- }
72
+ }
@@ -2,17 +2,18 @@
2
2
 
3
3
  import { SignUp } from '@clerk/nextjs';
4
4
  import { useEffect } from 'react';
5
+ import { clerkAuthPageAppearance } from './clerk-auth-appearance';
5
6
  import { useFingerprintContextSafe } from './fingerprint/fingerprint-provider';
6
7
 
7
8
  /**
8
9
  * SignUp component with fingerprint awareness
9
- * 如果没有FingerprintProvider,会优雅降级为普通SignUp组件
10
- * 如果有FingerprintProvider,会处理fingerprint相关逻辑
10
+ * Falls back to the standard SignUp component when FingerprintProvider is absent.
11
+ * Handles fingerprint-related metadata when FingerprintProvider is available.
11
12
  */
12
13
  export function SignUpWithFingerprint() {
13
14
  const fingerprintContext = useFingerprintContextSafe();
14
15
 
15
- // 如果没有fingerprint context,使用默认值
16
+ // Use defaults when fingerprint context is unavailable.
16
17
  const {
17
18
  fingerprintId = null,
18
19
  xUser = null,
@@ -20,19 +21,18 @@ export function SignUpWithFingerprint() {
20
21
  initializeAnonymousUser = async () => {}
21
22
  } = fingerprintContext || {};
22
23
 
23
- // 准备传递给Clerkmetadata,包含匿名用户信息
24
+ // Prepare Clerk metadata with anonymous user information.
24
25
  const unsafeMetadata = {
25
26
  user_id: xUser?.userId || null,
26
27
  fingerprint_id: fingerprintId || null,
27
28
  };
28
29
 
29
- // 确保匿名用户已初始化
30
+ // Ensure the anonymous user has been initialized.
30
31
  useEffect(() => {
31
32
  if (!isInitialized && fingerprintId) {
32
33
  initializeAnonymousUser();
33
34
  }
34
35
  }, [fingerprintId, isInitialized, initializeAnonymousUser]);
35
36
 
36
- return <SignUp unsafeMetadata={unsafeMetadata} />;
37
+ return <SignUp appearance={clerkAuthPageAppearance} unsafeMetadata={unsafeMetadata} />;
37
38
  }
38
-
@@ -11,10 +11,10 @@ import {
11
11
  type MobileMenuAction,
12
12
  } from './custom-header';
13
13
 
14
- // - bannerHeight/headerHeight 换成你项目期望的 rem 值即可(如果没有 Banner 就把 bannerHeight 设成 0)。
15
- // - layoutStyle 同时把变量传给 HomeLayout main 元素,这样内容整体会往下错开,不需要 has-banner/no-banner class。
16
- // - CustomHomeHeader 直接接受 HomeLayout 的各类 props(linksnavsearchTogglethemeSwitchi18n 等),内部会复用 Fumadocs 原本的导航功能。
17
- // - Banner 部分仍然可以用你现有的 FumaBannerSuit(或者任何自定义 Banner 组件),因为 Header 是固定定位、z-index 也处理好了,开关只影响 bannerHeight
14
+ // - Set bannerHeight/headerHeight to the rem values expected by the project. Use bannerHeight = 0 when there is no banner.
15
+ // - layoutStyle passes the variables to HomeLayout's main element, offsetting content without has-banner/no-banner classes.
16
+ // - CustomHomeHeader accepts HomeLayout props such as links, nav, searchToggle, themeSwitch, and i18n, then reuses Fumadocs navigation behavior.
17
+ // - The banner can still use FumaBannerSuit or any custom banner component. Header positioning and z-index are already handled; the toggle only affects bannerHeight.
18
18
 
19
19
  export interface CustomHomeLayoutProps {
20
20
  locale: string;
@@ -3,6 +3,7 @@ import { ReactNode, ReactElement, cloneElement, type CSSProperties } from 'react
3
3
  import { TocFooterWrapper } from './mdx/toc-footer-wrapper';
4
4
  import type { LLMCopyButtonProps, LLMCopyButton } from './mdx/toc-base';
5
5
  import { getAsNeededLocalizedUrl } from '@windrun-huaiin/lib/utils';
6
+ import { notFound } from 'next/navigation';
6
7
  import { PortableClerkTOC, PortableClerkTOCTitle } from './mdx/toc-clerk-portable';
7
8
  import { themeSvgIconColor } from '@windrun-huaiin/base-ui/lib';
8
9
 
@@ -36,14 +37,6 @@ interface FumaPageParams {
36
37
  * The copy button component, must be LLMCopyButton
37
38
  */
38
39
  copyButtonComponent?: ReactElement<LLMCopyButtonProps, typeof LLMCopyButton>;
39
- /*
40
- * The site icon component to use in NotFoundPage
41
- */
42
- siteIcon: ReactNode;
43
- /*
44
- * The fallback page component to use when the page is not found
45
- */
46
- FallbackPage: React.ComponentType<{ siteIcon: ReactNode }>;
47
40
  /*
48
41
  * Supported locales for generating alternates metadata, defaults to ['en']
49
42
  */
@@ -89,8 +82,6 @@ export function createFumaPage({
89
82
  mdxSourceDir,
90
83
  githubBaseUrl,
91
84
  copyButtonComponent,
92
- siteIcon,
93
- FallbackPage,
94
85
  supportedLocales = ['en'],
95
86
  showBreadcrumb = true,
96
87
  showTableOfContent = true,
@@ -138,18 +129,7 @@ export function createFumaPage({
138
129
  totalElapsedMs: durationMs(pageStartedAt),
139
130
  });
140
131
  if (!page) {
141
- return (
142
- <DocsPage
143
- full
144
- breadcrumb={{ enabled: false }}
145
- footer={{ enabled: false }}
146
- tableOfContent={{ enabled: false }}
147
- tableOfContentPopover={{ enabled: false }}
148
- className="max-w-none px-0 py-0"
149
- >
150
- <FallbackPage siteIcon={siteIcon} />
151
- </DocsPage>
152
- );
132
+ notFound();
153
133
  }
154
134
 
155
135
  const path = githubBaseUrl ? `${mdxSourceDir}/${page.path}` : undefined;
@@ -179,7 +179,7 @@ export function Mermaid({ chart, title, watermarkEnabled, watermarkText, handDra
179
179
  // prevent browser-level zoom (touchpad pinch/shortcut) from taking effect when the dialog is open
180
180
  useEffect(() => {
181
181
  if (!open) return;
182
- // 初次打开时,默认放大到 400%
182
+ // Init default zoom out 400%
183
183
  resetTransform();
184
184
  const onGlobalWheel = (ev: WheelEvent) => {
185
185
  if (ev.ctrlKey || ev.metaKey) {
@@ -10,7 +10,6 @@ export type SiteXProps = Omit<HTMLAttributes<HTMLSpanElement>, 'type'> & {
10
10
  };
11
11
 
12
12
  export async function SiteX({ locale, type, namespace, tKey, className, ...props }: SiteXProps) {
13
- // 默认命名空间和key
14
13
  let ns = namespace;
15
14
  let key = tKey;
16
15
  if (!ns) {