{"name":"dot","type":"registry:ui","files":[{"path":"dot.tsx","type":"registry:ui","content":"import type * as echarts from \"echarts/core\";\n\nexport type DotVariant = \"none\" | \"default\" | \"border\" | \"colored-border\" | \"ping\";\n\nexport type DotItemStyleOption = {\n  color?: string | echarts.graphic.LinearGradient;\n  borderColor?: string | echarts.graphic.LinearGradient;\n  borderWidth?: number;\n  opacity?: number;\n};\n\nexport type DotStyle = { size: number; itemStyle: DotItemStyleOption };\n\nfunction withAlpha(color: string, alpha: number): string {\n  if (color.startsWith(\"#\")) {\n    let hex = color.slice(1);\n    if (hex.length === 3)\n      hex = hex\n        .split(\"\")\n        .map((c) => c + c)\n        .join(\"\");\n    const n = parseInt(hex, 16);\n    return `rgba(${(n >> 16) & 255}, ${(n >> 8) & 255}, ${n & 255}, ${alpha})`;\n  }\n  const m = color.match(/rgba?\\(([^)]+)\\)/);\n  if (m) {\n    const [r, g, b] = m[1].split(\",\").map((s) => parseFloat(s));\n    return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n  }\n  return color;\n}\n\nexport function dotItemStyle(\n  variant: DotVariant,\n  paint: string | echarts.graphic.LinearGradient,\n  background: string,\n): DotItemStyleOption {\n  switch (variant) {\n    case \"border\":\n\n      return { color: paint, borderColor: background, borderWidth: 2 };\n    case \"colored-border\":\n\n      return { color: background, borderColor: paint, borderWidth: 1 };\n    case \"ping\": {\n\n      const halo = typeof paint === \"string\" ? withAlpha(paint, 0.28) : paint;\n      return { color: paint, borderColor: halo, borderWidth: 10 };\n    }\n    case \"default\":\n      return { color: paint, borderWidth: 0 };\n    default:\n      return {};\n  }\n}\n\nexport const DOT_SIZES: Record<DotVariant, number> = {\n  none: 0,\n  default: 6,\n  border: 8,\n  \"colored-border\": 6,\n  ping: 8,\n};\n\nexport function dotStyle(\n  variant: DotVariant,\n  paint: string | echarts.graphic.LinearGradient,\n  background: string,\n): DotStyle {\n  return { size: DOT_SIZES[variant], itemStyle: dotItemStyle(variant, paint, background) };\n}\n\nexport function sampleGradient(slots: string[], t: number): string {\n  if (slots.length <= 1) return slots[0] ?? \"rgba(120, 120, 120, 1)\";\n\n  const parse = (color: string) =>\n    color\n      .match(/rgba?\\(([^)]+)\\)/)?.[1]\n      .split(\",\")\n      .map(Number) ?? [120, 120, 120, 1];\n\n  const position = t * (slots.length - 1);\n  const index = Math.min(Math.floor(position), slots.length - 2);\n  const fraction = position - index;\n  const [r1, g1, b1, a1 = 1] = parse(slots[index]);\n  const [r2, g2, b2, a2 = 1] = parse(slots[index + 1]);\n  const lerp = (from: number, to: number) => from + (to - from) * fraction;\n\n  return `rgba(${Math.round(lerp(r1, r2))}, ${Math.round(lerp(g1, g2))}, ${Math.round(lerp(b1, b2))}, ${lerp(a1, a2).toFixed(3)})`;\n}\n","target":"components/ui/dot.tsx"}],"dependencies":["echarts"]}