@lofcz/orb-ui 0.7.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +25 -1
  3. package/dist/adapters/audio-level.d.ts +0 -0
  4. package/dist/adapters/elevenlabs/index.d.ts +0 -0
  5. package/dist/adapters/gemini-live/index.d.ts +0 -0
  6. package/dist/adapters/index.d.ts +0 -0
  7. package/dist/adapters/livekit/browser.d.ts +0 -0
  8. package/dist/adapters/livekit/index.d.ts +0 -0
  9. package/dist/adapters/openai-realtime/index.d.ts +0 -0
  10. package/dist/adapters/pipecat/index.d.ts +0 -0
  11. package/dist/adapters/types.d.ts +0 -0
  12. package/dist/adapters/vapi/index.d.ts +0 -0
  13. package/dist/adapters.cjs +0 -0
  14. package/dist/adapters.js +0 -0
  15. package/dist/components/Orb/Orb.d.ts +1 -1
  16. package/dist/components/Orb/Orb.types.d.ts +35 -1
  17. package/dist/components/Orb/index.d.ts +1 -1
  18. package/dist/components/Orb/signals.d.ts +0 -0
  19. package/dist/index.d.ts +1 -1
  20. package/dist/livekit-D-s4sYba.cjs +0 -0
  21. package/dist/livekit-Z3IMmWaG.js +0 -0
  22. package/dist/livekit-adapter.cjs +0 -0
  23. package/dist/livekit-adapter.js +0 -0
  24. package/dist/orb-ui.cjs +1 -1
  25. package/dist/orb-ui.js +266 -210
  26. package/dist/themes/bars/BarsTheme.d.ts +0 -0
  27. package/dist/themes/bars/index.d.ts +0 -0
  28. package/dist/themes/circle/CircleTheme.d.ts +0 -0
  29. package/dist/themes/circle/index.d.ts +0 -0
  30. package/dist/themes/cloud/CloudTheme.d.ts +0 -0
  31. package/dist/themes/cloud/index.d.ts +0 -0
  32. package/dist/themes/debug/DebugTheme.d.ts +0 -0
  33. package/dist/themes/debug/index.d.ts +0 -0
  34. package/dist/themes/index.d.ts +0 -0
  35. package/dist/themes/radial/RadialTheme.d.ts +0 -0
  36. package/dist/themes/radial/index.d.ts +0 -0
  37. package/package.json +13 -5
package/LICENSE CHANGED
File without changes
package/README.md CHANGED
@@ -267,6 +267,29 @@ the orb with the typed style variable:
267
267
  <Orb adapter={adapter} theme="radial" style={{ '--orb-ui-radial-control-surround': '#101010' }} />
268
268
  ```
269
269
 
270
+ ### Custom renderer
271
+
272
+ For an app-owned voice stack (Gemini Live, custom Web Audio), keep session control outside the orb and draw your own artwork. Orb still normalizes `state`, input/output volume, and activity:
273
+
274
+ ```tsx
275
+ import { Orb } from '@lofcz/orb-ui'
276
+
277
+ <Orb
278
+ signal={{ state: 'listening', inputVolume: 0.4, outputVolume: 0 }}
279
+ interactive={false}
280
+ renderTheme={({ rootProps, state, activity, inputVolume, outputVolume }) => (
281
+ <div {...rootProps} data-voice-orb={state}>
282
+ {/* canvas / svg / css — activity is 0–1 for the current state */}
283
+ <span>{activity.toFixed(2)}</span>
284
+ <span>{inputVolume.toFixed(2)}</span>
285
+ <span>{outputVolume.toFixed(2)}</span>
286
+ </div>
287
+ )}
288
+ />
289
+ ```
290
+
291
+ `theme` is ignored when `renderTheme` is set.
292
+
270
293
  ## Props
271
294
 
272
295
  | Prop | Type | Default | Description |
@@ -284,6 +307,7 @@ the orb with the typed style variable:
284
307
  | `aria-label` | `string` | generated | Accessible label for clickable visual themes |
285
308
  | `onStart` | `() => void` | — | Custom start handler (overrides adapter.start()) |
286
309
  | `onStop` | `() => void` | — | Custom stop handler (overrides adapter.stop()) |
310
+ | `renderTheme` | `OrbThemeRenderer` | — | Custom artwork; Orb still owns state and volume |
287
311
 
288
312
  ## States
289
313
 
@@ -299,7 +323,7 @@ the orb with the typed style variable:
299
323
  | [Pipecat](https://pipecat.ai) | `createPipecatAdapter` from `@lofcz/orb-ui/adapters` |
300
324
  | [OpenAI Realtime](https://developers.openai.com/api/docs/guides/realtime) | `createOpenAIRealtimeAdapter` from `@lofcz/orb-ui/adapters` |
301
325
  | [Gemini Live](https://ai.google.dev/gemini-api/docs/live-api) | `createGeminiLiveAdapter` from `@lofcz/orb-ui/adapters` |
302
- | Custom | Use controlled mode — pass `signal`, or `state` and `volume` directly |
326
+ | Custom / Gemini Live (app-owned session) | Controlled mode — pass `signal` or `state` + `volume`, plus `renderTheme` |
303
327
 
304
328
  ## Development
305
329
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/dist/adapters.cjs CHANGED
File without changes
package/dist/adapters.js CHANGED
File without changes
@@ -1,2 +1,2 @@
1
1
  import { OrbProps } from './Orb.types.js';
2
- export declare function Orb({ signal: signalProp, state: stateProp, volume: volumeProp, adapter, theme, size, className, style, disabled, interactive: interactiveProp, onStart, onStop, ...htmlProps }: OrbProps): import("react").JSX.Element;
2
+ export declare function Orb({ signal: signalProp, state: stateProp, volume: volumeProp, adapter, theme, size, className, style, disabled, interactive: interactiveProp, onStart, onStop, renderTheme, ...htmlProps }: OrbProps): string | number | boolean | Iterable<import('react').ReactNode> | import("react").JSX.Element | null | undefined;
@@ -1,4 +1,4 @@
1
- import { AriaAttributes, CSSProperties } from 'react';
1
+ import { AriaAttributes, CSSProperties, ReactNode } from 'react';
2
2
  export type OrbStyle = CSSProperties & {
3
3
  /** Background color revealed around the radial theme's floating phone control. */
4
4
  '--orb-ui-radial-control-surround'?: string;
@@ -83,5 +83,39 @@ export interface OrbProps extends OrbHtmlAttributes {
83
83
  * Overrides adapter.stop() when provided.
84
84
  */
85
85
  onStop?: () => void;
86
+ /**
87
+ * Replace built-in themes with custom artwork. Orb still owns state,
88
+ * volume, and start/stop. `theme` is ignored when this is set.
89
+ */
90
+ renderTheme?: OrbThemeRenderer;
91
+ }
92
+ export interface OrbThemeRendererRootProps extends OrbHtmlAttributes {
93
+ ref?: (element: HTMLElement | null) => void;
94
+ className?: string;
95
+ style?: OrbStyle;
96
+ }
97
+ export interface OrbThemeRendererControlProps extends OrbHtmlAttributes {
98
+ type: 'button';
99
+ className?: string;
100
+ style?: CSSProperties;
101
+ disabled: boolean;
102
+ onClick?: () => void;
103
+ }
104
+ export interface OrbThemeRendererProps {
105
+ state: OrbState;
106
+ signal: OrbSignal;
107
+ inputVolume: number;
108
+ outputVolume: number;
109
+ activity: number;
110
+ size: number;
111
+ isActive: boolean;
112
+ interactive: boolean;
113
+ disabled: boolean;
114
+ start: () => void | Promise<void>;
115
+ stop: () => void | Promise<void>;
116
+ toggle: () => void | Promise<void>;
117
+ rootProps: OrbThemeRendererRootProps;
118
+ controlProps: OrbThemeRendererControlProps;
86
119
  }
120
+ export type OrbThemeRenderer = (props: OrbThemeRendererProps) => ReactNode;
87
121
  export {};
@@ -1,2 +1,2 @@
1
1
  export { Orb } from './Orb.js';
2
- export type { OrbAdapter, OrbProps, OrbSignal, OrbSignalListener, OrbState, OrbStyle, OrbTheme, } from './Orb.types.js';
2
+ export type { OrbAdapter, OrbProps, OrbSignal, OrbSignalListener, OrbState, OrbStyle, OrbTheme, OrbThemeRenderer, OrbThemeRendererControlProps, OrbThemeRendererProps, OrbThemeRendererRootProps, } from './Orb.types.js';
File without changes
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { Orb } from './components/Orb/index.js';
2
- export type { OrbAdapter, OrbProps, OrbSignal, OrbSignalListener, OrbState, OrbStyle, OrbTheme, } from './components/Orb/index.js';
2
+ export type { OrbAdapter, OrbProps, OrbSignal, OrbSignalListener, OrbState, OrbStyle, OrbTheme, OrbThemeRenderer, OrbThemeRendererControlProps, OrbThemeRendererProps, OrbThemeRendererRootProps, } from './components/Orb/index.js';
3
3
  export { Orb as VoiceOrb } from './components/Orb/index.js';
4
4
  export type { OrbProps as VoiceOrbProps } from './components/Orb/index.js';
File without changes
File without changes
File without changes
File without changes
package/dist/orb-ui.cjs CHANGED
@@ -200,4 +200,4 @@ void main() {
200
200
  @media (prefers-reduced-motion: reduce) {
201
201
  [data-radial-spinner] { animation: none !important; }
202
202
  }
203
- `,se=.66,ce=.2;function X(e,t=0,n=1){return Math.min(n,Math.max(t,e))}function Z(e,t,n,r){return e+(t-e)*(1-Math.exp(-n*r))}function Q(e,t,n){let r=e.createShader(t);if(r){if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){e.deleteShader(r);return}return r}}function le(e,t){let n=e.getContext(`webgl`,{alpha:!0,antialias:!0,premultipliedAlpha:!0});if(!n)return;let r=Q(n,n.VERTEX_SHADER,ie),i=Q(n,n.FRAGMENT_SHADER,ae);if(!r||!i){r&&n.deleteShader(r),i&&n.deleteShader(i);return}let a=n.createProgram(),o=n.createBuffer();if(!a||!o){a&&n.deleteProgram(a),o&&n.deleteBuffer(o),n.deleteShader(r),n.deleteShader(i);return}if(n.attachShader(a,r),n.attachShader(a,i),n.linkProgram(a),!n.getProgramParameter(a,n.LINK_STATUS)){n.deleteProgram(a),n.deleteBuffer(o),n.deleteShader(r),n.deleteShader(i);return}let s=n.getAttribLocation(a,`a_position`),c=n.getUniformLocation(a,`u_resolution`),l=n.getUniformLocation(a,`u_time`),u=n.getUniformLocation(a,`u_rotation`),d=n.getUniformLocation(a,`u_listen`),f=n.getUniformLocation(a,`u_speak`);if(s<0||!c||!l||!u||!d||!f){n.deleteProgram(a),n.deleteBuffer(o),n.deleteShader(r),n.deleteShader(i);return}let p=Math.min(window.devicePixelRatio||1,2),m=Math.max(1,Math.round(t*p));return e.width=m,e.height=m,n.viewport(0,0,m,m),n.useProgram(a),n.bindBuffer(n.ARRAY_BUFFER,o),n.bufferData(n.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]),n.STATIC_DRAW),n.enableVertexAttribArray(s),n.vertexAttribPointer(s,2,n.FLOAT,!1,0,0),n.uniform2f(c,m,m),{draw(e,t,r,i){n.uniform1f(l,e),n.uniform1f(u,t),n.uniform1f(d,r),n.uniform1f(f,i),n.drawArrays(n.TRIANGLES,0,6)},destroy(){n.deleteProgram(a),n.deleteBuffer(o),n.deleteShader(r),n.deleteShader(i)}}}function ue(e){return e!==`idle`&&e!==`connecting`&&e!==`error`}function de({active:e}){return(0,t.jsx)(`svg`,{"aria-hidden":`true`,fill:`none`,viewBox:`0 0 24 24`,style:{display:`block`,width:`50%`,height:`50%`,transform:`rotate(${e?132:-8}deg)`,transformOrigin:`center`,transition:`transform 180ms ease`},children:(0,t.jsx)(`path`,{d:`M6.7 3.8 9.1 7a1.6 1.6 0 0 1-.2 2.1l-1.4 1.3a13.1 13.1 0 0 0 6.1 6.1l1.3-1.4a1.6 1.6 0 0 1 2.1-.2l3.2 2.4a1.6 1.6 0 0 1 .5 1.9l-.7 1.7c-.3.8-1.1 1.3-2 1.2C9.7 21.2 2.8 14.3 1.9 6c-.1-.9.4-1.7 1.2-2l1.7-.7a1.6 1.6 0 0 1 1.9.5Z`,fill:`currentColor`})})}function fe({state:n,volume:r,size:i,className:a,style:o,disabled:s=!1,interactive:c=!1,onClick:l,...u}){let d=(0,e.useRef)(null),f=(0,e.useRef)(n),p=(0,e.useRef)(r),m=(0,e.useRef)(!1);re(()=>{f.current=n,p.current=r},[n,r]);let h=i*se,g=h*ce;(0,e.useEffect)(()=>{let e=`orb-radial-keyframes`;if(!document.getElementById(e)){let t=document.createElement(`style`);t.id=e,t.textContent=oe,document.head.appendChild(t)}},[]),(0,e.useEffect)(()=>{let e=d.current;if(!e)return;let t=window.matchMedia(`(prefers-reduced-motion: reduce)`),n=()=>{m.current=t.matches};n(),t.addEventListener(`change`,n);let r=le(e,h),i=0,a=performance.now(),o=0,s=.36,c=.62,l=.15,u=0,g=0,_=0,v=0,y=+(f.current===`speaking`),b=X(p.current),x=f.current===`listening`?b:0,S=f.current===`speaking`?b:0,C=e=>{let t=Math.min((e-a)/1e3,.05);a=e;let n=f.current,d=m.current,h=X(p.current);b=d?0:Z(b,h,h>b?15:7,t);let w=n===`listening`?b:0,T=n===`speaking`?b:0;x=d?0:Z(x,w,w>x?17:7,t),S=d?0:Z(S,T,T>S?12:5,t);let E=.36,D=.62,O=.15;if(n===`connecting`?(E=.42,D=.68,O=.13):n===`listening`?(E=.54+x*.26,D=.78+x*.18,O=.18+x*.04):n===`thinking`?(E=.46,D=.72,O=.16):n===`speaking`&&(E=1.05+S*1.15),!d){s=Z(s,E,3.6,t),c=Z(c,D,3.6,t),l=Z(l,O,3.6,t),y=Z(y,+(n===`speaking`),n===`speaking`?3.8:3,t),o+=t*s,_+=t*c;let e=1.2+S*1.35+Math.sin(o*1.73)*.34+Math.sin(o*.61+.8)*.18;v+=t*Math.max(.65,e);let r=Math.sin(_)*l+Math.sin(_*.47+1.1)*.032,i=Math.sin(v*1.08),a=Math.sin(v*2.47+.9),d=Math.sin(v*.43-.5),f=r+(i*(.13+S*.17)+a*(.035+S*.035)+d*.055-r)*y,p=4.2+y*3,m=p*p,h=2*p;g+=((f-u)*m-g*h)*t,u+=g*t}r?.draw(o,u,x,S),i=requestAnimationFrame(C)};return i=requestAnimationFrame(C),()=>{cancelAnimationFrame(i),t.removeEventListener(`change`,n),r?.destroy()}},[h]);let _=ue(n),v=n===`connecting`,y=h+(c?g*.5:0),b={"--orb-ui-radial-control-surround":`#fff`,width:i,height:i,display:`flex`,alignItems:`center`,justifyContent:`center`,position:`relative`,...o},x=(0,t.jsxs)(`span`,{style:{position:`relative`,display:`block`,width:h,height:y,lineHeight:0},children:[(0,t.jsx)(`canvas`,{ref:d,"aria-hidden":`true`,"data-radial-surface":``,style:{position:`absolute`,left:0,top:0,display:`block`,width:h,height:h,borderRadius:`50%`,background:`conic-gradient(from 12deg, #06358d 0deg, #0b65b5 72deg, #c7f1ef 92deg, #45c2c8 172deg, #06358d 196deg, #0b65b5 254deg, #c7f1ef 278deg, #45c2c8 360deg)`}}),c?(0,t.jsx)(`button`,{...u,type:`button`,"data-radial-control":``,disabled:s,onClick:s?void 0:l,style:{appearance:`none`,WebkitAppearance:`none`,position:`absolute`,left:`50%`,top:h-g*.52,width:g,height:g,display:`flex`,alignItems:`center`,justifyContent:`center`,boxSizing:`border-box`,padding:0,margin:0,border:0,borderRadius:`50%`,background:v?`#9da1aa`:_?`#ef4146`:`#080808`,color:`#fff`,boxShadow:`0 0 0 ${Math.max(3,g*.085)}px var(--orb-ui-radial-control-surround), 0 2px 5px rgba(0, 0, 0, 0.18)`,cursor:s?`not-allowed`:`pointer`,opacity:s?.52:1,transform:`translateX(-50%)`,transition:`background 160ms ease, opacity 160ms ease, transform 160ms ease`,font:`inherit`},children:v?(0,t.jsx)(`span`,{"aria-hidden":`true`,"data-radial-spinner":``,style:{width:`42%`,height:`42%`,boxSizing:`border-box`,border:`${Math.max(1.5,g*.055)}px solid rgba(255, 255, 255, 0.38)`,borderTopColor:`#fff`,borderRightColor:`#fff`,borderRadius:`50%`,animation:`orb-radial-spinner 760ms linear infinite`}}):(0,t.jsx)(de,{active:_})}):null]});return c?(0,t.jsx)(`div`,{className:a,style:b,children:x}):(0,t.jsx)(`div`,{...u,className:a,style:b,children:x})}function $({signal:i,state:a,volume:s,adapter:c,theme:l=`debug`,size:u=200,className:d,style:f,disabled:p=!1,interactive:m=!0,onStart:h,onStop:g,..._}){let[v,y]=(0,e.useState)({state:`idle`});(0,e.useEffect)(()=>{if(y({state:`idle`}),c)return c.subscribe(y)},[c]);let x=i??v,S=n(a,i,v),C=r(s,S,x),w=S!==`idle`&&S!==`error`,T=(0,e.useCallback)(()=>{p||(w?g?g():c?.stop?.():h?h():c?.start?.())},[c,p,w,h,g]),D=w?!!(c?.stop||g):!!(c?.start||h),O=m&&D,k=O&&!p?T:void 0,A={state:S,volume:C,size:u,className:d,style:f,disabled:p,..._,"aria-label":_[`aria-label`]??(O?`${w?`Stop`:`Start`} voice session`:void 0)},j={...A,interactive:O};switch(l){case`circle`:return(0,t.jsx)(b,{...j,onClick:k});case`bars`:return(0,t.jsx)(E,{...j,onClick:k});case`cloud`:return(0,t.jsx)(ne,{...j,onClick:k});case`radial`:return(0,t.jsx)(fe,{...j,onClick:k});default:return(0,t.jsx)(o,{...A,disabled:p||!m,onStart:p||!m?void 0:h??(()=>c?.start?.()),onStop:p||!m?void 0:g??(()=>c?.stop?.())})}}exports.Orb=$,exports.VoiceOrb=$;
203
+ `,se=.66,ce=.2;function X(e,t=0,n=1){return Math.min(n,Math.max(t,e))}function Z(e,t,n,r){return e+(t-e)*(1-Math.exp(-n*r))}function Q(e,t,n){let r=e.createShader(t);if(r){if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){e.deleteShader(r);return}return r}}function le(e,t){let n=e.getContext(`webgl`,{alpha:!0,antialias:!0,premultipliedAlpha:!0});if(!n)return;let r=Q(n,n.VERTEX_SHADER,ie),i=Q(n,n.FRAGMENT_SHADER,ae);if(!r||!i){r&&n.deleteShader(r),i&&n.deleteShader(i);return}let a=n.createProgram(),o=n.createBuffer();if(!a||!o){a&&n.deleteProgram(a),o&&n.deleteBuffer(o),n.deleteShader(r),n.deleteShader(i);return}if(n.attachShader(a,r),n.attachShader(a,i),n.linkProgram(a),!n.getProgramParameter(a,n.LINK_STATUS)){n.deleteProgram(a),n.deleteBuffer(o),n.deleteShader(r),n.deleteShader(i);return}let s=n.getAttribLocation(a,`a_position`),c=n.getUniformLocation(a,`u_resolution`),l=n.getUniformLocation(a,`u_time`),u=n.getUniformLocation(a,`u_rotation`),d=n.getUniformLocation(a,`u_listen`),f=n.getUniformLocation(a,`u_speak`);if(s<0||!c||!l||!u||!d||!f){n.deleteProgram(a),n.deleteBuffer(o),n.deleteShader(r),n.deleteShader(i);return}let p=Math.min(window.devicePixelRatio||1,2),m=Math.max(1,Math.round(t*p));return e.width=m,e.height=m,n.viewport(0,0,m,m),n.useProgram(a),n.bindBuffer(n.ARRAY_BUFFER,o),n.bufferData(n.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]),n.STATIC_DRAW),n.enableVertexAttribArray(s),n.vertexAttribPointer(s,2,n.FLOAT,!1,0,0),n.uniform2f(c,m,m),{draw(e,t,r,i){n.uniform1f(l,e),n.uniform1f(u,t),n.uniform1f(d,r),n.uniform1f(f,i),n.drawArrays(n.TRIANGLES,0,6)},destroy(){n.deleteProgram(a),n.deleteBuffer(o),n.deleteShader(r),n.deleteShader(i)}}}function ue(e){return e!==`idle`&&e!==`connecting`&&e!==`error`}function de({active:e}){return(0,t.jsx)(`svg`,{"aria-hidden":`true`,fill:`none`,viewBox:`0 0 24 24`,style:{display:`block`,width:`50%`,height:`50%`,transform:`rotate(${e?132:-8}deg)`,transformOrigin:`center`,transition:`transform 180ms ease`},children:(0,t.jsx)(`path`,{d:`M6.7 3.8 9.1 7a1.6 1.6 0 0 1-.2 2.1l-1.4 1.3a13.1 13.1 0 0 0 6.1 6.1l1.3-1.4a1.6 1.6 0 0 1 2.1-.2l3.2 2.4a1.6 1.6 0 0 1 .5 1.9l-.7 1.7c-.3.8-1.1 1.3-2 1.2C9.7 21.2 2.8 14.3 1.9 6c-.1-.9.4-1.7 1.2-2l1.7-.7a1.6 1.6 0 0 1 1.9.5Z`,fill:`currentColor`})})}function fe({state:n,volume:r,size:i,className:a,style:o,disabled:s=!1,interactive:c=!1,onClick:l,...u}){let d=(0,e.useRef)(null),f=(0,e.useRef)(n),p=(0,e.useRef)(r),m=(0,e.useRef)(!1);re(()=>{f.current=n,p.current=r},[n,r]);let h=i*se,g=h*ce;(0,e.useEffect)(()=>{let e=`orb-radial-keyframes`;if(!document.getElementById(e)){let t=document.createElement(`style`);t.id=e,t.textContent=oe,document.head.appendChild(t)}},[]),(0,e.useEffect)(()=>{let e=d.current;if(!e)return;let t=window.matchMedia(`(prefers-reduced-motion: reduce)`),n=()=>{m.current=t.matches};n(),t.addEventListener(`change`,n);let r=le(e,h),i=0,a=performance.now(),o=0,s=.36,c=.62,l=.15,u=0,g=0,_=0,v=0,y=+(f.current===`speaking`),b=X(p.current),x=f.current===`listening`?b:0,S=f.current===`speaking`?b:0,C=e=>{let t=Math.min((e-a)/1e3,.05);a=e;let n=f.current,d=m.current,h=X(p.current);b=d?0:Z(b,h,h>b?15:7,t);let w=n===`listening`?b:0,T=n===`speaking`?b:0;x=d?0:Z(x,w,w>x?17:7,t),S=d?0:Z(S,T,T>S?12:5,t);let E=.36,D=.62,O=.15;if(n===`connecting`?(E=.42,D=.68,O=.13):n===`listening`?(E=.54+x*.26,D=.78+x*.18,O=.18+x*.04):n===`thinking`?(E=.46,D=.72,O=.16):n===`speaking`&&(E=1.05+S*1.15),!d){s=Z(s,E,3.6,t),c=Z(c,D,3.6,t),l=Z(l,O,3.6,t),y=Z(y,+(n===`speaking`),n===`speaking`?3.8:3,t),o+=t*s,_+=t*c;let e=1.2+S*1.35+Math.sin(o*1.73)*.34+Math.sin(o*.61+.8)*.18;v+=t*Math.max(.65,e);let r=Math.sin(_)*l+Math.sin(_*.47+1.1)*.032,i=Math.sin(v*1.08),a=Math.sin(v*2.47+.9),d=Math.sin(v*.43-.5),f=r+(i*(.13+S*.17)+a*(.035+S*.035)+d*.055-r)*y,p=4.2+y*3,m=p*p,h=2*p;g+=((f-u)*m-g*h)*t,u+=g*t}r?.draw(o,u,x,S),i=requestAnimationFrame(C)};return i=requestAnimationFrame(C),()=>{cancelAnimationFrame(i),t.removeEventListener(`change`,n),r?.destroy()}},[h]);let _=ue(n),v=n===`connecting`,y=h+(c?g*.5:0),b={"--orb-ui-radial-control-surround":`#fff`,width:i,height:i,display:`flex`,alignItems:`center`,justifyContent:`center`,position:`relative`,...o},x=(0,t.jsxs)(`span`,{style:{position:`relative`,display:`block`,width:h,height:y,lineHeight:0},children:[(0,t.jsx)(`canvas`,{ref:d,"aria-hidden":`true`,"data-radial-surface":``,style:{position:`absolute`,left:0,top:0,display:`block`,width:h,height:h,borderRadius:`50%`,background:`conic-gradient(from 12deg, #06358d 0deg, #0b65b5 72deg, #c7f1ef 92deg, #45c2c8 172deg, #06358d 196deg, #0b65b5 254deg, #c7f1ef 278deg, #45c2c8 360deg)`}}),c?(0,t.jsx)(`button`,{...u,type:`button`,"data-radial-control":``,disabled:s,onClick:s?void 0:l,style:{appearance:`none`,WebkitAppearance:`none`,position:`absolute`,left:`50%`,top:h-g*.52,width:g,height:g,display:`flex`,alignItems:`center`,justifyContent:`center`,boxSizing:`border-box`,padding:0,margin:0,border:0,borderRadius:`50%`,background:v?`#9da1aa`:_?`#ef4146`:`#080808`,color:`#fff`,boxShadow:`0 0 0 ${Math.max(3,g*.085)}px var(--orb-ui-radial-control-surround), 0 2px 5px rgba(0, 0, 0, 0.18)`,cursor:s?`not-allowed`:`pointer`,opacity:s?.52:1,transform:`translateX(-50%)`,transition:`background 160ms ease, opacity 160ms ease, transform 160ms ease`,font:`inherit`},children:v?(0,t.jsx)(`span`,{"aria-hidden":`true`,"data-radial-spinner":``,style:{width:`42%`,height:`42%`,boxSizing:`border-box`,border:`${Math.max(1.5,g*.055)}px solid rgba(255, 255, 255, 0.38)`,borderTopColor:`#fff`,borderRightColor:`#fff`,borderRadius:`50%`,animation:`orb-radial-spinner 760ms linear infinite`}}):(0,t.jsx)(de,{active:_})}):null]});return c?(0,t.jsx)(`div`,{className:a,style:b,children:x}):(0,t.jsx)(`div`,{...u,className:a,style:b,children:x})}function $({signal:i,state:a,volume:s,adapter:c,theme:l=`debug`,size:u=200,className:d,style:f,disabled:p=!1,interactive:m=!0,onStart:h,onStop:g,renderTheme:_,...v}){let[y,x]=(0,e.useState)({state:`idle`});(0,e.useEffect)(()=>{if(x({state:`idle`}),c)return c.subscribe(x)},[c]);let S=i??y,C=n(a,i,y),w=r(s,C,S),T=S.inputVolume??0,D=S.outputVolume??0,O=(0,e.useMemo)(()=>({...S,state:C,inputVolume:T,outputVolume:D}),[S,T,D,C]),k=C!==`idle`&&C!==`error`,A=(0,e.useCallback)(()=>{if(!p)return h?h():c?.start?.()},[c,p,h]),j=(0,e.useCallback)(()=>{if(!p)return g?g():c?.stop?.()},[c,p,g]),M=(0,e.useCallback)(()=>k?j():A(),[k,A,j]),N=k?!!(c?.stop||g):!!(c?.start||h),P=m&&N,F=P&&!p?M:void 0,I=v[`aria-label`]??(P?`${k?`Stop`:`Start`} voice session`:void 0),L={...v,"aria-label":I};if(_){let e={...v,type:`button`,disabled:p||!P,onClick:F,"data-orb-ui-state":C,"aria-label":I};return _({state:C,signal:O,inputVolume:T,outputVolume:D,activity:w,size:u,isActive:k,interactive:P,disabled:p,start:A,stop:j,toggle:M,rootProps:{className:d,style:{width:u,height:u,...f},"data-orb-ui-theme":`custom`,"data-orb-ui-state":C},controlProps:e})}let R={state:C,volume:w,size:u,className:d,style:f,disabled:p,...L},z={...R,interactive:P};switch(l){case`circle`:return(0,t.jsx)(b,{...z,onClick:F});case`bars`:return(0,t.jsx)(E,{...z,onClick:F});case`cloud`:return(0,t.jsx)(ne,{...z,onClick:F});case`radial`:return(0,t.jsx)(fe,{...z,onClick:F});default:return(0,t.jsx)(o,{...R,disabled:p||!m,onStart:p||!m?void 0:A,onStop:p||!m?void 0:j})}}exports.Orb=$,exports.VoiceOrb=$;