{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "cap-widget",
  "type": "registry:ui",
  "title": "Cap Widget",
  "description": "A cap widget component",
  "dependencies": [
    "@cap.js/widget"
  ],
  "files": [
    {
      "path": "src/registry/ui/cap-widget.tsx",
      "content": "\"use client\";\n\nimport {\n  forwardRef,\n  useCallback,\n  useEffect,\n  useImperativeHandle,\n  useRef,\n  useState,\n} from \"react\";\n\nimport type React from \"react\";\n\ndeclare module \"react\" {\n  namespace JSX {\n    interface IntrinsicElements {\n      \"cap-widget\": React.DetailedHTMLProps<\n        React.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n    }\n  }\n}\n\ndeclare global {\n  interface Window {\n    CAP_CUSTOM_FETCH?: (url: string, options?: RequestInit) => Promise<unknown>;\n    CAP_CUSTOM_WASM_URL?: string;\n  }\n}\n\ninterface CapWidgetProps\n  extends Omit<React.ComponentProps<\"div\">, \"onError\" | \"onProgress\"> {\n  endpoint: string;\n  workerCount?: number;\n  override?: {\n    wasmUrl?: string;\n    customFetch?: (url: string, options?: RequestInit) => Promise<unknown>;\n  };\n  locale?: {\n    initial?: string;\n    verifying?: string;\n    solved?: string;\n    error?: string;\n    wasmDisabled?: string;\n    verifyingAria?: string;\n    solvedAria?: string;\n    errorAria?: string;\n  };\n  onSolve?: (token: string) => void;\n  onError?: (message: string) => void;\n  onReset?: () => void;\n  onProgress?: (progress: number) => void;\n}\n\nconst CapWidget = forwardRef<HTMLDivElement, CapWidgetProps>(\n  (\n    {\n      endpoint,\n      workerCount,\n      override,\n      locale,\n      onSolve,\n      onError,\n      onReset,\n      onProgress,\n      style,\n      ...props\n    },\n    ref,\n  ) => {\n    const { wasmUrl, customFetch } = override ?? {};\n\n    const [loading, setLoading] = useState(true);\n    const widgetRef = useRef<HTMLDivElement>(null);\n    useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(\n      ref,\n      () => widgetRef.current,\n    );\n\n    const handleSolve = useCallback(\n      (e: Event) => {\n        console.log(\"handleSolve\", e);\n        const customEvent = e as CustomEvent<{ token?: string }>;\n        const token = customEvent.detail?.token;\n        if (!token) return;\n        onSolve?.(token);\n      },\n      [onSolve],\n    );\n\n    const handleError = useCallback(\n      (e: Event) => {\n        const customEvent = e as CustomEvent<{ message?: string }>;\n        const message = customEvent.detail?.message;\n        if (!message) return;\n        onError?.(message);\n      },\n      [onError],\n    );\n\n    const handleReset = useCallback(() => {\n      onReset?.();\n    }, [onReset]);\n\n    const handleProgress = useCallback(\n      (e: Event) => {\n        const customEvent = e as CustomEvent<{ progress?: number }>;\n        const progress = customEvent.detail?.progress ?? 0;\n        onProgress?.(progress);\n      },\n      [onProgress],\n    );\n\n    useEffect(() => {\n      let mounted = true;\n\n      const loadWidget = async () => {\n        // @ts-ignore\n        await import(\"@cap.js/widget\");\n\n        if (mounted) {\n          setLoading(false);\n        }\n      };\n\n      // 只在客户端执行\n      if (typeof window !== \"undefined\") {\n        loadWidget();\n      }\n\n      return () => {\n        mounted = false;\n      };\n    }, []);\n\n    useEffect(() => {\n      if (loading) return;\n      window.CAP_CUSTOM_FETCH = customFetch;\n      window.CAP_CUSTOM_WASM_URL = wasmUrl;\n      const widget = widgetRef.current;\n      if (widget) {\n        widget.addEventListener(\"solve\", handleSolve);\n        widget.addEventListener(\"error\", handleError);\n        widget.addEventListener(\"progress\", handleProgress);\n        widget.addEventListener(\"reset\", handleReset);\n      }\n      return () => {\n        window.CAP_CUSTOM_FETCH = undefined;\n        window.CAP_CUSTOM_WASM_URL = undefined;\n        if (widget) {\n          widget.removeEventListener(\"solve\", handleSolve);\n          widget.removeEventListener(\"error\", handleError);\n          widget.removeEventListener(\"progress\", handleProgress);\n          widget.removeEventListener(\"reset\", handleReset);\n        }\n      };\n    }, [\n      loading,\n      widgetRef,\n      wasmUrl,\n      customFetch,\n      handleReset,\n      handleProgress,\n      handleError,\n      handleSolve,\n    ]);\n\n    if (loading) return null;\n\n    return (\n      <div\n        style={\n          {\n            \"--cap-background\": \"var(--background)\",\n            \"--cap-border-color\": \"var(--border)\",\n            \"--cap-border-radius\": \"14px\",\n            \"--cap-color\": \"var(--foreground)\",\n            \"--cap-checkbox-border\": \"1px solid var(--ring)\",\n            \"--cap-checkbox-background\": \"var(--secondary)\",\n            \"--cap-spinner-color\": \"var(--primary)\",\n            \"--cap-spinner-background-color\": \"var(--primary-foreground)\",\n            ...style,\n          } as React.CSSProperties\n        }\n        {...props}\n      >\n        <cap-widget\n          ref={widgetRef}\n          data-cap-api-endpoint={endpoint}\n          data-cap-worker-count={workerCount}\n          data-cap-i18n-verifying-label={locale?.verifying}\n          data-cap-i18n-initial-state={locale?.initial}\n          data-cap-i18n-solved-label={locale?.solved}\n          data-cap-i18n-error-label={locale?.error}\n          data-cap-i18n-verify-aria-label={locale?.verifyingAria}\n          data-cap-i18n-verifying-aria-label={locale?.verifyingAria}\n          data-cap-i18n-verified-aria-label={locale?.solvedAria}\n          data-cap-i18n-error-aria-label={locale?.errorAria}\n        />\n      </div>\n    );\n  },\n);\n\nCapWidget.displayName = \"CapWidget\";\n\nexport { CapWidget };\n",
      "type": "registry:ui",
      "target": "components/wed/cap-widget.tsx"
    }
  ]
}