@windrun-huaiin/third-ui 15.1.0 → 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.
- package/LICENSE +1 -1
- package/dist/ai/ai-chat-composer.d.ts +2 -0
- package/dist/ai/ai-chat-composer.js +47 -0
- package/dist/ai/ai-chat-composer.mjs +45 -0
- package/dist/ai/ai-markdown.d.ts +2 -0
- package/dist/ai/ai-markdown.js +36 -0
- package/dist/ai/ai-markdown.mjs +34 -0
- package/dist/ai/ai-message-actions.d.ts +2 -0
- package/dist/ai/ai-message-actions.js +14 -0
- package/dist/ai/ai-message-actions.mjs +12 -0
- package/dist/ai/ai-message-bubble.d.ts +2 -0
- package/dist/ai/ai-message-bubble.js +66 -0
- package/dist/ai/ai-message-bubble.mjs +64 -0
- package/dist/ai/ai-message-content.d.ts +2 -0
- package/dist/ai/ai-message-content.js +63 -0
- package/dist/ai/ai-message-content.mjs +61 -0
- package/dist/ai/ai-message-list.d.ts +2 -0
- package/dist/ai/ai-message-list.js +24 -0
- package/dist/ai/ai-message-list.mjs +22 -0
- package/dist/ai/ai-message-meta.d.ts +2 -0
- package/dist/ai/ai-message-meta.js +38 -0
- package/dist/ai/ai-message-meta.mjs +36 -0
- package/dist/ai/ai-status-indicator.d.ts +2 -0
- package/dist/ai/ai-status-indicator.js +51 -0
- package/dist/ai/ai-status-indicator.mjs +49 -0
- package/dist/ai/index.d.ts +11 -0
- package/dist/ai/index.js +33 -0
- package/dist/ai/index.mjs +11 -0
- package/dist/ai/types.d.ts +110 -0
- package/dist/ai/use-ai-conversation.d.ts +13 -0
- package/dist/ai/use-ai-conversation.js +276 -0
- package/dist/ai/use-ai-conversation.mjs +274 -0
- package/dist/clerk/clerk-organization-client.js +2 -2
- package/dist/clerk/clerk-organization-client.mjs +2 -2
- package/dist/clerk/clerk-page-generator.d.ts +1 -1
- package/dist/clerk/clerk-user-client.js +2 -2
- package/dist/clerk/clerk-user-client.mjs +2 -2
- package/dist/clerk/fingerprint/fingerprint-provider.js +9 -9
- package/dist/clerk/fingerprint/fingerprint-provider.mjs +9 -9
- package/dist/fuma/base/custom-header.js +4 -4
- package/dist/fuma/base/custom-header.mjs +4 -4
- package/dist/fuma/mdx/banner.js +3 -3
- package/dist/fuma/mdx/banner.mjs +3 -3
- package/dist/fuma/mdx/fuma-github-info.js +3 -3
- package/dist/fuma/mdx/fuma-github-info.mjs +3 -3
- package/dist/fuma/mdx/gradient-button.js +3 -3
- package/dist/fuma/mdx/gradient-button.mjs +3 -3
- package/dist/fuma/mdx/index.d.ts +1 -0
- package/dist/fuma/mdx/index.js +2 -0
- package/dist/fuma/mdx/index.mjs +1 -0
- package/dist/fuma/mdx/markdown-component-map.d.ts +3 -0
- package/dist/fuma/mdx/markdown-component-map.js +73 -0
- package/dist/fuma/mdx/markdown-component-map.mjs +71 -0
- package/dist/fuma/mdx/mermaid.d.ts +2 -1
- package/dist/fuma/mdx/mermaid.js +130 -6
- package/dist/fuma/mdx/mermaid.mjs +130 -6
- package/dist/fuma/mdx/toc-base.js +4 -4
- package/dist/fuma/mdx/toc-base.mjs +4 -4
- package/dist/fuma/mdx/trophy-card.js +2 -2
- package/dist/fuma/mdx/trophy-card.mjs +2 -2
- package/dist/fuma/mdx/zia-card.js +3 -3
- package/dist/fuma/mdx/zia-card.mjs +3 -3
- package/dist/fuma/mdx/zia-file.js +3 -3
- package/dist/fuma/mdx/zia-file.mjs +3 -3
- package/dist/main/ads-alert-dialog.js +2 -2
- package/dist/main/ads-alert-dialog.mjs +2 -2
- package/dist/main/credit/credit-nav-button.js +2 -2
- package/dist/main/credit/credit-nav-button.mjs +2 -2
- package/dist/main/credit/credit-overview-client.js +4 -4
- package/dist/main/credit/credit-overview-client.mjs +4 -4
- package/dist/main/footer.js +2 -2
- package/dist/main/footer.mjs +2 -2
- package/dist/main/go-to-top.js +2 -2
- package/dist/main/go-to-top.mjs +2 -2
- package/dist/main/hero-media.d.ts +14 -0
- package/dist/main/hero-media.js +12 -0
- package/dist/main/hero-media.mjs +10 -0
- package/dist/main/hero-section.d.ts +10 -0
- package/dist/main/hero-section.js +11 -0
- package/dist/main/hero-section.mjs +9 -0
- package/dist/main/index.d.ts +3 -0
- package/dist/main/index.js +6 -0
- package/dist/main/index.mjs +3 -0
- package/dist/main/info-tooltip.d.ts +8 -0
- package/dist/main/info-tooltip.js +48 -0
- package/dist/main/info-tooltip.mjs +46 -0
- package/dist/main/pill-select/x-pill-select.js +2 -2
- package/dist/main/pill-select/x-pill-select.mjs +2 -2
- package/dist/main/pill-select/x-token-input.js +2 -2
- package/dist/main/pill-select/x-token-input.mjs +2 -2
- package/dist/main/x-button.js +3 -3
- package/dist/main/x-button.mjs +3 -3
- package/package.json +16 -3
- package/src/ai/ai-chat-composer.tsx +187 -0
- package/src/ai/ai-markdown.tsx +45 -0
- package/src/ai/ai-message-actions.tsx +16 -0
- package/src/ai/ai-message-bubble.tsx +138 -0
- package/src/ai/ai-message-content.tsx +149 -0
- package/src/ai/ai-message-list.tsx +59 -0
- package/src/ai/ai-message-meta.tsx +56 -0
- package/src/ai/ai-status-indicator.tsx +61 -0
- package/src/ai/index.ts +13 -0
- package/src/ai/types.ts +131 -0
- package/src/ai/use-ai-conversation.ts +422 -0
- package/src/clerk/clerk-organization-client.tsx +5 -5
- package/src/clerk/clerk-page-generator.tsx +1 -1
- package/src/clerk/clerk-user-client.tsx +4 -4
- package/src/clerk/fingerprint/fingerprint-provider.tsx +34 -22
- package/src/fuma/base/custom-header.tsx +5 -5
- package/src/fuma/mdx/banner.tsx +3 -3
- package/src/fuma/mdx/fuma-github-info.tsx +4 -4
- package/src/fuma/mdx/gradient-button.tsx +3 -3
- package/src/fuma/mdx/index.ts +2 -1
- package/src/fuma/mdx/markdown-component-map.tsx +174 -0
- package/src/fuma/mdx/mermaid.tsx +145 -10
- package/src/fuma/mdx/toc-base.tsx +5 -5
- package/src/fuma/mdx/trophy-card.tsx +2 -2
- package/src/fuma/mdx/zia-card.tsx +3 -3
- package/src/fuma/mdx/zia-file.tsx +3 -3
- package/src/main/ads-alert-dialog.tsx +5 -5
- package/src/main/credit/credit-nav-button.tsx +3 -3
- package/src/main/credit/credit-overview-client.tsx +15 -7
- package/src/main/features.tsx +5 -3
- package/src/main/footer.tsx +4 -5
- package/src/main/go-to-top.tsx +2 -2
- package/src/main/hero-media.tsx +53 -0
- package/src/main/hero-section.tsx +36 -0
- package/src/main/index.ts +5 -0
- package/src/main/info-tooltip.tsx +99 -0
- package/src/main/language-detector.tsx +4 -4
- package/src/main/pill-select/x-pill-select.tsx +2 -2
- package/src/main/pill-select/x-token-input.tsx +2 -2
- 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
|
|
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(
|
|
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 {
|
|
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(
|
|
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 };
|
|
@@ -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
|
|
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(
|
|
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 {
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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 {
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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;
|