Rocky_Mountain_Vending/.pnpm-store/v10/files/43/47ba645bcd1b77b2a7b32ba4458096956cba87a018f02561939cd436684a4732124dbc6cdc3dba92f0c9fc33ea36b9991c3f8ff5110f0493bb7d1704f249f1
DMleadgen 46d973904b
Initial commit: Rocky Mountain Vending website
Next.js website for Rocky Mountain Vending company featuring:
- Product catalog with Stripe integration
- Service areas and parts pages
- Admin dashboard with Clerk authentication
- SEO optimized pages with JSON-LD structured data

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 16:22:15 -07:00

124 lines
3.1 KiB
Text

/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {FunctionComponent} from 'preact';
import {useEffect, useState} from 'preact/hooks';
import {NavigationIcon, SnapshotIcon, TimespanIcon} from './icons';
import {getFilmstripFrames, getScreenDimensions} from './util';
import {Util} from '../../shared/util.js';
const ANIMATION_FRAME_DURATION_MS = 500;
const Separator: FunctionComponent = () => {
return <div className="Separator" role="separator"></div>;
};
const FlowStepIcon: FunctionComponent<{mode: LH.Result.GatherMode}> = ({mode}) => {
return <>
{
mode === 'navigation' && <NavigationIcon/>
}
{
mode === 'timespan' && <TimespanIcon/>
}
{
mode === 'snapshot' && <SnapshotIcon/>
}
</>;
};
const FlowSegment: FunctionComponent<{mode?: LH.Result.GatherMode}> = ({mode}) => {
return (
<div className="FlowSegment">
<div className="FlowSegment__top-line"/>
{
mode && <FlowStepIcon mode={mode}/>
}
<div className="FlowSegment__bottom-line"/>
</div>
);
};
const FlowStepAnimatedThumbnail: FunctionComponent<{
frames: Array<{data: string}>,
width: number,
height: number,
}> = ({frames, width, height}) => {
const [frameIndex, setFrameIndex] = useState(0);
// Handle a frame array of a different length being set.
const effectiveFrameIndex = frameIndex % frames.length;
useEffect(() => {
const interval = setInterval(
() => setFrameIndex(i => (i + 1) % frames.length),
ANIMATION_FRAME_DURATION_MS
);
return () => clearInterval(interval);
}, [frames.length]);
return (
<img
className="FlowStepThumbnail"
data-testid="FlowStepAnimatedThumbnail"
src={frames[effectiveFrameIndex].data}
style={{width, height}}
alt="Animated screenshots of a page tested by Lighthouse"
/>
);
};
const FlowStepThumbnail: FunctionComponent<{
lhr: LH.Result,
width?: number,
height?: number,
}> = ({lhr, width, height}) => {
const frames = getFilmstripFrames(lhr);
// Resize the image to fit the viewport aspect ratio.
const dimensions = getScreenDimensions(lhr);
if (width && height === undefined) {
height = dimensions.height * width / dimensions.width;
} else if (height && width === undefined) {
width = dimensions.width * height / dimensions.height;
}
if (!width || !height) {
// eslint-disable-next-line no-console
console.warn(new Error('FlowStepThumbnail requested without any dimensions').stack);
return <></>;
}
let thumbnail;
if (frames?.length) {
thumbnail = frames[frames.length - 1].data;
if (lhr.gatherMode === 'timespan') {
return <FlowStepAnimatedThumbnail frames={frames} width={width} height={height} />;
}
} else {
thumbnail = Util.getFullPageScreenshot(lhr)?.screenshot.data;
}
return <>
{
thumbnail &&
<img
className="FlowStepThumbnail"
src={thumbnail}
style={{width, height}}
alt="Screenshot of a page tested by Lighthouse"
/>
}
</>;
};
export {
Separator,
FlowStepIcon,
FlowSegment,
FlowStepThumbnail,
};