|
|
import React, { useCallback, useContext, useEffect, useMemo } from "react"; import chroma from "chroma-js"; import Select, { createFilter, Styles } from "react-select"; import LogListContext from "../../hooks/LogListContext"; import LogFilterChoiceContext from "../../hooks/LogFilterChoiceContext"; import { Config } from "react-select/src/filters";
import cssStyles from "./LogFilterSelector.module.sass";
export default function LogFilterSelector(props: {}) { const {filter, updateFilter} = useContext(LogListContext); const {channelNames, eventNames, characters} = useContext(LogFilterChoiceContext);
const options = useMemo(() => [ ...channelNames.map(n => ({type: 0, color: "#77BB77", value: n, label: n})), ...eventNames.map(n => ({type: 1, color: "#BB7777", value: n, label: n})), ...characters.map(c => ({type: 2, color: "#3377BB", value: c.id, label: c.name})), ], [channelNames, eventNames, characters])
const value = useMemo(() => { const value = []; if (filter.characters && filter.characters.length > 0) { value.push(...filter.characters.map(ch => options.find(c => c.type === 2 && c.value === ch))) } if (filter.events && filter.events.length > 0) { value.push(...filter.events.map(v => options.find(c => c.type === 1 && c.value === v))) } if (filter.channels && filter.channels.length > 0) { value.push(...filter.channels.map(v => options.find(c => c.type === 0 && c.value === v))) }
return value }, [filter, options])
const setValue = useCallback((value: {type:number, value:string}[] ) => { if (value == null) { value = []; }
updateFilter({ ...filter, channels: value.filter(v => v.type === 0).map(v => v.value), events: value.filter(v => v.type === 1).map(v => v.value), characters: value.filter(v => v.type === 2).map(v => v.value), }) }, [filter, updateFilter]);
return ( <Select className={cssStyles.multiSelect} closeMenuOnSelect={false} styles={colourStyles} filterOption={createFilter(filterConfig)} defaultValue={[]} isMulti={true} options={options} value={value} onChange={setValue} theme={defaultTheme => ({ ...defaultTheme, colors: { ...defaultTheme.colors, ...customTheme, }, })} /> ); }
const customTheme = { "primary": "#333333", "primary75": "#333333", "primary50": "#333333", "primary25": "#333333", "danger": "#000000", "dangerLight": "#000000", "neutral0": "#000000", "neutral5": "#000000", "neutral10": "#000000", "neutral20": "#000000", "neutral30": "#000000", "neutral40": "#000000", "neutral50": "#000000", "neutral60": "#000000", "neutral70": "#000000", "neutral80": "#000000", "neutral90": "#000000", }
const filterConfig: Config = { ignoreCase: true, ignoreAccents: true, trim: true, matchFrom: 'start', };
const colourStyles: Styles = { control: styles => ({ ...styles, backgroundColor: 'rgba(0, 0, 0, 0.25)' }), option: (styles, { data, isDisabled, isFocused, isSelected }) => { const color = chroma(data.color); return { ...styles, backgroundColor: isDisabled ? null : isSelected ? data.color : isFocused ? color.alpha(0.1).css() : null, color: isDisabled ? '#ccc' : isSelected ? chroma.contrast(color, 'white') > 2 ? 'white' : 'black' : data.color, cursor: isDisabled ? 'not-allowed' : 'default',
':active': { ...styles[':active'], backgroundColor: !isDisabled && (isSelected ? data.color : color.alpha(0.3).css()), }, }; }, multiValue: (styles, { data }) => { const color = chroma(data.color); return { ...styles, backgroundColor: color.alpha(0.1).css(), }; }, multiValueLabel: (styles, { data }) => ({ ...styles, color: data.color, }), multiValueRemove: (styles, { data }) => ({ ...styles, color: data.color, ':hover': { backgroundColor: data.color, color: 'white', }, }), };
|