{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "pixel-patterns",
  "title": "Pixel Patterns",
  "description": "Deterministic threshold, accent, and easing helpers for pixel-grid transition components.",
  "files": [
    {
      "path": "registry/lib/pixel-patterns/index.ts",
      "content": "export type Direction =\n  | \"top-bottom\"\n  | \"bottom-top\"\n  | \"left-right\"\n  | \"right-left\"\n  | \"center-out\"\n  | \"center-in\";\n\nexport type Pattern =\n  | \"random\"\n  | \"checker\"\n  | \"diagonal\"\n  | \"wave\"\n  | \"spiral\"\n  | \"radial\";\n\nexport type Easing =\n  | \"linear\"\n  | \"ease-in\"\n  | \"ease-out\"\n  | \"ease-in-out\"\n  | \"expo-out\";\n\nfunction seededRandom(row: number, col: number, seed: number): number {\n  const x = Math.sin(row * 127.1 + col * 311.7 + seed * 113.5) * 43758.5453;\n  return x - Math.floor(x);\n}\n\nfunction getDirectionalValue(\n  row: number,\n  col: number,\n  rows: number,\n  cols: number,\n  direction: Direction,\n): number {\n  const nr = rows > 1 ? row / (rows - 1) : 0.5;\n  const nc = cols > 1 ? col / (cols - 1) : 0.5;\n\n  switch (direction) {\n    case \"top-bottom\":\n      return nr;\n    case \"bottom-top\":\n      return 1 - nr;\n    case \"left-right\":\n      return nc;\n    case \"right-left\":\n      return 1 - nc;\n    case \"center-out\": {\n      const dx = nr - 0.5;\n      const dy = nc - 0.5;\n      return Math.min(Math.sqrt(dx * dx + dy * dy) / 0.7071, 1);\n    }\n    case \"center-in\": {\n      const dx = nr - 0.5;\n      const dy = nc - 0.5;\n      return 1 - Math.min(Math.sqrt(dx * dx + dy * dy) / 0.7071, 1);\n    }\n  }\n}\n\nfunction getPatternValue(\n  row: number,\n  col: number,\n  rows: number,\n  cols: number,\n  pattern: Pattern,\n  seed: number,\n): number {\n  const nr = rows > 1 ? row / (rows - 1) : 0.5;\n  const nc = cols > 1 ? col / (cols - 1) : 0.5;\n\n  switch (pattern) {\n    case \"random\":\n      return seededRandom(row, col, seed);\n    case \"checker\":\n      return (row + col) % 2 === 0 ? 0 : 1;\n    case \"diagonal\": {\n      const total = rows + cols - 2;\n      return total > 0 ? (row + col) / total : 0.5;\n    }\n    case \"wave\":\n      return (Math.sin(row * 0.5 + col * 0.3) + 1) / 2;\n    case \"spiral\": {\n      const angle = Math.atan2(nr - 0.5, nc - 0.5);\n      return (angle + Math.PI) / (2 * Math.PI);\n    }\n    case \"radial\": {\n      const dx = nr - 0.5;\n      const dy = nc - 0.5;\n      const dist = Math.sqrt(dx * dx + dy * dy) / 0.7071;\n      return Math.floor(dist * 10) / 10;\n    }\n  }\n}\n\nexport function computeThresholdMap(\n  rows: number,\n  cols: number,\n  direction: Direction,\n  pattern: Pattern,\n  patternIntensity: number,\n  seed = 42,\n): Float32Array {\n  const size = rows * cols;\n  const map = new Float32Array(size);\n\n  let min = Infinity;\n  let max = -Infinity;\n\n  for (let r = 0; r < rows; r++) {\n    for (let c = 0; c < cols; c++) {\n      const dir = getDirectionalValue(r, c, rows, cols, direction);\n      const pat = getPatternValue(r, c, rows, cols, pattern, seed);\n      const value = dir * (1 - patternIntensity) + pat * patternIntensity;\n      const idx = r * cols + c;\n\n      map[idx] = value;\n      if (value < min) min = value;\n      if (value > max) max = value;\n    }\n  }\n\n  const range = max - min || 1;\n  for (let i = 0; i < size; i++) {\n    map[i] = (map[i] - min) / range;\n  }\n\n  return map;\n}\n\nexport function computeAccentMap(\n  rows: number,\n  cols: number,\n  accentShare: number,\n  accentCount: number,\n  seed = 42,\n): Uint8Array {\n  const size = rows * cols;\n  const map = new Uint8Array(size);\n\n  for (let r = 0; r < rows; r++) {\n    for (let c = 0; c < cols; c++) {\n      const rand = seededRandom(r, c, seed + 999);\n      if (rand < accentShare) {\n        map[r * cols + c] =\n          1 + Math.floor(seededRandom(r, c, seed + 1337) * accentCount);\n      }\n    }\n  }\n\n  return map;\n}\n\nexport function applyEasing(t: number, easing: Easing): number {\n  const clamped = Math.max(0, Math.min(1, t));\n\n  switch (easing) {\n    case \"linear\":\n      return clamped;\n    case \"ease-in\":\n      return clamped * clamped;\n    case \"ease-out\":\n      return 1 - (1 - clamped) * (1 - clamped);\n    case \"ease-in-out\":\n      return clamped < 0.5\n        ? 2 * clamped * clamped\n        : 1 - 2 * (1 - clamped) * (1 - clamped);\n    case \"expo-out\":\n      return clamped === 1 ? 1 : 1 - Math.pow(2, -10 * clamped);\n  }\n}\n",
      "type": "registry:lib",
      "target": "lib/pixel-patterns.ts"
    }
  ],
  "type": "registry:lib"
}