UNPKG

nevera

Version:

Minimal 3kb charts as web components

77 lines (67 loc) 2.05 kB
/** * @param domain - input domain [min, max] * @param range - output range [min, max] * @returns scale function */ export function scaleLinear(domain: [number, number], range: [number, number]) { const [domainMin, domainMax] = domain; const [rangeMin, rangeMax] = range; const scale = (value: number): number => { if (domainMax === domainMin) { throw new Error("Domain min and max cannot be the same"); } const ratio = (value - domainMin) / (domainMax - domainMin); return rangeMin + ratio * (rangeMax - rangeMin); }; return scale; } /** * @param domain - name of categories as array * @param range - output range [min, max] * @param padding - padding between column as fraction, 0 to 1 * @returns band function */ export function scaleBand( domain: string[], range: [number, number], padding: number = 0 ) { const [rangeMin, rangeMax] = range; const step = (rangeMax - rangeMin) / (domain.length + padding * (domain.length - 1)); const bandWidth = step * (1 - padding); const positions = domain.map( (_, index) => rangeMin + index * (step + padding * step) ); const scale = (category: string): number | undefined => { const index = domain.indexOf(category); if (index === -1) return; return positions[index]; }; // TODO: not in love with this scale.bandWidth = bandWidth; return scale; } export const attachEvents = ( svg: SVGSVGElement, elName: string, data: { key: string }[], self: any ) => { const elements = svg.querySelectorAll(elName); const emitEvent = (type: string, value: string) => (e: Event) => { e.stopPropagation(); self.dispatchEvent( new CustomEvent(type, { bubbles: true, composed: true, detail: { value }, }) ); }; elements?.forEach((el, i) => { el.addEventListener("mouseover", emitEvent("mouseover", data[i].key)); el.addEventListener("mouseout", emitEvent("mouseout", data[i].key)); el.addEventListener("click", emitEvent("click", data[i].key)); }); };