{
	"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
	"name": "hexagon-pattern",
	"title": "Hexagon Pattern",
	"type": "registry:block",
	"description": "An SVG-based hexagon pattern background component with configurable radius, gap, direction, and highlighted cells.",
	"files": [
		{
			"content": "<script lang=\"ts\">\n\timport { cn } from \"$UTILS$\";\n\timport type { SVGAttributes } from \"svelte/elements\";\n\n\ttype Direction = \"horizontal\" | \"vertical\";\n\ttype HexPoint = readonly [number, number];\n\n\tinterface HexagonPatternProps extends SVGAttributes<SVGSVGElement> {\n\t\tradius?: number;\n\t\tgap?: number;\n\t\tx?: number;\n\t\ty?: number;\n\t\tdirection?: Direction;\n\t\tstrokeDasharray?: string;\n\t\thexagons?: Array<[col: number, row: number]>;\n\t\tclass?: string;\n\t}\n\n\tfunction hexVertexList(cx: number, cy: number, r: number, direction: Direction): HexPoint[] {\n\t\tconst startAngle = direction === \"horizontal\" ? 0 : 30;\n\t\treturn Array.from({ length: 6 }, (_, i) => {\n\t\t\tconst angle = ((startAngle + i * 60) * Math.PI) / 180;\n\t\t\treturn [cx + r * Math.cos(angle), cy + r * Math.sin(angle)] as const;\n\t\t});\n\t}\n\n\tfunction hexPoints(cx: number, cy: number, r: number, direction: Direction): string {\n\t\treturn hexVertexList(cx, cy, r, direction)\n\t\t\t.map(([px, py]) => `${px},${py}`)\n\t\t\t.join(\" \");\n\t}\n\n\tfunction edgeLexKey(a: HexPoint, b: HexPoint): string {\n\t\tconst [p, q] = a[0] < b[0] || (a[0] === b[0] && a[1] <= b[1]) ? [a, b] : [b, a];\n\t\treturn `${p[0].toFixed(6)},${p[1].toFixed(6)}|${q[0].toFixed(6)},${q[1].toFixed(6)}`;\n\t}\n\n\tfunction collectUniqueHexEdges(\n\t\tcenters: [number, number][],\n\t\tr: number,\n\t\tdirection: Direction\n\t): [HexPoint, HexPoint][] {\n\t\tconst seen = new Set<string>();\n\t\tconst edges: [HexPoint, HexPoint][] = [];\n\n\t\tfor (const [cx, cy] of centers) {\n\t\t\tconst verts = hexVertexList(cx, cy, r, direction);\n\t\t\tfor (let i = 0; i < 6; i++) {\n\t\t\t\tconst a = verts[i];\n\t\t\t\tconst b = verts[(i + 1) % 6];\n\t\t\t\tconst key = edgeLexKey(a, b);\n\t\t\t\tif (!seen.has(key)) {\n\t\t\t\t\tseen.add(key);\n\t\t\t\t\tedges.push([a, b]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn edges;\n\t}\n\n\tfunction isSolidStrokeDasharray(strokeDasharray: string): boolean {\n\t\tconst t = strokeDasharray.trim();\n\t\treturn t === \"\" || t === \"none\" || t === \"0\";\n\t}\n\n\tfunction getHexSpacing(\n\t\tr: number,\n\t\tdirection: Direction,\n\t\tgap: number\n\t): {\n\t\tcolStep: number;\n\t\trowStep: number;\n\t\ttileW: number;\n\t\ttileH: number;\n\t} {\n\t\tconst sqrt3 = Math.sqrt(3);\n\n\t\tif (direction === \"horizontal\") {\n\t\t\tconst colStep = (3 * r) / 2 + (sqrt3 * gap) / 2;\n\t\t\tconst rowStep = sqrt3 * r + gap;\n\n\t\t\treturn {\n\t\t\t\tcolStep,\n\t\t\t\trowStep,\n\t\t\t\ttileW: colStep * 2,\n\t\t\t\ttileH: rowStep,\n\t\t\t};\n\t\t}\n\n\t\tconst colStep = sqrt3 * r + gap;\n\t\tconst rowStep = (3 * r) / 2 + (sqrt3 * gap) / 2;\n\n\t\treturn {\n\t\t\tcolStep,\n\t\t\trowStep,\n\t\t\ttileW: colStep,\n\t\t\ttileH: rowStep * 2,\n\t\t};\n\t}\n\n\tfunction getTileGeometry(\n\t\tr: number,\n\t\tdirection: Direction,\n\t\tgap: number\n\t): {\n\t\ttileW: number;\n\t\ttileH: number;\n\t\tcenters: [number, number][];\n\t} {\n\t\tif (direction === \"horizontal\") {\n\t\t\tconst { colStep, rowStep, tileW, tileH } = getHexSpacing(r, direction, gap);\n\t\t\tconst canonical: [number, number][] = [\n\t\t\t\t[colStep / 2, rowStep / 2],\n\t\t\t\t[(colStep * 3) / 2, rowStep],\n\t\t\t];\n\n\t\t\tconst centers: [number, number][] = [];\n\t\t\tfor (const [cx, cy] of canonical) {\n\t\t\t\tcenters.push([cx, cy]);\n\t\t\t\tif (cy - r < 0) centers.push([cx, cy + tileH]);\n\t\t\t\tif (cy + r > tileH) centers.push([cx, cy - tileH]);\n\t\t\t\tif (cx - r < 0) centers.push([cx + tileW, cy]);\n\t\t\t\tif (cx + r > tileW) centers.push([cx - tileW, cy]);\n\t\t\t\tif (cy - r < 0 && cx - r < 0) centers.push([cx + tileW, cy + tileH]);\n\t\t\t\tif (cy - r < 0 && cx + r > tileW) centers.push([cx - tileW, cy + tileH]);\n\t\t\t\tif (cy + r > tileH && cx - r < 0) centers.push([cx + tileW, cy - tileH]);\n\t\t\t\tif (cy + r > tileH && cx + r > tileW) centers.push([cx - tileW, cy - tileH]);\n\t\t\t}\n\n\t\t\treturn { tileW, tileH, centers };\n\t\t}\n\n\t\tconst { colStep, rowStep, tileW, tileH } = getHexSpacing(r, direction, gap);\n\t\tconst canonical: [number, number][] = [\n\t\t\t[colStep / 2, rowStep / 2],\n\t\t\t[colStep, (rowStep * 3) / 2],\n\t\t];\n\n\t\tconst centers: [number, number][] = [];\n\t\tfor (const [cx, cy] of canonical) {\n\t\t\tcenters.push([cx, cy]);\n\t\t\tif (cy - r < 0) centers.push([cx, cy + tileH]);\n\t\t\tif (cy + r > tileH) centers.push([cx, cy - tileH]);\n\t\t\tif (cx - r < 0) centers.push([cx + tileW, cy]);\n\t\t\tif (cx + r > tileW) centers.push([cx - tileW, cy]);\n\t\t\tif (cy - r < 0 && cx - r < 0) centers.push([cx + tileW, cy + tileH]);\n\t\t\tif (cy - r < 0 && cx + r > tileW) centers.push([cx - tileW, cy + tileH]);\n\t\t\tif (cy + r > tileH && cx - r < 0) centers.push([cx + tileW, cy - tileH]);\n\t\t\tif (cy + r > tileH && cx + r > tileW) centers.push([cx - tileW, cy - tileH]);\n\t\t}\n\n\t\treturn { tileW, tileH, centers };\n\t}\n\n\tfunction hexCenter(\n\t\tcol: number,\n\t\trow: number,\n\t\tr: number,\n\t\tdirection: Direction,\n\t\tgap: number\n\t): [number, number] {\n\t\tif (direction === \"horizontal\") {\n\t\t\tconst { colStep, rowStep } = getHexSpacing(r, direction, gap);\n\t\t\tconst x = col * colStep + colStep / 2;\n\t\t\tconst y = row * rowStep + rowStep / 2 + (col % 2 !== 0 ? rowStep / 2 : 0);\n\t\t\treturn [x, y];\n\t\t}\n\n\t\tconst { colStep, rowStep } = getHexSpacing(r, direction, gap);\n\t\tconst x = col * colStep + colStep / 2 + (row % 2 !== 0 ? colStep / 2 : 0);\n\t\tconst y = row * rowStep + rowStep / 2;\n\t\treturn [x, y];\n\t}\n\n\tlet {\n\t\tradius = 40,\n\t\tgap = 0,\n\t\tx = -1,\n\t\ty = -1,\n\t\tstrokeDasharray = \"0\",\n\t\tdirection = \"horizontal\",\n\t\thexagons,\n\t\tclass: className,\n\t\t...props\n\t}: HexagonPatternProps = $props();\n\n\tconst id = $props.id();\n\tconst tileGeometry = $derived(getTileGeometry(radius, direction, gap));\n\tconst solidStroke = $derived(isSolidStrokeDasharray(strokeDasharray));\n\tconst dashedEdges = $derived(\n\t\tsolidStroke ? null : collectUniqueHexEdges(tileGeometry.centers, radius, direction)\n\t);\n</script>\n\n<svg\n\taria-hidden=\"true\"\n\tclass={cn(\n\t\t\"pointer-events-none absolute inset-0 h-full w-full fill-gray-400/30 stroke-gray-400/30\",\n\t\tclassName\n\t)}\n\t{...props}\n>\n\t<defs>\n\t\t<pattern\n\t\t\t{id}\n\t\t\twidth={tileGeometry.tileW}\n\t\t\theight={tileGeometry.tileH}\n\t\t\tpatternUnits=\"userSpaceOnUse\"\n\t\t\t{x}\n\t\t\t{y}\n\t\t>\n\t\t\t{#if solidStroke}\n\t\t\t\t{#each tileGeometry.centers as [cx, cy], i (`${cx}-${cy}-${i}`)}\n\t\t\t\t\t<polygon\n\t\t\t\t\t\tclass=\"fill-none\"\n\t\t\t\t\t\tpoints={hexPoints(cx, cy, radius, direction)}\n\t\t\t\t\t\tstroke-dasharray={strokeDasharray}\n\t\t\t\t\t/>\n\t\t\t\t{/each}\n\t\t\t{:else}\n\t\t\t\t{#each dashedEdges ?? [] as [a, b] (edgeLexKey(a, b))}\n\t\t\t\t\t<line\n\t\t\t\t\t\tclass=\"fill-none\"\n\t\t\t\t\t\tx1={a[0]}\n\t\t\t\t\t\tx2={b[0]}\n\t\t\t\t\t\ty1={a[1]}\n\t\t\t\t\t\ty2={b[1]}\n\t\t\t\t\t\tstroke-dasharray={strokeDasharray}\n\t\t\t\t\t/>\n\t\t\t\t{/each}\n\t\t\t{/if}\n\t\t</pattern>\n\t</defs>\n\n\t<rect width=\"100%\" height=\"100%\" fill={`url(#${id})`} stroke=\"none\" />\n\n\t{#if hexagons && hexagons.length > 0}\n\t\t<svg aria-hidden=\"true\" class=\"overflow-visible\" {x} {y}>\n\t\t\t{#each hexagons as [col, row], i (`${col}-${row}-${i}`)}\n\t\t\t\t{@const [cx, cy] = hexCenter(col, row, radius, direction, gap)}\n\t\t\t\t<polygon points={hexPoints(cx, cy, radius - 1, direction)} stroke-width=\"0\" />\n\t\t\t{/each}\n\t\t</svg>\n\t{/if}\n</svg>\n",
			"type": "registry:component",
			"target": "magic/hexagon-pattern/hexagon-pattern.svelte"
		},
		{
			"content": "import HexagonPattern from \"./hexagon-pattern.svelte\";\nexport { HexagonPattern };\n",
			"type": "registry:file",
			"target": "magic/hexagon-pattern/index.ts"
		}
	]
}