import CSS from "csstype"; import { evaluateSpringyValueInterpolator, interpolateSpringyValueInterpolatables, SpringyValueInterpolatables, SpringyValueInterpolate, SpringyValueInterpolateds, SpringyValues } from "./SpringyValueHook"; import {isDefined} from "./type_check"; export interface ResourceBarColors { filledColor: CSS.Property.Color toFillColor: CSS.Property.Color toEmptyColor: CSS.Property.Color emptiedColor: CSS.Property.Color } export function resourceGradient( {filledColor, toFillColor, toEmptyColor, emptiedColor}: ResourceBarColors, {displayedValue, recentValue, newValue, maxValue}: SpringyValues, direction: string): string { const effectiveMax = isDefined(maxValue) && maxValue !== 0 ? maxValue : Number.POSITIVE_INFINITY const currentStop = Math.min(Math.max(100 * displayedValue / effectiveMax, 0), 100) const currentSoftEdgeLeft = Math.min(Math.max(currentStop - 0.2, 0), 100) const currentSoftEdgeRight = Math.min(Math.max(currentStop + 0.2, 0), 100) const endFillingStop = Math.min(Math.max(100 * recentValue / effectiveMax, 0), currentStop) const midFillingStop = Math.min(Math.max(100 * newValue / effectiveMax, endFillingStop), currentStop) const endFadingStop = Math.min(Math.max(100 * recentValue / effectiveMax, currentStop), 100) const midFadingStop = Math.min(Math.max(100 * newValue / effectiveMax, currentStop), endFadingStop) const layers = [] if (currentStop === 100) { layers.unshift(filledColor) } else { layers.unshift(emptiedColor) if (currentStop > 0) { layers.unshift(`linear-gradient(${direction}, ${filledColor} 0% ${currentSoftEdgeLeft.toFixed(4)}%, transparent ${currentSoftEdgeRight.toFixed(4)}% 100%)`) } } if (endFillingStop !== currentStop || midFillingStop !== currentStop) { layers.unshift(`linear-gradient(${direction}, transparent 0% ${endFillingStop.toFixed(4)}%, ${toFillColor} ${midFillingStop.toFixed(4)}% ${currentSoftEdgeLeft.toFixed(4)}%, transparent ${currentSoftEdgeRight.toFixed(4)}% 100%)`) } if (endFadingStop !== currentStop || midFadingStop !== currentStop) { layers.unshift(`linear-gradient(${direction}, transparent 0% ${currentSoftEdgeLeft.toFixed(4)}%, ${toEmptyColor} ${currentSoftEdgeRight.toFixed(4)}% ${midFadingStop.toFixed(4)}%, transparent ${endFadingStop.toFixed(4)}% 100%)`) } return layers.join(", ") } export interface ResourceBarStyles extends CSS.Properties { foreground?: CSS.Properties["background"] barDirection?: string barColors?: ResourceBarColors } export const DEFAULT_BAR_COLORS: ResourceBarColors = { emptiedColor: 'black', filledColor: 'limegreen', toEmptyColor: 'red', toFillColor: 'cyan', } as const export const DEFAULT_BAR_DIRECTION: string = "to right" export function evaluateResourceBarStyles(barStyle: SpringyValueInterpolatables, interpolate: SpringyValueInterpolate) { const intermediate: SpringyValueInterpolatables = Object.assign({}, barStyle) delete intermediate.background delete intermediate.foreground delete intermediate.barColors delete intermediate.barDirection intermediate.background = (v: SpringyValues) => [ evaluateSpringyValueInterpolator(barStyle["foreground"], v) as string | undefined, resourceGradient( evaluateSpringyValueInterpolator(barStyle["barColors"], v) ?? DEFAULT_BAR_COLORS, v, evaluateSpringyValueInterpolator(barStyle["barDirection"], v) ?? DEFAULT_BAR_DIRECTION), evaluateSpringyValueInterpolator(barStyle["background"], v) as string | undefined ].filter((s) => !!s).join(', ') return interpolateSpringyValueInterpolatables(intermediate as SpringyValueInterpolateds, interpolate) }