@windrun-huaiin/third-ui 25.0.0 → 27.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 (173) hide show
  1. package/dist/ai/ai-prompt-textarea.d.ts +72 -0
  2. package/dist/ai/ai-prompt-textarea.js +114 -0
  3. package/dist/ai/ai-prompt-textarea.mjs +112 -0
  4. package/dist/ai/index.d.ts +1 -0
  5. package/dist/ai/index.js +2 -0
  6. package/dist/ai/index.mjs +1 -0
  7. package/dist/clerk/clerk-provider-client.js +0 -1
  8. package/dist/clerk/clerk-provider-client.mjs +0 -1
  9. package/dist/clerk/fingerprint/fingerprint-client.js +0 -4
  10. package/dist/clerk/fingerprint/fingerprint-client.mjs +0 -4
  11. package/dist/clerk/fingerprint/use-fingerprint.js +0 -6
  12. package/dist/clerk/fingerprint/use-fingerprint.mjs +0 -6
  13. package/dist/clerk/signin-with-fingerprint-client.js +0 -9
  14. package/dist/clerk/signin-with-fingerprint-client.mjs +0 -9
  15. package/dist/clerk/signup-button-with-fingerprint-client.js +0 -16
  16. package/dist/clerk/signup-button-with-fingerprint-client.mjs +0 -16
  17. package/dist/clerk/signup-with-fingerprint-client.js +0 -9
  18. package/dist/clerk/signup-with-fingerprint-client.mjs +0 -9
  19. package/dist/fuma/base/custom-header.js +10 -8
  20. package/dist/fuma/base/custom-header.mjs +10 -8
  21. package/dist/fuma/base/custom-home-layout.d.ts +1 -0
  22. package/dist/fuma/base/index.d.ts +1 -0
  23. package/dist/fuma/base/index.js +4 -0
  24. package/dist/fuma/base/index.mjs +1 -0
  25. package/dist/fuma/base/nav-config.d.ts +10 -0
  26. package/dist/fuma/base/nav-config.js +32 -0
  27. package/dist/fuma/base/nav-config.mjs +28 -0
  28. package/dist/fuma/base/site-layout.d.ts +4 -0
  29. package/dist/fuma/base/site-layout.js +2 -2
  30. package/dist/fuma/base/site-layout.mjs +2 -2
  31. package/dist/fuma/fuma-page-genarator.d.ts +1 -1
  32. package/dist/fuma/fuma-page-genarator.js +60 -5
  33. package/dist/fuma/fuma-page-genarator.mjs +60 -5
  34. package/dist/fuma/llm-copy-handler.js +0 -9
  35. package/dist/fuma/llm-copy-handler.mjs +0 -9
  36. package/dist/fuma/mdx/index.d.ts +0 -1
  37. package/dist/fuma/mdx/index.js +0 -2
  38. package/dist/fuma/mdx/index.mjs +0 -1
  39. package/dist/fuma/mdx/suno-embed.js +3 -1
  40. package/dist/fuma/mdx/suno-embed.mjs +3 -1
  41. package/dist/fuma/mdx/toc-base.js +0 -1
  42. package/dist/fuma/mdx/toc-base.mjs +0 -1
  43. package/dist/fuma/server/features/widgets.js +5 -1
  44. package/dist/fuma/server/features/widgets.mjs +5 -1
  45. package/dist/lib/site-docs-helper.d.ts +51 -0
  46. package/dist/lib/site-docs-helper.js +68 -0
  47. package/dist/lib/site-docs-helper.mjs +66 -0
  48. package/dist/main/alert-dialog/index.js +14 -0
  49. package/dist/main/alert-dialog/index.mjs +5 -0
  50. package/dist/main/buttons/gradient-button.d.ts +20 -0
  51. package/dist/main/buttons/gradient-button.js +88 -0
  52. package/dist/main/buttons/gradient-button.mjs +86 -0
  53. package/dist/main/buttons/index.d.ts +3 -0
  54. package/dist/main/buttons/index.js +12 -0
  55. package/dist/main/buttons/index.mjs +4 -0
  56. package/dist/main/buttons/x-button.d.ts +39 -0
  57. package/dist/main/buttons/x-button.js +92 -0
  58. package/dist/main/buttons/x-button.mjs +90 -0
  59. package/dist/main/buttons/x-toggle-button.d.ts +32 -0
  60. package/dist/main/buttons/x-toggle-button.js +95 -0
  61. package/dist/main/buttons/x-toggle-button.mjs +74 -0
  62. package/dist/main/credit/credit-overview-client.js +3 -2
  63. package/dist/main/credit/credit-overview-client.mjs +3 -2
  64. package/dist/main/credit/index.d.ts +4 -0
  65. package/dist/main/credit/index.js +10 -0
  66. package/dist/main/credit/index.mjs +3 -0
  67. package/dist/main/credit/server.d.ts +2 -0
  68. package/dist/main/credit/server.js +7 -0
  69. package/dist/main/credit/server.mjs +1 -0
  70. package/dist/main/cta.js +4 -2
  71. package/dist/main/cta.mjs +4 -2
  72. package/dist/main/hero/index.d.ts +2 -0
  73. package/dist/main/hero/index.js +10 -0
  74. package/dist/main/hero/index.mjs +3 -0
  75. package/dist/main/home/server.d.ts +7 -0
  76. package/dist/main/home/server.js +19 -0
  77. package/dist/main/home/server.mjs +7 -0
  78. package/dist/main/index.d.ts +0 -15
  79. package/dist/main/index.js +0 -43
  80. package/dist/main/index.mjs +0 -21
  81. package/dist/main/loading/index.d.ts +1 -0
  82. package/dist/main/loading/index.js +9 -0
  83. package/dist/main/loading/index.mjs +2 -0
  84. package/dist/main/loading-frame/index.d.ts +1 -0
  85. package/dist/main/loading-frame/index.js +9 -0
  86. package/dist/main/loading-frame/index.mjs +2 -0
  87. package/dist/main/money-price/index.d.ts +4 -0
  88. package/dist/main/money-price/index.js +15 -0
  89. package/dist/main/money-price/index.mjs +4 -0
  90. package/dist/main/money-price/money-price-button.d.ts +1 -1
  91. package/dist/main/money-price/money-price-button.js +10 -7
  92. package/dist/main/money-price/money-price-button.mjs +10 -7
  93. package/dist/main/money-price/money-price-interactive.js +9 -8
  94. package/dist/main/money-price/money-price-interactive.mjs +9 -8
  95. package/dist/main/money-price/money-price-types.d.ts +1 -0
  96. package/dist/main/money-price/server.d.ts +5 -0
  97. package/dist/main/money-price/server.js +18 -0
  98. package/dist/main/money-price/server.mjs +4 -0
  99. package/package.json +54 -4
  100. package/src/ai/index.ts +1 -0
  101. package/src/clerk/clerk-provider-client.tsx +1 -3
  102. package/src/clerk/fingerprint/fingerprint-client.ts +0 -4
  103. package/src/clerk/fingerprint/use-fingerprint.ts +0 -6
  104. package/src/clerk/signin-with-fingerprint-client.tsx +0 -10
  105. package/src/clerk/signup-button-with-fingerprint-client.tsx +0 -17
  106. package/src/clerk/signup-with-fingerprint-client.tsx +0 -10
  107. package/src/fuma/base/custom-header.tsx +12 -8
  108. package/src/fuma/base/custom-home-layout.tsx +7 -4
  109. package/src/fuma/base/index.ts +1 -0
  110. package/src/fuma/base/nav-config.ts +81 -0
  111. package/src/fuma/base/site-layout.tsx +6 -0
  112. package/src/fuma/fuma-banner-suit.tsx +1 -1
  113. package/src/fuma/fuma-page-genarator.tsx +60 -7
  114. package/src/fuma/llm-copy-handler.ts +0 -11
  115. package/src/fuma/mdx/index.ts +0 -1
  116. package/src/fuma/mdx/suno-embed.tsx +1 -1
  117. package/src/fuma/mdx/toc-base.tsx +0 -1
  118. package/src/fuma/mdx/toc-footer-wrapper.tsx +2 -2
  119. package/src/fuma/server/features/widgets.tsx +1 -1
  120. package/src/lib/server.ts +1 -1
  121. package/src/{fuma/mdx → main/buttons}/gradient-button.tsx +10 -21
  122. package/src/main/buttons/index.ts +5 -0
  123. package/src/main/{x-button.tsx → buttons/x-button.tsx} +28 -42
  124. package/src/main/credit/credit-overview-client.tsx +1 -1
  125. package/src/main/credit/index.ts +11 -0
  126. package/src/main/credit/server.ts +7 -0
  127. package/src/main/cta.tsx +1 -1
  128. package/src/main/hero/index.ts +4 -0
  129. package/src/main/home/server.ts +7 -0
  130. package/src/main/index.ts +1 -20
  131. package/src/main/language-detector.tsx +0 -1
  132. package/src/main/loading/index.ts +3 -0
  133. package/src/main/loading-frame/index.ts +3 -0
  134. package/src/main/money-price/index.ts +18 -0
  135. package/src/main/money-price/money-price-button.tsx +12 -6
  136. package/src/main/money-price/money-price-interactive.tsx +17 -10
  137. package/src/main/money-price/money-price-types.ts +1 -0
  138. package/src/main/money-price/server.ts +22 -0
  139. package/dist/fuma/mdx/features.d.ts +0 -8
  140. package/dist/fuma/mdx/features.js +0 -92
  141. package/dist/fuma/mdx/features.mjs +0 -85
  142. package/dist/fuma/mdx/image-grid.d.ts +0 -6
  143. package/dist/fuma/mdx/image-grid.js +0 -17
  144. package/dist/fuma/mdx/image-grid.mjs +0 -15
  145. package/dist/fuma/mdx/image-zoom.d.ts +0 -22
  146. package/dist/fuma/mdx/image-zoom.js +0 -39
  147. package/dist/fuma/mdx/image-zoom.mjs +0 -37
  148. package/dist/fuma/mdx/markdown-component-map.d.ts +0 -3
  149. package/dist/fuma/mdx/markdown-component-map.js +0 -79
  150. package/dist/fuma/mdx/markdown-component-map.mjs +0 -77
  151. package/dist/fuma/mdx/math.d.ts +0 -17
  152. package/dist/fuma/mdx/math.js +0 -60
  153. package/dist/fuma/mdx/math.mjs +0 -57
  154. package/dist/fuma/mdx/mermaid.d.ts +0 -13
  155. package/dist/fuma/mdx/mermaid.js +0 -360
  156. package/dist/fuma/mdx/mermaid.mjs +0 -358
  157. package/dist/fuma/mdx/site-mdx-components.d.ts +0 -13
  158. package/dist/fuma/mdx/site-mdx-components.js +0 -19
  159. package/dist/fuma/mdx/site-mdx-components.mjs +0 -17
  160. package/dist/fuma/mdx/site-mdx-presets.d.ts +0 -13
  161. package/dist/fuma/mdx/site-mdx-presets.js +0 -49
  162. package/dist/fuma/mdx/site-mdx-presets.mjs +0 -45
  163. package/dist/fuma/server/optional-features.d.ts +0 -6
  164. package/dist/fuma/server/optional-features.js +0 -17
  165. package/dist/fuma/server/optional-features.mjs +0 -6
  166. package/dist/fuma/server/site-mdx-components.d.ts +0 -13
  167. package/dist/fuma/server/site-mdx-components.js +0 -18
  168. package/dist/fuma/server/site-mdx-components.mjs +0 -16
  169. package/dist/fuma/server/site-mdx-presets.d.ts +0 -195
  170. package/dist/fuma/server/site-mdx-presets.js +0 -55
  171. package/dist/fuma/server/site-mdx-presets.mjs +0 -52
  172. /package/src/{main → ai}/ai-prompt-textarea.tsx +0 -0
  173. /package/src/main/{x-toggle-button.tsx → buttons/x-toggle-button.tsx} +0 -0
@@ -0,0 +1,4 @@
1
+ "use client";
2
+ export { MoneyPriceInteractive } from './money-price-interactive.mjs';
3
+ export { MoneyPriceButton } from './money-price-button.mjs';
4
+ export { UserState } from './money-price-types.mjs';
@@ -1,2 +1,2 @@
1
1
  import { type MoneyPriceButtonProps } from './money-price-types';
2
- export declare function MoneyPriceButton({ planKey, userContext, billingType, onAuth, onAction, texts, isProcessing, isInitLoading, enableSubscriptionUpgrade }: MoneyPriceButtonProps): import("react/jsx-runtime").JSX.Element | null;
2
+ export declare function MoneyPriceButton({ planKey, userContext, billingType, onAuth, onAction, texts, isProcessing, isAnyProcessing, isInitLoading, enableSubscriptionUpgrade }: MoneyPriceButtonProps): import("react/jsx-runtime").JSX.Element | null;
@@ -8,7 +8,7 @@ var lib = require('@windrun-huaiin/base-ui/lib');
8
8
  var moneyPriceTypes = require('./money-price-types.js');
9
9
  var React = require('react');
10
10
 
11
- function MoneyPriceButton({ planKey, userContext, billingType, onAuth, onAction, texts, isProcessing = false, isInitLoading = false, enableSubscriptionUpgrade = true }) {
11
+ function MoneyPriceButton({ planKey, userContext, billingType, onAuth, onAction, texts, isProcessing = false, isAnyProcessing = false, isInitLoading = false, enableSubscriptionUpgrade = true }) {
12
12
  if (isInitLoading) {
13
13
  return (jsxRuntime.jsx("div", { className: "w-full h-11 md:h-12 mt-4 md:mt-auto rounded-full bg-transparent", "aria-hidden": "true", "data-plan-button-placeholder": planKey }));
14
14
  }
@@ -184,16 +184,19 @@ function MoneyPriceButton({ planKey, userContext, billingType, onAuth, onAction,
184
184
  const config = getButtonConfig();
185
185
  if (config.hidden)
186
186
  return null;
187
+ const hasActiveSubscription = subscriptionStatus === moneyPriceTypes.UserState.ProUser ||
188
+ subscriptionStatus === moneyPriceTypes.UserState.UltraUser;
187
189
  if (!enableSubscriptionUpgrade &&
188
190
  billingType !== 'onetime' &&
191
+ hasActiveSubscription &&
189
192
  config.text === texts.upgrade &&
190
193
  typeof config.onClick === 'function') {
191
194
  return null;
192
195
  }
193
- const isBusy = isLoading || isProcessing;
194
- const isDisabled = config.disabled || isBusy;
195
- const displayText = isBusy ? 'Processing...' : config.text;
196
- const isDisabledByConfigOnly = config.disabled && !isBusy;
196
+ const isCurrentButtonBusy = isLoading || isProcessing;
197
+ const isDisabled = config.disabled || isCurrentButtonBusy || isAnyProcessing;
198
+ const displayText = isCurrentButtonBusy ? 'Processing...' : config.text;
199
+ const isDisabledByConfigOnly = config.disabled && !isCurrentButtonBusy && !isAnyProcessing;
197
200
  const handleClick = (e) => tslib.__awaiter(this, void 0, void 0, function* () {
198
201
  if (isDisabled) {
199
202
  e.preventDefault();
@@ -217,8 +220,8 @@ function MoneyPriceButton({ planKey, userContext, billingType, onAuth, onAction,
217
220
  });
218
221
  const buttonClassName = utils.cn('w-full h-11 md:h-12 px-5 md:px-8 mt-4 md:mt-auto inline-flex items-center justify-center text-white text-sm md:text-base font-bold tracking-wide shadow-md hover:shadow-lg transition-all duration-300 rounded-full', isDisabledByConfigOnly
219
222
  ? 'bg-gray-400 cursor-not-allowed'
220
- : lib.themeButtonGradientClass, !isDisabledByConfigOnly && !isBusy &&
221
- lib.themeButtonGradientHoverClass, isBusy && !isDisabledByConfigOnly && 'opacity-70 cursor-not-allowed');
223
+ : lib.themeButtonGradientClass, !isDisabledByConfigOnly && !isCurrentButtonBusy && !isAnyProcessing &&
224
+ lib.themeButtonGradientHoverClass, (isCurrentButtonBusy || isAnyProcessing) && !isDisabledByConfigOnly && 'opacity-70 cursor-not-allowed');
222
225
  return (jsxRuntime.jsx("button", { className: buttonClassName, disabled: isDisabled, onClick: handleClick, type: "button", "data-plan-button": planKey, children: displayText }));
223
226
  }
224
227
 
@@ -6,7 +6,7 @@ import { themeButtonGradientClass, themeButtonGradientHoverClass } from '@windru
6
6
  import { UserState } from './money-price-types.mjs';
7
7
  import { useState } from 'react';
8
8
 
9
- function MoneyPriceButton({ planKey, userContext, billingType, onAuth, onAction, texts, isProcessing = false, isInitLoading = false, enableSubscriptionUpgrade = true }) {
9
+ function MoneyPriceButton({ planKey, userContext, billingType, onAuth, onAction, texts, isProcessing = false, isAnyProcessing = false, isInitLoading = false, enableSubscriptionUpgrade = true }) {
10
10
  if (isInitLoading) {
11
11
  return (jsx("div", { className: "w-full h-11 md:h-12 mt-4 md:mt-auto rounded-full bg-transparent", "aria-hidden": "true", "data-plan-button-placeholder": planKey }));
12
12
  }
@@ -182,16 +182,19 @@ function MoneyPriceButton({ planKey, userContext, billingType, onAuth, onAction,
182
182
  const config = getButtonConfig();
183
183
  if (config.hidden)
184
184
  return null;
185
+ const hasActiveSubscription = subscriptionStatus === UserState.ProUser ||
186
+ subscriptionStatus === UserState.UltraUser;
185
187
  if (!enableSubscriptionUpgrade &&
186
188
  billingType !== 'onetime' &&
189
+ hasActiveSubscription &&
187
190
  config.text === texts.upgrade &&
188
191
  typeof config.onClick === 'function') {
189
192
  return null;
190
193
  }
191
- const isBusy = isLoading || isProcessing;
192
- const isDisabled = config.disabled || isBusy;
193
- const displayText = isBusy ? 'Processing...' : config.text;
194
- const isDisabledByConfigOnly = config.disabled && !isBusy;
194
+ const isCurrentButtonBusy = isLoading || isProcessing;
195
+ const isDisabled = config.disabled || isCurrentButtonBusy || isAnyProcessing;
196
+ const displayText = isCurrentButtonBusy ? 'Processing...' : config.text;
197
+ const isDisabledByConfigOnly = config.disabled && !isCurrentButtonBusy && !isAnyProcessing;
195
198
  const handleClick = (e) => __awaiter(this, void 0, void 0, function* () {
196
199
  if (isDisabled) {
197
200
  e.preventDefault();
@@ -215,8 +218,8 @@ function MoneyPriceButton({ planKey, userContext, billingType, onAuth, onAction,
215
218
  });
216
219
  const buttonClassName = cn('w-full h-11 md:h-12 px-5 md:px-8 mt-4 md:mt-auto inline-flex items-center justify-center text-white text-sm md:text-base font-bold tracking-wide shadow-md hover:shadow-lg transition-all duration-300 rounded-full', isDisabledByConfigOnly
217
220
  ? 'bg-gray-400 cursor-not-allowed'
218
- : themeButtonGradientClass, !isDisabledByConfigOnly && !isBusy &&
219
- themeButtonGradientHoverClass, isBusy && !isDisabledByConfigOnly && 'opacity-70 cursor-not-allowed');
221
+ : themeButtonGradientClass, !isDisabledByConfigOnly && !isCurrentButtonBusy && !isAnyProcessing &&
222
+ themeButtonGradientHoverClass, (isCurrentButtonBusy || isAnyProcessing) && !isDisabledByConfigOnly && 'opacity-70 cursor-not-allowed');
220
223
  return (jsx("button", { className: buttonClassName, disabled: isDisabled, onClick: handleClick, type: "button", "data-plan-button": planKey, children: displayText }));
221
224
  }
222
225
 
@@ -117,7 +117,7 @@ function MoneyPriceInteractive({ data, config, checkoutApiEndpoint, customerPort
117
117
  React.useEffect(() => {
118
118
  setBillingType(prev => (prev === initialBillingCandidate ? prev : initialBillingCandidate));
119
119
  }, [initialBillingCandidate]);
120
- const [isProcessing, setIsProcessing] = React.useState(false);
120
+ const [processingTarget, setProcessingTarget] = React.useState(null);
121
121
  const [isTouchDevice, setIsTouchDevice] = React.useState(false);
122
122
  React.useEffect(() => {
123
123
  setIsTouchDevice('ontouchstart' in window || navigator.maxTouchPoints > 0);
@@ -175,18 +175,18 @@ function MoneyPriceInteractive({ data, config, checkoutApiEndpoint, customerPort
175
175
  const handleAction = React.useCallback((plan, billing) => tslib.__awaiter(this, void 0, void 0, function* () {
176
176
  var _a;
177
177
  const isSubscriptionFlow = billing !== 'onetime';
178
- if (isSubscriptionFlow && !enableSubscriptionUpgrade) {
178
+ const hasActiveSubscription = userContext.isAuthenticated &&
179
+ (userContext.subscriptionStatus === moneyPriceTypes.UserState.ProUser ||
180
+ userContext.subscriptionStatus === moneyPriceTypes.UserState.UltraUser);
181
+ if (isSubscriptionFlow && hasActiveSubscription && !enableSubscriptionUpgrade) {
179
182
  return;
180
183
  }
181
184
  navigationLockRef.current = false;
182
- setIsProcessing(true);
185
+ setProcessingTarget({ plan, billing });
183
186
  const markNavigating = () => {
184
187
  navigationLockRef.current = true;
185
188
  };
186
189
  try {
187
- const hasActiveSubscription = userContext.isAuthenticated &&
188
- (userContext.subscriptionStatus === moneyPriceTypes.UserState.ProUser ||
189
- userContext.subscriptionStatus === moneyPriceTypes.UserState.UltraUser);
190
190
  const shouldUsePortal = isSubscriptionFlow && hasActiveSubscription;
191
191
  if (shouldUsePortal) {
192
192
  const handled = yield customerPortal.redirectToCustomerPortal({
@@ -255,7 +255,7 @@ function MoneyPriceInteractive({ data, config, checkoutApiEndpoint, customerPort
255
255
  }
256
256
  finally {
257
257
  if (!navigationLockRef.current) {
258
- setIsProcessing(false);
258
+ setProcessingTarget(null);
259
259
  }
260
260
  }
261
261
  }), [
@@ -332,7 +332,8 @@ function MoneyPriceInteractive({ data, config, checkoutApiEndpoint, customerPort
332
332
  // OneTime 模式下的特殊处理:普通文本 + 带样式的产品副标题
333
333
  jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [(selectedBillingOption === null || selectedBillingOption === void 0 ? void 0 : selectedBillingOption.subTitle) && (jsxRuntime.jsx("span", { className: "text-[11px] md:text-xs text-gray-700 dark:text-gray-300 font-medium", children: selectedBillingOption.subTitle })), plan.subtitle && (jsxRuntime.jsxs("span", { className: "px-2 py-0.5 text-[11px] md:text-xs rounded bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200 font-semibold align-middle", children: ["+", plan.subtitle] }))] })) : (
334
334
  // 其他模式下保持原逻辑
335
- showBillingSubtitle && (jsxRuntime.jsx("span", { className: "text-[11px] md:text-xs text-gray-700 dark:text-gray-300 font-medium", children: (selectedBillingOption === null || selectedBillingOption === void 0 ? void 0 : selectedBillingOption.subTitle) || '' }))) })] })] }), jsxRuntime.jsx("ul", { className: "flex-1 mb-6 mt-4 text-xs md:text-sm leading-5", children: getFeatureRows(plan).map((feature, i) => (jsxRuntime.jsxs("li", { className: "flex items-start gap-2 mb-2 min-h-[24px] md:min-h-[28px]", "data-feature-item": `${planKey}-${i}`, children: [feature ? (jsxRuntime.jsx("span", { className: "inline-flex items-center justify-center w-5 h-5 rounded-full bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-200 mr-1", children: feature.icon ? jsxRuntime.jsx("span", { children: feature.icon }) : jsxRuntime.jsx("span", { className: "font-bold", children: "\u2713" }) })) : (jsxRuntime.jsx("span", { className: "inline-flex items-center justify-center w-5 h-5 rounded-full mr-1", children: "\u00A0" })), feature && feature.tag && (jsxRuntime.jsx("span", { className: "px-1 py-0.5 text-[6px] rounded bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200 font-semibold align-middle", children: feature.tag })), feature ? (jsxRuntime.jsxs("div", { className: "flex-1 text-gray-800 dark:text-gray-200", children: [jsxRuntime.jsx("span", { children: feature.description }), feature.tooltip && (jsxRuntime.jsx("span", { className: "block text-[11px] text-gray-500 dark:text-gray-400 mt-1", children: feature.tooltip }))] })) : (jsxRuntime.jsx("span", { children: "\u00A0" }))] }, i))) }), jsxRuntime.jsx("div", { className: "flex-1" }), jsxRuntime.jsx(moneyPriceButton.MoneyPriceButton, { planKey: planKey, userContext: userContext, billingType: billingType, onAuth: handleAuth, onAction: handleAction, texts: data.buttonTexts, isProcessing: isProcessing, isInitLoading: false, enableSubscriptionUpgrade: enableSubscriptionUpgrade })] }, plan.key));
335
+ showBillingSubtitle && (jsxRuntime.jsx("span", { className: "text-[11px] md:text-xs text-gray-700 dark:text-gray-300 font-medium", children: (selectedBillingOption === null || selectedBillingOption === void 0 ? void 0 : selectedBillingOption.subTitle) || '' }))) })] })] }), jsxRuntime.jsx("ul", { className: "flex-1 mb-6 mt-4 text-xs md:text-sm leading-5", children: getFeatureRows(plan).map((feature, i) => (jsxRuntime.jsxs("li", { className: "flex items-start gap-2 mb-2 min-h-[24px] md:min-h-[28px]", "data-feature-item": `${planKey}-${i}`, children: [feature ? (jsxRuntime.jsx("span", { className: "inline-flex items-center justify-center w-5 h-5 rounded-full bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-200 mr-1", children: feature.icon ? jsxRuntime.jsx("span", { children: feature.icon }) : jsxRuntime.jsx("span", { className: "font-bold", children: "\u2713" }) })) : (jsxRuntime.jsx("span", { className: "inline-flex items-center justify-center w-5 h-5 rounded-full mr-1", children: "\u00A0" })), feature && feature.tag && (jsxRuntime.jsx("span", { className: "px-1 py-0.5 text-[6px] rounded bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200 font-semibold align-middle", children: feature.tag })), feature ? (jsxRuntime.jsxs("div", { className: "flex-1 text-gray-800 dark:text-gray-200", children: [jsxRuntime.jsx("span", { children: feature.description }), feature.tooltip && (jsxRuntime.jsx("span", { className: "block text-[11px] text-gray-500 dark:text-gray-400 mt-1", children: feature.tooltip }))] })) : (jsxRuntime.jsx("span", { children: "\u00A0" }))] }, i))) }), jsxRuntime.jsx("div", { className: "flex-1" }), jsxRuntime.jsx(moneyPriceButton.MoneyPriceButton, { planKey: planKey, userContext: userContext, billingType: billingType, onAuth: handleAuth, onAction: handleAction, texts: data.buttonTexts, isProcessing: (processingTarget === null || processingTarget === void 0 ? void 0 : processingTarget.plan) === planKey &&
336
+ (processingTarget === null || processingTarget === void 0 ? void 0 : processingTarget.billing) === billingType, isAnyProcessing: !!processingTarget, isInitLoading: false, enableSubscriptionUpgrade: enableSubscriptionUpgrade })] }, plan.key));
336
337
  }) }) })] }));
337
338
  }
338
339
 
@@ -115,7 +115,7 @@ function MoneyPriceInteractive({ data, config, checkoutApiEndpoint, customerPort
115
115
  useEffect(() => {
116
116
  setBillingType(prev => (prev === initialBillingCandidate ? prev : initialBillingCandidate));
117
117
  }, [initialBillingCandidate]);
118
- const [isProcessing, setIsProcessing] = useState(false);
118
+ const [processingTarget, setProcessingTarget] = useState(null);
119
119
  const [isTouchDevice, setIsTouchDevice] = useState(false);
120
120
  useEffect(() => {
121
121
  setIsTouchDevice('ontouchstart' in window || navigator.maxTouchPoints > 0);
@@ -173,18 +173,18 @@ function MoneyPriceInteractive({ data, config, checkoutApiEndpoint, customerPort
173
173
  const handleAction = useCallback((plan, billing) => __awaiter(this, void 0, void 0, function* () {
174
174
  var _a;
175
175
  const isSubscriptionFlow = billing !== 'onetime';
176
- if (isSubscriptionFlow && !enableSubscriptionUpgrade) {
176
+ const hasActiveSubscription = userContext.isAuthenticated &&
177
+ (userContext.subscriptionStatus === UserState.ProUser ||
178
+ userContext.subscriptionStatus === UserState.UltraUser);
179
+ if (isSubscriptionFlow && hasActiveSubscription && !enableSubscriptionUpgrade) {
177
180
  return;
178
181
  }
179
182
  navigationLockRef.current = false;
180
- setIsProcessing(true);
183
+ setProcessingTarget({ plan, billing });
181
184
  const markNavigating = () => {
182
185
  navigationLockRef.current = true;
183
186
  };
184
187
  try {
185
- const hasActiveSubscription = userContext.isAuthenticated &&
186
- (userContext.subscriptionStatus === UserState.ProUser ||
187
- userContext.subscriptionStatus === UserState.UltraUser);
188
188
  const shouldUsePortal = isSubscriptionFlow && hasActiveSubscription;
189
189
  if (shouldUsePortal) {
190
190
  const handled = yield redirectToCustomerPortal({
@@ -253,7 +253,7 @@ function MoneyPriceInteractive({ data, config, checkoutApiEndpoint, customerPort
253
253
  }
254
254
  finally {
255
255
  if (!navigationLockRef.current) {
256
- setIsProcessing(false);
256
+ setProcessingTarget(null);
257
257
  }
258
258
  }
259
259
  }), [
@@ -330,7 +330,8 @@ function MoneyPriceInteractive({ data, config, checkoutApiEndpoint, customerPort
330
330
  // OneTime 模式下的特殊处理:普通文本 + 带样式的产品副标题
331
331
  jsxs(Fragment, { children: [(selectedBillingOption === null || selectedBillingOption === void 0 ? void 0 : selectedBillingOption.subTitle) && (jsx("span", { className: "text-[11px] md:text-xs text-gray-700 dark:text-gray-300 font-medium", children: selectedBillingOption.subTitle })), plan.subtitle && (jsxs("span", { className: "px-2 py-0.5 text-[11px] md:text-xs rounded bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200 font-semibold align-middle", children: ["+", plan.subtitle] }))] })) : (
332
332
  // 其他模式下保持原逻辑
333
- showBillingSubtitle && (jsx("span", { className: "text-[11px] md:text-xs text-gray-700 dark:text-gray-300 font-medium", children: (selectedBillingOption === null || selectedBillingOption === void 0 ? void 0 : selectedBillingOption.subTitle) || '' }))) })] })] }), jsx("ul", { className: "flex-1 mb-6 mt-4 text-xs md:text-sm leading-5", children: getFeatureRows(plan).map((feature, i) => (jsxs("li", { className: "flex items-start gap-2 mb-2 min-h-[24px] md:min-h-[28px]", "data-feature-item": `${planKey}-${i}`, children: [feature ? (jsx("span", { className: "inline-flex items-center justify-center w-5 h-5 rounded-full bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-200 mr-1", children: feature.icon ? jsx("span", { children: feature.icon }) : jsx("span", { className: "font-bold", children: "\u2713" }) })) : (jsx("span", { className: "inline-flex items-center justify-center w-5 h-5 rounded-full mr-1", children: "\u00A0" })), feature && feature.tag && (jsx("span", { className: "px-1 py-0.5 text-[6px] rounded bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200 font-semibold align-middle", children: feature.tag })), feature ? (jsxs("div", { className: "flex-1 text-gray-800 dark:text-gray-200", children: [jsx("span", { children: feature.description }), feature.tooltip && (jsx("span", { className: "block text-[11px] text-gray-500 dark:text-gray-400 mt-1", children: feature.tooltip }))] })) : (jsx("span", { children: "\u00A0" }))] }, i))) }), jsx("div", { className: "flex-1" }), jsx(MoneyPriceButton, { planKey: planKey, userContext: userContext, billingType: billingType, onAuth: handleAuth, onAction: handleAction, texts: data.buttonTexts, isProcessing: isProcessing, isInitLoading: false, enableSubscriptionUpgrade: enableSubscriptionUpgrade })] }, plan.key));
333
+ showBillingSubtitle && (jsx("span", { className: "text-[11px] md:text-xs text-gray-700 dark:text-gray-300 font-medium", children: (selectedBillingOption === null || selectedBillingOption === void 0 ? void 0 : selectedBillingOption.subTitle) || '' }))) })] })] }), jsx("ul", { className: "flex-1 mb-6 mt-4 text-xs md:text-sm leading-5", children: getFeatureRows(plan).map((feature, i) => (jsxs("li", { className: "flex items-start gap-2 mb-2 min-h-[24px] md:min-h-[28px]", "data-feature-item": `${planKey}-${i}`, children: [feature ? (jsx("span", { className: "inline-flex items-center justify-center w-5 h-5 rounded-full bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-200 mr-1", children: feature.icon ? jsx("span", { children: feature.icon }) : jsx("span", { className: "font-bold", children: "\u2713" }) })) : (jsx("span", { className: "inline-flex items-center justify-center w-5 h-5 rounded-full mr-1", children: "\u00A0" })), feature && feature.tag && (jsx("span", { className: "px-1 py-0.5 text-[6px] rounded bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200 font-semibold align-middle", children: feature.tag })), feature ? (jsxs("div", { className: "flex-1 text-gray-800 dark:text-gray-200", children: [jsx("span", { children: feature.description }), feature.tooltip && (jsx("span", { className: "block text-[11px] text-gray-500 dark:text-gray-400 mt-1", children: feature.tooltip }))] })) : (jsx("span", { children: "\u00A0" }))] }, i))) }), jsx("div", { className: "flex-1" }), jsx(MoneyPriceButton, { planKey: planKey, userContext: userContext, billingType: billingType, onAuth: handleAuth, onAction: handleAction, texts: data.buttonTexts, isProcessing: (processingTarget === null || processingTarget === void 0 ? void 0 : processingTarget.plan) === planKey &&
334
+ (processingTarget === null || processingTarget === void 0 ? void 0 : processingTarget.billing) === billingType, isAnyProcessing: !!processingTarget, isInitLoading: false, enableSubscriptionUpgrade: enableSubscriptionUpgrade })] }, plan.key));
334
335
  }) }) })] }));
335
336
  }
336
337
 
@@ -112,6 +112,7 @@ export interface MoneyPriceButtonProps {
112
112
  upgrade: string;
113
113
  };
114
114
  isProcessing?: boolean;
115
+ isAnyProcessing?: boolean;
115
116
  isInitLoading: boolean;
116
117
  enableSubscriptionUpgrade?: boolean;
117
118
  }
@@ -0,0 +1,5 @@
1
+ export { MoneyPrice } from './money-price';
2
+ export { getActiveProviderConfigUtil, getCreditsFromPriceIdUtil, getPriceConfigUtil, } from './money-price-config-util';
3
+ export { buildMoneyPriceData } from './money-price-data';
4
+ export type { MoneyPriceConfig, MoneyPriceProps, MoneyPriceInteractiveProps, MoneyPriceButtonProps, MoneyPriceData, InitUserContext, PaymentProvider, PaymentProviderConfig, EnhancePricePlan, SubscriptionProductConfig, CreditPackProductConfig, UserContext, } from './money-price-types';
5
+ export { UserState } from './money-price-types';
@@ -0,0 +1,18 @@
1
+ 'use strict';
2
+
3
+ var moneyPrice = require('./money-price.js');
4
+ var moneyPriceConfigUtil = require('./money-price-config-util.js');
5
+ var moneyPriceData = require('./money-price-data.js');
6
+ var moneyPriceTypes = require('./money-price-types.js');
7
+
8
+
9
+
10
+ exports.MoneyPrice = moneyPrice.MoneyPrice;
11
+ exports.getActiveProviderConfigUtil = moneyPriceConfigUtil.getActiveProviderConfigUtil;
12
+ exports.getCreditsFromPriceIdUtil = moneyPriceConfigUtil.getCreditsFromPriceIdUtil;
13
+ exports.getPriceConfigUtil = moneyPriceConfigUtil.getPriceConfigUtil;
14
+ exports.buildMoneyPriceData = moneyPriceData.buildMoneyPriceData;
15
+ Object.defineProperty(exports, "UserState", {
16
+ enumerable: true,
17
+ get: function () { return moneyPriceTypes.UserState; }
18
+ });
@@ -0,0 +1,4 @@
1
+ export { MoneyPrice } from './money-price.mjs';
2
+ export { getActiveProviderConfigUtil, getCreditsFromPriceIdUtil, getPriceConfigUtil } from './money-price-config-util.mjs';
3
+ export { buildMoneyPriceData } from './money-price-data.mjs';
4
+ export { UserState } from './money-price-types.mjs';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windrun-huaiin/third-ui",
3
- "version": "25.0.0",
3
+ "version": "27.0.0",
4
4
  "description": "Third-party integrated UI components for windrun-huaiin projects",
5
5
  "exports": {
6
6
  "./clerk": {
@@ -28,6 +28,56 @@
28
28
  "import": "./dist/main/index.mjs",
29
29
  "require": "./dist/main/index.js"
30
30
  },
31
+ "./main/alert-dialog": {
32
+ "types": "./dist/main/alert-dialog/index.d.ts",
33
+ "import": "./dist/main/alert-dialog/index.mjs",
34
+ "require": "./dist/main/alert-dialog/index.js"
35
+ },
36
+ "./main/buttons": {
37
+ "types": "./dist/main/buttons/index.d.ts",
38
+ "import": "./dist/main/buttons/index.mjs",
39
+ "require": "./dist/main/buttons/index.js"
40
+ },
41
+ "./main/credit": {
42
+ "types": "./dist/main/credit/index.d.ts",
43
+ "import": "./dist/main/credit/index.mjs",
44
+ "require": "./dist/main/credit/index.js"
45
+ },
46
+ "./main/credit/server": {
47
+ "types": "./dist/main/credit/server.d.ts",
48
+ "import": "./dist/main/credit/server.mjs",
49
+ "require": "./dist/main/credit/server.js"
50
+ },
51
+ "./main/hero": {
52
+ "types": "./dist/main/hero/index.d.ts",
53
+ "import": "./dist/main/hero/index.mjs",
54
+ "require": "./dist/main/hero/index.js"
55
+ },
56
+ "./main/home/server": {
57
+ "types": "./dist/main/home/server.d.ts",
58
+ "import": "./dist/main/home/server.mjs",
59
+ "require": "./dist/main/home/server.js"
60
+ },
61
+ "./main/loading": {
62
+ "types": "./dist/main/loading/index.d.ts",
63
+ "import": "./dist/main/loading/index.mjs",
64
+ "require": "./dist/main/loading/index.js"
65
+ },
66
+ "./main/loading-frame": {
67
+ "types": "./dist/main/loading-frame/index.d.ts",
68
+ "import": "./dist/main/loading-frame/index.mjs",
69
+ "require": "./dist/main/loading-frame/index.js"
70
+ },
71
+ "./main/money-price": {
72
+ "types": "./dist/main/money-price/index.d.ts",
73
+ "import": "./dist/main/money-price/index.mjs",
74
+ "require": "./dist/main/money-price/index.js"
75
+ },
76
+ "./main/money-price/server": {
77
+ "types": "./dist/main/money-price/server.d.ts",
78
+ "import": "./dist/main/money-price/server.mjs",
79
+ "require": "./dist/main/money-price/server.js"
80
+ },
31
81
  "./main/pill-select": {
32
82
  "types": "./dist/main/pill-select/index.d.ts",
33
83
  "import": "./dist/main/pill-select/index.mjs",
@@ -137,9 +187,9 @@
137
187
  "tslib": "^2.8.1",
138
188
  "unified": "^11.0.5",
139
189
  "zod": "^4.3.6",
140
- "@windrun-huaiin/base-ui": "^25.0.0",
141
- "@windrun-huaiin/contracts": "^25.0.0",
142
- "@windrun-huaiin/lib": "^25.0.0"
190
+ "@windrun-huaiin/base-ui": "^27.0.0",
191
+ "@windrun-huaiin/lib": "^27.0.0",
192
+ "@windrun-huaiin/contracts": "^27.0.0"
143
193
  },
144
194
  "peerDependencies": {
145
195
  "clsx": "^2.1.1",
package/src/ai/index.ts CHANGED
@@ -11,3 +11,4 @@ export * from './ai-message-content';
11
11
  export * from './ai-message-meta';
12
12
  export * from './ai-message-actions';
13
13
  export * from './ai-status-indicator';
14
+ export * from './ai-prompt-textarea';
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { clerkIntl } from '@third-ui/lib/clerk-intl';
3
+ import { clerkIntl } from '../lib/clerk-intl';
4
4
  import { ClerkProvider } from '@clerk/nextjs';
5
5
  import React from 'react';
6
6
 
@@ -72,8 +72,6 @@ export function ClerkProviderClient({
72
72
  clerkProviderProps.waitlistUrl = waitlistWithLocale;
73
73
  }
74
74
 
75
- // console.log('ClerkProviderClient props:', clerkProviderProps);
76
-
77
75
  return (
78
76
  <ClerkProvider {...clerkProviderProps}>
79
77
  {children}
@@ -214,7 +214,6 @@ export async function generateFingerprintId(): Promise<string> {
214
214
  // 检查现有 ID
215
215
  const existingId = checkStoredFingerprintId();
216
216
  if (existingId) {
217
- console.log('Using existing fingerprint ID:', existingId);
218
217
  return existingId;
219
218
  }
220
219
 
@@ -228,7 +227,6 @@ export async function generateFingerprintId(): Promise<string> {
228
227
  setLocalStorageValue(FINGERPRINT_STORAGE_KEY, fingerprintId);
229
228
  setCookie(FINGERPRINT_COOKIE_NAME, fingerprintId, 365);
230
229
 
231
- console.log('Generated new fingerprint ID:', fingerprintId);
232
230
  return fingerprintId;
233
231
  } catch (error) {
234
232
  console.warn('Failed to generate fingerprint with FingerprintJS:', error);
@@ -237,7 +235,6 @@ export async function generateFingerprintId(): Promise<string> {
237
235
  setLocalStorageValue(FINGERPRINT_STORAGE_KEY, fallbackId);
238
236
  setCookie(FINGERPRINT_COOKIE_NAME, fallbackId, 365);
239
237
 
240
- console.log('Generated fallback fingerprint ID:', fallbackId);
241
238
  return fallbackId;
242
239
  }
243
240
  }
@@ -284,7 +281,6 @@ export function clearFingerprintId(): void {
284
281
  export async function getOrGenerateFingerprintId(): Promise<string> {
285
282
  const existingId = checkStoredFingerprintId();
286
283
  if (existingId) {
287
- console.log('Retrieved existing fingerprint ID:', existingId);
288
284
  return existingId;
289
285
  }
290
286
 
@@ -58,7 +58,6 @@ export function useFingerprint(config: FingerprintConfig): UseFingerprintResult
58
58
  // Capture first-touch as early as possible before any in-site navigation can overwrite context.
59
59
  getOrCreateFirstTouchData();
60
60
  const currentFingerprintId = await getOrGenerateFingerprintId();
61
- console.log('Initialized fingerprintId:', currentFingerprintId);
62
61
  setFingerprintIdState(currentFingerprintId);
63
62
  return currentFingerprintId;
64
63
  } catch (error) {
@@ -79,12 +78,10 @@ export function useFingerprint(config: FingerprintConfig): UseFingerprintResult
79
78
  }
80
79
 
81
80
  if (isInitializingAnonymousUserRef.current) {
82
- console.log('Skipping anonymous user initialization because a request is already in flight:', fingerprintId);
83
81
  return;
84
82
  }
85
83
 
86
84
  if (requestedAnonymousFingerprintRef.current === fingerprintId && isInitialized) {
87
- console.log('Skipping anonymous user initialization because fingerprint is already initialized:', fingerprintId);
88
85
  return;
89
86
  }
90
87
 
@@ -94,7 +91,6 @@ export function useFingerprint(config: FingerprintConfig): UseFingerprintResult
94
91
  setIsLoading(true);
95
92
  setError(null);
96
93
 
97
- console.log('Initializing anonymous user with fingerprintId:', fingerprintId);
98
94
  const fingerprintHeaders = await createFingerprintHeaders();
99
95
  const response = await fetch(config.apiEndpoint, {
100
96
  method: 'POST',
@@ -112,11 +108,9 @@ export function useFingerprint(config: FingerprintConfig): UseFingerprintResult
112
108
  }
113
109
 
114
110
  const data = await response.json();
115
- console.log('API response in initializeAnonymousUser:', data);
116
111
 
117
112
  if (data.success) {
118
113
  const updatedXUser = data.xUser || { userId: '', fingerprintId, clerkUserId: '', email: '', status: '', createdAt: '' };
119
- console.log('Setting xUser:', updatedXUser);
120
114
  setXUser(updatedXUser);
121
115
  setXCredit(data.xCredit || null);
122
116
  setXSubscription(data.xSubscription || null);
@@ -33,16 +33,6 @@ export function SignInWithFingerprint() {
33
33
  }
34
34
  }, [fingerprintId, isInitialized, initializeAnonymousUser]);
35
35
 
36
- // 调试日志和处理登录逻辑
37
- useEffect(() => {
38
- console.log('SignInWithFingerprint on [redirect] DEBUG:', {
39
- fingerprintProvider: fingerprintContext ? 'Available' : 'Not found',
40
- fingerprintId: fingerprintId || 'Not generated',
41
- xUser: xUser ? 'Initialized' : 'Not initialized',
42
- clerkMetadata: unsafeMetadata
43
- });
44
- }, [xUser, fingerprintId, fingerprintContext, unsafeMetadata]);
45
-
46
36
  return <SignIn unsafeMetadata={unsafeMetadata} />;
47
37
  }
48
38
 
@@ -50,15 +50,6 @@ export function SignUpButtonWithFingerprint({
50
50
  }
51
51
  }, [fingerprintId, isInitialized, initializeAnonymousUser]);
52
52
 
53
- // 调试日志和处理注册逻辑
54
- useEffect(() => {
55
- console.log('SignUpWithFingerprint on [modal] DEBUG:', {
56
- fingerprintProvider: fingerprintContext ? 'Available' : 'Not found',
57
- fingerprintId: fingerprintId || 'Not generated',
58
- xUser: xUser ? 'Initialized' : 'Not initialized',
59
- clerkMetadata: unsafeMetadata
60
- });
61
- }, [xUser, fingerprintId, fingerprintContext, unsafeMetadata]);
62
53
  const { openSignUp } = useClerk();
63
54
 
64
55
 
@@ -66,14 +57,6 @@ export function SignUpButtonWithFingerprint({
66
57
  openSignUp({
67
58
  unsafeMetadata,
68
59
  });
69
-
70
- // 记录日志
71
- console.log('SignUpButton on [modal] clicked', {
72
- timestamp: new Date().toISOString(),
73
- mode,
74
- userId,
75
- fingerprintId
76
- });
77
60
  };
78
61
 
79
62
  return (
@@ -33,16 +33,6 @@ export function SignUpWithFingerprint() {
33
33
  }
34
34
  }, [fingerprintId, isInitialized, initializeAnonymousUser]);
35
35
 
36
- // 调试日志和处理注册逻辑
37
- useEffect(() => {
38
- console.log('SignUpWithFingerprint on [redirect] DEBUG:', {
39
- fingerprintProvider: fingerprintContext ? 'Available' : 'Not found',
40
- fingerprintId: fingerprintId || 'Not generated',
41
- xUser: xUser ? 'Initialized' : 'Not initialized',
42
- clerkMetadata: unsafeMetadata
43
- });
44
- }, [xUser, fingerprintId, fingerprintContext, unsafeMetadata]);
45
-
46
36
  return <SignUp unsafeMetadata={unsafeMetadata} />;
47
37
  }
48
38
 
@@ -16,7 +16,6 @@ import Link from 'fumadocs-core/link';
16
16
  import { HomeLayoutProps } from 'fumadocs-ui/layouts/home';
17
17
  import {
18
18
  LinkItem,
19
- type LinkItemType,
20
19
  resolveLinkItems,
21
20
  } from 'fumadocs-ui/layouts/shared';
22
21
  import {
@@ -36,6 +35,7 @@ import { Popover, PopoverContent, PopoverTrigger } from 'fumadocs-ui/components/
36
35
  import { buttonVariants } from 'fumadocs-ui/components/ui/button';
37
36
  import { useI18n } from 'fumadocs-ui/contexts/i18n';
38
37
  import { HeaderThemeSwitch } from './header-theme-switch';
38
+ import type { ExtendedLinkItem } from './custom-home-layout';
39
39
 
40
40
  export type NavbarCSSVars = CSSProperties & {
41
41
  '--fd-banner-height'?: string;
@@ -316,6 +316,7 @@ export function CustomHomeHeader({
316
316
  >
317
317
  <Link
318
318
  href={nav.url ?? '/'}
319
+ prefetch={false}
319
320
  className="inline-flex items-center gap-2.5 font-semibold"
320
321
  >
321
322
  {renderNavTitle(nav.title)}
@@ -454,7 +455,7 @@ function NavbarLinkItem({
454
455
  item,
455
456
  ...props
456
457
  }: {
457
- item: LinkItemType;
458
+ item: ExtendedLinkItem;
458
459
  className?: string;
459
460
  }) {
460
461
  if (item.type === 'custom') return <div {...props}>{item.children}</div>;
@@ -465,6 +466,8 @@ function NavbarLinkItem({
465
466
  return <Fragment key={j}>{child.children}</Fragment>;
466
467
  }
467
468
 
469
+ const extendedChild = child as ExtendedLinkItem;
470
+
468
471
  const {
469
472
  banner = child.icon ? (
470
473
  <div className="w-fit rounded-md border bg-fd-muted p-1 [&_svg]:size-4">
@@ -478,6 +481,7 @@ function NavbarLinkItem({
478
481
  <NavigationMenuLink key={`${j}-${child.url}`} asChild>
479
482
  <Link
480
483
  href={child.url}
484
+ prefetch={extendedChild.prefetch ?? false}
481
485
  external={child.external}
482
486
  {...rest}
483
487
  className={cn(
@@ -506,7 +510,7 @@ function NavbarLinkItem({
506
510
  className={cn(navItemVariants(), 'rounded-md', props.className)}
507
511
  >
508
512
  {item.url ? (
509
- <Link href={item.url} external={item.external}>
513
+ <Link href={item.url} prefetch={item.prefetch ?? false} external={item.external}>
510
514
  {item.text}
511
515
  </Link>
512
516
  ) : (
@@ -545,7 +549,7 @@ function MenuLinkItem({
545
549
  item,
546
550
  ...props
547
551
  }: {
548
- item: LinkItemType;
552
+ item: ExtendedLinkItem;
549
553
  className?: string;
550
554
  }) {
551
555
  if (item.type === 'custom')
@@ -564,7 +568,7 @@ function MenuLinkItem({
564
568
  <p className="mb-1 text-sm text-fd-muted-foreground">
565
569
  {item.url ? (
566
570
  <NavigationMenuLink asChild>
567
- <Link href={item.url} external={item.external}>
571
+ <Link href={item.url} prefetch={item.prefetch ?? false} external={item.external}>
568
572
  {header}
569
573
  </Link>
570
574
  </NavigationMenuLink>
@@ -692,19 +696,19 @@ function CompactLanguageToggle({
692
696
  );
693
697
  }
694
698
 
695
- function isGithubItem(item: LinkItemType, githubUrl?: string): boolean {
699
+ function isGithubItem(item: ExtendedLinkItem, githubUrl?: string): boolean {
696
700
  return Boolean(
697
701
  githubUrl && item.type === 'icon' && item.url === githubUrl,
698
702
  );
699
703
  }
700
704
 
701
- function isSecondary(item: LinkItemType): boolean {
705
+ function isSecondary(item: ExtendedLinkItem): boolean {
702
706
  if ('secondary' in item && item.secondary != null) return item.secondary;
703
707
 
704
708
  return item.type === 'icon';
705
709
  }
706
710
 
707
- function isMobilePinned(item: LinkItemType): boolean {
711
+ function isMobilePinned(item: ExtendedLinkItem): boolean {
708
712
  return Boolean((item as { mobilePinned?: boolean }).mobilePinned);
709
713
  }
710
714
 
@@ -1,9 +1,9 @@
1
1
  import type { CSSProperties, ReactNode } from 'react';
2
2
  import { HomeLayout, type HomeLayoutProps } from 'fumadocs-ui/layouts/home';
3
3
  import { type LinkItemType } from 'fumadocs-ui/layouts/shared';
4
- import { FumaBannerSuit } from '@third-ui/fuma/fuma-banner-suit';
5
- import { Footer } from '@third-ui/main/footer';
6
- import { GoToTop } from '@third-ui/main/go-to-top';
4
+ import { FumaBannerSuit } from '../fuma-banner-suit';
5
+ import { Footer } from '../../main/footer';
6
+ import { GoToTop } from '../../main/go-to-top';
7
7
  import {
8
8
  NavbarCSSVars,
9
9
  CustomHomeHeader,
@@ -12,7 +12,10 @@ import {
12
12
  type MobileMenuAction,
13
13
  } from './custom-header';
14
14
 
15
- export type ExtendedLinkItem = LinkItemType & { mobilePinned?: boolean };
15
+ export type ExtendedLinkItem = LinkItemType & {
16
+ mobilePinned?: boolean;
17
+ prefetch?: boolean;
18
+ };
16
19
 
17
20
  // - bannerHeight/headerHeight 换成你项目期望的 rem 值即可(如果没有 Banner 就把 bannerHeight 设成 0)。
18
21
  // - layoutStyle 同时把变量传给 HomeLayout 的 main 元素,这样内容整体会往下错开,不需要 has-banner/no-banner class。
@@ -1,3 +1,4 @@
1
1
  export * from './custom-header';
2
2
  export * from './custom-home-layout';
3
+ export * from './nav-config';
3
4
  export * from './site-layout';