---
title: "ஹெட்லெஸ் ஹுக்"
description: "useThunderPhone React ஹுக் மூலம் முழுமையாக தனிப்பயன் குரல் UI-ஐ உருவாக்குங்கள்"
---

`useThunderPhone` ஹுக், பயனர் இடைமுகத்தின் மீது உங்களுக்கு முழுக் கட்டுப்பாட்டை வழங்குகிறது; அதே நேரத்தில் ThunderPhone குரல் அமர்வு, ஆடியோ வழிமாற்றம் மற்றும் இணைப்பு நிலையை நிர்வகிக்கிறது. உங்கள் சொந்த பொத்தான்கள், தளவமைப்புகள், அனிமேஷன்கள் மற்றும் பிராண்டிங்குடன் முழுமையாக தனிப்பயனாக்கப்பட்ட UI வேண்டும் என்றால் இதைப் பயன்படுத்துங்கள்; பின்னணியில் உள்ள அனைத்தையும் ThunderPhone கையாளும்.

## ஹெட்லெஸ் ஹுக்கை எப்போது பயன்படுத்த வேண்டும்

முன்கட்டமைக்கப்பட்ட `ThunderPhoneWidget` கூறு பெரும்பாலான பயன்பாட்டு நிலைகளை உள்ளடக்குகிறது; ஆனால் பின்வருபவை தேவைப்படும்போது ஹெட்லெஸ் ஹுக்கைப் பயன்படுத்துங்கள்:

- உங்கள் பயன்பாட்டின் வடிவமைப்பு அமைப்புடன் பொருந்தும் முழுமையாக தனிப்பயனாக்கப்பட்ட அழைப்பு UI
- நிகழ்நேர ஆடியோ மட்டங்களால் இயக்கப்படும் ஆடியோ-எதிர்வினை காட்சிப்படுத்தல்கள் (வேவ்ஃபார்ம்கள், ஆர்ப்கள், துடிக்கும் குறியீடுகள்)
- அழைப்புக்கு முந்தைய படிவங்கள், அழைப்புக்குப் பிந்தைய கருத்துக்கணிப்புகள் அல்லது குரலுடன் இணைந்த இன்லைன் அரட்டை போன்ற தனிப்பயன் அழைப்பு ஓட்டங்கள்
- ஏற்கனவே உள்ள கூறு நூலகத்துடன் ஒருங்கிணைப்பு (Material UI, Chakra, Radix போன்றவை)

---

## நிறுவல்

```bash
npm install @thunderphone/widget
```

<Note>
  நீங்கள் உங்கள் சொந்த UI-யை வழங்குவதால், ஹெட்லெஸ் ஹுக்கிற்கு `@thunderphone/widget/style.css`-ஐ இறக்குமதி செய்ய வேண்டியதில்லை. இருப்பினும், அதே `@thunderphone/widget` தொகுப்பை நிறுவ வேண்டும்.
</Note>

---

## அடிப்படைப் பயன்பாடு

```tsx
import { useThunderPhone } from '@thunderphone/widget'

function CustomCallButton() {
  const phone = useThunderPhone({
    publishableKey: 'pk_live_your_publishable_key',
  })

  const handleClick = () => {
    if (phone.state === 'connected') {
      phone.disconnect()
    } else {
      phone.connect()
    }
  }

  return (
    <>
      <button onClick={handleClick} disabled={phone.state === 'connecting'}>
        {phone.state === 'connecting'
          ? 'Connecting...'
          : phone.state === 'connected'
            ? 'End call'
            : 'Start call'}
      </button>
      {phone.audio}
    </>
  )
}
```

<Warning>
  **உங்கள் கூறு மரத்தில் எங்காவது `phone.audio`-வை ரெண்டர் செய்ய வேண்டும்.** இது அடிப்படையிலுள்ள ஆடியோ இணைப்பை நிர்வகிக்கும் கண்ணுக்குத் தெரியாத React உறுப்பு. இதை விடுத்தால், எந்த ஆடியோவும் இயங்காது; அமர்வும் செயல்படாது.
</Warning>

---

## விருப்பங்கள்

`UseThunderPhoneOptions` மூலம் இந்த விருப்பங்களை `useThunderPhone`-க்கு அனுப்புங்கள்:

| விருப்பம் | வகை | கட்டாயம் | இயல்புநிலை | விளக்கம் |
|--------|------|----------|---------|-------------|
| `publishableKey` | `string` | ஆம் | -- | வெளியிடக்கூடிய API விசை (`pk_live_...`). விசையின் விட்ஜெட் கட்டமைப்பிலிருந்து ஏஜென்ட் தானாகத் தீர்மானிக்கப்படுகிறது. |
| `apiBase` | `string` | இல்லை | `'https://api.thunderphone.com/v1'` | API அடிப்படை URL மேலெழுதுதல். |
| `language` | `string` | இல்லை | -- | ஒவ்வொரு அமர்விற்குமான மொழி மேலெழுதுதல் -- `en`, `es`, அல்லது `fr-FR` போன்ற மொழிக் குறியீடு அல்லது லோகேல். அமைக்கப்படாதபோது, ஏஜென்ட்டின் கட்டமைக்கப்பட்ட மொழி பயன்படுத்தப்படும். |
| `voice` | `string` | இல்லை | -- | ஒவ்வொரு அமர்விற்குமான குரல் மேலெழுதுதல் -- `maria` போன்ற குரல் பெயர். அமைக்கப்படாதபோது, ஏஜென்ட்டின் கட்டமைக்கப்பட்ட குரல் பயன்படுத்தப்படும். |
| `context` | `string` | இல்லை | -- | ஏஜென்ட்டுக்கு அனுப்பப்படும் ஒவ்வொரு அமர்விற்குமான உண்மைத் தகவல்களைக் கொண்ட பக்கம் அல்லது தளச் சூழல். சர்வர் பக்கத்தில் 12,000 எழுத்துகளாகக் குறைக்கப்படும். |
| `onConnect` | `() => void` | இல்லை | -- | குரல் அமர்வு இணைக்கப்படும்போது அழைக்கப்படும். |
| `onDisconnect` | `() => void` | இல்லை | -- | அமர்வு முடிவடையும்போது அழைக்கப்படும். |
| `onError` | `(error) => void` | இல்லை | -- | பிழைகள் ஏற்பட்டால் அழைக்கப்படும். பிழையில் `error` (குறியீடு) மற்றும் `message` புலங்கள் உள்ளன. |
| `ringtone` | `boolean \| string` | இல்லை | `false` | இணைக்கும்போது ரிங்டோனை இயக்கவும். இயல்புநிலை ரிங்டோனுக்கு `true` அல்லது தனிப்பயன் ஆடியோவுக்கு URL சரம் பயன்படுத்தவும். |

<Note>
  இந்த ஹுக் ஹெட்லெஸ் ஆகும்: இது `ThunderPhoneWidget` தோற்ற பண்புகளை (`theme`, `primaryColor`, `title`, `position`, `className`) ஏற்காது. அவற்றை அனுப்புவது TypeScript பிழையாகும் -- காட்சியமைப்பை முழுமையாக நீங்கள் உருவாக்க வேண்டும்.
</Note>

---

## திரும்பும் மதிப்பு

ஹூக் ஒரு `UseThunderPhoneReturn` ஆப்ஜெக்டைத் திருப்புகிறது:

| பண்பு | வகை | விளக்கம் |
|----------|------|-------------|
| `state` | `'idle' \| 'connecting' \| 'connected' \| 'disconnected' \| 'error'` | தற்போதைய இணைப்பு நிலை. |
| `connect` | `() => void` | குரல் அமர்வைத் தொடங்குங்கள். |
| `disconnect` | `() => void` | தற்போதைய அமர்வை முடிக்கவும். |
| `toggleMute` | `() => void` | மைக்ரோஃபோன் ஒலியடக்கத்தை ஆன்/ஆஃப் செய்யவும். |
| `isMuted` | `boolean` | மைக்ரோஃபோன் தற்போது ஒலியடக்கப்பட்டுள்ளதா என்பதைச் சொல்கிறது. |
| `error` | `string \| undefined` | நிலை `'error'` ஆக இருக்கும்போது பிழைச் செய்தி. |
| `agentName` | `string \| undefined` | இணைக்கப்பட்ட ஏஜென்ட்டின் காட்டப்படும் பெயர். |
| `audioLevel` | `number` | **நிராகரிக்கப்பட்டது -- எப்போதும் `0`.** பின்தொடர் இணக்கத்திற்காக வைத்திருக்கும் நிலையான இடப்பிடிப்பான்; இது ஒருபோதும் புதுப்பிக்கப்படாது. அதற்கு பதிலாக `audioLevelRef.current` ஐப் படியுங்கள். |
| `audioLevelRef` | `React.RefObject<number>` | ஏஜென்ட்டின் குரல் மற்றும் பார்வையாளரின் மைக்ரோஃபோன் ஒலியில் அதிகமானது எனும் நிகழ்நேர ஆடியோ அளவை (0--1) கொண்டுள்ள மாற்றக்கூடிய ref -- React-இன் render சுழற்சிக்கு வெளியே, ஒவ்வொரு animation frame-இலும் புதுப்பிக்கப்படும். மென்மையான, தடையற்ற அனிமேஷன்களுக்காக `requestAnimationFrame` லூப்களுக்குள் `audioLevelRef.current` ஐப் படியுங்கள் அல்லது React state-இல் மதிப்பு தேவைப்படும்போது இடைவெளியில் அதை மாதிரியாக எடுத்துக்கொள்ளுங்கள். |
| `audio` | `ReactNode` | ஆடியோ இணைப்பைக் கையாளும் கண்ணுக்குத் தெரியாத உறுப்பு -- **கட்டாயமாக render செய்யப்பட வேண்டும்**. |

---

## ஒலிக்குப் பதிலளிக்கும் UI

`audioLevelRef` ref, React மறு-ரெண்டர்களைத் தூண்டாமல் உங்களுக்கு பிரேம்-விகித ஒலி அளவுகளை வழங்குகிறது. இதனால் மென்மையான அலைவடிவக் காட்சிப்படுத்தல்கள், துடிக்கும் கோளங்கள் அல்லது உரையாடலுடன் இணைந்த எந்த அனிமேஷனையும் இயக்க இது ஏற்றதாகும். ஏஜென்டின் குரல் அல்லது பார்வையாளரின் மைக்ரோஃபோன் ஆகியவற்றில் எது அதிக ஒலியுடன் இருக்கிறதோ அதை இந்த அளவு பிரதிபலிக்கும்.

### அலைவடிவ உதாரணம்

```tsx
import { useRef, useEffect } from 'react'
import { useThunderPhone } from '@thunderphone/widget'

function WaveformCall() {
  const phone = useThunderPhone({
    publishableKey: 'pk_live_your_publishable_key',
  })
  const canvasRef = useRef<HTMLCanvasElement>(null)

  useEffect(() => {
    if (phone.state !== 'connected') return
    const canvas = canvasRef.current
    if (!canvas) return
    const ctx = canvas.getContext('2d')!

    let animId: number
    const draw = () => {
      const level = phone.audioLevelRef.current ?? 0
      ctx.clearRect(0, 0, canvas.width, canvas.height)

      // Draw bars that react to audio level
      const barCount = 24
      const barWidth = canvas.width / barCount
      for (let i = 0; i < barCount; i++) {
        const distance = Math.abs(i - barCount / 2) / (barCount / 2)
        const height = level * canvas.height * (1 - distance * 0.6)
        const y = (canvas.height - height) / 2
        ctx.fillStyle = '#0ea5e9'
        ctx.fillRect(i * barWidth + 1, y, barWidth - 2, height)
      }

      animId = requestAnimationFrame(draw)
    }
    animId = requestAnimationFrame(draw)
    return () => cancelAnimationFrame(animId)
  }, [phone.state, phone.audioLevelRef])

  return (
    <div>
      {phone.state === 'connected' && (
        <canvas ref={canvasRef} width={240} height={80} />
      )}
      <button
        onClick={phone.state === 'connected' ? phone.disconnect : phone.connect}
        disabled={phone.state === 'connecting'}
      >
        {phone.state === 'connected' ? 'End call' : 'Start call'}
      </button>
      {phone.audio}
    </div>
  )
}
```

### துடிக்கும் கோள உதாரணம்

```tsx
import { useRef, useEffect } from 'react'
import { useThunderPhone } from '@thunderphone/widget'

function PulsingOrb() {
  const phone = useThunderPhone({
    publishableKey: 'pk_live_your_publishable_key',
  })
  const orbRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    if (phone.state !== 'connected') return
    let animId: number
    const animate = () => {
      const level = phone.audioLevelRef.current ?? 0
      if (orbRef.current) {
        const scale = 1 + level * 0.5
        orbRef.current.style.transform = `scale(${scale})`
        orbRef.current.style.opacity = `${0.6 + level * 0.4}`
      }
      animId = requestAnimationFrame(animate)
    }
    animId = requestAnimationFrame(animate)
    return () => cancelAnimationFrame(animId)
  }, [phone.state, phone.audioLevelRef])

  return (
    <div style={{ textAlign: 'center' }}>
      <div
        ref={orbRef}
        style={{
          width: 80,
          height: 80,
          borderRadius: '50%',
          background: '#0ea5e9',
          margin: '20px auto',
          transition: 'transform 0.05s ease-out',
        }}
      />
      <button
        onClick={phone.state === 'connected' ? phone.disconnect : phone.connect}
        disabled={phone.state === 'connecting'}
      >
        {phone.state === 'connected' ? 'End call' : 'Call'}
      </button>
      {phone.audio}
    </div>
  )
}
```

### பேசும் நிலைக் குறியீட்டு உதாரணம்

ஒலி அளவுடன் மாறும் React-ரெண்டர் செய்யப்பட்ட UIக்கு -- வரம்பு அடிப்படையிலான “பேசுகிறது” பேட்ஜ் போன்றது -- `audioLevelRef.current`-ஐ ஒரு இடைவெளியில் மாதிரியாக எடுத்து, முடிவை நிலைமையில் சேமிக்கவும்:

```tsx
import { useEffect, useState } from 'react'
import { useThunderPhone } from '@thunderphone/widget'

function SpeakingBadge() {
  const phone = useThunderPhone({
    publishableKey: 'pk_live_your_publishable_key',
  })
  const [speaking, setSpeaking] = useState(false)

  useEffect(() => {
    if (phone.state !== 'connected') {
      setSpeaking(false)
      return
    }
    const interval = setInterval(() => {
      setSpeaking((phone.audioLevelRef.current ?? 0) > 0.1)
    }, 100)
    return () => clearInterval(interval)
  }, [phone.state, phone.audioLevelRef])

  return (
    <div>
      {phone.state === 'connected' && (
        <span>{speaking ? 'Speaking' : 'Listening'}</span>
      )}
      <button onClick={phone.state === 'connected' ? phone.disconnect : phone.connect}>
        {phone.state === 'connected' ? 'End call' : 'Start call'}
      </button>
      {phone.audio}
    </div>
  )
}
```

<Warning>
  எப்போதும் `audioLevelRef.current`-இலிருந்து அளவுகளைப் படிக்கவும். திரும்பும் பொருளில் உள்ள `audioLevel` எண் **நிராகரிக்கப்பட்டது, எப்போதும் `0` ஆகவே இருக்கும்** -- அதனை அடிப்படையாகக் கொண்ட எந்த தர்க்கமும் அமைதியாக பூஜ்ஜியத்தையே படிக்கும்.
</Warning>

---

## நிலை இயந்திரம்

`state` பண்பு இந்த வாழ்க்கைச்சுழற்சியைப் பின்பற்றுகிறது:

```
idle --> connecting --> connected --> disconnected --> idle (after 1.5s)
                  \
                   --> error (stays until connect() is called again)
```

| நிலை | விளக்கம் |
|-------|-------------|
| `idle` | செயலில் உள்ள அமர்வு இல்லை. `connect()` ஐ அழைக்கத் தயாராக உள்ளது. |
| `connecting` | அமர்வு நிறுவப்படுகிறது. இந்த நிலையில் அழைப்பு பொத்தானை முடக்கவும். |
| `connected` | குரல் அமர்வு செயலில் உள்ளது. பயனர் ஏஜென்ட்டுடன் பேசுகிறார். |
| `disconnected` | அமர்வு சுத்தமாக முடிந்தது. 1.5 வினாடிகளுக்குப் பிறகு தானாகவே மீண்டும் `idle` க்கு மாறும். |
| `error` | ஏதோ தவறு ஏற்பட்டது. செய்திக்காக `phone.error` ஐச் சரிபார்க்கவும். நிலை தானாகவே **அழிக்கப்படாது** -- மீண்டும் `connect()` ஐ அழைப்பது புதிய முயற்சியைத் தொடங்கி பிழையை மீட்டமைக்கும். |

---

## எடுத்துக்காட்டுகள்

### மியூட் கட்டுப்பாட்டுடன்

```tsx
import { useThunderPhone } from '@thunderphone/widget'

function CallWithMute() {
  const phone = useThunderPhone({
    publishableKey: 'pk_live_your_publishable_key',
  })

  return (
    <div>
      {phone.state === 'connected' && (
        <div>
          <p>Talking to {phone.agentName ?? 'Agent'}</p>
          <button onClick={phone.toggleMute}>
            {phone.isMuted ? 'Unmute' : 'Mute'}
          </button>
          <button onClick={phone.disconnect}>End call</button>
        </div>
      )}

      {phone.state !== 'connected' && (
        <button
          onClick={phone.connect}
          disabled={phone.state === 'connecting'}
        >
          {phone.state === 'connecting' ? 'Connecting...' : 'Call support'}
        </button>
      )}

      {phone.state === 'error' && (
        <p style={{ color: 'red' }}>{phone.error}</p>
      )}

      {phone.audio}
    </div>
  )
}
```

### ரிங்டோனுடன்

தொலைபேசி அழைப்பை உருவகப்படுத்த, இணைக்கும் போது ரிங் ஒலியை இயக்கவும்:

```tsx
import { useThunderPhone } from '@thunderphone/widget'

function PhoneCallButton() {
  const phone = useThunderPhone({
    publishableKey: 'pk_live_your_publishable_key',
    ringtone: true, // or a custom URL: 'https://example.com/ringtone.mp3'
  })

  return (
    <>
      <button
        onClick={phone.state === 'connected' ? phone.disconnect : phone.connect}
        disabled={phone.state === 'connecting'}
      >
        {phone.state === 'connecting'
          ? 'Ringing...'
          : phone.state === 'connected'
            ? 'Hang up'
            : 'Call'}
      </button>
      {phone.audio}
    </>
  )
}
```

ரிங்டோன் `connecting` நிலையில் தொடர்ந்து ஒலிக்கும்; ஏஜென்ட் இணைந்தவுடன் மெதுவாக மறையும். உள்ளமைக்கப்பட்ட இயல்புநிலை ரிங்டோனுக்கு `true`-ஐ அனுப்பவும் அல்லது உங்கள் சொந்த ஆடியோ கோப்பைப் பயன்படுத்த URL சரத்தை அனுப்பவும்.

### நிகழ்வு கால்பேக்குகளுடன்

```tsx
import { useThunderPhone } from '@thunderphone/widget'

function TrackedCallButton() {
  const phone = useThunderPhone({
    publishableKey: 'pk_live_your_publishable_key',
    onConnect: () => {
      analytics.track('call_started')
    },
    onDisconnect: () => {
      analytics.track('call_ended')
    },
    onError: (error) => {
      analytics.track('call_error', { code: error.error, message: error.message })
    },
  })

  return (
    <>
      <button
        onClick={phone.state === 'connected' ? phone.disconnect : phone.connect}
        disabled={phone.state === 'connecting'}
      >
        {phone.state === 'connected' ? 'Hang up' : 'Talk to AI'}
      </button>
      {phone.audio}
    </>
  )
}
```

### முழுமையான தனிப்பயன் UI

```tsx
import { useThunderPhone } from '@thunderphone/widget'

function FullCustomUI() {
  const phone = useThunderPhone({
    publishableKey: 'pk_live_your_publishable_key',
  })

  return (
    <div className="call-panel">
      <div className="call-status">
        {phone.state === 'idle' && <span>Ready</span>}
        {phone.state === 'connecting' && <span className="pulse">Connecting...</span>}
        {phone.state === 'connected' && (
          <span>On call with {phone.agentName}</span>
        )}
        {phone.state === 'error' && <span className="error">{phone.error}</span>}
      </div>

      <div className="call-controls">
        {phone.state === 'connected' ? (
          <>
            <button className="mute-btn" onClick={phone.toggleMute}>
              {phone.isMuted ? 'Unmute' : 'Mute'}
            </button>
            <button className="end-btn" onClick={phone.disconnect}>
              End
            </button>
          </>
        ) : (
          <button
            className="start-btn"
            onClick={phone.connect}
            disabled={phone.state === 'connecting'}
          >
            Start call
          </button>
        )}
      </div>

      {/* Required -- handles audio under the hood */}
      {phone.audio}
    </div>
  )
}
```

---

## குறிப்புகள்

<AccordionGroup>
  <Accordion title="phone.audio-ஐ எப்போதும் ரெண்டர் செய்யுங்கள்">
    `phone.audio` உறுப்பு கண்ணுக்குத் தெரியாதது, ஆனால் அவசியமானது. அதை உங்கள் JSX-இல் எங்கு வேண்டுமானாலும் வையுங்கள் -- அது காட்சியளிக்கும் DOM எதையும் ரெண்டர் செய்யாது, ஆனால் WebRTC ஆடியோ இணைப்பை உள்புறமாக நிர்வகிக்கும்.
  </Accordion>

  <Accordion title="இணைக்கும்போது பொத்தானை முடக்குங்கள்">
    `connecting` நிலை 1-3 வினாடிகள் நீடிக்கலாம். நகல் இணைப்பு முயற்சிகளைத் தடுக்க, இந்த நிலையில் அழைப்பு பொத்தானை முடக்குங்கள்.
  </Accordion>

  <Accordion title="பிழை நிலையை நேர்த்தியாகக் கையாளுங்கள்">
    நிலை `error` ஆக இருக்கும்போது, பயனருக்குக் `phone.error`-ஐக் காட்டி, உங்கள் அழைப்பு பொத்தானை இயக்கப்பட்ட நிலையிலேயே வைத்திருங்கள். ஹுக் தானாகவே `error` நிலையிலிருந்து வெளியேறாது -- மீண்டும் `connect()`-ஐ அழைப்பது புதிய முயற்சியைத் தொடங்கி, முந்தைய பிழையை நீக்கும்.
  </Accordion>

  <Accordion title="பக்க விளைவுகளுக்கு கால்பேக்குகளைப் பயன்படுத்துங்கள்">
    `onConnect`, `onDisconnect`, மற்றும் `onError` கால்பேக்குகள், நிலையைப் போலிங் செய்யாமல் பகுப்பாய்வு, பதிவேற்றம் அல்லது பிற பயன்பாட்டு தர்க்கத்தைத் தூண்டுவதற்கு ஏற்றவை.
  </Accordion>

  <Accordion title="audioLevelRef-இலிருந்து ஆடியோ நிலைகளைப் படியுங்கள்">
    `audioLevelRef` மட்டுமே நேரடி ஆடியோ-நிலை மூலமாகும். வேவ்ஃபார்ம் போன்ற மென்மையான அனிமேஷன்களுக்காக `requestAnimationFrame`-க்குள் `audioLevelRef.current`-ஐப் படியுங்கள் (ஒரு ref-ஐப் படிப்பது மறுரெண்டர்களை ஏற்படுத்தாது), அல்லது இடைவெளியில் அதை மாதிரியாக எடுத்து முடிவை React-ஆல் ரெண்டர் செய்யப்படும் UI-க்கான நிலையில் சேமியுங்கள். `audioLevel` எண் காலாவதியானது, எப்போதும் `0` ஆகவே இருக்கும் -- அதனை அடிப்படையாகக் கொண்டு தர்க்கத்தை உருவாக்காதீர்கள்.
  </Accordion>
</AccordionGroup>
