@harness-mix/cli 0.1.9 → 0.1.10
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 +7 -0
- package/README.md +25 -30
- package/output/native-build/desktop-controller.mjs +1 -1
- package/output/native-build/renderer-extension.js +703 -41
- package/package.json +9 -8
- package/scripts/native-config-test.cjs +32 -2
- package/scripts/native-ui-smoke.cjs +39 -4
- package/scripts/pets-test.cjs +146 -0
- package/src/main/native/launcher.js +49 -2
- package/src/main/native/pets.js +176 -15
- package/src/main/native/protocol.js +9 -8
- package/src/native-ui/desktop-control/dist/renderer-draft-prewarm-runtime.js +4 -4
- package/src/native-ui/desktop-control/dist/renderer-draft-prewarm-runtime.js.map +1 -1
- package/src/native-ui/desktop-control/dist/tsconfig.tsbuildinfo +1 -1
- package/src/native-ui/desktop-control/src/renderer-draft-prewarm-runtime.ts +4 -4
- package/src/native-ui/desktop-control/test/renderer-draft-prewarm-policy.test.ts +7 -0
- package/src/native-ui/renderer-extension/dist/types/agent-selection-state.d.ts +1 -0
- package/src/native-ui/renderer-extension/dist/types/agent-selection-state.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/renderer-binding-probe.d.ts +1 -0
- package/src/native-ui/renderer-extension/dist/types/renderer-binding-probe.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/renderer-model-client.d.ts +2 -0
- package/src/native-ui/renderer-extension/dist/types/renderer-model-client.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/renderer-settings-lifecycle.d.ts +2 -1
- package/src/native-ui/renderer-extension/dist/types/renderer-settings-lifecycle.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/settings/icons.d.ts +1 -1
- package/src/native-ui/renderer-extension/dist/types/settings/icons.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/settings/localization.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/settings/pages.d.ts +5 -3
- package/src/native-ui/renderer-extension/dist/types/settings/pages.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/settings/pet-market.d.ts +5 -0
- package/src/native-ui/renderer-extension/dist/types/settings/pet-market.d.ts.map +1 -0
- package/src/native-ui/renderer-extension/dist/types/settings/pets-client.d.ts +57 -0
- package/src/native-ui/renderer-extension/dist/types/settings/pets-client.d.ts.map +1 -0
- package/src/native-ui/renderer-extension/dist/types/settings/shell.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/settings/skin-runtime.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/tsconfig.tsbuildinfo +1 -1
- package/src/native-ui/renderer-extension/src/agent-selection-state.ts +45 -14
- package/src/native-ui/renderer-extension/src/renderer-binding-probe.ts +69 -27
- package/src/native-ui/renderer-extension/src/renderer-model-client.ts +6 -0
- package/src/native-ui/renderer-extension/src/renderer-settings-lifecycle.ts +3 -0
- package/src/native-ui/renderer-extension/src/settings/icons.ts +15 -12
- package/src/native-ui/renderer-extension/src/settings/localization.ts +2 -0
- package/src/native-ui/renderer-extension/src/settings/pages.ts +74 -66
- package/src/native-ui/renderer-extension/src/settings/pet-market.css +310 -0
- package/src/native-ui/renderer-extension/src/settings/pet-market.ts +447 -0
- package/src/native-ui/renderer-extension/src/settings/pets-client.ts +74 -0
- package/src/native-ui/renderer-extension/src/settings/shell.css +27 -8
- package/src/native-ui/renderer-extension/src/settings/shell.ts +4 -3
- package/src/native-ui/renderer-extension/src/settings/skin-runtime.ts +234 -3
- package/src/native-ui/renderer-extension/test/agent-selection-state.test.ts +58 -0
- package/src/native-ui/renderer-extension/test/renderer-binding-probe.test.ts +12 -0
- package/src/native-ui/renderer-extension/test/renderer-model-client.test.ts +1 -0
- package/src/native-ui/renderer-extension/test/settings/localization.test.ts +1 -0
- package/src/native-ui/renderer-extension/test/settings/shell.test.ts +3 -0
- package/src/native-ui/renderer-extension/test/settings/skin-runtime.test.ts +28 -2
|
@@ -31,10 +31,11 @@ import Search from "lucide/dist/esm/icons/search.mjs";
|
|
|
31
31
|
import CircleHelp from "lucide/dist/esm/icons/circle-question-mark.mjs";
|
|
32
32
|
import X from "lucide/dist/esm/icons/x.mjs";
|
|
33
33
|
import Users from "lucide/dist/esm/icons/users.mjs";
|
|
34
|
-
import Plus from "lucide/dist/esm/icons/plus.mjs";
|
|
35
|
-
import Database from 'lucide/dist/esm/icons/database.mjs';
|
|
36
|
-
import Palette from "lucide/dist/esm/icons/palette.mjs";
|
|
37
|
-
import ShieldCheck from "lucide/dist/esm/icons/shield-check.mjs";
|
|
34
|
+
import Plus from "lucide/dist/esm/icons/plus.mjs";
|
|
35
|
+
import Database from 'lucide/dist/esm/icons/database.mjs';
|
|
36
|
+
import Palette from "lucide/dist/esm/icons/palette.mjs";
|
|
37
|
+
import ShieldCheck from "lucide/dist/esm/icons/shield-check.mjs";
|
|
38
|
+
import PawPrint from "lucide/dist/esm/icons/paw-print.mjs";
|
|
38
39
|
import harnessMixLogoUrl from "../../../../assets/brand-harness-mix.png";
|
|
39
40
|
|
|
40
41
|
export const RENDERER_SETTINGS_ICON_NAMES = [
|
|
@@ -70,10 +71,11 @@ export const RENDERER_SETTINGS_ICON_NAMES = [
|
|
|
70
71
|
"trash",
|
|
71
72
|
"terminal",
|
|
72
73
|
"search",
|
|
73
|
-
"help",
|
|
74
|
-
"palette",
|
|
75
|
-
"shield",
|
|
76
|
-
"storage",
|
|
74
|
+
"help",
|
|
75
|
+
"palette",
|
|
76
|
+
"shield",
|
|
77
|
+
"storage",
|
|
78
|
+
"pets",
|
|
77
79
|
] as const;
|
|
78
80
|
|
|
79
81
|
export type RendererSettingsIconName = (typeof RENDERER_SETTINGS_ICON_NAMES)[number];
|
|
@@ -111,10 +113,11 @@ const iconNodes = {
|
|
|
111
113
|
trash: Trash,
|
|
112
114
|
terminal: Terminal,
|
|
113
115
|
search: Search,
|
|
114
|
-
help: CircleHelp,
|
|
115
|
-
palette: Palette,
|
|
116
|
-
shield: ShieldCheck,
|
|
117
|
-
storage: Database,
|
|
116
|
+
help: CircleHelp,
|
|
117
|
+
palette: Palette,
|
|
118
|
+
shield: ShieldCheck,
|
|
119
|
+
storage: Database,
|
|
120
|
+
pets: PawPrint,
|
|
118
121
|
} satisfies Record<RendererSettingsIconName, IconNode>;
|
|
119
122
|
|
|
120
123
|
export function isRendererSettingsIconName(value: string): value is RendererSettingsIconName {
|
|
@@ -516,6 +516,7 @@ const ENGLISH_MESSAGES: RendererSettingsMessages = Object.freeze({
|
|
|
516
516
|
"session-import": "Session Import",
|
|
517
517
|
storage: "Storage & verification",
|
|
518
518
|
skins: "Skins",
|
|
519
|
+
pets: "Pets",
|
|
519
520
|
updates: "Updates",
|
|
520
521
|
about: "About",
|
|
521
522
|
}),
|
|
@@ -775,6 +776,7 @@ const CHINESE_MESSAGES: RendererSettingsMessages = Object.freeze({
|
|
|
775
776
|
"session-import": "会话导入",
|
|
776
777
|
storage: "存储与验证",
|
|
777
778
|
skins: "皮肤",
|
|
779
|
+
pets: "桌宠",
|
|
778
780
|
updates: "更新",
|
|
779
781
|
about: "关于",
|
|
780
782
|
}),
|
|
@@ -26,12 +26,14 @@ import {
|
|
|
26
26
|
type RendererSessionImportClient,
|
|
27
27
|
type RendererImportedThreadOpener,
|
|
28
28
|
} from "./session-import-page.js";
|
|
29
|
-
import { createReleaseNotesElement } from "./release-notes.js";
|
|
30
|
-
import { createMcpSettingsPage, createSkillsSettingsPage } from './integrations-page.js';
|
|
31
|
-
import type { RendererIntegrationsClient } from '../renderer-integrations-client.js';
|
|
32
|
-
import { createAccountsSettingsPage, type RendererCodexAccountClient } from "./accounts-page.js";
|
|
33
|
-
import { createStorageSettingsPage, type RendererStorageClient } from './storage-page.js';
|
|
34
|
-
import { createSkinSettingsPage } from "./skin-market.js";
|
|
29
|
+
import { createReleaseNotesElement } from "./release-notes.js";
|
|
30
|
+
import { createMcpSettingsPage, createSkillsSettingsPage } from './integrations-page.js';
|
|
31
|
+
import type { RendererIntegrationsClient } from '../renderer-integrations-client.js';
|
|
32
|
+
import { createAccountsSettingsPage, type RendererCodexAccountClient } from "./accounts-page.js";
|
|
33
|
+
import { createStorageSettingsPage, type RendererStorageClient } from './storage-page.js';
|
|
34
|
+
import { createSkinSettingsPage } from "./skin-market.js";
|
|
35
|
+
import { createPetSettingsPage } from "./pet-market.js";
|
|
36
|
+
import type { RendererPetsClient } from "./pets-client.js";
|
|
35
37
|
|
|
36
38
|
export type {
|
|
37
39
|
RendererConnectionAgentSnapshot,
|
|
@@ -75,24 +77,25 @@ function windowsInstallerDownloadUrl(window: Window | null | undefined, version:
|
|
|
75
77
|
|
|
76
78
|
export const DEFAULT_RENDERER_SETTINGS_PAGE_IDS = [
|
|
77
79
|
"connections",
|
|
78
|
-
"accounts",
|
|
79
|
-
"mcp",
|
|
80
|
-
"skills",
|
|
81
|
-
"session-import",
|
|
82
|
-
"storage",
|
|
83
|
-
"skins",
|
|
84
|
-
"
|
|
80
|
+
"accounts",
|
|
81
|
+
"mcp",
|
|
82
|
+
"skills",
|
|
83
|
+
"session-import",
|
|
84
|
+
"storage",
|
|
85
|
+
"skins",
|
|
86
|
+
"pets",
|
|
87
|
+
"updates",
|
|
85
88
|
"about",
|
|
86
89
|
] as const;
|
|
87
90
|
|
|
88
91
|
export type DefaultRendererSettingsPageId = (typeof DEFAULT_RENDERER_SETTINGS_PAGE_IDS)[number];
|
|
89
92
|
|
|
90
|
-
export interface RendererUpdateClient {
|
|
91
|
-
checkUpdate(): Promise<UpdateCheckResult>;
|
|
92
|
-
startUpdate(): Promise<UpdateStartResult>;
|
|
93
|
-
readUpdateStatus(): Promise<UpdateStatusResult>;
|
|
94
|
-
readCurrentVersion?(): Promise<{ version: string }>;
|
|
95
|
-
}
|
|
93
|
+
export interface RendererUpdateClient {
|
|
94
|
+
checkUpdate(): Promise<UpdateCheckResult>;
|
|
95
|
+
startUpdate(): Promise<UpdateStartResult>;
|
|
96
|
+
readUpdateStatus(): Promise<UpdateStatusResult>;
|
|
97
|
+
readCurrentVersion?(): Promise<{ version: string }>;
|
|
98
|
+
}
|
|
96
99
|
|
|
97
100
|
function panelIconName(view: string): RendererSettingsIconName {
|
|
98
101
|
if (view === "failed" || view === "error") return "alert";
|
|
@@ -163,10 +166,10 @@ function formatUpdateBytes(value: number): string {
|
|
|
163
166
|
return `${scaled.toFixed(scaled >= 10 ? 0 : 1)} ${unit}`;
|
|
164
167
|
}
|
|
165
168
|
|
|
166
|
-
export function aboutPage(
|
|
167
|
-
messages: RendererSettingsMessages,
|
|
168
|
-
getClient: () => RendererUpdateClient | null = () => null,
|
|
169
|
-
): RendererSettingsPageDefinition {
|
|
169
|
+
export function aboutPage(
|
|
170
|
+
messages: RendererSettingsMessages,
|
|
171
|
+
getClient: () => RendererUpdateClient | null = () => null,
|
|
172
|
+
): RendererSettingsPageDefinition {
|
|
170
173
|
return Object.freeze({
|
|
171
174
|
id: "about",
|
|
172
175
|
label: messages.pageLabels.about,
|
|
@@ -189,7 +192,7 @@ export function aboutPage(
|
|
|
189
192
|
versionRow.className = "settings-about-version-row";
|
|
190
193
|
const versionBadge = document.createElement("span");
|
|
191
194
|
versionBadge.className = "settings-about-version-badge";
|
|
192
|
-
versionBadge.textContent = "v…";
|
|
195
|
+
versionBadge.textContent = "v…";
|
|
193
196
|
const checkUpdateBtn = document.createElement("button");
|
|
194
197
|
checkUpdateBtn.type = "button";
|
|
195
198
|
checkUpdateBtn.className = "settings-command-button settings-command-button--secondary";
|
|
@@ -229,27 +232,27 @@ export function aboutPage(
|
|
|
229
232
|
repositoryUrl,
|
|
230
233
|
);
|
|
231
234
|
repositorySection.append(openSource, repository);
|
|
232
|
-
panel.append(product, tagline, versionRow, introduction, starCallout, repositorySection);
|
|
233
|
-
context.content.append(heading, panel);
|
|
234
|
-
const client = getClient();
|
|
235
|
-
const readVersion = client?.readCurrentVersion
|
|
236
|
-
? () => client.readCurrentVersion!()
|
|
237
|
-
: client
|
|
238
|
-
? () => client.checkUpdate().then(({ currentVersion }) => ({ version: currentVersion }))
|
|
239
|
-
: null;
|
|
240
|
-
if (readVersion) {
|
|
241
|
-
void context.runLatest(readVersion, {
|
|
242
|
-
success(result) {
|
|
243
|
-
versionBadge.textContent = `v${result.version}`;
|
|
244
|
-
},
|
|
245
|
-
failure() {
|
|
246
|
-
versionBadge.textContent = "v—";
|
|
247
|
-
},
|
|
248
|
-
});
|
|
249
|
-
} else {
|
|
250
|
-
versionBadge.textContent = "v—";
|
|
251
|
-
}
|
|
252
|
-
return undefined;
|
|
235
|
+
panel.append(product, tagline, versionRow, introduction, starCallout, repositorySection);
|
|
236
|
+
context.content.append(heading, panel);
|
|
237
|
+
const client = getClient();
|
|
238
|
+
const readVersion = client?.readCurrentVersion
|
|
239
|
+
? () => client.readCurrentVersion!()
|
|
240
|
+
: client
|
|
241
|
+
? () => client.checkUpdate().then(({ currentVersion }) => ({ version: currentVersion }))
|
|
242
|
+
: null;
|
|
243
|
+
if (readVersion) {
|
|
244
|
+
void context.runLatest(readVersion, {
|
|
245
|
+
success(result) {
|
|
246
|
+
versionBadge.textContent = `v${result.version}`;
|
|
247
|
+
},
|
|
248
|
+
failure() {
|
|
249
|
+
versionBadge.textContent = "v—";
|
|
250
|
+
},
|
|
251
|
+
});
|
|
252
|
+
} else {
|
|
253
|
+
versionBadge.textContent = "v—";
|
|
254
|
+
}
|
|
255
|
+
return undefined;
|
|
253
256
|
},
|
|
254
257
|
});
|
|
255
258
|
}
|
|
@@ -627,21 +630,23 @@ export function createDefaultRendererSettingsPages(
|
|
|
627
630
|
getDiagnostics: () => RendererConnectionDiagnostics | null = () => null,
|
|
628
631
|
getAccountClient: () => RendererCodexAccountClient | null = () => null,
|
|
629
632
|
getSessionImportClient: () => RendererSessionImportClient | null = () => null,
|
|
630
|
-
openImportedThread: RendererImportedThreadOpener = () =>
|
|
631
|
-
Promise.reject(new Error("Imported Thread navigation is unavailable")),
|
|
632
|
-
getIntegrationsClient: () => RendererIntegrationsClient | null = () => null,
|
|
633
|
-
getStorageClient: () => RendererStorageClient | null = () => null,
|
|
634
|
-
|
|
633
|
+
openImportedThread: RendererImportedThreadOpener = () =>
|
|
634
|
+
Promise.reject(new Error("Imported Thread navigation is unavailable")),
|
|
635
|
+
getIntegrationsClient: () => RendererIntegrationsClient | null = () => null,
|
|
636
|
+
getStorageClient: () => RendererStorageClient | null = () => null,
|
|
637
|
+
getPetClient: () => RendererPetsClient | null = () => null,
|
|
638
|
+
): readonly RendererSettingsPageDefinition[] {
|
|
635
639
|
return Object.freeze([
|
|
636
640
|
createConnectionsSettingsPage(messages, getDiagnostics),
|
|
637
|
-
createAccountsSettingsPage(messages, getAccountClient),
|
|
638
|
-
createMcpSettingsPage(messages, getIntegrationsClient),
|
|
639
|
-
createSkillsSettingsPage(messages, getIntegrationsClient),
|
|
640
|
-
createSessionImportSettingsPage(messages, getSessionImportClient, openImportedThread),
|
|
641
|
-
createStorageSettingsPage(messages, getStorageClient),
|
|
642
|
-
createSkinSettingsPage(messages),
|
|
643
|
-
|
|
644
|
-
|
|
641
|
+
createAccountsSettingsPage(messages, getAccountClient),
|
|
642
|
+
createMcpSettingsPage(messages, getIntegrationsClient),
|
|
643
|
+
createSkillsSettingsPage(messages, getIntegrationsClient),
|
|
644
|
+
createSessionImportSettingsPage(messages, getSessionImportClient, openImportedThread),
|
|
645
|
+
createStorageSettingsPage(messages, getStorageClient),
|
|
646
|
+
createSkinSettingsPage(messages),
|
|
647
|
+
createPetSettingsPage(messages, getPetClient),
|
|
648
|
+
updatesPage(messages, getUpdateClient),
|
|
649
|
+
aboutPage(messages, getUpdateClient),
|
|
645
650
|
]);
|
|
646
651
|
}
|
|
647
652
|
|
|
@@ -651,9 +656,10 @@ export function createDefaultRendererSettingsRegistry(
|
|
|
651
656
|
getDiagnostics: () => RendererConnectionDiagnostics | null = () => null,
|
|
652
657
|
getAccountClient: () => RendererCodexAccountClient | null = () => null,
|
|
653
658
|
getSessionImportClient: () => RendererSessionImportClient | null = () => null,
|
|
654
|
-
openImportedThread?: RendererImportedThreadOpener,
|
|
655
|
-
getIntegrationsClient?: () => RendererIntegrationsClient | null,
|
|
656
|
-
getStorageClient?: () => RendererStorageClient | null,
|
|
659
|
+
openImportedThread?: RendererImportedThreadOpener,
|
|
660
|
+
getIntegrationsClient?: () => RendererIntegrationsClient | null,
|
|
661
|
+
getStorageClient?: () => RendererStorageClient | null,
|
|
662
|
+
getPetClient?: () => RendererPetsClient | null,
|
|
657
663
|
): RendererSettingsPageRegistry {
|
|
658
664
|
return createRendererSettingsPageRegistry(
|
|
659
665
|
createDefaultRendererSettingsPages(
|
|
@@ -662,12 +668,14 @@ export function createDefaultRendererSettingsRegistry(
|
|
|
662
668
|
getDiagnostics,
|
|
663
669
|
getAccountClient,
|
|
664
670
|
getSessionImportClient,
|
|
665
|
-
openImportedThread,
|
|
666
|
-
getIntegrationsClient,
|
|
667
|
-
getStorageClient,
|
|
671
|
+
openImportedThread,
|
|
672
|
+
getIntegrationsClient,
|
|
673
|
+
getStorageClient,
|
|
674
|
+
getPetClient,
|
|
668
675
|
),
|
|
669
676
|
);
|
|
670
677
|
}
|
|
671
678
|
|
|
672
|
-
export type { RendererCodexAccountClient } from "./accounts-page.js";
|
|
673
|
-
export type { RendererStorageClient, RendererStorageInspection } from './storage-page.js';
|
|
679
|
+
export type { RendererCodexAccountClient } from "./accounts-page.js";
|
|
680
|
+
export type { RendererStorageClient, RendererStorageInspection } from './storage-page.js';
|
|
681
|
+
export type { RendererPetsClient } from "./pets-client.js";
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
.pet-market__intro {
|
|
2
|
+
margin: 0 0 16px;
|
|
3
|
+
font-size: 13px;
|
|
4
|
+
line-height: 1.5;
|
|
5
|
+
color: var(--text-secondary, rgba(255, 255, 255, 0.65));
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.pet-safety-note {
|
|
9
|
+
display: flex;
|
|
10
|
+
align-items: flex-start;
|
|
11
|
+
gap: 10px;
|
|
12
|
+
padding: 10px 14px;
|
|
13
|
+
margin-bottom: 20px;
|
|
14
|
+
border-radius: 8px;
|
|
15
|
+
background: var(--bg-secondary, rgba(255, 255, 255, 0.04));
|
|
16
|
+
border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
|
|
17
|
+
font-size: 12px;
|
|
18
|
+
line-height: 1.4;
|
|
19
|
+
color: var(--text-secondary, rgba(255, 255, 255, 0.7));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.pet-safety-note strong {
|
|
23
|
+
display: block;
|
|
24
|
+
font-size: 12px;
|
|
25
|
+
font-weight: 600;
|
|
26
|
+
color: var(--text-primary, #ffffff);
|
|
27
|
+
margin-bottom: 2px;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.pet-safety-note svg {
|
|
31
|
+
flex-shrink: 0;
|
|
32
|
+
color: var(--accent, #10a37f);
|
|
33
|
+
margin-top: 1px;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.pet-market__toolbar {
|
|
37
|
+
display: flex;
|
|
38
|
+
flex-wrap: wrap;
|
|
39
|
+
align-items: center;
|
|
40
|
+
justify-content: space-between;
|
|
41
|
+
gap: 12px;
|
|
42
|
+
margin-bottom: 18px;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.pet-market__tabs {
|
|
46
|
+
display: flex;
|
|
47
|
+
align-items: center;
|
|
48
|
+
gap: 6px;
|
|
49
|
+
background: var(--bg-secondary, rgba(255, 255, 255, 0.04));
|
|
50
|
+
padding: 3px;
|
|
51
|
+
border-radius: 8px;
|
|
52
|
+
border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.pet-market__tab {
|
|
56
|
+
appearance: none;
|
|
57
|
+
background: transparent;
|
|
58
|
+
border: none;
|
|
59
|
+
color: var(--text-secondary, rgba(255, 255, 255, 0.6));
|
|
60
|
+
padding: 5px 12px;
|
|
61
|
+
border-radius: 6px;
|
|
62
|
+
font-size: 12px;
|
|
63
|
+
font-weight: 500;
|
|
64
|
+
cursor: pointer;
|
|
65
|
+
transition: background 0.15s, color 0.15s;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.pet-market__tab:hover {
|
|
69
|
+
color: var(--text-primary, #ffffff);
|
|
70
|
+
background: rgba(255, 255, 255, 0.05);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.pet-market__tab[data-active="true"] {
|
|
74
|
+
background: var(--bg-tertiary, rgba(255, 255, 255, 0.12));
|
|
75
|
+
color: var(--text-primary, #ffffff);
|
|
76
|
+
font-weight: 600;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.pet-market__search-wrap {
|
|
80
|
+
position: relative;
|
|
81
|
+
min-width: 200px;
|
|
82
|
+
flex: 1;
|
|
83
|
+
max-width: 280px;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.pet-market__search-wrap svg {
|
|
87
|
+
position: absolute;
|
|
88
|
+
left: 10px;
|
|
89
|
+
top: 50%;
|
|
90
|
+
transform: translateY(-50%);
|
|
91
|
+
pointer-events: none;
|
|
92
|
+
color: var(--text-tertiary, rgba(255, 255, 255, 0.4));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.pet-market__search {
|
|
96
|
+
width: 100%;
|
|
97
|
+
padding: 6px 12px 6px 32px;
|
|
98
|
+
border-radius: 6px;
|
|
99
|
+
background: var(--bg-secondary, rgba(255, 255, 255, 0.05));
|
|
100
|
+
border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.1));
|
|
101
|
+
color: var(--text-primary, #ffffff);
|
|
102
|
+
font-size: 12px;
|
|
103
|
+
outline: none;
|
|
104
|
+
transition: border-color 0.15s;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.pet-market__search:focus {
|
|
108
|
+
border-color: var(--accent, #10a37f);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.pet-market-grid {
|
|
112
|
+
display: grid;
|
|
113
|
+
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
|
114
|
+
gap: 16px;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.pet-card {
|
|
118
|
+
display: flex;
|
|
119
|
+
flex-direction: column;
|
|
120
|
+
background: var(--bg-secondary, rgba(255, 255, 255, 0.03));
|
|
121
|
+
border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
|
|
122
|
+
border-radius: 10px;
|
|
123
|
+
overflow: hidden;
|
|
124
|
+
transition: border-color 0.2s, box-shadow 0.2s;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.pet-card:hover {
|
|
128
|
+
border-color: var(--border-strong, rgba(255, 255, 255, 0.18));
|
|
129
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.pet-card[data-installed="true"] {
|
|
133
|
+
border-color: rgba(16, 163, 127, 0.35);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.pet-card__stage {
|
|
137
|
+
position: relative;
|
|
138
|
+
display: flex;
|
|
139
|
+
align-items: center;
|
|
140
|
+
justify-content: center;
|
|
141
|
+
height: 140px;
|
|
142
|
+
background: radial-gradient(circle at center, rgba(255, 255, 255, 0.06) 0%, rgba(255, 255, 255, 0.01) 70%);
|
|
143
|
+
border-bottom: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.06));
|
|
144
|
+
overflow: hidden;
|
|
145
|
+
user-select: none;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.pet-card__sprite {
|
|
149
|
+
width: 96px;
|
|
150
|
+
height: 104px;
|
|
151
|
+
background-repeat: no-repeat;
|
|
152
|
+
image-rendering: pixelated;
|
|
153
|
+
image-rendering: -webkit-optimize-contrast;
|
|
154
|
+
transition: transform 0.2s;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.pet-card:hover .pet-card__sprite {
|
|
158
|
+
transform: scale(1.08);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.pet-card__body {
|
|
162
|
+
display: flex;
|
|
163
|
+
flex-direction: column;
|
|
164
|
+
flex: 1;
|
|
165
|
+
padding: 14px;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.pet-card__header {
|
|
169
|
+
display: flex;
|
|
170
|
+
align-items: flex-start;
|
|
171
|
+
justify-content: space-between;
|
|
172
|
+
gap: 8px;
|
|
173
|
+
margin-bottom: 6px;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.pet-card__title {
|
|
177
|
+
font-size: 14px;
|
|
178
|
+
font-weight: 600;
|
|
179
|
+
color: var(--text-primary, #ffffff);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.pet-card__badges {
|
|
183
|
+
display: flex;
|
|
184
|
+
align-items: center;
|
|
185
|
+
gap: 4px;
|
|
186
|
+
flex-shrink: 0;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.pet-card__badge {
|
|
190
|
+
display: inline-flex;
|
|
191
|
+
align-items: center;
|
|
192
|
+
gap: 3px;
|
|
193
|
+
font-size: 10.5px;
|
|
194
|
+
padding: 2px 6px;
|
|
195
|
+
border-radius: 4px;
|
|
196
|
+
font-weight: 500;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.pet-card__badge--official {
|
|
200
|
+
background: rgba(59, 130, 246, 0.15);
|
|
201
|
+
color: #60a5fa;
|
|
202
|
+
border: 1px solid rgba(59, 130, 246, 0.3);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.pet-card__badge--community {
|
|
206
|
+
background: rgba(168, 85, 247, 0.15);
|
|
207
|
+
color: #c084fc;
|
|
208
|
+
border: 1px solid rgba(168, 85, 247, 0.3);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.pet-card__badge--installed {
|
|
212
|
+
background: rgba(16, 163, 127, 0.15);
|
|
213
|
+
color: #10a37f;
|
|
214
|
+
border: 1px solid rgba(16, 163, 127, 0.3);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.pet-card__description {
|
|
218
|
+
margin: 0 0 14px;
|
|
219
|
+
font-size: 12px;
|
|
220
|
+
line-height: 1.45;
|
|
221
|
+
color: var(--text-secondary, rgba(255, 255, 255, 0.6));
|
|
222
|
+
flex: 1;
|
|
223
|
+
display: -webkit-box;
|
|
224
|
+
-webkit-line-clamp: 3;
|
|
225
|
+
-webkit-box-orient: vertical;
|
|
226
|
+
overflow: hidden;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.pet-card__footer {
|
|
230
|
+
display: flex;
|
|
231
|
+
align-items: center;
|
|
232
|
+
justify-content: space-between;
|
|
233
|
+
gap: 8px;
|
|
234
|
+
margin-top: auto;
|
|
235
|
+
padding-top: 10px;
|
|
236
|
+
border-top: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.05));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.pet-card__dir-hint {
|
|
240
|
+
font-size: 11px;
|
|
241
|
+
color: var(--text-tertiary, rgba(255, 255, 255, 0.4));
|
|
242
|
+
white-space: nowrap;
|
|
243
|
+
overflow: hidden;
|
|
244
|
+
text-overflow: ellipsis;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.pet-card__actions {
|
|
248
|
+
display: flex;
|
|
249
|
+
align-items: center;
|
|
250
|
+
gap: 6px;
|
|
251
|
+
margin-left: auto;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.pet-btn {
|
|
255
|
+
display: inline-flex;
|
|
256
|
+
align-items: center;
|
|
257
|
+
justify-content: center;
|
|
258
|
+
gap: 6px;
|
|
259
|
+
font-size: 12px;
|
|
260
|
+
font-weight: 500;
|
|
261
|
+
padding: 5px 12px;
|
|
262
|
+
border-radius: 6px;
|
|
263
|
+
border: 1px solid transparent;
|
|
264
|
+
cursor: pointer;
|
|
265
|
+
transition: all 0.15s;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.pet-btn--primary {
|
|
269
|
+
background: var(--accent, #10a37f);
|
|
270
|
+
color: #ffffff;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.pet-btn--primary:hover:not(:disabled) {
|
|
274
|
+
filter: brightness(1.1);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.pet-btn--secondary {
|
|
278
|
+
background: var(--bg-tertiary, rgba(255, 255, 255, 0.08));
|
|
279
|
+
border-color: var(--border-subtle, rgba(255, 255, 255, 0.1));
|
|
280
|
+
color: var(--text-secondary, rgba(255, 255, 255, 0.75));
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.pet-btn--secondary:hover:not(:disabled) {
|
|
284
|
+
background: rgba(255, 255, 255, 0.12);
|
|
285
|
+
color: var(--text-primary, #ffffff);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
.pet-btn--danger {
|
|
289
|
+
background: transparent;
|
|
290
|
+
border-color: rgba(239, 68, 68, 0.25);
|
|
291
|
+
color: #f87171;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.pet-btn--danger:hover:not(:disabled) {
|
|
295
|
+
background: rgba(239, 68, 68, 0.12);
|
|
296
|
+
border-color: rgba(239, 68, 68, 0.5);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.pet-btn:disabled {
|
|
300
|
+
opacity: 0.5;
|
|
301
|
+
cursor: not-allowed;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.pet-market__empty {
|
|
305
|
+
grid-column: 1 / -1;
|
|
306
|
+
text-align: center;
|
|
307
|
+
padding: 40px 20px;
|
|
308
|
+
color: var(--text-tertiary, rgba(255, 255, 255, 0.45));
|
|
309
|
+
font-size: 13px;
|
|
310
|
+
}
|