Arc Beacon
cellforge/cell-orbit-12FreeComponent
A stepped 8-direction beacon beam sweeps around the circle with a dim opposite echo and diagonal spoke accents.
Install it
npx shadcn@latest add https://cellforge.dev/r/cell-orbit-12.jsonSource
1"use client";23import { useMemo } from "react";45import { CellForgeBase } from "@/components/ui/cellforge-core";6import { useCellForgePhases } from "@/components/ui/cellforge-hooks";7import { isWithinCircularMask } from "@/components/ui/cellforge-core";8import { usePrefersReducedMotion } from "@/components/ui/cellforge-hooks";9import { useSteppedCycle } from "@/components/ui/cellforge-hooks";10import type { DotAnimationResolver, CellForgeCommonProps } from "@/components/ui/cellforge-core";1112export type CellOrbit12Props = CellForgeCommonProps;1314const STEP_COUNT = 36;15const BASE_OPACITY = 0.06;16const MID_OPACITY = 0.3;17const ARC_OPACITY = 0.96;1819export function CellOrbit12({20 speed = 1.7,21 animated = true,22 hoverAnimated = false,23 ...rest24}: CellOrbit12Props) {25 const reducedMotion = usePrefersReducedMotion();26 const { phase: matrixPhase, onMouseEnter, onMouseLeave } = useCellForgePhases({27 animated: Boolean(animated && !reducedMotion),28 hoverAnimated: Boolean(hoverAnimated && !reducedMotion),29 speed30 });31 const step = useSteppedCycle({32 active: !reducedMotion && matrixPhase !== "idle",33 cycleMsBase: 1700,34 steps: STEP_COUNT,35 speed,36 });3738 const resolver = useMemo<DotAnimationResolver>(() => {39 return ({ row, col }) => {40 if (!isWithinCircularMask(row, col)) {41 return { className: "dmx-inactive" };42 }4344 const x = col - 2;45 const y = row - 2;46 const ring = Math.sqrt(x * x + y * y);47 const angle = Math.atan2(y, x);48 const stepBand = Math.floor((step / STEP_COUNT) * 8) % 8;49 const targetAngle = stepBand * (Math.PI / 4);50 const angleDelta = Math.acos(Math.cos(angle - targetAngle));51 const beam = Math.max(0, 1 - angleDelta / 0.42);52 const oppositeBeam = Math.max(0, 1 - Math.acos(Math.cos(angle - (targetAngle + Math.PI))) / 0.62);53 const spokePulse = Math.max(0, 1 - Math.abs(Math.abs(x) - Math.abs(y)) / 0.35);54 const ringTier = ring < 1 ? 0 : ring < 2 ? 1 : 2;5556 let opacity = BASE_OPACITY;57 if (beam > 0.78 && ringTier >= 1) {58 opacity = ARC_OPACITY;59 } else if (beam > 0.48) {60 opacity = 0.62;61 } else if (oppositeBeam > 0.52 && ringTier === 2) {62 opacity = MID_OPACITY;63 } else if (spokePulse > 0.9 && ringTier > 0) {64 opacity = MID_OPACITY;65 }6667 if (x === 0 && y === 0) {68 return { style: { opacity: Math.max(opacity, 0.26) } };69 }7071 return { style: { opacity } };72 };73 }, [step]);74// … truncated
More from @cellforge
All 71 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| All CellForge Loadersall | @cellforge | Components | Free | no deps | |
| Core Spokescell-angle-1 | @cellforge | Components | Free | no deps | |
| Column Rakecell-angle-10 | @cellforge | Components | Free | no deps | |
| Shelf Descentcell-angle-11 | @cellforge | Components | Free | no deps | |
| Skew Driftcell-angle-12 | @cellforge | Components | Free | no deps | |
| Serpent Zipcell-angle-13 | @cellforge | Components | Free | no deps | |
| Pillar Sweepcell-angle-14 | @cellforge | Components | Free | no deps | |
| Tripod Handoffcell-angle-15 | @cellforge | Components | Free | no deps |
