@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.
- package/LICENSE +0 -0
- package/README.md +25 -1
- package/dist/adapters/audio-level.d.ts +0 -0
- package/dist/adapters/elevenlabs/index.d.ts +0 -0
- package/dist/adapters/gemini-live/index.d.ts +0 -0
- package/dist/adapters/index.d.ts +0 -0
- package/dist/adapters/livekit/browser.d.ts +0 -0
- package/dist/adapters/livekit/index.d.ts +0 -0
- package/dist/adapters/openai-realtime/index.d.ts +0 -0
- package/dist/adapters/pipecat/index.d.ts +0 -0
- package/dist/adapters/types.d.ts +0 -0
- package/dist/adapters/vapi/index.d.ts +0 -0
- package/dist/adapters.cjs +0 -0
- package/dist/adapters.js +0 -0
- package/dist/components/Orb/Orb.d.ts +1 -1
- package/dist/components/Orb/Orb.types.d.ts +35 -1
- package/dist/components/Orb/index.d.ts +1 -1
- package/dist/components/Orb/signals.d.ts +0 -0
- package/dist/index.d.ts +1 -1
- package/dist/livekit-D-s4sYba.cjs +0 -0
- package/dist/livekit-Z3IMmWaG.js +0 -0
- package/dist/livekit-adapter.cjs +0 -0
- package/dist/livekit-adapter.js +0 -0
- package/dist/orb-ui.cjs +1 -1
- package/dist/orb-ui.js +266 -210
- package/dist/themes/bars/BarsTheme.d.ts +0 -0
- package/dist/themes/bars/index.d.ts +0 -0
- package/dist/themes/circle/CircleTheme.d.ts +0 -0
- package/dist/themes/circle/index.d.ts +0 -0
- package/dist/themes/cloud/CloudTheme.d.ts +0 -0
- package/dist/themes/cloud/index.d.ts +0 -0
- package/dist/themes/debug/DebugTheme.d.ts +0 -0
- package/dist/themes/debug/index.d.ts +0 -0
- package/dist/themes/index.d.ts +0 -0
- package/dist/themes/radial/RadialTheme.d.ts +0 -0
- package/dist/themes/radial/index.d.ts +0 -0
- 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
|
|
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
|
package/dist/adapters/index.d.ts
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/dist/adapters/types.d.ts
CHANGED
|
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
|
package/dist/livekit-Z3IMmWaG.js
CHANGED
|
File without changes
|
package/dist/livekit-adapter.cjs
CHANGED
|
File without changes
|
package/dist/livekit-adapter.js
CHANGED
|
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,...
|
|
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=$;
|