feat(dashboard): add traffic flow sankey chart (#5465)

* feat(dashboard): add traffic flow sankey chart

Add dashboard flow APIs and a Sankey-based flow view with user, optional API key, model, and channel layers.\n\nReuse the dashboard VChart palette, add precise link/node tooltips and interactions, and cover filtering, layer ordering, color stability, and error states with tests.

* feat: build flow chart from quota data

---------

Co-authored-by: CaIon <i@caion.me>
This commit is contained in:
Quaternijkon
2026-06-20 18:57:47 +08:00
committed by GitHub
co-authored by CaIon
parent f9e508bdae
commit a68041f7d6
29 changed files with 2659 additions and 77 deletions
+18 -1
View File
@@ -66,6 +66,11 @@ interface MultiSelectProps {
* Hidden values remain searchable/removable from the dropdown.
*/
maxVisibleChips?: number
/**
* Replaces individual chips with a compact summary while preserving the
* normal dropdown/search behaviour.
*/
renderSelectedSummary?: (values: string[]) => React.ReactNode
/**
* When true, clicking a chip's label copies its value to the clipboard
* instead of being inert. The remove (×) button keeps its own behaviour.
@@ -258,6 +263,14 @@ export function MultiSelect(props: MultiSelectProps) {
>
<ComboboxValue>
{(values: string[]) => {
if (props.renderSelectedSummary) {
return (
<span className='bg-muted text-muted-foreground flex h-[calc(--spacing(5.25))] w-fit items-center justify-center rounded-sm px-1.5 font-mono text-xs font-medium whitespace-nowrap'>
{props.renderSelectedSummary(values)}
</span>
)
}
const shouldLimit =
typeof props.maxVisibleChips === 'number' && !expanded
const visibleValues = shouldLimit
@@ -327,7 +340,11 @@ export function MultiSelect(props: MultiSelectProps) {
</ComboboxValue>
<ComboboxChipsInput
id={props.id}
placeholder={props.selected.length === 0 ? placeholder : undefined}
placeholder={
props.selected.length === 0 && !props.renderSelectedSummary
? placeholder
: undefined
}
onKeyDown={handleKeyDown}
aria-label={placeholder}
/>