@lofcz/orb-ui 0.7.1 → 0.8.0

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/README.md CHANGED
@@ -274,7 +274,7 @@ For an app-owned voice stack (Gemini Live, custom Web Audio), keep session contr
274
274
  ```tsx
275
275
  import { Orb } from '@lofcz/orb-ui'
276
276
 
277
- <Orb
277
+ ;<Orb
278
278
  signal={{ state: 'listening', inputVolume: 0.4, outputVolume: 0 }}
279
279
  interactive={false}
280
280
  renderTheme={({ rootProps, state, activity, inputVolume, outputVolume }) => (
@@ -292,22 +292,24 @@ import { Orb } from '@lofcz/orb-ui'
292
292
 
293
293
  ## Props
294
294
 
295
- | Prop | Type | Default | Description |
296
- | ------------- | ------------------------------------------------------ | --------- | ------------------------------------------------------- |
297
- | `theme` | `'debug' \| 'circle' \| 'bars' \| 'cloud' \| 'radial'` | `'debug'` | Visual theme |
298
- | `signal` | `OrbSignal` | | Rich controlled signal with state/input/output volume |
299
- | `state` | `OrbState` | `'idle'` | Conversation state (controlled mode) |
300
- | `volume` | `number` | `0` | Audio volume, 0–1. Overrides signal/adapter volume. |
301
- | `adapter` | `OrbAdapter` | | Provider adapter (manages signal updates automatically) |
302
- | `size` | `number` | `200` | Size in pixels |
303
- | `className` | `string` | — | Optional class name for the rendered theme |
304
- | `style` | `OrbStyle` | | Inline styles, including radial control surround color |
305
- | `disabled` | `boolean` | `false` | Disables clickable themes and debug start/stop controls |
306
- | `interactive` | `boolean` | `true` | Allows the theme control to start and stop a session |
307
- | `aria-label` | `string` | generated | Accessible label for clickable visual themes |
308
- | `onStart` | `() => void` | | Custom start handler (overrides adapter.start()) |
309
- | `onStop` | `() => void` | | Custom stop handler (overrides adapter.stop()) |
310
- | `renderTheme` | `OrbThemeRenderer` | — | Custom artwork; Orb still owns state and volume |
295
+ | Prop | Type | Default | Description |
296
+ | ------------- | ----------------------------------------------------------------- | --------- | ------------------------------------------------------- |
297
+ | `theme` | `'debug' \| 'circle' \| 'bars' \| 'cloud' \| 'radial' \| 'ocean'` | `'debug'` | Visual theme |
298
+ | `scheme` | `'light' \| 'dark'` | `'light'` | Preset selector for palette-aware themes (`ocean`) |
299
+ | `palette` | `OrbPalette` | | Hex color overrides for palette-aware themes (`ocean`) |
300
+ | `signal` | `OrbSignal` | | Rich controlled signal with state/input/output volume |
301
+ | `state` | `OrbState` | `'idle'` | Conversation state (controlled mode) |
302
+ | `volume` | `number` | `0` | Audio volume, 0–1. Overrides signal/adapter volume. |
303
+ | `adapter` | `OrbAdapter` | — | Provider adapter (manages signal updates automatically) |
304
+ | `size` | `number` | `200` | Size in pixels |
305
+ | `className` | `string` | | Optional class name for the rendered theme |
306
+ | `style` | `OrbStyle` | | Inline styles, including radial control surround color |
307
+ | `disabled` | `boolean` | `false` | Disables clickable themes and debug start/stop controls |
308
+ | `interactive` | `boolean` | `true` | Allows the theme control to start and stop a session |
309
+ | `aria-label` | `string` | generated | Accessible label for clickable visual themes |
310
+ | `onStart` | `() => void` | — | Custom start handler (overrides adapter.start()) |
311
+ | `onStop` | `() => void` | — | Custom stop handler (overrides adapter.stop()) |
312
+ | `renderTheme` | `OrbThemeRenderer` | — | Custom artwork; Orb still owns state and volume |
311
313
 
312
314
  ## States
313
315
 
@@ -315,14 +317,14 @@ import { Orb } from '@lofcz/orb-ui'
315
317
 
316
318
  ## Supported Providers
317
319
 
318
- | Provider | Adapter |
319
- | ------------------------------------------------------------------------- | --------------------------------------------------------------------- |
320
- | [Vapi](https://vapi.ai) | `createVapiAdapter` from `@lofcz/orb-ui/adapters` |
321
- | [ElevenLabs](https://elevenlabs.io/conversational-ai) | `createElevenLabsAdapter` from `@lofcz/orb-ui/adapters` |
322
- | [LiveKit](https://livekit.io) | `createLiveKitAdapter` from `@lofcz/orb-ui/adapters` |
323
- | [Pipecat](https://pipecat.ai) | `createPipecatAdapter` from `@lofcz/orb-ui/adapters` |
324
- | [OpenAI Realtime](https://developers.openai.com/api/docs/guides/realtime) | `createOpenAIRealtimeAdapter` from `@lofcz/orb-ui/adapters` |
325
- | [Gemini Live](https://ai.google.dev/gemini-api/docs/live-api) | `createGeminiLiveAdapter` from `@lofcz/orb-ui/adapters` |
320
+ | Provider | Adapter |
321
+ | ------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
322
+ | [Vapi](https://vapi.ai) | `createVapiAdapter` from `@lofcz/orb-ui/adapters` |
323
+ | [ElevenLabs](https://elevenlabs.io/conversational-ai) | `createElevenLabsAdapter` from `@lofcz/orb-ui/adapters` |
324
+ | [LiveKit](https://livekit.io) | `createLiveKitAdapter` from `@lofcz/orb-ui/adapters` |
325
+ | [Pipecat](https://pipecat.ai) | `createPipecatAdapter` from `@lofcz/orb-ui/adapters` |
326
+ | [OpenAI Realtime](https://developers.openai.com/api/docs/guides/realtime) | `createOpenAIRealtimeAdapter` from `@lofcz/orb-ui/adapters` |
327
+ | [Gemini Live](https://ai.google.dev/gemini-api/docs/live-api) | `createGeminiLiveAdapter` from `@lofcz/orb-ui/adapters` |
326
328
  | Custom / Gemini Live (app-owned session) | Controlled mode — pass `signal` or `state` + `volume`, plus `renderTheme` |
327
329
 
328
330
  ## Development
@@ -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, renderTheme, ...htmlProps }: OrbProps): string | number | boolean | Iterable<import('react').ReactNode> | import("react").JSX.Element | null | undefined;
2
+ export declare function Orb({ signal: signalProp, state: stateProp, volume: volumeProp, adapter, theme, size, scheme, palette, className, style, disabled, interactive: interactiveProp, onStart, onStop, renderTheme, ...htmlProps }: OrbProps): string | number | boolean | Iterable<import('react').ReactNode> | import("react").JSX.Element | null | undefined;
@@ -4,7 +4,27 @@ export type OrbStyle = CSSProperties & {
4
4
  '--orb-ui-radial-control-surround'?: string;
5
5
  };
6
6
  export type OrbState = 'idle' | 'connecting' | 'listening' | 'thinking' | 'speaking' | 'error';
7
- export type OrbTheme = 'debug' | 'circle' | 'bars' | 'cloud' | 'radial';
7
+ export type OrbTheme = 'debug' | 'circle' | 'bars' | 'cloud' | 'radial' | 'ocean';
8
+ /** Light or dark surroundings; themes with both presets pick their colors from it. */
9
+ export type OrbScheme = 'light' | 'dark';
10
+ /**
11
+ * Hex colors a palette-aware theme reads. Every field is optional; whatever is
12
+ * left out comes from the theme's preset for the active scheme.
13
+ */
14
+ export interface OrbPalette {
15
+ /** The darkest water, at the bottom of the orb. */
16
+ deep?: string;
17
+ /** Sunlit water just below the surface. */
18
+ shallow?: string;
19
+ /** Foam on the waterline and the glass rim. */
20
+ foam?: string;
21
+ /** The light source: sun by day, moon by night. Also drives the halo. */
22
+ glow?: string;
23
+ /** The air at the top of the orb. */
24
+ sky?: string;
25
+ /** The air just above the waterline. */
26
+ horizon?: string;
27
+ }
8
28
  export interface OrbSignal {
9
29
  state: OrbState;
10
30
  volume?: number;
@@ -62,6 +82,16 @@ export interface OrbProps extends OrbHtmlAttributes {
62
82
  theme?: OrbTheme;
63
83
  /** Size in pixels. Defaults to 200. */
64
84
  size?: number;
85
+ /**
86
+ * Light or dark surroundings. Palette-aware themes (`ocean`) switch presets
87
+ * on it; other themes ignore it. Defaults to 'light'.
88
+ */
89
+ scheme?: OrbScheme;
90
+ /**
91
+ * Color overrides for palette-aware themes (`ocean`). Merged over the preset
92
+ * selected by `scheme`; other themes ignore it.
93
+ */
94
+ palette?: OrbPalette;
65
95
  /** Optional class name for the rendered orb container/control. */
66
96
  className?: string;
67
97
  /** Optional inline styles for the rendered orb container/control. */
@@ -1,2 +1,2 @@
1
1
  export { Orb } from './Orb.js';
2
- export type { OrbAdapter, OrbProps, OrbSignal, OrbSignalListener, OrbState, OrbStyle, OrbTheme, OrbThemeRenderer, OrbThemeRendererControlProps, OrbThemeRendererProps, OrbThemeRendererRootProps, } from './Orb.types.js';
2
+ export type { OrbAdapter, OrbPalette, OrbProps, OrbScheme, OrbSignal, OrbSignalListener, OrbState, OrbStyle, OrbTheme, OrbThemeRenderer, OrbThemeRendererControlProps, OrbThemeRendererProps, OrbThemeRendererRootProps, } from './Orb.types.js';
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, OrbThemeRenderer, OrbThemeRendererControlProps, OrbThemeRendererProps, OrbThemeRendererRootProps, } from './components/Orb/index.js';
2
+ export type { OrbAdapter, OrbPalette, OrbProps, OrbScheme, 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';
package/dist/orb-ui.cjs CHANGED
@@ -108,13 +108,13 @@ void main() {
108
108
 
109
109
  gl_FragColor = vec4(color, edge);
110
110
  }
111
- `,A=.55,j=.204,M=.2145,N=.063,P=`#5659dc`,F=1.178,I=180,L=300,R=1350,z=246,B=420,V=354,ee=480;function H(e,t=0,n=1){return Math.min(n,Math.max(t,e))}function U(e,t,n,r){return e+(t-e)*(1-Math.exp(-n*r))}function W(e){return 1-(1-e)**3}function G(e,t,n){return e+(t-e)*n}function K(e,t,n){let r=H((e-t)/(n-t));return r*r*(3-2*r)}function q(e){return e===`listening`||e===`speaking`||e===`thinking`}function J(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 Y(e,t){let n=e.getContext(`webgl`,{alpha:!0,antialias:!0,premultipliedAlpha:!0});if(!n)return;let r=J(n,n.VERTEX_SHADER,O),i=J(n,n.FRAGMENT_SHADER,k);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_activity`);if(s<0||!c||!l||!u){n.deleteProgram(a),n.deleteBuffer(o),n.deleteShader(r),n.deleteShader(i);return}let d=Math.min(window.devicePixelRatio||1,2),f=Math.max(1,Math.round(t*d));return e.width=f,e.height=f,n.viewport(0,0,f,f),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,f,f),{draw(e,t){n.uniform1f(l,e),n.uniform1f(u,t),n.drawArrays(n.TRIANGLES,0,6)},destroy(){n.deleteProgram(a),n.deleteBuffer(o),n.deleteShader(r),n.deleteShader(i)}}}function te(e){if(e<=I)return N;if(e<=480)return G(N,F,W((e-I)/L));let t=e-I-L;return t>=R?1:1+.17799999999999994*(1-H(t/R))**2}function ne({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)(null),p=(0,e.useRef)(null),m=(0,e.useRef)(n),h=(0,e.useRef)(r),g=(0,e.useRef)(c),_=(0,e.useRef)(!1);D(()=>{m.current=n,h.current=r,g.current=c},[c,n,r]);let v=i*A;(0,e.useEffect)(()=>{let e=d.current,t=f.current,n=p.current;if(!e||!t||!n)return;let r=window.matchMedia(`(prefers-reduced-motion: reduce)`),i=()=>{_.current=r.matches};i(),r.addEventListener(`change`,i);let a=Y(e,v);a||(e.style.background=`linear-gradient(180deg, #626afb 2%, #8f9dfb 32%, #dde6fd 52%, #c9d3fb 84%)`);let o=0,s=performance.now(),c=m.current,l=q(c)?s:void 0,u=H(h.current),y=1,b=+!!q(c),x=1,S=+(c===`connecting`),C=0,w=r=>{let i=Math.min((r-s)/1e3,.05);s=r;let d=m.current,f=_.current;d!==c&&(q(d)&&!q(c)&&(l=r),(d===`idle`||d===`error`)&&(l=void 0),c=d);let p=H(h.current);u=f?0:U(u,p,p>u?11:6,i);let v=1;d===`listening`&&(v=1-u*j),d===`speaking`&&(v=1+u*M);let T=Math.abs(v-1)>Math.abs(y-1)?12:6;y=f?1:U(y,v,T,i);let E=q(d),D=d===`idle`&&g.current,O=E||D?1:0;b=f?O:U(b,O,14,i);let k=E||D?1:.92;x=f?k:U(x,k,12,i);let A=y*x;D&&(A=N);let P=+!D,F=D?b:0;if(E&&l!==void 0&&!f){let e=r-l,t=te(e),n=H((e-I-L)/R);A=t*G(1,y,n),P=K(e,z,B),F=b*(1-K(e,V,ee)),e>=1830&&(l=void 0)}let W=+(d===`connecting`);S=f?W:U(S,W,18,i),e.style.opacity=String(b*P),e.style.transform=`scale(${A})`,t.style.opacity=String(F),t.style.transform=`scale(${A})`,n.style.opacity=String(S),n.style.transform=`rotate(${f?45:r*.34}deg)`;let J=.24,Y=.1;d===`listening`?(J=.72+u*.78,Y=.28+u*.32):d===`speaking`&&(J=1.65+u*1.55,Y=.66+u*.34),f||(C+=i*J),a?.draw(C,Y),o=requestAnimationFrame(w)};return o=requestAnimationFrame(w),()=>{cancelAnimationFrame(o),r.removeEventListener(`change`,i),a?.destroy()}},[v]);let y={width:i,height:i,display:`flex`,alignItems:`center`,justifyContent:`center`,position:`relative`,...o},b=(0,t.jsxs)(`span`,{style:{position:`relative`,display:`block`,width:v,height:v,borderRadius:`50%`,lineHeight:0,cursor:c?s?`not-allowed`:`pointer`:`default`},children:[(0,t.jsx)(`span`,{ref:f,"data-cloud-launch-dot":``,"aria-hidden":`true`,style:{position:`absolute`,inset:0,display:`block`,borderRadius:`50%`,background:P,opacity:0,transform:`scale(${N})`,transformOrigin:`center`,willChange:`opacity, transform`}}),(0,t.jsx)(`canvas`,{ref:d,"aria-hidden":`true`,style:{position:`absolute`,inset:0,display:`block`,width:v,height:v,borderRadius:`50%`,opacity:0,transform:`scale(${N})`,transformOrigin:`center`,willChange:`opacity, transform`}}),(0,t.jsx)(`span`,{ref:p,"aria-hidden":`true`,style:{position:`absolute`,left:`50%`,top:`50%`,width:v*.105,height:v*.105,boxSizing:`border-box`,border:`${Math.max(1.5,v*.012)}px solid rgba(113, 120, 245, 0.24)`,borderTopColor:`#777ff6`,borderRightColor:`#777ff6`,borderRadius:`50%`,opacity:0,transform:`rotate(0deg)`,transformOrigin:`center`,marginLeft:v*-.0525,marginTop:v*-.0525,willChange:`opacity, transform`}})]});return c?(0,t.jsx)(`button`,{...u,type:`button`,className:a,disabled:s,onClick:s?void 0:l,style:{appearance:`none`,WebkitAppearance:`none`,border:0,padding:0,margin:0,background:`transparent`,color:`inherit`,font:`inherit`,cursor:s?`not-allowed`:`pointer`,...y},children:b}):(0,t.jsx)(`div`,{...u,className:a,style:y,children:b})}var re=typeof window<`u`?e.useLayoutEffect:e.useEffect,ie=`
111
+ `,A=.55,j=.204,M=.2145,N=.063,P=`#5659dc`,F=1.178,I=180,L=300,R=1350,ee=246,z=420,B=354,te=480;function V(e,t=0,n=1){return Math.min(n,Math.max(t,e))}function H(e,t,n,r){return e+(t-e)*(1-Math.exp(-n*r))}function U(e){return 1-(1-e)**3}function W(e,t,n){return e+(t-e)*n}function ne(e,t,n){let r=V((e-t)/(n-t));return r*r*(3-2*r)}function G(e){return e===`listening`||e===`speaking`||e===`thinking`}function K(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 q(e,t){let n=e.getContext(`webgl`,{alpha:!0,antialias:!0,premultipliedAlpha:!0});if(!n)return;let r=K(n,n.VERTEX_SHADER,O),i=K(n,n.FRAGMENT_SHADER,k);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_activity`);if(s<0||!c||!l||!u){n.deleteProgram(a),n.deleteBuffer(o),n.deleteShader(r),n.deleteShader(i);return}let d=Math.min(window.devicePixelRatio||1,2),f=Math.max(1,Math.round(t*d));return e.width=f,e.height=f,n.viewport(0,0,f,f),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,f,f),{draw(e,t){n.uniform1f(l,e),n.uniform1f(u,t),n.drawArrays(n.TRIANGLES,0,6)},destroy(){n.deleteProgram(a),n.deleteBuffer(o),n.deleteShader(r),n.deleteShader(i)}}}function re(e){if(e<=I)return N;if(e<=480)return W(N,F,U((e-I)/L));let t=e-I-L;return t>=R?1:1+.17799999999999994*(1-V(t/R))**2}function ie({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)(null),p=(0,e.useRef)(null),m=(0,e.useRef)(n),h=(0,e.useRef)(r),g=(0,e.useRef)(c),_=(0,e.useRef)(!1);D(()=>{m.current=n,h.current=r,g.current=c},[c,n,r]);let v=i*A;(0,e.useEffect)(()=>{let e=d.current,t=f.current,n=p.current;if(!e||!t||!n)return;let r=window.matchMedia(`(prefers-reduced-motion: reduce)`),i=()=>{_.current=r.matches};i(),r.addEventListener(`change`,i);let a=q(e,v);a||(e.style.background=`linear-gradient(180deg, #626afb 2%, #8f9dfb 32%, #dde6fd 52%, #c9d3fb 84%)`);let o=0,s=performance.now(),c=m.current,l=G(c)?s:void 0,u=V(h.current),y=1,b=+!!G(c),x=1,S=+(c===`connecting`),C=0,w=r=>{let i=Math.min((r-s)/1e3,.05);s=r;let d=m.current,f=_.current;d!==c&&(G(d)&&!G(c)&&(l=r),(d===`idle`||d===`error`)&&(l=void 0),c=d);let p=V(h.current);u=f?0:H(u,p,p>u?11:6,i);let v=1;d===`listening`&&(v=1-u*j),d===`speaking`&&(v=1+u*M);let T=Math.abs(v-1)>Math.abs(y-1)?12:6;y=f?1:H(y,v,T,i);let E=G(d),D=d===`idle`&&g.current,O=E||D?1:0;b=f?O:H(b,O,14,i);let k=E||D?1:.92;x=f?k:H(x,k,12,i);let A=y*x;D&&(A=N);let P=+!D,F=D?b:0;if(E&&l!==void 0&&!f){let e=r-l,t=re(e),n=V((e-I-L)/R);A=t*W(1,y,n),P=ne(e,ee,z),F=b*(1-ne(e,B,te)),e>=1830&&(l=void 0)}let U=+(d===`connecting`);S=f?U:H(S,U,18,i),e.style.opacity=String(b*P),e.style.transform=`scale(${A})`,t.style.opacity=String(F),t.style.transform=`scale(${A})`,n.style.opacity=String(S),n.style.transform=`rotate(${f?45:r*.34}deg)`;let K=.24,q=.1;d===`listening`?(K=.72+u*.78,q=.28+u*.32):d===`speaking`&&(K=1.65+u*1.55,q=.66+u*.34),f||(C+=i*K),a?.draw(C,q),o=requestAnimationFrame(w)};return o=requestAnimationFrame(w),()=>{cancelAnimationFrame(o),r.removeEventListener(`change`,i),a?.destroy()}},[v]);let y={width:i,height:i,display:`flex`,alignItems:`center`,justifyContent:`center`,position:`relative`,...o},b=(0,t.jsxs)(`span`,{style:{position:`relative`,display:`block`,width:v,height:v,borderRadius:`50%`,lineHeight:0,cursor:c?s?`not-allowed`:`pointer`:`default`},children:[(0,t.jsx)(`span`,{ref:f,"data-cloud-launch-dot":``,"aria-hidden":`true`,style:{position:`absolute`,inset:0,display:`block`,borderRadius:`50%`,background:P,opacity:0,transform:`scale(${N})`,transformOrigin:`center`,willChange:`opacity, transform`}}),(0,t.jsx)(`canvas`,{ref:d,"aria-hidden":`true`,style:{position:`absolute`,inset:0,display:`block`,width:v,height:v,borderRadius:`50%`,opacity:0,transform:`scale(${N})`,transformOrigin:`center`,willChange:`opacity, transform`}}),(0,t.jsx)(`span`,{ref:p,"aria-hidden":`true`,style:{position:`absolute`,left:`50%`,top:`50%`,width:v*.105,height:v*.105,boxSizing:`border-box`,border:`${Math.max(1.5,v*.012)}px solid rgba(113, 120, 245, 0.24)`,borderTopColor:`#777ff6`,borderRightColor:`#777ff6`,borderRadius:`50%`,opacity:0,transform:`rotate(0deg)`,transformOrigin:`center`,marginLeft:v*-.0525,marginTop:v*-.0525,willChange:`opacity, transform`}})]});return c?(0,t.jsx)(`button`,{...u,type:`button`,className:a,disabled:s,onClick:s?void 0:l,style:{appearance:`none`,WebkitAppearance:`none`,border:0,padding:0,margin:0,background:`transparent`,color:`inherit`,font:`inherit`,cursor:s?`not-allowed`:`pointer`,...y},children:b}):(0,t.jsx)(`div`,{...u,className:a,style:y,children:b})}var ae=typeof window<`u`?e.useLayoutEffect:e.useEffect,oe=`
112
112
  attribute vec2 a_position;
113
113
 
114
114
  void main() {
115
115
  gl_Position = vec4(a_position, 0.0, 1.0);
116
116
  }
117
- `,ae=`
117
+ `,se=`
118
118
  precision highp float;
119
119
 
120
120
  uniform vec2 u_resolution;
@@ -193,11 +193,111 @@ void main() {
193
193
  // perimeter so translucent edge pixels cannot become a bright outline.
194
194
  gl_FragColor = vec4(color * edge, edge);
195
195
  }
196
- `,oe=`
196
+ `,ce=`
197
197
  @keyframes orb-radial-spinner {
198
198
  to { transform: rotate(360deg); }
199
199
  }
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,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=$;
203
+ `,le=.66,ue=.2;function J(e,t=0,n=1){return Math.min(n,Math.max(t,e))}function Y(e,t,n,r){return e+(t-e)*(1-Math.exp(-n*r))}function X(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 de(e,t){let n=e.getContext(`webgl`,{alpha:!0,antialias:!0,premultipliedAlpha:!0});if(!n)return;let r=X(n,n.VERTEX_SHADER,oe),i=X(n,n.FRAGMENT_SHADER,se);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 fe(e){return e!==`idle`&&e!==`connecting`&&e!==`error`}function pe({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 me({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);ae(()=>{f.current=n,p.current=r},[n,r]);let h=i*le,g=h*ue;(0,e.useEffect)(()=>{let e=`orb-radial-keyframes`;if(!document.getElementById(e)){let t=document.createElement(`style`);t.id=e,t.textContent=ce,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=de(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=J(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=J(p.current);b=d?0:Y(b,h,h>b?15:7,t);let w=n===`listening`?b:0,T=n===`speaking`?b:0;x=d?0:Y(x,w,w>x?17:7,t),S=d?0:Y(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=Y(s,E,3.6,t),c=Y(c,D,3.6,t),l=Y(l,O,3.6,t),y=Y(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 _=fe(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)(pe,{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})}var he=typeof window<`u`?e.useLayoutEffect:e.useEffect,ge={light:{deep:`#0b4068`,shallow:`#43adca`,foam:`#f6fcfe`,glow:`#ffe4b3`,sky:`#d9ebf4`,horizon:`#a6d6e5`},dark:{deep:`#05182b`,shallow:`#1f7a9c`,foam:`#d6f0f8`,glow:`#b4dcff`,sky:`#0b1a2b`,horizon:`#1c4661`}},_e=`
204
+ attribute vec2 a_position;
205
+
206
+ void main() {
207
+ gl_Position = vec4(a_position, 0.0, 1.0);
208
+ }
209
+ `,ve=`
210
+ precision highp float;
211
+
212
+ uniform vec2 u_resolution;
213
+ uniform float u_time;
214
+ uniform float u_level;
215
+ uniform float u_swell;
216
+ uniform float u_ripple;
217
+ uniform float u_glow;
218
+ uniform float u_tilt;
219
+ uniform float u_listen;
220
+ uniform float u_speak;
221
+ uniform vec3 u_deep;
222
+ uniform vec3 u_shallow;
223
+ uniform vec3 u_foam;
224
+ uniform vec3 u_light;
225
+ uniform vec3 u_sky;
226
+ uniform vec3 u_horizon;
227
+
228
+ float swellHeight(float x, float t, float swell) {
229
+ return swell * (
230
+ sin(x * 2.1 + t * 0.9) +
231
+ 0.55 * sin(x * 3.7 - t * 0.63 + 1.3) +
232
+ 0.3 * sin(x * 6.3 + t * 1.21 + 2.1)
233
+ );
234
+ }
235
+
236
+ float rippleHeight(float x, float t, float ripple) {
237
+ return ripple * 0.028 * sin(x * 12.0 - t * 5.2) * sin(x * 7.5 + t * 3.7);
238
+ }
239
+
240
+ void main() {
241
+ vec2 uv = gl_FragCoord.xy / u_resolution;
242
+ vec2 p = (uv - 0.5) * 2.0;
243
+ float radius = length(p);
244
+ float edge = 1.0 - smoothstep(0.985, 1.0, radius);
245
+
246
+ if (edge <= 0.0) discard;
247
+
248
+ float z = sqrt(max(0.0, 1.0 - radius * radius));
249
+ vec3 normal = vec3(p, z);
250
+
251
+ // The water sits behind a curved glass front: coordinates bend toward the
252
+ // centre near the rim, so the sea reads as inside a sphere, not painted on.
253
+ vec2 q = p * (1.0 - 0.22 * (1.0 - z));
254
+ float c = cos(u_tilt);
255
+ float s = sin(u_tilt);
256
+ q = vec2(q.x * c - q.y * s, q.x * s + q.y * c);
257
+
258
+ float t = u_time;
259
+ float front = swellHeight(q.x, t, u_swell) + rippleHeight(q.x, t, u_ripple);
260
+ float waterline = u_level + front;
261
+ float d = q.y - waterline;
262
+ float depth = max(0.0, -d);
263
+
264
+ // A second, slower swell further back gives the water a body to look into.
265
+ float back = swellHeight(q.x * 0.8 + 1.7, t * 0.72, u_swell * 0.8);
266
+ float backline = u_level - 0.16 + back;
267
+ float backBand = 1.0 - smoothstep(0.0, 0.06, abs(q.y - backline));
268
+
269
+ vec3 water = mix(u_shallow, u_deep, smoothstep(0.0, 1.05, depth));
270
+ float caustic = sin(q.x * 6.0 + front * 4.0 + t * 0.8) * sin(q.y * 5.0 - t * 0.6 + q.x * 1.5);
271
+ caustic = pow(max(caustic, 0.0), 3.0) * exp(-depth * 1.6) * (0.28 + u_glow * 0.45);
272
+ water = mix(water, u_shallow * 1.25, caustic);
273
+ float shaft = pow(max(sin(q.x * 3.0 + t * 0.27), 0.0), 5.0) * exp(-depth * 2.2);
274
+ water = mix(water, u_light, shaft * 0.08 * (0.4 + u_glow));
275
+ water = mix(water, mix(u_shallow, u_foam, 0.3), backBand * 0.14 * step(0.0, -d));
276
+ water = mix(water, u_deep, exp(-depth * 24.0) * 0.18);
277
+
278
+ vec3 air = mix(u_horizon, u_sky, smoothstep(0.0, 0.85, d));
279
+ float sun = exp(-length(q - vec2(-0.36, 0.58)) * 3.1);
280
+ air = mix(air, u_light, sun * (0.22 + u_glow * 0.36));
281
+ air = mix(air, u_light, exp(-max(d, 0.0) * 6.0) * 0.1 * u_glow);
282
+
283
+ vec3 color = d < 0.0 ? water : air;
284
+
285
+ float foamWidth = 30.0 - u_speak * 10.0;
286
+ float foam = exp(-abs(d) * foamWidth) * (0.6 + u_speak * 0.35 + u_listen * 0.2);
287
+ float crest = smoothstep(0.35, 1.0, front / max(u_swell * 1.85, 0.001));
288
+ foam += crest * exp(-abs(d) * 16.0) * (0.22 + u_speak * 0.3);
289
+ color = mix(color, u_foam, clamp(foam, 0.0, 0.92));
290
+
291
+ // Glass: a Fresnel rim, one soft specular, and a little weight at the bottom.
292
+ float fresnel = pow(1.0 - z, 2.8);
293
+ color = mix(color, mix(u_foam, u_light, 0.5), fresnel * 0.32);
294
+ vec3 lightDir = normalize(vec3(-0.48, 0.7, 0.54));
295
+ float spec = pow(max(dot(normal, lightDir), 0.0), 48.0);
296
+ color = mix(color, vec3(1.0), spec * 0.4);
297
+ color *= 1.0 - 0.18 * smoothstep(0.1, 1.0, -p.y) * (1.0 - z * 0.6);
298
+
299
+ // The drawing buffer uses premultiplied alpha. Premultiply the antialiased
300
+ // perimeter so translucent edge pixels cannot become a bright outline.
301
+ gl_FragColor = vec4(color * edge, edge);
302
+ }
303
+ `,ye=.72;function Z(e,t=0,n=1){return Math.min(n,Math.max(t,e))}function Q(e,t,n,r){return e+(t-e)*(1-Math.exp(-n*r))}function be(e,t){let n=/^#?([0-9a-f]{6})$/i.exec(e.trim());if(!n)return t;let r=parseInt(n[1],16);return[(r>>16&255)/255,(r>>8&255)/255,(r&255)/255]}function $([e,t,n],r){return`rgba(${Math.round(e*255)}, ${Math.round(t*255)}, ${Math.round(n*255)}, ${r})`}function xe(e,t){let n=ge[e],r=e=>{let r=be(n[e],[0,0,0]),i=t?.[e];return i?be(i,r):r};return{deep:r(`deep`),shallow:r(`shallow`),foam:r(`foam`),glow:r(`glow`),sky:r(`sky`),horizon:r(`horizon`)}}function Se(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 Ce(e,t,n){let r=e.getContext(`webgl`,{alpha:!0,antialias:!0,premultipliedAlpha:!0});if(!r)return;let i=Se(r,r.VERTEX_SHADER,_e),a=Se(r,r.FRAGMENT_SHADER,ve);if(!i||!a){i&&r.deleteShader(i),a&&r.deleteShader(a);return}let o=r.createProgram(),s=r.createBuffer();if(!o||!s){o&&r.deleteProgram(o),s&&r.deleteBuffer(s),r.deleteShader(i),r.deleteShader(a);return}if(r.attachShader(o,i),r.attachShader(o,a),r.linkProgram(o),!r.getProgramParameter(o,r.LINK_STATUS)){r.deleteProgram(o),r.deleteBuffer(s),r.deleteShader(i),r.deleteShader(a);return}let c=()=>{r.deleteProgram(o),r.deleteBuffer(s),r.deleteShader(i),r.deleteShader(a)},l=r.getAttribLocation(o,`a_position`),u=e=>r.getUniformLocation(o,e),d={resolution:u(`u_resolution`),time:u(`u_time`),level:u(`u_level`),swell:u(`u_swell`),ripple:u(`u_ripple`),glow:u(`u_glow`),tilt:u(`u_tilt`),listen:u(`u_listen`),speak:u(`u_speak`),deep:u(`u_deep`),shallow:u(`u_shallow`),foam:u(`u_foam`),light:u(`u_light`),sky:u(`u_sky`),horizon:u(`u_horizon`)};if(l<0||Object.values(d).some(e=>!e)){c();return}let f=Math.min(window.devicePixelRatio||1,2),p=Math.max(1,Math.round(t*f));return e.width=p,e.height=p,r.viewport(0,0,p,p),r.useProgram(o),r.bindBuffer(r.ARRAY_BUFFER,s),r.bufferData(r.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]),r.STATIC_DRAW),r.enableVertexAttribArray(l),r.vertexAttribPointer(l,2,r.FLOAT,!1,0,0),r.uniform2f(d.resolution,p,p),r.uniform3fv(d.deep,n.deep),r.uniform3fv(d.shallow,n.shallow),r.uniform3fv(d.foam,n.foam),r.uniform3fv(d.light,n.glow),r.uniform3fv(d.sky,n.sky),r.uniform3fv(d.horizon,n.horizon),{draw(e){r.uniform1f(d.time,e.time),r.uniform1f(d.level,e.level),r.uniform1f(d.swell,e.swell),r.uniform1f(d.ripple,e.ripple),r.uniform1f(d.glow,e.glow),r.uniform1f(d.tilt,e.tilt),r.uniform1f(d.listen,e.listen),r.uniform1f(d.speak,e.speak),r.drawArrays(r.TRIANGLES,0,6)},destroy:c}}function we(e,t,n,r){switch(e){case`connecting`:return{swell:.03,speed:.32,glow:.28+.16*Math.sin(r*2.6),tiltAmplitude:.02,levelOffset:0};case`listening`:return{swell:.045+t*.02,speed:.5+t*.25,glow:.36+t*.3,tiltAmplitude:.03,levelOffset:t*.03};case`thinking`:return{swell:.05,speed:.58,glow:.5+.2*Math.sin(r*2.4),tiltAmplitude:.055,levelOffset:.01};case`speaking`:return{swell:.06+n*.09,speed:.82+n*.7,glow:.52+n*.42,tiltAmplitude:.035,levelOffset:.02+n*.03};case`error`:return{swell:.02,speed:.2,glow:.06,tiltAmplitude:.01,levelOffset:-.04};default:return{swell:.036,speed:.36,glow:.26,tiltAmplitude:.028,levelOffset:0}}}var Te=.1,Ee=7.5;function De({state:n,volume:r,size:i,scheme:a=`light`,palette:o,className:s,style:c,disabled:l=!1,interactive:u=!1,onClick:d,...f}){let p=(0,e.useRef)(null),m=(0,e.useRef)(null),h=(0,e.useRef)(n),g=(0,e.useRef)(r),_=(0,e.useRef)(!1);he(()=>{h.current=n,g.current=r},[n,r]);let v=i*ye,y=xe(a,o),b=JSON.stringify(y);(0,e.useEffect)(()=>{let e=p.current,t=m.current;if(!e||!t)return;let n=JSON.parse(b),r=window.matchMedia(`(prefers-reduced-motion: reduce)`),i=()=>{_.current=r.matches};i(),r.addEventListener(`change`,i);let a=Ce(e,v,n);a||(e.style.background=`linear-gradient(180deg, ${$(n.sky,1)} 0%, ${$(n.horizon,1)} 44%, ${$(n.shallow,1)} 48%, ${$(n.deep,1)} 100%)`);let o=0,s=performance.now(),c=0,l=0,u=0,d=0,f=Z(g.current),y=0,x=0,S=.036,C=.36,w=.26,T=.028,E=0,D=.3,O=e=>{let n=Math.min((e-s)/1e3,.05);s=e;let r=h.current,i=_.current,p=Z(g.current);f=i?0:Q(f,p,p>f?14:6,n);let m=r===`listening`?f:0,v=r===`speaking`?f:0;y=Q(y,m,m>y?16:6,n),x=Q(x,v,v>x?11:4.5,n),l+=n;let b=we(r,y,x,l);S=Q(S,b.swell,2.4,n),C=Q(C,b.speed,2.4,n),w=Q(w,b.glow,3.2,n),T=Q(T,b.tiltAmplitude,1.8,n),E=Q(E,b.levelOffset,3,n),i||(c+=n*C,u+=n*Math.PI*2/Ee,d+=n*.31);let k=Te+E+Math.sin(u)*.022,A=Math.sin(d)*T+Math.sin(d*2.3+.7)*.006;a?.draw({time:c,level:k,swell:i?.012:S,ripple:i?0:y,glow:w,tilt:i?0:A,listen:y,speak:x});let j=r===`error`?.08:.28+w*.3+x*.35;D=Q(D,j,4,n),t.style.opacity=String(D),t.style.transform=`scale(${1+x*.08+Math.sin(u)*.015})`,o=requestAnimationFrame(O)};return o=requestAnimationFrame(O),()=>{cancelAnimationFrame(o),r.removeEventListener(`change`,i),a?.destroy()}},[v,b]);let x={width:i,height:i,display:`flex`,alignItems:`center`,justifyContent:`center`,position:`relative`,...c},S=(0,t.jsxs)(`span`,{style:{position:`relative`,display:`block`,width:v,height:v,borderRadius:`50%`,lineHeight:0,cursor:u?l?`not-allowed`:`pointer`:`default`},children:[(0,t.jsx)(`span`,{ref:m,"data-ocean-halo":``,"aria-hidden":`true`,style:{position:`absolute`,inset:`-${v*.28}px`,display:`block`,borderRadius:`50%`,background:`radial-gradient(circle, ${$(y.glow,.55)} 0%, ${$(y.shallow,.22)} 42%, ${$(y.shallow,0)} 72%)`,opacity:.3,transformOrigin:`center`,willChange:`opacity, transform`,pointerEvents:`none`}}),(0,t.jsx)(`canvas`,{ref:p,"aria-hidden":`true`,"data-ocean-surface":``,style:{position:`absolute`,inset:0,display:`block`,width:v,height:v,borderRadius:`50%`,boxShadow:`0 ${v*.06}px ${v*.22}px ${$(y.deep,a===`dark`?.55:.28)}`}})]});return u?(0,t.jsx)(`button`,{...f,type:`button`,className:s,disabled:l,onClick:l?void 0:d,style:{appearance:`none`,WebkitAppearance:`none`,border:0,padding:0,margin:0,background:`transparent`,color:`inherit`,font:`inherit`,cursor:l?`not-allowed`:`pointer`,...x},children:S}):(0,t.jsx)(`div`,{...f,className:s,style:x,children:S})}function Oe({signal:i,state:a,volume:s,adapter:c,theme:l=`debug`,size:u=200,scheme:d,palette:f,className:p,style:m,disabled:h=!1,interactive:g=!0,onStart:_,onStop:v,renderTheme:y,...x}){let[S,C]=(0,e.useState)({state:`idle`});(0,e.useEffect)(()=>{if(C({state:`idle`}),c)return c.subscribe(C)},[c]);let w=i??S,T=n(a,i,S),D=r(s,T,w),O=w.inputVolume??0,k=w.outputVolume??0,A=(0,e.useMemo)(()=>({...w,state:T,inputVolume:O,outputVolume:k}),[w,O,k,T]),j=T!==`idle`&&T!==`error`,M=(0,e.useCallback)(()=>{if(!h)return _?_():c?.start?.()},[c,h,_]),N=(0,e.useCallback)(()=>{if(!h)return v?v():c?.stop?.()},[c,h,v]),P=(0,e.useCallback)(()=>j?N():M(),[j,M,N]),F=j?!!(c?.stop||v):!!(c?.start||_),I=g&&F,L=I&&!h?P:void 0,R=x[`aria-label`]??(I?`${j?`Stop`:`Start`} voice session`:void 0),ee={...x,"aria-label":R};if(y){let e={...x,type:`button`,disabled:h||!I,onClick:L,"data-orb-ui-state":T,"aria-label":R};return y({state:T,signal:A,inputVolume:O,outputVolume:k,activity:D,size:u,isActive:j,interactive:I,disabled:h,start:M,stop:N,toggle:P,rootProps:{className:p,style:{width:u,height:u,...m},"data-orb-ui-theme":`custom`,"data-orb-ui-state":T},controlProps:e})}let z={state:T,volume:D,size:u,className:p,style:m,disabled:h,...ee},B={...z,interactive:I};switch(l){case`circle`:return(0,t.jsx)(b,{...B,onClick:L});case`bars`:return(0,t.jsx)(E,{...B,onClick:L});case`cloud`:return(0,t.jsx)(ie,{...B,onClick:L});case`radial`:return(0,t.jsx)(me,{...B,onClick:L});case`ocean`:return(0,t.jsx)(De,{...B,scheme:d,palette:f,onClick:L});default:return(0,t.jsx)(o,{...z,disabled:h||!g,onStart:h||!g?void 0:M,onStop:h||!g?void 0:N})}}exports.Orb=Oe,exports.VoiceOrb=Oe;
package/dist/orb-ui.js CHANGED
@@ -711,13 +711,13 @@ function se({ state: e, volume: n, size: r, className: a, style: c, disabled: l
711
711
  //#endregion
712
712
  //#region src/themes/radial/RadialTheme.tsx
713
713
  var ce = typeof window < "u" ? n : t, le = "\nattribute vec2 a_position;\n\nvoid main() {\n gl_Position = vec4(a_position, 0.0, 1.0);\n}\n", ue = "\nprecision highp float;\n\nuniform vec2 u_resolution;\nuniform float u_time;\nuniform float u_rotation;\nuniform float u_listen;\nuniform float u_speak;\n\nvoid main() {\n vec2 uv = gl_FragCoord.xy / u_resolution;\n vec2 p = (uv - 0.5) * 2.0;\n float radius = length(p);\n float edge = 1.0 - smoothstep(0.993, 1.0, radius);\n\n if (edge <= 0.0) discard;\n\n float angle = atan(p.y, p.x);\n float warpStrength = 0.026 + u_speak * 0.105;\n float angularWarp =\n sin(angle * 3.0 - u_time * 0.54 + radius * 2.1) +\n 0.48 * sin(angle * 5.0 + u_time * 0.31 - radius * 3.7) +\n 0.22 * sin(angle * 8.0 - u_time * 0.19 + radius * 5.2);\n float phase =\n angle - 1.78 - u_rotation + angularWarp * warpStrength * (0.2 + radius * 0.8);\n\n // Two opposing dark lobes and two opposing aqua lobes form the main pinwheel.\n float lobeField = cos(phase * 2.0);\n float darkMix = smoothstep(-0.04, 0.38, lobeField);\n\n vec3 deepBlue = vec3(0.004, 0.105, 0.37);\n vec3 cobalt = vec3(0.015, 0.34, 0.76);\n vec3 aqua = vec3(0.24, 0.76, 0.79);\n vec3 paleAqua = vec3(0.77, 0.96, 0.95);\n\n float radialLight = 0.5 + 0.5 * sin(radius * 3.0 - u_time * 0.16);\n vec3 darkColor = mix(cobalt, deepBlue, 0.42 + 0.38 * radius);\n float darkRay = pow(max(lobeField, 0.0), 11.0);\n darkColor = mix(darkColor, aqua, darkRay * (0.18 + radialLight * 0.16));\n\n vec3 lightColor = mix(paleAqua, aqua, 0.5 + 0.2 * sin(radius * 3.4 + phase * 2.0));\n float lightRay = pow(max(-lobeField, 0.0), 5.0);\n lightColor = mix(lightColor, vec3(0.04, 0.42, 0.64), lightRay * 0.28);\n\n vec3 color = mix(lightColor, darkColor, darkMix);\n\n // Soft secondary streaks make each of the four lobes feel layered rather than flat.\n float secondaryRay = 0.5 + 0.5 * sin(phase * 6.0 + radius * 1.8 - u_time * 0.42);\n float rayStrength = (0.055 + u_speak * 0.045) * (0.25 + radius * 0.75);\n color = mix(color, vec3(0.26, 0.76, 0.8), secondaryRay * rayStrength);\n\n // The outer membrane keeps a circular perimeter while independent traveling waves\n // continuously reshape its inner boundary.\n float rimWave =\n 0.063 * sin(angle * 3.0 + u_time * 1.34) +\n 0.036 * sin(angle * 5.0 - u_time * 0.91 + 1.4) +\n 0.021 * sin(angle * 7.0 + u_time * 0.63 - 0.8) +\n 0.012 * sin(angle * 11.0 - u_time * 1.72 + sin(angle * 2.0 + u_time * 0.58));\n rimWave *= 1.0 + u_listen * 0.38;\n float rimInner = 0.82 + rimWave - u_listen * 0.2;\n float rim = smoothstep(rimInner - 0.02, rimInner + 0.015, radius);\n float rimStrength = rim * (0.3 + u_listen * 0.3);\n vec3 membrane = mix(\n vec3(0.47, 0.84, 0.84),\n vec3(0.76, 0.93, 0.92),\n smoothstep(0.78, 1.0, radius)\n );\n color = mix(color, membrane, clamp(rimStrength, 0.0, 0.72));\n\n // Only one transition direction becomes a bright seam, producing two opposing ribbons.\n float seamDirection = max(0.0, -sin(phase * 2.0));\n float seamExponent = mix(30.0, 3.2, smoothstep(0.05, 1.0, radius));\n float seam = pow(seamDirection, seamExponent) * (0.78 + radius * 0.25);\n color = mix(color, vec3(0.985, 0.995, 0.995), clamp(seam, 0.0, 0.96));\n\n // The drawing buffer uses premultiplied alpha. Premultiply the antialiased\n // perimeter so translucent edge pixels cannot become a bright outline.\n gl_FragColor = vec4(color * edge, edge);\n}\n", de = "\n@keyframes orb-radial-spinner {\n to { transform: rotate(360deg); }\n}\n@media (prefers-reduced-motion: reduce) {\n [data-radial-spinner] { animation: none !important; }\n}\n", fe = .66, pe = .2;
714
- function Z(e, t = 0, n = 1) {
714
+ function me(e, t = 0, n = 1) {
715
715
  return Math.min(n, Math.max(t, e));
716
716
  }
717
- function Q(e, t, n, r) {
717
+ function Z(e, t, n, r) {
718
718
  return e + (t - e) * (1 - Math.exp(-n * r));
719
719
  }
720
- function $(e, t, n) {
720
+ function he(e, t, n) {
721
721
  let r = e.createShader(t);
722
722
  if (r) {
723
723
  if (e.shaderSource(r, n), e.compileShader(r), !e.getShaderParameter(r, e.COMPILE_STATUS)) {
@@ -727,14 +727,14 @@ function $(e, t, n) {
727
727
  return r;
728
728
  }
729
729
  }
730
- function me(e, t) {
730
+ function ge(e, t) {
731
731
  let n = e.getContext("webgl", {
732
732
  alpha: !0,
733
733
  antialias: !0,
734
734
  premultipliedAlpha: !0
735
735
  });
736
736
  if (!n) return;
737
- let r = $(n, n.VERTEX_SHADER, le), i = $(n, n.FRAGMENT_SHADER, ue);
737
+ let r = he(n, n.VERTEX_SHADER, le), i = he(n, n.FRAGMENT_SHADER, ue);
738
738
  if (!r || !i) {
739
739
  r && n.deleteShader(r), i && n.deleteShader(i);
740
740
  return;
@@ -776,10 +776,10 @@ function me(e, t) {
776
776
  }
777
777
  };
778
778
  }
779
- function he(e) {
779
+ function _e(e) {
780
780
  return e !== "idle" && e !== "connecting" && e !== "error";
781
781
  }
782
- function ge({ active: e }) {
782
+ function ve({ active: e }) {
783
783
  return /* @__PURE__ */ o("svg", {
784
784
  "aria-hidden": "true",
785
785
  fill: "none",
@@ -798,7 +798,7 @@ function ge({ active: e }) {
798
798
  })
799
799
  });
800
800
  }
801
- function _e({ state: e, volume: n, size: r, className: a, style: c, disabled: l = !1, interactive: u = !1, onClick: d, ...f }) {
801
+ function ye({ state: e, volume: n, size: r, className: a, style: c, disabled: l = !1, interactive: u = !1, onClick: d, ...f }) {
802
802
  let p = i(null), m = i(e), h = i(n), g = i(!1);
803
803
  ce(() => {
804
804
  m.current = e, h.current = n;
@@ -817,16 +817,16 @@ function _e({ state: e, volume: n, size: r, className: a, style: c, disabled: l
817
817
  g.current = t.matches;
818
818
  };
819
819
  n(), t.addEventListener("change", n);
820
- let r = me(e, _), i = 0, a = performance.now(), o = 0, s = .36, c = .62, l = .15, u = 0, d = 0, f = 0, v = 0, y = +(m.current === "speaking"), b = Z(h.current), x = m.current === "listening" ? b : 0, S = m.current === "speaking" ? b : 0, C = (e) => {
820
+ let r = ge(e, _), i = 0, a = performance.now(), o = 0, s = .36, c = .62, l = .15, u = 0, d = 0, f = 0, v = 0, y = +(m.current === "speaking"), b = me(h.current), x = m.current === "listening" ? b : 0, S = m.current === "speaking" ? b : 0, C = (e) => {
821
821
  let t = Math.min((e - a) / 1e3, .05);
822
822
  a = e;
823
- let n = m.current, p = g.current, _ = Z(h.current);
824
- b = p ? 0 : Q(b, _, _ > b ? 15 : 7, t);
823
+ let n = m.current, p = g.current, _ = me(h.current);
824
+ b = p ? 0 : Z(b, _, _ > b ? 15 : 7, t);
825
825
  let w = n === "listening" ? b : 0, T = n === "speaking" ? b : 0;
826
- x = p ? 0 : Q(x, w, w > x ? 17 : 7, t), S = p ? 0 : Q(S, T, T > S ? 12 : 5, t);
826
+ x = p ? 0 : Z(x, w, w > x ? 17 : 7, t), S = p ? 0 : Z(S, T, T > S ? 12 : 5, t);
827
827
  let E = .36, D = .62, O = .15;
828
828
  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), !p) {
829
- s = Q(s, E, 3.6, t), c = Q(c, D, 3.6, t), l = Q(l, O, 3.6, t), y = Q(y, +(n === "speaking"), n === "speaking" ? 3.8 : 3, t), o += t * s, f += t * c;
829
+ 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, f += t * c;
830
830
  let e = 1.2 + S * 1.35 + Math.sin(o * 1.73) * .34 + Math.sin(o * .61 + .8) * .18;
831
831
  v += t * Math.max(.65, e);
832
832
  let r = Math.sin(f) * l + Math.sin(f * .47 + 1.1) * .032, i = Math.sin(v * 1.08), a = Math.sin(v * 2.47 + .9), p = Math.sin(v * .43 - .5), m = r + (i * (.13 + S * .17) + a * (.035 + S * .035) + p * .055 - r) * y, h = 4.2 + y * 3, g = h * h, _ = 2 * h;
@@ -838,7 +838,7 @@ function _e({ state: e, volume: n, size: r, className: a, style: c, disabled: l
838
838
  cancelAnimationFrame(i), t.removeEventListener("change", n), r?.destroy();
839
839
  };
840
840
  }, [_]);
841
- let y = he(e), b = e === "connecting", x = _ + (u ? v * .5 : 0), S = {
841
+ let y = _e(e), b = e === "connecting", x = _ + (u ? v * .5 : 0), S = {
842
842
  "--orb-ui-radial-control-surround": "#fff",
843
843
  width: r,
844
844
  height: r,
@@ -913,7 +913,7 @@ function _e({ state: e, volume: n, size: r, className: a, style: c, disabled: l
913
913
  borderRadius: "50%",
914
914
  animation: "orb-radial-spinner 760ms linear infinite"
915
915
  }
916
- }) : /* @__PURE__ */ o(ge, { active: y })
916
+ }) : /* @__PURE__ */ o(ve, { active: y })
917
917
  }) : null]
918
918
  });
919
919
  return u ? /* @__PURE__ */ o("div", {
@@ -928,113 +928,414 @@ function _e({ state: e, volume: n, size: r, className: a, style: c, disabled: l
928
928
  });
929
929
  }
930
930
  //#endregion
931
+ //#region src/themes/ocean/OceanTheme.tsx
932
+ var be = typeof window < "u" ? n : t, xe = {
933
+ light: {
934
+ deep: "#0b4068",
935
+ shallow: "#43adca",
936
+ foam: "#f6fcfe",
937
+ glow: "#ffe4b3",
938
+ sky: "#d9ebf4",
939
+ horizon: "#a6d6e5"
940
+ },
941
+ dark: {
942
+ deep: "#05182b",
943
+ shallow: "#1f7a9c",
944
+ foam: "#d6f0f8",
945
+ glow: "#b4dcff",
946
+ sky: "#0b1a2b",
947
+ horizon: "#1c4661"
948
+ }
949
+ }, Se = "\nattribute vec2 a_position;\n\nvoid main() {\n gl_Position = vec4(a_position, 0.0, 1.0);\n}\n", Ce = "\nprecision highp float;\n\nuniform vec2 u_resolution;\nuniform float u_time;\nuniform float u_level;\nuniform float u_swell;\nuniform float u_ripple;\nuniform float u_glow;\nuniform float u_tilt;\nuniform float u_listen;\nuniform float u_speak;\nuniform vec3 u_deep;\nuniform vec3 u_shallow;\nuniform vec3 u_foam;\nuniform vec3 u_light;\nuniform vec3 u_sky;\nuniform vec3 u_horizon;\n\nfloat swellHeight(float x, float t, float swell) {\n return swell * (\n sin(x * 2.1 + t * 0.9) +\n 0.55 * sin(x * 3.7 - t * 0.63 + 1.3) +\n 0.3 * sin(x * 6.3 + t * 1.21 + 2.1)\n );\n}\n\nfloat rippleHeight(float x, float t, float ripple) {\n return ripple * 0.028 * sin(x * 12.0 - t * 5.2) * sin(x * 7.5 + t * 3.7);\n}\n\nvoid main() {\n vec2 uv = gl_FragCoord.xy / u_resolution;\n vec2 p = (uv - 0.5) * 2.0;\n float radius = length(p);\n float edge = 1.0 - smoothstep(0.985, 1.0, radius);\n\n if (edge <= 0.0) discard;\n\n float z = sqrt(max(0.0, 1.0 - radius * radius));\n vec3 normal = vec3(p, z);\n\n // The water sits behind a curved glass front: coordinates bend toward the\n // centre near the rim, so the sea reads as inside a sphere, not painted on.\n vec2 q = p * (1.0 - 0.22 * (1.0 - z));\n float c = cos(u_tilt);\n float s = sin(u_tilt);\n q = vec2(q.x * c - q.y * s, q.x * s + q.y * c);\n\n float t = u_time;\n float front = swellHeight(q.x, t, u_swell) + rippleHeight(q.x, t, u_ripple);\n float waterline = u_level + front;\n float d = q.y - waterline;\n float depth = max(0.0, -d);\n\n // A second, slower swell further back gives the water a body to look into.\n float back = swellHeight(q.x * 0.8 + 1.7, t * 0.72, u_swell * 0.8);\n float backline = u_level - 0.16 + back;\n float backBand = 1.0 - smoothstep(0.0, 0.06, abs(q.y - backline));\n\n vec3 water = mix(u_shallow, u_deep, smoothstep(0.0, 1.05, depth));\n float caustic = sin(q.x * 6.0 + front * 4.0 + t * 0.8) * sin(q.y * 5.0 - t * 0.6 + q.x * 1.5);\n caustic = pow(max(caustic, 0.0), 3.0) * exp(-depth * 1.6) * (0.28 + u_glow * 0.45);\n water = mix(water, u_shallow * 1.25, caustic);\n float shaft = pow(max(sin(q.x * 3.0 + t * 0.27), 0.0), 5.0) * exp(-depth * 2.2);\n water = mix(water, u_light, shaft * 0.08 * (0.4 + u_glow));\n water = mix(water, mix(u_shallow, u_foam, 0.3), backBand * 0.14 * step(0.0, -d));\n water = mix(water, u_deep, exp(-depth * 24.0) * 0.18);\n\n vec3 air = mix(u_horizon, u_sky, smoothstep(0.0, 0.85, d));\n float sun = exp(-length(q - vec2(-0.36, 0.58)) * 3.1);\n air = mix(air, u_light, sun * (0.22 + u_glow * 0.36));\n air = mix(air, u_light, exp(-max(d, 0.0) * 6.0) * 0.1 * u_glow);\n\n vec3 color = d < 0.0 ? water : air;\n\n float foamWidth = 30.0 - u_speak * 10.0;\n float foam = exp(-abs(d) * foamWidth) * (0.6 + u_speak * 0.35 + u_listen * 0.2);\n float crest = smoothstep(0.35, 1.0, front / max(u_swell * 1.85, 0.001));\n foam += crest * exp(-abs(d) * 16.0) * (0.22 + u_speak * 0.3);\n color = mix(color, u_foam, clamp(foam, 0.0, 0.92));\n\n // Glass: a Fresnel rim, one soft specular, and a little weight at the bottom.\n float fresnel = pow(1.0 - z, 2.8);\n color = mix(color, mix(u_foam, u_light, 0.5), fresnel * 0.32);\n vec3 lightDir = normalize(vec3(-0.48, 0.7, 0.54));\n float spec = pow(max(dot(normal, lightDir), 0.0), 48.0);\n color = mix(color, vec3(1.0), spec * 0.4);\n color *= 1.0 - 0.18 * smoothstep(0.1, 1.0, -p.y) * (1.0 - z * 0.6);\n\n // The drawing buffer uses premultiplied alpha. Premultiply the antialiased\n // perimeter so translucent edge pixels cannot become a bright outline.\n gl_FragColor = vec4(color * edge, edge);\n}\n", we = .72;
950
+ function Te(e, t = 0, n = 1) {
951
+ return Math.min(n, Math.max(t, e));
952
+ }
953
+ function Q(e, t, n, r) {
954
+ return e + (t - e) * (1 - Math.exp(-n * r));
955
+ }
956
+ function Ee(e, t) {
957
+ let n = /^#?([0-9a-f]{6})$/i.exec(e.trim());
958
+ if (!n) return t;
959
+ let r = parseInt(n[1], 16);
960
+ return [
961
+ (r >> 16 & 255) / 255,
962
+ (r >> 8 & 255) / 255,
963
+ (r & 255) / 255
964
+ ];
965
+ }
966
+ function $([e, t, n], r) {
967
+ return `rgba(${Math.round(e * 255)}, ${Math.round(t * 255)}, ${Math.round(n * 255)}, ${r})`;
968
+ }
969
+ function De(e, t) {
970
+ let n = xe[e], r = (e) => {
971
+ let r = Ee(n[e], [
972
+ 0,
973
+ 0,
974
+ 0
975
+ ]), i = t?.[e];
976
+ return i ? Ee(i, r) : r;
977
+ };
978
+ return {
979
+ deep: r("deep"),
980
+ shallow: r("shallow"),
981
+ foam: r("foam"),
982
+ glow: r("glow"),
983
+ sky: r("sky"),
984
+ horizon: r("horizon")
985
+ };
986
+ }
987
+ function Oe(e, t, n) {
988
+ let r = e.createShader(t);
989
+ if (r) {
990
+ if (e.shaderSource(r, n), e.compileShader(r), !e.getShaderParameter(r, e.COMPILE_STATUS)) {
991
+ e.deleteShader(r);
992
+ return;
993
+ }
994
+ return r;
995
+ }
996
+ }
997
+ function ke(e, t, n) {
998
+ let r = e.getContext("webgl", {
999
+ alpha: !0,
1000
+ antialias: !0,
1001
+ premultipliedAlpha: !0
1002
+ });
1003
+ if (!r) return;
1004
+ let i = Oe(r, r.VERTEX_SHADER, Se), a = Oe(r, r.FRAGMENT_SHADER, Ce);
1005
+ if (!i || !a) {
1006
+ i && r.deleteShader(i), a && r.deleteShader(a);
1007
+ return;
1008
+ }
1009
+ let o = r.createProgram(), s = r.createBuffer();
1010
+ if (!o || !s) {
1011
+ o && r.deleteProgram(o), s && r.deleteBuffer(s), r.deleteShader(i), r.deleteShader(a);
1012
+ return;
1013
+ }
1014
+ if (r.attachShader(o, i), r.attachShader(o, a), r.linkProgram(o), !r.getProgramParameter(o, r.LINK_STATUS)) {
1015
+ r.deleteProgram(o), r.deleteBuffer(s), r.deleteShader(i), r.deleteShader(a);
1016
+ return;
1017
+ }
1018
+ let c = () => {
1019
+ r.deleteProgram(o), r.deleteBuffer(s), r.deleteShader(i), r.deleteShader(a);
1020
+ }, l = r.getAttribLocation(o, "a_position"), u = (e) => r.getUniformLocation(o, e), d = {
1021
+ resolution: u("u_resolution"),
1022
+ time: u("u_time"),
1023
+ level: u("u_level"),
1024
+ swell: u("u_swell"),
1025
+ ripple: u("u_ripple"),
1026
+ glow: u("u_glow"),
1027
+ tilt: u("u_tilt"),
1028
+ listen: u("u_listen"),
1029
+ speak: u("u_speak"),
1030
+ deep: u("u_deep"),
1031
+ shallow: u("u_shallow"),
1032
+ foam: u("u_foam"),
1033
+ light: u("u_light"),
1034
+ sky: u("u_sky"),
1035
+ horizon: u("u_horizon")
1036
+ };
1037
+ if (l < 0 || Object.values(d).some((e) => !e)) {
1038
+ c();
1039
+ return;
1040
+ }
1041
+ let f = Math.min(window.devicePixelRatio || 1, 2), p = Math.max(1, Math.round(t * f));
1042
+ return e.width = p, e.height = p, r.viewport(0, 0, p, p), r.useProgram(o), r.bindBuffer(r.ARRAY_BUFFER, s), r.bufferData(r.ARRAY_BUFFER, new Float32Array([
1043
+ -1,
1044
+ -1,
1045
+ 1,
1046
+ -1,
1047
+ -1,
1048
+ 1,
1049
+ -1,
1050
+ 1,
1051
+ 1,
1052
+ -1,
1053
+ 1,
1054
+ 1
1055
+ ]), r.STATIC_DRAW), r.enableVertexAttribArray(l), r.vertexAttribPointer(l, 2, r.FLOAT, !1, 0, 0), r.uniform2f(d.resolution, p, p), r.uniform3fv(d.deep, n.deep), r.uniform3fv(d.shallow, n.shallow), r.uniform3fv(d.foam, n.foam), r.uniform3fv(d.light, n.glow), r.uniform3fv(d.sky, n.sky), r.uniform3fv(d.horizon, n.horizon), {
1056
+ draw(e) {
1057
+ r.uniform1f(d.time, e.time), r.uniform1f(d.level, e.level), r.uniform1f(d.swell, e.swell), r.uniform1f(d.ripple, e.ripple), r.uniform1f(d.glow, e.glow), r.uniform1f(d.tilt, e.tilt), r.uniform1f(d.listen, e.listen), r.uniform1f(d.speak, e.speak), r.drawArrays(r.TRIANGLES, 0, 6);
1058
+ },
1059
+ destroy: c
1060
+ };
1061
+ }
1062
+ function Ae(e, t, n, r) {
1063
+ switch (e) {
1064
+ case "connecting": return {
1065
+ swell: .03,
1066
+ speed: .32,
1067
+ glow: .28 + .16 * Math.sin(r * 2.6),
1068
+ tiltAmplitude: .02,
1069
+ levelOffset: 0
1070
+ };
1071
+ case "listening": return {
1072
+ swell: .045 + t * .02,
1073
+ speed: .5 + t * .25,
1074
+ glow: .36 + t * .3,
1075
+ tiltAmplitude: .03,
1076
+ levelOffset: t * .03
1077
+ };
1078
+ case "thinking": return {
1079
+ swell: .05,
1080
+ speed: .58,
1081
+ glow: .5 + .2 * Math.sin(r * 2.4),
1082
+ tiltAmplitude: .055,
1083
+ levelOffset: .01
1084
+ };
1085
+ case "speaking": return {
1086
+ swell: .06 + n * .09,
1087
+ speed: .82 + n * .7,
1088
+ glow: .52 + n * .42,
1089
+ tiltAmplitude: .035,
1090
+ levelOffset: .02 + n * .03
1091
+ };
1092
+ case "error": return {
1093
+ swell: .02,
1094
+ speed: .2,
1095
+ glow: .06,
1096
+ tiltAmplitude: .01,
1097
+ levelOffset: -.04
1098
+ };
1099
+ default: return {
1100
+ swell: .036,
1101
+ speed: .36,
1102
+ glow: .26,
1103
+ tiltAmplitude: .028,
1104
+ levelOffset: 0
1105
+ };
1106
+ }
1107
+ }
1108
+ var je = .1, Me = 7.5;
1109
+ function Ne({ state: e, volume: n, size: r, scheme: a = "light", palette: c, className: l, style: u, disabled: d = !1, interactive: f = !1, onClick: p, ...m }) {
1110
+ let h = i(null), g = i(null), _ = i(e), v = i(n), y = i(!1);
1111
+ be(() => {
1112
+ _.current = e, v.current = n;
1113
+ }, [e, n]);
1114
+ let b = r * we, x = De(a, c), S = JSON.stringify(x);
1115
+ t(() => {
1116
+ let e = h.current, t = g.current;
1117
+ if (!e || !t) return;
1118
+ let n = JSON.parse(S), r = window.matchMedia("(prefers-reduced-motion: reduce)"), i = () => {
1119
+ y.current = r.matches;
1120
+ };
1121
+ i(), r.addEventListener("change", i);
1122
+ let a = ke(e, b, n);
1123
+ a || (e.style.background = `linear-gradient(180deg, ${$(n.sky, 1)} 0%, ${$(n.horizon, 1)} 44%, ${$(n.shallow, 1)} 48%, ${$(n.deep, 1)} 100%)`);
1124
+ let o = 0, s = performance.now(), c = 0, l = 0, u = 0, d = 0, f = Te(v.current), p = 0, m = 0, x = .036, C = .36, w = .26, T = .028, E = 0, D = .3, O = (e) => {
1125
+ let n = Math.min((e - s) / 1e3, .05);
1126
+ s = e;
1127
+ let r = _.current, i = y.current, h = Te(v.current);
1128
+ f = i ? 0 : Q(f, h, h > f ? 14 : 6, n);
1129
+ let g = r === "listening" ? f : 0, b = r === "speaking" ? f : 0;
1130
+ p = Q(p, g, g > p ? 16 : 6, n), m = Q(m, b, b > m ? 11 : 4.5, n), l += n;
1131
+ let S = Ae(r, p, m, l);
1132
+ x = Q(x, S.swell, 2.4, n), C = Q(C, S.speed, 2.4, n), w = Q(w, S.glow, 3.2, n), T = Q(T, S.tiltAmplitude, 1.8, n), E = Q(E, S.levelOffset, 3, n), i || (c += n * C, u += n * Math.PI * 2 / Me, d += n * .31);
1133
+ let k = je + E + Math.sin(u) * .022, A = Math.sin(d) * T + Math.sin(d * 2.3 + .7) * .006;
1134
+ a?.draw({
1135
+ time: c,
1136
+ level: k,
1137
+ swell: i ? .012 : x,
1138
+ ripple: i ? 0 : p,
1139
+ glow: w,
1140
+ tilt: i ? 0 : A,
1141
+ listen: p,
1142
+ speak: m
1143
+ });
1144
+ let j = r === "error" ? .08 : .28 + w * .3 + m * .35;
1145
+ D = Q(D, j, 4, n), t.style.opacity = String(D), t.style.transform = `scale(${1 + m * .08 + Math.sin(u) * .015})`, o = requestAnimationFrame(O);
1146
+ };
1147
+ return o = requestAnimationFrame(O), () => {
1148
+ cancelAnimationFrame(o), r.removeEventListener("change", i), a?.destroy();
1149
+ };
1150
+ }, [b, S]);
1151
+ let C = {
1152
+ width: r,
1153
+ height: r,
1154
+ display: "flex",
1155
+ alignItems: "center",
1156
+ justifyContent: "center",
1157
+ position: "relative",
1158
+ ...u
1159
+ }, w = /* @__PURE__ */ s("span", {
1160
+ style: {
1161
+ position: "relative",
1162
+ display: "block",
1163
+ width: b,
1164
+ height: b,
1165
+ borderRadius: "50%",
1166
+ lineHeight: 0,
1167
+ cursor: f ? d ? "not-allowed" : "pointer" : "default"
1168
+ },
1169
+ children: [/* @__PURE__ */ o("span", {
1170
+ ref: g,
1171
+ "data-ocean-halo": "",
1172
+ "aria-hidden": "true",
1173
+ style: {
1174
+ position: "absolute",
1175
+ inset: `-${b * .28}px`,
1176
+ display: "block",
1177
+ borderRadius: "50%",
1178
+ background: `radial-gradient(circle, ${$(x.glow, .55)} 0%, ${$(x.shallow, .22)} 42%, ${$(x.shallow, 0)} 72%)`,
1179
+ opacity: .3,
1180
+ transformOrigin: "center",
1181
+ willChange: "opacity, transform",
1182
+ pointerEvents: "none"
1183
+ }
1184
+ }), /* @__PURE__ */ o("canvas", {
1185
+ ref: h,
1186
+ "aria-hidden": "true",
1187
+ "data-ocean-surface": "",
1188
+ style: {
1189
+ position: "absolute",
1190
+ inset: 0,
1191
+ display: "block",
1192
+ width: b,
1193
+ height: b,
1194
+ borderRadius: "50%",
1195
+ boxShadow: `0 ${b * .06}px ${b * .22}px ${$(x.deep, a === "dark" ? .55 : .28)}`
1196
+ }
1197
+ })]
1198
+ });
1199
+ return f ? /* @__PURE__ */ o("button", {
1200
+ ...m,
1201
+ type: "button",
1202
+ className: l,
1203
+ disabled: d,
1204
+ onClick: d ? void 0 : p,
1205
+ style: {
1206
+ appearance: "none",
1207
+ WebkitAppearance: "none",
1208
+ border: 0,
1209
+ padding: 0,
1210
+ margin: 0,
1211
+ background: "transparent",
1212
+ color: "inherit",
1213
+ font: "inherit",
1214
+ cursor: d ? "not-allowed" : "pointer",
1215
+ ...C
1216
+ },
1217
+ children: w
1218
+ }) : /* @__PURE__ */ o("div", {
1219
+ ...m,
1220
+ className: l,
1221
+ style: C,
1222
+ children: w
1223
+ });
1224
+ }
1225
+ //#endregion
931
1226
  //#region src/components/Orb/Orb.tsx
932
- function ve({ signal: n, state: i, volume: s, adapter: u, theme: d = "debug", size: p = 200, className: m, style: h, disabled: g = !1, interactive: _ = !0, onStart: v, onStop: y, renderTheme: b, ...x }) {
933
- let [S, C] = a({ state: "idle" });
1227
+ function Pe({ signal: n, state: i, volume: s, adapter: u, theme: d = "debug", size: p = 200, scheme: m, palette: h, className: g, style: _, disabled: v = !1, interactive: y = !0, onStart: b, onStop: x, renderTheme: S, ...C }) {
1228
+ let [w, T] = a({ state: "idle" });
934
1229
  t(() => {
935
- if (C({ state: "idle" }), u) return u.subscribe(C);
1230
+ if (T({ state: "idle" }), u) return u.subscribe(T);
936
1231
  }, [u]);
937
- let w = n ?? S, T = c(i, n, S), D = l(s, T, w), O = w.inputVolume ?? 0, k = w.outputVolume ?? 0, A = r(() => ({
938
- ...w,
939
- state: T,
940
- inputVolume: O,
941
- outputVolume: k
1232
+ let D = n ?? w, O = c(i, n, w), k = l(s, O, D), A = D.inputVolume ?? 0, j = D.outputVolume ?? 0, N = r(() => ({
1233
+ ...D,
1234
+ state: O,
1235
+ inputVolume: A,
1236
+ outputVolume: j
942
1237
  }), [
943
- w,
944
- O,
945
- k,
946
- T
947
- ]), j = T !== "idle" && T !== "error", N = e(() => {
948
- if (!g) return v ? v() : u?.start?.();
1238
+ D,
1239
+ A,
1240
+ j,
1241
+ O
1242
+ ]), P = O !== "idle" && O !== "error", F = e(() => {
1243
+ if (!v) return b ? b() : u?.start?.();
949
1244
  }, [
950
1245
  u,
951
- g,
952
- v
953
- ]), P = e(() => {
954
- if (!g) return y ? y() : u?.stop?.();
1246
+ v,
1247
+ b
1248
+ ]), I = e(() => {
1249
+ if (!v) return x ? x() : u?.stop?.();
955
1250
  }, [
956
1251
  u,
957
- g,
958
- y
959
- ]), F = e(() => j ? P() : N(), [
960
- j,
961
- N,
962
- P
963
- ]), I = j ? !!(u?.stop || y) : !!(u?.start || v), L = _ && I, R = L && !g ? F : void 0, z = x["aria-label"] ?? (L ? `${j ? "Stop" : "Start"} voice session` : void 0), B = {
964
- ...x,
965
- "aria-label": z
1252
+ v,
1253
+ x
1254
+ ]), L = e(() => P ? I() : F(), [
1255
+ P,
1256
+ F,
1257
+ I
1258
+ ]), R = P ? !!(u?.stop || x) : !!(u?.start || b), z = y && R, B = z && !v ? L : void 0, V = C["aria-label"] ?? (z ? `${P ? "Stop" : "Start"} voice session` : void 0), H = {
1259
+ ...C,
1260
+ "aria-label": V
966
1261
  };
967
- if (b) {
1262
+ if (S) {
968
1263
  let e = {
969
- ...x,
1264
+ ...C,
970
1265
  type: "button",
971
- disabled: g || !L,
972
- onClick: R,
973
- "data-orb-ui-state": T,
974
- "aria-label": z
1266
+ disabled: v || !z,
1267
+ onClick: B,
1268
+ "data-orb-ui-state": O,
1269
+ "aria-label": V
975
1270
  };
976
- return b({
977
- state: T,
978
- signal: A,
979
- inputVolume: O,
980
- outputVolume: k,
981
- activity: D,
1271
+ return S({
1272
+ state: O,
1273
+ signal: N,
1274
+ inputVolume: A,
1275
+ outputVolume: j,
1276
+ activity: k,
982
1277
  size: p,
983
- isActive: j,
984
- interactive: L,
985
- disabled: g,
986
- start: N,
987
- stop: P,
988
- toggle: F,
1278
+ isActive: P,
1279
+ interactive: z,
1280
+ disabled: v,
1281
+ start: F,
1282
+ stop: I,
1283
+ toggle: L,
989
1284
  rootProps: {
990
- className: m,
1285
+ className: g,
991
1286
  style: {
992
1287
  width: p,
993
1288
  height: p,
994
- ...h
1289
+ ..._
995
1290
  },
996
1291
  "data-orb-ui-theme": "custom",
997
- "data-orb-ui-state": T
1292
+ "data-orb-ui-state": O
998
1293
  },
999
1294
  controlProps: e
1000
1295
  });
1001
1296
  }
1002
- let V = {
1003
- state: T,
1004
- volume: D,
1297
+ let U = {
1298
+ state: O,
1299
+ volume: k,
1005
1300
  size: p,
1006
- className: m,
1007
- style: h,
1008
- disabled: g,
1009
- ...B
1010
- }, H = {
1011
- ...V,
1012
- interactive: L
1301
+ className: g,
1302
+ style: _,
1303
+ disabled: v,
1304
+ ...H
1305
+ }, W = {
1306
+ ...U,
1307
+ interactive: z
1013
1308
  };
1014
1309
  switch (d) {
1015
1310
  case "circle": return /* @__PURE__ */ o(E, {
1016
- ...H,
1017
- onClick: R
1311
+ ...W,
1312
+ onClick: B
1018
1313
  });
1019
1314
  case "bars": return /* @__PURE__ */ o(M, {
1020
- ...H,
1021
- onClick: R
1315
+ ...W,
1316
+ onClick: B
1022
1317
  });
1023
1318
  case "cloud": return /* @__PURE__ */ o(se, {
1024
- ...H,
1025
- onClick: R
1319
+ ...W,
1320
+ onClick: B
1321
+ });
1322
+ case "radial": return /* @__PURE__ */ o(ye, {
1323
+ ...W,
1324
+ onClick: B
1026
1325
  });
1027
- case "radial": return /* @__PURE__ */ o(_e, {
1028
- ...H,
1029
- onClick: R
1326
+ case "ocean": return /* @__PURE__ */ o(Ne, {
1327
+ ...W,
1328
+ scheme: m,
1329
+ palette: h,
1330
+ onClick: B
1030
1331
  });
1031
1332
  default: return /* @__PURE__ */ o(f, {
1032
- ...V,
1033
- disabled: g || !_,
1034
- onStart: g || !_ ? void 0 : N,
1035
- onStop: g || !_ ? void 0 : P
1333
+ ...U,
1334
+ disabled: v || !y,
1335
+ onStart: v || !y ? void 0 : F,
1336
+ onStop: v || !y ? void 0 : I
1036
1337
  });
1037
1338
  }
1038
1339
  }
1039
1340
  //#endregion
1040
- export { ve as Orb, ve as VoiceOrb };
1341
+ export { Pe as Orb, Pe as VoiceOrb };
@@ -3,3 +3,4 @@ export { CircleTheme } from './circle/index.js';
3
3
  export { BarsTheme } from './bars/index.js';
4
4
  export { CloudTheme } from './cloud/index.js';
5
5
  export { RadialTheme } from './radial/index.js';
6
+ export { OceanTheme } from './ocean/index.js';
@@ -0,0 +1,27 @@
1
+ import { CSSProperties } from 'react';
2
+ import { OrbHtmlAttributes, OrbPalette, OrbScheme, OrbState } from '../../components/Orb/Orb.types.js';
3
+ interface OceanThemeProps extends OrbHtmlAttributes {
4
+ state: OrbState;
5
+ volume: number;
6
+ size: number;
7
+ scheme?: OrbScheme;
8
+ palette?: OrbPalette;
9
+ className?: string;
10
+ style?: CSSProperties;
11
+ disabled?: boolean;
12
+ interactive?: boolean;
13
+ onClick?: () => void;
14
+ }
15
+ type Rgb = [number, number, number];
16
+ interface ResolvedOceanPalette {
17
+ deep: Rgb;
18
+ shallow: Rgb;
19
+ foam: Rgb;
20
+ glow: Rgb;
21
+ sky: Rgb;
22
+ horizon: Rgb;
23
+ }
24
+ export declare const OCEAN_PALETTES: Record<OrbScheme, Required<OrbPalette>>;
25
+ export declare function resolveOceanPalette(scheme: OrbScheme, palette: OrbPalette | undefined): ResolvedOceanPalette;
26
+ export declare function OceanTheme({ state, volume, size, scheme, palette, className, style, disabled, interactive, onClick, ...controlProps }: OceanThemeProps): import("react").JSX.Element;
27
+ export {};
@@ -0,0 +1 @@
1
+ export { OceanTheme } from './OceanTheme.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lofcz/orb-ui",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "description": "React voice agent UI components with audio-reactive adapters for Vapi, ElevenLabs, LiveKit, Pipecat, OpenAI Realtime, Gemini Live, and custom voice AI apps.",
5
5
  "type": "module",
6
6
  "main": "./dist/orb-ui.cjs",