spb/phi-conseil
Public
1import type { SVGProps } from "react";2import { buildSpiral } from "@/lib/spiral";34/**5 * Spirale de Fibonacci construite par programme : carrés de côtés6 * 1, 1, 2, 3, 5, 8, 13, 21 (…) disposés en rectangle, et quart de cercle7 * inscrit dans chaque carré. L'approximation du nombre d'or est celle de la8 * suite de Fibonacci (21/13 ≈ 1,615) — ce n'est pas une spirale9 * logarithmique exacte.10 */1112type Props = SVGProps<SVGSVGElement> & {13 levels?: number;14 showSquares?: boolean;15 strokeWidth?: number;16 /** miroir horizontal / vertical pour orienter le motif */17 flipX?: boolean;18 flipY?: boolean;19 title?: string;20};2122export function GoldenSpiral({23 levels = 8,24 showSquares = true,25 strokeWidth = 0.12,26 flipX = false,27 flipY = false,28 title,29 ...rest30}: Props) {31 const { squares, path, bbox } = buildSpiral(levels);32 const pad = strokeWidth;33 const transform = `translate(${flipX ? bbox.x * 2 + bbox.w : 0} ${34 flipY ? bbox.y * 2 + bbox.h : 035 }) scale(${flipX ? -1 : 1} ${flipY ? -1 : 1})`;36 return (37 <svg38 viewBox={`${bbox.x - pad} ${bbox.y - pad} ${bbox.w + pad * 2} ${bbox.h + pad * 2}`}39 fill="none"40 stroke="currentColor"41 strokeWidth={strokeWidth}42 strokeLinecap="round"43 aria-hidden={title ? undefined : true}44 role={title ? "img" : undefined}45 {...rest}46 >47 {title ? <title>{title}</title> : null}48 <g transform={transform}>49 {showSquares50 ? squares.map((sq, i) => (51 <rect52 key={i}53 x={sq.x}54 y={sq.y}55 width={sq.s}56 height={sq.s}57 strokeWidth={strokeWidth * 0.75}58 opacity={0.8}59 />60 ))61 : null}62 <path d={path} />63 </g>64 </svg>65 );66}67