import React, { useState, useEffect } from 'react' import { useGG, themeState, fillScaleState, strokeScaleState, formatMissing, IScale, LegendOrientation, } from '@graphique/graphique' import { useAtom } from 'jotai' export interface Props { legendData: Datum[] legendScales: IScale orientation?: LegendOrientation labelFormat?: (v: string, i?: number) => string fontSize?: string | number onSelection?: (v: string) => void } export const CategoricalLegend = ({ legendData, legendScales, orientation, labelFormat, fontSize = 12, onSelection, }: Props) => { const [isFocused, setIsFocused] = useState( legendScales.groups || [], ) const [{ geoms, legend }] = useAtom(themeState) const [{ domain: fillDomain }] = useAtom(fillScaleState) const [{ domain: strokeDomain }] = useAtom(strokeScaleState) const legendGroups = ((fillDomain || strokeDomain) as string[]) || legendScales.groups const { ggState, updateData } = useGG() || {} const { scales, data } = ggState || {} useEffect(() => { setIsFocused(scales?.groups || []) }, [scales, data]) const getGroup = legendScales.groupAccessor ? legendScales.groupAccessor : () => legendScales.groups && legendScales.groups[0] const isHorizontal = orientation === LegendOrientation.H const toggleLegendGroup = (g: string) => { const prevFocused = isFocused let focusedGroups if (prevFocused.includes(g)) { if (prevFocused.length === 1) { focusedGroups = legendScales.groups as string[] } else { focusedGroups = prevFocused.filter((p) => p !== g) } } else { focusedGroups = [...prevFocused, g] } setIsFocused(focusedGroups) const includedGroups = Array.from(new Set(data?.map((d) => getGroup(d)))) if (onSelection) { onSelection(g) } if (data && updateData) { let updatedData if (includedGroups.includes(g)) { if (includedGroups.length === 1) { updatedData = legendData } else { updatedData = data.filter((d) => getGroup(d) !== g) } } else { updatedData = legendData.filter( (d) => includedGroups.includes(getGroup(d)) || getGroup(d) === g, ) } updateData(updatedData) } } return (
{geoms?.bar?.fillOpacity && legendGroups?.map((g: string, i, groups) => (
{ if (['Enter', ' '].includes(e.key)) { toggleLegendGroup(g) } }} onClick={() => toggleLegendGroup(g)} >
{labelFormat ? labelFormat(g, i) : formatMissing(g)}
))}
) }