@w0nna_dev/lina-widget 1.0.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.
Files changed (48) hide show
  1. package/README.md +906 -0
  2. package/dist/index.d.ts +2 -0
  3. package/dist/lina-widget.es.js +42504 -0
  4. package/dist/lina-widget.umd.js +5755 -0
  5. package/dist/src/components/floating-call/floating-call.d.ts +53 -0
  6. package/dist/src/components/floating-call/index.d.ts +1 -0
  7. package/dist/src/components/index.d.ts +10 -0
  8. package/dist/src/components/inline-call/index.d.ts +1 -0
  9. package/dist/src/components/inline-call/inline-call.d.ts +53 -0
  10. package/dist/src/components/orb-widget.d.ts +59 -0
  11. package/dist/src/components/pill-call/index.d.ts +1 -0
  12. package/dist/src/components/pill-call/pill-call.d.ts +53 -0
  13. package/dist/src/core/color-utils.d.ts +3 -0
  14. package/dist/src/core/global-styles.d.ts +1 -0
  15. package/dist/src/core/livekit-call-manager.d.ts +74 -0
  16. package/dist/src/core/orb/AudioAnalyzer.d.ts +78 -0
  17. package/dist/src/core/orb/OrbRenderer.d.ts +86 -0
  18. package/dist/src/core/orb/SoundManager.d.ts +60 -0
  19. package/dist/src/core/orb/colorPresets.d.ts +22 -0
  20. package/dist/src/core/orb/glow.glsl.d.ts +4 -0
  21. package/dist/src/core/orb/index.d.ts +12 -0
  22. package/dist/src/core/orb/orb.frag.glsl.d.ts +1 -0
  23. package/dist/src/core/orb/orb.vert.glsl.d.ts +1 -0
  24. package/dist/src/core/orb/themes.d.ts +53 -0
  25. package/dist/src/icons/index.d.ts +2 -0
  26. package/dist/src/lina/components/LinaWidget.d.ts +45 -0
  27. package/dist/src/lina/components/index.d.ts +1 -0
  28. package/dist/src/lina/core/LinaOrbRenderer.d.ts +94 -0
  29. package/dist/src/lina/core/index.d.ts +1 -0
  30. package/dist/src/lina/index.d.ts +2 -0
  31. package/dist/src/lina/shaders/core.glsl.d.ts +2 -0
  32. package/dist/src/lina/shaders/effects.glsl.d.ts +6 -0
  33. package/dist/src/lina/shaders/index.d.ts +3 -0
  34. package/dist/src/lina/shaders/shell.glsl.d.ts +2 -0
  35. package/dist/src/orb/components/HancAiWidget.d.ts +120 -0
  36. package/dist/src/orb/components/index.d.ts +3 -0
  37. package/dist/src/orb/core/AudioAnalyzer.d.ts +68 -0
  38. package/dist/src/orb/core/LiveKitManager.d.ts +46 -0
  39. package/dist/src/orb/core/OrbRenderer.d.ts +87 -0
  40. package/dist/src/orb/core/SoundManager.d.ts +55 -0
  41. package/dist/src/orb/core/index.d.ts +8 -0
  42. package/dist/src/orb/index.d.ts +5 -0
  43. package/dist/src/orb/shaders/glow.glsl.d.ts +4 -0
  44. package/dist/src/orb/shaders/index.d.ts +3 -0
  45. package/dist/src/orb/shaders/orb.frag.glsl.d.ts +1 -0
  46. package/dist/src/orb/shaders/orb.vert.glsl.d.ts +1 -0
  47. package/dist/vite.config.d.ts +2 -0
  48. package/package.json +43 -0
@@ -0,0 +1,53 @@
1
+ import { LitElement } from 'lit';
2
+ import { OrbColors } from '../../core/orb';
3
+ export declare class FloatingCall extends LitElement {
4
+ static styles: import('lit').CSSResult;
5
+ private callManager;
6
+ private orbRenderer;
7
+ private audioAnalyzer;
8
+ private soundManager;
9
+ private orbContainerRef;
10
+ private animationId;
11
+ agentId: string;
12
+ voiceServiceUrl?: string;
13
+ private callStatus;
14
+ private microphoneEnabled;
15
+ buttonStartText: string;
16
+ buttonConnectingText: string;
17
+ position: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left' | 'static';
18
+ size: number;
19
+ theme: string;
20
+ themeMode: 'dark' | 'light' | 'auto';
21
+ orbColors: Partial<OrbColors>;
22
+ glowIntensity: number;
23
+ idleGlowMultiplier: number;
24
+ morphStrength: number;
25
+ noiseScale: number;
26
+ noiseSpeed: number;
27
+ fresnelPower: number;
28
+ rotationSpeed: number;
29
+ audioReactivity: number;
30
+ audioSmoothing: number;
31
+ idleMorphMultiplier: number;
32
+ colorContrast: number;
33
+ soundEnabled: boolean;
34
+ soundVolume: number;
35
+ connectedCallback(): void;
36
+ disconnectedCallback(): void;
37
+ firstUpdated(): void;
38
+ updated(changedProperties: Map<string | number | symbol, unknown>): void;
39
+ private applyTheme;
40
+ private initializeOrb;
41
+ private cleanupOrb;
42
+ private startIdleAnimation;
43
+ private startRealAudioLoop;
44
+ private handleAudioTrack;
45
+ private handleLocalAudioTrack;
46
+ private handleMicrophoneEnabled;
47
+ private handleMicrophoneDisabled;
48
+ private handleStatusChange;
49
+ private toggleCall;
50
+ private getButtonIcon;
51
+ private get buttonText();
52
+ render(): import('lit-html').TemplateResult<1>;
53
+ }
@@ -0,0 +1 @@
1
+ export * from './floating-call';
@@ -0,0 +1,10 @@
1
+ export * from './inline-call';
2
+ export * from './floating-call';
3
+ export * from './pill-call';
4
+ export * from '../lina';
5
+ export { darkPresets, lightPresets, getColorPreset, getPresetNames } from '../core/orb/colorPresets';
6
+ export type { OrbColors } from '../core/orb';
7
+ export { themes, darkThemes, lightThemes, getTheme, getThemeNames, applyTheme, detectSystemTheme, watchSystemTheme } from '../core/orb/themes';
8
+ export type { ThemeConfig, Theme } from '../core/orb';
9
+ export { SoundManager } from '../core/orb';
10
+ export type { SoundConfig } from '../core/orb';
@@ -0,0 +1 @@
1
+ export * from './inline-call';
@@ -0,0 +1,53 @@
1
+ import { LitElement } from 'lit';
2
+ import { OrbColors } from '../../core/orb';
3
+ export declare class InlineCall extends LitElement {
4
+ static styles: import('lit').CSSResult;
5
+ private callManager;
6
+ private orbRenderer;
7
+ private audioAnalyzer;
8
+ private soundManager;
9
+ private orbContainerRef;
10
+ private animationId;
11
+ agentId: string;
12
+ voiceServiceUrl?: string;
13
+ private callStatus;
14
+ private microphoneEnabled;
15
+ buttonStartText: string;
16
+ buttonConnectingText: string;
17
+ size: number;
18
+ containerPadding: number;
19
+ theme: string;
20
+ themeMode: 'dark' | 'light' | 'auto';
21
+ orbColors: Partial<OrbColors>;
22
+ glowIntensity: number;
23
+ idleGlowMultiplier: number;
24
+ morphStrength: number;
25
+ noiseScale: number;
26
+ noiseSpeed: number;
27
+ fresnelPower: number;
28
+ rotationSpeed: number;
29
+ audioReactivity: number;
30
+ audioSmoothing: number;
31
+ idleMorphMultiplier: number;
32
+ colorContrast: number;
33
+ soundEnabled: boolean;
34
+ soundVolume: number;
35
+ connectedCallback(): void;
36
+ disconnectedCallback(): void;
37
+ firstUpdated(): void;
38
+ updated(changedProperties: Map<string | number | symbol, unknown>): void;
39
+ private applyTheme;
40
+ private initializeOrb;
41
+ private cleanupOrb;
42
+ private startIdleAnimation;
43
+ private startRealAudioLoop;
44
+ private handleAudioTrack;
45
+ private handleLocalAudioTrack;
46
+ private handleMicrophoneEnabled;
47
+ private handleMicrophoneDisabled;
48
+ private handleStatusChange;
49
+ private toggleCall;
50
+ private getButtonIcon;
51
+ private get buttonText();
52
+ render(): import('lit-html').TemplateResult<1>;
53
+ }
@@ -0,0 +1,59 @@
1
+ import { LitElement } from 'lit';
2
+ import { HancAiWidgetConfig, WidgetMode } from '../orb/components';
3
+ type ColorPreset = 'indigo' | 'cyan' | 'emerald' | 'rose' | 'amber';
4
+ type ThemeMode = 'auto' | 'dark' | 'light';
5
+ export declare class HancAiOrbElement extends LitElement {
6
+ static styles: import('lit').CSSResult[];
7
+ agentId: string;
8
+ voiceServiceUrl?: string;
9
+ size: number;
10
+ mode: WidgetMode;
11
+ position: NonNullable<HancAiWidgetConfig['position']>;
12
+ buttonText?: string;
13
+ activeButtonText?: string;
14
+ connectingText?: string;
15
+ buttonStartText?: string;
16
+ buttonEndText?: string;
17
+ buttonConnectingText?: string;
18
+ enableSounds: boolean;
19
+ soundVolume: number;
20
+ colors?: string;
21
+ orbConfig?: string;
22
+ theme: ThemeMode;
23
+ colorPreset: ColorPreset;
24
+ private orbContainer?;
25
+ private currentState;
26
+ private widget;
27
+ private themeQuery;
28
+ connectedCallback(): void;
29
+ disconnectedCallback(): void;
30
+ firstUpdated(): void;
31
+ protected updated(changedProperties: Map<string | number | symbol, unknown>): void;
32
+ render(): import('lit-html').TemplateResult<1>;
33
+ /**
34
+ * Programmatically start a call
35
+ */
36
+ startCall(): Promise<void>;
37
+ /**
38
+ * Programmatically end the call
39
+ */
40
+ endCall(): Promise<void>;
41
+ private initializeWidget;
42
+ private destroyWidget;
43
+ private buildConfig;
44
+ private resolveColors;
45
+ private parseColors;
46
+ private parseOrbConfig;
47
+ private applyHostStyles;
48
+ private getButtonText;
49
+ private getActiveButtonText;
50
+ private getConnectingText;
51
+ private applyThemeToWidget;
52
+ private setupThemeListener;
53
+ private teardownThemeListener;
54
+ private handleThemeChange;
55
+ private getResolvedTheme;
56
+ }
57
+ export declare class HancAiOrb extends HancAiOrbElement {
58
+ }
59
+ export {};
@@ -0,0 +1 @@
1
+ export { PillCall } from './pill-call';
@@ -0,0 +1,53 @@
1
+ import { LitElement } from 'lit';
2
+ import { OrbColors } from '../../core/orb';
3
+ export declare class PillCall extends LitElement {
4
+ static styles: import('lit').CSSResult;
5
+ private callManager;
6
+ private orbRenderer;
7
+ private audioAnalyzer;
8
+ private soundManager;
9
+ private orbContainerRef;
10
+ private animationId;
11
+ agentId: string;
12
+ voiceServiceUrl?: string;
13
+ private callStatus;
14
+ private microphoneEnabled;
15
+ buttonStartText: string;
16
+ buttonConnectingText: string;
17
+ buttonEndText: string;
18
+ orbSize: number;
19
+ theme: string;
20
+ themeMode: 'dark' | 'light' | 'auto';
21
+ orbColors: Partial<OrbColors>;
22
+ glowIntensity: number;
23
+ idleGlowMultiplier: number;
24
+ morphStrength: number;
25
+ noiseScale: number;
26
+ noiseSpeed: number;
27
+ fresnelPower: number;
28
+ rotationSpeed: number;
29
+ audioReactivity: number;
30
+ audioSmoothing: number;
31
+ idleMorphMultiplier: number;
32
+ colorContrast: number;
33
+ soundEnabled: boolean;
34
+ soundVolume: number;
35
+ connectedCallback(): void;
36
+ disconnectedCallback(): void;
37
+ firstUpdated(): void;
38
+ updated(changedProperties: Map<string | number | symbol, unknown>): void;
39
+ private applyTheme;
40
+ private initializeOrb;
41
+ private cleanupOrb;
42
+ private startIdleAnimation;
43
+ private startRealAudioLoop;
44
+ private handleAudioTrack;
45
+ private handleLocalAudioTrack;
46
+ private handleMicrophoneEnabled;
47
+ private handleMicrophoneDisabled;
48
+ private handleStatusChange;
49
+ private toggleCall;
50
+ private getButtonIcon;
51
+ private get buttonText();
52
+ render(): import('lit-html').TemplateResult<1>;
53
+ }
@@ -0,0 +1,3 @@
1
+ export declare function getRelativeLuminance(color: string): number | null;
2
+ export declare function blendColors(base: string, target: string, ratio: number): string;
3
+ export declare function colorWithAlpha(color: string, alpha: number): string;
@@ -0,0 +1 @@
1
+ export declare const globalStyles: import('lit').CSSResult;
@@ -0,0 +1,74 @@
1
+ import { Room } from 'livekit-client';
2
+ type CallStatus = 'idle' | 'connecting' | 'connected' | 'agent-connected' | 'disconnecting' | 'disconnected' | 'error' | 'ringing';
3
+ interface MakeCallOptions {
4
+ agentId: string;
5
+ }
6
+ export interface LiveKitCallManagerEvents {
7
+ 'status-changed': CustomEvent<CallStatus>;
8
+ 'room-connected': CustomEvent<{
9
+ roomName: string;
10
+ identity: string;
11
+ }>;
12
+ 'agent-connected': CustomEvent<{
13
+ participant: string;
14
+ }>;
15
+ 'agent-disconnected': CustomEvent<{
16
+ participant: string;
17
+ }>;
18
+ 'participant-connected': CustomEvent<{
19
+ participant: string;
20
+ isAgent: boolean;
21
+ }>;
22
+ 'participant-disconnected': CustomEvent<{
23
+ participant: string;
24
+ isAgent: boolean;
25
+ }>;
26
+ 'audio-track-added': CustomEvent<{
27
+ participant: string;
28
+ element: HTMLMediaElement;
29
+ }>;
30
+ 'audio-track-removed': CustomEvent<{
31
+ participant: string;
32
+ }>;
33
+ 'audio-playback-status-changed': CustomEvent<{
34
+ canPlayback: boolean;
35
+ }>;
36
+ 'microphone-enabled': Event;
37
+ 'microphone-disabled': Event;
38
+ 'audio-enabled': Event;
39
+ 'call-ended': Event;
40
+ disconnected: Event;
41
+ error: CustomEvent<{
42
+ error: string | null;
43
+ }>;
44
+ }
45
+ export declare class LiveKitCallManager extends EventTarget {
46
+ private room;
47
+ private callStatus;
48
+ private isReady;
49
+ private error;
50
+ private _serviceUrl?;
51
+ private microphoneEnabled;
52
+ private connectedParticipants;
53
+ private userIdentity;
54
+ private roomName;
55
+ private audioPlaybackPrompt;
56
+ set serviceUrl(url: string | undefined);
57
+ get serviceUrl(): string;
58
+ get status(): CallStatus;
59
+ get ready(): boolean;
60
+ get currentError(): string | null;
61
+ get currentRoom(): Room | null;
62
+ get isMicrophoneEnabled(): boolean;
63
+ get participants(): string[];
64
+ get identity(): string;
65
+ get roomNameValue(): string;
66
+ get showAudioPrompt(): boolean;
67
+ private updateStatus;
68
+ makeCall({ agentId }: MakeCallOptions): Promise<void>;
69
+ private setupRoomEventListeners;
70
+ toggleMicrophone(): Promise<void>;
71
+ enableAudio(): Promise<void>;
72
+ hangUp(): Promise<void>;
73
+ }
74
+ export {};
@@ -0,0 +1,78 @@
1
+ export interface AudioData {
2
+ bass: number;
3
+ mid: number;
4
+ treble: number;
5
+ level: number;
6
+ waveform: Float32Array;
7
+ frequency: Uint8Array;
8
+ }
9
+ export interface AudioAnalyzerOptions {
10
+ fftSize?: number;
11
+ smoothingTimeConstant?: number;
12
+ minDecibels?: number;
13
+ maxDecibels?: number;
14
+ }
15
+ export declare class AudioAnalyzer {
16
+ private audioContext;
17
+ private analyser;
18
+ private source;
19
+ private localSource;
20
+ private mixer;
21
+ private frequencyData;
22
+ private waveformData;
23
+ private smoothedBass;
24
+ private smoothedMid;
25
+ private smoothedTreble;
26
+ private smoothedLevel;
27
+ private readonly smoothingFactor;
28
+ private readonly options;
29
+ constructor(options?: AudioAnalyzerOptions);
30
+ /**
31
+ * Initialize analyzer with a MediaStream (remote audio)
32
+ */
33
+ connectStream(stream: MediaStream): Promise<void>;
34
+ /**
35
+ * Connect local microphone stream
36
+ */
37
+ connectLocalStream(stream: MediaStream): Promise<void>;
38
+ /**
39
+ * Setup mixer and analyser nodes
40
+ */
41
+ private setupMixerAndAnalyser;
42
+ /**
43
+ * Connect to an audio element
44
+ */
45
+ connectAudioElement(element: HTMLAudioElement): Promise<void>;
46
+ /**
47
+ * Get current audio analysis data
48
+ */
49
+ getAudioData(): AudioData;
50
+ /**
51
+ * Calculate bass, mid, treble from frequency data
52
+ */
53
+ private calculateFrequencyBands;
54
+ /**
55
+ * Calculate overall audio level
56
+ */
57
+ private calculateOverallLevel;
58
+ /**
59
+ * Get peak level (useful for visualization spikes)
60
+ */
61
+ getPeakLevel(): number;
62
+ /**
63
+ * Check if audio context is active
64
+ */
65
+ isActive(): boolean;
66
+ /**
67
+ * Cleanup resources
68
+ */
69
+ disconnect(): void;
70
+ /**
71
+ * Get raw AudioContext for advanced usage
72
+ */
73
+ getAudioContext(): AudioContext | null;
74
+ /**
75
+ * Get raw AnalyserNode for advanced usage
76
+ */
77
+ getAnalyser(): AnalyserNode | null;
78
+ }
@@ -0,0 +1,86 @@
1
+ import { AudioData } from './AudioAnalyzer';
2
+ export interface OrbColors {
3
+ primary: string;
4
+ secondary: string;
5
+ accent: string;
6
+ glow: string;
7
+ atmosphere: string;
8
+ depth?: string;
9
+ highlight?: string;
10
+ }
11
+ export interface OrbConfig {
12
+ size?: number;
13
+ segments?: number;
14
+ colors?: Partial<OrbColors>;
15
+ morphStrength?: number;
16
+ noiseScale?: number;
17
+ noiseSpeed?: number;
18
+ glowIntensity?: number;
19
+ idleGlowMultiplier?: number;
20
+ fresnelPower?: number;
21
+ rotationSpeed?: number;
22
+ audioReactivity?: number;
23
+ audioSmoothing?: number;
24
+ idleMorphMultiplier?: number;
25
+ colorContrast?: number;
26
+ }
27
+ export declare class OrbRenderer {
28
+ private container;
29
+ private scene;
30
+ private camera;
31
+ private renderer;
32
+ private orb;
33
+ private glowMesh;
34
+ private orbMaterial;
35
+ private glowMaterial;
36
+ private config;
37
+ private animationId;
38
+ private clock;
39
+ private isActive;
40
+ private targetRotation;
41
+ private currentRotation;
42
+ private audioValues;
43
+ private readonly canvasPadding;
44
+ constructor(container: HTMLElement, config?: OrbConfig);
45
+ private createOrb;
46
+ /**
47
+ * Update audio data with smoothing
48
+ */
49
+ updateAudio(audioData: AudioData): void;
50
+ /**
51
+ * Set simulated audio values (for demo/testing)
52
+ */
53
+ setSimulatedAudio(bass: number, mid: number, treble: number, level: number): void;
54
+ /**
55
+ * Set active state
56
+ */
57
+ setActive(active: boolean): void;
58
+ /**
59
+ * Update colors
60
+ */
61
+ setColors(colors: Partial<OrbColors>): void;
62
+ /**
63
+ * Update glow intensity settings (useful for light/dark theme switching)
64
+ */
65
+ setGlowSettings(glowIntensity: number, idleGlowMultiplier: number): void;
66
+ /**
67
+ * Start animation loop
68
+ */
69
+ start(): void;
70
+ /**
71
+ * Stop animation loop
72
+ */
73
+ stop(): void;
74
+ private animate;
75
+ private handleResize;
76
+ private handleMouseMove;
77
+ private handleMouseLeave;
78
+ /**
79
+ * Get the canvas element
80
+ */
81
+ getCanvas(): HTMLCanvasElement;
82
+ /**
83
+ * Cleanup resources
84
+ */
85
+ destroy(): void;
86
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * SoundManager - Programmatic melodic sound generation for call events
3
+ * Uses Web Audio API for zero-dependency sound synthesis
4
+ */
5
+ export interface SoundConfig {
6
+ enabled: boolean;
7
+ volume: number;
8
+ }
9
+ export declare class SoundManager {
10
+ private audioContext;
11
+ private config;
12
+ constructor(config?: Partial<SoundConfig>);
13
+ /**
14
+ * Initialize audio context (must be called from user interaction)
15
+ */
16
+ private ensureContext;
17
+ /**
18
+ * Prewarm audio context on user interaction
19
+ * This helps avoid audio context suspension issues
20
+ */
21
+ prewarm(): Promise<void>;
22
+ /**
23
+ * Create an oscillator with envelope
24
+ */
25
+ private createTone;
26
+ /**
27
+ * Play pleasant notification sound for call start
28
+ * Two-tone ascending melody like messenger notifications
29
+ */
30
+ playCallStartSound(): Promise<void>;
31
+ /**
32
+ * Play gentle descending sound for call end
33
+ * Single soft tone
34
+ */
35
+ playCallEndSound(): Promise<void>;
36
+ /**
37
+ * Update configuration
38
+ */
39
+ setConfig(config: Partial<SoundConfig>): void;
40
+ /**
41
+ * Enable or disable sounds
42
+ */
43
+ setEnabled(enabled: boolean): void;
44
+ /**
45
+ * Set volume (0.0 - 1.0)
46
+ */
47
+ setVolume(volume: number): void;
48
+ /**
49
+ * Get current config
50
+ */
51
+ getConfig(): SoundConfig;
52
+ /**
53
+ * Check if sounds are enabled
54
+ */
55
+ isEnabled(): boolean;
56
+ /**
57
+ * Cleanup
58
+ */
59
+ destroy(): void;
60
+ }
@@ -0,0 +1,22 @@
1
+ import { OrbColors } from './OrbRenderer';
2
+ /**
3
+ * Dark theme color presets optimized for dark backgrounds
4
+ */
5
+ export declare const darkPresets: Record<string, OrbColors>;
6
+ /**
7
+ * Light theme color presets optimized for light backgrounds
8
+ */
9
+ export declare const lightPresets: Record<string, OrbColors>;
10
+ /**
11
+ * Get a color preset by name
12
+ * @param presetName - Name of the preset
13
+ * @param theme - 'dark' or 'light'
14
+ * @returns OrbColors object
15
+ */
16
+ export declare function getColorPreset(presetName: string, theme?: 'dark' | 'light'): OrbColors;
17
+ /**
18
+ * Get all available preset names for a theme
19
+ * @param theme - 'dark' or 'light'
20
+ * @returns Array of preset names
21
+ */
22
+ export declare function getPresetNames(theme?: 'dark' | 'light'): string[];
@@ -0,0 +1,4 @@
1
+ export declare const glowVertexShader = "\nvarying vec3 vNormal;\nvarying vec3 vPosition;\nvarying float vIntensity;\n\nvoid main() {\n vNormal = normalize(normalMatrix * normal);\n vPosition = (modelViewMatrix * vec4(position, 1.0)).xyz;\n\n // Scale up for glow halo\n vec3 pos = position * 1.3;\n\n // Pre-calculate view intensity for smooth falloff\n vec3 viewDir = normalize(-vPosition);\n vIntensity = pow(1.0 - abs(dot(viewDir, vNormal)), 1.5);\n\n gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);\n}\n";
2
+ export declare const glowFragmentShader = "\nuniform float uTime;\nuniform float uAudioLevel;\nuniform vec3 uGlowColor;\nuniform float uGlowIntensity;\nuniform float uPulseSpeed;\n\nvarying vec3 vNormal;\nvarying vec3 vPosition;\nvarying float vIntensity;\n\nvoid main() {\n // Pulsing effect\n float pulse = sin(uTime * uPulseSpeed) * 0.1 + 0.9;\n pulse += uAudioLevel * 0.4;\n\n // Smooth radial glow using pre-calculated intensity\n float glow = vIntensity * uGlowIntensity * pulse;\n\n // Very soft falloff for diffuse glow\n glow = pow(glow, 0.8);\n glow *= smoothstep(0.0, 0.3, vIntensity);\n\n // Color with audio reactivity\n vec3 glowColor = uGlowColor * (1.0 + uAudioLevel * 0.5);\n\n // Softer alpha for more diffuse appearance\n gl_FragColor = vec4(glowColor, glow * 0.4);\n}\n";
3
+ export declare const atmosphereVertexShader = "\nvarying vec3 vNormal;\nvarying vec3 vPosition;\n\nvoid main() {\n vNormal = normalize(normalMatrix * normal);\n vPosition = position;\n\n // Scale for outer atmosphere\n vec3 pos = position * 1.5;\n\n gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);\n}\n";
4
+ export declare const atmosphereFragmentShader = "\nuniform float uTime;\nuniform float uAudioLevel;\nuniform vec3 uAtmosphereColor;\nuniform float uAtmosphereIntensity;\n\nvarying vec3 vNormal;\nvarying vec3 vPosition;\n\nvoid main() {\n vec3 viewDirection = normalize(cameraPosition - vPosition);\n\n // Inverse fresnel for atmosphere (stronger at edges, fading to center)\n float intensity = pow(1.0 - max(dot(viewDirection, vNormal), 0.0), 3.0);\n\n // Audio pulsing\n float pulse = 1.0 + uAudioLevel * 0.4;\n\n // Breathing animation\n float breathing = sin(uTime * 0.5) * 0.1 + 0.9;\n\n float alpha = intensity * uAtmosphereIntensity * pulse * breathing;\n\n // Fade out at very edges\n alpha *= smoothstep(1.0, 0.3, intensity);\n\n vec3 color = uAtmosphereColor * (1.0 + uAudioLevel * 0.3);\n\n gl_FragColor = vec4(color, alpha * 0.4);\n}\n";
@@ -0,0 +1,12 @@
1
+ export { OrbRenderer } from './OrbRenderer';
2
+ export type { OrbConfig, OrbColors } from './OrbRenderer';
3
+ export { AudioAnalyzer } from './AudioAnalyzer';
4
+ export type { AudioData, AudioAnalyzerOptions } from './AudioAnalyzer';
5
+ export { SoundManager } from './SoundManager';
6
+ export type { SoundConfig } from './SoundManager';
7
+ export { darkPresets, lightPresets, getColorPreset, getPresetNames } from './colorPresets';
8
+ export { themes, darkThemes, lightThemes, getTheme, getThemeNames, applyTheme, detectSystemTheme, watchSystemTheme } from './themes';
9
+ export type { ThemeConfig, Theme } from './themes';
10
+ export { orbVertexShader } from './orb.vert.glsl';
11
+ export { orbFragmentShader } from './orb.frag.glsl';
12
+ export { glowVertexShader, glowFragmentShader, atmosphereVertexShader, atmosphereFragmentShader, } from './glow.glsl';
@@ -0,0 +1 @@
1
+ export declare const orbFragmentShader = "\nuniform float uTime;\nuniform float uAudioBass;\nuniform float uAudioMid;\nuniform float uAudioTreble;\nuniform float uAudioLevel;\nuniform vec3 uColorPrimary;\nuniform vec3 uColorSecondary;\nuniform vec3 uColorAccent;\nuniform vec3 uColorDepth;\nuniform vec3 uColorHighlight;\nuniform float uFresnelPower;\nuniform float uGlowIntensity;\nuniform float uColorContrast;\n\nvarying vec3 vNormal;\nvarying vec3 vPosition;\nvarying vec2 vUv;\nvarying float vDisplacement;\nvarying float vElevation;\n\n// Simplex noise for fragment effects\nvec3 mod289(vec3 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\n\nvec4 mod289(vec4 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\n\nvec4 permute(vec4 x) {\n return mod289(((x * 34.0) + 1.0) * x);\n}\n\nvec4 taylorInvSqrt(vec4 r) {\n return 1.79284291400159 - 0.85373472095314 * r;\n}\n\nfloat snoise(vec3 v) {\n const vec2 C = vec2(1.0 / 6.0, 1.0 / 3.0);\n const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);\n\n vec3 i = floor(v + dot(v, C.yyy));\n vec3 x0 = v - i + dot(i, C.xxx);\n\n vec3 g = step(x0.yzx, x0.xyz);\n vec3 l = 1.0 - g;\n vec3 i1 = min(g.xyz, l.zxy);\n vec3 i2 = max(g.xyz, l.zxy);\n\n vec3 x1 = x0 - i1 + C.xxx;\n vec3 x2 = x0 - i2 + C.yyy;\n vec3 x3 = x0 - D.yyy;\n\n i = mod289(i);\n vec4 p = permute(permute(permute(\n i.z + vec4(0.0, i1.z, i2.z, 1.0))\n + i.y + vec4(0.0, i1.y, i2.y, 1.0))\n + i.x + vec4(0.0, i1.x, i2.x, 1.0));\n\n float n_ = 1.0 / 7.0;\n vec3 ns = n_ * D.wyz - D.xzx;\n\n vec4 j = p - 49.0 * floor(p * ns.z * ns.z);\n\n vec4 x_ = floor(j * ns.z);\n vec4 y_ = floor(j - 7.0 * x_);\n\n vec4 x = x_ * ns.x + ns.yyyy;\n vec4 y = y_ * ns.x + ns.yyyy;\n vec4 h = 1.0 - abs(x) - abs(y);\n\n vec4 b0 = vec4(x.xy, y.xy);\n vec4 b1 = vec4(x.zw, y.zw);\n\n vec4 s0 = floor(b0) * 2.0 + 1.0;\n vec4 s1 = floor(b1) * 2.0 + 1.0;\n vec4 sh = -step(h, vec4(0.0));\n\n vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;\n vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww;\n\n vec3 p0 = vec3(a0.xy, h.x);\n vec3 p1 = vec3(a0.zw, h.y);\n vec3 p2 = vec3(a1.xy, h.z);\n vec3 p3 = vec3(a1.zw, h.w);\n\n vec4 norm = taylorInvSqrt(vec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));\n p0 *= norm.x;\n p1 *= norm.y;\n p2 *= norm.z;\n p3 *= norm.w;\n\n vec4 m = max(0.6 - vec4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0);\n m = m * m;\n return 42.0 * dot(m * m, vec4(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3)));\n}\n\nvoid main() {\n // View direction for fresnel\n vec3 viewDirection = normalize(cameraPosition - vPosition);\n\n // Fresnel effect - edge glow\n float fresnel = pow(1.0 - max(dot(viewDirection, vNormal), 0.0), uFresnelPower);\n\n // Dynamic color mixing based on audio - using multiple noise layers for smoke effect\n float colorMix = snoise(vPosition * 2.0 + uTime * 0.5) * 0.5 + 0.5;\n colorMix += vDisplacement * 2.0;\n\n // Secondary noise layer for more complex smoke patterns\n float smokeLayer = snoise(vPosition * 1.2 - uTime * 0.3) * 0.5 + 0.5;\n colorMix = colorMix * 0.6 + smokeLayer * 0.4;\n\n // Apply contrast to make smoke patterns more visible\n colorMix = (colorMix - 0.5) * uColorContrast + 0.5;\n colorMix = clamp(colorMix, 0.0, 1.0);\n\n // Audio-reactive color shifts\n float audioInfluence = uAudioBass * 0.4 + uAudioMid * 0.35 + uAudioTreble * 0.25;\n\n // 4-color gradient for volumetric smoke effect:\n // depth (0.0) -> primary (0.33) -> secondary (0.66) -> highlight (1.0)\n vec3 gradientColor;\n if (colorMix < 0.33) {\n // Depth to Primary\n float t = colorMix / 0.33;\n gradientColor = mix(uColorDepth, uColorPrimary, t);\n } else if (colorMix < 0.66) {\n // Primary to Secondary\n float t = (colorMix - 0.33) / 0.33;\n gradientColor = mix(uColorPrimary, uColorSecondary, t);\n } else {\n // Secondary to Highlight\n float t = (colorMix - 0.66) / 0.34;\n gradientColor = mix(uColorSecondary, uColorHighlight, t);\n }\n\n // Add accent color based on audio peaks\n gradientColor = mix(gradientColor, uColorAccent, audioInfluence * 0.5);\n\n // Iridescent effect\n float iridescence = snoise(vPosition * 3.0 + uTime * 0.3) * 0.15;\n vec3 iridescentShift = vec3(\n sin(iridescence * 6.28 + 0.0) * 0.1,\n sin(iridescence * 6.28 + 2.09) * 0.1,\n sin(iridescence * 6.28 + 4.18) * 0.1\n );\n gradientColor += iridescentShift * (0.5 + audioInfluence);\n\n // Inner glow effect\n float innerGlow = pow(1.0 - fresnel, 3.0) * 0.3;\n vec3 glowColor = uColorAccent * innerGlow * (1.0 + uAudioLevel * 2.0);\n\n // Edge glow (fresnel)\n vec3 edgeGlow = mix(uColorSecondary, uColorAccent, audioInfluence) * fresnel * uGlowIntensity;\n\n // Pulsing highlights\n float pulse = sin(uTime * 2.0 + vPosition.y * 5.0) * 0.5 + 0.5;\n pulse *= uAudioMid;\n vec3 pulseHighlight = uColorAccent * pulse * 0.2;\n\n // Subsurface scattering simulation\n float sss = pow(max(dot(viewDirection, -vNormal), 0.0), 2.0) * 0.15;\n vec3 sssColor = uColorPrimary * sss * (1.0 + uAudioBass);\n\n // Combine all effects\n vec3 finalColor = gradientColor + edgeGlow + glowColor + pulseHighlight + sssColor;\n\n // Add depth variation\n float depthFade = smoothstep(-1.0, 1.0, vPosition.z);\n finalColor *= 0.8 + depthFade * 0.2;\n\n // Tone mapping and gamma correction\n finalColor = finalColor / (finalColor + vec3(1.0));\n finalColor = pow(finalColor, vec3(1.0 / 2.2));\n\n // Alpha based on fresnel for soft edges\n float alpha = 0.9 + fresnel * 0.1;\n\n gl_FragColor = vec4(finalColor, alpha);\n}\n";
@@ -0,0 +1 @@
1
+ export declare const orbVertexShader = "\nuniform float uTime;\nuniform float uAudioBass;\nuniform float uAudioMid;\nuniform float uAudioTreble;\nuniform float uAudioLevel;\nuniform float uMorphStrength;\nuniform float uNoiseScale;\nuniform float uNoiseSpeed;\nuniform float uAudioReactivity;\n\nvarying vec3 vNormal;\nvarying vec3 vPosition;\nvarying vec2 vUv;\nvarying float vDisplacement;\nvarying float vElevation;\n\n// Simplex 3D noise\nvec4 permute(vec4 x) {\n return mod(((x * 34.0) + 1.0) * x, 289.0);\n}\n\nvec4 taylorInvSqrt(vec4 r) {\n return 1.79284291400159 - 0.85373472095314 * r;\n}\n\nfloat snoise(vec3 v) {\n const vec2 C = vec2(1.0 / 6.0, 1.0 / 3.0);\n const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);\n\n vec3 i = floor(v + dot(v, C.yyy));\n vec3 x0 = v - i + dot(i, C.xxx);\n\n vec3 g = step(x0.yzx, x0.xyz);\n vec3 l = 1.0 - g;\n vec3 i1 = min(g.xyz, l.zxy);\n vec3 i2 = max(g.xyz, l.zxy);\n\n vec3 x1 = x0 - i1 + C.xxx;\n vec3 x2 = x0 - i2 + C.yyy;\n vec3 x3 = x0 - D.yyy;\n\n i = mod(i, 289.0);\n vec4 p = permute(permute(permute(\n i.z + vec4(0.0, i1.z, i2.z, 1.0))\n + i.y + vec4(0.0, i1.y, i2.y, 1.0))\n + i.x + vec4(0.0, i1.x, i2.x, 1.0));\n\n float n_ = 1.0 / 7.0;\n vec3 ns = n_ * D.wyz - D.xzx;\n\n vec4 j = p - 49.0 * floor(p * ns.z * ns.z);\n\n vec4 x_ = floor(j * ns.z);\n vec4 y_ = floor(j - 7.0 * x_);\n\n vec4 x = x_ * ns.x + ns.yyyy;\n vec4 y = y_ * ns.x + ns.yyyy;\n vec4 h = 1.0 - abs(x) - abs(y);\n\n vec4 b0 = vec4(x.xy, y.xy);\n vec4 b1 = vec4(x.zw, y.zw);\n\n vec4 s0 = floor(b0) * 2.0 + 1.0;\n vec4 s1 = floor(b1) * 2.0 + 1.0;\n vec4 sh = -step(h, vec4(0.0));\n\n vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;\n vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww;\n\n vec3 p0 = vec3(a0.xy, h.x);\n vec3 p1 = vec3(a0.zw, h.y);\n vec3 p2 = vec3(a1.xy, h.z);\n vec3 p3 = vec3(a1.zw, h.w);\n\n vec4 norm = taylorInvSqrt(vec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));\n p0 *= norm.x;\n p1 *= norm.y;\n p2 *= norm.z;\n p3 *= norm.w;\n\n vec4 m = max(0.6 - vec4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0);\n m = m * m;\n return 42.0 * dot(m * m, vec4(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3)));\n}\n\n// Fractal Brownian Motion\nfloat fbm(vec3 p, int octaves) {\n float value = 0.0;\n float amplitude = 0.5;\n float frequency = 1.0;\n\n for (int i = 0; i < 6; i++) {\n if (i >= octaves) break;\n value += amplitude * snoise(p * frequency);\n amplitude *= 0.5;\n frequency *= 2.0;\n }\n\n return value;\n}\n\nvoid main() {\n vUv = uv;\n vNormal = normalize(normalMatrix * normal);\n\n vec3 pos = position;\n\n // Time-based animation\n float t = uTime * uNoiseSpeed;\n\n // Multi-layered noise displacement\n vec3 noisePos = pos * uNoiseScale + t * 0.3;\n\n // Base organic movement\n float baseNoise = fbm(noisePos, 4) * 0.15;\n\n // Audio-reactive displacement layers (multiplied by audioReactivity)\n float bassDisplacement = snoise(noisePos * 0.8 + t * 0.5) * uAudioBass * 0.25 * uAudioReactivity;\n float midDisplacement = snoise(noisePos * 1.5 + t * 0.8) * uAudioMid * 0.18 * uAudioReactivity;\n float trebleDisplacement = snoise(noisePos * 3.0 + t * 1.2) * uAudioTreble * 0.1 * uAudioReactivity;\n\n // Combine all displacement\n float totalDisplacement = baseNoise + bassDisplacement + midDisplacement + trebleDisplacement;\n\n // Apply morphing strength\n totalDisplacement *= uMorphStrength;\n\n // Add breathing effect\n float breathing = sin(uTime * 0.8) * 0.02 * (1.0 + uAudioLevel * 0.5);\n totalDisplacement += breathing;\n\n // Apply displacement along normal\n pos += normal * totalDisplacement;\n\n vDisplacement = totalDisplacement;\n vElevation = pos.y;\n vPosition = pos;\n\n gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);\n}\n";
@@ -0,0 +1,53 @@
1
+ import { OrbColors } from './OrbRenderer';
2
+ /**
3
+ * Complete theme configuration including colors and glow settings
4
+ */
5
+ export interface ThemeConfig {
6
+ colors: OrbColors;
7
+ glowIntensity: number;
8
+ idleGlowMultiplier: number;
9
+ }
10
+ /**
11
+ * Theme with both dark and light variants
12
+ */
13
+ export interface Theme {
14
+ dark: ThemeConfig;
15
+ light: ThemeConfig;
16
+ }
17
+ /**
18
+ * All available themes with dark and light variants
19
+ */
20
+ export declare const themes: Record<string, Theme>;
21
+ export declare const darkThemes: Record<string, ThemeConfig>;
22
+ export declare const lightThemes: Record<string, ThemeConfig>;
23
+ /**
24
+ * Detect system color scheme preference
25
+ * @returns 'dark' or 'light' based on system preference
26
+ */
27
+ export declare function detectSystemTheme(): 'dark' | 'light';
28
+ /**
29
+ * Get a complete theme configuration by name
30
+ * @param themeName - Name of the theme (e.g., 'emerald', 'rose')
31
+ * @param mode - 'dark', 'light', or 'auto' (auto detects system preference)
32
+ * @returns ThemeConfig object with colors and glow settings
33
+ */
34
+ export declare function getTheme(themeName: string, mode?: 'dark' | 'light' | 'auto'): ThemeConfig;
35
+ /**
36
+ * Get all available theme names
37
+ * @returns Array of theme names
38
+ */
39
+ export declare function getThemeNames(): string[];
40
+ /**
41
+ * Apply a theme to a widget element
42
+ * @param element - The widget element
43
+ * @param themeName - Name of the theme
44
+ * @param mode - 'dark', 'light', or 'auto'
45
+ */
46
+ export declare function applyTheme(element: any, themeName: string, mode?: 'dark' | 'light' | 'auto'): void;
47
+ /**
48
+ * Watch for system theme changes and update widget
49
+ * @param element - The widget element
50
+ * @param themeName - Name of the theme
51
+ * @returns Cleanup function to stop watching
52
+ */
53
+ export declare function watchSystemTheme(element: any, themeName: string): () => void;