{"$schema":"https:\/\/ui.particle.academy\/schema\/registry-item.json","name":"shape-element","type":"registry:ui","title":"ShapeElement","description":"SVG shape primitives \u2014 rect \/ ellipse \/ line \/ arrow \/ triangle.","package":"fancy-slides","dependencies":[],"registryDependencies":["types","theme"],"files":[{"path":"components\/fancy\/shape-element\/ShapeElement.tsx","content":"import type { ShapeElement, Theme } from \"..\/..\/..\/types\";\r\nimport { resolveTheme } from \"..\/..\/..\/theme\/theme-utils\";\r\n\r\nexport interface ShapeElementRendererProps {\r\n    element: ShapeElement;\r\n    theme?: Theme;\r\n    slideWidthPx: number;\r\n}\r\n\r\n\/**\r\n * SVG-rendered shape primitive. Sized to fill its element box; the box\r\n * decides world position via the parent Slide's positioning wrapper.\r\n *\/\r\nexport function ShapeElementRenderer({ element, theme, slideWidthPx }: ShapeElementRendererProps) {\r\n    const t = resolveTheme(theme);\r\n    const designWidth = t.slideWidth ?? 1920;\r\n    const scale = slideWidthPx \/ designWidth;\r\n\r\n    const fill = element.fill ?? \"rgba(139, 92, 246, 0.15)\";\r\n    const stroke = element.stroke ?? t.colors?.accent ?? \"#8b5cf6\";\r\n    const strokeWidth = (element.strokeWidth ?? 2) * scale;\r\n    const dasharray = element.dashed ? `${6 * scale} ${4 * scale}` : undefined;\r\n\r\n    \/\/ SVG uses a 0..100 viewBox so radius\/strokeWidth are in box-relative units\r\n    \/\/ and resolution-independent at render time.\r\n    return (\r\n        <svg\r\n            viewBox=\"0 0 100 100\"\r\n            preserveAspectRatio=\"none\"\r\n            style={{ width: \"100%\", height: \"100%\", display: \"block\", overflow: \"visible\" }}\r\n        >\r\n            {renderShape(element, { fill, stroke, strokeWidth, dasharray })}\r\n        <\/svg>\r\n    );\r\n}\r\n\r\ninterface ShapeStyle {\r\n    fill: string;\r\n    stroke: string;\r\n    strokeWidth: number;\r\n    dasharray?: string;\r\n}\r\n\r\nfunction renderShape(el: ShapeElement, s: ShapeStyle) {\r\n    \/\/ vectorEffect=\"non-scaling-stroke\" keeps the visible stroke at the\r\n    \/\/ pixel width we asked for, regardless of how the parent SVG's\r\n    \/\/ `preserveAspectRatio=\"none\"` stretches the viewBox. Without this,\r\n    \/\/ narrow arrow \/ line boxes shrink the stroke into invisibility because\r\n    \/\/ the y-axis is squashed.\r\n    const common = {\r\n        fill: s.fill,\r\n        stroke: s.stroke,\r\n        strokeWidth: s.strokeWidth,\r\n        strokeDasharray: s.dasharray,\r\n        vectorEffect: \"non-scaling-stroke\" as const,\r\n    };\r\n    switch (el.shape) {\r\n        case \"rect\":\r\n            return <rect x=\"0\" y=\"0\" width=\"100\" height=\"100\" {...common} \/>;\r\n        case \"rounded-rect\": {\r\n            const r = el.radius ?? 8;\r\n            return <rect x=\"0\" y=\"0\" width=\"100\" height=\"100\" rx={r} ry={r} {...common} \/>;\r\n        }\r\n        case \"ellipse\":\r\n            return <ellipse cx=\"50\" cy=\"50\" rx=\"50\" ry=\"50\" {...common} \/>;\r\n        case \"triangle\":\r\n            return <polygon points=\"50,0 100,100 0,100\" {...common} \/>;\r\n        case \"line\":\r\n            return <line x1=\"0\" y1=\"50\" x2=\"100\" y2=\"50\" {...common} fill=\"none\" \/>;\r\n        case \"arrow\":\r\n            \/\/ Render the arrow as a polyline shaft + an inline triangular\r\n            \/\/ head built from the same SVG geometry. Avoids SVG markers,\r\n            \/\/ which scale with stroke-width and turn into specks at tile\r\n            \/\/ sizes.\r\n            return (\r\n                <g>\r\n                    <line x1=\"0\" y1=\"50\" x2=\"85\" y2=\"50\" {...common} fill=\"none\" \/>\r\n                    <polygon points=\"100,50 80,30 80,70\" fill={s.stroke} stroke=\"none\" \/>\r\n                <\/g>\r\n            );\r\n        default:\r\n            return null;\r\n    }\r\n}\r\n","type":"registry:ui","target":"components\/fancy\/shape-element\/ShapeElement.tsx"},{"path":"components\/fancy\/shape-element\/index.ts","content":"export { ShapeElementRenderer } from \".\/ShapeElement\";\r\nexport type { ShapeElementRendererProps } from \".\/ShapeElement\";\r\n","type":"registry:ui","target":"components\/fancy\/shape-element\/index.ts"}]}