co-mono/packages/web-ui/src/components/CustomProviderCard.ts
Mario Zechner e533aebacd Fix Lit dependency duplication and update mini-lit to 0.2.0
- Move lit from dependencies to peerDependencies in web-ui to prevent multiple Lit instances being loaded
- Update mini-lit from 0.1.8/0.1.10 to 0.2.0 in root package.json and web-ui/package.json
- Install @tailwindcss/vite in web-ui/example
- Run biome formatting fixes across codebase

This resolves HMR custom element re-registration errors caused by duplicate Lit registries.
2025-11-12 16:03:43 +01:00

100 lines
2.9 KiB
TypeScript

import { i18n } from "@mariozechner/mini-lit";
import { Button } from "@mariozechner/mini-lit/dist/Button.js";
import { html, LitElement, type TemplateResult } from "lit";
import { customElement, property } from "lit/decorators.js";
import type { CustomProvider } from "../storage/stores/custom-providers-store.js";
@customElement("custom-provider-card")
export class CustomProviderCard extends LitElement {
@property({ type: Object }) provider!: CustomProvider;
@property({ type: Boolean }) isAutoDiscovery = false;
@property({ type: Object }) status?: { modelCount: number; status: "connected" | "disconnected" | "checking" };
@property() onRefresh?: (provider: CustomProvider) => void;
@property() onEdit?: (provider: CustomProvider) => void;
@property() onDelete?: (provider: CustomProvider) => void;
protected createRenderRoot() {
return this;
}
private renderStatus(): TemplateResult {
if (!this.isAutoDiscovery) {
return html`
<div class="text-xs text-muted-foreground mt-1">
${i18n("Models")}: ${this.provider.models?.length || 0}
</div>
`;
}
if (!this.status) return html``;
const statusIcon =
this.status.status === "connected"
? html`<span class="text-green-500">●</span>`
: this.status.status === "checking"
? html`<span class="text-yellow-500">●</span>`
: html`<span class="text-red-500">●</span>`;
const statusText =
this.status.status === "connected"
? `${this.status.modelCount} ${i18n("models")}`
: this.status.status === "checking"
? i18n("Checking...")
: i18n("Disconnected");
return html`
<div class="text-xs text-muted-foreground mt-1 flex items-center gap-1">
${statusIcon} ${statusText}
</div>
`;
}
render(): TemplateResult {
return html`
<div class="border border-border rounded-lg p-4 space-y-2">
<div class="flex items-center justify-between">
<div class="flex-1">
<div class="font-medium text-sm text-foreground">${this.provider.name}</div>
<div class="text-xs text-muted-foreground mt-1">
<span class="capitalize">${this.provider.type}</span>
${this.provider.baseUrl ? html`${this.provider.baseUrl}` : ""}
</div>
${this.renderStatus()}
</div>
<div class="flex gap-2">
${
this.isAutoDiscovery && this.onRefresh
? Button({
onClick: () => this.onRefresh?.(this.provider),
variant: "ghost",
size: "sm",
children: i18n("Refresh"),
})
: ""
}
${
this.onEdit
? Button({
onClick: () => this.onEdit?.(this.provider),
variant: "ghost",
size: "sm",
children: i18n("Edit"),
})
: ""
}
${
this.onDelete
? Button({
onClick: () => this.onDelete?.(this.provider),
variant: "ghost",
size: "sm",
children: i18n("Delete"),
})
: ""
}
</div>
</div>
</div>
`;
}
}