/* eslint-disable max-lines-per-function */ import _ from 'lodash' // type Escape = (s: string) => string // const esc: Escape = s => `${s}` // const join = (...args: Array) => // args.filter(x => String(x)).join('-') // const trim = (s: string) => s.trim() import Regression from 'regression' const defaultTheme = { template: {}, grids: [1, 2, 3, 4, 5, 6, 8, 10, 12], spacing: { '2': '0.5rem', '4': '1rem' }, regression: { zeroLine: { type: 'linear', points: [ [0.75, 0.65], [6, 4.75], ], values: { one: 1 }, prop: 'lineHeight', }, arrayNum: { type: 'linear', points: [ [0.75, 0.65], [6, 4.75], ], values: [10, 30, 50], prop: 'lineHeight', }, }, } type DataPoint = [number, number] type Points = ReadonlyArray export type RegressionPluginOptions = { [name: string]: { points: ReadonlyArray source: {} } } import { TailwindPlugin } from './utils' type RegressionPlugin = (options?: RegressionPluginOptions) => TailwindPlugin export enum RegressionType { exponential = 'exponential', logarithmic = 'logarithmic', polynomial = 'polynomial', power = 'power', linear = 'linear', } // const RTypes = ['exponential', 'logarithmic', 'polynomial', 'power', 'linear'] export const regressionPlugin: RegressionPlugin = options => { const {} = options || {} return ({ addUtilities, e, theme, variants }) => { const config = theme('regression', defaultTheme.regression) const regressionVariants = variants('regression', ['responsive']) const mapped = _.map(config, (value, name) => { const regressionType = value.type in RegressionType ? (value.type as RegressionType) : 'linear' const points: Points = value.points.map(p => [p[0], p[1]]) const predictor = Regression[regressionType](points) const getPredicted = (value: string | number) => { if (typeof value === 'string') { const floatValue = parseFloat(value) const sourceValue = isNaN(floatValue) && `${parseInt(value)}` === `${value}` ? parseInt(value) : floatValue const predicted = predictor.predict(sourceValue)[1] return value.replace(`${sourceValue}`, `${predicted}`) } else { return predictor.predict(value)[1] } } const values = Array.isArray(value.values) ? value.values.map(key => [`${key}`, key]) : Object.entries(value.values) return { ...Object.fromEntries( values.map(([k, v]) => [ `.${e(`${name}-${k}`)}`, { [value.prop]: getPredicted(`${v}`) }, ]) ), } }) addUtilities([mapped], regressionVariants) } } export default regressionPlugin