UNPKG

@shopify/cli-kit

Version:

A set of utilities, interfaces, and models that are common across all the platform features

56 lines 2.07 kB
/* eslint-disable id-length */ import { Text, useStdout } from 'ink'; import React, { memo, useCallback, useLayoutEffect, useRef, useState } from 'react'; import gradient from 'gradient-string'; function rainbow(text, frame) { const hue = 5 * frame; const leftColor = { h: hue % 360, s: 0.8, v: 1 }; const rightColor = { h: (hue + 1) % 360, s: 0.8, v: 1 }; return gradient(leftColor, rightColor)(text, { interpolation: 'hsv', hsvSpin: 'long' }); } function rotated(text, steps) { const normalizedSteps = steps % text.length; const start = text.slice(-normalizedSteps); const end = text.slice(0, -normalizedSteps); return start + end; } function truncated(text, maxWidth) { return maxWidth ? text.slice(0, maxWidth) : text; } /** * `TextAnimation` applies a rainbow animation to text. */ const TextAnimation = memo(({ text, maxWidth }) => { const frame = useRef(0); const [renderedFrame, setRenderedFrame] = useState(text); const timeout = useRef(); const { stdout } = useStdout(); const [width, setWidth] = useState(maxWidth ?? Math.floor(stdout.columns * 0.66)); useLayoutEffect(() => { const handleResize = () => { setWidth(Math.floor(stdout.columns * 0.66)); }; stdout.on('resize', handleResize); return () => { stdout.off('resize', handleResize); }; }, [stdout]); const renderAnimation = useCallback(() => { const newFrame = frame.current + 1; frame.current = newFrame; setRenderedFrame(rainbow(truncated(rotated(text, frame.current), width), frame.current)); timeout.current = setTimeout(() => { renderAnimation(); }, 35); }, [text, width]); useLayoutEffect(() => { renderAnimation(); return () => { clearTimeout(timeout.current); }; }, [renderAnimation]); return React.createElement(Text, null, renderedFrame); }); TextAnimation.displayName = 'TextAnimation'; export { TextAnimation }; //# sourceMappingURL=TextAnimation.js.map