@windrun-huaiin/third-ui 15.1.1 → 16.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 (125) hide show
  1. package/LICENSE +1 -1
  2. package/dist/ai/ai-chat-composer.d.ts +2 -0
  3. package/dist/ai/ai-chat-composer.js +47 -0
  4. package/dist/ai/ai-chat-composer.mjs +45 -0
  5. package/dist/ai/ai-markdown.d.ts +2 -0
  6. package/dist/ai/ai-markdown.js +36 -0
  7. package/dist/ai/ai-markdown.mjs +34 -0
  8. package/dist/ai/ai-message-actions.d.ts +2 -0
  9. package/dist/ai/ai-message-actions.js +14 -0
  10. package/dist/ai/ai-message-actions.mjs +12 -0
  11. package/dist/ai/ai-message-bubble.d.ts +2 -0
  12. package/dist/ai/ai-message-bubble.js +66 -0
  13. package/dist/ai/ai-message-bubble.mjs +64 -0
  14. package/dist/ai/ai-message-content.d.ts +2 -0
  15. package/dist/ai/ai-message-content.js +63 -0
  16. package/dist/ai/ai-message-content.mjs +61 -0
  17. package/dist/ai/ai-message-list.d.ts +2 -0
  18. package/dist/ai/ai-message-list.js +24 -0
  19. package/dist/ai/ai-message-list.mjs +22 -0
  20. package/dist/ai/ai-message-meta.d.ts +2 -0
  21. package/dist/ai/ai-message-meta.js +38 -0
  22. package/dist/ai/ai-message-meta.mjs +36 -0
  23. package/dist/ai/ai-status-indicator.d.ts +2 -0
  24. package/dist/ai/ai-status-indicator.js +51 -0
  25. package/dist/ai/ai-status-indicator.mjs +49 -0
  26. package/dist/ai/index.d.ts +11 -0
  27. package/dist/ai/index.js +33 -0
  28. package/dist/ai/index.mjs +11 -0
  29. package/dist/ai/types.d.ts +110 -0
  30. package/dist/ai/use-ai-conversation.d.ts +13 -0
  31. package/dist/ai/use-ai-conversation.js +276 -0
  32. package/dist/ai/use-ai-conversation.mjs +274 -0
  33. package/dist/clerk/clerk-organization-client.js +2 -2
  34. package/dist/clerk/clerk-organization-client.mjs +2 -2
  35. package/dist/clerk/clerk-page-generator.d.ts +1 -1
  36. package/dist/clerk/clerk-user-client.js +2 -2
  37. package/dist/clerk/clerk-user-client.mjs +2 -2
  38. package/dist/clerk/fingerprint/fingerprint-provider.js +9 -9
  39. package/dist/clerk/fingerprint/fingerprint-provider.mjs +9 -9
  40. package/dist/fuma/base/custom-header.js +4 -4
  41. package/dist/fuma/base/custom-header.mjs +4 -4
  42. package/dist/fuma/mdx/banner.js +3 -3
  43. package/dist/fuma/mdx/banner.mjs +3 -3
  44. package/dist/fuma/mdx/fuma-github-info.js +3 -3
  45. package/dist/fuma/mdx/fuma-github-info.mjs +3 -3
  46. package/dist/fuma/mdx/gradient-button.js +3 -3
  47. package/dist/fuma/mdx/gradient-button.mjs +3 -3
  48. package/dist/fuma/mdx/index.d.ts +1 -0
  49. package/dist/fuma/mdx/index.js +2 -0
  50. package/dist/fuma/mdx/index.mjs +1 -0
  51. package/dist/fuma/mdx/markdown-component-map.d.ts +3 -0
  52. package/dist/fuma/mdx/markdown-component-map.js +73 -0
  53. package/dist/fuma/mdx/markdown-component-map.mjs +71 -0
  54. package/dist/fuma/mdx/mermaid.d.ts +2 -1
  55. package/dist/fuma/mdx/mermaid.js +130 -6
  56. package/dist/fuma/mdx/mermaid.mjs +130 -6
  57. package/dist/fuma/mdx/toc-base.js +4 -4
  58. package/dist/fuma/mdx/toc-base.mjs +4 -4
  59. package/dist/fuma/mdx/trophy-card.js +2 -2
  60. package/dist/fuma/mdx/trophy-card.mjs +2 -2
  61. package/dist/fuma/mdx/zia-card.js +3 -3
  62. package/dist/fuma/mdx/zia-card.mjs +3 -3
  63. package/dist/fuma/mdx/zia-file.js +3 -3
  64. package/dist/fuma/mdx/zia-file.mjs +3 -3
  65. package/dist/main/ads-alert-dialog.js +2 -2
  66. package/dist/main/ads-alert-dialog.mjs +2 -2
  67. package/dist/main/credit/credit-nav-button.js +2 -2
  68. package/dist/main/credit/credit-nav-button.mjs +2 -2
  69. package/dist/main/credit/credit-overview-client.js +4 -4
  70. package/dist/main/credit/credit-overview-client.mjs +4 -4
  71. package/dist/main/footer.js +2 -2
  72. package/dist/main/footer.mjs +2 -2
  73. package/dist/main/go-to-top.js +2 -2
  74. package/dist/main/go-to-top.mjs +2 -2
  75. package/dist/main/index.d.ts +1 -0
  76. package/dist/main/index.js +2 -0
  77. package/dist/main/index.mjs +1 -0
  78. package/dist/main/info-tooltip.d.ts +8 -0
  79. package/dist/main/info-tooltip.js +48 -0
  80. package/dist/main/info-tooltip.mjs +46 -0
  81. package/dist/main/pill-select/x-pill-select.js +2 -2
  82. package/dist/main/pill-select/x-pill-select.mjs +2 -2
  83. package/dist/main/pill-select/x-token-input.js +2 -2
  84. package/dist/main/pill-select/x-token-input.mjs +2 -2
  85. package/dist/main/x-button.js +3 -3
  86. package/dist/main/x-button.mjs +3 -3
  87. package/package.json +16 -3
  88. package/src/ai/ai-chat-composer.tsx +187 -0
  89. package/src/ai/ai-markdown.tsx +45 -0
  90. package/src/ai/ai-message-actions.tsx +16 -0
  91. package/src/ai/ai-message-bubble.tsx +138 -0
  92. package/src/ai/ai-message-content.tsx +149 -0
  93. package/src/ai/ai-message-list.tsx +59 -0
  94. package/src/ai/ai-message-meta.tsx +56 -0
  95. package/src/ai/ai-status-indicator.tsx +61 -0
  96. package/src/ai/index.ts +13 -0
  97. package/src/ai/types.ts +131 -0
  98. package/src/ai/use-ai-conversation.ts +422 -0
  99. package/src/clerk/clerk-organization-client.tsx +5 -5
  100. package/src/clerk/clerk-page-generator.tsx +1 -1
  101. package/src/clerk/clerk-user-client.tsx +4 -4
  102. package/src/clerk/fingerprint/fingerprint-provider.tsx +34 -22
  103. package/src/fuma/base/custom-header.tsx +5 -5
  104. package/src/fuma/mdx/banner.tsx +3 -3
  105. package/src/fuma/mdx/fuma-github-info.tsx +4 -4
  106. package/src/fuma/mdx/gradient-button.tsx +3 -3
  107. package/src/fuma/mdx/index.ts +2 -1
  108. package/src/fuma/mdx/markdown-component-map.tsx +174 -0
  109. package/src/fuma/mdx/mermaid.tsx +145 -10
  110. package/src/fuma/mdx/toc-base.tsx +5 -5
  111. package/src/fuma/mdx/trophy-card.tsx +2 -2
  112. package/src/fuma/mdx/zia-card.tsx +3 -3
  113. package/src/fuma/mdx/zia-file.tsx +3 -3
  114. package/src/main/ads-alert-dialog.tsx +5 -5
  115. package/src/main/credit/credit-nav-button.tsx +3 -3
  116. package/src/main/credit/credit-overview-client.tsx +15 -7
  117. package/src/main/features.tsx +5 -3
  118. package/src/main/footer.tsx +4 -5
  119. package/src/main/go-to-top.tsx +2 -2
  120. package/src/main/index.ts +2 -0
  121. package/src/main/info-tooltip.tsx +99 -0
  122. package/src/main/language-detector.tsx +4 -4
  123. package/src/main/pill-select/x-pill-select.tsx +2 -2
  124. package/src/main/pill-select/x-token-input.tsx +2 -2
  125. package/src/main/x-button.tsx +4 -4
@@ -0,0 +1,274 @@
1
+ "use client";
2
+ import { __awaiter } from 'tslib';
3
+ import { useState, useRef, startTransition } from 'react';
4
+
5
+ function createId(prefix) {
6
+ try {
7
+ return `${prefix}-${crypto.randomUUID()}`;
8
+ }
9
+ catch (_a) {
10
+ return `${prefix}-${Date.now()}-${Math.random().toString(16).slice(2)}`;
11
+ }
12
+ }
13
+ function getAssistantMessageText(message) {
14
+ return message.parts
15
+ .flatMap((part) => (part.type === 'text' ? [part.text] : []))
16
+ .join('');
17
+ }
18
+ function createUserMessage(input) {
19
+ return {
20
+ id: createId('user'),
21
+ role: 'user',
22
+ parts: [{ type: 'text', text: input.text }],
23
+ createdAt: Date.now(),
24
+ metadata: input.metadata,
25
+ };
26
+ }
27
+ function getRuntimeMetadata(message) {
28
+ var _a;
29
+ const metadata = (_a = message.metadata) === null || _a === void 0 ? void 0 : _a.aiRuntime;
30
+ if (!metadata || typeof metadata !== 'object') {
31
+ return {};
32
+ }
33
+ return metadata;
34
+ }
35
+ function withRuntimeMetadata(message, nextMetadata) {
36
+ var _a;
37
+ return Object.assign(Object.assign({}, message), { metadata: Object.assign(Object.assign({}, ((_a = message.metadata) !== null && _a !== void 0 ? _a : {})), { aiRuntime: Object.assign(Object.assign({}, getRuntimeMetadata(message)), nextMetadata) }) });
38
+ }
39
+ function createAssistantPlaceholder(requestStartedAt) {
40
+ return {
41
+ id: createId('assistant'),
42
+ role: 'assistant',
43
+ parts: [{ type: 'text', text: '' }],
44
+ status: 'streaming',
45
+ createdAt: Date.now(),
46
+ metadata: {
47
+ aiRuntime: {
48
+ requestStartedAt,
49
+ },
50
+ },
51
+ };
52
+ }
53
+ function defaultTransport(endpoint) {
54
+ return (input, signal) => __awaiter(this, void 0, void 0, function* () {
55
+ return fetch(endpoint, {
56
+ method: 'POST',
57
+ signal,
58
+ headers: {
59
+ 'Content-Type': 'application/json',
60
+ },
61
+ body: JSON.stringify(input),
62
+ });
63
+ });
64
+ }
65
+ function updateAssistantText(messages, messageId, textDelta) {
66
+ return messages.map((message) => {
67
+ if (message.id !== messageId) {
68
+ return message;
69
+ }
70
+ const currentText = getAssistantMessageText(message);
71
+ const runtimeMetadata = getRuntimeMetadata(message);
72
+ const now = Date.now();
73
+ return withRuntimeMetadata(Object.assign(Object.assign({}, message), { parts: [{ type: 'text', text: currentText + textDelta }], status: 'streaming' }), runtimeMetadata.firstTokenAt
74
+ ? {}
75
+ : {
76
+ firstTokenAt: now,
77
+ firstTokenMs: runtimeMetadata.requestStartedAt
78
+ ? now - runtimeMetadata.requestStartedAt
79
+ : undefined,
80
+ });
81
+ });
82
+ }
83
+ function updateMessageStarted(messages, placeholderId, messageId) {
84
+ return messages.map((message) => {
85
+ if (message.id !== placeholderId) {
86
+ return message;
87
+ }
88
+ return withRuntimeMetadata(Object.assign(Object.assign({}, message), { id: messageId }), {
89
+ streamStartedAt: Date.now(),
90
+ });
91
+ });
92
+ }
93
+ function updateMessageStatus(messages, messageId, status) {
94
+ return messages.map((message) => {
95
+ if (message.id !== messageId) {
96
+ return message;
97
+ }
98
+ const now = Date.now();
99
+ const runtimeMetadata = getRuntimeMetadata(message);
100
+ return withRuntimeMetadata(Object.assign(Object.assign({}, message), { status }), {
101
+ completedAt: now,
102
+ totalMs: runtimeMetadata.requestStartedAt
103
+ ? now - runtimeMetadata.requestStartedAt
104
+ : undefined,
105
+ });
106
+ });
107
+ }
108
+ function applyErrorToLatestAssistant(messages, error) {
109
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
110
+ const message = messages[index];
111
+ if (message.role !== 'assistant') {
112
+ continue;
113
+ }
114
+ const nextMessages = [...messages];
115
+ const now = Date.now();
116
+ const runtimeMetadata = getRuntimeMetadata(message);
117
+ nextMessages[index] = withRuntimeMetadata(Object.assign(Object.assign({}, message), { status: error.status, failureReason: error.failureReason, errorMessage: error.error, upstreamStatusCode: error.upstreamStatusCode }), {
118
+ completedAt: now,
119
+ totalMs: runtimeMetadata.requestStartedAt
120
+ ? now - runtimeMetadata.requestStartedAt
121
+ : undefined,
122
+ });
123
+ return nextMessages;
124
+ }
125
+ return messages;
126
+ }
127
+ function consumeEventStream(response, onEvent) {
128
+ return __awaiter(this, void 0, void 0, function* () {
129
+ var _a;
130
+ if (!response.body) {
131
+ throw new Error('Missing response body');
132
+ }
133
+ const reader = response.body.getReader();
134
+ const decoder = new TextDecoder();
135
+ let buffer = '';
136
+ for (;;) {
137
+ const chunk = yield reader.read();
138
+ if (chunk.done) {
139
+ break;
140
+ }
141
+ buffer += decoder.decode(chunk.value, { stream: true });
142
+ const frames = buffer.split('\n\n');
143
+ buffer = (_a = frames.pop()) !== null && _a !== void 0 ? _a : '';
144
+ for (const frame of frames) {
145
+ const line = frame
146
+ .split('\n')
147
+ .find((item) => item.startsWith('data: '));
148
+ if (!line) {
149
+ continue;
150
+ }
151
+ onEvent(JSON.parse(line.slice(6)));
152
+ }
153
+ }
154
+ });
155
+ }
156
+ function useAIConversation(options) {
157
+ var _a, _b;
158
+ const transport = (_a = options.transport) !== null && _a !== void 0 ? _a : defaultTransport(options.endpoint);
159
+ const [state, setState] = useState({
160
+ sessionId: options.initialSessionId,
161
+ messages: (_b = options.initialMessages) !== null && _b !== void 0 ? _b : [],
162
+ isStreaming: false,
163
+ });
164
+ const abortRef = useRef(null);
165
+ const sendMessage = (input) => __awaiter(this, void 0, void 0, function* () {
166
+ var _a, _b, _c;
167
+ const text = input.text.trim();
168
+ if (!text || state.isStreaming) {
169
+ return;
170
+ }
171
+ const userMessage = createUserMessage(input);
172
+ const requestStartedAt = Date.now();
173
+ const assistantMessage = createAssistantPlaceholder(requestStartedAt);
174
+ startTransition(() => {
175
+ setState((current) => (Object.assign(Object.assign({}, current), { messages: [...current.messages, userMessage, assistantMessage], isStreaming: true, error: undefined })));
176
+ });
177
+ const controller = new AbortController();
178
+ abortRef.current = controller;
179
+ try {
180
+ const response = yield transport({
181
+ sessionId: state.sessionId,
182
+ messages: [...state.messages, userMessage],
183
+ modelName: options.modelName,
184
+ metadata: Object.assign(Object.assign({}, ((_a = options.metadata) !== null && _a !== void 0 ? _a : {})), ((_b = input.metadata) !== null && _b !== void 0 ? _b : {})),
185
+ }, controller.signal);
186
+ if (!response.ok) {
187
+ const payload = (yield response.json());
188
+ throw new Error(payload.error || 'AI request failed');
189
+ }
190
+ yield consumeEventStream(response, (event) => {
191
+ var _a;
192
+ (_a = options.onEvent) === null || _a === void 0 ? void 0 : _a.call(options, event);
193
+ startTransition(() => {
194
+ setState((current) => {
195
+ if (event.type === 'message_started') {
196
+ return Object.assign(Object.assign({}, current), { messages: updateMessageStarted(current.messages, assistantMessage.id, event.messageId) });
197
+ }
198
+ if (event.type === 'text_delta') {
199
+ return Object.assign(Object.assign({}, current), { messages: updateAssistantText(current.messages, event.messageId, event.text) });
200
+ }
201
+ if (event.type === 'part') {
202
+ return Object.assign(Object.assign({}, current), { messages: current.messages.map((message) => {
203
+ if (message.id !== event.messageId) {
204
+ return message;
205
+ }
206
+ return Object.assign(Object.assign({}, message), { parts: [...message.parts, event.part] });
207
+ }) });
208
+ }
209
+ if (event.type === 'message_completed') {
210
+ return Object.assign(Object.assign({}, current), { isStreaming: false, messages: updateMessageStatus(current.messages, event.messageId, 'completed') });
211
+ }
212
+ if (event.type === 'error') {
213
+ return Object.assign(Object.assign({}, current), { isStreaming: false, error: event.error.error, messages: applyErrorToLatestAssistant(current.messages, event.error) });
214
+ }
215
+ return current;
216
+ });
217
+ });
218
+ });
219
+ startTransition(() => {
220
+ setState((current) => (Object.assign(Object.assign({}, current), { isStreaming: false })));
221
+ });
222
+ }
223
+ catch (error) {
224
+ const nextError = error instanceof Error ? error : new Error('AI request failed');
225
+ (_c = options.onError) === null || _c === void 0 ? void 0 : _c.call(options, nextError);
226
+ startTransition(() => {
227
+ setState((current) => (Object.assign(Object.assign({}, current), { isStreaming: false, error: nextError.message, messages: applyErrorToLatestAssistant(current.messages, {
228
+ error: nextError.message,
229
+ status: controller.signal.aborted ? 'request_aborted' : 'failed',
230
+ failureReason: 'unknown',
231
+ upstreamStatusCode: controller.signal.aborted ? 499 : 500,
232
+ }) })));
233
+ });
234
+ }
235
+ finally {
236
+ abortRef.current = null;
237
+ }
238
+ });
239
+ const stopGeneration = () => {
240
+ var _a;
241
+ (_a = abortRef.current) === null || _a === void 0 ? void 0 : _a.abort();
242
+ };
243
+ const resetConversation = () => {
244
+ startTransition(() => {
245
+ var _a;
246
+ setState({
247
+ sessionId: options.initialSessionId,
248
+ messages: (_a = options.initialMessages) !== null && _a !== void 0 ? _a : [],
249
+ isStreaming: false,
250
+ });
251
+ });
252
+ };
253
+ const removeMessage = (messageId) => {
254
+ startTransition(() => {
255
+ setState((current) => (Object.assign(Object.assign({}, current), { messages: current.messages.filter((message) => message.id !== messageId) })));
256
+ });
257
+ };
258
+ const loadConversation = (messages, sessionId) => {
259
+ startTransition(() => {
260
+ setState({
261
+ sessionId,
262
+ messages,
263
+ isStreaming: false,
264
+ });
265
+ });
266
+ };
267
+ return Object.assign(Object.assign({}, state), { sendMessage,
268
+ stopGeneration,
269
+ resetConversation,
270
+ removeMessage,
271
+ loadConversation });
272
+ }
273
+
274
+ export { useAIConversation };
@@ -3,7 +3,7 @@
3
3
 
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
  var nextjs = require('@clerk/nextjs');
6
- var server = require('@windrun-huaiin/base-ui/components/server');
6
+ var icons = require('@windrun-huaiin/base-ui/icons');
7
7
 
8
8
  function ClerkOrganizationClient({ data }) {
9
9
  return (jsxRuntime.jsx("div", { className: ` ms-3 me-2 flex items-center h-10 rounded-full border shadow-lg ${data.className}`, children: jsxRuntime.jsx("div", { className: "flex items-center gap-x-4 w-full min-w-40", children: jsxRuntime.jsxs(nextjs.OrganizationSwitcher, { appearance: {
@@ -12,7 +12,7 @@ function ClerkOrganizationClient({ data }) {
12
12
  organizationSwitcherTriggerIcon: "",
13
13
  userButtonAvatarBox: "w-8 h-8 border rounded-full",
14
14
  },
15
- }, children: [jsxRuntime.jsx(nextjs.OrganizationSwitcher.OrganizationProfilePage, { label: data.homepage, url: "/", labelIcon: jsxRuntime.jsx(server.globalLucideIcons.D8, {}) }), jsxRuntime.jsx(nextjs.OrganizationSwitcher.OrganizationProfilePage, { labelIcon: jsxRuntime.jsx(server.globalLucideIcons.ReceiptText, {}), label: data.terms, url: `/${data.locale}/legal/terms` }), jsxRuntime.jsx(nextjs.OrganizationSwitcher.OrganizationProfilePage, { labelIcon: jsxRuntime.jsx(server.globalLucideIcons.ShieldUser, {}), label: data.privacy, url: `/${data.locale}/legal/privacy` })] }) }) }));
15
+ }, children: [jsxRuntime.jsx(nextjs.OrganizationSwitcher.OrganizationProfilePage, { label: data.homepage, url: "/", labelIcon: jsxRuntime.jsx(icons.D8Icon, {}) }), jsxRuntime.jsx(nextjs.OrganizationSwitcher.OrganizationProfilePage, { labelIcon: jsxRuntime.jsx(icons.ReceiptTextIcon, {}), label: data.terms, url: `/${data.locale}/legal/terms` }), jsxRuntime.jsx(nextjs.OrganizationSwitcher.OrganizationProfilePage, { labelIcon: jsxRuntime.jsx(icons.ShieldUserIcon, {}), label: data.privacy, url: `/${data.locale}/legal/privacy` })] }) }) }));
16
16
  }
17
17
 
18
18
  exports.ClerkOrganizationClient = ClerkOrganizationClient;
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from 'react/jsx-runtime';
3
3
  import { OrganizationSwitcher } from '@clerk/nextjs';
4
- import { globalLucideIcons } from '@windrun-huaiin/base-ui/components/server';
4
+ import { D8Icon, ReceiptTextIcon, ShieldUserIcon } from '@windrun-huaiin/base-ui/icons';
5
5
 
6
6
  function ClerkOrganizationClient({ data }) {
7
7
  return (jsx("div", { className: ` ms-3 me-2 flex items-center h-10 rounded-full border shadow-lg ${data.className}`, children: jsx("div", { className: "flex items-center gap-x-4 w-full min-w-40", children: jsxs(OrganizationSwitcher, { appearance: {
@@ -10,7 +10,7 @@ function ClerkOrganizationClient({ data }) {
10
10
  organizationSwitcherTriggerIcon: "",
11
11
  userButtonAvatarBox: "w-8 h-8 border rounded-full",
12
12
  },
13
- }, children: [jsx(OrganizationSwitcher.OrganizationProfilePage, { label: data.homepage, url: "/", labelIcon: jsx(globalLucideIcons.D8, {}) }), jsx(OrganizationSwitcher.OrganizationProfilePage, { labelIcon: jsx(globalLucideIcons.ReceiptText, {}), label: data.terms, url: `/${data.locale}/legal/terms` }), jsx(OrganizationSwitcher.OrganizationProfilePage, { labelIcon: jsx(globalLucideIcons.ShieldUser, {}), label: data.privacy, url: `/${data.locale}/legal/privacy` })] }) }) }));
13
+ }, children: [jsx(OrganizationSwitcher.OrganizationProfilePage, { label: data.homepage, url: "/", labelIcon: jsx(D8Icon, {}) }), jsx(OrganizationSwitcher.OrganizationProfilePage, { labelIcon: jsx(ReceiptTextIcon, {}), label: data.terms, url: `/${data.locale}/legal/terms` }), jsx(OrganizationSwitcher.OrganizationProfilePage, { labelIcon: jsx(ShieldUserIcon, {}), label: data.privacy, url: `/${data.locale}/legal/privacy` })] }) }) }));
14
14
  }
15
15
 
16
16
  export { ClerkOrganizationClient };
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @license
3
3
  * MIT License
4
- * Copyright (c) 2025 D8ger
4
+ * Copyright (c) 2026 D8ger
5
5
  *
6
6
  * This source code is licensed under the MIT license found in the
7
7
  * LICENSE file in the root directory of this source tree.
@@ -4,7 +4,7 @@
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
  var React = require('react');
6
6
  var nextjs = require('@clerk/nextjs');
7
- var server = require('@windrun-huaiin/base-ui/components/server');
7
+ var icons = require('@windrun-huaiin/base-ui/icons');
8
8
  var lib = require('@windrun-huaiin/base-ui/lib');
9
9
  var signupButtonWithFingerprintClient = require('./signup-button-with-fingerprint-client.js');
10
10
 
@@ -15,7 +15,7 @@ function ClerkUserClient({ data }) {
15
15
  elements: {
16
16
  userButtonAvatarBox: "w-8 h-8 border",
17
17
  }
18
- }, children: jsxRuntime.jsxs(nextjs.UserButton.MenuItems, { children: [jsxRuntime.jsx(nextjs.UserButton.Action, { label: "manageAccount" }), jsxRuntime.jsx(nextjs.UserButton.Link, { labelIcon: jsxRuntime.jsx(server.globalLucideIcons.ReceiptText, { className: "size-4 fill-none stroke-(--clerk-icon-stroke-color)" }), label: data.terms, href: `/${data.locale}/legal/terms` }), jsxRuntime.jsx(nextjs.UserButton.Link, { labelIcon: jsxRuntime.jsx(server.globalLucideIcons.ShieldUser, { className: "size-4 fill-none stroke-(--clerk-icon-stroke-color)" }), label: data.privacy, href: `/${data.locale}/legal/privacy` }), jsxRuntime.jsx(nextjs.UserButton.Action, { label: "signOut" })] }) }))] })] }));
18
+ }, children: jsxRuntime.jsxs(nextjs.UserButton.MenuItems, { children: [jsxRuntime.jsx(nextjs.UserButton.Action, { label: "manageAccount" }), jsxRuntime.jsx(nextjs.UserButton.Link, { labelIcon: jsxRuntime.jsx(icons.ReceiptTextIcon, { className: "size-4 fill-none stroke-(--clerk-icon-stroke-color)" }), label: data.terms, href: `/${data.locale}/legal/terms` }), jsxRuntime.jsx(nextjs.UserButton.Link, { labelIcon: jsxRuntime.jsx(icons.ShieldUserIcon, { className: "size-4 fill-none stroke-(--clerk-icon-stroke-color)" }), label: data.privacy, href: `/${data.locale}/legal/privacy` }), jsxRuntime.jsx(nextjs.UserButton.Action, { label: "signOut" })] }) }))] })] }));
19
19
  }
20
20
 
21
21
  exports.ClerkUserClient = ClerkUserClient;
@@ -2,7 +2,7 @@
2
2
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
3
3
  import { useState } from 'react';
4
4
  import { useAuth, ClerkLoading, ClerkLoaded, SignInButton, UserButton } from '@clerk/nextjs';
5
- import { globalLucideIcons } from '@windrun-huaiin/base-ui/components/server';
5
+ import { ReceiptTextIcon, ShieldUserIcon } from '@windrun-huaiin/base-ui/icons';
6
6
  import { themeButtonGradientClass } from '@windrun-huaiin/base-ui/lib';
7
7
  import { SignUpButtonWithFingerprint } from './signup-button-with-fingerprint-client.mjs';
8
8
 
@@ -13,7 +13,7 @@ function ClerkUserClient({ data }) {
13
13
  elements: {
14
14
  userButtonAvatarBox: "w-8 h-8 border",
15
15
  }
16
- }, children: jsxs(UserButton.MenuItems, { children: [jsx(UserButton.Action, { label: "manageAccount" }), jsx(UserButton.Link, { labelIcon: jsx(globalLucideIcons.ReceiptText, { className: "size-4 fill-none stroke-(--clerk-icon-stroke-color)" }), label: data.terms, href: `/${data.locale}/legal/terms` }), jsx(UserButton.Link, { labelIcon: jsx(globalLucideIcons.ShieldUser, { className: "size-4 fill-none stroke-(--clerk-icon-stroke-color)" }), label: data.privacy, href: `/${data.locale}/legal/privacy` }), jsx(UserButton.Action, { label: "signOut" })] }) }))] })] }));
16
+ }, children: jsxs(UserButton.MenuItems, { children: [jsx(UserButton.Action, { label: "manageAccount" }), jsx(UserButton.Link, { labelIcon: jsx(ReceiptTextIcon, { className: "size-4 fill-none stroke-(--clerk-icon-stroke-color)" }), label: data.terms, href: `/${data.locale}/legal/terms` }), jsx(UserButton.Link, { labelIcon: jsx(ShieldUserIcon, { className: "size-4 fill-none stroke-(--clerk-icon-stroke-color)" }), label: data.privacy, href: `/${data.locale}/legal/privacy` }), jsx(UserButton.Action, { label: "signOut" })] }) }))] })] }));
17
17
  }
18
18
 
19
19
  export { ClerkUserClient };
@@ -3,7 +3,7 @@
3
3
 
4
4
  var tslib = require('tslib');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
- var server = require('@windrun-huaiin/base-ui/components/server');
6
+ var icons = require('@windrun-huaiin/base-ui/icons');
7
7
  var lib = require('@windrun-huaiin/base-ui/lib');
8
8
  var utils = require('@windrun-huaiin/lib/utils');
9
9
  var React = require('react');
@@ -93,7 +93,7 @@ function FingerprintStatus() {
93
93
  {
94
94
  key: 'paid',
95
95
  label: 'Paid',
96
- icon: jsxRuntime.jsx(server.globalLucideIcons.Settings2, { className: "size-4 text-green-500 dark:text-green-300" }),
96
+ icon: jsxRuntime.jsx(icons.Settings2Icon, { className: "size-4 text-green-500 dark:text-green-300" }),
97
97
  balance: xCredit.balancePaid,
98
98
  total: xCredit.totalPaidLimit,
99
99
  start: xCredit.paidStart,
@@ -102,7 +102,7 @@ function FingerprintStatus() {
102
102
  {
103
103
  key: 'oneTimePaid',
104
104
  label: 'OneTimePaid',
105
- icon: jsxRuntime.jsx(server.globalLucideIcons.Coins, { className: "size-4 text-amber-500 dark:text-amber-300" }),
105
+ icon: jsxRuntime.jsx(icons.CoinsIcon, { className: "size-4 text-amber-500 dark:text-amber-300" }),
106
106
  balance: xCredit.balanceOneTimePaid,
107
107
  total: xCredit.totalOneTimePaidLimit,
108
108
  start: xCredit.oneTimePaidStart,
@@ -111,7 +111,7 @@ function FingerprintStatus() {
111
111
  {
112
112
  key: 'free',
113
113
  label: 'Free',
114
- icon: jsxRuntime.jsx(server.globalLucideIcons.Gift, { className: "size-4 text-purple-500 dark:text-purple-300" }),
114
+ icon: jsxRuntime.jsx(icons.GiftIcon, { className: "size-4 text-purple-500 dark:text-purple-300" }),
115
115
  balance: xCredit.balanceFree,
116
116
  total: xCredit.totalFreeLimit,
117
117
  start: xCredit.freeStart,
@@ -247,11 +247,11 @@ function FingerprintStatus() {
247
247
  setActiveDebugFingerprintId(nextFingerprintId);
248
248
  setTestResult(`Generated test fingerprint override: ${nextFingerprintId}`);
249
249
  };
250
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [!isOpen && (jsxRuntime.jsx("button", { onClick: handleToggle, type: "button", "aria-label": "Fingerprint debug panel", className: utils.cn('fixed left-2 top-2 md:left-2 md:top-3 z-10000 inline-flex size-8 md:size-11 items-center justify-center rounded-full', lib.themeButtonGradientClass, lib.themeButtonGradientHoverClass, 'text-white rounded-full shadow-lg hover:shadow-xl transition-all duration-300'), children: jsxRuntime.jsx(server.globalLucideIcons.Lightbulb, { className: "size-6 text-white" }) })), isOpen && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { onClick: handleBackdropClick, className: "fixed inset-0 z-9998 bg-black/60 backdrop-blur-sm" }), jsxRuntime.jsxs("div", { ref: modalRef, className: utils.cn('fixed inset-3 z-9999 mx-auto w-[min(95vw,520px)] overflow-y-auto rounded-2xl border', 'border-slate-200/70 bg-white/95 p-4 shadow-2xl backdrop-blur-sm', 'font-sans text-sm text-slate-700 dark:border-white/12 dark:bg-slate-950/95 dark:text-slate-200', 'sm:inset-auto md:left-2 sm:top-1 md:right-auto sm:w-[min(520px,95vw)] sm:p-5'), children: [jsxRuntime.jsx("header", { className: "mb-4", children: jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [jsxRuntime.jsxs("div", { className: utils.cn("flex items-center gap-2 text-base font-bold tracking-wider", lib.themeIconColor), children: [jsxRuntime.jsx(server.globalLucideIcons.ShieldUser, { className: "size-4" }), "Fingerprint Debug Panel"] }), jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntime.jsxs("button", { type: "button", onClick: () => setPanelMode((prev) => prev === 'info' ? 'test' : 'info'), className: utils.cn('inline-flex items-center gap-2 rounded-full border px-2 py-1 text-[11px] font-semibold shadow-sm transition-all duration-200', panelMode === 'test'
250
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [!isOpen && (jsxRuntime.jsx("button", { onClick: handleToggle, type: "button", "aria-label": "Fingerprint debug panel", className: utils.cn('fixed left-2 top-2 md:left-2 md:top-3 z-10000 inline-flex size-8 md:size-11 items-center justify-center rounded-full', lib.themeButtonGradientClass, lib.themeButtonGradientHoverClass, 'text-white rounded-full shadow-lg hover:shadow-xl transition-all duration-300'), children: jsxRuntime.jsx(icons.LightbulbIcon, { className: "size-6 text-white" }) })), isOpen && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { onClick: handleBackdropClick, className: "fixed inset-0 z-9998 bg-black/60 backdrop-blur-sm" }), jsxRuntime.jsxs("div", { ref: modalRef, className: utils.cn('fixed inset-3 z-9999 mx-auto w-[min(95vw,520px)] overflow-y-auto rounded-2xl border', 'border-slate-200/70 bg-white/95 p-4 shadow-2xl backdrop-blur-sm', 'font-sans text-sm text-slate-700 dark:border-white/12 dark:bg-slate-950/95 dark:text-slate-200', 'sm:inset-auto md:left-2 sm:top-1 md:right-auto sm:w-[min(520px,95vw)] sm:p-5'), children: [jsxRuntime.jsx("header", { className: "mb-4", children: jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [jsxRuntime.jsxs("div", { className: utils.cn("flex items-center gap-2 text-base font-bold tracking-wider", lib.themeIconColor), children: [jsxRuntime.jsx(icons.ShieldUserIcon, { className: "size-4" }), "Fingerprint Debug Panel"] }), jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntime.jsxs("button", { type: "button", onClick: () => setPanelMode((prev) => prev === 'info' ? 'test' : 'info'), className: utils.cn('inline-flex items-center gap-2 rounded-full border px-2 py-1 text-[11px] font-semibold shadow-sm transition-all duration-200', panelMode === 'test'
251
251
  ? utils.cn('border-transparent text-white', lib.themeButtonGradientClass, lib.themeButtonGradientHoverClass)
252
252
  : themedGhostButtonClass), "aria-pressed": panelMode === 'test', children: [jsxRuntime.jsx("span", { children: "Concurrent Test" }), jsxRuntime.jsx("span", { className: utils.cn('relative inline-flex h-5 w-9 items-center rounded-full transition-colors', panelMode === 'test'
253
253
  ? 'bg-white/25'
254
- : 'bg-slate-300 dark:bg-slate-700'), children: jsxRuntime.jsx("span", { className: utils.cn('inline-block size-4 rounded-full shadow-sm transition-transform', panelMode === 'test' ? 'bg-white' : 'bg-white dark:bg-slate-100', panelMode === 'test' ? 'translate-x-4' : 'translate-x-0.5') }) })] }), jsxRuntime.jsx("button", { type: "button", "aria-label": "Close fingerprint panel", className: "rounded-full p-2 text-slate-500 transition hover:bg-slate-100 hover:text-slate-700 dark:text-slate-300 dark:hover:bg-white/10 dark:hover:text-white", onClick: () => setIsOpen(false), children: jsxRuntime.jsx(server.globalLucideIcons.X, { className: "size-4" }) })] })] }) }), jsxRuntime.jsxs("section", { className: "space-y-1", children: [panelMode === 'info' ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(PanelSection, { icon: jsxRuntime.jsx(server.globalLucideIcons.Fingerprint, { className: "size-4" }), title: "User", rightInfo: jsxRuntime.jsx(StatusTag, { value: userStatus }), items: [
254
+ : 'bg-slate-300 dark:bg-slate-700'), children: jsxRuntime.jsx("span", { className: utils.cn('inline-block size-4 rounded-full shadow-sm transition-transform', panelMode === 'test' ? 'bg-white' : 'bg-white dark:bg-slate-100', panelMode === 'test' ? 'translate-x-4' : 'translate-x-0.5') }) })] }), jsxRuntime.jsx("button", { type: "button", "aria-label": "Close fingerprint panel", className: "rounded-full p-2 text-slate-500 transition hover:bg-slate-100 hover:text-slate-700 dark:text-slate-300 dark:hover:bg-white/10 dark:hover:text-white", onClick: () => setIsOpen(false), children: jsxRuntime.jsx(icons.XIcon, { className: "size-4" }) })] })] }) }), jsxRuntime.jsxs("section", { className: "space-y-1", children: [panelMode === 'info' ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(PanelSection, { icon: jsxRuntime.jsx(icons.FingerprintIcon, { className: "size-4" }), title: "User", rightInfo: jsxRuntime.jsx(StatusTag, { value: userStatus }), items: [
255
255
  { label: 'UserID', value: jsxRuntime.jsx(ui.CopyableText, { text: (xUser === null || xUser === void 0 ? void 0 : xUser.userId) || '' }) },
256
256
  { label: 'NickName', value: jsxRuntime.jsx(ui.CopyableText, { text: (xUser === null || xUser === void 0 ? void 0 : xUser.userName) || '' }) },
257
257
  { label: 'FingerprintID', value: jsxRuntime.jsx(ui.CopyableText, { text: (xUser === null || xUser === void 0 ? void 0 : xUser.fingerprintId) || fingerprintId || '' }) },
@@ -259,17 +259,17 @@ function FingerprintStatus() {
259
259
  { label: 'Email', value: jsxRuntime.jsx(ui.CopyableText, { text: (xUser === null || xUser === void 0 ? void 0 : xUser.email) || '' }) },
260
260
  { label: 'StripeCusID', value: jsxRuntime.jsx(ui.CopyableText, { text: (xUser === null || xUser === void 0 ? void 0 : xUser.stripeCusId) || '' }) },
261
261
  { label: 'CreatedAt', value: (xUser === null || xUser === void 0 ? void 0 : xUser.createdAt) || '--' },
262
- ] }), jsxRuntime.jsxs("div", { className: "space-y-2 rounded-xl border border-slate-200/70 bg-white/80 p-4 shadow-sm dark:border-white/12 dark:bg-slate-900/50", children: [jsxRuntime.jsx(PanelHeader, { icon: jsxRuntime.jsx(server.globalLucideIcons.Gem, { className: "size-4" }), title: "Credits Info", rightInfo: jsxRuntime.jsx("span", { className: utils.cn("font-semibold", lib.themeIconColor), children: totalCredits }) }), jsxRuntime.jsx("div", { className: "space-y-3", children: creditBuckets.length > 0 ? (creditBuckets.map((bucket) => {
262
+ ] }), jsxRuntime.jsxs("div", { className: "space-y-2 rounded-xl border border-slate-200/70 bg-white/80 p-4 shadow-sm dark:border-white/12 dark:bg-slate-900/50", children: [jsxRuntime.jsx(PanelHeader, { icon: jsxRuntime.jsx(icons.GemIcon, { className: "size-4" }), title: "Credits Info", rightInfo: jsxRuntime.jsx("span", { className: utils.cn("font-semibold", lib.themeIconColor), children: totalCredits }) }), jsxRuntime.jsx("div", { className: "space-y-3", children: creditBuckets.length > 0 ? (creditBuckets.map((bucket) => {
263
263
  const percent = Math.round(computeProgress(bucket.balance, bucket.total) * 100);
264
264
  return (jsxRuntime.jsxs("div", { className: "rounded-lg border border-slate-200/70 bg-white/70 p-3 dark:border-white/10 dark:bg-slate-900/40", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-xs font-medium text-slate-600 dark:text-slate-300", children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [bucket.icon, jsxRuntime.jsx("span", { children: bucket.label })] }), jsxRuntime.jsxs("span", { className: "font-semibold text-slate-700 dark:text-slate-100", children: [formatNumber(bucket.balance), " / ", formatNumber(bucket.total)] })] }), jsxRuntime.jsx("div", { className: "mt-2 h-1.5 w-full rounded-full bg-slate-200 dark:bg-slate-800", children: jsxRuntime.jsx("div", { className: "h-full rounded-full bg-linear-to-r from-purple-500 via-pink-500 to-rose-400 transition-[width]", style: { width: `${percent}%` } }) }), jsxRuntime.jsxs("div", { className: "mt-2 flex items-center justify-between text-[11px] text-slate-500 dark:text-slate-400", children: [jsxRuntime.jsx("span", { children: formatRangeText(bucket.start, bucket.end) }), jsxRuntime.jsxs("span", { children: [percent, "%"] })] })] }, bucket.key));
265
- })) : (jsxRuntime.jsx(EmptyPlaceholder, { label: "No Credits Yet", icon: jsxRuntime.jsx(server.globalLucideIcons.DatabaseZap, { className: "size-4" }) })) })] }), jsxRuntime.jsx(PanelSection, { icon: jsxRuntime.jsx(server.globalLucideIcons.Bell, { className: "size-4" }), title: "Subscription", rightInfo: jsxRuntime.jsx(StatusTag, { value: subStatus }), items: [
265
+ })) : (jsxRuntime.jsx(EmptyPlaceholder, { label: "No Credits Yet", icon: jsxRuntime.jsx(icons.DatabaseZapIcon, { className: "size-4" }) })) })] }), jsxRuntime.jsx(PanelSection, { icon: jsxRuntime.jsx(icons.BellIcon, { className: "size-4" }), title: "Subscription", rightInfo: jsxRuntime.jsx(StatusTag, { value: subStatus }), items: [
266
266
  { label: 'Plan', value: subscriptionStatus.priceName },
267
267
  { label: 'Period', value: subscriptionStatus.period },
268
268
  { label: 'Allocated', value: subscriptionStatus.creditsAllocated },
269
269
  { label: 'SubID', value: jsxRuntime.jsx(ui.CopyableText, { text: (xSubscription === null || xSubscription === void 0 ? void 0 : xSubscription.paySubscriptionId) || '' }) },
270
270
  { label: 'OrderID', value: jsxRuntime.jsx(ui.CopyableText, { text: (xSubscription === null || xSubscription === void 0 ? void 0 : xSubscription.orderId) || '' }) },
271
271
  { label: 'PriceID', value: jsxRuntime.jsx(ui.CopyableText, { text: (xSubscription === null || xSubscription === void 0 ? void 0 : xSubscription.priceId) || '' }) },
272
- ] })] })) : (jsxRuntime.jsxs("div", { className: "space-y-3 rounded-xl border border-slate-200/70 bg-white/85 p-4 shadow-sm dark:border-white/12 dark:bg-slate-900/45", children: [jsxRuntime.jsx(PanelHeader, { icon: jsxRuntime.jsx(server.globalLucideIcons.DatabaseZap, { className: "size-4" }), title: "Concurrent Base Info", rightInfo: jsxRuntime.jsx(StatusTag, { value: isRunningTest ? 'pending' : 'idle' }) }), jsxRuntime.jsxs("div", { className: "space-y-2 text-xs text-slate-500 dark:text-slate-300", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsxRuntime.jsx("span", { className: "text-slate-400 dark:text-slate-500", children: "Real Browser" }), jsxRuntime.jsx(ui.CopyableText, { text: fingerprintId || '' })] }), jsxRuntime.jsxs("div", { className: "space-y-1", children: [jsxRuntime.jsx("span", { className: "text-slate-400 dark:text-slate-500", children: "Test Override" }), jsxRuntime.jsxs("div", { className: "flex items-center gap-2 py-1", children: [jsxRuntime.jsx("div", { className: "min-w-0 flex-1 rounded-lg border border-slate-200 bg-white px-3 py-2 font-mono text-[0.5rem] sm:text-[0.625rem] md:text-xs leading-tight text-slate-700 dark:border-white/10 dark:bg-slate-950 dark:text-slate-100", children: jsxRuntime.jsx(ui.CopyableText, { text: activeDebugFingerprintId || '' }) }), jsxRuntime.jsx("button", { type: "button", disabled: isRunningTest, onClick: regenerateTestFingerprint, "aria-label": "Generate new test fingerprint", className: "inline-flex size-9 items-center justify-center rounded-lg border border-slate-200 bg-slate-50 text-slate-700 transition hover:border-slate-300 hover:bg-slate-100 disabled:cursor-not-allowed disabled:opacity-50 dark:border-white/10 dark:bg-slate-950 dark:text-slate-100 dark:hover:bg-slate-900", children: jsxRuntime.jsx(server.globalLucideIcons.RefreshCcw, { className: "size-4" }) })] })] })] }), jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: [jsxRuntime.jsx("button", { type: "button", disabled: isRunningTest, onClick: runContextParallelInitTest, className: utils.cn('shrink-0 rounded-full border px-3 py-2 text-xs font-semibold transition-all duration-200 disabled:cursor-not-allowed disabled:opacity-50', themedGhostButtonClass), children: "Frontend Prevention Test" }), jsxRuntime.jsx("button", { type: "button", disabled: isRunningTest, onClick: runRawParallelPostTest, className: utils.cn('shrink-0 rounded-full border px-3 py-2 text-xs font-semibold text-white shadow-sm transition-all duration-200 disabled:cursor-not-allowed disabled:opacity-50', 'border-transparent', lib.themeButtonGradientClass, lib.themeButtonGradientHoverClass), children: "Backend Idempotency Test" })] }), jsxRuntime.jsx("div", { className: "rounded-lg border border-dashed border-slate-200 bg-slate-50/80 p-3 dark:border-white/10 dark:bg-slate-950/50", children: jsxRuntime.jsx("pre", { className: "overflow-x-auto whitespace-pre-wrap break-all font-mono text-[11px] leading-5 text-slate-600 dark:text-slate-300", children: testResult || 'No test executed yet.' }) })] })), error && (jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3 rounded-xl border border-amber-200 bg-amber-50 p-3 text-xs text-amber-600 shadow-sm dark:border-amber-500/40 dark:bg-amber-500/10 dark:text-amber-200", children: [jsxRuntime.jsxs("div", { className: "flex items-start gap-2", children: [jsxRuntime.jsx(server.globalLucideIcons.X, { className: "mt-0.5 size-4 shrink-0" }), jsxRuntime.jsx("span", { children: error })] }), jsxRuntime.jsx("button", { type: "button", "aria-label": "Dismiss error", onClick: clearError, className: "shrink-0 rounded-full p-1 text-amber-500 transition hover:bg-amber-100 hover:text-amber-700 dark:text-amber-200 dark:hover:bg-amber-500/10 dark:hover:text-amber-100", children: jsxRuntime.jsx(server.globalLucideIcons.X, { className: "size-4" }) })] }))] })] })] }))] }));
272
+ ] })] })) : (jsxRuntime.jsxs("div", { className: "space-y-3 rounded-xl border border-slate-200/70 bg-white/85 p-4 shadow-sm dark:border-white/12 dark:bg-slate-900/45", children: [jsxRuntime.jsx(PanelHeader, { icon: jsxRuntime.jsx(icons.DatabaseZapIcon, { className: "size-4" }), title: "Concurrent Base Info", rightInfo: jsxRuntime.jsx(StatusTag, { value: isRunningTest ? 'pending' : 'idle' }) }), jsxRuntime.jsxs("div", { className: "space-y-2 text-xs text-slate-500 dark:text-slate-300", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsxRuntime.jsx("span", { className: "text-slate-400 dark:text-slate-500", children: "Real Browser" }), jsxRuntime.jsx(ui.CopyableText, { text: fingerprintId || '' })] }), jsxRuntime.jsxs("div", { className: "space-y-1", children: [jsxRuntime.jsx("span", { className: "text-slate-400 dark:text-slate-500", children: "Test Override" }), jsxRuntime.jsxs("div", { className: "flex items-center gap-2 py-1", children: [jsxRuntime.jsx("div", { className: "min-w-0 flex-1 rounded-lg border border-slate-200 bg-white px-3 py-2 font-mono text-[0.5rem] sm:text-[0.625rem] md:text-xs leading-tight text-slate-700 dark:border-white/10 dark:bg-slate-950 dark:text-slate-100", children: jsxRuntime.jsx(ui.CopyableText, { text: activeDebugFingerprintId || '' }) }), jsxRuntime.jsx("button", { type: "button", disabled: isRunningTest, onClick: regenerateTestFingerprint, "aria-label": "Generate new test fingerprint", className: "inline-flex size-9 items-center justify-center rounded-lg border border-slate-200 bg-slate-50 text-slate-700 transition hover:border-slate-300 hover:bg-slate-100 disabled:cursor-not-allowed disabled:opacity-50 dark:border-white/10 dark:bg-slate-950 dark:text-slate-100 dark:hover:bg-slate-900", children: jsxRuntime.jsx(icons.RefreshCcwIcon, { className: "size-4" }) })] })] })] }), jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: [jsxRuntime.jsx("button", { type: "button", disabled: isRunningTest, onClick: runContextParallelInitTest, className: utils.cn('shrink-0 rounded-full border px-3 py-2 text-xs font-semibold transition-all duration-200 disabled:cursor-not-allowed disabled:opacity-50', themedGhostButtonClass), children: "Frontend Prevention Test" }), jsxRuntime.jsx("button", { type: "button", disabled: isRunningTest, onClick: runRawParallelPostTest, className: utils.cn('shrink-0 rounded-full border px-3 py-2 text-xs font-semibold text-white shadow-sm transition-all duration-200 disabled:cursor-not-allowed disabled:opacity-50', 'border-transparent', lib.themeButtonGradientClass, lib.themeButtonGradientHoverClass), children: "Backend Idempotency Test" })] }), jsxRuntime.jsx("div", { className: "rounded-lg border border-dashed border-slate-200 bg-slate-50/80 p-3 dark:border-white/10 dark:bg-slate-950/50", children: jsxRuntime.jsx("pre", { className: "overflow-x-auto whitespace-pre-wrap break-all font-mono text-[11px] leading-5 text-slate-600 dark:text-slate-300", children: testResult || 'No test executed yet.' }) })] })), error && (jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3 rounded-xl border border-amber-200 bg-amber-50 p-3 text-xs text-amber-600 shadow-sm dark:border-amber-500/40 dark:bg-amber-500/10 dark:text-amber-200", children: [jsxRuntime.jsxs("div", { className: "flex items-start gap-2", children: [jsxRuntime.jsx(icons.XIcon, { className: "mt-0.5 size-4 shrink-0" }), jsxRuntime.jsx("span", { children: error })] }), jsxRuntime.jsx("button", { type: "button", "aria-label": "Dismiss error", onClick: clearError, className: "shrink-0 rounded-full p-1 text-amber-500 transition hover:bg-amber-100 hover:text-amber-700 dark:text-amber-200 dark:hover:bg-amber-500/10 dark:hover:text-amber-100", children: jsxRuntime.jsx(icons.XIcon, { className: "size-4" }) })] }))] })] })] }))] }));
273
273
  }
274
274
  /* ==================== 新增辅助组件 ==================== */
275
275
  // 标题行:左侧图标+标题,右侧信息(右对齐)
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { __awaiter } from 'tslib';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
- import { globalLucideIcons } from '@windrun-huaiin/base-ui/components/server';
4
+ import { Settings2Icon, CoinsIcon, GiftIcon, LightbulbIcon, ShieldUserIcon, XIcon, FingerprintIcon, GemIcon, DatabaseZapIcon, BellIcon, RefreshCcwIcon } from '@windrun-huaiin/base-ui/icons';
5
5
  import { themeIconColor, themeButtonGradientClass, themeButtonGradientHoverClass } from '@windrun-huaiin/base-ui/lib';
6
6
  import { cn } from '@windrun-huaiin/lib/utils';
7
7
  import { createContext, useContext, useState, useRef, useEffect, useMemo } from 'react';
@@ -91,7 +91,7 @@ function FingerprintStatus() {
91
91
  {
92
92
  key: 'paid',
93
93
  label: 'Paid',
94
- icon: jsx(globalLucideIcons.Settings2, { className: "size-4 text-green-500 dark:text-green-300" }),
94
+ icon: jsx(Settings2Icon, { className: "size-4 text-green-500 dark:text-green-300" }),
95
95
  balance: xCredit.balancePaid,
96
96
  total: xCredit.totalPaidLimit,
97
97
  start: xCredit.paidStart,
@@ -100,7 +100,7 @@ function FingerprintStatus() {
100
100
  {
101
101
  key: 'oneTimePaid',
102
102
  label: 'OneTimePaid',
103
- icon: jsx(globalLucideIcons.Coins, { className: "size-4 text-amber-500 dark:text-amber-300" }),
103
+ icon: jsx(CoinsIcon, { className: "size-4 text-amber-500 dark:text-amber-300" }),
104
104
  balance: xCredit.balanceOneTimePaid,
105
105
  total: xCredit.totalOneTimePaidLimit,
106
106
  start: xCredit.oneTimePaidStart,
@@ -109,7 +109,7 @@ function FingerprintStatus() {
109
109
  {
110
110
  key: 'free',
111
111
  label: 'Free',
112
- icon: jsx(globalLucideIcons.Gift, { className: "size-4 text-purple-500 dark:text-purple-300" }),
112
+ icon: jsx(GiftIcon, { className: "size-4 text-purple-500 dark:text-purple-300" }),
113
113
  balance: xCredit.balanceFree,
114
114
  total: xCredit.totalFreeLimit,
115
115
  start: xCredit.freeStart,
@@ -245,11 +245,11 @@ function FingerprintStatus() {
245
245
  setActiveDebugFingerprintId(nextFingerprintId);
246
246
  setTestResult(`Generated test fingerprint override: ${nextFingerprintId}`);
247
247
  };
248
- return (jsxs(Fragment, { children: [!isOpen && (jsx("button", { onClick: handleToggle, type: "button", "aria-label": "Fingerprint debug panel", className: cn('fixed left-2 top-2 md:left-2 md:top-3 z-10000 inline-flex size-8 md:size-11 items-center justify-center rounded-full', themeButtonGradientClass, themeButtonGradientHoverClass, 'text-white rounded-full shadow-lg hover:shadow-xl transition-all duration-300'), children: jsx(globalLucideIcons.Lightbulb, { className: "size-6 text-white" }) })), isOpen && (jsxs(Fragment, { children: [jsx("div", { onClick: handleBackdropClick, className: "fixed inset-0 z-9998 bg-black/60 backdrop-blur-sm" }), jsxs("div", { ref: modalRef, className: cn('fixed inset-3 z-9999 mx-auto w-[min(95vw,520px)] overflow-y-auto rounded-2xl border', 'border-slate-200/70 bg-white/95 p-4 shadow-2xl backdrop-blur-sm', 'font-sans text-sm text-slate-700 dark:border-white/12 dark:bg-slate-950/95 dark:text-slate-200', 'sm:inset-auto md:left-2 sm:top-1 md:right-auto sm:w-[min(520px,95vw)] sm:p-5'), children: [jsx("header", { className: "mb-4", children: jsxs("div", { className: "flex items-start justify-between gap-3", children: [jsxs("div", { className: cn("flex items-center gap-2 text-base font-bold tracking-wider", themeIconColor), children: [jsx(globalLucideIcons.ShieldUser, { className: "size-4" }), "Fingerprint Debug Panel"] }), jsxs("div", { className: "flex items-center gap-2", children: [jsxs("button", { type: "button", onClick: () => setPanelMode((prev) => prev === 'info' ? 'test' : 'info'), className: cn('inline-flex items-center gap-2 rounded-full border px-2 py-1 text-[11px] font-semibold shadow-sm transition-all duration-200', panelMode === 'test'
248
+ return (jsxs(Fragment, { children: [!isOpen && (jsx("button", { onClick: handleToggle, type: "button", "aria-label": "Fingerprint debug panel", className: cn('fixed left-2 top-2 md:left-2 md:top-3 z-10000 inline-flex size-8 md:size-11 items-center justify-center rounded-full', themeButtonGradientClass, themeButtonGradientHoverClass, 'text-white rounded-full shadow-lg hover:shadow-xl transition-all duration-300'), children: jsx(LightbulbIcon, { className: "size-6 text-white" }) })), isOpen && (jsxs(Fragment, { children: [jsx("div", { onClick: handleBackdropClick, className: "fixed inset-0 z-9998 bg-black/60 backdrop-blur-sm" }), jsxs("div", { ref: modalRef, className: cn('fixed inset-3 z-9999 mx-auto w-[min(95vw,520px)] overflow-y-auto rounded-2xl border', 'border-slate-200/70 bg-white/95 p-4 shadow-2xl backdrop-blur-sm', 'font-sans text-sm text-slate-700 dark:border-white/12 dark:bg-slate-950/95 dark:text-slate-200', 'sm:inset-auto md:left-2 sm:top-1 md:right-auto sm:w-[min(520px,95vw)] sm:p-5'), children: [jsx("header", { className: "mb-4", children: jsxs("div", { className: "flex items-start justify-between gap-3", children: [jsxs("div", { className: cn("flex items-center gap-2 text-base font-bold tracking-wider", themeIconColor), children: [jsx(ShieldUserIcon, { className: "size-4" }), "Fingerprint Debug Panel"] }), jsxs("div", { className: "flex items-center gap-2", children: [jsxs("button", { type: "button", onClick: () => setPanelMode((prev) => prev === 'info' ? 'test' : 'info'), className: cn('inline-flex items-center gap-2 rounded-full border px-2 py-1 text-[11px] font-semibold shadow-sm transition-all duration-200', panelMode === 'test'
249
249
  ? cn('border-transparent text-white', themeButtonGradientClass, themeButtonGradientHoverClass)
250
250
  : themedGhostButtonClass), "aria-pressed": panelMode === 'test', children: [jsx("span", { children: "Concurrent Test" }), jsx("span", { className: cn('relative inline-flex h-5 w-9 items-center rounded-full transition-colors', panelMode === 'test'
251
251
  ? 'bg-white/25'
252
- : 'bg-slate-300 dark:bg-slate-700'), children: jsx("span", { className: cn('inline-block size-4 rounded-full shadow-sm transition-transform', panelMode === 'test' ? 'bg-white' : 'bg-white dark:bg-slate-100', panelMode === 'test' ? 'translate-x-4' : 'translate-x-0.5') }) })] }), jsx("button", { type: "button", "aria-label": "Close fingerprint panel", className: "rounded-full p-2 text-slate-500 transition hover:bg-slate-100 hover:text-slate-700 dark:text-slate-300 dark:hover:bg-white/10 dark:hover:text-white", onClick: () => setIsOpen(false), children: jsx(globalLucideIcons.X, { className: "size-4" }) })] })] }) }), jsxs("section", { className: "space-y-1", children: [panelMode === 'info' ? (jsxs(Fragment, { children: [jsx(PanelSection, { icon: jsx(globalLucideIcons.Fingerprint, { className: "size-4" }), title: "User", rightInfo: jsx(StatusTag, { value: userStatus }), items: [
252
+ : 'bg-slate-300 dark:bg-slate-700'), children: jsx("span", { className: cn('inline-block size-4 rounded-full shadow-sm transition-transform', panelMode === 'test' ? 'bg-white' : 'bg-white dark:bg-slate-100', panelMode === 'test' ? 'translate-x-4' : 'translate-x-0.5') }) })] }), jsx("button", { type: "button", "aria-label": "Close fingerprint panel", className: "rounded-full p-2 text-slate-500 transition hover:bg-slate-100 hover:text-slate-700 dark:text-slate-300 dark:hover:bg-white/10 dark:hover:text-white", onClick: () => setIsOpen(false), children: jsx(XIcon, { className: "size-4" }) })] })] }) }), jsxs("section", { className: "space-y-1", children: [panelMode === 'info' ? (jsxs(Fragment, { children: [jsx(PanelSection, { icon: jsx(FingerprintIcon, { className: "size-4" }), title: "User", rightInfo: jsx(StatusTag, { value: userStatus }), items: [
253
253
  { label: 'UserID', value: jsx(CopyableText, { text: (xUser === null || xUser === void 0 ? void 0 : xUser.userId) || '' }) },
254
254
  { label: 'NickName', value: jsx(CopyableText, { text: (xUser === null || xUser === void 0 ? void 0 : xUser.userName) || '' }) },
255
255
  { label: 'FingerprintID', value: jsx(CopyableText, { text: (xUser === null || xUser === void 0 ? void 0 : xUser.fingerprintId) || fingerprintId || '' }) },
@@ -257,17 +257,17 @@ function FingerprintStatus() {
257
257
  { label: 'Email', value: jsx(CopyableText, { text: (xUser === null || xUser === void 0 ? void 0 : xUser.email) || '' }) },
258
258
  { label: 'StripeCusID', value: jsx(CopyableText, { text: (xUser === null || xUser === void 0 ? void 0 : xUser.stripeCusId) || '' }) },
259
259
  { label: 'CreatedAt', value: (xUser === null || xUser === void 0 ? void 0 : xUser.createdAt) || '--' },
260
- ] }), jsxs("div", { className: "space-y-2 rounded-xl border border-slate-200/70 bg-white/80 p-4 shadow-sm dark:border-white/12 dark:bg-slate-900/50", children: [jsx(PanelHeader, { icon: jsx(globalLucideIcons.Gem, { className: "size-4" }), title: "Credits Info", rightInfo: jsx("span", { className: cn("font-semibold", themeIconColor), children: totalCredits }) }), jsx("div", { className: "space-y-3", children: creditBuckets.length > 0 ? (creditBuckets.map((bucket) => {
260
+ ] }), jsxs("div", { className: "space-y-2 rounded-xl border border-slate-200/70 bg-white/80 p-4 shadow-sm dark:border-white/12 dark:bg-slate-900/50", children: [jsx(PanelHeader, { icon: jsx(GemIcon, { className: "size-4" }), title: "Credits Info", rightInfo: jsx("span", { className: cn("font-semibold", themeIconColor), children: totalCredits }) }), jsx("div", { className: "space-y-3", children: creditBuckets.length > 0 ? (creditBuckets.map((bucket) => {
261
261
  const percent = Math.round(computeProgress(bucket.balance, bucket.total) * 100);
262
262
  return (jsxs("div", { className: "rounded-lg border border-slate-200/70 bg-white/70 p-3 dark:border-white/10 dark:bg-slate-900/40", children: [jsxs("div", { className: "flex items-center justify-between text-xs font-medium text-slate-600 dark:text-slate-300", children: [jsxs("div", { className: "flex items-center gap-1.5", children: [bucket.icon, jsx("span", { children: bucket.label })] }), jsxs("span", { className: "font-semibold text-slate-700 dark:text-slate-100", children: [formatNumber(bucket.balance), " / ", formatNumber(bucket.total)] })] }), jsx("div", { className: "mt-2 h-1.5 w-full rounded-full bg-slate-200 dark:bg-slate-800", children: jsx("div", { className: "h-full rounded-full bg-linear-to-r from-purple-500 via-pink-500 to-rose-400 transition-[width]", style: { width: `${percent}%` } }) }), jsxs("div", { className: "mt-2 flex items-center justify-between text-[11px] text-slate-500 dark:text-slate-400", children: [jsx("span", { children: formatRangeText(bucket.start, bucket.end) }), jsxs("span", { children: [percent, "%"] })] })] }, bucket.key));
263
- })) : (jsx(EmptyPlaceholder, { label: "No Credits Yet", icon: jsx(globalLucideIcons.DatabaseZap, { className: "size-4" }) })) })] }), jsx(PanelSection, { icon: jsx(globalLucideIcons.Bell, { className: "size-4" }), title: "Subscription", rightInfo: jsx(StatusTag, { value: subStatus }), items: [
263
+ })) : (jsx(EmptyPlaceholder, { label: "No Credits Yet", icon: jsx(DatabaseZapIcon, { className: "size-4" }) })) })] }), jsx(PanelSection, { icon: jsx(BellIcon, { className: "size-4" }), title: "Subscription", rightInfo: jsx(StatusTag, { value: subStatus }), items: [
264
264
  { label: 'Plan', value: subscriptionStatus.priceName },
265
265
  { label: 'Period', value: subscriptionStatus.period },
266
266
  { label: 'Allocated', value: subscriptionStatus.creditsAllocated },
267
267
  { label: 'SubID', value: jsx(CopyableText, { text: (xSubscription === null || xSubscription === void 0 ? void 0 : xSubscription.paySubscriptionId) || '' }) },
268
268
  { label: 'OrderID', value: jsx(CopyableText, { text: (xSubscription === null || xSubscription === void 0 ? void 0 : xSubscription.orderId) || '' }) },
269
269
  { label: 'PriceID', value: jsx(CopyableText, { text: (xSubscription === null || xSubscription === void 0 ? void 0 : xSubscription.priceId) || '' }) },
270
- ] })] })) : (jsxs("div", { className: "space-y-3 rounded-xl border border-slate-200/70 bg-white/85 p-4 shadow-sm dark:border-white/12 dark:bg-slate-900/45", children: [jsx(PanelHeader, { icon: jsx(globalLucideIcons.DatabaseZap, { className: "size-4" }), title: "Concurrent Base Info", rightInfo: jsx(StatusTag, { value: isRunningTest ? 'pending' : 'idle' }) }), jsxs("div", { className: "space-y-2 text-xs text-slate-500 dark:text-slate-300", children: [jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsx("span", { className: "text-slate-400 dark:text-slate-500", children: "Real Browser" }), jsx(CopyableText, { text: fingerprintId || '' })] }), jsxs("div", { className: "space-y-1", children: [jsx("span", { className: "text-slate-400 dark:text-slate-500", children: "Test Override" }), jsxs("div", { className: "flex items-center gap-2 py-1", children: [jsx("div", { className: "min-w-0 flex-1 rounded-lg border border-slate-200 bg-white px-3 py-2 font-mono text-[0.5rem] sm:text-[0.625rem] md:text-xs leading-tight text-slate-700 dark:border-white/10 dark:bg-slate-950 dark:text-slate-100", children: jsx(CopyableText, { text: activeDebugFingerprintId || '' }) }), jsx("button", { type: "button", disabled: isRunningTest, onClick: regenerateTestFingerprint, "aria-label": "Generate new test fingerprint", className: "inline-flex size-9 items-center justify-center rounded-lg border border-slate-200 bg-slate-50 text-slate-700 transition hover:border-slate-300 hover:bg-slate-100 disabled:cursor-not-allowed disabled:opacity-50 dark:border-white/10 dark:bg-slate-950 dark:text-slate-100 dark:hover:bg-slate-900", children: jsx(globalLucideIcons.RefreshCcw, { className: "size-4" }) })] })] })] }), jsxs("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: [jsx("button", { type: "button", disabled: isRunningTest, onClick: runContextParallelInitTest, className: cn('shrink-0 rounded-full border px-3 py-2 text-xs font-semibold transition-all duration-200 disabled:cursor-not-allowed disabled:opacity-50', themedGhostButtonClass), children: "Frontend Prevention Test" }), jsx("button", { type: "button", disabled: isRunningTest, onClick: runRawParallelPostTest, className: cn('shrink-0 rounded-full border px-3 py-2 text-xs font-semibold text-white shadow-sm transition-all duration-200 disabled:cursor-not-allowed disabled:opacity-50', 'border-transparent', themeButtonGradientClass, themeButtonGradientHoverClass), children: "Backend Idempotency Test" })] }), jsx("div", { className: "rounded-lg border border-dashed border-slate-200 bg-slate-50/80 p-3 dark:border-white/10 dark:bg-slate-950/50", children: jsx("pre", { className: "overflow-x-auto whitespace-pre-wrap break-all font-mono text-[11px] leading-5 text-slate-600 dark:text-slate-300", children: testResult || 'No test executed yet.' }) })] })), error && (jsxs("div", { className: "flex items-start justify-between gap-3 rounded-xl border border-amber-200 bg-amber-50 p-3 text-xs text-amber-600 shadow-sm dark:border-amber-500/40 dark:bg-amber-500/10 dark:text-amber-200", children: [jsxs("div", { className: "flex items-start gap-2", children: [jsx(globalLucideIcons.X, { className: "mt-0.5 size-4 shrink-0" }), jsx("span", { children: error })] }), jsx("button", { type: "button", "aria-label": "Dismiss error", onClick: clearError, className: "shrink-0 rounded-full p-1 text-amber-500 transition hover:bg-amber-100 hover:text-amber-700 dark:text-amber-200 dark:hover:bg-amber-500/10 dark:hover:text-amber-100", children: jsx(globalLucideIcons.X, { className: "size-4" }) })] }))] })] })] }))] }));
270
+ ] })] })) : (jsxs("div", { className: "space-y-3 rounded-xl border border-slate-200/70 bg-white/85 p-4 shadow-sm dark:border-white/12 dark:bg-slate-900/45", children: [jsx(PanelHeader, { icon: jsx(DatabaseZapIcon, { className: "size-4" }), title: "Concurrent Base Info", rightInfo: jsx(StatusTag, { value: isRunningTest ? 'pending' : 'idle' }) }), jsxs("div", { className: "space-y-2 text-xs text-slate-500 dark:text-slate-300", children: [jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsx("span", { className: "text-slate-400 dark:text-slate-500", children: "Real Browser" }), jsx(CopyableText, { text: fingerprintId || '' })] }), jsxs("div", { className: "space-y-1", children: [jsx("span", { className: "text-slate-400 dark:text-slate-500", children: "Test Override" }), jsxs("div", { className: "flex items-center gap-2 py-1", children: [jsx("div", { className: "min-w-0 flex-1 rounded-lg border border-slate-200 bg-white px-3 py-2 font-mono text-[0.5rem] sm:text-[0.625rem] md:text-xs leading-tight text-slate-700 dark:border-white/10 dark:bg-slate-950 dark:text-slate-100", children: jsx(CopyableText, { text: activeDebugFingerprintId || '' }) }), jsx("button", { type: "button", disabled: isRunningTest, onClick: regenerateTestFingerprint, "aria-label": "Generate new test fingerprint", className: "inline-flex size-9 items-center justify-center rounded-lg border border-slate-200 bg-slate-50 text-slate-700 transition hover:border-slate-300 hover:bg-slate-100 disabled:cursor-not-allowed disabled:opacity-50 dark:border-white/10 dark:bg-slate-950 dark:text-slate-100 dark:hover:bg-slate-900", children: jsx(RefreshCcwIcon, { className: "size-4" }) })] })] })] }), jsxs("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: [jsx("button", { type: "button", disabled: isRunningTest, onClick: runContextParallelInitTest, className: cn('shrink-0 rounded-full border px-3 py-2 text-xs font-semibold transition-all duration-200 disabled:cursor-not-allowed disabled:opacity-50', themedGhostButtonClass), children: "Frontend Prevention Test" }), jsx("button", { type: "button", disabled: isRunningTest, onClick: runRawParallelPostTest, className: cn('shrink-0 rounded-full border px-3 py-2 text-xs font-semibold text-white shadow-sm transition-all duration-200 disabled:cursor-not-allowed disabled:opacity-50', 'border-transparent', themeButtonGradientClass, themeButtonGradientHoverClass), children: "Backend Idempotency Test" })] }), jsx("div", { className: "rounded-lg border border-dashed border-slate-200 bg-slate-50/80 p-3 dark:border-white/10 dark:bg-slate-950/50", children: jsx("pre", { className: "overflow-x-auto whitespace-pre-wrap break-all font-mono text-[11px] leading-5 text-slate-600 dark:text-slate-300", children: testResult || 'No test executed yet.' }) })] })), error && (jsxs("div", { className: "flex items-start justify-between gap-3 rounded-xl border border-amber-200 bg-amber-50 p-3 text-xs text-amber-600 shadow-sm dark:border-amber-500/40 dark:bg-amber-500/10 dark:text-amber-200", children: [jsxs("div", { className: "flex items-start gap-2", children: [jsx(XIcon, { className: "mt-0.5 size-4 shrink-0" }), jsx("span", { children: error })] }), jsx("button", { type: "button", "aria-label": "Dismiss error", onClick: clearError, className: "shrink-0 rounded-full p-1 text-amber-500 transition hover:bg-amber-100 hover:text-amber-700 dark:text-amber-200 dark:hover:bg-amber-500/10 dark:hover:text-amber-100", children: jsx(XIcon, { className: "size-4" }) })] }))] })] })] }))] }));
271
271
  }
272
272
  /* ==================== 新增辅助组件 ==================== */
273
273
  // 标题行:左侧图标+标题,右侧信息(右对齐)
@@ -5,8 +5,8 @@ var tslib = require('tslib');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var React = require('react');
7
7
  var classVarianceAuthority = require('class-variance-authority');
8
+ var icons = require('@windrun-huaiin/base-ui/icons');
8
9
  var Link = require('fumadocs-core/link');
9
- var server = require('@windrun-huaiin/base-ui/components/server');
10
10
  var shared = require('fumadocs-ui/layouts/shared');
11
11
  var cn = require('fumadocs-ui/utils/cn');
12
12
  var searchToggle = require('fumadocs-ui/components/layout/search-toggle');
@@ -59,7 +59,7 @@ function CustomHomeHeader({ nav = {}, i18n = false, links, githubUrl, themeSwitc
59
59
  theme: themeSwitch.enabled !== false
60
60
  ? (_c = themeSwitch.component) !== null && _c !== void 0 ? _c : jsxRuntime.jsx(themeToggle.ThemeToggle, { mode: themeSwitch === null || themeSwitch === void 0 ? void 0 : themeSwitch.mode })
61
61
  : null,
62
- i18n: i18n ? (jsxRuntime.jsx(CompactLanguageToggle, { children: jsxRuntime.jsx(server.globalLucideIcons.Languages, { className: "size-5" }) })) : null,
62
+ i18n: i18n ? (jsxRuntime.jsx(CompactLanguageToggle, { children: jsxRuntime.jsx(icons.LanguagesIcon, { className: "size-5" }) })) : null,
63
63
  secondary: desktopSecondaryDisplayItems.length ? (jsxRuntime.jsx("ul", { className: "flex flex-row gap-2 items-center empty:hidden", children: desktopSecondaryDisplayItems.map((item, i) => (jsxRuntime.jsx(NavbarLinkItem, { item: item, className: cn.cn(item.type === 'icon' && [
64
64
  '-mx-1',
65
65
  i === 0 && 'ms-0',
@@ -78,7 +78,7 @@ function CustomHomeHeader({ nav = {}, i18n = false, links, githubUrl, themeSwitc
78
78
  secondary: secondaryMenuDisplayItems.length ? (jsxRuntime.jsx(jsxRuntime.Fragment, { children: secondaryMenuDisplayItems.map((item, i) => (jsxRuntime.jsx(MenuLinkItem, { item: item, className: "-me-1.5" }, i))) })) : null,
79
79
  github: githubMobileMenuItem ? (jsxRuntime.jsx(MenuLinkItem, { item: githubMobileMenuItem, className: "-me-1.5" })) : null,
80
80
  separator: jsxRuntime.jsx("div", { role: "separator", className: "flex-1" }),
81
- i18n: i18n ? (jsxRuntime.jsxs(CompactLanguageToggle, { children: [jsxRuntime.jsx(server.globalLucideIcons.Languages, { className: "size-5" }), jsxRuntime.jsx(languageToggle.LanguageToggleText, {}), jsxRuntime.jsx(server.globalLucideIcons.ChevronDown, { className: "size-3 text-fd-muted-foreground" })] })) : null,
81
+ i18n: i18n ? (jsxRuntime.jsxs(CompactLanguageToggle, { children: [jsxRuntime.jsx(icons.LanguagesIcon, { className: "size-5" }), jsxRuntime.jsx(languageToggle.LanguageToggleText, {}), jsxRuntime.jsx(icons.ChevronDownIcon, { className: "size-3 text-fd-muted-foreground" })] })) : null,
82
82
  theme: themeSwitch.enabled !== false
83
83
  ? (_d = themeSwitch.component) !== null && _d !== void 0 ? _d : jsxRuntime.jsx(themeToggle.ThemeToggle, { mode: themeSwitch === null || themeSwitch === void 0 ? void 0 : themeSwitch.mode })
84
84
  : null,
@@ -93,7 +93,7 @@ function CustomHomeHeader({ nav = {}, i18n = false, links, githubUrl, themeSwitc
93
93
  size: 'icon',
94
94
  color: 'ghost',
95
95
  className: 'group [&_svg]:size-5.5',
96
- })), enableHover: nav.enableHoverToOpen, children: jsxRuntime.jsx(server.globalLucideIcons.ChevronDown, { className: "transition-transform duration-300 group-data-[state=open]:rotate-180" }) }), jsxRuntime.jsxs(MenuContent, { className: "sm:flex-row sm:items-center sm:justify-end", children: [primaryMenuItems.map((item, i) => (jsxRuntime.jsx(MenuLinkItem, { item: item, className: "sm:hidden" }, i))), shouldRenderMobileUtilities ? (jsxRuntime.jsx("div", { className: "-ms-1.5 flex flex-row items-center gap-1.5 max-sm:mt-2", children: mobileMenuActionsOrder.map((action) => {
96
+ })), enableHover: nav.enableHoverToOpen, children: jsxRuntime.jsx(icons.ChevronDownIcon, { className: "transition-transform duration-300 group-data-[state=open]:rotate-180" }) }), jsxRuntime.jsxs(MenuContent, { className: "sm:flex-row sm:items-center sm:justify-end", children: [primaryMenuItems.map((item, i) => (jsxRuntime.jsx(MenuLinkItem, { item: item, className: "sm:hidden" }, i))), shouldRenderMobileUtilities ? (jsxRuntime.jsx("div", { className: "-ms-1.5 flex flex-row items-center gap-1.5 max-sm:mt-2", children: mobileMenuActionsOrder.map((action) => {
97
97
  const node = renderMobileMenuAction(action);
98
98
  if (!node)
99
99
  return null;