mirror of
https://github.com/Nezumi-2711/9router.git
synced 2026-09-23 04:09:49 +00:00
Refactor
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
"use client";
|
||||
|
||||
import { CAPACITY_META } from "@/shared/constants/models";
|
||||
import Tooltip from "./Tooltip";
|
||||
|
||||
// Render small icon badges for a model's capabilities (only those set true).
|
||||
// colorOverride: force a single color class for all badges (default: per-cap color).
|
||||
// size: icon font-size in px (default 16).
|
||||
export default function CapacityBadges({ caps, className = "", colorOverride, size = 16 }) {
|
||||
if (!caps) return null;
|
||||
const active = Object.keys(CAPACITY_META).filter((k) => caps[k]);
|
||||
if (active.length === 0) return null;
|
||||
|
||||
return (
|
||||
<span className={`inline-flex items-center gap-0.5 ${className}`}>
|
||||
{active.map((k) => (
|
||||
<Tooltip key={k} text={`${CAPACITY_META[k].label} — ${CAPACITY_META[k].desc}`}>
|
||||
<span
|
||||
className={`material-symbols-outlined leading-none cursor-help ${colorOverride || CAPACITY_META[k].color}`}
|
||||
style={{ fontSize: `${size}px` }}
|
||||
>
|
||||
{CAPACITY_META[k].icon}
|
||||
</span>
|
||||
</Tooltip>
|
||||
))}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import { useState, useMemo, useEffect } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import Modal from "./Modal";
|
||||
import ProviderIcon from "./ProviderIcon";
|
||||
import CapacityBadges from "./CapacityBadges";
|
||||
import { useModelCaps } from "@/shared/hooks/useModelCaps";
|
||||
import { getModelsByProviderId, getModelKind } from "@/shared/constants/models";
|
||||
import { OAUTH_PROVIDERS, APIKEY_PROVIDERS, FREE_PROVIDERS, FREE_TIER_PROVIDERS, AI_PROVIDERS, isOpenAICompatibleProvider, isAnthropicCompatibleProvider, getProviderAlias } from "@/shared/constants/providers";
|
||||
|
||||
@@ -40,6 +42,7 @@ export default function ModelSelectModal({
|
||||
return kinds.includes(kindFilter);
|
||||
});
|
||||
}, [activeProviders, kindFilter]);
|
||||
const { getCaps } = useModelCaps();
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [combos, setCombos] = useState([]);
|
||||
const [providerNodes, setProviderNodes] = useState([]);
|
||||
@@ -499,9 +502,13 @@ export default function ModelSelectModal({
|
||||
<>
|
||||
{model.name}
|
||||
<span className="text-[9px] opacity-60 font-normal">custom</span>
|
||||
<CapacityBadges caps={getCaps(model.value)} />
|
||||
</>
|
||||
) : (
|
||||
model.name
|
||||
<>
|
||||
{model.name}
|
||||
<CapacityBadges caps={getCaps(model.value)} />
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
@@ -12,10 +12,10 @@ export default function Tooltip({ text, children, position = "top", color }) {
|
||||
const bgClass = color ? "" : "bg-gray-900";
|
||||
|
||||
return (
|
||||
<div className="relative inline-flex group">
|
||||
<div className="relative inline-flex group/tt">
|
||||
{children}
|
||||
<div
|
||||
className={`pointer-events-none absolute ${posClass} z-50 w-max max-w-56 rounded px-2 py-1 text-[11px] leading-snug ${bgClass} text-white opacity-0 group-hover:opacity-100 transition-opacity duration-150 whitespace-normal`}
|
||||
className={`pointer-events-none absolute ${posClass} z-50 w-max max-w-56 rounded px-2 py-1 text-[11px] leading-snug ${bgClass} text-white opacity-0 group-hover/tt:opacity-100 transition-opacity duration-150 whitespace-normal`}
|
||||
style={bgStyle}
|
||||
>
|
||||
{text}
|
||||
|
||||
@@ -36,6 +36,7 @@ export { default as NoAuthProxyCard } from "./NoAuthProxyCard";
|
||||
export { default as SegmentedControl } from "./SegmentedControl";
|
||||
export { default as Tooltip } from "./Tooltip";
|
||||
export { default as ProviderInfoCard } from "./ProviderInfoCard";
|
||||
export { default as CapacityBadges } from "./CapacityBadges";
|
||||
|
||||
// Layouts
|
||||
export * from "./layouts";
|
||||
|
||||
Reference in New Issue
Block a user