| import { describe, it, expect } from 'vitest'; | ||
| import { | ||
| Poline, | ||
| ColorPoint, | ||
| positionFunctions, | ||
| pointToHSL, | ||
| hslToPoint, | ||
| randomHSLPair, | ||
| randomHSLTriple, | ||
| } from '../src/index'; | ||
| describe('ColorPoint', () => { | ||
| it('should initialize with xyz coordinates', () => { | ||
| const point = new ColorPoint({ xyz: [0.5, 0.5, 1] }); | ||
| expect(point.x).toBe(0.5); | ||
| expect(point.y).toBe(0.5); | ||
| expect(point.z).toBe(1); | ||
| expect(point.color).toBeDefined(); | ||
| expect(point.color.length).toBe(3); | ||
| }); | ||
| it('should initialize with HSL color', () => { | ||
| const point = new ColorPoint({ color: [180, 0.5, 0.5] }); | ||
| expect(point.color[0]).toBe(180); | ||
| expect(point.color[1]).toBe(0.5); | ||
| expect(point.color[2]).toBe(0.5); | ||
| expect(point.x).toBeDefined(); | ||
| expect(point.y).toBeDefined(); | ||
| expect(point.z).toBeDefined(); | ||
| }); | ||
| it('should throw error when initialized with both xyz and color', () => { | ||
| expect(() => { | ||
| new ColorPoint({ xyz: [0.5, 0.5, 1], color: [180, 0.5, 0.5] }); | ||
| }).toThrow('Point must be initialized with either x,y,z or hsl'); | ||
| }); | ||
| it('should throw error when initialized with neither xyz nor color', () => { | ||
| expect(() => { | ||
| new ColorPoint({}); | ||
| }).toThrow('Point must be initialized with either x,y,z or hsl'); | ||
| }); | ||
| it('should update color when position is set', () => { | ||
| const point = new ColorPoint({ xyz: [0.5, 0.5, 1] }); | ||
| const initialColor = [...point.color]; | ||
| point.position = [0.7, 0.7, 0.8]; | ||
| expect(point.x).toBe(0.7); | ||
| expect(point.y).toBe(0.7); | ||
| expect(point.z).toBe(0.8); | ||
| expect(point.color).not.toEqual(initialColor); | ||
| }); | ||
| it('should update position when HSL is set', () => { | ||
| const point = new ColorPoint({ color: [180, 0.5, 0.5] }); | ||
| const initialPosition = [point.x, point.y, point.z]; | ||
| point.hsl = [90, 0.8, 0.3]; | ||
| expect(point.color[0]).toBe(90); | ||
| expect(point.color[1]).toBe(0.8); | ||
| expect(point.color[2]).toBe(0.3); | ||
| expect([point.x, point.y, point.z]).not.toEqual(initialPosition); | ||
| }); | ||
| it('should generate valid CSS color strings', () => { | ||
| const point = new ColorPoint({ color: [180, 0.5, 0.5] }); | ||
| expect(point.hslCSS).toMatch(/^hsl\(\d+\.?\d*, \d+\.?\d*%, \d+\.?\d*%\)$/); | ||
| expect(point.oklchCSS).toMatch(/^oklch\(\d+\.?\d*% \d+\.?\d* \d+\.?\d*\)$/); | ||
| expect(point.lchCSS).toMatch(/^lch\(\d+\.?\d*% \d+\.?\d* \d+\.?\d*\)$/); | ||
| }); | ||
| it('should handle invertedLightness correctly', () => { | ||
| const point = new ColorPoint({ | ||
| color: [0, 1, 0.2], | ||
| invertedLightness: false, | ||
| }); | ||
| expect(point.color[2]).toBeCloseTo(0.2); | ||
| point.invertedLightness = true; | ||
| expect(point.color[2]).toBeCloseTo(0.8); | ||
| point.invertedLightness = false; | ||
| expect(point.color[2]).toBeCloseTo(0.2); | ||
| }); | ||
| it('should shift hue correctly', () => { | ||
| const point = new ColorPoint({ color: [100, 0.5, 0.5] }); | ||
| point.shiftHue(50); | ||
| expect(point.color[0]).toBe(150); | ||
| point.shiftHue(-200); | ||
| expect(point.color[0]).toBe(310); // (150 - 200 + 360) % 360 | ||
| }); | ||
| it('should handle hue wrapping at 360 degrees', () => { | ||
| const point = new ColorPoint({ color: [350, 0.5, 0.5] }); | ||
| point.shiftHue(20); | ||
| expect(point.color[0]).toBe(10); // (350 + 20) % 360 | ||
| }); | ||
| }); | ||
| describe('pointToHSL and hslToPoint conversion', () => { | ||
| it('should convert xyz to HSL', () => { | ||
| const hsl = pointToHSL([0.5, 0.5, 1], false); | ||
| expect(hsl).toBeDefined(); | ||
| expect(hsl.length).toBe(3); | ||
| expect(hsl[1]).toBe(1); // saturation from z | ||
| expect(hsl[2]).toBeCloseTo(0); // lightness at center | ||
| }); | ||
| it('should convert HSL to xyz', () => { | ||
| const xyz = hslToPoint([180, 0.8, 0.5], false); | ||
| expect(xyz).toBeDefined(); | ||
| expect(xyz.length).toBe(3); | ||
| expect(xyz[2]).toBe(0.8); // z from saturation | ||
| }); | ||
| it('should be reversible (xyz -> HSL -> xyz)', () => { | ||
| const originalXYZ: [number, number, number] = [0.7, 0.3, 0.9]; | ||
| const hsl = pointToHSL(originalXYZ, false); | ||
| const convertedXYZ = hslToPoint(hsl, false); | ||
| expect(convertedXYZ[0]).toBeCloseTo(originalXYZ[0], 5); | ||
| expect(convertedXYZ[1]).toBeCloseTo(originalXYZ[1], 5); | ||
| expect(convertedXYZ[2]).toBeCloseTo(originalXYZ[2], 5); | ||
| }); | ||
| it('should be reversible (HSL -> xyz -> HSL)', () => { | ||
| const originalHSL: [number, number, number] = [240, 0.6, 0.4]; | ||
| const xyz = hslToPoint(originalHSL, false); | ||
| const convertedHSL = pointToHSL(xyz, false); | ||
| expect(convertedHSL[0]).toBeCloseTo(originalHSL[0], 5); | ||
| expect(convertedHSL[1]).toBeCloseTo(originalHSL[1], 5); | ||
| expect(convertedHSL[2]).toBeCloseTo(originalHSL[2], 5); | ||
| }); | ||
| it('should handle invertedLightness in conversions', () => { | ||
| const hsl: [number, number, number] = [180, 0.5, 0.3]; | ||
| const xyz = hslToPoint(hsl, false); | ||
| const xyzInverted = hslToPoint(hsl, true); | ||
| const hslBack = pointToHSL(xyz, false); | ||
| const hslBackInverted = pointToHSL(xyzInverted, true); | ||
| expect(hslBack[2]).toBeCloseTo(0.3, 5); | ||
| expect(hslBackInverted[2]).toBeCloseTo(0.3, 5); | ||
| }); | ||
| }); | ||
| describe('randomHSLPair and randomHSLTriple', () => { | ||
| it('should generate random HSL pair with default values', () => { | ||
| const pair = randomHSLPair(); | ||
| expect(pair.length).toBe(2); | ||
| expect(pair[0].length).toBe(3); | ||
| expect(pair[1].length).toBe(3); | ||
| // Check hue range | ||
| expect(pair[0][0]).toBeGreaterThanOrEqual(0); | ||
| expect(pair[0][0]).toBeLessThan(360); | ||
| expect(pair[1][0]).toBeGreaterThanOrEqual(0); | ||
| expect(pair[1][0]).toBeLessThan(360); | ||
| // Check saturation range | ||
| expect(pair[0][1]).toBeGreaterThanOrEqual(0); | ||
| expect(pair[0][1]).toBeLessThanOrEqual(1); | ||
| expect(pair[1][1]).toBeGreaterThanOrEqual(0); | ||
| expect(pair[1][1]).toBeLessThanOrEqual(1); | ||
| // Check lightness range | ||
| expect(pair[0][2]).toBeGreaterThanOrEqual(0); | ||
| expect(pair[0][2]).toBeLessThanOrEqual(1); | ||
| expect(pair[1][2]).toBeGreaterThanOrEqual(0); | ||
| expect(pair[1][2]).toBeLessThanOrEqual(1); | ||
| }); | ||
| it('should generate random HSL pair with custom values', () => { | ||
| const pair = randomHSLPair(100, [0.5, 0.8], [0.2, 0.7]); | ||
| expect(pair[0][0]).toBe(100); | ||
| expect(pair[0][1]).toBe(0.5); | ||
| expect(pair[0][2]).toBe(0.2); | ||
| expect(pair[1][1]).toBe(0.8); | ||
| expect(pair[1][2]).toBe(0.7); | ||
| }); | ||
| it('should generate random HSL triple with default values', () => { | ||
| const triple = randomHSLTriple(); | ||
| expect(triple.length).toBe(3); | ||
| triple.forEach((color) => { | ||
| expect(color.length).toBe(3); | ||
| expect(color[0]).toBeGreaterThanOrEqual(0); | ||
| expect(color[0]).toBeLessThan(360); | ||
| expect(color[1]).toBeGreaterThanOrEqual(0); | ||
| expect(color[1]).toBeLessThanOrEqual(1); | ||
| expect(color[2]).toBeGreaterThanOrEqual(0); | ||
| expect(color[2]).toBeLessThanOrEqual(1); | ||
| }); | ||
| }); | ||
| it('should generate random HSL triple with custom values', () => { | ||
| const triple = randomHSLTriple(200, [0.3, 0.6, 0.9], [0.1, 0.5, 0.8]); | ||
| expect(triple[0][0]).toBe(200); | ||
| expect(triple[0][1]).toBe(0.3); | ||
| expect(triple[0][2]).toBe(0.1); | ||
| expect(triple[1][1]).toBe(0.6); | ||
| expect(triple[1][2]).toBe(0.5); | ||
| expect(triple[2][1]).toBe(0.9); | ||
| expect(triple[2][2]).toBe(0.8); | ||
| }); | ||
| }); | ||
| describe('Poline', () => { | ||
| it('should initialize with default values', () => { | ||
| const poline = new Poline(); | ||
| expect(poline.anchorPoints.length).toBe(2); // Default random pair | ||
| expect(poline.numPoints).toBe(4); // Default numPoints | ||
| expect(poline.invertedLightness).toBe(false); | ||
| expect(poline.closedLoop).toBe(false); | ||
| }); | ||
| it('should initialize with custom options', () => { | ||
| const poline = new Poline({ | ||
| anchorColors: [ | ||
| [0, 1, 0.5], | ||
| [180, 1, 0.5], | ||
| ], | ||
| numPoints: 10, | ||
| invertedLightness: true, | ||
| closedLoop: true, | ||
| }); | ||
| expect(poline.numPoints).toBe(10); | ||
| expect(poline.invertedLightness).toBe(true); | ||
| expect(poline.closedLoop).toBe(true); | ||
| expect(poline.anchorPoints.length).toBe(2); | ||
| }); | ||
| it('should throw error when initialized with less than 2 anchor colors', () => { | ||
| expect(() => { | ||
| new Poline({ anchorColors: [[0, 1, 0.5]] }); | ||
| }).toThrow('Must have at least two anchor colors'); | ||
| }); | ||
| it('should update anchor points when invertedLightness is toggled', () => { | ||
| const poline = new Poline({ | ||
| anchorColors: [ | ||
| [0, 1, 0.5], | ||
| [180, 1, 0.5], | ||
| ], // HSL | ||
| invertedLightness: false, | ||
| }); | ||
| // Toggle invertedLightness | ||
| poline.invertedLightness = true; | ||
| // Check if the property updated | ||
| expect(poline.invertedLightness).toBe(true); | ||
| }); | ||
| it('should correctly invert lightness for anchors', () => { | ||
| const poline = new Poline({ | ||
| anchorColors: [ | ||
| [0, 1, 0.2], | ||
| [0, 1, 0.2], | ||
| ], // Dark color | ||
| invertedLightness: false, | ||
| }); | ||
| // Initial state: Lightness 0.2 | ||
| expect(poline.anchorPoints[0].color[2]).toBeCloseTo(0.2); | ||
| // Invert | ||
| poline.invertedLightness = true; | ||
| // New state: Lightness should be 1 - 0.2 = 0.8 | ||
| expect(poline.anchorPoints[0].color[2]).toBeCloseTo(0.8); | ||
| // Invert back | ||
| poline.invertedLightness = false; | ||
| expect(poline.anchorPoints[0].color[2]).toBeCloseTo(0.2); | ||
| }); | ||
| it('should add and remove anchor points', () => { | ||
| const poline = new Poline(); | ||
| const initialCount = poline.anchorPoints.length; | ||
| poline.addAnchorPoint({ color: [0, 1, 0.5] }); | ||
| expect(poline.anchorPoints.length).toBe(initialCount + 1); | ||
| poline.removeAnchorPoint({ index: initialCount }); | ||
| expect(poline.anchorPoints.length).toBe(initialCount); | ||
| }); | ||
| it('should throw error when removing anchor point with less than 3 remaining', () => { | ||
| const poline = new Poline({ | ||
| anchorColors: [ | ||
| [0, 1, 0.5], | ||
| [180, 1, 0.5], | ||
| ], | ||
| }); | ||
| expect(() => { | ||
| poline.removeAnchorPoint({ index: 0 }); | ||
| }).toThrow('Must have at least two anchor points'); | ||
| }); | ||
| it('should get color at specific position', () => { | ||
| const poline = new Poline({ | ||
| anchorColors: [ | ||
| [0, 1, 0.5], | ||
| [0, 1, 0.5], | ||
| ], // Same color for easy check | ||
| positionFunction: positionFunctions.linearPosition, | ||
| }); | ||
| const color = poline.getColorAt(0.5); | ||
| expect(color.color[0]).toBeCloseTo(0); | ||
| expect(color.color[1]).toBeCloseTo(1); | ||
| expect(color.color[2]).toBeCloseTo(0.5); | ||
| }); | ||
| it('should throw error when getColorAt is called with invalid position', () => { | ||
| const poline = new Poline(); | ||
| expect(() => poline.getColorAt(-0.1)).toThrow( | ||
| 'Position must be between 0 and 1' | ||
| ); | ||
| expect(() => poline.getColorAt(1.1)).toThrow( | ||
| 'Position must be between 0 and 1' | ||
| ); | ||
| }); | ||
| it('should handle getColorAt at edge positions', () => { | ||
| const poline = new Poline({ | ||
| anchorColors: [ | ||
| [0, 1, 0.2], | ||
| [180, 1, 0.8], | ||
| ], | ||
| positionFunction: positionFunctions.linearPosition, | ||
| }); | ||
| const colorStart = poline.getColorAt(0); | ||
| const colorEnd = poline.getColorAt(1); | ||
| // At start should be close to first anchor | ||
| expect(colorStart.color[0]).toBeCloseTo(0, 0); | ||
| expect(colorStart.color[2]).toBeCloseTo(0.2, 0); | ||
| // At end should be close to second anchor | ||
| expect(colorEnd.color[0]).toBeCloseTo(180, 0); | ||
| expect(colorEnd.color[2]).toBeCloseTo(0.8, 0); | ||
| }); | ||
| it('should update numPoints correctly', () => { | ||
| const poline = new Poline({ numPoints: 5 }); | ||
| expect(poline.numPoints).toBe(5); | ||
| poline.numPoints = 10; | ||
| expect(poline.numPoints).toBe(10); | ||
| }); | ||
| it('should throw error when numPoints is less than 1', () => { | ||
| const poline = new Poline(); | ||
| expect(() => { | ||
| poline.numPoints = 0; | ||
| }).toThrow('Must have at least one point'); | ||
| }); | ||
| it('should update and retrieve position functions', () => { | ||
| const poline = new Poline(); | ||
| poline.positionFunction = positionFunctions.exponentialPosition; | ||
| expect(poline.positionFunction).toBe( | ||
| positionFunctions.exponentialPosition | ||
| ); | ||
| }); | ||
| it('should handle array of position functions', () => { | ||
| const poline = new Poline(); | ||
| const funcs = [ | ||
| positionFunctions.linearPosition, | ||
| positionFunctions.exponentialPosition, | ||
| positionFunctions.quadraticPosition, | ||
| ]; | ||
| poline.positionFunction = funcs; | ||
| expect(poline.positionFunctionX).toBe(funcs[0]); | ||
| expect(poline.positionFunctionY).toBe(funcs[1]); | ||
| expect(poline.positionFunctionZ).toBe(funcs[2]); | ||
| }); | ||
| it('should throw error with invalid position function array', () => { | ||
| const poline = new Poline(); | ||
| expect(() => { | ||
| poline.positionFunction = [positionFunctions.linearPosition]; | ||
| }).toThrow('Position function array must have 3 elements'); | ||
| }); | ||
| it('should update individual position functions', () => { | ||
| const poline = new Poline(); | ||
| poline.positionFunctionX = positionFunctions.linearPosition; | ||
| poline.positionFunctionY = positionFunctions.exponentialPosition; | ||
| poline.positionFunctionZ = positionFunctions.quadraticPosition; | ||
| expect(poline.positionFunctionX).toBe(positionFunctions.linearPosition); | ||
| expect(poline.positionFunctionY).toBe( | ||
| positionFunctions.exponentialPosition | ||
| ); | ||
| expect(poline.positionFunctionZ).toBe(positionFunctions.quadraticPosition); | ||
| }); | ||
| it('should add anchor point at specific index', () => { | ||
| const poline = new Poline({ | ||
| anchorColors: [ | ||
| [0, 1, 0.5], | ||
| [180, 1, 0.5], | ||
| ], | ||
| }); | ||
| poline.addAnchorPoint({ color: [90, 1, 0.5], insertAtIndex: 1 }); | ||
| expect(poline.anchorPoints.length).toBe(3); | ||
| expect(poline.anchorPoints[1].color[0]).toBe(90); | ||
| }); | ||
| it('should update anchor point by index', () => { | ||
| const poline = new Poline({ | ||
| anchorColors: [ | ||
| [0, 1, 0.5], | ||
| [180, 1, 0.5], | ||
| ], | ||
| }); | ||
| poline.updateAnchorPoint({ pointIndex: 0, color: [45, 0.8, 0.6] }); | ||
| expect(poline.anchorPoints[0].color[0]).toBe(45); | ||
| expect(poline.anchorPoints[0].color[1]).toBe(0.8); | ||
| expect(poline.anchorPoints[0].color[2]).toBe(0.6); | ||
| }); | ||
| it('should update anchor point by reference', () => { | ||
| const poline = new Poline({ | ||
| anchorColors: [ | ||
| [0, 1, 0.5], | ||
| [180, 1, 0.5], | ||
| ], | ||
| }); | ||
| const anchor = poline.anchorPoints[0]; | ||
| poline.updateAnchorPoint({ point: anchor, color: [90, 0.7, 0.4] }); | ||
| expect(poline.anchorPoints[0].color[0]).toBe(90); | ||
| }); | ||
| it('should throw error when updating without point or index', () => { | ||
| const poline = new Poline(); | ||
| expect(() => { | ||
| poline.updateAnchorPoint({ color: [0, 1, 0.5] }); | ||
| }).toThrow('Must provide a point or pointIndex'); | ||
| }); | ||
| it('should throw error when updating without new values', () => { | ||
| const poline = new Poline(); | ||
| expect(() => { | ||
| poline.updateAnchorPoint({ pointIndex: 0 }); | ||
| }).toThrow('Must provide a new xyz position or color'); | ||
| }); | ||
| it('should find closest anchor point by xyz', () => { | ||
| const poline = new Poline({ | ||
| anchorColors: [ | ||
| [0, 1, 0.5], | ||
| [180, 1, 0.5], | ||
| ], | ||
| }); | ||
| const anchor0Pos = poline.anchorPoints[0].position; | ||
| const closest = poline.getClosestAnchorPoint({ | ||
| xyz: [anchor0Pos[0] + 0.01, anchor0Pos[1] + 0.01, anchor0Pos[2]], | ||
| }); | ||
| expect(closest).toBe(poline.anchorPoints[0]); | ||
| }); | ||
| it('should find closest anchor point by hsl', () => { | ||
| const poline = new Poline({ | ||
| anchorColors: [ | ||
| [0, 1, 0.5], | ||
| [180, 1, 0.5], | ||
| ], | ||
| }); | ||
| const closest = poline.getClosestAnchorPoint({ hsl: [5, 1, 0.5] }); | ||
| expect(closest).toBe(poline.anchorPoints[0]); | ||
| }); | ||
| it('should return null when no anchor within maxDistance', () => { | ||
| const poline = new Poline({ | ||
| anchorColors: [ | ||
| [0, 1, 0.5], | ||
| [180, 1, 0.5], | ||
| ], | ||
| }); | ||
| const closest = poline.getClosestAnchorPoint({ | ||
| xyz: [5, 5, 5], | ||
| maxDistance: 0.01, | ||
| }); | ||
| expect(closest).toBeNull(); | ||
| }); | ||
| it('should throw error when getClosestAnchorPoint called without xyz or hsl', () => { | ||
| const poline = new Poline(); | ||
| expect(() => { | ||
| poline.getClosestAnchorPoint({ maxDistance: 1 }); | ||
| }).toThrow('Must provide a xyz or hsl'); | ||
| }); | ||
| it('should toggle closedLoop', () => { | ||
| const poline = new Poline({ closedLoop: false }); | ||
| expect(poline.closedLoop).toBe(false); | ||
| poline.closedLoop = true; | ||
| expect(poline.closedLoop).toBe(true); | ||
| }); | ||
| it('should shift hue for all anchor points', () => { | ||
| const poline = new Poline({ | ||
| anchorColors: [ | ||
| [100, 1, 0.5], | ||
| [200, 1, 0.5], | ||
| ], | ||
| }); | ||
| poline.shiftHue(30); | ||
| expect(poline.anchorPoints[0].color[0]).toBe(130); | ||
| expect(poline.anchorPoints[1].color[0]).toBe(230); | ||
| }); | ||
| it('should generate flattenedPoints correctly', () => { | ||
| const poline = new Poline({ | ||
| anchorColors: [ | ||
| [0, 1, 0.5], | ||
| [180, 1, 0.5], | ||
| ], | ||
| numPoints: 4, | ||
| }); | ||
| const flattened = poline.flattenedPoints; | ||
| expect(flattened.length).toBeGreaterThan(0); | ||
| expect(flattened[0]).toBeInstanceOf(ColorPoint); | ||
| }); | ||
| it('should generate colors array', () => { | ||
| const poline = new Poline({ | ||
| anchorColors: [ | ||
| [0, 1, 0.5], | ||
| [180, 1, 0.5], | ||
| ], | ||
| numPoints: 4, | ||
| }); | ||
| const colors = poline.colors; | ||
| expect(colors.length).toBeGreaterThan(0); | ||
| colors.forEach((color) => { | ||
| expect(color.length).toBe(3); | ||
| }); | ||
| }); | ||
| it('should generate CSS color strings in different formats', () => { | ||
| const poline = new Poline({ | ||
| anchorColors: [ | ||
| [0, 1, 0.5], | ||
| [180, 1, 0.5], | ||
| ], | ||
| numPoints: 2, | ||
| }); | ||
| const hslColors = poline.colorsCSS; | ||
| const lchColors = poline.colorsCSSlch; | ||
| const oklchColors = poline.colorsCSSoklch; | ||
| expect(hslColors.length).toBeGreaterThan(0); | ||
| expect(lchColors.length).toBeGreaterThan(0); | ||
| expect(oklchColors.length).toBeGreaterThan(0); | ||
| hslColors.forEach((color) => { | ||
| expect(color).toMatch(/^hsl\(/); | ||
| }); | ||
| lchColors.forEach((color) => { | ||
| expect(color).toMatch(/^lch\(/); | ||
| }); | ||
| oklchColors.forEach((color) => { | ||
| expect(color).toMatch(/^oklch\(/); | ||
| }); | ||
| }); | ||
| it('should handle closed loop with 2 anchors correctly', () => { | ||
| const poline = new Poline({ | ||
| anchorColors: [ | ||
| [0, 1, 0.5], | ||
| [180, 1, 0.5], | ||
| ], | ||
| closedLoop: true, | ||
| numPoints: 4, | ||
| }); | ||
| expect(poline.closedLoop).toBe(true); | ||
| const colors = poline.colors; | ||
| expect(colors.length).toBeGreaterThan(0); | ||
| }); | ||
| it('should handle multiple anchor points in closed loop', () => { | ||
| const poline = new Poline({ | ||
| anchorColors: [ | ||
| [0, 1, 0.5], | ||
| [120, 1, 0.5], | ||
| [240, 1, 0.5], | ||
| ], | ||
| closedLoop: true, | ||
| numPoints: 3, | ||
| }); | ||
| expect(poline.anchorPoints.length).toBe(3); | ||
| expect(poline.closedLoop).toBe(true); | ||
| }); | ||
| it('should interpolate colors correctly across multiple segments', () => { | ||
| const poline = new Poline({ | ||
| anchorColors: [ | ||
| [0, 1, 0.2], | ||
| [120, 1, 0.5], | ||
| [240, 1, 0.8], | ||
| ], | ||
| positionFunction: positionFunctions.linearPosition, | ||
| numPoints: 2, | ||
| }); | ||
| // Test start | ||
| const colorStart = poline.getColorAt(0); | ||
| expect(colorStart.color[0]).toBeCloseTo(0, 0); | ||
| // Test middle (should be in second segment) | ||
| const colorMiddle = poline.getColorAt(0.5); | ||
| expect(colorMiddle.color[0]).toBeGreaterThan(0); | ||
| expect(colorMiddle.color[0]).toBeLessThan(240); | ||
| // Test end | ||
| const colorEnd = poline.getColorAt(1); | ||
| expect(colorEnd.color[0]).toBeCloseTo(240, 0); | ||
| }); | ||
| }); | ||
| describe('Position Functions', () => { | ||
| it('should have all expected position functions', () => { | ||
| expect(positionFunctions.linearPosition).toBeDefined(); | ||
| expect(positionFunctions.exponentialPosition).toBeDefined(); | ||
| expect(positionFunctions.quadraticPosition).toBeDefined(); | ||
| expect(positionFunctions.cubicPosition).toBeDefined(); | ||
| expect(positionFunctions.quarticPosition).toBeDefined(); | ||
| expect(positionFunctions.sinusoidalPosition).toBeDefined(); | ||
| expect(positionFunctions.asinusoidalPosition).toBeDefined(); | ||
| expect(positionFunctions.arcPosition).toBeDefined(); | ||
| expect(positionFunctions.smoothStepPosition).toBeDefined(); | ||
| }); | ||
| it('should return values between 0 and 1 for t between 0 and 1', () => { | ||
| const functions = Object.values(positionFunctions); | ||
| const testValues = [0, 0.25, 0.5, 0.75, 1]; | ||
| functions.forEach((fn) => { | ||
| testValues.forEach((t) => { | ||
| const result = fn(t); | ||
| expect(result).toBeGreaterThanOrEqual(0); | ||
| expect(result).toBeLessThanOrEqual(1); | ||
| }); | ||
| }); | ||
| }); | ||
| it('should return 0 at t=0 for most functions', () => { | ||
| expect(positionFunctions.linearPosition(0)).toBe(0); | ||
| expect(positionFunctions.exponentialPosition(0)).toBe(0); | ||
| expect(positionFunctions.quadraticPosition(0)).toBe(0); | ||
| expect(positionFunctions.cubicPosition(0)).toBe(0); | ||
| expect(positionFunctions.quarticPosition(0)).toBe(0); | ||
| expect(positionFunctions.sinusoidalPosition(0)).toBeCloseTo(0); | ||
| expect(positionFunctions.asinusoidalPosition(0)).toBeCloseTo(0); | ||
| expect(positionFunctions.smoothStepPosition(0)).toBe(0); | ||
| }); | ||
| it('should return 1 at t=1 for all functions', () => { | ||
| Object.values(positionFunctions).forEach((fn) => { | ||
| expect(fn(1)).toBeCloseTo(1); | ||
| }); | ||
| }); | ||
| it('should handle reverse parameter correctly', () => { | ||
| const t = 0.3; | ||
| const expNormal = positionFunctions.exponentialPosition(t, false); | ||
| const expReverse = positionFunctions.exponentialPosition(t, true); | ||
| expect(expReverse).toBeGreaterThan(expNormal); | ||
| const sinNormal = positionFunctions.sinusoidalPosition(t, false); | ||
| const sinReverse = positionFunctions.sinusoidalPosition(t, true); | ||
| // sinReverse should be less than sinNormal for early t values | ||
| // because reverse means 1 - sin((1-t) * PI/2) which is smaller for small t | ||
| expect(sinReverse).toBeLessThan(sinNormal); | ||
| }); | ||
| it('linearPosition should return t', () => { | ||
| expect(positionFunctions.linearPosition(0.3)).toBe(0.3); | ||
| expect(positionFunctions.linearPosition(0.7)).toBe(0.7); | ||
| }); | ||
| it('smoothStepPosition should have smooth transition', () => { | ||
| const p0 = positionFunctions.smoothStepPosition(0); | ||
| const p25 = positionFunctions.smoothStepPosition(0.25); | ||
| const p50 = positionFunctions.smoothStepPosition(0.5); | ||
| const p75 = positionFunctions.smoothStepPosition(0.75); | ||
| const p100 = positionFunctions.smoothStepPosition(1); | ||
| expect(p0).toBe(0); | ||
| expect(p50).toBe(0.5); | ||
| expect(p100).toBe(1); | ||
| expect(p25).toBeLessThan(0.5); | ||
| expect(p75).toBeGreaterThan(0.5); | ||
| }); | ||
| }); |
+11
-1
@@ -240,2 +240,12 @@ "use strict"; | ||
| } | ||
| set invertedLightness(val) { | ||
| this._invertedLightness = val; | ||
| this.color = pointToHSL( | ||
| [this.x, this.y, this.z], | ||
| this._invertedLightness | ||
| ); | ||
| } | ||
| get invertedLightness() { | ||
| return this._invertedLightness; | ||
| } | ||
| shiftHue(angle) { | ||
@@ -265,3 +275,2 @@ this.color[0] = (360 + (this.color[0] + angle)) % 360; | ||
| }) { | ||
| this._needsUpdate = true; | ||
| this._positionFunctionX = sinusoidalPosition; | ||
@@ -477,2 +486,3 @@ this._positionFunctionY = sinusoidalPosition; | ||
| this._invertedLightness = newStatus; | ||
| this.anchorPoints.forEach((p) => p.invertedLightness = newStatus); | ||
| this.updateAnchorPairs(); | ||
@@ -479,0 +489,0 @@ } |
+4
-3
@@ -65,7 +65,9 @@ export type FuncNumberReturn = (arg0: number) => Vector2; | ||
| get lchCSS(): string; | ||
| set invertedLightness(val: boolean); | ||
| get invertedLightness(): boolean; | ||
| shiftHue(angle: number): void; | ||
| } | ||
| export type PolineOptions = { | ||
| anchorColors: Vector3[]; | ||
| numPoints: number; | ||
| anchorColors?: Vector3[]; | ||
| numPoints?: number; | ||
| positionFunction?: (t: number, invert?: boolean) => number; | ||
@@ -79,3 +81,2 @@ positionFunctionX?: (t: number, invert?: boolean) => number; | ||
| export declare class Poline { | ||
| private _needsUpdate; | ||
| private _anchorPoints; | ||
@@ -82,0 +83,0 @@ private _numPoints; |
+11
-1
@@ -239,2 +239,12 @@ "use strict"; | ||
| } | ||
| set invertedLightness(val) { | ||
| this._invertedLightness = val; | ||
| this.color = pointToHSL( | ||
| [this.x, this.y, this.z], | ||
| this._invertedLightness | ||
| ); | ||
| } | ||
| get invertedLightness() { | ||
| return this._invertedLightness; | ||
| } | ||
| shiftHue(angle) { | ||
@@ -264,3 +274,2 @@ this.color[0] = (360 + (this.color[0] + angle)) % 360; | ||
| }) { | ||
| this._needsUpdate = true; | ||
| this._positionFunctionX = sinusoidalPosition; | ||
@@ -476,2 +485,3 @@ this._positionFunctionY = sinusoidalPosition; | ||
| this._invertedLightness = newStatus; | ||
| this.anchorPoints.forEach((p) => p.invertedLightness = newStatus); | ||
| this.updateAnchorPairs(); | ||
@@ -478,0 +488,0 @@ } |
@@ -1,1 +0,1 @@ | ||
| "use strict";var g=Object.defineProperty;var V=Object.getOwnPropertyDescriptor;var w=Object.getOwnPropertyNames;var L=Object.prototype.hasOwnProperty;var l=Math.pow;var S=(i,t)=>{for(var o in t)g(i,o,{get:t[o],enumerable:!0})},y=(i,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of w(t))!L.call(i,s)&&s!==o&&g(i,s,{get:()=>t[s],enumerable:!(n=V(t,s))||n.enumerable});return i};var E=i=>y(g({},"__esModule",{value:!0}),i);var H={};S(H,{ColorPoint:()=>P,Poline:()=>f,hslToPoint:()=>m,pointToHSL:()=>_,positionFunctions:()=>N,randomHSLPair:()=>v,randomHSLTriple:()=>I});module.exports=E(H);var _=(i,t)=>{let[o,n,s]=i,c=.5,h=.5,e=Math.atan2(n-h,o-c)*(180/Math.PI);e=(360+e)%360;let a=s,u=Math.sqrt(Math.pow(n-h,2)+Math.pow(o-c,2))/c;return[e,a,t?1-u:u]},m=(i,t)=>{let[o,n,s]=i,c=.5,h=.5,r=o/(180/Math.PI),e=(t?1-s:s)*c,a=c+e*Math.cos(r),d=h+e*Math.sin(r);return[a,d,n]},v=(i=Math.random()*360,t=[Math.random(),Math.random()],o=[.75+Math.random()*.2,.3+Math.random()*.2])=>[[i,t[0],o[0]],[(i+60+Math.random()*180)%360,t[1],o[1]]],I=(i=Math.random()*360,t=[Math.random(),Math.random(),Math.random()],o=[.75+Math.random()*.2,Math.random()*.2,.75+Math.random()*.2])=>[[i,t[0],o[0]],[(i+60+Math.random()*180)%360,t[1],o[1]],[(i+60+Math.random()*180)%360,t[2],o[2]]],x=(i,t,o,n=!1,s=(r,e)=>e?1-r:r,c=(r,e)=>e?1-r:r,h=(r,e)=>e?1-r:r)=>{let r=s(i,n),e=c(i,n),a=h(i,n),d=(1-r)*t[0]+r*o[0],u=(1-e)*t[1]+e*o[1],F=(1-a)*t[2]+a*o[2];return[d,u,F]},X=(i,t,o=4,n=!1,s=(r,e)=>e?1-r:r,c=(r,e)=>e?1-r:r,h=(r,e)=>e?1-r:r)=>{let r=[];for(let e=0;e<o;e++){let[a,d,u]=x(e/(o-1),i,t,n,s,c,h);r.push([a,d,u])}return r},Y=i=>i,Z=(i,t=!1)=>t?1-l(1-i,2):l(i,2),z=(i,t=!1)=>t?1-l(1-i,3):l(i,3),$=(i,t=!1)=>t?1-l(1-i,4):l(i,4),O=(i,t=!1)=>t?1-l(1-i,5):l(i,5),p=(i,t=!1)=>t?1-Math.sin((1-i)*Math.PI/2):Math.sin(i*Math.PI/2),k=(i,t=!1)=>t?1-Math.asin(1-i)/(Math.PI/2):Math.asin(i)/(Math.PI/2),T=(i,t=!1)=>t?1-Math.sqrt(1-l(i,2)):1-Math.sqrt(1-i),q=i=>l(i,2)*(3-2*i),N={linearPosition:Y,exponentialPosition:Z,quadraticPosition:z,cubicPosition:$,quarticPosition:O,sinusoidalPosition:p,asinusoidalPosition:k,arcPosition:T,smoothStepPosition:q},M=(i,t,o=!1)=>{let n=i[0],s=t[0],c=0;o&&n!==null&&s!==null?(c=Math.min(Math.abs(n-s),360-Math.abs(n-s)),c=c/360):c=n===null||s===null?0:n-s;let h=c,r=i[1]===null||t[1]===null?0:t[1]-i[1],e=i[2]===null||t[2]===null?0:t[2]-i[2];return Math.sqrt(h*h+r*r+e*e)},P=class{constructor({xyz:t,color:o,invertedLightness:n=!1}={}){this.x=0;this.y=0;this.z=0;this.color=[0,0,0];this._invertedLightness=!1;this._invertedLightness=n,this.positionOrColor({xyz:t,color:o,invertedLightness:n})}positionOrColor({xyz:t,color:o,invertedLightness:n=!1}){if(this._invertedLightness=n,t&&o||!t&&!o)throw new Error("Point must be initialized with either x,y,z or hsl");t?(this.x=t[0],this.y=t[1],this.z=t[2],this.color=_([this.x,this.y,this.z],n)):o&&(this.color=o,[this.x,this.y,this.z]=m(o,n))}set position([t,o,n]){this.x=t,this.y=o,this.z=n,this.color=_([this.x,this.y,this.z],this._invertedLightness)}get position(){return[this.x,this.y,this.z]}set hsl([t,o,n]){this.color=[t,o,n],[this.x,this.y,this.z]=m(this.color,this._invertedLightness)}get hsl(){return this.color}get hslCSS(){let[t,o,n]=this.color;return`hsl(${t.toFixed(2)}, ${(o*100).toFixed(2)}%, ${(n*100).toFixed(2)}%)`}get oklchCSS(){let[t,o,n]=this.color;return`oklch(${(n*100).toFixed(2)}% ${(o*.4).toFixed(3)} ${t.toFixed(2)})`}get lchCSS(){let[t,o,n]=this.color;return`lch(${(n*100).toFixed(2)}% ${(o*150).toFixed(2)} ${t.toFixed(2)})`}shiftHue(t){this.color[0]=(360+(this.color[0]+t))%360,[this.x,this.y,this.z]=m(this.color,this._invertedLightness)}},f=class{constructor({anchorColors:t=v(),numPoints:o=4,positionFunction:n=p,positionFunctionX:s,positionFunctionY:c,positionFunctionZ:h,closedLoop:r,invertedLightness:e}={anchorColors:v(),numPoints:4,positionFunction:p,closedLoop:!1}){this._needsUpdate=!0;this._positionFunctionX=p;this._positionFunctionY=p;this._positionFunctionZ=p;this.connectLastAndFirstAnchor=!1;this._animationFrame=null;this._invertedLightness=!1;if(!t||t.length<2)throw new Error("Must have at least two anchor colors");this._anchorPoints=t.map(a=>new P({color:a,invertedLightness:e})),this._numPoints=o+2,this._positionFunctionX=s||n||p,this._positionFunctionY=c||n||p,this._positionFunctionZ=h||n||p,this.connectLastAndFirstAnchor=r||!1,this._invertedLightness=e||!1,this.updateAnchorPairs()}get numPoints(){return this._numPoints-2}set numPoints(t){if(t<1)throw new Error("Must have at least one point");this._numPoints=t+2,this.updateAnchorPairs()}set positionFunction(t){if(Array.isArray(t)){if(t.length!==3)throw new Error("Position function array must have 3 elements");if(typeof t[0]!="function"||typeof t[1]!="function"||typeof t[2]!="function")throw new Error("Position function array must have 3 functions");this._positionFunctionX=t[0],this._positionFunctionY=t[1],this._positionFunctionZ=t[2]}else this._positionFunctionX=t,this._positionFunctionY=t,this._positionFunctionZ=t;this.updateAnchorPairs()}get positionFunction(){return this._positionFunctionX===this._positionFunctionY&&this._positionFunctionX===this._positionFunctionZ?this._positionFunctionX:[this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ]}set positionFunctionX(t){this._positionFunctionX=t,this.updateAnchorPairs()}get positionFunctionX(){return this._positionFunctionX}set positionFunctionY(t){this._positionFunctionY=t,this.updateAnchorPairs()}get positionFunctionY(){return this._positionFunctionY}set positionFunctionZ(t){this._positionFunctionZ=t,this.updateAnchorPairs()}get positionFunctionZ(){return this._positionFunctionZ}get anchorPoints(){return this._anchorPoints}set anchorPoints(t){this._anchorPoints=t,this.updateAnchorPairs()}updateAnchorPairs(){this._anchorPairs=[];let t=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1;for(let o=0;o<t;o++){let n=[this.anchorPoints[o],this.anchorPoints[(o+1)%this.anchorPoints.length]];this._anchorPairs.push(n)}this.points=this._anchorPairs.map((o,n)=>{let s=o[0]?o[0].position:[0,0,0],c=o[1]?o[1].position:[0,0,0],h=this.shouldInvertEaseForSegment(n);return X(s,c,this._numPoints,!!h,this.positionFunctionX,this.positionFunctionY,this.positionFunctionZ).map(r=>new P({xyz:r,invertedLightness:this._invertedLightness}))})}addAnchorPoint({xyz:t,color:o,insertAtIndex:n}){let s=new P({xyz:t,color:o,invertedLightness:this._invertedLightness});return n!==void 0?this.anchorPoints.splice(n,0,s):this.anchorPoints.push(s),this.updateAnchorPairs(),s}removeAnchorPoint({point:t,index:o}){if(!t&&o===void 0)throw new Error("Must provide a point or index");if(this.anchorPoints.length<3)throw new Error("Must have at least two anchor points");let n;if(o!==void 0?n=o:t&&(n=this.anchorPoints.indexOf(t)),n>-1&&n<this.anchorPoints.length)this.anchorPoints.splice(n,1),this.updateAnchorPairs();else throw new Error("Point not found")}updateAnchorPoint({point:t,pointIndex:o,xyz:n,color:s}){if(o!==void 0&&(t=this.anchorPoints[o]),!t)throw new Error("Must provide a point or pointIndex");if(!n&&!s)throw new Error("Must provide a new xyz position or color");return n&&(t.position=n),s&&(t.hsl=s),this.updateAnchorPairs(),t}getClosestAnchorPoint({xyz:t,hsl:o,maxDistance:n=1}){if(!t&&!o)throw new Error("Must provide a xyz or hsl");let s;t?s=this.anchorPoints.map(r=>M(r.position,t)):o&&(s=this.anchorPoints.map(r=>M(r.hsl,o,!0)));let c=Math.min(...s);if(c>n)return null;let h=s.indexOf(c);return this.anchorPoints[h]||null}set closedLoop(t){this.connectLastAndFirstAnchor=t,this.updateAnchorPairs()}get closedLoop(){return this.connectLastAndFirstAnchor}set invertedLightness(t){this._invertedLightness=t,this.updateAnchorPairs()}get invertedLightness(){return this._invertedLightness}get flattenedPoints(){return this.points.flat().filter((t,o)=>o!=0?o%this._numPoints:!0)}get colors(){let t=this.flattenedPoints.map(o=>o.color);return this.connectLastAndFirstAnchor&&this._anchorPoints.length!==2&&t.pop(),t}cssColors(t="hsl"){let o={hsl:s=>s.hslCSS,oklch:s=>s.oklchCSS,lch:s=>s.lchCSS},n=this.flattenedPoints.map(o[t]);return this.connectLastAndFirstAnchor&&n.pop(),n}get colorsCSS(){return this.cssColors("hsl")}get colorsCSSlch(){return this.cssColors("lch")}get colorsCSSoklch(){return this.cssColors("oklch")}shiftHue(t=20){this.anchorPoints.forEach(o=>o.shiftHue(t)),this.updateAnchorPairs()}getColorAt(t){var C;if(t<0||t>1)throw new Error("Position must be between 0 and 1");if(this.anchorPoints.length===0)throw new Error("No anchor points available");let o=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1,n=this.connectLastAndFirstAnchor&&this.anchorPoints.length===2?2:o,s=t*n,c=Math.floor(s),h=s-c,r=c>=n?n-1:c,e=c>=n?1:h,a=this._anchorPairs[r];if(!a||a.length<2||!a[0]||!a[1])return new P({color:((C=this.anchorPoints[0])==null?void 0:C.color)||[0,0,0],invertedLightness:this._invertedLightness});let d=a[0].position,u=a[1].position,F=this.shouldInvertEaseForSegment(r),A=x(e,d,u,F,this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ);return new P({xyz:A,invertedLightness:this._invertedLightness})}shouldInvertEaseForSegment(t){return!!(t%2||this.connectLastAndFirstAnchor&&this.anchorPoints.length===2&&t===0)}},{p5:b}=globalThis;if(b&&b.VERSION&&b.VERSION.startsWith("1.")){console.info("p5 < 1.x detected, adding poline to p5 prototype");let i=new f;b.prototype.poline=i;let t=()=>i.colors.map(o=>`hsl(${Math.round(o[0])},${o[1]*100}%,${o[2]*100}%)`);b.prototype.registerMethod("polineColors",t),globalThis.poline=i,globalThis.polineColors=t} | ||
| "use strict";var _=Object.defineProperty;var V=Object.getOwnPropertyDescriptor;var A=Object.getOwnPropertyNames;var w=Object.prototype.hasOwnProperty;var l=Math.pow;var y=(i,t)=>{for(var o in t)_(i,o,{get:t[o],enumerable:!0})},S=(i,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of A(t))!w.call(i,s)&&s!==o&&_(i,s,{get:()=>t[s],enumerable:!(n=V(t,s))||n.enumerable});return i};var E=i=>S(_({},"__esModule",{value:!0}),i);var H={};y(H,{ColorPoint:()=>P,Poline:()=>g,hslToPoint:()=>f,pointToHSL:()=>m,positionFunctions:()=>N,randomHSLPair:()=>v,randomHSLTriple:()=>I});module.exports=E(H);var m=(i,t)=>{let[o,n,s]=i,c=.5,h=.5,r=Math.atan2(n-h,o-c)*(180/Math.PI);r=(360+r)%360;let a=s,u=Math.sqrt(Math.pow(n-h,2)+Math.pow(o-c,2))/c;return[r,a,t?1-u:u]},f=(i,t)=>{let[o,n,s]=i,c=.5,h=.5,e=o/(180/Math.PI),r=(t?1-s:s)*c,a=c+r*Math.cos(e),d=h+r*Math.sin(e);return[a,d,n]},v=(i=Math.random()*360,t=[Math.random(),Math.random()],o=[.75+Math.random()*.2,.3+Math.random()*.2])=>[[i,t[0],o[0]],[(i+60+Math.random()*180)%360,t[1],o[1]]],I=(i=Math.random()*360,t=[Math.random(),Math.random(),Math.random()],o=[.75+Math.random()*.2,Math.random()*.2,.75+Math.random()*.2])=>[[i,t[0],o[0]],[(i+60+Math.random()*180)%360,t[1],o[1]],[(i+60+Math.random()*180)%360,t[2],o[2]]],x=(i,t,o,n=!1,s=(e,r)=>r?1-e:e,c=(e,r)=>r?1-e:e,h=(e,r)=>r?1-e:e)=>{let e=s(i,n),r=c(i,n),a=h(i,n),d=(1-e)*t[0]+e*o[0],u=(1-r)*t[1]+r*o[1],F=(1-a)*t[2]+a*o[2];return[d,u,F]},X=(i,t,o=4,n=!1,s=(e,r)=>r?1-e:e,c=(e,r)=>r?1-e:e,h=(e,r)=>r?1-e:e)=>{let e=[];for(let r=0;r<o;r++){let[a,d,u]=x(r/(o-1),i,t,n,s,c,h);e.push([a,d,u])}return e},z=i=>i,Y=(i,t=!1)=>t?1-l(1-i,2):l(i,2),Z=(i,t=!1)=>t?1-l(1-i,3):l(i,3),$=(i,t=!1)=>t?1-l(1-i,4):l(i,4),O=(i,t=!1)=>t?1-l(1-i,5):l(i,5),p=(i,t=!1)=>t?1-Math.sin((1-i)*Math.PI/2):Math.sin(i*Math.PI/2),k=(i,t=!1)=>t?1-Math.asin(1-i)/(Math.PI/2):Math.asin(i)/(Math.PI/2),T=(i,t=!1)=>t?1-Math.sqrt(1-l(i,2)):1-Math.sqrt(1-i),q=i=>l(i,2)*(3-2*i),N={linearPosition:z,exponentialPosition:Y,quadraticPosition:Z,cubicPosition:$,quarticPosition:O,sinusoidalPosition:p,asinusoidalPosition:k,arcPosition:T,smoothStepPosition:q},M=(i,t,o=!1)=>{let n=i[0],s=t[0],c=0;o&&n!==null&&s!==null?(c=Math.min(Math.abs(n-s),360-Math.abs(n-s)),c=c/360):c=n===null||s===null?0:n-s;let h=c,e=i[1]===null||t[1]===null?0:t[1]-i[1],r=i[2]===null||t[2]===null?0:t[2]-i[2];return Math.sqrt(h*h+e*e+r*r)},P=class{constructor({xyz:t,color:o,invertedLightness:n=!1}={}){this.x=0;this.y=0;this.z=0;this.color=[0,0,0];this._invertedLightness=!1;this._invertedLightness=n,this.positionOrColor({xyz:t,color:o,invertedLightness:n})}positionOrColor({xyz:t,color:o,invertedLightness:n=!1}){if(this._invertedLightness=n,t&&o||!t&&!o)throw new Error("Point must be initialized with either x,y,z or hsl");t?(this.x=t[0],this.y=t[1],this.z=t[2],this.color=m([this.x,this.y,this.z],n)):o&&(this.color=o,[this.x,this.y,this.z]=f(o,n))}set position([t,o,n]){this.x=t,this.y=o,this.z=n,this.color=m([this.x,this.y,this.z],this._invertedLightness)}get position(){return[this.x,this.y,this.z]}set hsl([t,o,n]){this.color=[t,o,n],[this.x,this.y,this.z]=f(this.color,this._invertedLightness)}get hsl(){return this.color}get hslCSS(){let[t,o,n]=this.color;return`hsl(${t.toFixed(2)}, ${(o*100).toFixed(2)}%, ${(n*100).toFixed(2)}%)`}get oklchCSS(){let[t,o,n]=this.color;return`oklch(${(n*100).toFixed(2)}% ${(o*.4).toFixed(3)} ${t.toFixed(2)})`}get lchCSS(){let[t,o,n]=this.color;return`lch(${(n*100).toFixed(2)}% ${(o*150).toFixed(2)} ${t.toFixed(2)})`}set invertedLightness(t){this._invertedLightness=t,this.color=m([this.x,this.y,this.z],this._invertedLightness)}get invertedLightness(){return this._invertedLightness}shiftHue(t){this.color[0]=(360+(this.color[0]+t))%360,[this.x,this.y,this.z]=f(this.color,this._invertedLightness)}},g=class{constructor({anchorColors:t=v(),numPoints:o=4,positionFunction:n=p,positionFunctionX:s,positionFunctionY:c,positionFunctionZ:h,closedLoop:e,invertedLightness:r}={anchorColors:v(),numPoints:4,positionFunction:p,closedLoop:!1}){this._positionFunctionX=p;this._positionFunctionY=p;this._positionFunctionZ=p;this.connectLastAndFirstAnchor=!1;this._animationFrame=null;this._invertedLightness=!1;if(!t||t.length<2)throw new Error("Must have at least two anchor colors");this._anchorPoints=t.map(a=>new P({color:a,invertedLightness:r})),this._numPoints=o+2,this._positionFunctionX=s||n||p,this._positionFunctionY=c||n||p,this._positionFunctionZ=h||n||p,this.connectLastAndFirstAnchor=e||!1,this._invertedLightness=r||!1,this.updateAnchorPairs()}get numPoints(){return this._numPoints-2}set numPoints(t){if(t<1)throw new Error("Must have at least one point");this._numPoints=t+2,this.updateAnchorPairs()}set positionFunction(t){if(Array.isArray(t)){if(t.length!==3)throw new Error("Position function array must have 3 elements");if(typeof t[0]!="function"||typeof t[1]!="function"||typeof t[2]!="function")throw new Error("Position function array must have 3 functions");this._positionFunctionX=t[0],this._positionFunctionY=t[1],this._positionFunctionZ=t[2]}else this._positionFunctionX=t,this._positionFunctionY=t,this._positionFunctionZ=t;this.updateAnchorPairs()}get positionFunction(){return this._positionFunctionX===this._positionFunctionY&&this._positionFunctionX===this._positionFunctionZ?this._positionFunctionX:[this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ]}set positionFunctionX(t){this._positionFunctionX=t,this.updateAnchorPairs()}get positionFunctionX(){return this._positionFunctionX}set positionFunctionY(t){this._positionFunctionY=t,this.updateAnchorPairs()}get positionFunctionY(){return this._positionFunctionY}set positionFunctionZ(t){this._positionFunctionZ=t,this.updateAnchorPairs()}get positionFunctionZ(){return this._positionFunctionZ}get anchorPoints(){return this._anchorPoints}set anchorPoints(t){this._anchorPoints=t,this.updateAnchorPairs()}updateAnchorPairs(){this._anchorPairs=[];let t=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1;for(let o=0;o<t;o++){let n=[this.anchorPoints[o],this.anchorPoints[(o+1)%this.anchorPoints.length]];this._anchorPairs.push(n)}this.points=this._anchorPairs.map((o,n)=>{let s=o[0]?o[0].position:[0,0,0],c=o[1]?o[1].position:[0,0,0],h=this.shouldInvertEaseForSegment(n);return X(s,c,this._numPoints,!!h,this.positionFunctionX,this.positionFunctionY,this.positionFunctionZ).map(e=>new P({xyz:e,invertedLightness:this._invertedLightness}))})}addAnchorPoint({xyz:t,color:o,insertAtIndex:n}){let s=new P({xyz:t,color:o,invertedLightness:this._invertedLightness});return n!==void 0?this.anchorPoints.splice(n,0,s):this.anchorPoints.push(s),this.updateAnchorPairs(),s}removeAnchorPoint({point:t,index:o}){if(!t&&o===void 0)throw new Error("Must provide a point or index");if(this.anchorPoints.length<3)throw new Error("Must have at least two anchor points");let n;if(o!==void 0?n=o:t&&(n=this.anchorPoints.indexOf(t)),n>-1&&n<this.anchorPoints.length)this.anchorPoints.splice(n,1),this.updateAnchorPairs();else throw new Error("Point not found")}updateAnchorPoint({point:t,pointIndex:o,xyz:n,color:s}){if(o!==void 0&&(t=this.anchorPoints[o]),!t)throw new Error("Must provide a point or pointIndex");if(!n&&!s)throw new Error("Must provide a new xyz position or color");return n&&(t.position=n),s&&(t.hsl=s),this.updateAnchorPairs(),t}getClosestAnchorPoint({xyz:t,hsl:o,maxDistance:n=1}){if(!t&&!o)throw new Error("Must provide a xyz or hsl");let s;t?s=this.anchorPoints.map(e=>M(e.position,t)):o&&(s=this.anchorPoints.map(e=>M(e.hsl,o,!0)));let c=Math.min(...s);if(c>n)return null;let h=s.indexOf(c);return this.anchorPoints[h]||null}set closedLoop(t){this.connectLastAndFirstAnchor=t,this.updateAnchorPairs()}get closedLoop(){return this.connectLastAndFirstAnchor}set invertedLightness(t){this._invertedLightness=t,this.anchorPoints.forEach(o=>o.invertedLightness=t),this.updateAnchorPairs()}get invertedLightness(){return this._invertedLightness}get flattenedPoints(){return this.points.flat().filter((t,o)=>o!=0?o%this._numPoints:!0)}get colors(){let t=this.flattenedPoints.map(o=>o.color);return this.connectLastAndFirstAnchor&&this._anchorPoints.length!==2&&t.pop(),t}cssColors(t="hsl"){let o={hsl:s=>s.hslCSS,oklch:s=>s.oklchCSS,lch:s=>s.lchCSS},n=this.flattenedPoints.map(o[t]);return this.connectLastAndFirstAnchor&&n.pop(),n}get colorsCSS(){return this.cssColors("hsl")}get colorsCSSlch(){return this.cssColors("lch")}get colorsCSSoklch(){return this.cssColors("oklch")}shiftHue(t=20){this.anchorPoints.forEach(o=>o.shiftHue(t)),this.updateAnchorPairs()}getColorAt(t){var C;if(t<0||t>1)throw new Error("Position must be between 0 and 1");if(this.anchorPoints.length===0)throw new Error("No anchor points available");let o=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1,n=this.connectLastAndFirstAnchor&&this.anchorPoints.length===2?2:o,s=t*n,c=Math.floor(s),h=s-c,e=c>=n?n-1:c,r=c>=n?1:h,a=this._anchorPairs[e];if(!a||a.length<2||!a[0]||!a[1])return new P({color:((C=this.anchorPoints[0])==null?void 0:C.color)||[0,0,0],invertedLightness:this._invertedLightness});let d=a[0].position,u=a[1].position,F=this.shouldInvertEaseForSegment(e),L=x(r,d,u,F,this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ);return new P({xyz:L,invertedLightness:this._invertedLightness})}shouldInvertEaseForSegment(t){return!!(t%2||this.connectLastAndFirstAnchor&&this.anchorPoints.length===2&&t===0)}},{p5:b}=globalThis;if(b&&b.VERSION&&b.VERSION.startsWith("1.")){console.info("p5 < 1.x detected, adding poline to p5 prototype");let i=new g;b.prototype.poline=i;let t=()=>i.colors.map(o=>`hsl(${Math.round(o[0])},${o[1]*100}%,${o[2]*100}%)`);b.prototype.registerMethod("polineColors",t),globalThis.poline=i,globalThis.polineColors=t} |
@@ -1,1 +0,1 @@ | ||
| "use strict";var poline=(()=>{var g=Object.defineProperty;var V=Object.getOwnPropertyDescriptor;var w=Object.getOwnPropertyNames;var L=Object.prototype.hasOwnProperty;var l=Math.pow;var S=(i,t)=>{for(var o in t)g(i,o,{get:t[o],enumerable:!0})},y=(i,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of w(t))!L.call(i,s)&&s!==o&&g(i,s,{get:()=>t[s],enumerable:!(n=V(t,s))||n.enumerable});return i};var E=i=>y(g({},"__esModule",{value:!0}),i);var H={};S(H,{ColorPoint:()=>P,Poline:()=>f,hslToPoint:()=>m,pointToHSL:()=>_,positionFunctions:()=>N,randomHSLPair:()=>v,randomHSLTriple:()=>I});var _=(i,t)=>{let[o,n,s]=i,c=.5,h=.5,e=Math.atan2(n-h,o-c)*(180/Math.PI);e=(360+e)%360;let a=s,u=Math.sqrt(Math.pow(n-h,2)+Math.pow(o-c,2))/c;return[e,a,t?1-u:u]},m=(i,t)=>{let[o,n,s]=i,c=.5,h=.5,r=o/(180/Math.PI),e=(t?1-s:s)*c,a=c+e*Math.cos(r),d=h+e*Math.sin(r);return[a,d,n]},v=(i=Math.random()*360,t=[Math.random(),Math.random()],o=[.75+Math.random()*.2,.3+Math.random()*.2])=>[[i,t[0],o[0]],[(i+60+Math.random()*180)%360,t[1],o[1]]],I=(i=Math.random()*360,t=[Math.random(),Math.random(),Math.random()],o=[.75+Math.random()*.2,Math.random()*.2,.75+Math.random()*.2])=>[[i,t[0],o[0]],[(i+60+Math.random()*180)%360,t[1],o[1]],[(i+60+Math.random()*180)%360,t[2],o[2]]],x=(i,t,o,n=!1,s=(r,e)=>e?1-r:r,c=(r,e)=>e?1-r:r,h=(r,e)=>e?1-r:r)=>{let r=s(i,n),e=c(i,n),a=h(i,n),d=(1-r)*t[0]+r*o[0],u=(1-e)*t[1]+e*o[1],F=(1-a)*t[2]+a*o[2];return[d,u,F]},X=(i,t,o=4,n=!1,s=(r,e)=>e?1-r:r,c=(r,e)=>e?1-r:r,h=(r,e)=>e?1-r:r)=>{let r=[];for(let e=0;e<o;e++){let[a,d,u]=x(e/(o-1),i,t,n,s,c,h);r.push([a,d,u])}return r},Y=i=>i,Z=(i,t=!1)=>t?1-l(1-i,2):l(i,2),z=(i,t=!1)=>t?1-l(1-i,3):l(i,3),$=(i,t=!1)=>t?1-l(1-i,4):l(i,4),O=(i,t=!1)=>t?1-l(1-i,5):l(i,5),p=(i,t=!1)=>t?1-Math.sin((1-i)*Math.PI/2):Math.sin(i*Math.PI/2),k=(i,t=!1)=>t?1-Math.asin(1-i)/(Math.PI/2):Math.asin(i)/(Math.PI/2),T=(i,t=!1)=>t?1-Math.sqrt(1-l(i,2)):1-Math.sqrt(1-i),q=i=>l(i,2)*(3-2*i),N={linearPosition:Y,exponentialPosition:Z,quadraticPosition:z,cubicPosition:$,quarticPosition:O,sinusoidalPosition:p,asinusoidalPosition:k,arcPosition:T,smoothStepPosition:q},M=(i,t,o=!1)=>{let n=i[0],s=t[0],c=0;o&&n!==null&&s!==null?(c=Math.min(Math.abs(n-s),360-Math.abs(n-s)),c=c/360):c=n===null||s===null?0:n-s;let h=c,r=i[1]===null||t[1]===null?0:t[1]-i[1],e=i[2]===null||t[2]===null?0:t[2]-i[2];return Math.sqrt(h*h+r*r+e*e)},P=class{constructor({xyz:t,color:o,invertedLightness:n=!1}={}){this.x=0;this.y=0;this.z=0;this.color=[0,0,0];this._invertedLightness=!1;this._invertedLightness=n,this.positionOrColor({xyz:t,color:o,invertedLightness:n})}positionOrColor({xyz:t,color:o,invertedLightness:n=!1}){if(this._invertedLightness=n,t&&o||!t&&!o)throw new Error("Point must be initialized with either x,y,z or hsl");t?(this.x=t[0],this.y=t[1],this.z=t[2],this.color=_([this.x,this.y,this.z],n)):o&&(this.color=o,[this.x,this.y,this.z]=m(o,n))}set position([t,o,n]){this.x=t,this.y=o,this.z=n,this.color=_([this.x,this.y,this.z],this._invertedLightness)}get position(){return[this.x,this.y,this.z]}set hsl([t,o,n]){this.color=[t,o,n],[this.x,this.y,this.z]=m(this.color,this._invertedLightness)}get hsl(){return this.color}get hslCSS(){let[t,o,n]=this.color;return`hsl(${t.toFixed(2)}, ${(o*100).toFixed(2)}%, ${(n*100).toFixed(2)}%)`}get oklchCSS(){let[t,o,n]=this.color;return`oklch(${(n*100).toFixed(2)}% ${(o*.4).toFixed(3)} ${t.toFixed(2)})`}get lchCSS(){let[t,o,n]=this.color;return`lch(${(n*100).toFixed(2)}% ${(o*150).toFixed(2)} ${t.toFixed(2)})`}shiftHue(t){this.color[0]=(360+(this.color[0]+t))%360,[this.x,this.y,this.z]=m(this.color,this._invertedLightness)}},f=class{constructor({anchorColors:t=v(),numPoints:o=4,positionFunction:n=p,positionFunctionX:s,positionFunctionY:c,positionFunctionZ:h,closedLoop:r,invertedLightness:e}={anchorColors:v(),numPoints:4,positionFunction:p,closedLoop:!1}){this._needsUpdate=!0;this._positionFunctionX=p;this._positionFunctionY=p;this._positionFunctionZ=p;this.connectLastAndFirstAnchor=!1;this._animationFrame=null;this._invertedLightness=!1;if(!t||t.length<2)throw new Error("Must have at least two anchor colors");this._anchorPoints=t.map(a=>new P({color:a,invertedLightness:e})),this._numPoints=o+2,this._positionFunctionX=s||n||p,this._positionFunctionY=c||n||p,this._positionFunctionZ=h||n||p,this.connectLastAndFirstAnchor=r||!1,this._invertedLightness=e||!1,this.updateAnchorPairs()}get numPoints(){return this._numPoints-2}set numPoints(t){if(t<1)throw new Error("Must have at least one point");this._numPoints=t+2,this.updateAnchorPairs()}set positionFunction(t){if(Array.isArray(t)){if(t.length!==3)throw new Error("Position function array must have 3 elements");if(typeof t[0]!="function"||typeof t[1]!="function"||typeof t[2]!="function")throw new Error("Position function array must have 3 functions");this._positionFunctionX=t[0],this._positionFunctionY=t[1],this._positionFunctionZ=t[2]}else this._positionFunctionX=t,this._positionFunctionY=t,this._positionFunctionZ=t;this.updateAnchorPairs()}get positionFunction(){return this._positionFunctionX===this._positionFunctionY&&this._positionFunctionX===this._positionFunctionZ?this._positionFunctionX:[this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ]}set positionFunctionX(t){this._positionFunctionX=t,this.updateAnchorPairs()}get positionFunctionX(){return this._positionFunctionX}set positionFunctionY(t){this._positionFunctionY=t,this.updateAnchorPairs()}get positionFunctionY(){return this._positionFunctionY}set positionFunctionZ(t){this._positionFunctionZ=t,this.updateAnchorPairs()}get positionFunctionZ(){return this._positionFunctionZ}get anchorPoints(){return this._anchorPoints}set anchorPoints(t){this._anchorPoints=t,this.updateAnchorPairs()}updateAnchorPairs(){this._anchorPairs=[];let t=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1;for(let o=0;o<t;o++){let n=[this.anchorPoints[o],this.anchorPoints[(o+1)%this.anchorPoints.length]];this._anchorPairs.push(n)}this.points=this._anchorPairs.map((o,n)=>{let s=o[0]?o[0].position:[0,0,0],c=o[1]?o[1].position:[0,0,0],h=this.shouldInvertEaseForSegment(n);return X(s,c,this._numPoints,!!h,this.positionFunctionX,this.positionFunctionY,this.positionFunctionZ).map(r=>new P({xyz:r,invertedLightness:this._invertedLightness}))})}addAnchorPoint({xyz:t,color:o,insertAtIndex:n}){let s=new P({xyz:t,color:o,invertedLightness:this._invertedLightness});return n!==void 0?this.anchorPoints.splice(n,0,s):this.anchorPoints.push(s),this.updateAnchorPairs(),s}removeAnchorPoint({point:t,index:o}){if(!t&&o===void 0)throw new Error("Must provide a point or index");if(this.anchorPoints.length<3)throw new Error("Must have at least two anchor points");let n;if(o!==void 0?n=o:t&&(n=this.anchorPoints.indexOf(t)),n>-1&&n<this.anchorPoints.length)this.anchorPoints.splice(n,1),this.updateAnchorPairs();else throw new Error("Point not found")}updateAnchorPoint({point:t,pointIndex:o,xyz:n,color:s}){if(o!==void 0&&(t=this.anchorPoints[o]),!t)throw new Error("Must provide a point or pointIndex");if(!n&&!s)throw new Error("Must provide a new xyz position or color");return n&&(t.position=n),s&&(t.hsl=s),this.updateAnchorPairs(),t}getClosestAnchorPoint({xyz:t,hsl:o,maxDistance:n=1}){if(!t&&!o)throw new Error("Must provide a xyz or hsl");let s;t?s=this.anchorPoints.map(r=>M(r.position,t)):o&&(s=this.anchorPoints.map(r=>M(r.hsl,o,!0)));let c=Math.min(...s);if(c>n)return null;let h=s.indexOf(c);return this.anchorPoints[h]||null}set closedLoop(t){this.connectLastAndFirstAnchor=t,this.updateAnchorPairs()}get closedLoop(){return this.connectLastAndFirstAnchor}set invertedLightness(t){this._invertedLightness=t,this.updateAnchorPairs()}get invertedLightness(){return this._invertedLightness}get flattenedPoints(){return this.points.flat().filter((t,o)=>o!=0?o%this._numPoints:!0)}get colors(){let t=this.flattenedPoints.map(o=>o.color);return this.connectLastAndFirstAnchor&&this._anchorPoints.length!==2&&t.pop(),t}cssColors(t="hsl"){let o={hsl:s=>s.hslCSS,oklch:s=>s.oklchCSS,lch:s=>s.lchCSS},n=this.flattenedPoints.map(o[t]);return this.connectLastAndFirstAnchor&&n.pop(),n}get colorsCSS(){return this.cssColors("hsl")}get colorsCSSlch(){return this.cssColors("lch")}get colorsCSSoklch(){return this.cssColors("oklch")}shiftHue(t=20){this.anchorPoints.forEach(o=>o.shiftHue(t)),this.updateAnchorPairs()}getColorAt(t){var C;if(t<0||t>1)throw new Error("Position must be between 0 and 1");if(this.anchorPoints.length===0)throw new Error("No anchor points available");let o=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1,n=this.connectLastAndFirstAnchor&&this.anchorPoints.length===2?2:o,s=t*n,c=Math.floor(s),h=s-c,r=c>=n?n-1:c,e=c>=n?1:h,a=this._anchorPairs[r];if(!a||a.length<2||!a[0]||!a[1])return new P({color:((C=this.anchorPoints[0])==null?void 0:C.color)||[0,0,0],invertedLightness:this._invertedLightness});let d=a[0].position,u=a[1].position,F=this.shouldInvertEaseForSegment(r),A=x(e,d,u,F,this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ);return new P({xyz:A,invertedLightness:this._invertedLightness})}shouldInvertEaseForSegment(t){return!!(t%2||this.connectLastAndFirstAnchor&&this.anchorPoints.length===2&&t===0)}},{p5:b}=globalThis;if(b&&b.VERSION&&b.VERSION.startsWith("1.")){console.info("p5 < 1.x detected, adding poline to p5 prototype");let i=new f;b.prototype.poline=i;let t=()=>i.colors.map(o=>`hsl(${Math.round(o[0])},${o[1]*100}%,${o[2]*100}%)`);b.prototype.registerMethod("polineColors",t),globalThis.poline=i,globalThis.polineColors=t}return E(H);})(); | ||
| "use strict";var poline=(()=>{var _=Object.defineProperty;var V=Object.getOwnPropertyDescriptor;var A=Object.getOwnPropertyNames;var w=Object.prototype.hasOwnProperty;var l=Math.pow;var y=(i,t)=>{for(var o in t)_(i,o,{get:t[o],enumerable:!0})},S=(i,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of A(t))!w.call(i,s)&&s!==o&&_(i,s,{get:()=>t[s],enumerable:!(n=V(t,s))||n.enumerable});return i};var E=i=>S(_({},"__esModule",{value:!0}),i);var H={};y(H,{ColorPoint:()=>P,Poline:()=>g,hslToPoint:()=>f,pointToHSL:()=>m,positionFunctions:()=>N,randomHSLPair:()=>v,randomHSLTriple:()=>I});var m=(i,t)=>{let[o,n,s]=i,c=.5,h=.5,r=Math.atan2(n-h,o-c)*(180/Math.PI);r=(360+r)%360;let a=s,u=Math.sqrt(Math.pow(n-h,2)+Math.pow(o-c,2))/c;return[r,a,t?1-u:u]},f=(i,t)=>{let[o,n,s]=i,c=.5,h=.5,e=o/(180/Math.PI),r=(t?1-s:s)*c,a=c+r*Math.cos(e),d=h+r*Math.sin(e);return[a,d,n]},v=(i=Math.random()*360,t=[Math.random(),Math.random()],o=[.75+Math.random()*.2,.3+Math.random()*.2])=>[[i,t[0],o[0]],[(i+60+Math.random()*180)%360,t[1],o[1]]],I=(i=Math.random()*360,t=[Math.random(),Math.random(),Math.random()],o=[.75+Math.random()*.2,Math.random()*.2,.75+Math.random()*.2])=>[[i,t[0],o[0]],[(i+60+Math.random()*180)%360,t[1],o[1]],[(i+60+Math.random()*180)%360,t[2],o[2]]],x=(i,t,o,n=!1,s=(e,r)=>r?1-e:e,c=(e,r)=>r?1-e:e,h=(e,r)=>r?1-e:e)=>{let e=s(i,n),r=c(i,n),a=h(i,n),d=(1-e)*t[0]+e*o[0],u=(1-r)*t[1]+r*o[1],F=(1-a)*t[2]+a*o[2];return[d,u,F]},X=(i,t,o=4,n=!1,s=(e,r)=>r?1-e:e,c=(e,r)=>r?1-e:e,h=(e,r)=>r?1-e:e)=>{let e=[];for(let r=0;r<o;r++){let[a,d,u]=x(r/(o-1),i,t,n,s,c,h);e.push([a,d,u])}return e},z=i=>i,Y=(i,t=!1)=>t?1-l(1-i,2):l(i,2),Z=(i,t=!1)=>t?1-l(1-i,3):l(i,3),$=(i,t=!1)=>t?1-l(1-i,4):l(i,4),O=(i,t=!1)=>t?1-l(1-i,5):l(i,5),p=(i,t=!1)=>t?1-Math.sin((1-i)*Math.PI/2):Math.sin(i*Math.PI/2),k=(i,t=!1)=>t?1-Math.asin(1-i)/(Math.PI/2):Math.asin(i)/(Math.PI/2),T=(i,t=!1)=>t?1-Math.sqrt(1-l(i,2)):1-Math.sqrt(1-i),q=i=>l(i,2)*(3-2*i),N={linearPosition:z,exponentialPosition:Y,quadraticPosition:Z,cubicPosition:$,quarticPosition:O,sinusoidalPosition:p,asinusoidalPosition:k,arcPosition:T,smoothStepPosition:q},M=(i,t,o=!1)=>{let n=i[0],s=t[0],c=0;o&&n!==null&&s!==null?(c=Math.min(Math.abs(n-s),360-Math.abs(n-s)),c=c/360):c=n===null||s===null?0:n-s;let h=c,e=i[1]===null||t[1]===null?0:t[1]-i[1],r=i[2]===null||t[2]===null?0:t[2]-i[2];return Math.sqrt(h*h+e*e+r*r)},P=class{constructor({xyz:t,color:o,invertedLightness:n=!1}={}){this.x=0;this.y=0;this.z=0;this.color=[0,0,0];this._invertedLightness=!1;this._invertedLightness=n,this.positionOrColor({xyz:t,color:o,invertedLightness:n})}positionOrColor({xyz:t,color:o,invertedLightness:n=!1}){if(this._invertedLightness=n,t&&o||!t&&!o)throw new Error("Point must be initialized with either x,y,z or hsl");t?(this.x=t[0],this.y=t[1],this.z=t[2],this.color=m([this.x,this.y,this.z],n)):o&&(this.color=o,[this.x,this.y,this.z]=f(o,n))}set position([t,o,n]){this.x=t,this.y=o,this.z=n,this.color=m([this.x,this.y,this.z],this._invertedLightness)}get position(){return[this.x,this.y,this.z]}set hsl([t,o,n]){this.color=[t,o,n],[this.x,this.y,this.z]=f(this.color,this._invertedLightness)}get hsl(){return this.color}get hslCSS(){let[t,o,n]=this.color;return`hsl(${t.toFixed(2)}, ${(o*100).toFixed(2)}%, ${(n*100).toFixed(2)}%)`}get oklchCSS(){let[t,o,n]=this.color;return`oklch(${(n*100).toFixed(2)}% ${(o*.4).toFixed(3)} ${t.toFixed(2)})`}get lchCSS(){let[t,o,n]=this.color;return`lch(${(n*100).toFixed(2)}% ${(o*150).toFixed(2)} ${t.toFixed(2)})`}set invertedLightness(t){this._invertedLightness=t,this.color=m([this.x,this.y,this.z],this._invertedLightness)}get invertedLightness(){return this._invertedLightness}shiftHue(t){this.color[0]=(360+(this.color[0]+t))%360,[this.x,this.y,this.z]=f(this.color,this._invertedLightness)}},g=class{constructor({anchorColors:t=v(),numPoints:o=4,positionFunction:n=p,positionFunctionX:s,positionFunctionY:c,positionFunctionZ:h,closedLoop:e,invertedLightness:r}={anchorColors:v(),numPoints:4,positionFunction:p,closedLoop:!1}){this._positionFunctionX=p;this._positionFunctionY=p;this._positionFunctionZ=p;this.connectLastAndFirstAnchor=!1;this._animationFrame=null;this._invertedLightness=!1;if(!t||t.length<2)throw new Error("Must have at least two anchor colors");this._anchorPoints=t.map(a=>new P({color:a,invertedLightness:r})),this._numPoints=o+2,this._positionFunctionX=s||n||p,this._positionFunctionY=c||n||p,this._positionFunctionZ=h||n||p,this.connectLastAndFirstAnchor=e||!1,this._invertedLightness=r||!1,this.updateAnchorPairs()}get numPoints(){return this._numPoints-2}set numPoints(t){if(t<1)throw new Error("Must have at least one point");this._numPoints=t+2,this.updateAnchorPairs()}set positionFunction(t){if(Array.isArray(t)){if(t.length!==3)throw new Error("Position function array must have 3 elements");if(typeof t[0]!="function"||typeof t[1]!="function"||typeof t[2]!="function")throw new Error("Position function array must have 3 functions");this._positionFunctionX=t[0],this._positionFunctionY=t[1],this._positionFunctionZ=t[2]}else this._positionFunctionX=t,this._positionFunctionY=t,this._positionFunctionZ=t;this.updateAnchorPairs()}get positionFunction(){return this._positionFunctionX===this._positionFunctionY&&this._positionFunctionX===this._positionFunctionZ?this._positionFunctionX:[this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ]}set positionFunctionX(t){this._positionFunctionX=t,this.updateAnchorPairs()}get positionFunctionX(){return this._positionFunctionX}set positionFunctionY(t){this._positionFunctionY=t,this.updateAnchorPairs()}get positionFunctionY(){return this._positionFunctionY}set positionFunctionZ(t){this._positionFunctionZ=t,this.updateAnchorPairs()}get positionFunctionZ(){return this._positionFunctionZ}get anchorPoints(){return this._anchorPoints}set anchorPoints(t){this._anchorPoints=t,this.updateAnchorPairs()}updateAnchorPairs(){this._anchorPairs=[];let t=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1;for(let o=0;o<t;o++){let n=[this.anchorPoints[o],this.anchorPoints[(o+1)%this.anchorPoints.length]];this._anchorPairs.push(n)}this.points=this._anchorPairs.map((o,n)=>{let s=o[0]?o[0].position:[0,0,0],c=o[1]?o[1].position:[0,0,0],h=this.shouldInvertEaseForSegment(n);return X(s,c,this._numPoints,!!h,this.positionFunctionX,this.positionFunctionY,this.positionFunctionZ).map(e=>new P({xyz:e,invertedLightness:this._invertedLightness}))})}addAnchorPoint({xyz:t,color:o,insertAtIndex:n}){let s=new P({xyz:t,color:o,invertedLightness:this._invertedLightness});return n!==void 0?this.anchorPoints.splice(n,0,s):this.anchorPoints.push(s),this.updateAnchorPairs(),s}removeAnchorPoint({point:t,index:o}){if(!t&&o===void 0)throw new Error("Must provide a point or index");if(this.anchorPoints.length<3)throw new Error("Must have at least two anchor points");let n;if(o!==void 0?n=o:t&&(n=this.anchorPoints.indexOf(t)),n>-1&&n<this.anchorPoints.length)this.anchorPoints.splice(n,1),this.updateAnchorPairs();else throw new Error("Point not found")}updateAnchorPoint({point:t,pointIndex:o,xyz:n,color:s}){if(o!==void 0&&(t=this.anchorPoints[o]),!t)throw new Error("Must provide a point or pointIndex");if(!n&&!s)throw new Error("Must provide a new xyz position or color");return n&&(t.position=n),s&&(t.hsl=s),this.updateAnchorPairs(),t}getClosestAnchorPoint({xyz:t,hsl:o,maxDistance:n=1}){if(!t&&!o)throw new Error("Must provide a xyz or hsl");let s;t?s=this.anchorPoints.map(e=>M(e.position,t)):o&&(s=this.anchorPoints.map(e=>M(e.hsl,o,!0)));let c=Math.min(...s);if(c>n)return null;let h=s.indexOf(c);return this.anchorPoints[h]||null}set closedLoop(t){this.connectLastAndFirstAnchor=t,this.updateAnchorPairs()}get closedLoop(){return this.connectLastAndFirstAnchor}set invertedLightness(t){this._invertedLightness=t,this.anchorPoints.forEach(o=>o.invertedLightness=t),this.updateAnchorPairs()}get invertedLightness(){return this._invertedLightness}get flattenedPoints(){return this.points.flat().filter((t,o)=>o!=0?o%this._numPoints:!0)}get colors(){let t=this.flattenedPoints.map(o=>o.color);return this.connectLastAndFirstAnchor&&this._anchorPoints.length!==2&&t.pop(),t}cssColors(t="hsl"){let o={hsl:s=>s.hslCSS,oklch:s=>s.oklchCSS,lch:s=>s.lchCSS},n=this.flattenedPoints.map(o[t]);return this.connectLastAndFirstAnchor&&n.pop(),n}get colorsCSS(){return this.cssColors("hsl")}get colorsCSSlch(){return this.cssColors("lch")}get colorsCSSoklch(){return this.cssColors("oklch")}shiftHue(t=20){this.anchorPoints.forEach(o=>o.shiftHue(t)),this.updateAnchorPairs()}getColorAt(t){var C;if(t<0||t>1)throw new Error("Position must be between 0 and 1");if(this.anchorPoints.length===0)throw new Error("No anchor points available");let o=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1,n=this.connectLastAndFirstAnchor&&this.anchorPoints.length===2?2:o,s=t*n,c=Math.floor(s),h=s-c,e=c>=n?n-1:c,r=c>=n?1:h,a=this._anchorPairs[e];if(!a||a.length<2||!a[0]||!a[1])return new P({color:((C=this.anchorPoints[0])==null?void 0:C.color)||[0,0,0],invertedLightness:this._invertedLightness});let d=a[0].position,u=a[1].position,F=this.shouldInvertEaseForSegment(e),L=x(r,d,u,F,this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ);return new P({xyz:L,invertedLightness:this._invertedLightness})}shouldInvertEaseForSegment(t){return!!(t%2||this.connectLastAndFirstAnchor&&this.anchorPoints.length===2&&t===0)}},{p5:b}=globalThis;if(b&&b.VERSION&&b.VERSION.startsWith("1.")){console.info("p5 < 1.x detected, adding poline to p5 prototype");let i=new g;b.prototype.poline=i;let t=()=>i.colors.map(o=>`hsl(${Math.round(o[0])},${o[1]*100}%,${o[2]*100}%)`);b.prototype.registerMethod("polineColors",t),globalThis.poline=i,globalThis.polineColors=t}return E(H);})(); |
@@ -1,1 +0,1 @@ | ||
| var F=(i,t)=>{let[o,n,r]=i,c=.5,h=.5,e=Math.atan2(n-h,o-c)*(180/Math.PI);e=(360+e)%360;let a=r,l=Math.sqrt(Math.pow(n-h,2)+Math.pow(o-c,2))/c;return[e,a,t?1-l:l]},m=(i,t)=>{let[o,n,r]=i,c=.5,h=.5,s=o/(180/Math.PI),e=(t?1-r:r)*c,a=c+e*Math.cos(s),p=h+e*Math.sin(s);return[a,p,n]},g=(i=Math.random()*360,t=[Math.random(),Math.random()],o=[.75+Math.random()*.2,.3+Math.random()*.2])=>[[i,t[0],o[0]],[(i+60+Math.random()*180)%360,t[1],o[1]]],I=(i=Math.random()*360,t=[Math.random(),Math.random(),Math.random()],o=[.75+Math.random()*.2,Math.random()*.2,.75+Math.random()*.2])=>[[i,t[0],o[0]],[(i+60+Math.random()*180)%360,t[1],o[1]],[(i+60+Math.random()*180)%360,t[2],o[2]]],v=(i,t,o,n=!1,r=(s,e)=>e?1-s:s,c=(s,e)=>e?1-s:s,h=(s,e)=>e?1-s:s)=>{let s=r(i,n),e=c(i,n),a=h(i,n),p=(1-s)*t[0]+s*o[0],l=(1-e)*t[1]+e*o[1],b=(1-a)*t[2]+a*o[2];return[p,l,b]},M=(i,t,o=4,n=!1,r=(s,e)=>e?1-s:s,c=(s,e)=>e?1-s:s,h=(s,e)=>e?1-s:s)=>{let s=[];for(let e=0;e<o;e++){let[a,p,l]=v(e/(o-1),i,t,n,r,c,h);s.push([a,p,l])}return s},x=i=>i,A=(i,t=!1)=>t?1-(1-i)**2:i**2,V=(i,t=!1)=>t?1-(1-i)**3:i**3,w=(i,t=!1)=>t?1-(1-i)**4:i**4,L=(i,t=!1)=>t?1-(1-i)**5:i**5,u=(i,t=!1)=>t?1-Math.sin((1-i)*Math.PI/2):Math.sin(i*Math.PI/2),S=(i,t=!1)=>t?1-Math.asin(1-i)/(Math.PI/2):Math.asin(i)/(Math.PI/2),y=(i,t=!1)=>t?1-Math.sqrt(1-i**2):1-Math.sqrt(1-i),E=i=>i**2*(3-2*i),X={linearPosition:x,exponentialPosition:A,quadraticPosition:V,cubicPosition:w,quarticPosition:L,sinusoidalPosition:u,asinusoidalPosition:S,arcPosition:y,smoothStepPosition:E},_=(i,t,o=!1)=>{let n=i[0],r=t[0],c=0;o&&n!==null&&r!==null?(c=Math.min(Math.abs(n-r),360-Math.abs(n-r)),c=c/360):c=n===null||r===null?0:n-r;let h=c,s=i[1]===null||t[1]===null?0:t[1]-i[1],e=i[2]===null||t[2]===null?0:t[2]-i[2];return Math.sqrt(h*h+s*s+e*e)},d=class{constructor({xyz:t,color:o,invertedLightness:n=!1}={}){this.x=0;this.y=0;this.z=0;this.color=[0,0,0];this._invertedLightness=!1;this._invertedLightness=n,this.positionOrColor({xyz:t,color:o,invertedLightness:n})}positionOrColor({xyz:t,color:o,invertedLightness:n=!1}){if(this._invertedLightness=n,t&&o||!t&&!o)throw new Error("Point must be initialized with either x,y,z or hsl");t?(this.x=t[0],this.y=t[1],this.z=t[2],this.color=F([this.x,this.y,this.z],n)):o&&(this.color=o,[this.x,this.y,this.z]=m(o,n))}set position([t,o,n]){this.x=t,this.y=o,this.z=n,this.color=F([this.x,this.y,this.z],this._invertedLightness)}get position(){return[this.x,this.y,this.z]}set hsl([t,o,n]){this.color=[t,o,n],[this.x,this.y,this.z]=m(this.color,this._invertedLightness)}get hsl(){return this.color}get hslCSS(){let[t,o,n]=this.color;return`hsl(${t.toFixed(2)}, ${(o*100).toFixed(2)}%, ${(n*100).toFixed(2)}%)`}get oklchCSS(){let[t,o,n]=this.color;return`oklch(${(n*100).toFixed(2)}% ${(o*.4).toFixed(3)} ${t.toFixed(2)})`}get lchCSS(){let[t,o,n]=this.color;return`lch(${(n*100).toFixed(2)}% ${(o*150).toFixed(2)} ${t.toFixed(2)})`}shiftHue(t){this.color[0]=(360+(this.color[0]+t))%360,[this.x,this.y,this.z]=m(this.color,this._invertedLightness)}},f=class{constructor({anchorColors:t=g(),numPoints:o=4,positionFunction:n=u,positionFunctionX:r,positionFunctionY:c,positionFunctionZ:h,closedLoop:s,invertedLightness:e}={anchorColors:g(),numPoints:4,positionFunction:u,closedLoop:!1}){this._needsUpdate=!0;this._positionFunctionX=u;this._positionFunctionY=u;this._positionFunctionZ=u;this.connectLastAndFirstAnchor=!1;this._animationFrame=null;this._invertedLightness=!1;if(!t||t.length<2)throw new Error("Must have at least two anchor colors");this._anchorPoints=t.map(a=>new d({color:a,invertedLightness:e})),this._numPoints=o+2,this._positionFunctionX=r||n||u,this._positionFunctionY=c||n||u,this._positionFunctionZ=h||n||u,this.connectLastAndFirstAnchor=s||!1,this._invertedLightness=e||!1,this.updateAnchorPairs()}get numPoints(){return this._numPoints-2}set numPoints(t){if(t<1)throw new Error("Must have at least one point");this._numPoints=t+2,this.updateAnchorPairs()}set positionFunction(t){if(Array.isArray(t)){if(t.length!==3)throw new Error("Position function array must have 3 elements");if(typeof t[0]!="function"||typeof t[1]!="function"||typeof t[2]!="function")throw new Error("Position function array must have 3 functions");this._positionFunctionX=t[0],this._positionFunctionY=t[1],this._positionFunctionZ=t[2]}else this._positionFunctionX=t,this._positionFunctionY=t,this._positionFunctionZ=t;this.updateAnchorPairs()}get positionFunction(){return this._positionFunctionX===this._positionFunctionY&&this._positionFunctionX===this._positionFunctionZ?this._positionFunctionX:[this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ]}set positionFunctionX(t){this._positionFunctionX=t,this.updateAnchorPairs()}get positionFunctionX(){return this._positionFunctionX}set positionFunctionY(t){this._positionFunctionY=t,this.updateAnchorPairs()}get positionFunctionY(){return this._positionFunctionY}set positionFunctionZ(t){this._positionFunctionZ=t,this.updateAnchorPairs()}get positionFunctionZ(){return this._positionFunctionZ}get anchorPoints(){return this._anchorPoints}set anchorPoints(t){this._anchorPoints=t,this.updateAnchorPairs()}updateAnchorPairs(){this._anchorPairs=[];let t=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1;for(let o=0;o<t;o++){let n=[this.anchorPoints[o],this.anchorPoints[(o+1)%this.anchorPoints.length]];this._anchorPairs.push(n)}this.points=this._anchorPairs.map((o,n)=>{let r=o[0]?o[0].position:[0,0,0],c=o[1]?o[1].position:[0,0,0],h=this.shouldInvertEaseForSegment(n);return M(r,c,this._numPoints,!!h,this.positionFunctionX,this.positionFunctionY,this.positionFunctionZ).map(s=>new d({xyz:s,invertedLightness:this._invertedLightness}))})}addAnchorPoint({xyz:t,color:o,insertAtIndex:n}){let r=new d({xyz:t,color:o,invertedLightness:this._invertedLightness});return n!==void 0?this.anchorPoints.splice(n,0,r):this.anchorPoints.push(r),this.updateAnchorPairs(),r}removeAnchorPoint({point:t,index:o}){if(!t&&o===void 0)throw new Error("Must provide a point or index");if(this.anchorPoints.length<3)throw new Error("Must have at least two anchor points");let n;if(o!==void 0?n=o:t&&(n=this.anchorPoints.indexOf(t)),n>-1&&n<this.anchorPoints.length)this.anchorPoints.splice(n,1),this.updateAnchorPairs();else throw new Error("Point not found")}updateAnchorPoint({point:t,pointIndex:o,xyz:n,color:r}){if(o!==void 0&&(t=this.anchorPoints[o]),!t)throw new Error("Must provide a point or pointIndex");if(!n&&!r)throw new Error("Must provide a new xyz position or color");return n&&(t.position=n),r&&(t.hsl=r),this.updateAnchorPairs(),t}getClosestAnchorPoint({xyz:t,hsl:o,maxDistance:n=1}){if(!t&&!o)throw new Error("Must provide a xyz or hsl");let r;t?r=this.anchorPoints.map(s=>_(s.position,t)):o&&(r=this.anchorPoints.map(s=>_(s.hsl,o,!0)));let c=Math.min(...r);if(c>n)return null;let h=r.indexOf(c);return this.anchorPoints[h]||null}set closedLoop(t){this.connectLastAndFirstAnchor=t,this.updateAnchorPairs()}get closedLoop(){return this.connectLastAndFirstAnchor}set invertedLightness(t){this._invertedLightness=t,this.updateAnchorPairs()}get invertedLightness(){return this._invertedLightness}get flattenedPoints(){return this.points.flat().filter((t,o)=>o!=0?o%this._numPoints:!0)}get colors(){let t=this.flattenedPoints.map(o=>o.color);return this.connectLastAndFirstAnchor&&this._anchorPoints.length!==2&&t.pop(),t}cssColors(t="hsl"){let o={hsl:r=>r.hslCSS,oklch:r=>r.oklchCSS,lch:r=>r.lchCSS},n=this.flattenedPoints.map(o[t]);return this.connectLastAndFirstAnchor&&n.pop(),n}get colorsCSS(){return this.cssColors("hsl")}get colorsCSSlch(){return this.cssColors("lch")}get colorsCSSoklch(){return this.cssColors("oklch")}shiftHue(t=20){this.anchorPoints.forEach(o=>o.shiftHue(t)),this.updateAnchorPairs()}getColorAt(t){if(t<0||t>1)throw new Error("Position must be between 0 and 1");if(this.anchorPoints.length===0)throw new Error("No anchor points available");let o=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1,n=this.connectLastAndFirstAnchor&&this.anchorPoints.length===2?2:o,r=t*n,c=Math.floor(r),h=r-c,s=c>=n?n-1:c,e=c>=n?1:h,a=this._anchorPairs[s];if(!a||a.length<2||!a[0]||!a[1])return new d({color:this.anchorPoints[0]?.color||[0,0,0],invertedLightness:this._invertedLightness});let p=a[0].position,l=a[1].position,b=this.shouldInvertEaseForSegment(s),C=v(e,p,l,b,this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ);return new d({xyz:C,invertedLightness:this._invertedLightness})}shouldInvertEaseForSegment(t){return!!(t%2||this.connectLastAndFirstAnchor&&this.anchorPoints.length===2&&t===0)}},{p5:P}=globalThis;if(P&&P.VERSION&&P.VERSION.startsWith("1.")){console.info("p5 < 1.x detected, adding poline to p5 prototype");let i=new f;P.prototype.poline=i;let t=()=>i.colors.map(o=>`hsl(${Math.round(o[0])},${o[1]*100}%,${o[2]*100}%)`);P.prototype.registerMethod("polineColors",t),globalThis.poline=i,globalThis.polineColors=t}export{d as ColorPoint,f as Poline,m as hslToPoint,F as pointToHSL,X as positionFunctions,g as randomHSLPair,I as randomHSLTriple}; | ||
| var m=(i,t)=>{let[o,n,e]=i,c=.5,h=.5,r=Math.atan2(n-h,o-c)*(180/Math.PI);r=(360+r)%360;let a=e,l=Math.sqrt(Math.pow(n-h,2)+Math.pow(o-c,2))/c;return[r,a,t?1-l:l]},f=(i,t)=>{let[o,n,e]=i,c=.5,h=.5,s=o/(180/Math.PI),r=(t?1-e:e)*c,a=c+r*Math.cos(s),p=h+r*Math.sin(s);return[a,p,n]},F=(i=Math.random()*360,t=[Math.random(),Math.random()],o=[.75+Math.random()*.2,.3+Math.random()*.2])=>[[i,t[0],o[0]],[(i+60+Math.random()*180)%360,t[1],o[1]]],I=(i=Math.random()*360,t=[Math.random(),Math.random(),Math.random()],o=[.75+Math.random()*.2,Math.random()*.2,.75+Math.random()*.2])=>[[i,t[0],o[0]],[(i+60+Math.random()*180)%360,t[1],o[1]],[(i+60+Math.random()*180)%360,t[2],o[2]]],v=(i,t,o,n=!1,e=(s,r)=>r?1-s:s,c=(s,r)=>r?1-s:s,h=(s,r)=>r?1-s:s)=>{let s=e(i,n),r=c(i,n),a=h(i,n),p=(1-s)*t[0]+s*o[0],l=(1-r)*t[1]+r*o[1],b=(1-a)*t[2]+a*o[2];return[p,l,b]},M=(i,t,o=4,n=!1,e=(s,r)=>r?1-s:s,c=(s,r)=>r?1-s:s,h=(s,r)=>r?1-s:s)=>{let s=[];for(let r=0;r<o;r++){let[a,p,l]=v(r/(o-1),i,t,n,e,c,h);s.push([a,p,l])}return s},x=i=>i,L=(i,t=!1)=>t?1-(1-i)**2:i**2,V=(i,t=!1)=>t?1-(1-i)**3:i**3,A=(i,t=!1)=>t?1-(1-i)**4:i**4,w=(i,t=!1)=>t?1-(1-i)**5:i**5,u=(i,t=!1)=>t?1-Math.sin((1-i)*Math.PI/2):Math.sin(i*Math.PI/2),y=(i,t=!1)=>t?1-Math.asin(1-i)/(Math.PI/2):Math.asin(i)/(Math.PI/2),S=(i,t=!1)=>t?1-Math.sqrt(1-i**2):1-Math.sqrt(1-i),E=i=>i**2*(3-2*i),X={linearPosition:x,exponentialPosition:L,quadraticPosition:V,cubicPosition:A,quarticPosition:w,sinusoidalPosition:u,asinusoidalPosition:y,arcPosition:S,smoothStepPosition:E},_=(i,t,o=!1)=>{let n=i[0],e=t[0],c=0;o&&n!==null&&e!==null?(c=Math.min(Math.abs(n-e),360-Math.abs(n-e)),c=c/360):c=n===null||e===null?0:n-e;let h=c,s=i[1]===null||t[1]===null?0:t[1]-i[1],r=i[2]===null||t[2]===null?0:t[2]-i[2];return Math.sqrt(h*h+s*s+r*r)},d=class{constructor({xyz:t,color:o,invertedLightness:n=!1}={}){this.x=0;this.y=0;this.z=0;this.color=[0,0,0];this._invertedLightness=!1;this._invertedLightness=n,this.positionOrColor({xyz:t,color:o,invertedLightness:n})}positionOrColor({xyz:t,color:o,invertedLightness:n=!1}){if(this._invertedLightness=n,t&&o||!t&&!o)throw new Error("Point must be initialized with either x,y,z or hsl");t?(this.x=t[0],this.y=t[1],this.z=t[2],this.color=m([this.x,this.y,this.z],n)):o&&(this.color=o,[this.x,this.y,this.z]=f(o,n))}set position([t,o,n]){this.x=t,this.y=o,this.z=n,this.color=m([this.x,this.y,this.z],this._invertedLightness)}get position(){return[this.x,this.y,this.z]}set hsl([t,o,n]){this.color=[t,o,n],[this.x,this.y,this.z]=f(this.color,this._invertedLightness)}get hsl(){return this.color}get hslCSS(){let[t,o,n]=this.color;return`hsl(${t.toFixed(2)}, ${(o*100).toFixed(2)}%, ${(n*100).toFixed(2)}%)`}get oklchCSS(){let[t,o,n]=this.color;return`oklch(${(n*100).toFixed(2)}% ${(o*.4).toFixed(3)} ${t.toFixed(2)})`}get lchCSS(){let[t,o,n]=this.color;return`lch(${(n*100).toFixed(2)}% ${(o*150).toFixed(2)} ${t.toFixed(2)})`}set invertedLightness(t){this._invertedLightness=t,this.color=m([this.x,this.y,this.z],this._invertedLightness)}get invertedLightness(){return this._invertedLightness}shiftHue(t){this.color[0]=(360+(this.color[0]+t))%360,[this.x,this.y,this.z]=f(this.color,this._invertedLightness)}},g=class{constructor({anchorColors:t=F(),numPoints:o=4,positionFunction:n=u,positionFunctionX:e,positionFunctionY:c,positionFunctionZ:h,closedLoop:s,invertedLightness:r}={anchorColors:F(),numPoints:4,positionFunction:u,closedLoop:!1}){this._positionFunctionX=u;this._positionFunctionY=u;this._positionFunctionZ=u;this.connectLastAndFirstAnchor=!1;this._animationFrame=null;this._invertedLightness=!1;if(!t||t.length<2)throw new Error("Must have at least two anchor colors");this._anchorPoints=t.map(a=>new d({color:a,invertedLightness:r})),this._numPoints=o+2,this._positionFunctionX=e||n||u,this._positionFunctionY=c||n||u,this._positionFunctionZ=h||n||u,this.connectLastAndFirstAnchor=s||!1,this._invertedLightness=r||!1,this.updateAnchorPairs()}get numPoints(){return this._numPoints-2}set numPoints(t){if(t<1)throw new Error("Must have at least one point");this._numPoints=t+2,this.updateAnchorPairs()}set positionFunction(t){if(Array.isArray(t)){if(t.length!==3)throw new Error("Position function array must have 3 elements");if(typeof t[0]!="function"||typeof t[1]!="function"||typeof t[2]!="function")throw new Error("Position function array must have 3 functions");this._positionFunctionX=t[0],this._positionFunctionY=t[1],this._positionFunctionZ=t[2]}else this._positionFunctionX=t,this._positionFunctionY=t,this._positionFunctionZ=t;this.updateAnchorPairs()}get positionFunction(){return this._positionFunctionX===this._positionFunctionY&&this._positionFunctionX===this._positionFunctionZ?this._positionFunctionX:[this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ]}set positionFunctionX(t){this._positionFunctionX=t,this.updateAnchorPairs()}get positionFunctionX(){return this._positionFunctionX}set positionFunctionY(t){this._positionFunctionY=t,this.updateAnchorPairs()}get positionFunctionY(){return this._positionFunctionY}set positionFunctionZ(t){this._positionFunctionZ=t,this.updateAnchorPairs()}get positionFunctionZ(){return this._positionFunctionZ}get anchorPoints(){return this._anchorPoints}set anchorPoints(t){this._anchorPoints=t,this.updateAnchorPairs()}updateAnchorPairs(){this._anchorPairs=[];let t=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1;for(let o=0;o<t;o++){let n=[this.anchorPoints[o],this.anchorPoints[(o+1)%this.anchorPoints.length]];this._anchorPairs.push(n)}this.points=this._anchorPairs.map((o,n)=>{let e=o[0]?o[0].position:[0,0,0],c=o[1]?o[1].position:[0,0,0],h=this.shouldInvertEaseForSegment(n);return M(e,c,this._numPoints,!!h,this.positionFunctionX,this.positionFunctionY,this.positionFunctionZ).map(s=>new d({xyz:s,invertedLightness:this._invertedLightness}))})}addAnchorPoint({xyz:t,color:o,insertAtIndex:n}){let e=new d({xyz:t,color:o,invertedLightness:this._invertedLightness});return n!==void 0?this.anchorPoints.splice(n,0,e):this.anchorPoints.push(e),this.updateAnchorPairs(),e}removeAnchorPoint({point:t,index:o}){if(!t&&o===void 0)throw new Error("Must provide a point or index");if(this.anchorPoints.length<3)throw new Error("Must have at least two anchor points");let n;if(o!==void 0?n=o:t&&(n=this.anchorPoints.indexOf(t)),n>-1&&n<this.anchorPoints.length)this.anchorPoints.splice(n,1),this.updateAnchorPairs();else throw new Error("Point not found")}updateAnchorPoint({point:t,pointIndex:o,xyz:n,color:e}){if(o!==void 0&&(t=this.anchorPoints[o]),!t)throw new Error("Must provide a point or pointIndex");if(!n&&!e)throw new Error("Must provide a new xyz position or color");return n&&(t.position=n),e&&(t.hsl=e),this.updateAnchorPairs(),t}getClosestAnchorPoint({xyz:t,hsl:o,maxDistance:n=1}){if(!t&&!o)throw new Error("Must provide a xyz or hsl");let e;t?e=this.anchorPoints.map(s=>_(s.position,t)):o&&(e=this.anchorPoints.map(s=>_(s.hsl,o,!0)));let c=Math.min(...e);if(c>n)return null;let h=e.indexOf(c);return this.anchorPoints[h]||null}set closedLoop(t){this.connectLastAndFirstAnchor=t,this.updateAnchorPairs()}get closedLoop(){return this.connectLastAndFirstAnchor}set invertedLightness(t){this._invertedLightness=t,this.anchorPoints.forEach(o=>o.invertedLightness=t),this.updateAnchorPairs()}get invertedLightness(){return this._invertedLightness}get flattenedPoints(){return this.points.flat().filter((t,o)=>o!=0?o%this._numPoints:!0)}get colors(){let t=this.flattenedPoints.map(o=>o.color);return this.connectLastAndFirstAnchor&&this._anchorPoints.length!==2&&t.pop(),t}cssColors(t="hsl"){let o={hsl:e=>e.hslCSS,oklch:e=>e.oklchCSS,lch:e=>e.lchCSS},n=this.flattenedPoints.map(o[t]);return this.connectLastAndFirstAnchor&&n.pop(),n}get colorsCSS(){return this.cssColors("hsl")}get colorsCSSlch(){return this.cssColors("lch")}get colorsCSSoklch(){return this.cssColors("oklch")}shiftHue(t=20){this.anchorPoints.forEach(o=>o.shiftHue(t)),this.updateAnchorPairs()}getColorAt(t){if(t<0||t>1)throw new Error("Position must be between 0 and 1");if(this.anchorPoints.length===0)throw new Error("No anchor points available");let o=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1,n=this.connectLastAndFirstAnchor&&this.anchorPoints.length===2?2:o,e=t*n,c=Math.floor(e),h=e-c,s=c>=n?n-1:c,r=c>=n?1:h,a=this._anchorPairs[s];if(!a||a.length<2||!a[0]||!a[1])return new d({color:this.anchorPoints[0]?.color||[0,0,0],invertedLightness:this._invertedLightness});let p=a[0].position,l=a[1].position,b=this.shouldInvertEaseForSegment(s),C=v(r,p,l,b,this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ);return new d({xyz:C,invertedLightness:this._invertedLightness})}shouldInvertEaseForSegment(t){return!!(t%2||this.connectLastAndFirstAnchor&&this.anchorPoints.length===2&&t===0)}},{p5:P}=globalThis;if(P&&P.VERSION&&P.VERSION.startsWith("1.")){console.info("p5 < 1.x detected, adding poline to p5 prototype");let i=new g;P.prototype.poline=i;let t=()=>i.colors.map(o=>`hsl(${Math.round(o[0])},${o[1]*100}%,${o[2]*100}%)`);P.prototype.registerMethod("polineColors",t),globalThis.poline=i,globalThis.polineColors=t}export{d as ColorPoint,g as Poline,f as hslToPoint,m as pointToHSL,X as positionFunctions,F as randomHSLPair,I as randomHSLTriple}; |
+11
-1
@@ -211,2 +211,12 @@ var __pow = Math.pow; | ||
| } | ||
| set invertedLightness(val) { | ||
| this._invertedLightness = val; | ||
| this.color = pointToHSL( | ||
| [this.x, this.y, this.z], | ||
| this._invertedLightness | ||
| ); | ||
| } | ||
| get invertedLightness() { | ||
| return this._invertedLightness; | ||
| } | ||
| shiftHue(angle) { | ||
@@ -236,3 +246,2 @@ this.color[0] = (360 + (this.color[0] + angle)) % 360; | ||
| }) { | ||
| this._needsUpdate = true; | ||
| this._positionFunctionX = sinusoidalPosition; | ||
@@ -448,2 +457,3 @@ this._positionFunctionY = sinusoidalPosition; | ||
| this._invertedLightness = newStatus; | ||
| this.anchorPoints.forEach((p) => p.invertedLightness = newStatus); | ||
| this.updateAnchorPairs(); | ||
@@ -450,0 +460,0 @@ } |
| { | ||
| "version": 3, | ||
| "sources": ["../src/index.ts"], | ||
| "sourcesContent": ["/* eslint-disable @typescript-eslint/ban-ts-comment */\nexport type FuncNumberReturn = (arg0: number) => Vector2;\nexport type Vector2 = [number, number];\nexport type Vector3 = [number, ...Vector2];\nexport type PartialVector3 = [number | null, number | null, number | null];\n\ntype CSSColorMethods = {\n hsl: (p: ColorPoint) => string;\n oklch: (p: ColorPoint) => string;\n lch: (p: ColorPoint) => string;\n};\n\n/**\n * Converts the given (x, y, z) coordinate to an HSL color\n * The (x, y) values are used to calculate the hue, while the z value is used as the saturation\n * The lightness value is calculated based on the distance of (x, y) from the center (0.5, 0.5)\n * Returns an array [hue, saturation, lightness]\n * @param xyz:Vector3 [x, y, z] coordinate array in (x, y, z) format (0-1, 0-1, 0-1)\n * @returns [hue, saturation, lightness]: Vector3 color array in HSL format (0-360, 0-1, 0-1)\n * @example\n * pointToHSL([0.5, 0.5, 1]) // [0, 1, 0.5]\n * pointToHSL([0.5, 0.5, 0]) // [0, 1, 0]\n **/\n\nexport const pointToHSL = (\n xyz: Vector3,\n invertedLightness: boolean\n): Vector3 => {\n const [x, y, z] = xyz;\n\n // cy and cx are the center (y and x) values\n const cx = 0.5;\n const cy = 0.5;\n\n // Calculate the angle between the point (x, y) and the center (cx, cy)\n const radians = Math.atan2(y - cy, x - cx);\n\n // Convert the angle to degrees and shift it so that it goes from 0 to 360\n let deg = radians * (180 / Math.PI);\n deg = (360 + deg) % 360;\n\n // The saturation value is taken from the z coordinate\n const s = z;\n\n // Calculate the lightness value based on the distance from the center\n const dist = Math.sqrt(Math.pow(y - cy, 2) + Math.pow(x - cx, 2));\n const l = dist / cx;\n\n // Return the HSL color as an array [hue, saturation, lightness]\n return [deg, s, invertedLightness ? 1 - l : l];\n};\n\n/**\n * Converts the given HSL color to an (x, y, z) coordinate\n * The hue value is used to calculate the (x, y) position, while the saturation value is used as the z coordinate\n * The lightness value is used to calculate the distance from the center (0.5, 0.5)\n * Returns an array [x, y, z]\n * @param hsl:Vector3 [hue, saturation, lightness] color array in HSL format (0-360, 0-1, 0-1)\n * @returns [x, y, z]:Vector3 coordinate array in (x, y, z) format (0-1, 0-1, 0-1)\n * @example\n * hslToPoint([0, 1, 0.5]) // [0.5, 0.5, 1]\n * hslToPoint([0, 1, 0]) // [0.5, 0.5, 1]\n * hslToPoint([0, 1, 1]) // [0.5, 0.5, 1]\n * hslToPoint([0, 0, 0.5]) // [0.5, 0.5, 0]\n **/\nexport const hslToPoint = (\n hsl: Vector3,\n invertedLightness: boolean\n): Vector3 => {\n // Destructure the input array into separate hue, saturation, and lightness values\n const [h, s, l] = hsl;\n // cx and cy are the center (x and y) values\n const cx = 0.5;\n const cy = 0.5;\n // Calculate the angle in radians based on the hue value\n const radians = h / (180 / Math.PI);\n\n // Calculate the distance from the center based on the lightness value\n const dist = (invertedLightness ? 1 - l : l) * cx;\n\n // Calculate the x and y coordinates based on the distance and angle\n const x = cx + dist * Math.cos(radians);\n const y = cy + dist * Math.sin(radians);\n // The z coordinate is equal to the saturation value\n const z = s;\n // Return the (x, y, z) coordinate as an array [x, y, z]\n return [x, y, z];\n};\n\nexport const randomHSLPair = (\n startHue: number = Math.random() * 360,\n saturations: Vector2 = [Math.random(), Math.random()],\n lightnesses: Vector2 = [0.75 + Math.random() * 0.2, 0.3 + Math.random() * 0.2]\n): [Vector3, Vector3] => [\n [startHue, saturations[0], lightnesses[0]],\n [(startHue + 60 + Math.random() * 180) % 360, saturations[1], lightnesses[1]],\n];\n\nexport const randomHSLTriple = (\n startHue: number = Math.random() * 360,\n saturations: Vector3 = [Math.random(), Math.random(), Math.random()],\n lightnesses: Vector3 = [\n 0.75 + Math.random() * 0.2,\n Math.random() * 0.2,\n 0.75 + Math.random() * 0.2,\n ]\n): [Vector3, Vector3, Vector3] => [\n [startHue, saturations[0], lightnesses[0]],\n [(startHue + 60 + Math.random() * 180) % 360, saturations[1], lightnesses[1]],\n [(startHue + 60 + Math.random() * 180) % 360, saturations[2], lightnesses[2]],\n];\n\nconst vectorOnLine = (\n t: number,\n p1: Vector3,\n p2: Vector3,\n invert = false,\n fx = (t: number, invert: boolean): number => (invert ? 1 - t : t),\n fy = (t: number, invert: boolean): number => (invert ? 1 - t : t),\n fz = (t: number, invert: boolean): number => (invert ? 1 - t : t)\n): Vector3 => {\n const tModifiedX = fx(t, invert);\n const tModifiedY = fy(t, invert);\n const tModifiedZ = fz(t, invert);\n const x = (1 - tModifiedX) * p1[0] + tModifiedX * p2[0];\n const y = (1 - tModifiedY) * p1[1] + tModifiedY * p2[1];\n const z = (1 - tModifiedZ) * p1[2] + tModifiedZ * p2[2];\n\n return [x, y, z];\n};\n\nconst vectorsOnLine = (\n p1: Vector3,\n p2: Vector3,\n numPoints = 4,\n invert = false,\n fx = (t: number, invert: boolean): number => (invert ? 1 - t : t),\n fy = (t: number, invert: boolean): number => (invert ? 1 - t : t),\n fz = (t: number, invert: boolean): number => (invert ? 1 - t : t)\n): Vector3[] => {\n const points: Vector3[] = [];\n\n for (let i = 0; i < numPoints; i++) {\n const [x, y, z] = vectorOnLine(\n i / (numPoints - 1),\n p1,\n p2,\n invert,\n fx,\n fy,\n fz\n );\n points.push([x, y, z]);\n }\n\n return points;\n};\n\nexport type PositionFunction = (t: number, reverse?: boolean) => number;\n\nconst linearPosition: PositionFunction = (t: number) => {\n return t;\n};\n\nconst exponentialPosition: PositionFunction = (t: number, reverse = false) => {\n if (reverse) {\n return 1 - (1 - t) ** 2;\n }\n return t ** 2;\n};\n\nconst quadraticPosition: PositionFunction = (t: number, reverse = false) => {\n if (reverse) {\n return 1 - (1 - t) ** 3;\n }\n return t ** 3;\n};\n\nconst cubicPosition: PositionFunction = (t: number, reverse = false) => {\n if (reverse) {\n return 1 - (1 - t) ** 4;\n }\n return t ** 4;\n};\n\nconst quarticPosition: PositionFunction = (t: number, reverse = false) => {\n if (reverse) {\n return 1 - (1 - t) ** 5;\n }\n return t ** 5;\n};\n\nconst sinusoidalPosition: PositionFunction = (t: number, reverse = false) => {\n if (reverse) {\n return 1 - Math.sin(((1 - t) * Math.PI) / 2);\n }\n return Math.sin((t * Math.PI) / 2);\n};\n\nconst asinusoidalPosition: PositionFunction = (t: number, reverse = false) => {\n if (reverse) {\n return 1 - Math.asin(1 - t) / (Math.PI / 2);\n }\n return Math.asin(t) / (Math.PI / 2);\n};\n\nconst arcPosition: PositionFunction = (t: number, reverse = false) => {\n if (reverse) {\n return 1 - Math.sqrt(1 - t ** 2);\n }\n return 1 - Math.sqrt(1 - t);\n};\n\nconst smoothStepPosition: PositionFunction = (t: number) => {\n return t ** 2 * (3 - 2 * t);\n};\n\nexport const positionFunctions = {\n linearPosition,\n exponentialPosition,\n quadraticPosition,\n cubicPosition,\n quarticPosition,\n sinusoidalPosition,\n asinusoidalPosition,\n arcPosition,\n smoothStepPosition,\n};\n\n/**\n * Calculates the distance between two points\n * @param p1 The first point\n * @param p2 The second point\n * @param hueMode Whether to use the hue distance function\n * @returns The distance between the two points\n * @example\n * const p1 = [0, 0, 0];\n * const p2 = [1, 1, 1];\n * const dist = distance(p1, p2);\n * console.log(dist); // 1.7320508075688772\n **/\nconst distance = (\n p1: PartialVector3,\n p2: PartialVector3,\n hueMode = false\n): number => {\n const a1 = p1[0];\n const a2 = p2[0];\n let diffA = 0;\n\n if (hueMode && a1 !== null && a2 !== null) {\n diffA = Math.min(Math.abs(a1 - a2), 360 - Math.abs(a1 - a2));\n diffA = diffA / 360;\n } else {\n diffA = a1 === null || a2 === null ? 0 : a1 - a2;\n }\n\n const a = diffA;\n const b = p1[1] === null || p2[1] === null ? 0 : p2[1] - p1[1];\n const c = p1[2] === null || p2[2] === null ? 0 : p2[2] - p1[2];\n\n return Math.sqrt(a * a + b * b + c * c);\n};\n\nexport type ColorPointCollection = {\n xyz?: Vector3;\n color?: Vector3;\n invertedLightness?: boolean;\n};\n\nexport class ColorPoint {\n public x = 0;\n public y = 0;\n public z = 0;\n public color: Vector3 = [0, 0, 0];\n private _invertedLightness = false;\n\n constructor({\n xyz,\n color,\n invertedLightness = false,\n }: ColorPointCollection = {}) {\n this._invertedLightness = invertedLightness;\n this.positionOrColor({ xyz, color, invertedLightness });\n }\n\n positionOrColor({\n xyz,\n color,\n invertedLightness = false,\n }: ColorPointCollection) {\n this._invertedLightness = invertedLightness;\n if ((xyz && color) || (!xyz && !color)) {\n throw new Error(\"Point must be initialized with either x,y,z or hsl\");\n } else if (xyz) {\n this.x = xyz[0];\n this.y = xyz[1];\n this.z = xyz[2];\n this.color = pointToHSL([this.x, this.y, this.z], invertedLightness);\n } else if (color) {\n this.color = color;\n [this.x, this.y, this.z] = hslToPoint(color, invertedLightness);\n }\n }\n\n set position([x, y, z]: Vector3) {\n this.x = x;\n this.y = y;\n this.z = z;\n this.color = pointToHSL(\n [this.x, this.y, this.z] as Vector3,\n this._invertedLightness\n );\n }\n\n get position(): Vector3 {\n return [this.x, this.y, this.z];\n }\n\n set hsl([h, s, l]: Vector3) {\n this.color = [h, s, l];\n [this.x, this.y, this.z] = hslToPoint(\n this.color as Vector3,\n this._invertedLightness\n );\n }\n\n get hsl(): Vector3 {\n return this.color;\n }\n\n get hslCSS(): string {\n const [h, s, l] = this.color;\n return `hsl(${h.toFixed(2)}, ${(s * 100).toFixed(2)}%, ${(l * 100).toFixed(\n 2\n )}%)`;\n }\n\n get oklchCSS(): string {\n const [h, s, l] = this.color;\n return `oklch(${(l * 100).toFixed(2)}% ${(s * 0.4).toFixed(3)} ${h.toFixed(\n 2\n )})`;\n }\n\n get lchCSS(): string {\n const [h, s, l] = this.color;\n return `lch(${(l * 100).toFixed(2)}% ${(s * 150).toFixed(2)} ${h.toFixed(\n 2\n )})`;\n }\n\n shiftHue(angle: number): void {\n this.color[0] = (360 + (this.color[0] + angle)) % 360;\n [this.x, this.y, this.z] = hslToPoint(\n this.color as Vector3,\n this._invertedLightness\n );\n }\n}\n\nexport type PolineOptions = {\n anchorColors: Vector3[];\n numPoints: number;\n positionFunction?: (t: number, invert?: boolean) => number;\n positionFunctionX?: (t: number, invert?: boolean) => number;\n positionFunctionY?: (t: number, invert?: boolean) => number;\n positionFunctionZ?: (t: number, invert?: boolean) => number;\n invertedLightness?: boolean;\n closedLoop?: boolean;\n};\nexport class Poline {\n private _needsUpdate = true;\n private _anchorPoints: ColorPoint[];\n\n private _numPoints: number;\n private points: ColorPoint[][];\n\n private _positionFunctionX = sinusoidalPosition;\n private _positionFunctionY = sinusoidalPosition;\n private _positionFunctionZ = sinusoidalPosition;\n\n private _anchorPairs: ColorPoint[][];\n\n private connectLastAndFirstAnchor = false;\n\n private _animationFrame: null | number = null;\n\n private _invertedLightness = false;\n\n constructor(\n {\n anchorColors = randomHSLPair(),\n numPoints = 4,\n positionFunction = sinusoidalPosition,\n positionFunctionX,\n positionFunctionY,\n positionFunctionZ,\n closedLoop,\n invertedLightness,\n }: PolineOptions = {\n anchorColors: randomHSLPair(),\n numPoints: 4,\n positionFunction: sinusoidalPosition,\n closedLoop: false,\n }\n ) {\n if (!anchorColors || anchorColors.length < 2) {\n throw new Error(\"Must have at least two anchor colors\");\n }\n\n this._anchorPoints = anchorColors.map(\n (point) => new ColorPoint({ color: point, invertedLightness })\n );\n\n this._numPoints = numPoints + 2; // add two for the anchor points\n\n this._positionFunctionX =\n positionFunctionX || positionFunction || sinusoidalPosition;\n this._positionFunctionY =\n positionFunctionY || positionFunction || sinusoidalPosition;\n this._positionFunctionZ =\n positionFunctionZ || positionFunction || sinusoidalPosition;\n\n this.connectLastAndFirstAnchor = closedLoop || false;\n\n this._invertedLightness = invertedLightness || false;\n\n this.updateAnchorPairs();\n }\n\n public get numPoints(): number {\n return this._numPoints - 2;\n }\n\n public set numPoints(numPoints: number) {\n if (numPoints < 1) {\n throw new Error(\"Must have at least one point\");\n }\n this._numPoints = numPoints + 2; // add two for the anchor points\n this.updateAnchorPairs();\n }\n\n public set positionFunction(\n positionFunction: PositionFunction | PositionFunction[]\n ) {\n if (Array.isArray(positionFunction)) {\n if (positionFunction.length !== 3) {\n throw new Error(\"Position function array must have 3 elements\");\n }\n if (\n typeof positionFunction[0] !== \"function\" ||\n typeof positionFunction[1] !== \"function\" ||\n typeof positionFunction[2] !== \"function\"\n ) {\n throw new Error(\"Position function array must have 3 functions\");\n }\n this._positionFunctionX = positionFunction[0];\n this._positionFunctionY = positionFunction[1];\n this._positionFunctionZ = positionFunction[2];\n } else {\n this._positionFunctionX = positionFunction;\n this._positionFunctionY = positionFunction;\n this._positionFunctionZ = positionFunction;\n }\n\n this.updateAnchorPairs();\n }\n\n public get positionFunction(): PositionFunction | PositionFunction[] {\n // not to sure what to do here, because the position function is a combination of the three\n if (\n this._positionFunctionX === this._positionFunctionY &&\n this._positionFunctionX === this._positionFunctionZ\n ) {\n return this._positionFunctionX;\n }\n\n return [\n this._positionFunctionX,\n this._positionFunctionY,\n this._positionFunctionZ,\n ];\n }\n\n public set positionFunctionX(positionFunctionX: PositionFunction) {\n this._positionFunctionX = positionFunctionX;\n this.updateAnchorPairs();\n }\n\n public get positionFunctionX(): PositionFunction {\n return this._positionFunctionX;\n }\n\n public set positionFunctionY(positionFunctionY: PositionFunction) {\n this._positionFunctionY = positionFunctionY;\n this.updateAnchorPairs();\n }\n\n public get positionFunctionY(): PositionFunction {\n return this._positionFunctionY;\n }\n\n public set positionFunctionZ(positionFunctionZ: PositionFunction) {\n this._positionFunctionZ = positionFunctionZ;\n this.updateAnchorPairs();\n }\n\n public get positionFunctionZ(): PositionFunction {\n return this._positionFunctionZ;\n }\n\n public get anchorPoints(): ColorPoint[] {\n return this._anchorPoints;\n }\n\n public set anchorPoints(anchorPoints: ColorPoint[]) {\n this._anchorPoints = anchorPoints;\n this.updateAnchorPairs();\n }\n\n public updateAnchorPairs(): void {\n this._anchorPairs = [] as ColorPoint[][];\n\n const anchorPointsLength = this.connectLastAndFirstAnchor\n ? this.anchorPoints.length\n : this.anchorPoints.length - 1;\n\n for (let i = 0; i < anchorPointsLength; i++) {\n const pair = [\n this.anchorPoints[i],\n this.anchorPoints[(i + 1) % this.anchorPoints.length],\n ] as ColorPoint[];\n\n this._anchorPairs.push(pair);\n }\n\n this.points = this._anchorPairs.map((pair, i) => {\n const p1position = pair[0] ? pair[0].position : ([0, 0, 0] as Vector3);\n const p2position = pair[1] ? pair[1].position : ([0, 0, 0] as Vector3);\n\n // Special handling for closed loop with exactly 2 anchors\n // we want to invert the ease for the first segment\n const shouldInvertEase = this.shouldInvertEaseForSegment(i);\n\n return vectorsOnLine(\n p1position,\n p2position,\n this._numPoints,\n shouldInvertEase ? true : false,\n this.positionFunctionX,\n this.positionFunctionY,\n this.positionFunctionZ\n ).map(\n (p) =>\n new ColorPoint({ xyz: p, invertedLightness: this._invertedLightness })\n );\n });\n }\n\n public addAnchorPoint({\n xyz,\n color,\n insertAtIndex,\n }: ColorPointCollection & { insertAtIndex?: number }): ColorPoint {\n const newAnchor = new ColorPoint({\n xyz,\n color,\n invertedLightness: this._invertedLightness,\n });\n if (insertAtIndex !== undefined) {\n this.anchorPoints.splice(insertAtIndex, 0, newAnchor);\n } else {\n this.anchorPoints.push(newAnchor);\n }\n this.updateAnchorPairs();\n return newAnchor;\n }\n\n public removeAnchorPoint({\n point,\n index,\n }: {\n point?: ColorPoint;\n index?: number;\n }): void {\n if (!point && index === undefined) {\n throw new Error(\"Must provide a point or index\");\n }\n\n if (this.anchorPoints.length < 3) {\n throw new Error(\"Must have at least two anchor points\");\n }\n\n let apid;\n\n if (index !== undefined) {\n apid = index;\n } else if (point) {\n apid = this.anchorPoints.indexOf(point);\n }\n\n if (apid > -1 && apid < this.anchorPoints.length) {\n this.anchorPoints.splice(apid, 1);\n this.updateAnchorPairs();\n } else {\n throw new Error(\"Point not found\");\n }\n }\n\n public updateAnchorPoint({\n point,\n pointIndex,\n xyz,\n color,\n }: {\n point?: ColorPoint;\n pointIndex?: number;\n } & ColorPointCollection): ColorPoint {\n if (pointIndex !== undefined) {\n point = this.anchorPoints[pointIndex];\n }\n\n if (!point) {\n throw new Error(\"Must provide a point or pointIndex\");\n }\n\n if (!xyz && !color) {\n throw new Error(\"Must provide a new xyz position or color\");\n }\n\n if (xyz) point.position = xyz;\n if (color) point.hsl = color;\n\n this.updateAnchorPairs();\n\n return point;\n }\n\n public getClosestAnchorPoint({\n xyz,\n hsl,\n maxDistance = 1,\n }: {\n xyz?: PartialVector3;\n hsl?: PartialVector3;\n maxDistance?: number;\n }): ColorPoint | null {\n if (!xyz && !hsl) {\n throw new Error(\"Must provide a xyz or hsl\");\n }\n\n let distances;\n\n if (xyz) {\n distances = this.anchorPoints.map((anchor) =>\n distance(anchor.position, xyz)\n );\n } else if (hsl) {\n distances = this.anchorPoints.map((anchor) =>\n distance(anchor.hsl, hsl, true)\n );\n }\n\n const minDistance = Math.min(...distances);\n\n if (minDistance > maxDistance) {\n return null;\n }\n\n const closestAnchorIndex = distances.indexOf(minDistance);\n\n return this.anchorPoints[closestAnchorIndex] || null;\n }\n\n public set closedLoop(newStatus: boolean) {\n this.connectLastAndFirstAnchor = newStatus;\n this.updateAnchorPairs();\n }\n\n public get closedLoop(): boolean {\n return this.connectLastAndFirstAnchor;\n }\n\n public set invertedLightness(newStatus: boolean) {\n this._invertedLightness = newStatus;\n this.updateAnchorPairs();\n }\n\n public get invertedLightness(): boolean {\n return this._invertedLightness;\n }\n\n /**\n * Returns a flattened array of all points across all segments,\n * removing duplicated anchor points at segment boundaries.\n *\n * Since anchor points exist at both the end of one segment and\n * the beginning of the next, this method keeps only one instance of each.\n * The filter logic keeps the first point (index 0) and then filters out\n * points whose indices are multiples of the segment size (_numPoints),\n * which are the anchor points at the start of each segment (except the first).\n *\n * This approach ensures we get all unique points in the correct order\n * while avoiding duplicated anchor points.\n *\n * @returns {ColorPoint[]} A flat array of unique ColorPoint instances\n */\n public get flattenedPoints() {\n return this.points\n .flat()\n .filter((p, i) => (i != 0 ? i % this._numPoints : true));\n }\n\n public get colors() {\n const colors = this.flattenedPoints.map((p) => p.color);\n if (this.connectLastAndFirstAnchor && this._anchorPoints.length !== 2) {\n colors.pop();\n }\n return colors;\n }\n\n public cssColors(mode: \"hsl\" | \"oklch\" | \"lch\" = \"hsl\"): string[] {\n const methods: CSSColorMethods = {\n hsl: (p: ColorPoint): string => p.hslCSS,\n oklch: (p: ColorPoint): string => p.oklchCSS,\n lch: (p: ColorPoint): string => p.lchCSS,\n };\n const cssColors = this.flattenedPoints.map(methods[mode]);\n if (this.connectLastAndFirstAnchor) {\n cssColors.pop();\n }\n return cssColors;\n }\n\n public get colorsCSS() {\n return this.cssColors(\"hsl\");\n }\n\n public get colorsCSSlch() {\n return this.cssColors(\"lch\");\n }\n\n public get colorsCSSoklch() {\n return this.cssColors(\"oklch\");\n }\n\n public shiftHue(hShift = 20): void {\n this.anchorPoints.forEach((p) => p.shiftHue(hShift));\n this.updateAnchorPairs();\n }\n\n /**\n * Returns a color at a specific position along the entire color line (0-1)\n * Treats all segments as one continuous path, respecting easing functions\n * @param t Position along the line (0-1), where 0 is start and 1 is end\n * @returns ColorPoint at the specified position\n * @example\n * getColorAt(0) // Returns color at the very beginning\n * getColorAt(0.5) // Returns color at the middle of the entire journey\n * getColorAt(1) // Returns color at the very end\n */\n public getColorAt(t: number): ColorPoint {\n if (t < 0 || t > 1) {\n throw new Error(\"Position must be between 0 and 1\");\n }\n\n if (this.anchorPoints.length === 0) {\n throw new Error(\"No anchor points available\");\n }\n\n // For closed loops, we need to handle the full circle\n const totalSegments = this.connectLastAndFirstAnchor\n ? this.anchorPoints.length\n : this.anchorPoints.length - 1;\n\n // Special case: if we only have 2 anchors in a closed loop,\n // we actually have 2 segments going different ways\n const effectiveSegments =\n this.connectLastAndFirstAnchor && this.anchorPoints.length === 2\n ? 2\n : totalSegments;\n\n // Calculate which segment we're in and the position within that segment\n const segmentPosition = t * effectiveSegments;\n const segmentIndex = Math.floor(segmentPosition);\n const localT = segmentPosition - segmentIndex;\n\n // Handle edge case where t = 1 (end of line)\n const actualSegmentIndex =\n segmentIndex >= effectiveSegments ? effectiveSegments - 1 : segmentIndex;\n const actualLocalT = segmentIndex >= effectiveSegments ? 1 : localT;\n\n // Get the anchor pair for this segment\n const pair = this._anchorPairs[actualSegmentIndex];\n if (!pair || pair.length < 2 || !pair[0] || !pair[1]) {\n // Fallback to first anchor if something goes wrong\n return new ColorPoint({\n color: this.anchorPoints[0]?.color || [0, 0, 0],\n invertedLightness: this._invertedLightness,\n });\n }\n\n const p1position = pair[0].position;\n const p2position = pair[1].position;\n\n // Apply the same easing logic as in updateAnchorPairs\n const shouldInvertEase =\n this.shouldInvertEaseForSegment(actualSegmentIndex);\n\n // Use the existing vectorOnLine function for consistent interpolation\n const xyz = vectorOnLine(\n actualLocalT,\n p1position,\n p2position,\n shouldInvertEase,\n this._positionFunctionX,\n this._positionFunctionY,\n this._positionFunctionZ\n );\n\n return new ColorPoint({\n xyz,\n invertedLightness: this._invertedLightness,\n });\n }\n\n /**\n * Determines whether easing should be inverted for a given segment\n * @param segmentIndex The index of the segment\n * @returns Whether easing should be inverted\n */\n private shouldInvertEaseForSegment(segmentIndex: number): boolean {\n return !!(\n segmentIndex % 2 ||\n (this.connectLastAndFirstAnchor &&\n this.anchorPoints.length === 2 &&\n segmentIndex === 0)\n );\n }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst { p5 } = globalThis as any;\n\nif (p5 && p5.VERSION && p5.VERSION.startsWith(\"1.\")) {\n console.info(\"p5 < 1.x detected, adding poline to p5 prototype\");\n\n const poline = new Poline();\n p5.prototype.poline = poline;\n\n const polineColors = () =>\n poline.colors.map(\n (c) => `hsl(${Math.round(c[0])},${c[1] * 100}%,${c[2] * 100}%)`\n );\n\n p5.prototype.registerMethod(\"polineColors\", polineColors);\n\n globalThis.poline = poline;\n globalThis.polineColors = polineColors;\n}\n"], | ||
| "mappings": "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", | ||
| "sourcesContent": ["/* eslint-disable @typescript-eslint/ban-ts-comment */\nexport type FuncNumberReturn = (arg0: number) => Vector2;\nexport type Vector2 = [number, number];\nexport type Vector3 = [number, ...Vector2];\nexport type PartialVector3 = [number | null, number | null, number | null];\n\ntype CSSColorMethods = {\n hsl: (p: ColorPoint) => string;\n oklch: (p: ColorPoint) => string;\n lch: (p: ColorPoint) => string;\n};\n\n/**\n * Converts the given (x, y, z) coordinate to an HSL color\n * The (x, y) values are used to calculate the hue, while the z value is used as the saturation\n * The lightness value is calculated based on the distance of (x, y) from the center (0.5, 0.5)\n * Returns an array [hue, saturation, lightness]\n * @param xyz:Vector3 [x, y, z] coordinate array in (x, y, z) format (0-1, 0-1, 0-1)\n * @returns [hue, saturation, lightness]: Vector3 color array in HSL format (0-360, 0-1, 0-1)\n * @example\n * pointToHSL([0.5, 0.5, 1]) // [0, 1, 0.5]\n * pointToHSL([0.5, 0.5, 0]) // [0, 1, 0]\n **/\n\nexport const pointToHSL = (\n xyz: Vector3,\n invertedLightness: boolean\n): Vector3 => {\n const [x, y, z] = xyz;\n\n // cy and cx are the center (y and x) values\n const cx = 0.5;\n const cy = 0.5;\n\n // Calculate the angle between the point (x, y) and the center (cx, cy)\n const radians = Math.atan2(y - cy, x - cx);\n\n // Convert the angle to degrees and shift it so that it goes from 0 to 360\n let deg = radians * (180 / Math.PI);\n deg = (360 + deg) % 360;\n\n // The saturation value is taken from the z coordinate\n const s = z;\n\n // Calculate the lightness value based on the distance from the center\n const dist = Math.sqrt(Math.pow(y - cy, 2) + Math.pow(x - cx, 2));\n const l = dist / cx;\n\n // Return the HSL color as an array [hue, saturation, lightness]\n return [deg, s, invertedLightness ? 1 - l : l];\n};\n\n/**\n * Converts the given HSL color to an (x, y, z) coordinate\n * The hue value is used to calculate the (x, y) position, while the saturation value is used as the z coordinate\n * The lightness value is used to calculate the distance from the center (0.5, 0.5)\n * Returns an array [x, y, z]\n * @param hsl:Vector3 [hue, saturation, lightness] color array in HSL format (0-360, 0-1, 0-1)\n * @returns [x, y, z]:Vector3 coordinate array in (x, y, z) format (0-1, 0-1, 0-1)\n * @example\n * hslToPoint([0, 1, 0.5]) // [0.5, 0.5, 1]\n * hslToPoint([0, 1, 0]) // [0.5, 0.5, 1]\n * hslToPoint([0, 1, 1]) // [0.5, 0.5, 1]\n * hslToPoint([0, 0, 0.5]) // [0.5, 0.5, 0]\n **/\nexport const hslToPoint = (\n hsl: Vector3,\n invertedLightness: boolean\n): Vector3 => {\n // Destructure the input array into separate hue, saturation, and lightness values\n const [h, s, l] = hsl;\n // cx and cy are the center (x and y) values\n const cx = 0.5;\n const cy = 0.5;\n // Calculate the angle in radians based on the hue value\n const radians = h / (180 / Math.PI);\n\n // Calculate the distance from the center based on the lightness value\n const dist = (invertedLightness ? 1 - l : l) * cx;\n\n // Calculate the x and y coordinates based on the distance and angle\n const x = cx + dist * Math.cos(radians);\n const y = cy + dist * Math.sin(radians);\n // The z coordinate is equal to the saturation value\n const z = s;\n // Return the (x, y, z) coordinate as an array [x, y, z]\n return [x, y, z];\n};\n\nexport const randomHSLPair = (\n startHue: number = Math.random() * 360,\n saturations: Vector2 = [Math.random(), Math.random()],\n lightnesses: Vector2 = [0.75 + Math.random() * 0.2, 0.3 + Math.random() * 0.2]\n): [Vector3, Vector3] => [\n [startHue, saturations[0], lightnesses[0]],\n [(startHue + 60 + Math.random() * 180) % 360, saturations[1], lightnesses[1]],\n];\n\nexport const randomHSLTriple = (\n startHue: number = Math.random() * 360,\n saturations: Vector3 = [Math.random(), Math.random(), Math.random()],\n lightnesses: Vector3 = [\n 0.75 + Math.random() * 0.2,\n Math.random() * 0.2,\n 0.75 + Math.random() * 0.2,\n ]\n): [Vector3, Vector3, Vector3] => [\n [startHue, saturations[0], lightnesses[0]],\n [(startHue + 60 + Math.random() * 180) % 360, saturations[1], lightnesses[1]],\n [(startHue + 60 + Math.random() * 180) % 360, saturations[2], lightnesses[2]],\n];\n\nconst vectorOnLine = (\n t: number,\n p1: Vector3,\n p2: Vector3,\n invert = false,\n fx = (t: number, invert: boolean): number => (invert ? 1 - t : t),\n fy = (t: number, invert: boolean): number => (invert ? 1 - t : t),\n fz = (t: number, invert: boolean): number => (invert ? 1 - t : t)\n): Vector3 => {\n const tModifiedX = fx(t, invert);\n const tModifiedY = fy(t, invert);\n const tModifiedZ = fz(t, invert);\n const x = (1 - tModifiedX) * p1[0] + tModifiedX * p2[0];\n const y = (1 - tModifiedY) * p1[1] + tModifiedY * p2[1];\n const z = (1 - tModifiedZ) * p1[2] + tModifiedZ * p2[2];\n\n return [x, y, z];\n};\n\nconst vectorsOnLine = (\n p1: Vector3,\n p2: Vector3,\n numPoints = 4,\n invert = false,\n fx = (t: number, invert: boolean): number => (invert ? 1 - t : t),\n fy = (t: number, invert: boolean): number => (invert ? 1 - t : t),\n fz = (t: number, invert: boolean): number => (invert ? 1 - t : t)\n): Vector3[] => {\n const points: Vector3[] = [];\n\n for (let i = 0; i < numPoints; i++) {\n const [x, y, z] = vectorOnLine(\n i / (numPoints - 1),\n p1,\n p2,\n invert,\n fx,\n fy,\n fz\n );\n points.push([x, y, z]);\n }\n\n return points;\n};\n\nexport type PositionFunction = (t: number, reverse?: boolean) => number;\n\nconst linearPosition: PositionFunction = (t: number) => {\n return t;\n};\n\nconst exponentialPosition: PositionFunction = (t: number, reverse = false) => {\n if (reverse) {\n return 1 - (1 - t) ** 2;\n }\n return t ** 2;\n};\n\nconst quadraticPosition: PositionFunction = (t: number, reverse = false) => {\n if (reverse) {\n return 1 - (1 - t) ** 3;\n }\n return t ** 3;\n};\n\nconst cubicPosition: PositionFunction = (t: number, reverse = false) => {\n if (reverse) {\n return 1 - (1 - t) ** 4;\n }\n return t ** 4;\n};\n\nconst quarticPosition: PositionFunction = (t: number, reverse = false) => {\n if (reverse) {\n return 1 - (1 - t) ** 5;\n }\n return t ** 5;\n};\n\nconst sinusoidalPosition: PositionFunction = (t: number, reverse = false) => {\n if (reverse) {\n return 1 - Math.sin(((1 - t) * Math.PI) / 2);\n }\n return Math.sin((t * Math.PI) / 2);\n};\n\nconst asinusoidalPosition: PositionFunction = (t: number, reverse = false) => {\n if (reverse) {\n return 1 - Math.asin(1 - t) / (Math.PI / 2);\n }\n return Math.asin(t) / (Math.PI / 2);\n};\n\nconst arcPosition: PositionFunction = (t: number, reverse = false) => {\n if (reverse) {\n return 1 - Math.sqrt(1 - t ** 2);\n }\n return 1 - Math.sqrt(1 - t);\n};\n\nconst smoothStepPosition: PositionFunction = (t: number) => {\n return t ** 2 * (3 - 2 * t);\n};\n\nexport const positionFunctions = {\n linearPosition,\n exponentialPosition,\n quadraticPosition,\n cubicPosition,\n quarticPosition,\n sinusoidalPosition,\n asinusoidalPosition,\n arcPosition,\n smoothStepPosition,\n};\n\n/**\n * Calculates the distance between two points\n * @param p1 The first point\n * @param p2 The second point\n * @param hueMode Whether to use the hue distance function\n * @returns The distance between the two points\n * @example\n * const p1 = [0, 0, 0];\n * const p2 = [1, 1, 1];\n * const dist = distance(p1, p2);\n * console.log(dist); // 1.7320508075688772\n **/\nconst distance = (\n p1: PartialVector3,\n p2: PartialVector3,\n hueMode = false\n): number => {\n const a1 = p1[0];\n const a2 = p2[0];\n let diffA = 0;\n\n if (hueMode && a1 !== null && a2 !== null) {\n diffA = Math.min(Math.abs(a1 - a2), 360 - Math.abs(a1 - a2));\n diffA = diffA / 360;\n } else {\n diffA = a1 === null || a2 === null ? 0 : a1 - a2;\n }\n\n const a = diffA;\n const b = p1[1] === null || p2[1] === null ? 0 : p2[1] - p1[1];\n const c = p1[2] === null || p2[2] === null ? 0 : p2[2] - p1[2];\n\n return Math.sqrt(a * a + b * b + c * c);\n};\n\nexport type ColorPointCollection = {\n xyz?: Vector3;\n color?: Vector3;\n invertedLightness?: boolean;\n};\n\nexport class ColorPoint {\n public x = 0;\n public y = 0;\n public z = 0;\n public color: Vector3 = [0, 0, 0];\n private _invertedLightness = false;\n\n constructor({\n xyz,\n color,\n invertedLightness = false,\n }: ColorPointCollection = {}) {\n this._invertedLightness = invertedLightness;\n this.positionOrColor({ xyz, color, invertedLightness });\n }\n\n positionOrColor({\n xyz,\n color,\n invertedLightness = false,\n }: ColorPointCollection) {\n this._invertedLightness = invertedLightness;\n if ((xyz && color) || (!xyz && !color)) {\n throw new Error(\"Point must be initialized with either x,y,z or hsl\");\n } else if (xyz) {\n this.x = xyz[0];\n this.y = xyz[1];\n this.z = xyz[2];\n this.color = pointToHSL([this.x, this.y, this.z], invertedLightness);\n } else if (color) {\n this.color = color;\n [this.x, this.y, this.z] = hslToPoint(color, invertedLightness);\n }\n }\n\n set position([x, y, z]: Vector3) {\n this.x = x;\n this.y = y;\n this.z = z;\n this.color = pointToHSL(\n [this.x, this.y, this.z] as Vector3,\n this._invertedLightness\n );\n }\n\n get position(): Vector3 {\n return [this.x, this.y, this.z];\n }\n\n set hsl([h, s, l]: Vector3) {\n this.color = [h, s, l];\n [this.x, this.y, this.z] = hslToPoint(\n this.color as Vector3,\n this._invertedLightness\n );\n }\n\n get hsl(): Vector3 {\n return this.color;\n }\n\n get hslCSS(): string {\n const [h, s, l] = this.color;\n return `hsl(${h.toFixed(2)}, ${(s * 100).toFixed(2)}%, ${(l * 100).toFixed(\n 2\n )}%)`;\n }\n\n get oklchCSS(): string {\n const [h, s, l] = this.color;\n return `oklch(${(l * 100).toFixed(2)}% ${(s * 0.4).toFixed(3)} ${h.toFixed(\n 2\n )})`;\n }\n\n get lchCSS(): string {\n const [h, s, l] = this.color;\n return `lch(${(l * 100).toFixed(2)}% ${(s * 150).toFixed(2)} ${h.toFixed(\n 2\n )})`;\n }\n\n set invertedLightness(val: boolean) {\n this._invertedLightness = val;\n this.color = pointToHSL(\n [this.x, this.y, this.z] as Vector3,\n this._invertedLightness\n );\n }\n\n get invertedLightness(): boolean {\n return this._invertedLightness;\n }\n\n shiftHue(angle: number): void {\n this.color[0] = (360 + (this.color[0] + angle)) % 360;\n [this.x, this.y, this.z] = hslToPoint(\n this.color as Vector3,\n this._invertedLightness\n );\n }\n}\n\nexport type PolineOptions = {\n anchorColors?: Vector3[];\n numPoints?: number;\n positionFunction?: (t: number, invert?: boolean) => number;\n positionFunctionX?: (t: number, invert?: boolean) => number;\n positionFunctionY?: (t: number, invert?: boolean) => number;\n positionFunctionZ?: (t: number, invert?: boolean) => number;\n invertedLightness?: boolean;\n closedLoop?: boolean;\n};\nexport class Poline {\n private _anchorPoints: ColorPoint[];\n\n private _numPoints: number;\n private points: ColorPoint[][];\n\n private _positionFunctionX = sinusoidalPosition;\n private _positionFunctionY = sinusoidalPosition;\n private _positionFunctionZ = sinusoidalPosition;\n\n private _anchorPairs: ColorPoint[][];\n\n private connectLastAndFirstAnchor = false;\n\n private _animationFrame: null | number = null;\n\n private _invertedLightness = false;\n\n constructor(\n {\n anchorColors = randomHSLPair(),\n numPoints = 4,\n positionFunction = sinusoidalPosition,\n positionFunctionX,\n positionFunctionY,\n positionFunctionZ,\n closedLoop,\n invertedLightness,\n }: PolineOptions = {\n anchorColors: randomHSLPair(),\n numPoints: 4,\n positionFunction: sinusoidalPosition,\n closedLoop: false,\n }\n ) {\n if (!anchorColors || anchorColors.length < 2) {\n throw new Error(\"Must have at least two anchor colors\");\n }\n\n this._anchorPoints = anchorColors.map(\n (point) => new ColorPoint({ color: point, invertedLightness })\n );\n\n this._numPoints = numPoints + 2; // add two for the anchor points\n\n this._positionFunctionX =\n positionFunctionX || positionFunction || sinusoidalPosition;\n this._positionFunctionY =\n positionFunctionY || positionFunction || sinusoidalPosition;\n this._positionFunctionZ =\n positionFunctionZ || positionFunction || sinusoidalPosition;\n\n this.connectLastAndFirstAnchor = closedLoop || false;\n\n this._invertedLightness = invertedLightness || false;\n\n this.updateAnchorPairs();\n }\n\n public get numPoints(): number {\n return this._numPoints - 2;\n }\n\n public set numPoints(numPoints: number) {\n if (numPoints < 1) {\n throw new Error(\"Must have at least one point\");\n }\n this._numPoints = numPoints + 2; // add two for the anchor points\n this.updateAnchorPairs();\n }\n\n public set positionFunction(\n positionFunction: PositionFunction | PositionFunction[]\n ) {\n if (Array.isArray(positionFunction)) {\n if (positionFunction.length !== 3) {\n throw new Error(\"Position function array must have 3 elements\");\n }\n if (\n typeof positionFunction[0] !== \"function\" ||\n typeof positionFunction[1] !== \"function\" ||\n typeof positionFunction[2] !== \"function\"\n ) {\n throw new Error(\"Position function array must have 3 functions\");\n }\n this._positionFunctionX = positionFunction[0];\n this._positionFunctionY = positionFunction[1];\n this._positionFunctionZ = positionFunction[2];\n } else {\n this._positionFunctionX = positionFunction;\n this._positionFunctionY = positionFunction;\n this._positionFunctionZ = positionFunction;\n }\n\n this.updateAnchorPairs();\n }\n\n public get positionFunction(): PositionFunction | PositionFunction[] {\n // not to sure what to do here, because the position function is a combination of the three\n if (\n this._positionFunctionX === this._positionFunctionY &&\n this._positionFunctionX === this._positionFunctionZ\n ) {\n return this._positionFunctionX;\n }\n\n return [\n this._positionFunctionX,\n this._positionFunctionY,\n this._positionFunctionZ,\n ];\n }\n\n public set positionFunctionX(positionFunctionX: PositionFunction) {\n this._positionFunctionX = positionFunctionX;\n this.updateAnchorPairs();\n }\n\n public get positionFunctionX(): PositionFunction {\n return this._positionFunctionX;\n }\n\n public set positionFunctionY(positionFunctionY: PositionFunction) {\n this._positionFunctionY = positionFunctionY;\n this.updateAnchorPairs();\n }\n\n public get positionFunctionY(): PositionFunction {\n return this._positionFunctionY;\n }\n\n public set positionFunctionZ(positionFunctionZ: PositionFunction) {\n this._positionFunctionZ = positionFunctionZ;\n this.updateAnchorPairs();\n }\n\n public get positionFunctionZ(): PositionFunction {\n return this._positionFunctionZ;\n }\n\n public get anchorPoints(): ColorPoint[] {\n return this._anchorPoints;\n }\n\n public set anchorPoints(anchorPoints: ColorPoint[]) {\n this._anchorPoints = anchorPoints;\n this.updateAnchorPairs();\n }\n\n public updateAnchorPairs(): void {\n this._anchorPairs = [] as ColorPoint[][];\n\n const anchorPointsLength = this.connectLastAndFirstAnchor\n ? this.anchorPoints.length\n : this.anchorPoints.length - 1;\n\n for (let i = 0; i < anchorPointsLength; i++) {\n const pair = [\n this.anchorPoints[i],\n this.anchorPoints[(i + 1) % this.anchorPoints.length],\n ] as ColorPoint[];\n\n this._anchorPairs.push(pair);\n }\n\n this.points = this._anchorPairs.map((pair, i) => {\n const p1position = pair[0] ? pair[0].position : ([0, 0, 0] as Vector3);\n const p2position = pair[1] ? pair[1].position : ([0, 0, 0] as Vector3);\n\n // Special handling for closed loop with exactly 2 anchors\n // we want to invert the ease for the first segment\n const shouldInvertEase = this.shouldInvertEaseForSegment(i);\n\n return vectorsOnLine(\n p1position,\n p2position,\n this._numPoints,\n shouldInvertEase ? true : false,\n this.positionFunctionX,\n this.positionFunctionY,\n this.positionFunctionZ\n ).map(\n (p) =>\n new ColorPoint({ xyz: p, invertedLightness: this._invertedLightness })\n );\n });\n }\n\n public addAnchorPoint({\n xyz,\n color,\n insertAtIndex,\n }: ColorPointCollection & { insertAtIndex?: number }): ColorPoint {\n const newAnchor = new ColorPoint({\n xyz,\n color,\n invertedLightness: this._invertedLightness,\n });\n if (insertAtIndex !== undefined) {\n this.anchorPoints.splice(insertAtIndex, 0, newAnchor);\n } else {\n this.anchorPoints.push(newAnchor);\n }\n this.updateAnchorPairs();\n return newAnchor;\n }\n\n public removeAnchorPoint({\n point,\n index,\n }: {\n point?: ColorPoint;\n index?: number;\n }): void {\n if (!point && index === undefined) {\n throw new Error(\"Must provide a point or index\");\n }\n\n if (this.anchorPoints.length < 3) {\n throw new Error(\"Must have at least two anchor points\");\n }\n\n let apid;\n\n if (index !== undefined) {\n apid = index;\n } else if (point) {\n apid = this.anchorPoints.indexOf(point);\n }\n\n if (apid > -1 && apid < this.anchorPoints.length) {\n this.anchorPoints.splice(apid, 1);\n this.updateAnchorPairs();\n } else {\n throw new Error(\"Point not found\");\n }\n }\n\n public updateAnchorPoint({\n point,\n pointIndex,\n xyz,\n color,\n }: {\n point?: ColorPoint;\n pointIndex?: number;\n } & ColorPointCollection): ColorPoint {\n if (pointIndex !== undefined) {\n point = this.anchorPoints[pointIndex];\n }\n\n if (!point) {\n throw new Error(\"Must provide a point or pointIndex\");\n }\n\n if (!xyz && !color) {\n throw new Error(\"Must provide a new xyz position or color\");\n }\n\n if (xyz) point.position = xyz;\n if (color) point.hsl = color;\n\n this.updateAnchorPairs();\n\n return point;\n }\n\n public getClosestAnchorPoint({\n xyz,\n hsl,\n maxDistance = 1,\n }: {\n xyz?: PartialVector3;\n hsl?: PartialVector3;\n maxDistance?: number;\n }): ColorPoint | null {\n if (!xyz && !hsl) {\n throw new Error(\"Must provide a xyz or hsl\");\n }\n\n let distances;\n\n if (xyz) {\n distances = this.anchorPoints.map((anchor) =>\n distance(anchor.position, xyz)\n );\n } else if (hsl) {\n distances = this.anchorPoints.map((anchor) =>\n distance(anchor.hsl, hsl, true)\n );\n }\n\n const minDistance = Math.min(...distances);\n\n if (minDistance > maxDistance) {\n return null;\n }\n\n const closestAnchorIndex = distances.indexOf(minDistance);\n\n return this.anchorPoints[closestAnchorIndex] || null;\n }\n\n public set closedLoop(newStatus: boolean) {\n this.connectLastAndFirstAnchor = newStatus;\n this.updateAnchorPairs();\n }\n\n public get closedLoop(): boolean {\n return this.connectLastAndFirstAnchor;\n }\n\n public set invertedLightness(newStatus: boolean) {\n this._invertedLightness = newStatus;\n this.anchorPoints.forEach((p) => (p.invertedLightness = newStatus));\n this.updateAnchorPairs();\n }\n\n public get invertedLightness(): boolean {\n return this._invertedLightness;\n }\n\n /**\n * Returns a flattened array of all points across all segments,\n * removing duplicated anchor points at segment boundaries.\n *\n * Since anchor points exist at both the end of one segment and\n * the beginning of the next, this method keeps only one instance of each.\n * The filter logic keeps the first point (index 0) and then filters out\n * points whose indices are multiples of the segment size (_numPoints),\n * which are the anchor points at the start of each segment (except the first).\n *\n * This approach ensures we get all unique points in the correct order\n * while avoiding duplicated anchor points.\n *\n * @returns {ColorPoint[]} A flat array of unique ColorPoint instances\n */\n public get flattenedPoints() {\n return this.points\n .flat()\n .filter((p, i) => (i != 0 ? i % this._numPoints : true));\n }\n\n public get colors() {\n const colors = this.flattenedPoints.map((p) => p.color);\n if (this.connectLastAndFirstAnchor && this._anchorPoints.length !== 2) {\n colors.pop();\n }\n return colors;\n }\n\n public cssColors(mode: \"hsl\" | \"oklch\" | \"lch\" = \"hsl\"): string[] {\n const methods: CSSColorMethods = {\n hsl: (p: ColorPoint): string => p.hslCSS,\n oklch: (p: ColorPoint): string => p.oklchCSS,\n lch: (p: ColorPoint): string => p.lchCSS,\n };\n const cssColors = this.flattenedPoints.map(methods[mode]);\n if (this.connectLastAndFirstAnchor) {\n cssColors.pop();\n }\n return cssColors;\n }\n\n public get colorsCSS() {\n return this.cssColors(\"hsl\");\n }\n\n public get colorsCSSlch() {\n return this.cssColors(\"lch\");\n }\n\n public get colorsCSSoklch() {\n return this.cssColors(\"oklch\");\n }\n\n public shiftHue(hShift = 20): void {\n this.anchorPoints.forEach((p) => p.shiftHue(hShift));\n this.updateAnchorPairs();\n }\n\n /**\n * Returns a color at a specific position along the entire color line (0-1)\n * Treats all segments as one continuous path, respecting easing functions\n * @param t Position along the line (0-1), where 0 is start and 1 is end\n * @returns ColorPoint at the specified position\n * @example\n * getColorAt(0) // Returns color at the very beginning\n * getColorAt(0.5) // Returns color at the middle of the entire journey\n * getColorAt(1) // Returns color at the very end\n */\n public getColorAt(t: number): ColorPoint {\n if (t < 0 || t > 1) {\n throw new Error(\"Position must be between 0 and 1\");\n }\n\n if (this.anchorPoints.length === 0) {\n throw new Error(\"No anchor points available\");\n }\n\n // For closed loops, we need to handle the full circle\n const totalSegments = this.connectLastAndFirstAnchor\n ? this.anchorPoints.length\n : this.anchorPoints.length - 1;\n\n // Special case: if we only have 2 anchors in a closed loop,\n // we actually have 2 segments going different ways\n const effectiveSegments =\n this.connectLastAndFirstAnchor && this.anchorPoints.length === 2\n ? 2\n : totalSegments;\n\n // Calculate which segment we're in and the position within that segment\n const segmentPosition = t * effectiveSegments;\n const segmentIndex = Math.floor(segmentPosition);\n const localT = segmentPosition - segmentIndex;\n\n // Handle edge case where t = 1 (end of line)\n const actualSegmentIndex =\n segmentIndex >= effectiveSegments ? effectiveSegments - 1 : segmentIndex;\n const actualLocalT = segmentIndex >= effectiveSegments ? 1 : localT;\n\n // Get the anchor pair for this segment\n const pair = this._anchorPairs[actualSegmentIndex];\n if (!pair || pair.length < 2 || !pair[0] || !pair[1]) {\n // Fallback to first anchor if something goes wrong\n return new ColorPoint({\n color: this.anchorPoints[0]?.color || [0, 0, 0],\n invertedLightness: this._invertedLightness,\n });\n }\n\n const p1position = pair[0].position;\n const p2position = pair[1].position;\n\n // Apply the same easing logic as in updateAnchorPairs\n const shouldInvertEase =\n this.shouldInvertEaseForSegment(actualSegmentIndex);\n\n // Use the existing vectorOnLine function for consistent interpolation\n const xyz = vectorOnLine(\n actualLocalT,\n p1position,\n p2position,\n shouldInvertEase,\n this._positionFunctionX,\n this._positionFunctionY,\n this._positionFunctionZ\n );\n\n return new ColorPoint({\n xyz,\n invertedLightness: this._invertedLightness,\n });\n }\n\n /**\n * Determines whether easing should be inverted for a given segment\n * @param segmentIndex The index of the segment\n * @returns Whether easing should be inverted\n */\n private shouldInvertEaseForSegment(segmentIndex: number): boolean {\n return !!(\n segmentIndex % 2 ||\n (this.connectLastAndFirstAnchor &&\n this.anchorPoints.length === 2 &&\n segmentIndex === 0)\n );\n }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst { p5 } = globalThis as any;\n\nif (p5 && p5.VERSION && p5.VERSION.startsWith(\"1.\")) {\n console.info(\"p5 < 1.x detected, adding poline to p5 prototype\");\n\n const poline = new Poline();\n p5.prototype.poline = poline;\n\n const polineColors = () =>\n poline.colors.map(\n (c) => `hsl(${Math.round(c[0])},${c[1] * 100}%,${c[2] * 100}%)`\n );\n\n p5.prototype.registerMethod(\"polineColors\", polineColors);\n\n globalThis.poline = poline;\n globalThis.polineColors = polineColors;\n}\n"], | ||
| "mappings": "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", | ||
| "names": ["t", "invert"] | ||
| } |
+11
-1
@@ -250,2 +250,12 @@ (function(root, factory) { | ||
| } | ||
| set invertedLightness(val) { | ||
| this._invertedLightness = val; | ||
| this.color = pointToHSL( | ||
| [this.x, this.y, this.z], | ||
| this._invertedLightness | ||
| ); | ||
| } | ||
| get invertedLightness() { | ||
| return this._invertedLightness; | ||
| } | ||
| shiftHue(angle) { | ||
@@ -275,3 +285,2 @@ this.color[0] = (360 + (this.color[0] + angle)) % 360; | ||
| }) { | ||
| this._needsUpdate = true; | ||
| this._positionFunctionX = sinusoidalPosition; | ||
@@ -487,2 +496,3 @@ this._positionFunctionY = sinusoidalPosition; | ||
| this._invertedLightness = newStatus; | ||
| this.anchorPoints.forEach((p) => p.invertedLightness = newStatus); | ||
| this.updateAnchorPairs(); | ||
@@ -489,0 +499,0 @@ } |
+11
-1
@@ -229,2 +229,12 @@ "use strict"; | ||
| } | ||
| set invertedLightness(val) { | ||
| this._invertedLightness = val; | ||
| this.color = pointToHSL( | ||
| [this.x, this.y, this.z], | ||
| this._invertedLightness | ||
| ); | ||
| } | ||
| get invertedLightness() { | ||
| return this._invertedLightness; | ||
| } | ||
| shiftHue(angle) { | ||
@@ -254,3 +264,2 @@ this.color[0] = (360 + (this.color[0] + angle)) % 360; | ||
| }) { | ||
| this._needsUpdate = true; | ||
| this._positionFunctionX = sinusoidalPosition; | ||
@@ -466,2 +475,3 @@ this._positionFunctionY = sinusoidalPosition; | ||
| this._invertedLightness = newStatus; | ||
| this.anchorPoints.forEach((p) => p.invertedLightness = newStatus); | ||
| this.updateAnchorPairs(); | ||
@@ -468,0 +478,0 @@ } |
+11
-1
@@ -228,2 +228,12 @@ "use strict"; | ||
| } | ||
| set invertedLightness(val) { | ||
| this._invertedLightness = val; | ||
| this.color = pointToHSL( | ||
| [this.x, this.y, this.z], | ||
| this._invertedLightness | ||
| ); | ||
| } | ||
| get invertedLightness() { | ||
| return this._invertedLightness; | ||
| } | ||
| shiftHue(angle) { | ||
@@ -253,3 +263,2 @@ this.color[0] = (360 + (this.color[0] + angle)) % 360; | ||
| }) { | ||
| this._needsUpdate = true; | ||
| this._positionFunctionX = sinusoidalPosition; | ||
@@ -465,2 +474,3 @@ this._positionFunctionY = sinusoidalPosition; | ||
| this._invertedLightness = newStatus; | ||
| this.anchorPoints.forEach((p) => p.invertedLightness = newStatus); | ||
| this.updateAnchorPairs(); | ||
@@ -467,0 +477,0 @@ } |
@@ -1,2 +0,2 @@ | ||
| "use strict";var _=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var X=Object.prototype.hasOwnProperty;var d=Math.pow;var Y=(e,t)=>{for(var o in t)_(e,o,{get:t[o],enumerable:!0})},T=(e,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of G(t))!X.call(e,i)&&i!==o&&_(e,i,{get:()=>t[i],enumerable:!(n=z(t,i))||n.enumerable});return e};var I=e=>T(_({},"__esModule",{value:!0}),e);var U={};Y(U,{Poline:()=>b,PolinePicker:()=>C,positionFunctions:()=>y});module.exports=I(U);var A=(e,t)=>{let[o,n,i]=e,s=.5,l=.5,c=Math.atan2(n-l,o-s)*(180/Math.PI);c=(360+c)%360;let h=i,p=Math.sqrt(Math.pow(n-l,2)+Math.pow(o-s,2))/s;return[c,h,t?1-p:p]},S=(e,t)=>{let[o,n,i]=e,s=.5,l=.5,r=o/(180/Math.PI),c=(t?1-i:i)*s,h=s+c*Math.cos(r),a=l+c*Math.sin(r);return[h,a,n]},L=(e=Math.random()*360,t=[Math.random(),Math.random()],o=[.75+Math.random()*.2,.3+Math.random()*.2])=>[[e,t[0],o[0]],[(e+60+Math.random()*180)%360,t[1],o[1]]];var V=(e,t,o,n=!1,i=(r,c)=>c?1-r:r,s=(r,c)=>c?1-r:r,l=(r,c)=>c?1-r:r)=>{let r=i(e,n),c=s(e,n),h=l(e,n),a=(1-r)*t[0]+r*o[0],p=(1-c)*t[1]+c*o[1],u=(1-h)*t[2]+h*o[2];return[a,p,u]},$=(e,t,o=4,n=!1,i=(r,c)=>c?1-r:r,s=(r,c)=>c?1-r:r,l=(r,c)=>c?1-r:r)=>{let r=[];for(let c=0;c<o;c++){let[h,a,p]=V(c/(o-1),e,t,n,i,s,l);r.push([h,a,p])}return r},Z=e=>e,q=(e,t=!1)=>t?1-d(1-e,2):d(e,2),N=(e,t=!1)=>t?1-d(1-e,3):d(e,3),R=(e,t=!1)=>t?1-d(1-e,4):d(e,4),D=(e,t=!1)=>t?1-d(1-e,5):d(e,5),P=(e,t=!1)=>t?1-Math.sin((1-e)*Math.PI/2):Math.sin(e*Math.PI/2),O=(e,t=!1)=>t?1-Math.asin(1-e)/(Math.PI/2):Math.asin(e)/(Math.PI/2),B=(e,t=!1)=>t?1-Math.sqrt(1-d(e,2)):1-Math.sqrt(1-e),H=e=>d(e,2)*(3-2*e),y={linearPosition:Z,exponentialPosition:q,quadraticPosition:N,cubicPosition:R,quarticPosition:D,sinusoidalPosition:P,asinusoidalPosition:O,arcPosition:B,smoothStepPosition:H},x=(e,t,o=!1)=>{let n=e[0],i=t[0],s=0;o&&n!==null&&i!==null?(s=Math.min(Math.abs(n-i),360-Math.abs(n-i)),s=s/360):s=n===null||i===null?0:n-i;let l=s,r=e[1]===null||t[1]===null?0:t[1]-e[1],c=e[2]===null||t[2]===null?0:t[2]-e[2];return Math.sqrt(l*l+r*r+c*c)},m=class{constructor({xyz:t,color:o,invertedLightness:n=!1}={}){this.x=0;this.y=0;this.z=0;this.color=[0,0,0];this._invertedLightness=!1;this._invertedLightness=n,this.positionOrColor({xyz:t,color:o,invertedLightness:n})}positionOrColor({xyz:t,color:o,invertedLightness:n=!1}){if(this._invertedLightness=n,t&&o||!t&&!o)throw new Error("Point must be initialized with either x,y,z or hsl");t?(this.x=t[0],this.y=t[1],this.z=t[2],this.color=A([this.x,this.y,this.z],n)):o&&(this.color=o,[this.x,this.y,this.z]=S(o,n))}set position([t,o,n]){this.x=t,this.y=o,this.z=n,this.color=A([this.x,this.y,this.z],this._invertedLightness)}get position(){return[this.x,this.y,this.z]}set hsl([t,o,n]){this.color=[t,o,n],[this.x,this.y,this.z]=S(this.color,this._invertedLightness)}get hsl(){return this.color}get hslCSS(){let[t,o,n]=this.color;return`hsl(${t.toFixed(2)}, ${(o*100).toFixed(2)}%, ${(n*100).toFixed(2)}%)`}get oklchCSS(){let[t,o,n]=this.color;return`oklch(${(n*100).toFixed(2)}% ${(o*.4).toFixed(3)} ${t.toFixed(2)})`}get lchCSS(){let[t,o,n]=this.color;return`lch(${(n*100).toFixed(2)}% ${(o*150).toFixed(2)} ${t.toFixed(2)})`}shiftHue(t){this.color[0]=(360+(this.color[0]+t))%360,[this.x,this.y,this.z]=S(this.color,this._invertedLightness)}},b=class{constructor({anchorColors:t=L(),numPoints:o=4,positionFunction:n=P,positionFunctionX:i,positionFunctionY:s,positionFunctionZ:l,closedLoop:r,invertedLightness:c}={anchorColors:L(),numPoints:4,positionFunction:P,closedLoop:!1}){this._needsUpdate=!0;this._positionFunctionX=P;this._positionFunctionY=P;this._positionFunctionZ=P;this.connectLastAndFirstAnchor=!1;this._animationFrame=null;this._invertedLightness=!1;if(!t||t.length<2)throw new Error("Must have at least two anchor colors");this._anchorPoints=t.map(h=>new m({color:h,invertedLightness:c})),this._numPoints=o+2,this._positionFunctionX=i||n||P,this._positionFunctionY=s||n||P,this._positionFunctionZ=l||n||P,this.connectLastAndFirstAnchor=r||!1,this._invertedLightness=c||!1,this.updateAnchorPairs()}get numPoints(){return this._numPoints-2}set numPoints(t){if(t<1)throw new Error("Must have at least one point");this._numPoints=t+2,this.updateAnchorPairs()}set positionFunction(t){if(Array.isArray(t)){if(t.length!==3)throw new Error("Position function array must have 3 elements");if(typeof t[0]!="function"||typeof t[1]!="function"||typeof t[2]!="function")throw new Error("Position function array must have 3 functions");this._positionFunctionX=t[0],this._positionFunctionY=t[1],this._positionFunctionZ=t[2]}else this._positionFunctionX=t,this._positionFunctionY=t,this._positionFunctionZ=t;this.updateAnchorPairs()}get positionFunction(){return this._positionFunctionX===this._positionFunctionY&&this._positionFunctionX===this._positionFunctionZ?this._positionFunctionX:[this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ]}set positionFunctionX(t){this._positionFunctionX=t,this.updateAnchorPairs()}get positionFunctionX(){return this._positionFunctionX}set positionFunctionY(t){this._positionFunctionY=t,this.updateAnchorPairs()}get positionFunctionY(){return this._positionFunctionY}set positionFunctionZ(t){this._positionFunctionZ=t,this.updateAnchorPairs()}get positionFunctionZ(){return this._positionFunctionZ}get anchorPoints(){return this._anchorPoints}set anchorPoints(t){this._anchorPoints=t,this.updateAnchorPairs()}updateAnchorPairs(){this._anchorPairs=[];let t=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1;for(let o=0;o<t;o++){let n=[this.anchorPoints[o],this.anchorPoints[(o+1)%this.anchorPoints.length]];this._anchorPairs.push(n)}this.points=this._anchorPairs.map((o,n)=>{let i=o[0]?o[0].position:[0,0,0],s=o[1]?o[1].position:[0,0,0],l=this.shouldInvertEaseForSegment(n);return $(i,s,this._numPoints,!!l,this.positionFunctionX,this.positionFunctionY,this.positionFunctionZ).map(r=>new m({xyz:r,invertedLightness:this._invertedLightness}))})}addAnchorPoint({xyz:t,color:o,insertAtIndex:n}){let i=new m({xyz:t,color:o,invertedLightness:this._invertedLightness});return n!==void 0?this.anchorPoints.splice(n,0,i):this.anchorPoints.push(i),this.updateAnchorPairs(),i}removeAnchorPoint({point:t,index:o}){if(!t&&o===void 0)throw new Error("Must provide a point or index");if(this.anchorPoints.length<3)throw new Error("Must have at least two anchor points");let n;if(o!==void 0?n=o:t&&(n=this.anchorPoints.indexOf(t)),n>-1&&n<this.anchorPoints.length)this.anchorPoints.splice(n,1),this.updateAnchorPairs();else throw new Error("Point not found")}updateAnchorPoint({point:t,pointIndex:o,xyz:n,color:i}){if(o!==void 0&&(t=this.anchorPoints[o]),!t)throw new Error("Must provide a point or pointIndex");if(!n&&!i)throw new Error("Must provide a new xyz position or color");return n&&(t.position=n),i&&(t.hsl=i),this.updateAnchorPairs(),t}getClosestAnchorPoint({xyz:t,hsl:o,maxDistance:n=1}){if(!t&&!o)throw new Error("Must provide a xyz or hsl");let i;t?i=this.anchorPoints.map(r=>x(r.position,t)):o&&(i=this.anchorPoints.map(r=>x(r.hsl,o,!0)));let s=Math.min(...i);if(s>n)return null;let l=i.indexOf(s);return this.anchorPoints[l]||null}set closedLoop(t){this.connectLastAndFirstAnchor=t,this.updateAnchorPairs()}get closedLoop(){return this.connectLastAndFirstAnchor}set invertedLightness(t){this._invertedLightness=t,this.updateAnchorPairs()}get invertedLightness(){return this._invertedLightness}get flattenedPoints(){return this.points.flat().filter((t,o)=>o!=0?o%this._numPoints:!0)}get colors(){let t=this.flattenedPoints.map(o=>o.color);return this.connectLastAndFirstAnchor&&this._anchorPoints.length!==2&&t.pop(),t}cssColors(t="hsl"){let o={hsl:i=>i.hslCSS,oklch:i=>i.oklchCSS,lch:i=>i.lchCSS},n=this.flattenedPoints.map(o[t]);return this.connectLastAndFirstAnchor&&n.pop(),n}get colorsCSS(){return this.cssColors("hsl")}get colorsCSSlch(){return this.cssColors("lch")}get colorsCSSoklch(){return this.cssColors("oklch")}shiftHue(t=20){this.anchorPoints.forEach(o=>o.shiftHue(t)),this.updateAnchorPairs()}getColorAt(t){var w;if(t<0||t>1)throw new Error("Position must be between 0 and 1");if(this.anchorPoints.length===0)throw new Error("No anchor points available");let o=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1,n=this.connectLastAndFirstAnchor&&this.anchorPoints.length===2?2:o,i=t*n,s=Math.floor(i),l=i-s,r=s>=n?n-1:s,c=s>=n?1:l,h=this._anchorPairs[r];if(!h||h.length<2||!h[0]||!h[1])return new m({color:((w=this.anchorPoints[0])==null?void 0:w.color)||[0,0,0],invertedLightness:this._invertedLightness});let a=h[0].position,p=h[1].position,u=this.shouldInvertEaseForSegment(r),f=V(c,a,p,u,this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ);return new m({xyz:f,invertedLightness:this._invertedLightness})}shouldInvertEaseForSegment(t){return!!(t%2||this.connectLastAndFirstAnchor&&this.anchorPoints.length===2&&t===0)}},{p5:g}=globalThis;if(g&&g.VERSION&&g.VERSION.startsWith("1.")){console.info("p5 < 1.x detected, adding poline to p5 prototype");let e=new b;g.prototype.poline=e;let t=()=>e.colors.map(o=>`hsl(${Math.round(o[0])},${o[1]*100}%,${o[2]*100}%)`);g.prototype.registerMethod("polineColors",t),globalThis.poline=e,globalThis.polineColors=t}var F="http://www.w3.org/2000/svg",v=100,C=class extends HTMLElement{constructor(){super();this.currentPoint=null;this.allowAddPoints=!1;this.boundPointerDown=this.handlePointerDown.bind(this);this.boundPointerMove=this.handlePointerMove.bind(this);this.boundPointerUp=this.handlePointerUp.bind(this);this.attachShadow({mode:"open"}),this.interactive=this.hasAttribute("interactive"),this.allowAddPoints=this.hasAttribute("allow-add-points")}connectedCallback(){this.interactive=this.hasAttribute("interactive"),this.allowAddPoints=this.hasAttribute("allow-add-points"),this.render(),this.interactive&&this.addEventListeners()}disconnectedCallback(){this.removeEventListeners()}setPoline(o){this.poline=o,this.updateSVG(),this.updateLightnessBackground()}setAllowAddPoints(o){this.allowAddPoints=o}addPointAtPosition(o,n){if(!this.poline)return null;let i=o/this.svg.clientWidth,s=n/this.svg.clientHeight,l=this.poline.addAnchorPoint({xyz:[i,s,s]});return this.updateSVG(),this.dispatchPolineChange(),l}updateLightnessBackground(){var n;let o=(n=this.shadowRoot)==null?void 0:n.querySelector(".picker");o&&this.poline&&(this.poline.invertedLightness?(o.style.setProperty("--maxL","#000"),o.style.setProperty("--minL","#fff")):(o.style.setProperty("--maxL","#fff"),o.style.setProperty("--minL","#000")))}render(){if(!this.shadowRoot)return;this.shadowRoot.innerHTML=` | ||
| "use strict";var _=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var X=Object.prototype.hasOwnProperty;var d=Math.pow;var Y=(e,t)=>{for(var o in t)_(e,o,{get:t[o],enumerable:!0})},T=(e,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of G(t))!X.call(e,i)&&i!==o&&_(e,i,{get:()=>t[i],enumerable:!(n=z(t,i))||n.enumerable});return e};var I=e=>T(_({},"__esModule",{value:!0}),e);var U={};Y(U,{Poline:()=>b,PolinePicker:()=>C,positionFunctions:()=>y});module.exports=I(U);var S=(e,t)=>{let[o,n,i]=e,s=.5,h=.5,c=Math.atan2(n-h,o-s)*(180/Math.PI);c=(360+c)%360;let l=i,p=Math.sqrt(Math.pow(n-h,2)+Math.pow(o-s,2))/s;return[c,l,t?1-p:p]},F=(e,t)=>{let[o,n,i]=e,s=.5,h=.5,r=o/(180/Math.PI),c=(t?1-i:i)*s,l=s+c*Math.cos(r),a=h+c*Math.sin(r);return[l,a,n]},A=(e=Math.random()*360,t=[Math.random(),Math.random()],o=[.75+Math.random()*.2,.3+Math.random()*.2])=>[[e,t[0],o[0]],[(e+60+Math.random()*180)%360,t[1],o[1]]];var V=(e,t,o,n=!1,i=(r,c)=>c?1-r:r,s=(r,c)=>c?1-r:r,h=(r,c)=>c?1-r:r)=>{let r=i(e,n),c=s(e,n),l=h(e,n),a=(1-r)*t[0]+r*o[0],p=(1-c)*t[1]+c*o[1],u=(1-l)*t[2]+l*o[2];return[a,p,u]},$=(e,t,o=4,n=!1,i=(r,c)=>c?1-r:r,s=(r,c)=>c?1-r:r,h=(r,c)=>c?1-r:r)=>{let r=[];for(let c=0;c<o;c++){let[l,a,p]=V(c/(o-1),e,t,n,i,s,h);r.push([l,a,p])}return r},Z=e=>e,q=(e,t=!1)=>t?1-d(1-e,2):d(e,2),N=(e,t=!1)=>t?1-d(1-e,3):d(e,3),R=(e,t=!1)=>t?1-d(1-e,4):d(e,4),D=(e,t=!1)=>t?1-d(1-e,5):d(e,5),P=(e,t=!1)=>t?1-Math.sin((1-e)*Math.PI/2):Math.sin(e*Math.PI/2),O=(e,t=!1)=>t?1-Math.asin(1-e)/(Math.PI/2):Math.asin(e)/(Math.PI/2),B=(e,t=!1)=>t?1-Math.sqrt(1-d(e,2)):1-Math.sqrt(1-e),H=e=>d(e,2)*(3-2*e),y={linearPosition:Z,exponentialPosition:q,quadraticPosition:N,cubicPosition:R,quarticPosition:D,sinusoidalPosition:P,asinusoidalPosition:O,arcPosition:B,smoothStepPosition:H},x=(e,t,o=!1)=>{let n=e[0],i=t[0],s=0;o&&n!==null&&i!==null?(s=Math.min(Math.abs(n-i),360-Math.abs(n-i)),s=s/360):s=n===null||i===null?0:n-i;let h=s,r=e[1]===null||t[1]===null?0:t[1]-e[1],c=e[2]===null||t[2]===null?0:t[2]-e[2];return Math.sqrt(h*h+r*r+c*c)},g=class{constructor({xyz:t,color:o,invertedLightness:n=!1}={}){this.x=0;this.y=0;this.z=0;this.color=[0,0,0];this._invertedLightness=!1;this._invertedLightness=n,this.positionOrColor({xyz:t,color:o,invertedLightness:n})}positionOrColor({xyz:t,color:o,invertedLightness:n=!1}){if(this._invertedLightness=n,t&&o||!t&&!o)throw new Error("Point must be initialized with either x,y,z or hsl");t?(this.x=t[0],this.y=t[1],this.z=t[2],this.color=S([this.x,this.y,this.z],n)):o&&(this.color=o,[this.x,this.y,this.z]=F(o,n))}set position([t,o,n]){this.x=t,this.y=o,this.z=n,this.color=S([this.x,this.y,this.z],this._invertedLightness)}get position(){return[this.x,this.y,this.z]}set hsl([t,o,n]){this.color=[t,o,n],[this.x,this.y,this.z]=F(this.color,this._invertedLightness)}get hsl(){return this.color}get hslCSS(){let[t,o,n]=this.color;return`hsl(${t.toFixed(2)}, ${(o*100).toFixed(2)}%, ${(n*100).toFixed(2)}%)`}get oklchCSS(){let[t,o,n]=this.color;return`oklch(${(n*100).toFixed(2)}% ${(o*.4).toFixed(3)} ${t.toFixed(2)})`}get lchCSS(){let[t,o,n]=this.color;return`lch(${(n*100).toFixed(2)}% ${(o*150).toFixed(2)} ${t.toFixed(2)})`}set invertedLightness(t){this._invertedLightness=t,this.color=S([this.x,this.y,this.z],this._invertedLightness)}get invertedLightness(){return this._invertedLightness}shiftHue(t){this.color[0]=(360+(this.color[0]+t))%360,[this.x,this.y,this.z]=F(this.color,this._invertedLightness)}},b=class{constructor({anchorColors:t=A(),numPoints:o=4,positionFunction:n=P,positionFunctionX:i,positionFunctionY:s,positionFunctionZ:h,closedLoop:r,invertedLightness:c}={anchorColors:A(),numPoints:4,positionFunction:P,closedLoop:!1}){this._positionFunctionX=P;this._positionFunctionY=P;this._positionFunctionZ=P;this.connectLastAndFirstAnchor=!1;this._animationFrame=null;this._invertedLightness=!1;if(!t||t.length<2)throw new Error("Must have at least two anchor colors");this._anchorPoints=t.map(l=>new g({color:l,invertedLightness:c})),this._numPoints=o+2,this._positionFunctionX=i||n||P,this._positionFunctionY=s||n||P,this._positionFunctionZ=h||n||P,this.connectLastAndFirstAnchor=r||!1,this._invertedLightness=c||!1,this.updateAnchorPairs()}get numPoints(){return this._numPoints-2}set numPoints(t){if(t<1)throw new Error("Must have at least one point");this._numPoints=t+2,this.updateAnchorPairs()}set positionFunction(t){if(Array.isArray(t)){if(t.length!==3)throw new Error("Position function array must have 3 elements");if(typeof t[0]!="function"||typeof t[1]!="function"||typeof t[2]!="function")throw new Error("Position function array must have 3 functions");this._positionFunctionX=t[0],this._positionFunctionY=t[1],this._positionFunctionZ=t[2]}else this._positionFunctionX=t,this._positionFunctionY=t,this._positionFunctionZ=t;this.updateAnchorPairs()}get positionFunction(){return this._positionFunctionX===this._positionFunctionY&&this._positionFunctionX===this._positionFunctionZ?this._positionFunctionX:[this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ]}set positionFunctionX(t){this._positionFunctionX=t,this.updateAnchorPairs()}get positionFunctionX(){return this._positionFunctionX}set positionFunctionY(t){this._positionFunctionY=t,this.updateAnchorPairs()}get positionFunctionY(){return this._positionFunctionY}set positionFunctionZ(t){this._positionFunctionZ=t,this.updateAnchorPairs()}get positionFunctionZ(){return this._positionFunctionZ}get anchorPoints(){return this._anchorPoints}set anchorPoints(t){this._anchorPoints=t,this.updateAnchorPairs()}updateAnchorPairs(){this._anchorPairs=[];let t=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1;for(let o=0;o<t;o++){let n=[this.anchorPoints[o],this.anchorPoints[(o+1)%this.anchorPoints.length]];this._anchorPairs.push(n)}this.points=this._anchorPairs.map((o,n)=>{let i=o[0]?o[0].position:[0,0,0],s=o[1]?o[1].position:[0,0,0],h=this.shouldInvertEaseForSegment(n);return $(i,s,this._numPoints,!!h,this.positionFunctionX,this.positionFunctionY,this.positionFunctionZ).map(r=>new g({xyz:r,invertedLightness:this._invertedLightness}))})}addAnchorPoint({xyz:t,color:o,insertAtIndex:n}){let i=new g({xyz:t,color:o,invertedLightness:this._invertedLightness});return n!==void 0?this.anchorPoints.splice(n,0,i):this.anchorPoints.push(i),this.updateAnchorPairs(),i}removeAnchorPoint({point:t,index:o}){if(!t&&o===void 0)throw new Error("Must provide a point or index");if(this.anchorPoints.length<3)throw new Error("Must have at least two anchor points");let n;if(o!==void 0?n=o:t&&(n=this.anchorPoints.indexOf(t)),n>-1&&n<this.anchorPoints.length)this.anchorPoints.splice(n,1),this.updateAnchorPairs();else throw new Error("Point not found")}updateAnchorPoint({point:t,pointIndex:o,xyz:n,color:i}){if(o!==void 0&&(t=this.anchorPoints[o]),!t)throw new Error("Must provide a point or pointIndex");if(!n&&!i)throw new Error("Must provide a new xyz position or color");return n&&(t.position=n),i&&(t.hsl=i),this.updateAnchorPairs(),t}getClosestAnchorPoint({xyz:t,hsl:o,maxDistance:n=1}){if(!t&&!o)throw new Error("Must provide a xyz or hsl");let i;t?i=this.anchorPoints.map(r=>x(r.position,t)):o&&(i=this.anchorPoints.map(r=>x(r.hsl,o,!0)));let s=Math.min(...i);if(s>n)return null;let h=i.indexOf(s);return this.anchorPoints[h]||null}set closedLoop(t){this.connectLastAndFirstAnchor=t,this.updateAnchorPairs()}get closedLoop(){return this.connectLastAndFirstAnchor}set invertedLightness(t){this._invertedLightness=t,this.anchorPoints.forEach(o=>o.invertedLightness=t),this.updateAnchorPairs()}get invertedLightness(){return this._invertedLightness}get flattenedPoints(){return this.points.flat().filter((t,o)=>o!=0?o%this._numPoints:!0)}get colors(){let t=this.flattenedPoints.map(o=>o.color);return this.connectLastAndFirstAnchor&&this._anchorPoints.length!==2&&t.pop(),t}cssColors(t="hsl"){let o={hsl:i=>i.hslCSS,oklch:i=>i.oklchCSS,lch:i=>i.lchCSS},n=this.flattenedPoints.map(o[t]);return this.connectLastAndFirstAnchor&&n.pop(),n}get colorsCSS(){return this.cssColors("hsl")}get colorsCSSlch(){return this.cssColors("lch")}get colorsCSSoklch(){return this.cssColors("oklch")}shiftHue(t=20){this.anchorPoints.forEach(o=>o.shiftHue(t)),this.updateAnchorPairs()}getColorAt(t){var w;if(t<0||t>1)throw new Error("Position must be between 0 and 1");if(this.anchorPoints.length===0)throw new Error("No anchor points available");let o=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1,n=this.connectLastAndFirstAnchor&&this.anchorPoints.length===2?2:o,i=t*n,s=Math.floor(i),h=i-s,r=s>=n?n-1:s,c=s>=n?1:h,l=this._anchorPairs[r];if(!l||l.length<2||!l[0]||!l[1])return new g({color:((w=this.anchorPoints[0])==null?void 0:w.color)||[0,0,0],invertedLightness:this._invertedLightness});let a=l[0].position,p=l[1].position,u=this.shouldInvertEaseForSegment(r),f=V(c,a,p,u,this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ);return new g({xyz:f,invertedLightness:this._invertedLightness})}shouldInvertEaseForSegment(t){return!!(t%2||this.connectLastAndFirstAnchor&&this.anchorPoints.length===2&&t===0)}},{p5:m}=globalThis;if(m&&m.VERSION&&m.VERSION.startsWith("1.")){console.info("p5 < 1.x detected, adding poline to p5 prototype");let e=new b;m.prototype.poline=e;let t=()=>e.colors.map(o=>`hsl(${Math.round(o[0])},${o[1]*100}%,${o[2]*100}%)`);m.prototype.registerMethod("polineColors",t),globalThis.poline=e,globalThis.polineColors=t}var L="http://www.w3.org/2000/svg",v=100,C=class extends HTMLElement{constructor(){super();this.currentPoint=null;this.allowAddPoints=!1;this.boundPointerDown=this.handlePointerDown.bind(this);this.boundPointerMove=this.handlePointerMove.bind(this);this.boundPointerUp=this.handlePointerUp.bind(this);this.attachShadow({mode:"open"}),this.interactive=this.hasAttribute("interactive"),this.allowAddPoints=this.hasAttribute("allow-add-points")}connectedCallback(){this.interactive=this.hasAttribute("interactive"),this.allowAddPoints=this.hasAttribute("allow-add-points"),this.render(),this.interactive&&this.addEventListeners()}disconnectedCallback(){this.removeEventListeners()}setPoline(o){this.poline=o,this.updateSVG(),this.updateLightnessBackground()}setAllowAddPoints(o){this.allowAddPoints=o}addPointAtPosition(o,n){if(!this.poline)return null;let i=o/this.svg.clientWidth,s=n/this.svg.clientHeight,h=this.poline.addAnchorPoint({xyz:[i,s,s]});return this.updateSVG(),this.dispatchPolineChange(),h}updateLightnessBackground(){var n;let o=(n=this.shadowRoot)==null?void 0:n.querySelector(".picker");o&&this.poline&&(this.poline.invertedLightness?(o.style.setProperty("--maxL","#000"),o.style.setProperty("--minL","#fff")):(o.style.setProperty("--maxL","#fff"),o.style.setProperty("--minL","#000")))}render(){if(!this.shadowRoot)return;this.shadowRoot.innerHTML=` | ||
| <style> | ||
@@ -52,3 +52,3 @@ :host { | ||
| </style> | ||
| `,this.svg=this.createSVG();let o=document.createElement("div");o.className="picker",o.appendChild(this.svg),this.shadowRoot.appendChild(o),this.wheel=this.svg.querySelector(".wheel"),this.line=this.svg.querySelector(".wheel__line"),this.anchors=this.svg.querySelector(".wheel__anchors"),this.points=this.svg.querySelector(".wheel__points"),this.poline&&(this.updateSVG(),this.updateLightnessBackground())}createSVG(){let o=document.createElementNS(F,"svg");return o.setAttribute("viewBox",`0 0 ${v} ${v}`),o.innerHTML=` | ||
| `,this.svg=this.createSVG();let o=document.createElement("div");o.className="picker",o.appendChild(this.svg),this.shadowRoot.appendChild(o),this.wheel=this.svg.querySelector(".wheel"),this.line=this.svg.querySelector(".wheel__line"),this.anchors=this.svg.querySelector(".wheel__anchors"),this.points=this.svg.querySelector(".wheel__points"),this.poline&&(this.updateSVG(),this.updateLightnessBackground())}createSVG(){let o=document.createElementNS(L,"svg");return o.setAttribute("viewBox",`0 0 ${v} ${v}`),o.innerHTML=` | ||
| <defs> | ||
@@ -66,2 +66,2 @@ <filter id="goo"> | ||
| </g> | ||
| `,o}updateSVG(){if(!this.poline||!this.svg)return;let o=this.poline.flattenedPoints,n=o.map(s=>{let l=this.pointToCartesian(s);if(!l)return"";let[r,c]=l;return`${r},${c}`}).filter(s=>s!=="").join(" ");this.line.setAttribute("points",n);let i=(s,l,r,c)=>{let h=s.children;for(;h.length>l.length;){let a=h[h.length-1];a&&s.removeChild(a)}l.forEach((a,p)=>{let u=h[p],f=this.pointToCartesian(a);if(!f)return;let[w=0,M=0]=f,E=c(a),k=a.hslCSS;u||(u=document.createElementNS(F,"circle"),u.setAttribute("class",r),s.appendChild(u)),u.setAttribute("cx",w.toString()),u.setAttribute("cy",M.toString()),u.setAttribute("r",E.toString()),u.setAttribute("fill",k)})};i(this.anchors,this.poline.anchorPoints,"wheel__anchor",()=>2),i(this.points,o,"wheel__point",s=>.5+s.color[1])}pointToCartesian(o){let n=v/2,i=n+(o.x-.5)*v,s=n+(o.y-.5)*v;return[i,s]}addEventListeners(){this.svg&&(this.svg.addEventListener("pointerdown",this.boundPointerDown),this.svg.addEventListener("pointermove",this.boundPointerMove),this.svg.addEventListener("pointerup",this.boundPointerUp))}removeEventListeners(){this.svg&&(this.svg.removeEventListener("pointerdown",this.boundPointerDown),this.svg.removeEventListener("pointermove",this.boundPointerMove),this.svg.removeEventListener("pointerup",this.boundPointerUp))}handlePointerDown(o){o.stopPropagation();let{normalizedX:n,normalizedY:i}=this.pointerToNormalizedCoordinates(o),s=this.poline.getClosestAnchorPoint({xyz:[n,i,null],maxDistance:.1});s?this.currentPoint=s:this.allowAddPoints&&(this.currentPoint=this.poline.addAnchorPoint({xyz:[n,i,i]}),this.updateSVG(),this.dispatchPolineChange())}handlePointerMove(o){if(this.currentPoint){let{normalizedX:n,normalizedY:i}=this.pointerToNormalizedCoordinates(o);this.poline.updateAnchorPoint({point:this.currentPoint,xyz:[n,i,this.currentPoint.z]}),this.updateSVG(),this.dispatchPolineChange()}}handlePointerUp(){this.currentPoint=null}getPointerPosition(o){let n=this.svg.getBoundingClientRect();return{x:o.clientX-n.left,y:o.clientY-n.top}}pointerToNormalizedCoordinates(o){let n=this.svg.getBoundingClientRect(),i=(o.clientX-n.left)/n.width*v,s=(o.clientY-n.top)/n.height*v;return{normalizedX:i/v,normalizedY:s/v}}createCircleElement(o,n,i){let s=this.pointToCartesian(o);if(!s)return null;let[l=0,r=0]=s,c=document.createElementNS(F,"circle");return c.setAttribute("class",n),c.setAttribute("cx",l.toString()),c.setAttribute("cy",r.toString()),c.setAttribute("r",i.toString()),c.setAttribute("fill",o.hslCSS),c}dispatchPolineChange(){this.dispatchEvent(new CustomEvent("poline-change",{detail:{poline:this.poline}}))}};customElements.define("poline-picker",C); | ||
| `,o}updateSVG(){if(!this.poline||!this.svg)return;let o=this.poline.flattenedPoints,n=o.map(s=>{let h=this.pointToCartesian(s);if(!h)return"";let[r,c]=h;return`${r},${c}`}).filter(s=>s!=="").join(" ");this.line.setAttribute("points",n);let i=(s,h,r,c)=>{let l=s.children;for(;l.length>h.length;){let a=l[l.length-1];a&&s.removeChild(a)}h.forEach((a,p)=>{let u=l[p],f=this.pointToCartesian(a);if(!f)return;let[w=0,M=0]=f,E=c(a),k=a.hslCSS;u||(u=document.createElementNS(L,"circle"),u.setAttribute("class",r),s.appendChild(u)),u.setAttribute("cx",w.toString()),u.setAttribute("cy",M.toString()),u.setAttribute("r",E.toString()),u.setAttribute("fill",k)})};i(this.anchors,this.poline.anchorPoints,"wheel__anchor",()=>2),i(this.points,o,"wheel__point",s=>.5+s.color[1])}pointToCartesian(o){let n=v/2,i=n+(o.x-.5)*v,s=n+(o.y-.5)*v;return[i,s]}addEventListeners(){this.svg&&(this.svg.addEventListener("pointerdown",this.boundPointerDown),this.svg.addEventListener("pointermove",this.boundPointerMove),this.svg.addEventListener("pointerup",this.boundPointerUp))}removeEventListeners(){this.svg&&(this.svg.removeEventListener("pointerdown",this.boundPointerDown),this.svg.removeEventListener("pointermove",this.boundPointerMove),this.svg.removeEventListener("pointerup",this.boundPointerUp))}handlePointerDown(o){o.stopPropagation();let{normalizedX:n,normalizedY:i}=this.pointerToNormalizedCoordinates(o),s=this.poline.getClosestAnchorPoint({xyz:[n,i,null],maxDistance:.1});s?this.currentPoint=s:this.allowAddPoints&&(this.currentPoint=this.poline.addAnchorPoint({xyz:[n,i,i]}),this.updateSVG(),this.dispatchPolineChange())}handlePointerMove(o){if(this.currentPoint){let{normalizedX:n,normalizedY:i}=this.pointerToNormalizedCoordinates(o);this.poline.updateAnchorPoint({point:this.currentPoint,xyz:[n,i,this.currentPoint.z]}),this.updateSVG(),this.dispatchPolineChange()}}handlePointerUp(){this.currentPoint=null}getPointerPosition(o){let n=this.svg.getBoundingClientRect();return{x:o.clientX-n.left,y:o.clientY-n.top}}pointerToNormalizedCoordinates(o){let n=this.svg.getBoundingClientRect(),i=(o.clientX-n.left)/n.width*v,s=(o.clientY-n.top)/n.height*v;return{normalizedX:i/v,normalizedY:s/v}}createCircleElement(o,n,i){let s=this.pointToCartesian(o);if(!s)return null;let[h=0,r=0]=s,c=document.createElementNS(L,"circle");return c.setAttribute("class",n),c.setAttribute("cx",h.toString()),c.setAttribute("cy",r.toString()),c.setAttribute("r",i.toString()),c.setAttribute("fill",o.hslCSS),c}dispatchPolineChange(){this.dispatchEvent(new CustomEvent("poline-change",{detail:{poline:this.poline}}))}};customElements.define("poline-picker",C); |
@@ -1,2 +0,2 @@ | ||
| "use strict";var polinePicker=(()=>{var _=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var X=Object.prototype.hasOwnProperty;var d=Math.pow;var Y=(e,t)=>{for(var o in t)_(e,o,{get:t[o],enumerable:!0})},T=(e,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of G(t))!X.call(e,i)&&i!==o&&_(e,i,{get:()=>t[i],enumerable:!(n=z(t,i))||n.enumerable});return e};var I=e=>T(_({},"__esModule",{value:!0}),e);var U={};Y(U,{Poline:()=>b,PolinePicker:()=>C,positionFunctions:()=>y});var A=(e,t)=>{let[o,n,i]=e,s=.5,l=.5,c=Math.atan2(n-l,o-s)*(180/Math.PI);c=(360+c)%360;let h=i,p=Math.sqrt(Math.pow(n-l,2)+Math.pow(o-s,2))/s;return[c,h,t?1-p:p]},S=(e,t)=>{let[o,n,i]=e,s=.5,l=.5,r=o/(180/Math.PI),c=(t?1-i:i)*s,h=s+c*Math.cos(r),a=l+c*Math.sin(r);return[h,a,n]},L=(e=Math.random()*360,t=[Math.random(),Math.random()],o=[.75+Math.random()*.2,.3+Math.random()*.2])=>[[e,t[0],o[0]],[(e+60+Math.random()*180)%360,t[1],o[1]]];var V=(e,t,o,n=!1,i=(r,c)=>c?1-r:r,s=(r,c)=>c?1-r:r,l=(r,c)=>c?1-r:r)=>{let r=i(e,n),c=s(e,n),h=l(e,n),a=(1-r)*t[0]+r*o[0],p=(1-c)*t[1]+c*o[1],u=(1-h)*t[2]+h*o[2];return[a,p,u]},$=(e,t,o=4,n=!1,i=(r,c)=>c?1-r:r,s=(r,c)=>c?1-r:r,l=(r,c)=>c?1-r:r)=>{let r=[];for(let c=0;c<o;c++){let[h,a,p]=V(c/(o-1),e,t,n,i,s,l);r.push([h,a,p])}return r},Z=e=>e,q=(e,t=!1)=>t?1-d(1-e,2):d(e,2),N=(e,t=!1)=>t?1-d(1-e,3):d(e,3),R=(e,t=!1)=>t?1-d(1-e,4):d(e,4),D=(e,t=!1)=>t?1-d(1-e,5):d(e,5),P=(e,t=!1)=>t?1-Math.sin((1-e)*Math.PI/2):Math.sin(e*Math.PI/2),O=(e,t=!1)=>t?1-Math.asin(1-e)/(Math.PI/2):Math.asin(e)/(Math.PI/2),B=(e,t=!1)=>t?1-Math.sqrt(1-d(e,2)):1-Math.sqrt(1-e),H=e=>d(e,2)*(3-2*e),y={linearPosition:Z,exponentialPosition:q,quadraticPosition:N,cubicPosition:R,quarticPosition:D,sinusoidalPosition:P,asinusoidalPosition:O,arcPosition:B,smoothStepPosition:H},x=(e,t,o=!1)=>{let n=e[0],i=t[0],s=0;o&&n!==null&&i!==null?(s=Math.min(Math.abs(n-i),360-Math.abs(n-i)),s=s/360):s=n===null||i===null?0:n-i;let l=s,r=e[1]===null||t[1]===null?0:t[1]-e[1],c=e[2]===null||t[2]===null?0:t[2]-e[2];return Math.sqrt(l*l+r*r+c*c)},m=class{constructor({xyz:t,color:o,invertedLightness:n=!1}={}){this.x=0;this.y=0;this.z=0;this.color=[0,0,0];this._invertedLightness=!1;this._invertedLightness=n,this.positionOrColor({xyz:t,color:o,invertedLightness:n})}positionOrColor({xyz:t,color:o,invertedLightness:n=!1}){if(this._invertedLightness=n,t&&o||!t&&!o)throw new Error("Point must be initialized with either x,y,z or hsl");t?(this.x=t[0],this.y=t[1],this.z=t[2],this.color=A([this.x,this.y,this.z],n)):o&&(this.color=o,[this.x,this.y,this.z]=S(o,n))}set position([t,o,n]){this.x=t,this.y=o,this.z=n,this.color=A([this.x,this.y,this.z],this._invertedLightness)}get position(){return[this.x,this.y,this.z]}set hsl([t,o,n]){this.color=[t,o,n],[this.x,this.y,this.z]=S(this.color,this._invertedLightness)}get hsl(){return this.color}get hslCSS(){let[t,o,n]=this.color;return`hsl(${t.toFixed(2)}, ${(o*100).toFixed(2)}%, ${(n*100).toFixed(2)}%)`}get oklchCSS(){let[t,o,n]=this.color;return`oklch(${(n*100).toFixed(2)}% ${(o*.4).toFixed(3)} ${t.toFixed(2)})`}get lchCSS(){let[t,o,n]=this.color;return`lch(${(n*100).toFixed(2)}% ${(o*150).toFixed(2)} ${t.toFixed(2)})`}shiftHue(t){this.color[0]=(360+(this.color[0]+t))%360,[this.x,this.y,this.z]=S(this.color,this._invertedLightness)}},b=class{constructor({anchorColors:t=L(),numPoints:o=4,positionFunction:n=P,positionFunctionX:i,positionFunctionY:s,positionFunctionZ:l,closedLoop:r,invertedLightness:c}={anchorColors:L(),numPoints:4,positionFunction:P,closedLoop:!1}){this._needsUpdate=!0;this._positionFunctionX=P;this._positionFunctionY=P;this._positionFunctionZ=P;this.connectLastAndFirstAnchor=!1;this._animationFrame=null;this._invertedLightness=!1;if(!t||t.length<2)throw new Error("Must have at least two anchor colors");this._anchorPoints=t.map(h=>new m({color:h,invertedLightness:c})),this._numPoints=o+2,this._positionFunctionX=i||n||P,this._positionFunctionY=s||n||P,this._positionFunctionZ=l||n||P,this.connectLastAndFirstAnchor=r||!1,this._invertedLightness=c||!1,this.updateAnchorPairs()}get numPoints(){return this._numPoints-2}set numPoints(t){if(t<1)throw new Error("Must have at least one point");this._numPoints=t+2,this.updateAnchorPairs()}set positionFunction(t){if(Array.isArray(t)){if(t.length!==3)throw new Error("Position function array must have 3 elements");if(typeof t[0]!="function"||typeof t[1]!="function"||typeof t[2]!="function")throw new Error("Position function array must have 3 functions");this._positionFunctionX=t[0],this._positionFunctionY=t[1],this._positionFunctionZ=t[2]}else this._positionFunctionX=t,this._positionFunctionY=t,this._positionFunctionZ=t;this.updateAnchorPairs()}get positionFunction(){return this._positionFunctionX===this._positionFunctionY&&this._positionFunctionX===this._positionFunctionZ?this._positionFunctionX:[this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ]}set positionFunctionX(t){this._positionFunctionX=t,this.updateAnchorPairs()}get positionFunctionX(){return this._positionFunctionX}set positionFunctionY(t){this._positionFunctionY=t,this.updateAnchorPairs()}get positionFunctionY(){return this._positionFunctionY}set positionFunctionZ(t){this._positionFunctionZ=t,this.updateAnchorPairs()}get positionFunctionZ(){return this._positionFunctionZ}get anchorPoints(){return this._anchorPoints}set anchorPoints(t){this._anchorPoints=t,this.updateAnchorPairs()}updateAnchorPairs(){this._anchorPairs=[];let t=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1;for(let o=0;o<t;o++){let n=[this.anchorPoints[o],this.anchorPoints[(o+1)%this.anchorPoints.length]];this._anchorPairs.push(n)}this.points=this._anchorPairs.map((o,n)=>{let i=o[0]?o[0].position:[0,0,0],s=o[1]?o[1].position:[0,0,0],l=this.shouldInvertEaseForSegment(n);return $(i,s,this._numPoints,!!l,this.positionFunctionX,this.positionFunctionY,this.positionFunctionZ).map(r=>new m({xyz:r,invertedLightness:this._invertedLightness}))})}addAnchorPoint({xyz:t,color:o,insertAtIndex:n}){let i=new m({xyz:t,color:o,invertedLightness:this._invertedLightness});return n!==void 0?this.anchorPoints.splice(n,0,i):this.anchorPoints.push(i),this.updateAnchorPairs(),i}removeAnchorPoint({point:t,index:o}){if(!t&&o===void 0)throw new Error("Must provide a point or index");if(this.anchorPoints.length<3)throw new Error("Must have at least two anchor points");let n;if(o!==void 0?n=o:t&&(n=this.anchorPoints.indexOf(t)),n>-1&&n<this.anchorPoints.length)this.anchorPoints.splice(n,1),this.updateAnchorPairs();else throw new Error("Point not found")}updateAnchorPoint({point:t,pointIndex:o,xyz:n,color:i}){if(o!==void 0&&(t=this.anchorPoints[o]),!t)throw new Error("Must provide a point or pointIndex");if(!n&&!i)throw new Error("Must provide a new xyz position or color");return n&&(t.position=n),i&&(t.hsl=i),this.updateAnchorPairs(),t}getClosestAnchorPoint({xyz:t,hsl:o,maxDistance:n=1}){if(!t&&!o)throw new Error("Must provide a xyz or hsl");let i;t?i=this.anchorPoints.map(r=>x(r.position,t)):o&&(i=this.anchorPoints.map(r=>x(r.hsl,o,!0)));let s=Math.min(...i);if(s>n)return null;let l=i.indexOf(s);return this.anchorPoints[l]||null}set closedLoop(t){this.connectLastAndFirstAnchor=t,this.updateAnchorPairs()}get closedLoop(){return this.connectLastAndFirstAnchor}set invertedLightness(t){this._invertedLightness=t,this.updateAnchorPairs()}get invertedLightness(){return this._invertedLightness}get flattenedPoints(){return this.points.flat().filter((t,o)=>o!=0?o%this._numPoints:!0)}get colors(){let t=this.flattenedPoints.map(o=>o.color);return this.connectLastAndFirstAnchor&&this._anchorPoints.length!==2&&t.pop(),t}cssColors(t="hsl"){let o={hsl:i=>i.hslCSS,oklch:i=>i.oklchCSS,lch:i=>i.lchCSS},n=this.flattenedPoints.map(o[t]);return this.connectLastAndFirstAnchor&&n.pop(),n}get colorsCSS(){return this.cssColors("hsl")}get colorsCSSlch(){return this.cssColors("lch")}get colorsCSSoklch(){return this.cssColors("oklch")}shiftHue(t=20){this.anchorPoints.forEach(o=>o.shiftHue(t)),this.updateAnchorPairs()}getColorAt(t){var w;if(t<0||t>1)throw new Error("Position must be between 0 and 1");if(this.anchorPoints.length===0)throw new Error("No anchor points available");let o=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1,n=this.connectLastAndFirstAnchor&&this.anchorPoints.length===2?2:o,i=t*n,s=Math.floor(i),l=i-s,r=s>=n?n-1:s,c=s>=n?1:l,h=this._anchorPairs[r];if(!h||h.length<2||!h[0]||!h[1])return new m({color:((w=this.anchorPoints[0])==null?void 0:w.color)||[0,0,0],invertedLightness:this._invertedLightness});let a=h[0].position,p=h[1].position,u=this.shouldInvertEaseForSegment(r),f=V(c,a,p,u,this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ);return new m({xyz:f,invertedLightness:this._invertedLightness})}shouldInvertEaseForSegment(t){return!!(t%2||this.connectLastAndFirstAnchor&&this.anchorPoints.length===2&&t===0)}},{p5:g}=globalThis;if(g&&g.VERSION&&g.VERSION.startsWith("1.")){console.info("p5 < 1.x detected, adding poline to p5 prototype");let e=new b;g.prototype.poline=e;let t=()=>e.colors.map(o=>`hsl(${Math.round(o[0])},${o[1]*100}%,${o[2]*100}%)`);g.prototype.registerMethod("polineColors",t),globalThis.poline=e,globalThis.polineColors=t}var F="http://www.w3.org/2000/svg",v=100,C=class extends HTMLElement{constructor(){super();this.currentPoint=null;this.allowAddPoints=!1;this.boundPointerDown=this.handlePointerDown.bind(this);this.boundPointerMove=this.handlePointerMove.bind(this);this.boundPointerUp=this.handlePointerUp.bind(this);this.attachShadow({mode:"open"}),this.interactive=this.hasAttribute("interactive"),this.allowAddPoints=this.hasAttribute("allow-add-points")}connectedCallback(){this.interactive=this.hasAttribute("interactive"),this.allowAddPoints=this.hasAttribute("allow-add-points"),this.render(),this.interactive&&this.addEventListeners()}disconnectedCallback(){this.removeEventListeners()}setPoline(o){this.poline=o,this.updateSVG(),this.updateLightnessBackground()}setAllowAddPoints(o){this.allowAddPoints=o}addPointAtPosition(o,n){if(!this.poline)return null;let i=o/this.svg.clientWidth,s=n/this.svg.clientHeight,l=this.poline.addAnchorPoint({xyz:[i,s,s]});return this.updateSVG(),this.dispatchPolineChange(),l}updateLightnessBackground(){var n;let o=(n=this.shadowRoot)==null?void 0:n.querySelector(".picker");o&&this.poline&&(this.poline.invertedLightness?(o.style.setProperty("--maxL","#000"),o.style.setProperty("--minL","#fff")):(o.style.setProperty("--maxL","#fff"),o.style.setProperty("--minL","#000")))}render(){if(!this.shadowRoot)return;this.shadowRoot.innerHTML=` | ||
| "use strict";var polinePicker=(()=>{var _=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var X=Object.prototype.hasOwnProperty;var d=Math.pow;var Y=(e,t)=>{for(var o in t)_(e,o,{get:t[o],enumerable:!0})},T=(e,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of G(t))!X.call(e,i)&&i!==o&&_(e,i,{get:()=>t[i],enumerable:!(n=z(t,i))||n.enumerable});return e};var I=e=>T(_({},"__esModule",{value:!0}),e);var U={};Y(U,{Poline:()=>b,PolinePicker:()=>C,positionFunctions:()=>y});var S=(e,t)=>{let[o,n,i]=e,s=.5,h=.5,c=Math.atan2(n-h,o-s)*(180/Math.PI);c=(360+c)%360;let l=i,p=Math.sqrt(Math.pow(n-h,2)+Math.pow(o-s,2))/s;return[c,l,t?1-p:p]},F=(e,t)=>{let[o,n,i]=e,s=.5,h=.5,r=o/(180/Math.PI),c=(t?1-i:i)*s,l=s+c*Math.cos(r),a=h+c*Math.sin(r);return[l,a,n]},A=(e=Math.random()*360,t=[Math.random(),Math.random()],o=[.75+Math.random()*.2,.3+Math.random()*.2])=>[[e,t[0],o[0]],[(e+60+Math.random()*180)%360,t[1],o[1]]];var V=(e,t,o,n=!1,i=(r,c)=>c?1-r:r,s=(r,c)=>c?1-r:r,h=(r,c)=>c?1-r:r)=>{let r=i(e,n),c=s(e,n),l=h(e,n),a=(1-r)*t[0]+r*o[0],p=(1-c)*t[1]+c*o[1],u=(1-l)*t[2]+l*o[2];return[a,p,u]},$=(e,t,o=4,n=!1,i=(r,c)=>c?1-r:r,s=(r,c)=>c?1-r:r,h=(r,c)=>c?1-r:r)=>{let r=[];for(let c=0;c<o;c++){let[l,a,p]=V(c/(o-1),e,t,n,i,s,h);r.push([l,a,p])}return r},Z=e=>e,q=(e,t=!1)=>t?1-d(1-e,2):d(e,2),N=(e,t=!1)=>t?1-d(1-e,3):d(e,3),R=(e,t=!1)=>t?1-d(1-e,4):d(e,4),D=(e,t=!1)=>t?1-d(1-e,5):d(e,5),P=(e,t=!1)=>t?1-Math.sin((1-e)*Math.PI/2):Math.sin(e*Math.PI/2),O=(e,t=!1)=>t?1-Math.asin(1-e)/(Math.PI/2):Math.asin(e)/(Math.PI/2),B=(e,t=!1)=>t?1-Math.sqrt(1-d(e,2)):1-Math.sqrt(1-e),H=e=>d(e,2)*(3-2*e),y={linearPosition:Z,exponentialPosition:q,quadraticPosition:N,cubicPosition:R,quarticPosition:D,sinusoidalPosition:P,asinusoidalPosition:O,arcPosition:B,smoothStepPosition:H},x=(e,t,o=!1)=>{let n=e[0],i=t[0],s=0;o&&n!==null&&i!==null?(s=Math.min(Math.abs(n-i),360-Math.abs(n-i)),s=s/360):s=n===null||i===null?0:n-i;let h=s,r=e[1]===null||t[1]===null?0:t[1]-e[1],c=e[2]===null||t[2]===null?0:t[2]-e[2];return Math.sqrt(h*h+r*r+c*c)},g=class{constructor({xyz:t,color:o,invertedLightness:n=!1}={}){this.x=0;this.y=0;this.z=0;this.color=[0,0,0];this._invertedLightness=!1;this._invertedLightness=n,this.positionOrColor({xyz:t,color:o,invertedLightness:n})}positionOrColor({xyz:t,color:o,invertedLightness:n=!1}){if(this._invertedLightness=n,t&&o||!t&&!o)throw new Error("Point must be initialized with either x,y,z or hsl");t?(this.x=t[0],this.y=t[1],this.z=t[2],this.color=S([this.x,this.y,this.z],n)):o&&(this.color=o,[this.x,this.y,this.z]=F(o,n))}set position([t,o,n]){this.x=t,this.y=o,this.z=n,this.color=S([this.x,this.y,this.z],this._invertedLightness)}get position(){return[this.x,this.y,this.z]}set hsl([t,o,n]){this.color=[t,o,n],[this.x,this.y,this.z]=F(this.color,this._invertedLightness)}get hsl(){return this.color}get hslCSS(){let[t,o,n]=this.color;return`hsl(${t.toFixed(2)}, ${(o*100).toFixed(2)}%, ${(n*100).toFixed(2)}%)`}get oklchCSS(){let[t,o,n]=this.color;return`oklch(${(n*100).toFixed(2)}% ${(o*.4).toFixed(3)} ${t.toFixed(2)})`}get lchCSS(){let[t,o,n]=this.color;return`lch(${(n*100).toFixed(2)}% ${(o*150).toFixed(2)} ${t.toFixed(2)})`}set invertedLightness(t){this._invertedLightness=t,this.color=S([this.x,this.y,this.z],this._invertedLightness)}get invertedLightness(){return this._invertedLightness}shiftHue(t){this.color[0]=(360+(this.color[0]+t))%360,[this.x,this.y,this.z]=F(this.color,this._invertedLightness)}},b=class{constructor({anchorColors:t=A(),numPoints:o=4,positionFunction:n=P,positionFunctionX:i,positionFunctionY:s,positionFunctionZ:h,closedLoop:r,invertedLightness:c}={anchorColors:A(),numPoints:4,positionFunction:P,closedLoop:!1}){this._positionFunctionX=P;this._positionFunctionY=P;this._positionFunctionZ=P;this.connectLastAndFirstAnchor=!1;this._animationFrame=null;this._invertedLightness=!1;if(!t||t.length<2)throw new Error("Must have at least two anchor colors");this._anchorPoints=t.map(l=>new g({color:l,invertedLightness:c})),this._numPoints=o+2,this._positionFunctionX=i||n||P,this._positionFunctionY=s||n||P,this._positionFunctionZ=h||n||P,this.connectLastAndFirstAnchor=r||!1,this._invertedLightness=c||!1,this.updateAnchorPairs()}get numPoints(){return this._numPoints-2}set numPoints(t){if(t<1)throw new Error("Must have at least one point");this._numPoints=t+2,this.updateAnchorPairs()}set positionFunction(t){if(Array.isArray(t)){if(t.length!==3)throw new Error("Position function array must have 3 elements");if(typeof t[0]!="function"||typeof t[1]!="function"||typeof t[2]!="function")throw new Error("Position function array must have 3 functions");this._positionFunctionX=t[0],this._positionFunctionY=t[1],this._positionFunctionZ=t[2]}else this._positionFunctionX=t,this._positionFunctionY=t,this._positionFunctionZ=t;this.updateAnchorPairs()}get positionFunction(){return this._positionFunctionX===this._positionFunctionY&&this._positionFunctionX===this._positionFunctionZ?this._positionFunctionX:[this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ]}set positionFunctionX(t){this._positionFunctionX=t,this.updateAnchorPairs()}get positionFunctionX(){return this._positionFunctionX}set positionFunctionY(t){this._positionFunctionY=t,this.updateAnchorPairs()}get positionFunctionY(){return this._positionFunctionY}set positionFunctionZ(t){this._positionFunctionZ=t,this.updateAnchorPairs()}get positionFunctionZ(){return this._positionFunctionZ}get anchorPoints(){return this._anchorPoints}set anchorPoints(t){this._anchorPoints=t,this.updateAnchorPairs()}updateAnchorPairs(){this._anchorPairs=[];let t=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1;for(let o=0;o<t;o++){let n=[this.anchorPoints[o],this.anchorPoints[(o+1)%this.anchorPoints.length]];this._anchorPairs.push(n)}this.points=this._anchorPairs.map((o,n)=>{let i=o[0]?o[0].position:[0,0,0],s=o[1]?o[1].position:[0,0,0],h=this.shouldInvertEaseForSegment(n);return $(i,s,this._numPoints,!!h,this.positionFunctionX,this.positionFunctionY,this.positionFunctionZ).map(r=>new g({xyz:r,invertedLightness:this._invertedLightness}))})}addAnchorPoint({xyz:t,color:o,insertAtIndex:n}){let i=new g({xyz:t,color:o,invertedLightness:this._invertedLightness});return n!==void 0?this.anchorPoints.splice(n,0,i):this.anchorPoints.push(i),this.updateAnchorPairs(),i}removeAnchorPoint({point:t,index:o}){if(!t&&o===void 0)throw new Error("Must provide a point or index");if(this.anchorPoints.length<3)throw new Error("Must have at least two anchor points");let n;if(o!==void 0?n=o:t&&(n=this.anchorPoints.indexOf(t)),n>-1&&n<this.anchorPoints.length)this.anchorPoints.splice(n,1),this.updateAnchorPairs();else throw new Error("Point not found")}updateAnchorPoint({point:t,pointIndex:o,xyz:n,color:i}){if(o!==void 0&&(t=this.anchorPoints[o]),!t)throw new Error("Must provide a point or pointIndex");if(!n&&!i)throw new Error("Must provide a new xyz position or color");return n&&(t.position=n),i&&(t.hsl=i),this.updateAnchorPairs(),t}getClosestAnchorPoint({xyz:t,hsl:o,maxDistance:n=1}){if(!t&&!o)throw new Error("Must provide a xyz or hsl");let i;t?i=this.anchorPoints.map(r=>x(r.position,t)):o&&(i=this.anchorPoints.map(r=>x(r.hsl,o,!0)));let s=Math.min(...i);if(s>n)return null;let h=i.indexOf(s);return this.anchorPoints[h]||null}set closedLoop(t){this.connectLastAndFirstAnchor=t,this.updateAnchorPairs()}get closedLoop(){return this.connectLastAndFirstAnchor}set invertedLightness(t){this._invertedLightness=t,this.anchorPoints.forEach(o=>o.invertedLightness=t),this.updateAnchorPairs()}get invertedLightness(){return this._invertedLightness}get flattenedPoints(){return this.points.flat().filter((t,o)=>o!=0?o%this._numPoints:!0)}get colors(){let t=this.flattenedPoints.map(o=>o.color);return this.connectLastAndFirstAnchor&&this._anchorPoints.length!==2&&t.pop(),t}cssColors(t="hsl"){let o={hsl:i=>i.hslCSS,oklch:i=>i.oklchCSS,lch:i=>i.lchCSS},n=this.flattenedPoints.map(o[t]);return this.connectLastAndFirstAnchor&&n.pop(),n}get colorsCSS(){return this.cssColors("hsl")}get colorsCSSlch(){return this.cssColors("lch")}get colorsCSSoklch(){return this.cssColors("oklch")}shiftHue(t=20){this.anchorPoints.forEach(o=>o.shiftHue(t)),this.updateAnchorPairs()}getColorAt(t){var w;if(t<0||t>1)throw new Error("Position must be between 0 and 1");if(this.anchorPoints.length===0)throw new Error("No anchor points available");let o=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1,n=this.connectLastAndFirstAnchor&&this.anchorPoints.length===2?2:o,i=t*n,s=Math.floor(i),h=i-s,r=s>=n?n-1:s,c=s>=n?1:h,l=this._anchorPairs[r];if(!l||l.length<2||!l[0]||!l[1])return new g({color:((w=this.anchorPoints[0])==null?void 0:w.color)||[0,0,0],invertedLightness:this._invertedLightness});let a=l[0].position,p=l[1].position,u=this.shouldInvertEaseForSegment(r),f=V(c,a,p,u,this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ);return new g({xyz:f,invertedLightness:this._invertedLightness})}shouldInvertEaseForSegment(t){return!!(t%2||this.connectLastAndFirstAnchor&&this.anchorPoints.length===2&&t===0)}},{p5:m}=globalThis;if(m&&m.VERSION&&m.VERSION.startsWith("1.")){console.info("p5 < 1.x detected, adding poline to p5 prototype");let e=new b;m.prototype.poline=e;let t=()=>e.colors.map(o=>`hsl(${Math.round(o[0])},${o[1]*100}%,${o[2]*100}%)`);m.prototype.registerMethod("polineColors",t),globalThis.poline=e,globalThis.polineColors=t}var L="http://www.w3.org/2000/svg",v=100,C=class extends HTMLElement{constructor(){super();this.currentPoint=null;this.allowAddPoints=!1;this.boundPointerDown=this.handlePointerDown.bind(this);this.boundPointerMove=this.handlePointerMove.bind(this);this.boundPointerUp=this.handlePointerUp.bind(this);this.attachShadow({mode:"open"}),this.interactive=this.hasAttribute("interactive"),this.allowAddPoints=this.hasAttribute("allow-add-points")}connectedCallback(){this.interactive=this.hasAttribute("interactive"),this.allowAddPoints=this.hasAttribute("allow-add-points"),this.render(),this.interactive&&this.addEventListeners()}disconnectedCallback(){this.removeEventListeners()}setPoline(o){this.poline=o,this.updateSVG(),this.updateLightnessBackground()}setAllowAddPoints(o){this.allowAddPoints=o}addPointAtPosition(o,n){if(!this.poline)return null;let i=o/this.svg.clientWidth,s=n/this.svg.clientHeight,h=this.poline.addAnchorPoint({xyz:[i,s,s]});return this.updateSVG(),this.dispatchPolineChange(),h}updateLightnessBackground(){var n;let o=(n=this.shadowRoot)==null?void 0:n.querySelector(".picker");o&&this.poline&&(this.poline.invertedLightness?(o.style.setProperty("--maxL","#000"),o.style.setProperty("--minL","#fff")):(o.style.setProperty("--maxL","#fff"),o.style.setProperty("--minL","#000")))}render(){if(!this.shadowRoot)return;this.shadowRoot.innerHTML=` | ||
| <style> | ||
@@ -52,3 +52,3 @@ :host { | ||
| </style> | ||
| `,this.svg=this.createSVG();let o=document.createElement("div");o.className="picker",o.appendChild(this.svg),this.shadowRoot.appendChild(o),this.wheel=this.svg.querySelector(".wheel"),this.line=this.svg.querySelector(".wheel__line"),this.anchors=this.svg.querySelector(".wheel__anchors"),this.points=this.svg.querySelector(".wheel__points"),this.poline&&(this.updateSVG(),this.updateLightnessBackground())}createSVG(){let o=document.createElementNS(F,"svg");return o.setAttribute("viewBox",`0 0 ${v} ${v}`),o.innerHTML=` | ||
| `,this.svg=this.createSVG();let o=document.createElement("div");o.className="picker",o.appendChild(this.svg),this.shadowRoot.appendChild(o),this.wheel=this.svg.querySelector(".wheel"),this.line=this.svg.querySelector(".wheel__line"),this.anchors=this.svg.querySelector(".wheel__anchors"),this.points=this.svg.querySelector(".wheel__points"),this.poline&&(this.updateSVG(),this.updateLightnessBackground())}createSVG(){let o=document.createElementNS(L,"svg");return o.setAttribute("viewBox",`0 0 ${v} ${v}`),o.innerHTML=` | ||
| <defs> | ||
@@ -66,2 +66,2 @@ <filter id="goo"> | ||
| </g> | ||
| `,o}updateSVG(){if(!this.poline||!this.svg)return;let o=this.poline.flattenedPoints,n=o.map(s=>{let l=this.pointToCartesian(s);if(!l)return"";let[r,c]=l;return`${r},${c}`}).filter(s=>s!=="").join(" ");this.line.setAttribute("points",n);let i=(s,l,r,c)=>{let h=s.children;for(;h.length>l.length;){let a=h[h.length-1];a&&s.removeChild(a)}l.forEach((a,p)=>{let u=h[p],f=this.pointToCartesian(a);if(!f)return;let[w=0,M=0]=f,E=c(a),k=a.hslCSS;u||(u=document.createElementNS(F,"circle"),u.setAttribute("class",r),s.appendChild(u)),u.setAttribute("cx",w.toString()),u.setAttribute("cy",M.toString()),u.setAttribute("r",E.toString()),u.setAttribute("fill",k)})};i(this.anchors,this.poline.anchorPoints,"wheel__anchor",()=>2),i(this.points,o,"wheel__point",s=>.5+s.color[1])}pointToCartesian(o){let n=v/2,i=n+(o.x-.5)*v,s=n+(o.y-.5)*v;return[i,s]}addEventListeners(){this.svg&&(this.svg.addEventListener("pointerdown",this.boundPointerDown),this.svg.addEventListener("pointermove",this.boundPointerMove),this.svg.addEventListener("pointerup",this.boundPointerUp))}removeEventListeners(){this.svg&&(this.svg.removeEventListener("pointerdown",this.boundPointerDown),this.svg.removeEventListener("pointermove",this.boundPointerMove),this.svg.removeEventListener("pointerup",this.boundPointerUp))}handlePointerDown(o){o.stopPropagation();let{normalizedX:n,normalizedY:i}=this.pointerToNormalizedCoordinates(o),s=this.poline.getClosestAnchorPoint({xyz:[n,i,null],maxDistance:.1});s?this.currentPoint=s:this.allowAddPoints&&(this.currentPoint=this.poline.addAnchorPoint({xyz:[n,i,i]}),this.updateSVG(),this.dispatchPolineChange())}handlePointerMove(o){if(this.currentPoint){let{normalizedX:n,normalizedY:i}=this.pointerToNormalizedCoordinates(o);this.poline.updateAnchorPoint({point:this.currentPoint,xyz:[n,i,this.currentPoint.z]}),this.updateSVG(),this.dispatchPolineChange()}}handlePointerUp(){this.currentPoint=null}getPointerPosition(o){let n=this.svg.getBoundingClientRect();return{x:o.clientX-n.left,y:o.clientY-n.top}}pointerToNormalizedCoordinates(o){let n=this.svg.getBoundingClientRect(),i=(o.clientX-n.left)/n.width*v,s=(o.clientY-n.top)/n.height*v;return{normalizedX:i/v,normalizedY:s/v}}createCircleElement(o,n,i){let s=this.pointToCartesian(o);if(!s)return null;let[l=0,r=0]=s,c=document.createElementNS(F,"circle");return c.setAttribute("class",n),c.setAttribute("cx",l.toString()),c.setAttribute("cy",r.toString()),c.setAttribute("r",i.toString()),c.setAttribute("fill",o.hslCSS),c}dispatchPolineChange(){this.dispatchEvent(new CustomEvent("poline-change",{detail:{poline:this.poline}}))}};customElements.define("poline-picker",C);return I(U);})(); | ||
| `,o}updateSVG(){if(!this.poline||!this.svg)return;let o=this.poline.flattenedPoints,n=o.map(s=>{let h=this.pointToCartesian(s);if(!h)return"";let[r,c]=h;return`${r},${c}`}).filter(s=>s!=="").join(" ");this.line.setAttribute("points",n);let i=(s,h,r,c)=>{let l=s.children;for(;l.length>h.length;){let a=l[l.length-1];a&&s.removeChild(a)}h.forEach((a,p)=>{let u=l[p],f=this.pointToCartesian(a);if(!f)return;let[w=0,M=0]=f,E=c(a),k=a.hslCSS;u||(u=document.createElementNS(L,"circle"),u.setAttribute("class",r),s.appendChild(u)),u.setAttribute("cx",w.toString()),u.setAttribute("cy",M.toString()),u.setAttribute("r",E.toString()),u.setAttribute("fill",k)})};i(this.anchors,this.poline.anchorPoints,"wheel__anchor",()=>2),i(this.points,o,"wheel__point",s=>.5+s.color[1])}pointToCartesian(o){let n=v/2,i=n+(o.x-.5)*v,s=n+(o.y-.5)*v;return[i,s]}addEventListeners(){this.svg&&(this.svg.addEventListener("pointerdown",this.boundPointerDown),this.svg.addEventListener("pointermove",this.boundPointerMove),this.svg.addEventListener("pointerup",this.boundPointerUp))}removeEventListeners(){this.svg&&(this.svg.removeEventListener("pointerdown",this.boundPointerDown),this.svg.removeEventListener("pointermove",this.boundPointerMove),this.svg.removeEventListener("pointerup",this.boundPointerUp))}handlePointerDown(o){o.stopPropagation();let{normalizedX:n,normalizedY:i}=this.pointerToNormalizedCoordinates(o),s=this.poline.getClosestAnchorPoint({xyz:[n,i,null],maxDistance:.1});s?this.currentPoint=s:this.allowAddPoints&&(this.currentPoint=this.poline.addAnchorPoint({xyz:[n,i,i]}),this.updateSVG(),this.dispatchPolineChange())}handlePointerMove(o){if(this.currentPoint){let{normalizedX:n,normalizedY:i}=this.pointerToNormalizedCoordinates(o);this.poline.updateAnchorPoint({point:this.currentPoint,xyz:[n,i,this.currentPoint.z]}),this.updateSVG(),this.dispatchPolineChange()}}handlePointerUp(){this.currentPoint=null}getPointerPosition(o){let n=this.svg.getBoundingClientRect();return{x:o.clientX-n.left,y:o.clientY-n.top}}pointerToNormalizedCoordinates(o){let n=this.svg.getBoundingClientRect(),i=(o.clientX-n.left)/n.width*v,s=(o.clientY-n.top)/n.height*v;return{normalizedX:i/v,normalizedY:s/v}}createCircleElement(o,n,i){let s=this.pointToCartesian(o);if(!s)return null;let[h=0,r=0]=s,c=document.createElementNS(L,"circle");return c.setAttribute("class",n),c.setAttribute("cx",h.toString()),c.setAttribute("cy",r.toString()),c.setAttribute("r",i.toString()),c.setAttribute("fill",o.hslCSS),c}dispatchPolineChange(){this.dispatchEvent(new CustomEvent("poline-change",{detail:{poline:this.poline}}))}};customElements.define("poline-picker",C);return I(U);})(); |
@@ -1,2 +0,2 @@ | ||
| var _=(e,t)=>{let[o,n,i]=e,s=.5,l=.5,c=Math.atan2(n-l,o-s)*(180/Math.PI);c=(360+c)%360;let h=i,p=Math.sqrt(Math.pow(n-l,2)+Math.pow(o-s,2))/s;return[c,h,t?1-p:p]},f=(e,t)=>{let[o,n,i]=e,s=.5,l=.5,r=o/(180/Math.PI),c=(t?1-i:i)*s,h=s+c*Math.cos(r),a=l+c*Math.sin(r);return[h,a,n]},S=(e=Math.random()*360,t=[Math.random(),Math.random()],o=[.75+Math.random()*.2,.3+Math.random()*.2])=>[[e,t[0],o[0]],[(e+60+Math.random()*180)%360,t[1],o[1]]];var A=(e,t,o,n=!1,i=(r,c)=>c?1-r:r,s=(r,c)=>c?1-r:r,l=(r,c)=>c?1-r:r)=>{let r=i(e,n),c=s(e,n),h=l(e,n),a=(1-r)*t[0]+r*o[0],p=(1-c)*t[1]+c*o[1],u=(1-h)*t[2]+h*o[2];return[a,p,u]},M=(e,t,o=4,n=!1,i=(r,c)=>c?1-r:r,s=(r,c)=>c?1-r:r,l=(r,c)=>c?1-r:r)=>{let r=[];for(let c=0;c<o;c++){let[h,a,p]=A(c/(o-1),e,t,n,i,s,l);r.push([h,a,p])}return r},E=e=>e,k=(e,t=!1)=>t?1-(1-e)**2:e**2,z=(e,t=!1)=>t?1-(1-e)**3:e**3,G=(e,t=!1)=>t?1-(1-e)**4:e**4,X=(e,t=!1)=>t?1-(1-e)**5:e**5,d=(e,t=!1)=>t?1-Math.sin((1-e)*Math.PI/2):Math.sin(e*Math.PI/2),Y=(e,t=!1)=>t?1-Math.asin(1-e)/(Math.PI/2):Math.asin(e)/(Math.PI/2),T=(e,t=!1)=>t?1-Math.sqrt(1-e**2):1-Math.sqrt(1-e),I=e=>e**2*(3-2*e),$={linearPosition:E,exponentialPosition:k,quadraticPosition:z,cubicPosition:G,quarticPosition:X,sinusoidalPosition:d,asinusoidalPosition:Y,arcPosition:T,smoothStepPosition:I},F=(e,t,o=!1)=>{let n=e[0],i=t[0],s=0;o&&n!==null&&i!==null?(s=Math.min(Math.abs(n-i),360-Math.abs(n-i)),s=s/360):s=n===null||i===null?0:n-i;let l=s,r=e[1]===null||t[1]===null?0:t[1]-e[1],c=e[2]===null||t[2]===null?0:t[2]-e[2];return Math.sqrt(l*l+r*r+c*c)},v=class{constructor({xyz:t,color:o,invertedLightness:n=!1}={}){this.x=0;this.y=0;this.z=0;this.color=[0,0,0];this._invertedLightness=!1;this._invertedLightness=n,this.positionOrColor({xyz:t,color:o,invertedLightness:n})}positionOrColor({xyz:t,color:o,invertedLightness:n=!1}){if(this._invertedLightness=n,t&&o||!t&&!o)throw new Error("Point must be initialized with either x,y,z or hsl");t?(this.x=t[0],this.y=t[1],this.z=t[2],this.color=_([this.x,this.y,this.z],n)):o&&(this.color=o,[this.x,this.y,this.z]=f(o,n))}set position([t,o,n]){this.x=t,this.y=o,this.z=n,this.color=_([this.x,this.y,this.z],this._invertedLightness)}get position(){return[this.x,this.y,this.z]}set hsl([t,o,n]){this.color=[t,o,n],[this.x,this.y,this.z]=f(this.color,this._invertedLightness)}get hsl(){return this.color}get hslCSS(){let[t,o,n]=this.color;return`hsl(${t.toFixed(2)}, ${(o*100).toFixed(2)}%, ${(n*100).toFixed(2)}%)`}get oklchCSS(){let[t,o,n]=this.color;return`oklch(${(n*100).toFixed(2)}% ${(o*.4).toFixed(3)} ${t.toFixed(2)})`}get lchCSS(){let[t,o,n]=this.color;return`lch(${(n*100).toFixed(2)}% ${(o*150).toFixed(2)} ${t.toFixed(2)})`}shiftHue(t){this.color[0]=(360+(this.color[0]+t))%360,[this.x,this.y,this.z]=f(this.color,this._invertedLightness)}},b=class{constructor({anchorColors:t=S(),numPoints:o=4,positionFunction:n=d,positionFunctionX:i,positionFunctionY:s,positionFunctionZ:l,closedLoop:r,invertedLightness:c}={anchorColors:S(),numPoints:4,positionFunction:d,closedLoop:!1}){this._needsUpdate=!0;this._positionFunctionX=d;this._positionFunctionY=d;this._positionFunctionZ=d;this.connectLastAndFirstAnchor=!1;this._animationFrame=null;this._invertedLightness=!1;if(!t||t.length<2)throw new Error("Must have at least two anchor colors");this._anchorPoints=t.map(h=>new v({color:h,invertedLightness:c})),this._numPoints=o+2,this._positionFunctionX=i||n||d,this._positionFunctionY=s||n||d,this._positionFunctionZ=l||n||d,this.connectLastAndFirstAnchor=r||!1,this._invertedLightness=c||!1,this.updateAnchorPairs()}get numPoints(){return this._numPoints-2}set numPoints(t){if(t<1)throw new Error("Must have at least one point");this._numPoints=t+2,this.updateAnchorPairs()}set positionFunction(t){if(Array.isArray(t)){if(t.length!==3)throw new Error("Position function array must have 3 elements");if(typeof t[0]!="function"||typeof t[1]!="function"||typeof t[2]!="function")throw new Error("Position function array must have 3 functions");this._positionFunctionX=t[0],this._positionFunctionY=t[1],this._positionFunctionZ=t[2]}else this._positionFunctionX=t,this._positionFunctionY=t,this._positionFunctionZ=t;this.updateAnchorPairs()}get positionFunction(){return this._positionFunctionX===this._positionFunctionY&&this._positionFunctionX===this._positionFunctionZ?this._positionFunctionX:[this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ]}set positionFunctionX(t){this._positionFunctionX=t,this.updateAnchorPairs()}get positionFunctionX(){return this._positionFunctionX}set positionFunctionY(t){this._positionFunctionY=t,this.updateAnchorPairs()}get positionFunctionY(){return this._positionFunctionY}set positionFunctionZ(t){this._positionFunctionZ=t,this.updateAnchorPairs()}get positionFunctionZ(){return this._positionFunctionZ}get anchorPoints(){return this._anchorPoints}set anchorPoints(t){this._anchorPoints=t,this.updateAnchorPairs()}updateAnchorPairs(){this._anchorPairs=[];let t=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1;for(let o=0;o<t;o++){let n=[this.anchorPoints[o],this.anchorPoints[(o+1)%this.anchorPoints.length]];this._anchorPairs.push(n)}this.points=this._anchorPairs.map((o,n)=>{let i=o[0]?o[0].position:[0,0,0],s=o[1]?o[1].position:[0,0,0],l=this.shouldInvertEaseForSegment(n);return M(i,s,this._numPoints,!!l,this.positionFunctionX,this.positionFunctionY,this.positionFunctionZ).map(r=>new v({xyz:r,invertedLightness:this._invertedLightness}))})}addAnchorPoint({xyz:t,color:o,insertAtIndex:n}){let i=new v({xyz:t,color:o,invertedLightness:this._invertedLightness});return n!==void 0?this.anchorPoints.splice(n,0,i):this.anchorPoints.push(i),this.updateAnchorPairs(),i}removeAnchorPoint({point:t,index:o}){if(!t&&o===void 0)throw new Error("Must provide a point or index");if(this.anchorPoints.length<3)throw new Error("Must have at least two anchor points");let n;if(o!==void 0?n=o:t&&(n=this.anchorPoints.indexOf(t)),n>-1&&n<this.anchorPoints.length)this.anchorPoints.splice(n,1),this.updateAnchorPairs();else throw new Error("Point not found")}updateAnchorPoint({point:t,pointIndex:o,xyz:n,color:i}){if(o!==void 0&&(t=this.anchorPoints[o]),!t)throw new Error("Must provide a point or pointIndex");if(!n&&!i)throw new Error("Must provide a new xyz position or color");return n&&(t.position=n),i&&(t.hsl=i),this.updateAnchorPairs(),t}getClosestAnchorPoint({xyz:t,hsl:o,maxDistance:n=1}){if(!t&&!o)throw new Error("Must provide a xyz or hsl");let i;t?i=this.anchorPoints.map(r=>F(r.position,t)):o&&(i=this.anchorPoints.map(r=>F(r.hsl,o,!0)));let s=Math.min(...i);if(s>n)return null;let l=i.indexOf(s);return this.anchorPoints[l]||null}set closedLoop(t){this.connectLastAndFirstAnchor=t,this.updateAnchorPairs()}get closedLoop(){return this.connectLastAndFirstAnchor}set invertedLightness(t){this._invertedLightness=t,this.updateAnchorPairs()}get invertedLightness(){return this._invertedLightness}get flattenedPoints(){return this.points.flat().filter((t,o)=>o!=0?o%this._numPoints:!0)}get colors(){let t=this.flattenedPoints.map(o=>o.color);return this.connectLastAndFirstAnchor&&this._anchorPoints.length!==2&&t.pop(),t}cssColors(t="hsl"){let o={hsl:i=>i.hslCSS,oklch:i=>i.oklchCSS,lch:i=>i.lchCSS},n=this.flattenedPoints.map(o[t]);return this.connectLastAndFirstAnchor&&n.pop(),n}get colorsCSS(){return this.cssColors("hsl")}get colorsCSSlch(){return this.cssColors("lch")}get colorsCSSoklch(){return this.cssColors("oklch")}shiftHue(t=20){this.anchorPoints.forEach(o=>o.shiftHue(t)),this.updateAnchorPairs()}getColorAt(t){if(t<0||t>1)throw new Error("Position must be between 0 and 1");if(this.anchorPoints.length===0)throw new Error("No anchor points available");let o=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1,n=this.connectLastAndFirstAnchor&&this.anchorPoints.length===2?2:o,i=t*n,s=Math.floor(i),l=i-s,r=s>=n?n-1:s,c=s>=n?1:l,h=this._anchorPairs[r];if(!h||h.length<2||!h[0]||!h[1])return new v({color:this.anchorPoints[0]?.color||[0,0,0],invertedLightness:this._invertedLightness});let a=h[0].position,p=h[1].position,u=this.shouldInvertEaseForSegment(r),g=A(c,a,p,u,this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ);return new v({xyz:g,invertedLightness:this._invertedLightness})}shouldInvertEaseForSegment(t){return!!(t%2||this.connectLastAndFirstAnchor&&this.anchorPoints.length===2&&t===0)}},{p5:m}=globalThis;if(m&&m.VERSION&&m.VERSION.startsWith("1.")){console.info("p5 < 1.x detected, adding poline to p5 prototype");let e=new b;m.prototype.poline=e;let t=()=>e.colors.map(o=>`hsl(${Math.round(o[0])},${o[1]*100}%,${o[2]*100}%)`);m.prototype.registerMethod("polineColors",t),globalThis.poline=e,globalThis.polineColors=t}var w="http://www.w3.org/2000/svg",P=100,C=class extends HTMLElement{constructor(){super();this.currentPoint=null;this.allowAddPoints=!1;this.boundPointerDown=this.handlePointerDown.bind(this);this.boundPointerMove=this.handlePointerMove.bind(this);this.boundPointerUp=this.handlePointerUp.bind(this);this.attachShadow({mode:"open"}),this.interactive=this.hasAttribute("interactive"),this.allowAddPoints=this.hasAttribute("allow-add-points")}connectedCallback(){this.interactive=this.hasAttribute("interactive"),this.allowAddPoints=this.hasAttribute("allow-add-points"),this.render(),this.interactive&&this.addEventListeners()}disconnectedCallback(){this.removeEventListeners()}setPoline(o){this.poline=o,this.updateSVG(),this.updateLightnessBackground()}setAllowAddPoints(o){this.allowAddPoints=o}addPointAtPosition(o,n){if(!this.poline)return null;let i=o/this.svg.clientWidth,s=n/this.svg.clientHeight,l=this.poline.addAnchorPoint({xyz:[i,s,s]});return this.updateSVG(),this.dispatchPolineChange(),l}updateLightnessBackground(){let o=this.shadowRoot?.querySelector(".picker");o&&this.poline&&(this.poline.invertedLightness?(o.style.setProperty("--maxL","#000"),o.style.setProperty("--minL","#fff")):(o.style.setProperty("--maxL","#fff"),o.style.setProperty("--minL","#000")))}render(){if(!this.shadowRoot)return;this.shadowRoot.innerHTML=` | ||
| var f=(e,t)=>{let[o,n,i]=e,s=.5,h=.5,c=Math.atan2(n-h,o-s)*(180/Math.PI);c=(360+c)%360;let l=i,p=Math.sqrt(Math.pow(n-h,2)+Math.pow(o-s,2))/s;return[c,l,t?1-p:p]},w=(e,t)=>{let[o,n,i]=e,s=.5,h=.5,r=o/(180/Math.PI),c=(t?1-i:i)*s,l=s+c*Math.cos(r),a=h+c*Math.sin(r);return[l,a,n]},S=(e=Math.random()*360,t=[Math.random(),Math.random()],o=[.75+Math.random()*.2,.3+Math.random()*.2])=>[[e,t[0],o[0]],[(e+60+Math.random()*180)%360,t[1],o[1]]];var L=(e,t,o,n=!1,i=(r,c)=>c?1-r:r,s=(r,c)=>c?1-r:r,h=(r,c)=>c?1-r:r)=>{let r=i(e,n),c=s(e,n),l=h(e,n),a=(1-r)*t[0]+r*o[0],p=(1-c)*t[1]+c*o[1],u=(1-l)*t[2]+l*o[2];return[a,p,u]},M=(e,t,o=4,n=!1,i=(r,c)=>c?1-r:r,s=(r,c)=>c?1-r:r,h=(r,c)=>c?1-r:r)=>{let r=[];for(let c=0;c<o;c++){let[l,a,p]=L(c/(o-1),e,t,n,i,s,h);r.push([l,a,p])}return r},E=e=>e,k=(e,t=!1)=>t?1-(1-e)**2:e**2,z=(e,t=!1)=>t?1-(1-e)**3:e**3,G=(e,t=!1)=>t?1-(1-e)**4:e**4,X=(e,t=!1)=>t?1-(1-e)**5:e**5,d=(e,t=!1)=>t?1-Math.sin((1-e)*Math.PI/2):Math.sin(e*Math.PI/2),Y=(e,t=!1)=>t?1-Math.asin(1-e)/(Math.PI/2):Math.asin(e)/(Math.PI/2),T=(e,t=!1)=>t?1-Math.sqrt(1-e**2):1-Math.sqrt(1-e),I=e=>e**2*(3-2*e),$={linearPosition:E,exponentialPosition:k,quadraticPosition:z,cubicPosition:G,quarticPosition:X,sinusoidalPosition:d,asinusoidalPosition:Y,arcPosition:T,smoothStepPosition:I},F=(e,t,o=!1)=>{let n=e[0],i=t[0],s=0;o&&n!==null&&i!==null?(s=Math.min(Math.abs(n-i),360-Math.abs(n-i)),s=s/360):s=n===null||i===null?0:n-i;let h=s,r=e[1]===null||t[1]===null?0:t[1]-e[1],c=e[2]===null||t[2]===null?0:t[2]-e[2];return Math.sqrt(h*h+r*r+c*c)},v=class{constructor({xyz:t,color:o,invertedLightness:n=!1}={}){this.x=0;this.y=0;this.z=0;this.color=[0,0,0];this._invertedLightness=!1;this._invertedLightness=n,this.positionOrColor({xyz:t,color:o,invertedLightness:n})}positionOrColor({xyz:t,color:o,invertedLightness:n=!1}){if(this._invertedLightness=n,t&&o||!t&&!o)throw new Error("Point must be initialized with either x,y,z or hsl");t?(this.x=t[0],this.y=t[1],this.z=t[2],this.color=f([this.x,this.y,this.z],n)):o&&(this.color=o,[this.x,this.y,this.z]=w(o,n))}set position([t,o,n]){this.x=t,this.y=o,this.z=n,this.color=f([this.x,this.y,this.z],this._invertedLightness)}get position(){return[this.x,this.y,this.z]}set hsl([t,o,n]){this.color=[t,o,n],[this.x,this.y,this.z]=w(this.color,this._invertedLightness)}get hsl(){return this.color}get hslCSS(){let[t,o,n]=this.color;return`hsl(${t.toFixed(2)}, ${(o*100).toFixed(2)}%, ${(n*100).toFixed(2)}%)`}get oklchCSS(){let[t,o,n]=this.color;return`oklch(${(n*100).toFixed(2)}% ${(o*.4).toFixed(3)} ${t.toFixed(2)})`}get lchCSS(){let[t,o,n]=this.color;return`lch(${(n*100).toFixed(2)}% ${(o*150).toFixed(2)} ${t.toFixed(2)})`}set invertedLightness(t){this._invertedLightness=t,this.color=f([this.x,this.y,this.z],this._invertedLightness)}get invertedLightness(){return this._invertedLightness}shiftHue(t){this.color[0]=(360+(this.color[0]+t))%360,[this.x,this.y,this.z]=w(this.color,this._invertedLightness)}},b=class{constructor({anchorColors:t=S(),numPoints:o=4,positionFunction:n=d,positionFunctionX:i,positionFunctionY:s,positionFunctionZ:h,closedLoop:r,invertedLightness:c}={anchorColors:S(),numPoints:4,positionFunction:d,closedLoop:!1}){this._positionFunctionX=d;this._positionFunctionY=d;this._positionFunctionZ=d;this.connectLastAndFirstAnchor=!1;this._animationFrame=null;this._invertedLightness=!1;if(!t||t.length<2)throw new Error("Must have at least two anchor colors");this._anchorPoints=t.map(l=>new v({color:l,invertedLightness:c})),this._numPoints=o+2,this._positionFunctionX=i||n||d,this._positionFunctionY=s||n||d,this._positionFunctionZ=h||n||d,this.connectLastAndFirstAnchor=r||!1,this._invertedLightness=c||!1,this.updateAnchorPairs()}get numPoints(){return this._numPoints-2}set numPoints(t){if(t<1)throw new Error("Must have at least one point");this._numPoints=t+2,this.updateAnchorPairs()}set positionFunction(t){if(Array.isArray(t)){if(t.length!==3)throw new Error("Position function array must have 3 elements");if(typeof t[0]!="function"||typeof t[1]!="function"||typeof t[2]!="function")throw new Error("Position function array must have 3 functions");this._positionFunctionX=t[0],this._positionFunctionY=t[1],this._positionFunctionZ=t[2]}else this._positionFunctionX=t,this._positionFunctionY=t,this._positionFunctionZ=t;this.updateAnchorPairs()}get positionFunction(){return this._positionFunctionX===this._positionFunctionY&&this._positionFunctionX===this._positionFunctionZ?this._positionFunctionX:[this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ]}set positionFunctionX(t){this._positionFunctionX=t,this.updateAnchorPairs()}get positionFunctionX(){return this._positionFunctionX}set positionFunctionY(t){this._positionFunctionY=t,this.updateAnchorPairs()}get positionFunctionY(){return this._positionFunctionY}set positionFunctionZ(t){this._positionFunctionZ=t,this.updateAnchorPairs()}get positionFunctionZ(){return this._positionFunctionZ}get anchorPoints(){return this._anchorPoints}set anchorPoints(t){this._anchorPoints=t,this.updateAnchorPairs()}updateAnchorPairs(){this._anchorPairs=[];let t=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1;for(let o=0;o<t;o++){let n=[this.anchorPoints[o],this.anchorPoints[(o+1)%this.anchorPoints.length]];this._anchorPairs.push(n)}this.points=this._anchorPairs.map((o,n)=>{let i=o[0]?o[0].position:[0,0,0],s=o[1]?o[1].position:[0,0,0],h=this.shouldInvertEaseForSegment(n);return M(i,s,this._numPoints,!!h,this.positionFunctionX,this.positionFunctionY,this.positionFunctionZ).map(r=>new v({xyz:r,invertedLightness:this._invertedLightness}))})}addAnchorPoint({xyz:t,color:o,insertAtIndex:n}){let i=new v({xyz:t,color:o,invertedLightness:this._invertedLightness});return n!==void 0?this.anchorPoints.splice(n,0,i):this.anchorPoints.push(i),this.updateAnchorPairs(),i}removeAnchorPoint({point:t,index:o}){if(!t&&o===void 0)throw new Error("Must provide a point or index");if(this.anchorPoints.length<3)throw new Error("Must have at least two anchor points");let n;if(o!==void 0?n=o:t&&(n=this.anchorPoints.indexOf(t)),n>-1&&n<this.anchorPoints.length)this.anchorPoints.splice(n,1),this.updateAnchorPairs();else throw new Error("Point not found")}updateAnchorPoint({point:t,pointIndex:o,xyz:n,color:i}){if(o!==void 0&&(t=this.anchorPoints[o]),!t)throw new Error("Must provide a point or pointIndex");if(!n&&!i)throw new Error("Must provide a new xyz position or color");return n&&(t.position=n),i&&(t.hsl=i),this.updateAnchorPairs(),t}getClosestAnchorPoint({xyz:t,hsl:o,maxDistance:n=1}){if(!t&&!o)throw new Error("Must provide a xyz or hsl");let i;t?i=this.anchorPoints.map(r=>F(r.position,t)):o&&(i=this.anchorPoints.map(r=>F(r.hsl,o,!0)));let s=Math.min(...i);if(s>n)return null;let h=i.indexOf(s);return this.anchorPoints[h]||null}set closedLoop(t){this.connectLastAndFirstAnchor=t,this.updateAnchorPairs()}get closedLoop(){return this.connectLastAndFirstAnchor}set invertedLightness(t){this._invertedLightness=t,this.anchorPoints.forEach(o=>o.invertedLightness=t),this.updateAnchorPairs()}get invertedLightness(){return this._invertedLightness}get flattenedPoints(){return this.points.flat().filter((t,o)=>o!=0?o%this._numPoints:!0)}get colors(){let t=this.flattenedPoints.map(o=>o.color);return this.connectLastAndFirstAnchor&&this._anchorPoints.length!==2&&t.pop(),t}cssColors(t="hsl"){let o={hsl:i=>i.hslCSS,oklch:i=>i.oklchCSS,lch:i=>i.lchCSS},n=this.flattenedPoints.map(o[t]);return this.connectLastAndFirstAnchor&&n.pop(),n}get colorsCSS(){return this.cssColors("hsl")}get colorsCSSlch(){return this.cssColors("lch")}get colorsCSSoklch(){return this.cssColors("oklch")}shiftHue(t=20){this.anchorPoints.forEach(o=>o.shiftHue(t)),this.updateAnchorPairs()}getColorAt(t){if(t<0||t>1)throw new Error("Position must be between 0 and 1");if(this.anchorPoints.length===0)throw new Error("No anchor points available");let o=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1,n=this.connectLastAndFirstAnchor&&this.anchorPoints.length===2?2:o,i=t*n,s=Math.floor(i),h=i-s,r=s>=n?n-1:s,c=s>=n?1:h,l=this._anchorPairs[r];if(!l||l.length<2||!l[0]||!l[1])return new v({color:this.anchorPoints[0]?.color||[0,0,0],invertedLightness:this._invertedLightness});let a=l[0].position,p=l[1].position,u=this.shouldInvertEaseForSegment(r),m=L(c,a,p,u,this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ);return new v({xyz:m,invertedLightness:this._invertedLightness})}shouldInvertEaseForSegment(t){return!!(t%2||this.connectLastAndFirstAnchor&&this.anchorPoints.length===2&&t===0)}},{p5:g}=globalThis;if(g&&g.VERSION&&g.VERSION.startsWith("1.")){console.info("p5 < 1.x detected, adding poline to p5 prototype");let e=new b;g.prototype.poline=e;let t=()=>e.colors.map(o=>`hsl(${Math.round(o[0])},${o[1]*100}%,${o[2]*100}%)`);g.prototype.registerMethod("polineColors",t),globalThis.poline=e,globalThis.polineColors=t}var C="http://www.w3.org/2000/svg",P=100,_=class extends HTMLElement{constructor(){super();this.currentPoint=null;this.allowAddPoints=!1;this.boundPointerDown=this.handlePointerDown.bind(this);this.boundPointerMove=this.handlePointerMove.bind(this);this.boundPointerUp=this.handlePointerUp.bind(this);this.attachShadow({mode:"open"}),this.interactive=this.hasAttribute("interactive"),this.allowAddPoints=this.hasAttribute("allow-add-points")}connectedCallback(){this.interactive=this.hasAttribute("interactive"),this.allowAddPoints=this.hasAttribute("allow-add-points"),this.render(),this.interactive&&this.addEventListeners()}disconnectedCallback(){this.removeEventListeners()}setPoline(o){this.poline=o,this.updateSVG(),this.updateLightnessBackground()}setAllowAddPoints(o){this.allowAddPoints=o}addPointAtPosition(o,n){if(!this.poline)return null;let i=o/this.svg.clientWidth,s=n/this.svg.clientHeight,h=this.poline.addAnchorPoint({xyz:[i,s,s]});return this.updateSVG(),this.dispatchPolineChange(),h}updateLightnessBackground(){let o=this.shadowRoot?.querySelector(".picker");o&&this.poline&&(this.poline.invertedLightness?(o.style.setProperty("--maxL","#000"),o.style.setProperty("--minL","#fff")):(o.style.setProperty("--maxL","#fff"),o.style.setProperty("--minL","#000")))}render(){if(!this.shadowRoot)return;this.shadowRoot.innerHTML=` | ||
| <style> | ||
@@ -52,3 +52,3 @@ :host { | ||
| </style> | ||
| `,this.svg=this.createSVG();let o=document.createElement("div");o.className="picker",o.appendChild(this.svg),this.shadowRoot.appendChild(o),this.wheel=this.svg.querySelector(".wheel"),this.line=this.svg.querySelector(".wheel__line"),this.anchors=this.svg.querySelector(".wheel__anchors"),this.points=this.svg.querySelector(".wheel__points"),this.poline&&(this.updateSVG(),this.updateLightnessBackground())}createSVG(){let o=document.createElementNS(w,"svg");return o.setAttribute("viewBox",`0 0 ${P} ${P}`),o.innerHTML=` | ||
| `,this.svg=this.createSVG();let o=document.createElement("div");o.className="picker",o.appendChild(this.svg),this.shadowRoot.appendChild(o),this.wheel=this.svg.querySelector(".wheel"),this.line=this.svg.querySelector(".wheel__line"),this.anchors=this.svg.querySelector(".wheel__anchors"),this.points=this.svg.querySelector(".wheel__points"),this.poline&&(this.updateSVG(),this.updateLightnessBackground())}createSVG(){let o=document.createElementNS(C,"svg");return o.setAttribute("viewBox",`0 0 ${P} ${P}`),o.innerHTML=` | ||
| <defs> | ||
@@ -66,2 +66,2 @@ <filter id="goo"> | ||
| </g> | ||
| `,o}updateSVG(){if(!this.poline||!this.svg)return;let o=this.poline.flattenedPoints,n=o.map(s=>{let l=this.pointToCartesian(s);if(!l)return"";let[r,c]=l;return`${r},${c}`}).filter(s=>s!=="").join(" ");this.line.setAttribute("points",n);let i=(s,l,r,c)=>{let h=s.children;for(;h.length>l.length;){let a=h[h.length-1];a&&s.removeChild(a)}l.forEach((a,p)=>{let u=h[p],g=this.pointToCartesian(a);if(!g)return;let[L=0,x=0]=g,V=c(a),y=a.hslCSS;u||(u=document.createElementNS(w,"circle"),u.setAttribute("class",r),s.appendChild(u)),u.setAttribute("cx",L.toString()),u.setAttribute("cy",x.toString()),u.setAttribute("r",V.toString()),u.setAttribute("fill",y)})};i(this.anchors,this.poline.anchorPoints,"wheel__anchor",()=>2),i(this.points,o,"wheel__point",s=>.5+s.color[1])}pointToCartesian(o){let n=P/2,i=n+(o.x-.5)*P,s=n+(o.y-.5)*P;return[i,s]}addEventListeners(){this.svg&&(this.svg.addEventListener("pointerdown",this.boundPointerDown),this.svg.addEventListener("pointermove",this.boundPointerMove),this.svg.addEventListener("pointerup",this.boundPointerUp))}removeEventListeners(){this.svg&&(this.svg.removeEventListener("pointerdown",this.boundPointerDown),this.svg.removeEventListener("pointermove",this.boundPointerMove),this.svg.removeEventListener("pointerup",this.boundPointerUp))}handlePointerDown(o){o.stopPropagation();let{normalizedX:n,normalizedY:i}=this.pointerToNormalizedCoordinates(o),s=this.poline.getClosestAnchorPoint({xyz:[n,i,null],maxDistance:.1});s?this.currentPoint=s:this.allowAddPoints&&(this.currentPoint=this.poline.addAnchorPoint({xyz:[n,i,i]}),this.updateSVG(),this.dispatchPolineChange())}handlePointerMove(o){if(this.currentPoint){let{normalizedX:n,normalizedY:i}=this.pointerToNormalizedCoordinates(o);this.poline.updateAnchorPoint({point:this.currentPoint,xyz:[n,i,this.currentPoint.z]}),this.updateSVG(),this.dispatchPolineChange()}}handlePointerUp(){this.currentPoint=null}getPointerPosition(o){let n=this.svg.getBoundingClientRect();return{x:o.clientX-n.left,y:o.clientY-n.top}}pointerToNormalizedCoordinates(o){let n=this.svg.getBoundingClientRect(),i=(o.clientX-n.left)/n.width*P,s=(o.clientY-n.top)/n.height*P;return{normalizedX:i/P,normalizedY:s/P}}createCircleElement(o,n,i){let s=this.pointToCartesian(o);if(!s)return null;let[l=0,r=0]=s,c=document.createElementNS(w,"circle");return c.setAttribute("class",n),c.setAttribute("cx",l.toString()),c.setAttribute("cy",r.toString()),c.setAttribute("r",i.toString()),c.setAttribute("fill",o.hslCSS),c}dispatchPolineChange(){this.dispatchEvent(new CustomEvent("poline-change",{detail:{poline:this.poline}}))}};customElements.define("poline-picker",C);export{b as Poline,C as PolinePicker,$ as positionFunctions}; | ||
| `,o}updateSVG(){if(!this.poline||!this.svg)return;let o=this.poline.flattenedPoints,n=o.map(s=>{let h=this.pointToCartesian(s);if(!h)return"";let[r,c]=h;return`${r},${c}`}).filter(s=>s!=="").join(" ");this.line.setAttribute("points",n);let i=(s,h,r,c)=>{let l=s.children;for(;l.length>h.length;){let a=l[l.length-1];a&&s.removeChild(a)}h.forEach((a,p)=>{let u=l[p],m=this.pointToCartesian(a);if(!m)return;let[A=0,x=0]=m,V=c(a),y=a.hslCSS;u||(u=document.createElementNS(C,"circle"),u.setAttribute("class",r),s.appendChild(u)),u.setAttribute("cx",A.toString()),u.setAttribute("cy",x.toString()),u.setAttribute("r",V.toString()),u.setAttribute("fill",y)})};i(this.anchors,this.poline.anchorPoints,"wheel__anchor",()=>2),i(this.points,o,"wheel__point",s=>.5+s.color[1])}pointToCartesian(o){let n=P/2,i=n+(o.x-.5)*P,s=n+(o.y-.5)*P;return[i,s]}addEventListeners(){this.svg&&(this.svg.addEventListener("pointerdown",this.boundPointerDown),this.svg.addEventListener("pointermove",this.boundPointerMove),this.svg.addEventListener("pointerup",this.boundPointerUp))}removeEventListeners(){this.svg&&(this.svg.removeEventListener("pointerdown",this.boundPointerDown),this.svg.removeEventListener("pointermove",this.boundPointerMove),this.svg.removeEventListener("pointerup",this.boundPointerUp))}handlePointerDown(o){o.stopPropagation();let{normalizedX:n,normalizedY:i}=this.pointerToNormalizedCoordinates(o),s=this.poline.getClosestAnchorPoint({xyz:[n,i,null],maxDistance:.1});s?this.currentPoint=s:this.allowAddPoints&&(this.currentPoint=this.poline.addAnchorPoint({xyz:[n,i,i]}),this.updateSVG(),this.dispatchPolineChange())}handlePointerMove(o){if(this.currentPoint){let{normalizedX:n,normalizedY:i}=this.pointerToNormalizedCoordinates(o);this.poline.updateAnchorPoint({point:this.currentPoint,xyz:[n,i,this.currentPoint.z]}),this.updateSVG(),this.dispatchPolineChange()}}handlePointerUp(){this.currentPoint=null}getPointerPosition(o){let n=this.svg.getBoundingClientRect();return{x:o.clientX-n.left,y:o.clientY-n.top}}pointerToNormalizedCoordinates(o){let n=this.svg.getBoundingClientRect(),i=(o.clientX-n.left)/n.width*P,s=(o.clientY-n.top)/n.height*P;return{normalizedX:i/P,normalizedY:s/P}}createCircleElement(o,n,i){let s=this.pointToCartesian(o);if(!s)return null;let[h=0,r=0]=s,c=document.createElementNS(C,"circle");return c.setAttribute("class",n),c.setAttribute("cx",h.toString()),c.setAttribute("cy",r.toString()),c.setAttribute("r",i.toString()),c.setAttribute("fill",o.hslCSS),c}dispatchPolineChange(){this.dispatchEvent(new CustomEvent("poline-change",{detail:{poline:this.poline}}))}};customElements.define("poline-picker",_);export{b as Poline,_ as PolinePicker,$ as positionFunctions}; |
+11
-1
@@ -200,2 +200,12 @@ // src/index.ts | ||
| } | ||
| set invertedLightness(val) { | ||
| this._invertedLightness = val; | ||
| this.color = pointToHSL( | ||
| [this.x, this.y, this.z], | ||
| this._invertedLightness | ||
| ); | ||
| } | ||
| get invertedLightness() { | ||
| return this._invertedLightness; | ||
| } | ||
| shiftHue(angle) { | ||
@@ -225,3 +235,2 @@ this.color[0] = (360 + (this.color[0] + angle)) % 360; | ||
| }) { | ||
| this._needsUpdate = true; | ||
| this._positionFunctionX = sinusoidalPosition; | ||
@@ -437,2 +446,3 @@ this._positionFunctionY = sinusoidalPosition; | ||
| this._invertedLightness = newStatus; | ||
| this.anchorPoints.forEach((p) => p.invertedLightness = newStatus); | ||
| this.updateAnchorPairs(); | ||
@@ -439,0 +449,0 @@ } |
+5
-4
| { | ||
| "name": "poline", | ||
| "version": "0.12.0", | ||
| "version": "0.13.0", | ||
| "description": "color palette generator mico-lib", | ||
@@ -24,4 +24,4 @@ "type": "module", | ||
| "scripts": { | ||
| "build": "npm run lint && tsc --build && node ./build.js", | ||
| "test": "npm run lint && echo \"Error: no test specified\" && exit 1", | ||
| "build": "npm test && npm run lint && tsc --build && node ./build.js", | ||
| "test": "vitest run", | ||
| "lint": "eslint . --ext .ts && npx prettier --check ./src/", | ||
@@ -58,4 +58,5 @@ "prettier": "npx prettier --write ./src/", | ||
| "prettier": "^2.8.1", | ||
| "typescript": "^4.9.4" | ||
| "typescript": "^4.9.4", | ||
| "vitest": "^3.2.4" | ||
| } | ||
| } |
+37
-2
@@ -432,4 +432,4 @@ <h1><a href="https://meodai.github.io/poline/"><img width="200" src="https://meodai.github.io/poline/poline-logo.png" alt="poline" /></a></h1> | ||
| type PolineOptions = { | ||
| anchorColors: Vector3[]; | ||
| numPoints: number; | ||
| anchorColors?: Vector3[]; // Optional: defaults to random pair | ||
| numPoints?: number; // Optional: defaults to 4 | ||
| positionFunction?: PositionFunction; | ||
@@ -651,2 +651,37 @@ positionFunctionX?: PositionFunction; | ||
| ## Development | ||
| ### Testing | ||
| "**poline**" includes a comprehensive test suite to ensure reliability and correctness. Tests are written using [Vitest](https://vitest.dev/) and cover all major functionality including: | ||
| - ColorPoint class operations | ||
| - HSL/XYZ coordinate conversions | ||
| - Position functions and easing | ||
| - Palette generation and manipulation | ||
| - Anchor point management | ||
| - Edge cases and error handling | ||
| To run the tests: | ||
| ```bash | ||
| npm test | ||
| ``` | ||
| Tests are automatically run before building to ensure code quality. | ||
| ### Building | ||
| To build the project: | ||
| ```bash | ||
| npm run build | ||
| ``` | ||
| This will: | ||
| 1. Run the test suite | ||
| 2. Lint and format check the code | ||
| 3. Compile TypeScript to JavaScript | ||
| 4. Generate all distribution bundles (ESM, CommonJS, UMD, minified versions) | ||
| ## License | ||
@@ -653,0 +688,0 @@ |
+15
-3
@@ -353,2 +353,14 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ | ||
| set invertedLightness(val: boolean) { | ||
| this._invertedLightness = val; | ||
| this.color = pointToHSL( | ||
| [this.x, this.y, this.z] as Vector3, | ||
| this._invertedLightness | ||
| ); | ||
| } | ||
| get invertedLightness(): boolean { | ||
| return this._invertedLightness; | ||
| } | ||
| shiftHue(angle: number): void { | ||
@@ -364,4 +376,4 @@ this.color[0] = (360 + (this.color[0] + angle)) % 360; | ||
| export type PolineOptions = { | ||
| anchorColors: Vector3[]; | ||
| numPoints: number; | ||
| anchorColors?: Vector3[]; | ||
| numPoints?: number; | ||
| positionFunction?: (t: number, invert?: boolean) => number; | ||
@@ -375,3 +387,2 @@ positionFunctionX?: (t: number, invert?: boolean) => number; | ||
| export class Poline { | ||
| private _needsUpdate = true; | ||
| private _anchorPoints: ColorPoint[]; | ||
@@ -690,2 +701,3 @@ | ||
| this._invertedLightness = newStatus; | ||
| this.anchorPoints.forEach((p) => (p.invertedLightness = newStatus)); | ||
| this.updateAnchorPairs(); | ||
@@ -692,0 +704,0 @@ } |
+2
-1
@@ -13,5 +13,6 @@ { | ||
| "strict": true, | ||
| "strictPropertyInitialization": false | ||
| "strictPropertyInitialization": false, | ||
| "skipLibCheck": true | ||
| }, | ||
| "include": ["src/**/*", "demo-src"] | ||
| } |
Sorry, the diff of this file is too big to display
No tests
QualityPackage does not have any tests. This is a strong signal of a poorly maintained or low quality package.
1453092
1.96%35
2.94%7560
10.24%7
-12.5%692
5.33%9
12.5%