@nextclaw/ui 0.5.37 → 0.5.38
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/CHANGELOG.md +6 -0
- package/dist/assets/{ChannelsList-DtvhbEV9.js → ChannelsList-3B_zyiKA.js} +1 -1
- package/dist/assets/{ChatPage-Bw_aXB4R.js → ChatPage-DusH09PT.js} +1 -1
- package/dist/assets/{CronConfig-BZLXcDbm.js → CronConfig-5GTz5wPt.js} +1 -1
- package/dist/assets/DocBrowser-BtqGmg0N.js +1 -0
- package/dist/assets/MarketplacePage-BEW4M9BT.js +49 -0
- package/dist/assets/{ModelConfig-Bi8Q4_NG.js → ModelConfig-CwxXYqME.js} +1 -1
- package/dist/assets/{ProvidersList-D2OB0siE.js → ProvidersList-D4oaYHpJ.js} +1 -1
- package/dist/assets/{RuntimeConfig-Bz9aUkwu.js → RuntimeConfig-BwTxGi_U.js} +1 -1
- package/dist/assets/{SecretsConfig-Bqi-biOL.js → SecretsConfig-x36MY4ym.js} +1 -1
- package/dist/assets/{SessionsConfig-DcWT2QvI.js → SessionsConfig-qEffYDZ0.js} +1 -1
- package/dist/assets/{card-DwZkVl7S.js → card-Bq6uwDJQ.js} +1 -1
- package/dist/assets/index-DMEuanmd.css +1 -0
- package/dist/assets/index-wB2uPrKu.js +2 -0
- package/dist/assets/{label-BBDuC6Nm.js → label-Cq1vSfWg.js} +1 -1
- package/dist/assets/{logos-DMFt4YDI.js → logos-BKBMs40Q.js} +1 -1
- package/dist/assets/{page-layout-hPFzCUTQ.js → page-layout-D8MW2vP-.js} +1 -1
- package/dist/assets/{switch-CwkcbkEs.js → switch-CycMxy31.js} +1 -1
- package/dist/assets/{tabs-custom-TUrWRyYy.js → tabs-custom-N4olWJSw.js} +1 -1
- package/dist/assets/{useConfig-DZVUrqQz.js → useConfig-tR_KAfMV.js} +1 -1
- package/dist/assets/{useConfirmDialog-D5X0Iqid.js → useConfirmDialog-DE0Yp8Ai.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +1 -1
- package/src/api/marketplace.ts +24 -0
- package/src/api/types.ts +28 -0
- package/src/components/config/ModelConfig.tsx +1 -0
- package/src/components/config/ProviderForm.tsx +1 -0
- package/src/components/doc-browser/DocBrowser.tsx +382 -323
- package/src/components/doc-browser/DocBrowserContext.tsx +389 -157
- package/src/components/layout/Sidebar.tsx +1 -1
- package/src/components/marketplace/MarketplacePage.tsx +252 -12
- package/src/lib/i18n.ts +21 -2
- package/dist/assets/DocBrowser-BY0TiFOc.js +0 -1
- package/dist/assets/MarketplacePage-BDlAw7fO.js +0 -1
- package/dist/assets/index-C1NAfZSm.js +0 -2
- package/dist/assets/index-DWgSvrx4.css +0 -1
|
@@ -2,13 +2,19 @@
|
|
|
2
2
|
import type {
|
|
3
3
|
MarketplaceInstalledRecord,
|
|
4
4
|
MarketplaceItemSummary,
|
|
5
|
+
MarketplaceLocalizedTextMap,
|
|
5
6
|
MarketplaceManageAction,
|
|
7
|
+
MarketplacePluginContentView,
|
|
8
|
+
MarketplaceSkillContentView,
|
|
6
9
|
MarketplaceSort,
|
|
7
10
|
MarketplaceItemType
|
|
8
11
|
} from '@/api/types';
|
|
12
|
+
import { fetchMarketplacePluginContent, fetchMarketplaceSkillContent } from '@/api/marketplace';
|
|
9
13
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
|
10
14
|
import { Tabs } from '@/components/ui/tabs-custom';
|
|
11
15
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
|
|
16
|
+
import { useDocBrowser } from '@/components/doc-browser';
|
|
17
|
+
import { useI18n } from '@/components/providers/I18nProvider';
|
|
12
18
|
import { useConfirmDialog } from '@/hooks/useConfirmDialog';
|
|
13
19
|
import {
|
|
14
20
|
useInstallMarketplaceItem,
|
|
@@ -123,16 +129,68 @@ function findCatalogItemForRecord(
|
|
|
123
129
|
return catalogLookup.get(toLookupKey(record.type, record.label));
|
|
124
130
|
}
|
|
125
131
|
|
|
132
|
+
function buildLocaleFallbacks(language: string): string[] {
|
|
133
|
+
const normalized = language.trim().toLowerCase().replace(/_/g, '-');
|
|
134
|
+
const base = normalized.split('-')[0];
|
|
135
|
+
const fallbacks = [normalized, base, 'en'];
|
|
136
|
+
return Array.from(new Set(fallbacks.filter(Boolean)));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function normalizeLocaleTag(locale: string): string {
|
|
140
|
+
return locale.trim().toLowerCase().replace(/_/g, '-');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function pickLocalizedText(
|
|
144
|
+
localized: MarketplaceLocalizedTextMap | undefined,
|
|
145
|
+
fallback: string | undefined,
|
|
146
|
+
localeFallbacks: string[]
|
|
147
|
+
): string {
|
|
148
|
+
if (localized) {
|
|
149
|
+
const entries = Object.entries(localized)
|
|
150
|
+
.map(([locale, text]) => ({ locale: normalizeLocaleTag(locale), text: typeof text === 'string' ? text.trim() : '' }))
|
|
151
|
+
.filter((entry) => entry.text.length > 0);
|
|
152
|
+
|
|
153
|
+
if (entries.length > 0) {
|
|
154
|
+
const exactMap = new Map(entries.map((entry) => [entry.locale, entry.text] as const));
|
|
155
|
+
|
|
156
|
+
for (const locale of localeFallbacks) {
|
|
157
|
+
const normalizedLocale = normalizeLocaleTag(locale);
|
|
158
|
+
const exact = exactMap.get(normalizedLocale);
|
|
159
|
+
if (exact) {
|
|
160
|
+
return exact;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
for (const locale of localeFallbacks) {
|
|
165
|
+
const base = normalizeLocaleTag(locale).split('-')[0];
|
|
166
|
+
if (!base) {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
const matched = entries.find((entry) => entry.locale === base || entry.locale.startsWith(`${base}-`));
|
|
170
|
+
if (matched) {
|
|
171
|
+
return matched.text;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return entries[0]?.text ?? '';
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return fallback?.trim() ?? '';
|
|
180
|
+
}
|
|
181
|
+
|
|
126
182
|
function matchInstalledSearch(
|
|
127
183
|
record: MarketplaceInstalledRecord,
|
|
128
184
|
item: MarketplaceItemSummary | undefined,
|
|
129
|
-
query: string
|
|
185
|
+
query: string,
|
|
186
|
+
localeFallbacks: string[]
|
|
130
187
|
): boolean {
|
|
131
188
|
const normalizedQuery = normalizeMarketplaceKey(query);
|
|
132
189
|
if (!normalizedQuery) {
|
|
133
190
|
return true;
|
|
134
191
|
}
|
|
135
192
|
|
|
193
|
+
const localizedSummary = pickLocalizedText(item?.summaryI18n, item?.summary, localeFallbacks);
|
|
136
194
|
const values = [
|
|
137
195
|
record.id,
|
|
138
196
|
record.spec,
|
|
@@ -140,6 +198,7 @@ function matchInstalledSearch(
|
|
|
140
198
|
item?.name,
|
|
141
199
|
item?.slug,
|
|
142
200
|
item?.summary,
|
|
201
|
+
localizedSummary,
|
|
143
202
|
...(item?.tags ?? [])
|
|
144
203
|
];
|
|
145
204
|
|
|
@@ -166,12 +225,93 @@ function ItemIcon({ name, fallback }: { name?: string; fallback: string }) {
|
|
|
166
225
|
const letters = displayName.substring(0, 2).toUpperCase();
|
|
167
226
|
const colorClass = getAvatarColor(displayName);
|
|
168
227
|
return (
|
|
169
|
-
<div className={cn(
|
|
228
|
+
<div className={cn('flex items-center justify-center w-10 h-10 rounded-xl text-white font-semibold text-sm shrink-0', colorClass)}>
|
|
170
229
|
{letters}
|
|
171
230
|
</div>
|
|
172
231
|
);
|
|
173
232
|
}
|
|
174
233
|
|
|
234
|
+
function escapeHtml(text: string): string {
|
|
235
|
+
return text
|
|
236
|
+
.replace(/&/g, '&')
|
|
237
|
+
.replace(/</g, '<')
|
|
238
|
+
.replace(/>/g, '>')
|
|
239
|
+
.replace(/"/g, '"')
|
|
240
|
+
.replace(/'/g, ''');
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function buildGenericDetailDataUrl(params: {
|
|
244
|
+
title: string;
|
|
245
|
+
typeLabel: string;
|
|
246
|
+
spec: string;
|
|
247
|
+
summary?: string;
|
|
248
|
+
description?: string;
|
|
249
|
+
metadataRaw?: string;
|
|
250
|
+
contentRaw?: string;
|
|
251
|
+
sourceUrl?: string;
|
|
252
|
+
sourceLabel?: string;
|
|
253
|
+
tags?: string[];
|
|
254
|
+
author?: string;
|
|
255
|
+
}): string {
|
|
256
|
+
const metadata = params.metadataRaw?.trim() || '-';
|
|
257
|
+
const content = params.contentRaw?.trim() || '-';
|
|
258
|
+
const summary = params.summary?.trim();
|
|
259
|
+
const description = params.description?.trim();
|
|
260
|
+
const shouldShowDescription = Boolean(description) && description !== summary;
|
|
261
|
+
|
|
262
|
+
const html = `<!doctype html>
|
|
263
|
+
<html>
|
|
264
|
+
<head>
|
|
265
|
+
<meta charset="utf-8" />
|
|
266
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
267
|
+
<title>${escapeHtml(params.title)}</title>
|
|
268
|
+
<style>
|
|
269
|
+
:root { color-scheme: light; }
|
|
270
|
+
body { margin: 0; background: #f7f9fc; color: #0f172a; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
|
|
271
|
+
.wrap { max-width: 980px; margin: 0 auto; padding: 28px 20px 40px; }
|
|
272
|
+
.hero { border: 1px solid #dbeafe; border-radius: 16px; background: linear-gradient(180deg, #eff6ff, #ffffff); padding: 20px; box-shadow: 0 6px 20px rgba(30, 64, 175, 0.08); }
|
|
273
|
+
.hero h1 { margin: 0; font-size: 26px; }
|
|
274
|
+
.meta { margin-top: 8px; color: #475569; font-size: 13px; }
|
|
275
|
+
.summary { margin-top: 14px; font-size: 14px; line-height: 1.7; color: #334155; }
|
|
276
|
+
.grid { display: grid; grid-template-columns: 260px 1fr; gap: 14px; margin-top: 16px; }
|
|
277
|
+
.card { border: 1px solid #e2e8f0; background: #fff; border-radius: 14px; overflow: hidden; }
|
|
278
|
+
.card h2 { margin: 0; padding: 12px 14px; font-size: 13px; font-weight: 700; color: #1d4ed8; border-bottom: 1px solid #e2e8f0; background: #f8fafc; }
|
|
279
|
+
.card .body { padding: 12px 14px; font-size: 13px; color: #334155; line-height: 1.7; }
|
|
280
|
+
.code { white-space: pre-wrap; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; line-height: 1.6; margin: 0; }
|
|
281
|
+
.tags { margin-top: 10px; }
|
|
282
|
+
.tag { display: inline-block; margin: 0 6px 6px 0; padding: 4px 9px; border-radius: 999px; background: #e0e7ff; color: #3730a3; font-size: 11px; }
|
|
283
|
+
.source { color: #2563eb; text-decoration: none; }
|
|
284
|
+
@media (max-width: 860px) { .grid { grid-template-columns: 1fr; } }
|
|
285
|
+
</style>
|
|
286
|
+
</head>
|
|
287
|
+
<body>
|
|
288
|
+
<main class="wrap">
|
|
289
|
+
<section class="hero">
|
|
290
|
+
<h1>${escapeHtml(params.title)}</h1>
|
|
291
|
+
<div class="meta">${escapeHtml(params.typeLabel)} · ${escapeHtml(params.spec)}${params.author ? ` · ${escapeHtml(params.author)}` : ''}</div>
|
|
292
|
+
${summary ? `<p class="summary">${escapeHtml(summary)}</p>` : ''}
|
|
293
|
+
${shouldShowDescription ? `<p class="summary">${escapeHtml(description as string)}</p>` : ''}
|
|
294
|
+
${params.tags && params.tags.length > 0 ? `<div class="tags">${params.tags.map((tag) => `<span class="tag">${escapeHtml(tag)}</span>`).join('')}</div>` : ''}
|
|
295
|
+
${params.sourceUrl ? `<p class="meta" style="margin-top:12px;">${escapeHtml(params.sourceLabel ?? 'Source')}: <a class="source" href="${escapeHtml(params.sourceUrl)}" target="_blank" rel="noopener noreferrer">${escapeHtml(params.sourceUrl)}</a></p>` : ''}
|
|
296
|
+
</section>
|
|
297
|
+
|
|
298
|
+
<section class="grid">
|
|
299
|
+
<article class="card">
|
|
300
|
+
<h2>Metadata</h2>
|
|
301
|
+
<div class="body"><pre class="code">${escapeHtml(metadata)}</pre></div>
|
|
302
|
+
</article>
|
|
303
|
+
<article class="card">
|
|
304
|
+
<h2>Content</h2>
|
|
305
|
+
<div class="body"><pre class="code">${escapeHtml(content)}</pre></div>
|
|
306
|
+
</article>
|
|
307
|
+
</section>
|
|
308
|
+
</main>
|
|
309
|
+
</body>
|
|
310
|
+
</html>`;
|
|
311
|
+
|
|
312
|
+
return `data:text/html;charset=utf-8,${encodeURIComponent(html)}`;
|
|
313
|
+
}
|
|
314
|
+
|
|
175
315
|
function FilterPanel(props: {
|
|
176
316
|
scope: ScopeType;
|
|
177
317
|
searchText: string;
|
|
@@ -212,8 +352,10 @@ function FilterPanel(props: {
|
|
|
212
352
|
function MarketplaceListCard(props: {
|
|
213
353
|
item?: MarketplaceItemSummary;
|
|
214
354
|
record?: MarketplaceInstalledRecord;
|
|
355
|
+
localeFallbacks: string[];
|
|
215
356
|
installState: InstallState;
|
|
216
357
|
manageState: ManageState;
|
|
358
|
+
onOpen: () => void;
|
|
217
359
|
onInstall: (item: MarketplaceItemSummary) => void;
|
|
218
360
|
onManage: (action: MarketplaceManageAction, record: MarketplaceInstalledRecord) => void;
|
|
219
361
|
}) {
|
|
@@ -221,7 +363,8 @@ function MarketplaceListCard(props: {
|
|
|
221
363
|
const pluginRecord = record?.type === 'plugin' ? record : undefined;
|
|
222
364
|
const type = props.item?.type ?? record?.type;
|
|
223
365
|
const title = props.item?.name ?? record?.label ?? record?.id ?? record?.spec ?? t('marketplaceUnknownItem');
|
|
224
|
-
const summary = props.item?.summary
|
|
366
|
+
const summary = pickLocalizedText(props.item?.summaryI18n, props.item?.summary, props.localeFallbacks)
|
|
367
|
+
|| (record ? t('marketplaceInstalledLocalSummary') : '');
|
|
225
368
|
const spec = props.item?.install.spec ?? record?.spec ?? '';
|
|
226
369
|
|
|
227
370
|
const targetId = record?.id || record?.spec;
|
|
@@ -239,14 +382,17 @@ function MarketplaceListCard(props: {
|
|
|
239
382
|
const displayType = type === 'plugin' ? t('marketplaceTypePlugin') : type === 'skill' ? t('marketplaceTypeSkill') : t('marketplaceTypeExtension');
|
|
240
383
|
|
|
241
384
|
return (
|
|
242
|
-
<article
|
|
385
|
+
<article
|
|
386
|
+
onClick={props.onOpen}
|
|
387
|
+
className="group bg-white border border-gray-200/40 hover:border-blue-300/80 rounded-2xl px-5 py-4 hover:shadow-md shadow-sm transition-all flex items-start gap-3.5 justify-between cursor-pointer"
|
|
388
|
+
>
|
|
243
389
|
<div className="flex gap-3 min-w-0 flex-1 h-full items-start">
|
|
244
390
|
<ItemIcon name={title} fallback={spec || t('marketplaceTypeExtension')} />
|
|
245
391
|
<div className="min-w-0 flex-1 flex flex-col justify-center h-full">
|
|
246
392
|
<TooltipProvider delayDuration={400}>
|
|
247
393
|
<Tooltip>
|
|
248
394
|
<TooltipTrigger asChild>
|
|
249
|
-
<div className="text-[14px] font-semibold text-gray-900 truncate leading-tight
|
|
395
|
+
<div className="text-[14px] font-semibold text-gray-900 truncate leading-tight">{title}</div>
|
|
250
396
|
</TooltipTrigger>
|
|
251
397
|
<TooltipContent className="max-w-[300px] text-xs">
|
|
252
398
|
{title}
|
|
@@ -260,7 +406,7 @@ function MarketplaceListCard(props: {
|
|
|
260
406
|
<span className="text-[10px] text-gray-300">•</span>
|
|
261
407
|
<Tooltip>
|
|
262
408
|
<TooltipTrigger asChild>
|
|
263
|
-
<span className="text-[11px] text-gray-400 truncate max-w-full font-mono
|
|
409
|
+
<span className="text-[11px] text-gray-400 truncate max-w-full font-mono">{spec}</span>
|
|
264
410
|
</TooltipTrigger>
|
|
265
411
|
<TooltipContent className="max-w-[300px] text-xs font-mono break-all">
|
|
266
412
|
{spec}
|
|
@@ -272,7 +418,7 @@ function MarketplaceListCard(props: {
|
|
|
272
418
|
|
|
273
419
|
<Tooltip>
|
|
274
420
|
<TooltipTrigger asChild>
|
|
275
|
-
<p className="text-[12px] text-gray-500/90 line-clamp-1 transition-colors leading-relaxed text-left
|
|
421
|
+
<p className="text-[12px] text-gray-500/90 line-clamp-1 transition-colors leading-relaxed text-left">{summary}</p>
|
|
276
422
|
</TooltipTrigger>
|
|
277
423
|
{summary && (
|
|
278
424
|
<TooltipContent className="max-w-[400px] text-xs leading-relaxed">
|
|
@@ -287,7 +433,10 @@ function MarketplaceListCard(props: {
|
|
|
287
433
|
<div className="shrink-0 flex items-center h-full">
|
|
288
434
|
{props.item && !record && (
|
|
289
435
|
<button
|
|
290
|
-
onClick={() =>
|
|
436
|
+
onClick={(event) => {
|
|
437
|
+
event.stopPropagation();
|
|
438
|
+
props.onInstall(props.item as MarketplaceItemSummary);
|
|
439
|
+
}}
|
|
291
440
|
disabled={isInstalling}
|
|
292
441
|
className="inline-flex items-center gap-1.5 h-8 px-4 rounded-xl text-xs font-medium bg-primary text-white hover:bg-primary-600 disabled:opacity-50 transition-colors"
|
|
293
442
|
>
|
|
@@ -298,7 +447,10 @@ function MarketplaceListCard(props: {
|
|
|
298
447
|
{pluginRecord && canToggle && (
|
|
299
448
|
<button
|
|
300
449
|
disabled={props.manageState.isPending}
|
|
301
|
-
onClick={() =>
|
|
450
|
+
onClick={(event) => {
|
|
451
|
+
event.stopPropagation();
|
|
452
|
+
props.onManage(isDisabled ? 'enable' : 'disable', pluginRecord);
|
|
453
|
+
}}
|
|
302
454
|
className="inline-flex items-center h-8 px-4 rounded-xl text-xs font-medium border border-gray-200/80 text-gray-600 bg-white hover:bg-gray-50 hover:border-gray-300 disabled:opacity-50 transition-colors"
|
|
303
455
|
>
|
|
304
456
|
{busyForRecord && props.manageState.action !== 'uninstall'
|
|
@@ -310,7 +462,10 @@ function MarketplaceListCard(props: {
|
|
|
310
462
|
{record && canUninstall && (
|
|
311
463
|
<button
|
|
312
464
|
disabled={props.manageState.isPending}
|
|
313
|
-
onClick={() =>
|
|
465
|
+
onClick={(event) => {
|
|
466
|
+
event.stopPropagation();
|
|
467
|
+
props.onManage('uninstall', record);
|
|
468
|
+
}}
|
|
314
469
|
className="inline-flex items-center h-8 px-4 rounded-xl text-xs font-medium border border-rose-100 text-rose-500 bg-white hover:bg-rose-50 hover:border-rose-200 disabled:opacity-50 transition-colors"
|
|
315
470
|
>
|
|
316
471
|
{busyForRecord && props.manageState.action === 'uninstall' ? t('marketplaceRemoving') : t('marketplaceUninstall')}
|
|
@@ -354,6 +509,8 @@ function PaginationBar(props: {
|
|
|
354
509
|
export function MarketplacePage() {
|
|
355
510
|
const navigate = useNavigate();
|
|
356
511
|
const params = useParams<{ type?: string }>();
|
|
512
|
+
const { language } = useI18n();
|
|
513
|
+
const docBrowser = useDocBrowser();
|
|
357
514
|
|
|
358
515
|
const routeType: MarketplaceRouteType | null = useMemo(() => {
|
|
359
516
|
if (params.type === 'plugins' || params.type === 'skills') {
|
|
@@ -369,6 +526,8 @@ export function MarketplacePage() {
|
|
|
369
526
|
}, [routeType, navigate]);
|
|
370
527
|
|
|
371
528
|
const typeFilter: MarketplaceItemType = routeType === 'skills' ? 'skill' : 'plugin';
|
|
529
|
+
const localeFallbacks = useMemo(() => buildLocaleFallbacks(language), [language]);
|
|
530
|
+
|
|
372
531
|
const isPluginModule = typeFilter === 'plugin';
|
|
373
532
|
const copyKeys = isPluginModule
|
|
374
533
|
? {
|
|
@@ -461,7 +620,7 @@ export function MarketplacePage() {
|
|
|
461
620
|
record,
|
|
462
621
|
item: findCatalogItemForRecord(record, catalogLookup)
|
|
463
622
|
}))
|
|
464
|
-
.filter((entry) => matchInstalledSearch(entry.record, entry.item, query));
|
|
623
|
+
.filter((entry) => matchInstalledSearch(entry.record, entry.item, query, localeFallbacks));
|
|
465
624
|
|
|
466
625
|
entries.sort((left, right) => {
|
|
467
626
|
const leftTs = left.record.installedAt ? Date.parse(left.record.installedAt) : Number.NaN;
|
|
@@ -477,7 +636,7 @@ export function MarketplacePage() {
|
|
|
477
636
|
});
|
|
478
637
|
|
|
479
638
|
return entries;
|
|
480
|
-
}, [installedRecords, typeFilter, catalogLookup, query]);
|
|
639
|
+
}, [installedRecords, typeFilter, catalogLookup, query, localeFallbacks]);
|
|
481
640
|
|
|
482
641
|
const total = scope === 'installed' ? installedEntries.length : (itemsQuery.data?.total ?? 0);
|
|
483
642
|
const totalPages = scope === 'installed' ? 1 : (itemsQuery.data?.totalPages ?? 0);
|
|
@@ -509,6 +668,7 @@ export function MarketplacePage() {
|
|
|
509
668
|
{ id: 'all', label: t(copyKeys.tabMarketplace) },
|
|
510
669
|
{ id: 'installed', label: t(copyKeys.tabInstalled), count: installedQuery.data?.total ?? 0 }
|
|
511
670
|
];
|
|
671
|
+
|
|
512
672
|
const handleInstall = async (item: MarketplaceItemSummary) => {
|
|
513
673
|
const installSpec = item.install.spec;
|
|
514
674
|
if (installingSpecs.has(installSpec)) {
|
|
@@ -577,6 +737,82 @@ export function MarketplacePage() {
|
|
|
577
737
|
});
|
|
578
738
|
};
|
|
579
739
|
|
|
740
|
+
const openItemDetail = async (item?: MarketplaceItemSummary, record?: MarketplaceInstalledRecord) => {
|
|
741
|
+
const title = item?.name ?? record?.label ?? record?.id ?? record?.spec ?? t('marketplaceUnknownItem');
|
|
742
|
+
|
|
743
|
+
if (!item) {
|
|
744
|
+
const url = buildGenericDetailDataUrl({
|
|
745
|
+
title,
|
|
746
|
+
typeLabel: record?.type === 'plugin' ? t('marketplaceTypePlugin') : t('marketplaceTypeSkill'),
|
|
747
|
+
spec: record?.spec ?? '-',
|
|
748
|
+
summary: t('marketplaceInstalledLocalSummary'),
|
|
749
|
+
metadataRaw: JSON.stringify(record ?? {}, null, 2),
|
|
750
|
+
contentRaw: '-'
|
|
751
|
+
});
|
|
752
|
+
docBrowser.open(url, { newTab: true, title, kind: 'content' });
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
const summary = pickLocalizedText(item.summaryI18n, item.summary, localeFallbacks);
|
|
757
|
+
|
|
758
|
+
if (item.type === 'skill') {
|
|
759
|
+
try {
|
|
760
|
+
const content: MarketplaceSkillContentView = await fetchMarketplaceSkillContent(item.slug);
|
|
761
|
+
const url = buildGenericDetailDataUrl({
|
|
762
|
+
title,
|
|
763
|
+
typeLabel: t('marketplaceTypeSkill'),
|
|
764
|
+
spec: item.install.spec,
|
|
765
|
+
summary,
|
|
766
|
+
metadataRaw: content.metadataRaw,
|
|
767
|
+
contentRaw: content.bodyRaw || content.raw,
|
|
768
|
+
sourceUrl: content.sourceUrl,
|
|
769
|
+
sourceLabel: `Source (${content.source})`,
|
|
770
|
+
tags: item.tags,
|
|
771
|
+
author: item.author
|
|
772
|
+
});
|
|
773
|
+
docBrowser.open(url, { newTab: true, title, kind: 'content' });
|
|
774
|
+
} catch (error) {
|
|
775
|
+
const url = buildGenericDetailDataUrl({
|
|
776
|
+
title,
|
|
777
|
+
typeLabel: t('marketplaceTypeSkill'),
|
|
778
|
+
spec: item.install.spec,
|
|
779
|
+
summary,
|
|
780
|
+
metadataRaw: JSON.stringify({ error: error instanceof Error ? error.message : String(error) }, null, 2),
|
|
781
|
+
contentRaw: t('marketplaceOperationFailed')
|
|
782
|
+
});
|
|
783
|
+
docBrowser.open(url, { newTab: true, title, kind: 'content' });
|
|
784
|
+
}
|
|
785
|
+
return;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
try {
|
|
789
|
+
const content: MarketplacePluginContentView = await fetchMarketplacePluginContent(item.slug);
|
|
790
|
+
const url = buildGenericDetailDataUrl({
|
|
791
|
+
title,
|
|
792
|
+
typeLabel: t('marketplaceTypePlugin'),
|
|
793
|
+
spec: item.install.spec,
|
|
794
|
+
summary,
|
|
795
|
+
metadataRaw: content.metadataRaw,
|
|
796
|
+
contentRaw: content.bodyRaw || content.raw || item.summary,
|
|
797
|
+
sourceUrl: content.sourceUrl,
|
|
798
|
+
sourceLabel: `Source (${content.source})`,
|
|
799
|
+
tags: item.tags,
|
|
800
|
+
author: item.author
|
|
801
|
+
});
|
|
802
|
+
docBrowser.open(url, { newTab: true, title, kind: 'content' });
|
|
803
|
+
} catch (error) {
|
|
804
|
+
const url = buildGenericDetailDataUrl({
|
|
805
|
+
title,
|
|
806
|
+
typeLabel: t('marketplaceTypePlugin'),
|
|
807
|
+
spec: item.install.spec,
|
|
808
|
+
summary,
|
|
809
|
+
metadataRaw: JSON.stringify({ error: error instanceof Error ? error.message : String(error) }, null, 2),
|
|
810
|
+
contentRaw: '-'
|
|
811
|
+
});
|
|
812
|
+
docBrowser.open(url, { newTab: true, title, kind: 'content' });
|
|
813
|
+
}
|
|
814
|
+
};
|
|
815
|
+
|
|
580
816
|
return (
|
|
581
817
|
<PageLayout>
|
|
582
818
|
<PageHeader title={t(copyKeys.pageTitle)} description={t(copyKeys.pageDescription)} />
|
|
@@ -628,8 +864,10 @@ export function MarketplacePage() {
|
|
|
628
864
|
key={item.id}
|
|
629
865
|
item={item}
|
|
630
866
|
record={findInstalledRecordForItem(item, installedRecordLookup)}
|
|
867
|
+
localeFallbacks={localeFallbacks}
|
|
631
868
|
installState={installState}
|
|
632
869
|
manageState={manageState}
|
|
870
|
+
onOpen={() => void openItemDetail(item, findInstalledRecordForItem(item, installedRecordLookup))}
|
|
633
871
|
onInstall={handleInstall}
|
|
634
872
|
onManage={handleManage}
|
|
635
873
|
/>
|
|
@@ -640,8 +878,10 @@ export function MarketplacePage() {
|
|
|
640
878
|
key={entry.key}
|
|
641
879
|
item={entry.item}
|
|
642
880
|
record={entry.record}
|
|
881
|
+
localeFallbacks={localeFallbacks}
|
|
643
882
|
installState={installState}
|
|
644
883
|
manageState={manageState}
|
|
884
|
+
onOpen={() => void openItemDetail(entry.item, entry.record)}
|
|
645
885
|
onInstall={handleInstall}
|
|
646
886
|
onManage={handleManage}
|
|
647
887
|
/>
|
package/src/lib/i18n.ts
CHANGED
|
@@ -168,6 +168,10 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
168
168
|
modelName: { zh: '模型', en: 'Model' },
|
|
169
169
|
modelPickerNoOptions: { zh: '暂无可选模型', en: 'No model options available' },
|
|
170
170
|
modelPickerUseCustom: { zh: '使用自定义模型:{value}', en: 'Use custom model: {value}' },
|
|
171
|
+
modelInputCustomHint: {
|
|
172
|
+
zh: '如果列表里没有目标模型,可直接输入自定义模型 ID。',
|
|
173
|
+
en: 'If the model is not listed, type a custom model ID directly.'
|
|
174
|
+
},
|
|
171
175
|
maxTokens: { zh: '最大 Token 数', en: 'Max Tokens' },
|
|
172
176
|
maxToolIterations: { zh: '最大工具迭代次数', en: 'Max Tool Iterations' },
|
|
173
177
|
saveChanges: { zh: '保存变更', en: 'Save Changes' },
|
|
@@ -206,7 +210,14 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
206
210
|
providerTestConnectionSuccess: { zh: '连接测试通过', en: 'Connection test passed' },
|
|
207
211
|
providerTestConnectionFailed: { zh: '连接测试失败', en: 'Connection test failed' },
|
|
208
212
|
providerModelsTitle: { zh: '可用模型列表', en: 'Available Models' },
|
|
209
|
-
providerModelInputPlaceholder: {
|
|
213
|
+
providerModelInputPlaceholder: {
|
|
214
|
+
zh: '输入模型 ID(无需 provider 前缀,不在列表也可)',
|
|
215
|
+
en: 'Enter model id (without provider prefix; custom values allowed)'
|
|
216
|
+
},
|
|
217
|
+
providerModelInputHint: {
|
|
218
|
+
zh: '列表仅作参考,不在列表也可直接输入并添加。',
|
|
219
|
+
en: 'The list is only a reference. You can type and add models that are not listed.'
|
|
220
|
+
},
|
|
210
221
|
providerAddModel: { zh: '添加模型', en: 'Add Model' },
|
|
211
222
|
providerModelsEmpty: { zh: '当前没有模型,可直接输入并添加。', en: 'No models yet. Add one by typing model id.' },
|
|
212
223
|
providerModelDefaultTag: { zh: '默认', en: 'Default' },
|
|
@@ -550,6 +561,11 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
550
561
|
marketplaceOperationFailed: { zh: '操作失败', en: 'Operation failed' },
|
|
551
562
|
marketplaceInstalledPluginsCountSuffix: { zh: '个已安装插件', en: 'installed plugins' },
|
|
552
563
|
marketplaceInstalledSkillsCountSuffix: { zh: '个已安装技能', en: 'installed skills' },
|
|
564
|
+
marketplaceDetailPanelTitle: { zh: '详情预览', en: 'Detail Preview' },
|
|
565
|
+
marketplaceDetailPanelEmpty: { zh: '点击左侧任意插件/技能,在这里查看详情。', en: 'Click an item on the left to preview details here.' },
|
|
566
|
+
marketplaceDetailSummary: { zh: '摘要', en: 'Summary' },
|
|
567
|
+
marketplaceDetailDescription: { zh: '描述', en: 'Description' },
|
|
568
|
+
marketplaceOpenInDocBrowserTab: { zh: '新标签打开', en: 'Open in New Tab' },
|
|
553
569
|
|
|
554
570
|
// Status
|
|
555
571
|
connected: { zh: '已连接', en: 'Connected' },
|
|
@@ -582,7 +598,7 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
582
598
|
headerValue: { zh: 'Header 值', en: 'Header Value' },
|
|
583
599
|
|
|
584
600
|
// Doc Browser
|
|
585
|
-
docBrowserTitle: { zh: '
|
|
601
|
+
docBrowserTitle: { zh: '内嵌浏览器', en: 'Embedded Browser' },
|
|
586
602
|
docBrowserSearchPlaceholder: { zh: '搜索,也可以输入文档地址直接打开', en: 'Search, or enter a doc URL to open' },
|
|
587
603
|
docBrowserUrlPlaceholder: { zh: '输入文档路径,如 /guide/channels', en: 'Enter a doc path, e.g. /guide/channels' },
|
|
588
604
|
docBrowserOpenExternal: { zh: '文档中心打开', en: 'Open in Docs' },
|
|
@@ -590,6 +606,9 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
590
606
|
docBrowserDockMode: { zh: '固定到侧栏', en: 'Dock to Sidebar' },
|
|
591
607
|
docBrowserClose: { zh: '关闭', en: 'Close' },
|
|
592
608
|
docBrowserHelp: { zh: '帮助文档', en: 'Help Docs' },
|
|
609
|
+
docBrowserNewTab: { zh: '新建标签', en: 'New Tab' },
|
|
610
|
+
docBrowserCloseTab: { zh: '关闭标签', en: 'Close Tab' },
|
|
611
|
+
docBrowserTabUntitled: { zh: '未命名', en: 'Untitled' },
|
|
593
612
|
};
|
|
594
613
|
|
|
595
614
|
export function t(key: string, lang: I18nLanguage = getLanguage()): string {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as s,j as t,s as J,aS as K,aT as Q,ad as Z,aU as ee,aV as te,a0 as re,ak as se,aW as oe}from"./vendor-DN_iJQc4.js";import{u as ae,D as W,t as x,c as C}from"./index-C1NAfZSm.js";function ce(){const{isOpen:U,mode:h,currentUrl:i,navVersion:f,close:B,toggleMode:P,goBack:Y,goForward:F,canGoBack:I,canGoForward:O,navigate:v,syncUrl:z}=ae(),[b,y]=s.useState(""),[j,M]=s.useState(!1),[A,m]=s.useState(!1),[l,N]=s.useState(()=>({x:Math.max(40,window.innerWidth-520),y:80})),[a,R]=s.useState({w:480,h:600}),[E,T]=s.useState(420),c=s.useRef(null),d=s.useRef(null),p=s.useRef(null),k=s.useRef(null),S=s.useRef(f);s.useEffect(()=>{try{const e=new URL(i);y(e.pathname)}catch{y(i)}},[i]),s.useEffect(()=>{var e;if(f!==S.current){S.current=f;return}if((e=k.current)!=null&&e.contentWindow)try{const r=new URL(i).pathname;k.current.contentWindow.postMessage({type:"docs-navigate",path:r},"*")}catch{}},[i,f]),s.useEffect(()=>{h==="floating"&&N(e=>({x:Math.max(40,window.innerWidth-a.w-40),y:e.y}))},[h,a.w]),s.useEffect(()=>{const e=r=>{var o;((o=r.data)==null?void 0:o.type)==="docs-route-change"&&typeof r.data.url=="string"&&z(r.data.url)};return window.addEventListener("message",e),()=>window.removeEventListener("message",e)},[z]);const V=s.useCallback(e=>{e.preventDefault();const r=b.trim();r&&(r.startsWith("/")?v(`${W}${r}`):r.startsWith("http")?v(r):v(`${W}/${r}`))},[b,v]),_=s.useCallback(e=>{h==="floating"&&(M(!0),c.current={startX:e.clientX,startY:e.clientY,startPosX:l.x,startPosY:l.y})},[h,l]);s.useEffect(()=>{if(!j)return;const e=o=>{c.current&&N({x:c.current.startPosX+(o.clientX-c.current.startX),y:c.current.startPosY+(o.clientY-c.current.startY)})},r=()=>{M(!1),c.current=null};return window.addEventListener("mousemove",e),window.addEventListener("mouseup",r),()=>{window.removeEventListener("mousemove",e),window.removeEventListener("mouseup",r)}},[j]);const L=s.useCallback(e=>{e.preventDefault(),e.stopPropagation(),m(!0);const r=e.currentTarget.dataset.axis;d.current={startX:e.clientX,startY:e.clientY,startW:a.w,startH:a.h};const o=u=>{d.current&&R(g=>({w:r==="y"?g.w:Math.max(360,d.current.startW+(u.clientX-d.current.startX)),h:r==="x"?g.h:Math.max(400,d.current.startH+(u.clientY-d.current.startY))}))},w=()=>{m(!1),d.current=null,window.removeEventListener("mousemove",o),window.removeEventListener("mouseup",w)};window.addEventListener("mousemove",o),window.addEventListener("mouseup",w)},[a]),$=s.useCallback(e=>{e.preventDefault(),e.stopPropagation(),m(!0),p.current={startX:e.clientX,startW:E};const r=w=>{if(!p.current)return;const u=p.current.startX-w.clientX;T(Math.max(320,Math.min(800,p.current.startW+u)))},o=()=>{m(!1),p.current=null,window.removeEventListener("mousemove",r),window.removeEventListener("mouseup",o)};window.addEventListener("mousemove",r),window.addEventListener("mouseup",o)},[E]),G=s.useCallback(e=>{e.preventDefault(),e.stopPropagation(),m(!0);const r=e.clientX,o=a.w,w=l.x,u=H=>{const q=r-H.clientX,X=Math.max(360,o+q);R(D=>({...D,w:X})),N(D=>({...D,x:w-(X-o)}))},g=()=>{m(!1),window.removeEventListener("mousemove",u),window.removeEventListener("mouseup",g)};window.addEventListener("mousemove",u),window.addEventListener("mouseup",g)},[a.w,l.x]);if(!U)return null;const n=h==="docked";return t.jsxs("div",{className:C("flex flex-col bg-white overflow-hidden relative",n?"h-full border-l border-gray-200 shrink-0":"rounded-2xl shadow-2xl border border-gray-200"),style:n?{width:E}:{position:"fixed",left:l.x,top:l.y,width:a.w,height:a.h,zIndex:9999},children:[n&&t.jsx("div",{className:"absolute top-0 left-0 w-1.5 h-full cursor-ew-resize z-20 hover:bg-primary/10 transition-colors",onMouseDown:$}),t.jsxs("div",{className:C("flex items-center justify-between px-4 py-2.5 bg-gray-50 border-b border-gray-200 shrink-0 select-none",!n&&"cursor-grab active:cursor-grabbing"),onMouseDown:n?void 0:_,children:[t.jsxs("div",{className:"flex items-center gap-2.5",children:[t.jsx(J,{className:"w-4 h-4 text-primary"}),t.jsx("span",{className:"text-sm font-semibold text-gray-900",children:x("docBrowserTitle")})]}),t.jsxs("div",{className:"flex items-center gap-1",children:[t.jsx("button",{onClick:P,className:"hover:bg-gray-200 rounded-md p-1.5 text-gray-500 hover:text-gray-700 transition-colors",title:n?x("docBrowserFloatMode"):x("docBrowserDockMode"),children:n?t.jsx(K,{className:"w-3.5 h-3.5"}):t.jsx(Q,{className:"w-3.5 h-3.5"})}),t.jsx("button",{onClick:B,className:"hover:bg-gray-200 rounded-md p-1.5 text-gray-500 hover:text-gray-700 transition-colors",title:x("docBrowserClose"),children:t.jsx(Z,{className:"w-3.5 h-3.5"})})]})]}),t.jsxs("div",{className:"flex items-center gap-2 px-3.5 py-2 bg-white border-b border-gray-100 shrink-0",children:[t.jsx("button",{onClick:Y,disabled:!I,className:"p-1.5 rounded-md hover:bg-gray-100 disabled:opacity-30 disabled:cursor-not-allowed text-gray-600 transition-colors",children:t.jsx(ee,{className:"w-4 h-4"})}),t.jsx("button",{onClick:F,disabled:!O,className:"p-1.5 rounded-md hover:bg-gray-100 disabled:opacity-30 disabled:cursor-not-allowed text-gray-600 transition-colors",children:t.jsx(te,{className:"w-4 h-4"})}),t.jsxs("form",{onSubmit:V,className:"flex-1 relative",children:[t.jsx(re,{className:"w-3.5 h-3.5 absolute left-3 top-1/2 -translate-y-1/2 text-gray-400"}),t.jsx("input",{type:"text",value:b,onChange:e=>y(e.target.value),placeholder:x("docBrowserSearchPlaceholder"),className:"w-full h-8 pl-8 pr-3 rounded-lg bg-gray-50 border border-gray-200 text-xs text-gray-700 focus:outline-none focus:ring-1 focus:ring-primary/30 focus:border-primary/40 transition-colors placeholder:text-gray-400"})]})]}),t.jsxs("div",{className:"flex-1 relative overflow-hidden",children:[t.jsx("iframe",{ref:k,src:i,className:"absolute inset-0 w-full h-full border-0",title:"NextClaw Documentation",sandbox:"allow-same-origin allow-scripts allow-popups allow-forms",allow:"clipboard-read; clipboard-write"},f),(A||j)&&t.jsx("div",{className:"absolute inset-0 z-10"})]}),t.jsx("div",{className:"flex items-center justify-between px-4 py-2 bg-gray-50 border-t border-gray-200 shrink-0",children:t.jsxs("a",{href:i,target:"_blank",rel:"noopener noreferrer","data-doc-external":!0,className:"flex items-center gap-1.5 text-xs text-primary hover:text-primary-hover font-medium transition-colors",children:[x("docBrowserOpenExternal"),t.jsx(se,{className:"w-3 h-3"})]})}),!n&&t.jsxs(t.Fragment,{children:[t.jsx("div",{className:"absolute top-0 left-0 w-1.5 h-full cursor-ew-resize z-20 hover:bg-primary/10 transition-colors",onMouseDown:G}),t.jsx("div",{className:"absolute top-0 right-0 w-1.5 h-full cursor-ew-resize z-20 hover:bg-primary/10 transition-colors",onMouseDown:L,"data-axis":"x"}),t.jsx("div",{className:"absolute bottom-0 left-0 h-1.5 w-full cursor-ns-resize z-20 hover:bg-primary/10 transition-colors",onMouseDown:L,"data-axis":"y"}),t.jsx("div",{className:"absolute bottom-0 right-0 w-4 h-4 cursor-se-resize z-30 flex items-center justify-center text-gray-300 hover:text-gray-500 transition-colors",onMouseDown:L,children:t.jsx(oe,{className:"w-3 h-3 rotate-[-45deg]"})})]})]})}export{ce as DocBrowser};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as o,j as s,at as Oe,au as $e,av as Fe,aw as xe,ax as qe,ay as He,az as E,aA as he,aB as Ke,aC as Ue,aD as ze,aE as Qe,aF as Be,aG as Ge,aH as Ve,aq as ye,ar as be,as as ke,ag as q,aI as Ye,aJ as Xe,aK as Je}from"./vendor-DN_iJQc4.js";import{c as ve,j as H,t as c,S as We,a as Ze,b as et,d as tt,e as ge}from"./index-C1NAfZSm.js";import{T as at}from"./tabs-custom-TUrWRyYy.js";import{P as Te,u as nt}from"./useConfirmDialog-D5X0Iqid.js";import{P as st,a as rt}from"./page-layout-hPFzCUTQ.js";var[K]=Ue("Tooltip",[he]),U=he(),Ce="TooltipProvider",lt=700,Y="tooltip.open",[ot,W]=K(Ce),Se=e=>{const{__scopeTooltip:t,delayDuration:a=lt,skipDelayDuration:n=300,disableHoverableContent:l=!1,children:r}=e,u=o.useRef(!0),b=o.useRef(!1),d=o.useRef(0);return o.useEffect(()=>{const x=d.current;return()=>window.clearTimeout(x)},[]),s.jsx(ot,{scope:t,isOpenDelayedRef:u,delayDuration:a,onOpen:o.useCallback(()=>{window.clearTimeout(d.current),u.current=!1},[]),onClose:o.useCallback(()=>{window.clearTimeout(d.current),d.current=window.setTimeout(()=>u.current=!0,n)},[n]),isPointerInTransitRef:b,onPointerInTransitChange:o.useCallback(x=>{b.current=x},[]),disableHoverableContent:l,children:r})};Se.displayName=Ce;var L="Tooltip",[it,A]=K(L),Pe=e=>{const{__scopeTooltip:t,children:a,open:n,defaultOpen:l,onOpenChange:r,disableHoverableContent:u,delayDuration:b}=e,d=W(L,e.__scopeTooltip),x=U(t),[i,h]=o.useState(null),k=Oe(),m=o.useRef(0),T=u??d.disableHoverableContent,y=b??d.delayDuration,C=o.useRef(!1),[P,f]=$e({prop:n,defaultProp:l??!1,onChange:O=>{O?(d.onOpen(),document.dispatchEvent(new CustomEvent(Y))):d.onClose(),r==null||r(O)},caller:L}),v=o.useMemo(()=>P?C.current?"delayed-open":"instant-open":"closed",[P]),j=o.useCallback(()=>{window.clearTimeout(m.current),m.current=0,C.current=!1,f(!0)},[f]),S=o.useCallback(()=>{window.clearTimeout(m.current),m.current=0,f(!1)},[f]),_=o.useCallback(()=>{window.clearTimeout(m.current),m.current=window.setTimeout(()=>{C.current=!0,f(!0),m.current=0},y)},[y,f]);return o.useEffect(()=>()=>{m.current&&(window.clearTimeout(m.current),m.current=0)},[]),s.jsx(Fe,{...x,children:s.jsx(it,{scope:t,contentId:k,open:P,stateAttribute:v,trigger:i,onTriggerChange:h,onTriggerEnter:o.useCallback(()=>{d.isOpenDelayedRef.current?_():j()},[d.isOpenDelayedRef,_,j]),onTriggerLeave:o.useCallback(()=>{T?S():(window.clearTimeout(m.current),m.current=0)},[S,T]),onOpen:j,onClose:S,disableHoverableContent:T,children:a})})};Pe.displayName=L;var X="TooltipTrigger",we=o.forwardRef((e,t)=>{const{__scopeTooltip:a,...n}=e,l=A(X,a),r=W(X,a),u=U(a),b=o.useRef(null),d=xe(t,b,l.onTriggerChange),x=o.useRef(!1),i=o.useRef(!1),h=o.useCallback(()=>x.current=!1,[]);return o.useEffect(()=>()=>document.removeEventListener("pointerup",h),[h]),s.jsx(qe,{asChild:!0,...u,children:s.jsx(He.button,{"aria-describedby":l.open?l.contentId:void 0,"data-state":l.stateAttribute,...n,ref:d,onPointerMove:E(e.onPointerMove,k=>{k.pointerType!=="touch"&&!i.current&&!r.isPointerInTransitRef.current&&(l.onTriggerEnter(),i.current=!0)}),onPointerLeave:E(e.onPointerLeave,()=>{l.onTriggerLeave(),i.current=!1}),onPointerDown:E(e.onPointerDown,()=>{l.open&&l.onClose(),x.current=!0,document.addEventListener("pointerup",h,{once:!0})}),onFocus:E(e.onFocus,()=>{x.current||l.onOpen()}),onBlur:E(e.onBlur,l.onClose),onClick:E(e.onClick,l.onClose)})})});we.displayName=X;var Z="TooltipPortal",[ct,ut]=K(Z,{forceMount:void 0}),je=e=>{const{__scopeTooltip:t,forceMount:a,children:n,container:l}=e,r=A(Z,t);return s.jsx(ct,{scope:t,forceMount:a,children:s.jsx(Te,{present:a||r.open,children:s.jsx(Ke,{asChild:!0,container:l,children:n})})})};je.displayName=Z;var R="TooltipContent",Ie=o.forwardRef((e,t)=>{const a=ut(R,e.__scopeTooltip),{forceMount:n=a.forceMount,side:l="top",...r}=e,u=A(R,e.__scopeTooltip);return s.jsx(Te,{present:n||u.open,children:u.disableHoverableContent?s.jsx(Ne,{side:l,...r,ref:t}):s.jsx(dt,{side:l,...r,ref:t})})}),dt=o.forwardRef((e,t)=>{const a=A(R,e.__scopeTooltip),n=W(R,e.__scopeTooltip),l=o.useRef(null),r=xe(t,l),[u,b]=o.useState(null),{trigger:d,onClose:x}=a,i=l.current,{onPointerInTransitChange:h}=n,k=o.useCallback(()=>{b(null),h(!1)},[h]),m=o.useCallback((T,y)=>{const C=T.currentTarget,P={x:T.clientX,y:T.clientY},f=xt(P,C.getBoundingClientRect()),v=ht(P,f),j=yt(y.getBoundingClientRect()),S=kt([...v,...j]);b(S),h(!0)},[h]);return o.useEffect(()=>()=>k(),[k]),o.useEffect(()=>{if(d&&i){const T=C=>m(C,i),y=C=>m(C,d);return d.addEventListener("pointerleave",T),i.addEventListener("pointerleave",y),()=>{d.removeEventListener("pointerleave",T),i.removeEventListener("pointerleave",y)}}},[d,i,m,k]),o.useEffect(()=>{if(u){const T=y=>{const C=y.target,P={x:y.clientX,y:y.clientY},f=(d==null?void 0:d.contains(C))||(i==null?void 0:i.contains(C)),v=!bt(P,u);f?k():v&&(k(),x())};return document.addEventListener("pointermove",T),()=>document.removeEventListener("pointermove",T)}},[d,i,u,x,k]),s.jsx(Ne,{...e,ref:r})}),[pt,mt]=K(L,{isInside:!1}),gt=Ge("TooltipContent"),Ne=o.forwardRef((e,t)=>{const{__scopeTooltip:a,children:n,"aria-label":l,onEscapeKeyDown:r,onPointerDownOutside:u,...b}=e,d=A(R,a),x=U(a),{onClose:i}=d;return o.useEffect(()=>(document.addEventListener(Y,i),()=>document.removeEventListener(Y,i)),[i]),o.useEffect(()=>{if(d.trigger){const h=k=>{const m=k.target;m!=null&&m.contains(d.trigger)&&i()};return window.addEventListener("scroll",h,{capture:!0}),()=>window.removeEventListener("scroll",h,{capture:!0})}},[d.trigger,i]),s.jsx(ze,{asChild:!0,disableOutsidePointerEvents:!1,onEscapeKeyDown:r,onPointerDownOutside:u,onFocusOutside:h=>h.preventDefault(),onDismiss:i,children:s.jsxs(Qe,{"data-state":d.stateAttribute,...x,...b,ref:t,style:{...b.style,"--radix-tooltip-content-transform-origin":"var(--radix-popper-transform-origin)","--radix-tooltip-content-available-width":"var(--radix-popper-available-width)","--radix-tooltip-content-available-height":"var(--radix-popper-available-height)","--radix-tooltip-trigger-width":"var(--radix-popper-anchor-width)","--radix-tooltip-trigger-height":"var(--radix-popper-anchor-height)"},children:[s.jsx(gt,{children:n}),s.jsx(pt,{scope:a,isInside:!0,children:s.jsx(Be,{id:d.contentId,role:"tooltip",children:l||n})})]})})});Ie.displayName=R;var Ee="TooltipArrow",ft=o.forwardRef((e,t)=>{const{__scopeTooltip:a,...n}=e,l=U(a);return mt(Ee,a).isInside?null:s.jsx(Ve,{...l,...n,ref:t})});ft.displayName=Ee;function xt(e,t){const a=Math.abs(t.top-e.y),n=Math.abs(t.bottom-e.y),l=Math.abs(t.right-e.x),r=Math.abs(t.left-e.x);switch(Math.min(a,n,l,r)){case r:return"left";case l:return"right";case a:return"top";case n:return"bottom";default:throw new Error("unreachable")}}function ht(e,t,a=5){const n=[];switch(t){case"top":n.push({x:e.x-a,y:e.y+a},{x:e.x+a,y:e.y+a});break;case"bottom":n.push({x:e.x-a,y:e.y-a},{x:e.x+a,y:e.y-a});break;case"left":n.push({x:e.x+a,y:e.y-a},{x:e.x+a,y:e.y+a});break;case"right":n.push({x:e.x-a,y:e.y-a},{x:e.x-a,y:e.y+a});break}return n}function yt(e){const{top:t,right:a,bottom:n,left:l}=e;return[{x:l,y:t},{x:a,y:t},{x:a,y:n},{x:l,y:n}]}function bt(e,t){const{x:a,y:n}=e;let l=!1;for(let r=0,u=t.length-1;r<t.length;u=r++){const b=t[r],d=t[u],x=b.x,i=b.y,h=d.x,k=d.y;i>n!=k>n&&a<(h-x)*(n-i)/(k-i)+x&&(l=!l)}return l}function kt(e){const t=e.slice();return t.sort((a,n)=>a.x<n.x?-1:a.x>n.x?1:a.y<n.y?-1:a.y>n.y?1:0),vt(t)}function vt(e){if(e.length<=1)return e.slice();const t=[];for(let n=0;n<e.length;n++){const l=e[n];for(;t.length>=2;){const r=t[t.length-1],u=t[t.length-2];if((r.x-u.x)*(l.y-u.y)>=(r.y-u.y)*(l.x-u.x))t.pop();else break}t.push(l)}t.pop();const a=[];for(let n=e.length-1;n>=0;n--){const l=e[n];for(;a.length>=2;){const r=a[a.length-1],u=a[a.length-2];if((r.x-u.x)*(l.y-u.y)>=(r.y-u.y)*(l.x-u.x))a.pop();else break}a.push(l)}return a.pop(),t.length===1&&a.length===1&&t[0].x===a[0].x&&t[0].y===a[0].y?t:t.concat(a)}var Tt=Se,Ct=Pe,St=we,Pt=je,Me=Ie;const wt=Tt,G=Ct,V=St,F=o.forwardRef(({className:e,sideOffset:t=4,...a},n)=>s.jsx(Pt,{children:s.jsx(Me,{ref:n,sideOffset:t,className:ve("z-[var(--z-tooltip)] overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",e),...a})}));F.displayName=Me.displayName;function z(e){return e==="plugin"?"plugins":"skills"}async function jt(e){var r,u;const t=new URLSearchParams,a=z(e.type);(r=e.q)!=null&&r.trim()&&t.set("q",e.q.trim()),(u=e.tag)!=null&&u.trim()&&t.set("tag",e.tag.trim()),e.sort&&t.set("sort",e.sort),typeof e.page=="number"&&Number.isFinite(e.page)&&t.set("page",String(Math.max(1,Math.trunc(e.page)))),typeof e.pageSize=="number"&&Number.isFinite(e.pageSize)&&t.set("pageSize",String(Math.max(1,Math.trunc(e.pageSize))));const n=t.toString(),l=await H.get(n?`/api/marketplace/${a}/items?${n}`:`/api/marketplace/${a}/items`);if(!l.ok)throw new Error(l.error.message);return l.data}async function It(e){const t=z(e.type),a=await H.post(`/api/marketplace/${t}/install`,e);if(!a.ok)throw new Error(a.error.message);return a.data}async function Nt(e){const t=z(e),a=await H.get(`/api/marketplace/${t}/installed`);if(!a.ok)throw new Error(a.error.message);return a.data}async function Et(e){const t=z(e.type),a=await H.post(`/api/marketplace/${t}/manage`,e);if(!a.ok)throw new Error(a.error.message);return a.data}function Mt(e){return ye({queryKey:["marketplace-items",e],queryFn:()=>jt(e),staleTime:15e3})}function Rt(e){return ye({queryKey:["marketplace-installed",e],queryFn:()=>Nt(e),staleTime:1e4})}function Dt(){const e=be();return ke({mutationFn:t=>It(t),onSuccess:t=>{e.invalidateQueries({queryKey:["marketplace-installed",t.type]}),e.refetchQueries({queryKey:["marketplace-installed",t.type],type:"active"}),e.refetchQueries({queryKey:["marketplace-items"],type:"active"});const a=t.type==="plugin"?c("marketplaceInstallSuccessPlugin"):c("marketplaceInstallSuccessSkill");q.success(t.message||a)},onError:t=>{q.error(t.message||c("marketplaceInstallFailed"))}})}function Lt(){const e=be();return ke({mutationFn:t=>Et(t),onSuccess:t=>{e.invalidateQueries({queryKey:["marketplace-installed",t.type]}),e.invalidateQueries({queryKey:["marketplace-items"]}),e.refetchQueries({queryKey:["marketplace-installed",t.type],type:"active"}),e.refetchQueries({queryKey:["marketplace-items"],type:"active"});const a=t.action==="enable"?c("marketplaceEnableSuccess"):t.action==="disable"?c("marketplaceDisableSuccess"):c("marketplaceUninstallSuccess");q.success(t.message||a)},onError:t=>{q.error(t.message||c("marketplaceOperationFailed"))}})}const At=12;function J(e){return(e??"").trim().toLowerCase()}function M(e,t){const a=J(t);return a.length>0?`${e}:${a}`:""}function _t(e){const t=new Map;for(const a of e){const n=[a.install.spec,a.slug,a.id];for(const l of n){const r=M(a.type,l);!r||t.has(r)||t.set(r,a)}}return t}function Ot(e){const t=new Map;for(const a of e){const n=[a.spec,a.id,a.label];for(const l of n){const r=M(a.type,l);!r||t.has(r)||t.set(r,a)}}return t}function $t(e,t){const a=[e.install.spec,e.slug,e.id];for(const n of a){const l=M(e.type,n);if(!l)continue;const r=t.get(l);if(r)return r}}function Ft(e,t){const a=t.get(M(e.type,e.spec));if(a)return a;const n=t.get(M(e.type,e.id));return n||t.get(M(e.type,e.label))}function qt(e,t,a){const n=J(a);return n?[e.id,e.spec,e.label,t==null?void 0:t.name,t==null?void 0:t.slug,t==null?void 0:t.summary,...(t==null?void 0:t.tags)??[]].map(r=>J(r)).filter(Boolean).some(r=>r.includes(n)):!0}function Ht(e){const t=["bg-amber-600","bg-orange-500","bg-yellow-600","bg-emerald-600","bg-teal-600","bg-cyan-600","bg-stone-600","bg-rose-500","bg-violet-500"];let a=0;for(let n=0;n<e.length;n++)a=e.charCodeAt(n)+((a<<5)-a);return t[Math.abs(a)%t.length]}function Kt({name:e,fallback:t}){const a=e||t,n=a.substring(0,2).toUpperCase(),l=Ht(a);return s.jsx("div",{className:ve("flex items-center justify-center w-10 h-10 rounded-xl text-white font-semibold text-sm shrink-0",l),children:n})}function Ut(e){return s.jsx("div",{className:"mb-4",children:s.jsxs("div",{className:"flex gap-3 items-center",children:[s.jsxs("div",{className:"flex-1 min-w-0 relative",children:[s.jsx(Je,{className:"h-4 w-4 text-gray-400 absolute left-3 top-1/2 -translate-y-1/2"}),s.jsx("input",{value:e.searchText,onChange:t=>e.onSearchTextChange(t.target.value),placeholder:e.searchPlaceholder,className:"w-full h-9 border border-gray-200/80 rounded-xl pl-9 pr-3 text-sm focus:outline-none focus:ring-1 focus:ring-primary/40"})]}),e.scope==="all"&&s.jsxs(We,{value:e.sort,onValueChange:t=>e.onSortChange(t),children:[s.jsx(Ze,{className:"h-9 w-[150px] shrink-0 rounded-lg",children:s.jsx(et,{})}),s.jsxs(tt,{children:[s.jsx(ge,{value:"relevance",children:c("marketplaceSortRelevance")}),s.jsx(ge,{value:"updated",children:c("marketplaceSortUpdated")})]})]})]})})}function fe(e){var P,f,v,j,S;const t=e.record,a=(t==null?void 0:t.type)==="plugin"?t:void 0,n=((P=e.item)==null?void 0:P.type)??(t==null?void 0:t.type),l=((f=e.item)==null?void 0:f.name)??(t==null?void 0:t.label)??(t==null?void 0:t.id)??(t==null?void 0:t.spec)??c("marketplaceUnknownItem"),r=((v=e.item)==null?void 0:v.summary)??(t?c("marketplaceInstalledLocalSummary"):""),u=((j=e.item)==null?void 0:j.install.spec)??(t==null?void 0:t.spec)??"",b=(t==null?void 0:t.id)||(t==null?void 0:t.spec),d=!!b&&e.manageState.isPending&&e.manageState.targetId===b,x=!!a,i=(t==null?void 0:t.type)==="plugin"&&t.origin!=="bundled",h=(t==null?void 0:t.type)==="skill"&&t.source==="workspace",k=!!(i||h),m=t?t.enabled===!1||t.runtimeStatus==="disabled":!1,T=(S=e.item)==null?void 0:S.install.spec,y=typeof T=="string"&&e.installState.installingSpecs.has(T),C=n==="plugin"?c("marketplaceTypePlugin"):n==="skill"?c("marketplaceTypeSkill"):c("marketplaceTypeExtension");return s.jsxs("article",{className:"group bg-white border border-gray-200/40 hover:border-gray-200/80 rounded-2xl px-5 py-4 hover:shadow-md shadow-sm transition-all flex items-start gap-3.5 justify-between cursor-default",children:[s.jsxs("div",{className:"flex gap-3 min-w-0 flex-1 h-full items-start",children:[s.jsx(Kt,{name:l,fallback:u||c("marketplaceTypeExtension")}),s.jsx("div",{className:"min-w-0 flex-1 flex flex-col justify-center h-full",children:s.jsxs(wt,{delayDuration:400,children:[s.jsxs(G,{children:[s.jsx(V,{asChild:!0,children:s.jsx("div",{className:"text-[14px] font-semibold text-gray-900 truncate leading-tight cursor-default",children:l})}),s.jsx(F,{className:"max-w-[300px] text-xs",children:l})]}),s.jsxs("div",{className:"flex items-center gap-1.5 mt-0.5 mb-1.5",children:[s.jsx("span",{className:"text-[11px] text-gray-500 font-medium",children:C}),u&&s.jsxs(s.Fragment,{children:[s.jsx("span",{className:"text-[10px] text-gray-300",children:"•"}),s.jsxs(G,{children:[s.jsx(V,{asChild:!0,children:s.jsx("span",{className:"text-[11px] text-gray-400 truncate max-w-full font-mono cursor-default",children:u})}),s.jsx(F,{className:"max-w-[300px] text-xs font-mono break-all",children:u})]})]})]}),s.jsxs(G,{children:[s.jsx(V,{asChild:!0,children:s.jsx("p",{className:"text-[12px] text-gray-500/90 line-clamp-1 transition-colors leading-relaxed text-left cursor-default",children:r})}),r&&s.jsx(F,{className:"max-w-[400px] text-xs leading-relaxed",children:r})]})]})})]}),s.jsxs("div",{className:"shrink-0 flex items-center h-full",children:[e.item&&!t&&s.jsx("button",{onClick:()=>e.onInstall(e.item),disabled:y,className:"inline-flex items-center gap-1.5 h-8 px-4 rounded-xl text-xs font-medium bg-primary text-white hover:bg-primary-600 disabled:opacity-50 transition-colors",children:y?c("marketplaceInstalling"):c("marketplaceInstall")}),a&&x&&s.jsx("button",{disabled:e.manageState.isPending,onClick:()=>e.onManage(m?"enable":"disable",a),className:"inline-flex items-center h-8 px-4 rounded-xl text-xs font-medium border border-gray-200/80 text-gray-600 bg-white hover:bg-gray-50 hover:border-gray-300 disabled:opacity-50 transition-colors",children:d&&e.manageState.action!=="uninstall"?e.manageState.action==="enable"?c("marketplaceEnabling"):c("marketplaceDisabling"):m?c("marketplaceEnable"):c("marketplaceDisable")}),t&&k&&s.jsx("button",{disabled:e.manageState.isPending,onClick:()=>e.onManage("uninstall",t),className:"inline-flex items-center h-8 px-4 rounded-xl text-xs font-medium border border-rose-100 text-rose-500 bg-white hover:bg-rose-50 hover:border-rose-200 disabled:opacity-50 transition-colors",children:d&&e.manageState.action==="uninstall"?c("marketplaceRemoving"):c("marketplaceUninstall")})]})]})}function zt(e){return s.jsxs("div",{className:"mt-4 flex items-center justify-end gap-2",children:[s.jsx("button",{className:"h-8 px-3 rounded-xl border border-gray-200/80 text-sm text-gray-600 disabled:opacity-40",onClick:e.onPrev,disabled:e.page<=1||e.busy,children:c("prev")}),s.jsx("div",{className:"text-sm text-gray-600 min-w-20 text-center",children:e.totalPages===0?"0 / 0":`${e.page} / ${e.totalPages}`}),s.jsx("button",{className:"h-8 px-3 rounded-xl border border-gray-200/80 text-sm text-gray-600 disabled:opacity-40",onClick:e.onNext,disabled:e.totalPages===0||e.page>=e.totalPages||e.busy,children:c("next")})]})}function Xt(){var le,oe,ie,ce,ue,de,pe,me;const e=Ye(),t=Xe(),a=o.useMemo(()=>t.type==="plugins"||t.type==="skills"?t.type:null,[t.type]);o.useEffect(()=>{a||e("/marketplace/plugins",{replace:!0})},[a,e]);const n=a==="skills"?"skill":"plugin",r=n==="plugin"?{pageTitle:"marketplacePluginsPageTitle",pageDescription:"marketplacePluginsPageDescription",tabMarketplace:"marketplaceTabMarketplacePlugins",tabInstalled:"marketplaceTabInstalledPlugins",searchPlaceholder:"marketplaceSearchPlaceholderPlugins",sectionCatalog:"marketplaceSectionPlugins",sectionInstalled:"marketplaceSectionInstalledPlugins",errorLoadData:"marketplaceErrorLoadingPluginsData",errorLoadInstalled:"marketplaceErrorLoadingInstalledPlugins",emptyData:"marketplaceNoPlugins",emptyInstalled:"marketplaceNoInstalledPlugins",installedCountSuffix:"marketplaceInstalledPluginsCountSuffix"}:{pageTitle:"marketplaceSkillsPageTitle",pageDescription:"marketplaceSkillsPageDescription",tabMarketplace:"marketplaceTabMarketplaceSkills",tabInstalled:"marketplaceTabInstalledSkills",searchPlaceholder:"marketplaceSearchPlaceholderSkills",sectionCatalog:"marketplaceSectionSkills",sectionInstalled:"marketplaceSectionInstalledSkills",errorLoadData:"marketplaceErrorLoadingSkillsData",errorLoadInstalled:"marketplaceErrorLoadingInstalledSkills",emptyData:"marketplaceNoSkills",emptyInstalled:"marketplaceNoInstalledSkills",installedCountSuffix:"marketplaceInstalledSkillsCountSuffix"},[u,b]=o.useState(""),[d,x]=o.useState(""),[i,h]=o.useState("all"),[k,m]=o.useState("relevance"),[T,y]=o.useState(1),[C,P]=o.useState(new Set);o.useEffect(()=>{const p=setTimeout(()=>{y(1),x(u.trim())},250);return()=>clearTimeout(p)},[u]),o.useEffect(()=>{y(1)},[n]);const f=Rt(n),v=Mt({q:d||void 0,type:n,sort:k,page:T,pageSize:At}),j=Dt(),S=Lt(),{confirm:_,ConfirmDialog:O}=nt(),$=o.useMemo(()=>{var p;return((p=f.data)==null?void 0:p.records)??[]},[(le=f.data)==null?void 0:le.records]),N=o.useMemo(()=>{var p;return((p=v.data)==null?void 0:p.items)??[]},[(oe=v.data)==null?void 0:oe.items]),ee=o.useMemo(()=>_t(N),[N]),Re=o.useMemo(()=>Ot($),[$]),D=o.useMemo(()=>{const p=$.filter(g=>g.type===n).map(g=>({key:`${g.type}:${g.spec}:${g.id??""}`,record:g,item:Ft(g,ee)})).filter(g=>qt(g.record,g.item,d));return p.sort((g,w)=>{const I=g.record.installedAt?Date.parse(g.record.installedAt):Number.NaN,B=w.record.installedAt?Date.parse(w.record.installedAt):Number.NaN,Ae=!Number.isNaN(I),_e=!Number.isNaN(B);return Ae&&_e&&I!==B?B-I:g.record.spec.localeCompare(w.record.spec)}),p},[$,n,ee,d]),te=i==="installed"?D.length:((ie=v.data)==null?void 0:ie.total)??0,Q=i==="installed"?1:((ce=v.data)==null?void 0:ce.totalPages)??0,De=o.useMemo(()=>i==="installed"?f.isLoading?c("loading"):`${D.length} ${c(r.installedCountSuffix)}`:v.data?`${N.length} / ${te}`:c("loading"),[i,f.isLoading,D.length,v.data,N.length,te,r.installedCountSuffix]),ae={installingSpecs:C},ne={isPending:S.isPending,targetId:((ue=S.variables)==null?void 0:ue.id)||((de=S.variables)==null?void 0:de.spec),action:(pe=S.variables)==null?void 0:pe.action},Le=[{id:"all",label:c(r.tabMarketplace)},{id:"installed",label:c(r.tabInstalled),count:((me=f.data)==null?void 0:me.total)??0}],se=async p=>{const g=p.install.spec;if(!C.has(g)){P(w=>{const I=new Set(w);return I.add(g),I});try{await j.mutateAsync({type:p.type,spec:g,kind:p.install.kind,...p.type==="skill"?{skill:p.slug,installPath:`skills/${p.slug}`}:{}})}catch{}finally{P(w=>{if(!w.has(g))return w;const I=new Set(w);return I.delete(g),I})}}},re=async(p,g)=>{if(S.isPending)return;const w=g.id||g.spec;w&&(p==="uninstall"&&!await _({title:`${c("marketplaceUninstallTitle")} ${w}?`,description:c("marketplaceUninstallDescription"),confirmLabel:c("marketplaceUninstall"),variant:"destructive"})||S.mutate({type:g.type,action:p,id:w,spec:g.spec}))};return s.jsxs(st,{children:[s.jsx(rt,{title:c(r.pageTitle),description:c(r.pageDescription)}),s.jsx(at,{tabs:Le,activeTab:i,onChange:p=>{h(p),y(1)},className:"mb-4"}),s.jsx(Ut,{scope:i,searchText:u,searchPlaceholder:c(r.searchPlaceholder),sort:k,onSearchTextChange:b,onSortChange:p=>{y(1),m(p)}}),s.jsxs("section",{children:[s.jsxs("div",{className:"flex items-center justify-between mb-3",children:[s.jsx("h3",{className:"text-[14px] font-semibold text-gray-900",children:i==="installed"?c(r.sectionInstalled):c(r.sectionCatalog)}),s.jsx("span",{className:"text-[12px] text-gray-500",children:De})]}),i==="all"&&v.isError&&s.jsxs("div",{className:"p-4 rounded-xl bg-rose-50 border border-rose-200 text-rose-700 text-sm",children:[c(r.errorLoadData),": ",v.error.message]}),i==="installed"&&f.isError&&s.jsxs("div",{className:"p-4 rounded-xl bg-rose-50 border border-rose-200 text-rose-700 text-sm",children:[c(r.errorLoadInstalled),": ",f.error.message]}),s.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 2xl:grid-cols-3 gap-3",children:[i==="all"&&N.map(p=>s.jsx(fe,{item:p,record:$t(p,Re),installState:ae,manageState:ne,onInstall:se,onManage:re},p.id)),i==="installed"&&D.map(p=>s.jsx(fe,{item:p.item,record:p.record,installState:ae,manageState:ne,onInstall:se,onManage:re},p.key))]}),i==="all"&&!v.isLoading&&!v.isError&&N.length===0&&s.jsx("div",{className:"text-[13px] text-gray-500 py-8 text-center",children:c(r.emptyData)}),i==="installed"&&!f.isLoading&&!f.isError&&D.length===0&&s.jsx("div",{className:"text-[13px] text-gray-500 py-8 text-center",children:c(r.emptyInstalled)})]}),i==="all"&&s.jsx(zt,{page:T,totalPages:Q,busy:v.isFetching,onPrev:()=>y(p=>Math.max(1,p-1)),onNext:()=>y(p=>Q>0?Math.min(Q,p+1):p+1)}),s.jsx(O,{})]})}export{Xt as MarketplacePage};
|