@w0nna_dev/lina-widget 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8746,7 +8746,7 @@ function Ky(i) {
8746
8746
  value: i.value
8747
8747
  });
8748
8748
  }
8749
- class mw extends hi.EventEmitter {
8749
+ class gw extends hi.EventEmitter {
8750
8750
  constructor() {
8751
8751
  let e = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
8752
8752
  super(), this.onKeyRatcheted = (t, n, s) => {
@@ -17878,7 +17878,7 @@ class h_ extends os {
17878
17878
  });
17879
17879
  }
17880
17880
  }
17881
- class gw extends hi.EventEmitter {
17881
+ class vw extends hi.EventEmitter {
17882
17882
  constructor(e, t) {
17883
17883
  let n = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {};
17884
17884
  super(), this.options = {}, this.checkResults = /* @__PURE__ */ new Map(), this.url = e, this.token = t, this.options = n;
@@ -39694,7 +39694,7 @@ class bu {
39694
39694
  }
39695
39695
  }
39696
39696
  const JM = "/sounds/pop-connect.mp3", ZM = "/sounds/pop-disconnect.mp3";
39697
- class _u {
39697
+ let _u = class {
39698
39698
  constructor(e = {}) {
39699
39699
  this.audioContext = null, this.connectAudio = null, this.disconnectAudio = null, this.config = {
39700
39700
  enabled: !0,
@@ -39844,7 +39844,7 @@ class _u {
39844
39844
  destroy() {
39845
39845
  this.audioContext && (this.audioContext.close(), this.audioContext = null), this.connectAudio && (this.connectAudio.pause(), this.connectAudio.src = "", this.connectAudio = null), this.disconnectAudio && (this.disconnectAudio.pause(), this.disconnectAudio.src = "", this.disconnectAudio = null);
39846
39846
  }
39847
- }
39847
+ };
39848
39848
  const Si = {
39849
39849
  default: {
39850
39850
  primary: "#6366f1",
@@ -39991,11 +39991,11 @@ const Si = {
39991
39991
  // Light pink
39992
39992
  }
39993
39993
  };
39994
- function vw(i, e = "dark") {
39994
+ function bw(i, e = "dark") {
39995
39995
  const t = e === "dark" ? Si : xi;
39996
39996
  return t[i] || t[Object.keys(t)[0]];
39997
39997
  }
39998
- function yw(i = "dark") {
39998
+ function _w(i = "dark") {
39999
39999
  return Object.keys(i === "dark" ? Si : xi);
40000
40000
  }
40001
40001
  const da = {
@@ -40083,9 +40083,9 @@ const da = {
40083
40083
  idleGlowMultiplier: 1.2
40084
40084
  }
40085
40085
  }
40086
- }, bw = Object.fromEntries(
40086
+ }, Sw = Object.fromEntries(
40087
40087
  Object.entries(da).map(([i, e]) => [i, e.dark])
40088
- ), _w = Object.fromEntries(
40088
+ ), xw = Object.fromEntries(
40089
40089
  Object.entries(da).map(([i, e]) => [i, e.light])
40090
40090
  );
40091
40091
  function QM() {
@@ -40095,14 +40095,14 @@ function Jo(i, e = "auto") {
40095
40095
  const t = da[i] || da.default, n = e === "auto" ? QM() : e;
40096
40096
  return t[n];
40097
40097
  }
40098
- function Sw() {
40098
+ function Tw() {
40099
40099
  return Object.keys(da);
40100
40100
  }
40101
40101
  function ew(i, e, t = "auto") {
40102
40102
  const n = Jo(e, t);
40103
40103
  i.orbColors = n.colors, i.glowIntensity = n.glowIntensity, i.idleGlowMultiplier = n.idleGlowMultiplier;
40104
40104
  }
40105
- function xw(i, e) {
40105
+ function Cw(i, e) {
40106
40106
  if (typeof window > "u")
40107
40107
  return () => {
40108
40108
  };
@@ -42211,14 +42211,172 @@ class cw {
42211
42211
  this.pulseRings = [], this.particles && (this.particles.geometry.dispose(), this.particles.material.dispose()), this.renderer.dispose(), this.renderer.domElement.parentNode && this.renderer.domElement.parentNode.removeChild(this.renderer.domElement);
42212
42212
  }
42213
42213
  }
42214
- var lw = Object.defineProperty, dw = Object.getOwnPropertyDescriptor, jt = (i, e, t, n) => {
42215
- for (var s = n > 1 ? void 0 : n ? dw(e, t) : e, r = i.length - 1, o; r >= 0; r--)
42214
+ class lw {
42215
+ constructor(e = {}) {
42216
+ this.audioContext = null, this.config = {
42217
+ enabled: !0,
42218
+ volume: 0.3,
42219
+ ...e
42220
+ };
42221
+ }
42222
+ /**
42223
+ * Initialize audio context (must be called from user interaction)
42224
+ */
42225
+ async ensureContext() {
42226
+ if (!this.config.enabled) return null;
42227
+ if (!this.audioContext)
42228
+ try {
42229
+ this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
42230
+ } catch {
42231
+ return console.warn("Web Audio API not supported"), null;
42232
+ }
42233
+ return this.audioContext.state === "suspended" && await this.audioContext.resume(), this.audioContext;
42234
+ }
42235
+ /**
42236
+ * Create an oscillator with envelope
42237
+ */
42238
+ createTone(e, t, n, s, r = "sine") {
42239
+ const o = e.createOscillator(), a = e.createGain();
42240
+ o.type = r, o.frequency.setValueAtTime(t, n);
42241
+ const c = 0.05, l = 0.1, d = 0.7, u = 0.3;
42242
+ return a.gain.setValueAtTime(0, n), a.gain.linearRampToValueAtTime(this.config.volume, n + c), a.gain.linearRampToValueAtTime(this.config.volume * d, n + c + l), a.gain.setValueAtTime(this.config.volume * d, n + s - u), a.gain.linearRampToValueAtTime(0, n + s), o.connect(a), { oscillator: o, gain: a };
42243
+ }
42244
+ /**
42245
+ * Play ascending melodic sound for call start
42246
+ * C4 → E4 → G4 (C major chord arpeggio)
42247
+ */
42248
+ async playCallStartSound() {
42249
+ const e = await this.ensureContext();
42250
+ if (!e || typeof e.createGain != "function") return;
42251
+ const t = e.currentTime, n = e.createGain();
42252
+ n.gain.setValueAtTime(1, t), n.connect(e.destination);
42253
+ const s = [
42254
+ { freq: 261.63, start: 0, duration: 0.5 },
42255
+ // C4
42256
+ { freq: 329.63, start: 0.15, duration: 0.5 },
42257
+ // E4
42258
+ { freq: 392, start: 0.3, duration: 0.6 },
42259
+ // G4
42260
+ { freq: 523.25, start: 0.5, duration: 0.8 }
42261
+ // C5 (octave up)
42262
+ ], r = [];
42263
+ s.forEach((o) => {
42264
+ const { oscillator: a, gain: c } = this.createTone(
42265
+ e,
42266
+ o.freq,
42267
+ t + o.start,
42268
+ o.duration,
42269
+ "sine"
42270
+ );
42271
+ c.connect(n), a.start(t + o.start), a.stop(t + o.start + o.duration), r.push(a);
42272
+ const { oscillator: l, gain: d } = this.createTone(
42273
+ e,
42274
+ o.freq * 2,
42275
+ // Octave up
42276
+ t + o.start,
42277
+ o.duration,
42278
+ "triangle"
42279
+ );
42280
+ d.gain.setValueAtTime(d.gain.value * 0.3, t), d.connect(n), l.start(t + o.start), l.stop(t + o.start + o.duration), r.push(l);
42281
+ }), setTimeout(() => {
42282
+ r.forEach((o) => {
42283
+ try {
42284
+ o.disconnect();
42285
+ } catch {
42286
+ }
42287
+ });
42288
+ }, 2e3);
42289
+ }
42290
+ /**
42291
+ * Play descending melodic sound for call end
42292
+ * G4 → E4 → C4 (descending C major arpeggio)
42293
+ */
42294
+ async playCallEndSound() {
42295
+ const e = await this.ensureContext();
42296
+ if (!e || typeof e.createGain != "function") return;
42297
+ const t = e.currentTime, n = e.createGain();
42298
+ n.gain.setValueAtTime(1, t), n.connect(e.destination);
42299
+ const s = [
42300
+ { freq: 523.25, start: 0, duration: 0.4 },
42301
+ // C5
42302
+ { freq: 392, start: 0.12, duration: 0.4 },
42303
+ // G4
42304
+ { freq: 329.63, start: 0.24, duration: 0.5 },
42305
+ // E4
42306
+ { freq: 261.63, start: 0.4, duration: 0.7 }
42307
+ // C4
42308
+ ], r = [];
42309
+ s.forEach((o) => {
42310
+ const { oscillator: a, gain: c } = this.createTone(
42311
+ e,
42312
+ o.freq,
42313
+ t + o.start,
42314
+ o.duration,
42315
+ "sine"
42316
+ );
42317
+ c.connect(n), a.start(t + o.start), a.stop(t + o.start + o.duration), r.push(a);
42318
+ const { oscillator: l, gain: d } = this.createTone(
42319
+ e,
42320
+ o.freq * 2,
42321
+ t + o.start,
42322
+ o.duration,
42323
+ "triangle"
42324
+ );
42325
+ d.gain.setValueAtTime(d.gain.value * 0.25, t), d.connect(n), l.start(t + o.start), l.stop(t + o.start + o.duration), r.push(l);
42326
+ }), setTimeout(() => {
42327
+ r.forEach((o) => {
42328
+ try {
42329
+ o.disconnect();
42330
+ } catch {
42331
+ }
42332
+ });
42333
+ }, 1500);
42334
+ }
42335
+ /**
42336
+ * Update configuration
42337
+ */
42338
+ setConfig(e) {
42339
+ this.config = { ...this.config, ...e };
42340
+ }
42341
+ /**
42342
+ * Enable or disable sounds
42343
+ */
42344
+ setEnabled(e) {
42345
+ this.config.enabled = e;
42346
+ }
42347
+ /**
42348
+ * Set volume (0.0 - 1.0)
42349
+ */
42350
+ setVolume(e) {
42351
+ this.config.volume = Math.max(0, Math.min(1, e));
42352
+ }
42353
+ /**
42354
+ * Get current config
42355
+ */
42356
+ getConfig() {
42357
+ return { ...this.config };
42358
+ }
42359
+ /**
42360
+ * Check if sounds are enabled
42361
+ */
42362
+ isEnabled() {
42363
+ return this.config.enabled;
42364
+ }
42365
+ /**
42366
+ * Cleanup
42367
+ */
42368
+ destroy() {
42369
+ this.audioContext && (this.audioContext.close(), this.audioContext = null);
42370
+ }
42371
+ }
42372
+ var dw = Object.defineProperty, uw = Object.getOwnPropertyDescriptor, jt = (i, e, t, n) => {
42373
+ for (var s = n > 1 ? void 0 : n ? uw(e, t) : e, r = i.length - 1, o; r >= 0; r--)
42216
42374
  (o = i[r]) && (s = (n ? o(e, t, s) : o(s)) || s);
42217
- return n && s && lw(e, t, s), s;
42375
+ return n && s && dw(e, t, s), s;
42218
42376
  };
42219
42377
  let Ft = class extends es {
42220
42378
  constructor() {
42221
- super(...arguments), this.orbRenderer = null, this.orbContainerRef = No(), this.audioSimPhase = 0, this.animationId = null, this.callManager = null, this.size = 300, this.headerLogo = "HANC.ai", this.headerTitle = "Lina-Voice AI", this.showBranding = !0, this.version = "v1.1.2", this.agentId = "", this.voiceServiceUrl = "", this.btnStartText = "Start", this.btnEndText = "End", this.colors = {}, this.brandingLogoColor = "rgba(255, 255, 255, 0.9)", this.brandingTitleColor = "rgba(255, 255, 255, 0.6)", this.brandingDividerColor = "rgba(255, 255, 255, 0.3)", this.versionColor = "rgba(255, 255, 255, 0.3)", this.buttonBackground = "linear-gradient(135deg, rgba(139, 92, 246, 0.95) 0%, rgba(124, 58, 237, 0.95) 100%)", this.buttonTextColor = "rgba(255, 255, 255, 0.95)", this.currentState = "idle", this.callStatus = "idle", this.isLoading = !0, this._hasMicPermission = null, this._localAudioContext = null, this._localAudioAnalyser = null, this._localAudioMonitorId = null, this._agentAudioContext = null, this._agentAudioAnalyser = null, this._agentAudioMonitorId = null, this._agentIsSpeaking = !1, this._interruptionTimeout = null, this._lastInterruptionTime = 0, this.handleCallClick = async () => {
42379
+ super(...arguments), this.orbRenderer = null, this.orbContainerRef = No(), this.audioSimPhase = 0, this.animationId = null, this.callManager = null, this.soundManager = new lw({ enabled: !0, volume: 0.4 }), this.size = 300, this.headerLogo = "HANC.ai", this.headerTitle = "Lina-Voice AI", this.showBranding = !0, this.version = "v1.1.2", this.agentId = "", this.voiceServiceUrl = "", this.btnStartText = "Start", this.btnEndText = "End", this.colors = {}, this.brandingLogoColor = "rgba(255, 255, 255, 0.9)", this.brandingTitleColor = "rgba(255, 255, 255, 0.6)", this.brandingDividerColor = "rgba(255, 255, 255, 0.3)", this.versionColor = "rgba(255, 255, 255, 0.3)", this.buttonBackground = "linear-gradient(135deg, rgba(139, 92, 246, 0.95) 0%, rgba(124, 58, 237, 0.95) 100%)", this.buttonTextColor = "rgba(255, 255, 255, 0.95)", this.currentState = "idle", this.callStatus = "idle", this.isLoading = !0, this._hasMicPermission = null, this._localAudioContext = null, this._localAudioAnalyser = null, this._localAudioMonitorId = null, this._agentAudioContext = null, this._agentAudioAnalyser = null, this._agentAudioMonitorId = null, this._agentIsSpeaking = !1, this._interruptionTimeout = null, this._lastInterruptionTime = 0, this.handleCallClick = async () => {
42222
42380
  if (this.callStatus === "mic-denied")
42223
42381
  try {
42224
42382
  (await navigator.mediaDevices.getUserMedia({ audio: !0 })).getTracks().forEach((e) => e.stop()), this._hasMicPermission = !0, this.callStatus = "idle";
@@ -42364,6 +42522,9 @@ let Ft = class extends es {
42364
42522
  case "agent_state":
42365
42523
  (n = i.payload) != null && n.state && (this.setState(i.payload.state), this._agentIsSpeaking = i.payload.state === "speaking");
42366
42524
  break;
42525
+ case "end_call":
42526
+ console.log("[LinaWidget] Agent requested to end call"), this.endCall();
42527
+ break;
42367
42528
  }
42368
42529
  }
42369
42530
  /**
@@ -42384,13 +42545,13 @@ let Ft = class extends es {
42384
42545
  break;
42385
42546
  case "connected":
42386
42547
  case "agent-connected":
42387
- this.callStatus = "active", this.currentState = "speaking", (t = this.orbRenderer) == null || t.setState("speaking"), this.startActiveAnimation();
42548
+ this.callStatus = "active", this.currentState = "speaking", (t = this.orbRenderer) == null || t.setState("speaking"), this.startActiveAnimation(), this.soundManager.playCallStartSound();
42388
42549
  break;
42389
42550
  case "disconnecting":
42390
42551
  this.callStatus = "ending";
42391
42552
  break;
42392
42553
  case "disconnected":
42393
- this.callStatus = "idle", this.currentState = "idle", (n = this.orbRenderer) == null || n.setState("idle"), this.startIdleAnimation();
42554
+ this.callStatus = "idle", this.currentState = "idle", (n = this.orbRenderer) == null || n.setState("idle"), this.startIdleAnimation(), this.soundManager.playCallEndSound();
42394
42555
  break;
42395
42556
  case "error":
42396
42557
  this.callStatus = "error", this.currentState = "idle", (s = this.orbRenderer) == null || s.setState("idle");
@@ -42398,8 +42559,8 @@ let Ft = class extends es {
42398
42559
  }
42399
42560
  }
42400
42561
  cleanup() {
42401
- var i, e;
42402
- this.animationId !== null && (cancelAnimationFrame(this.animationId), this.animationId = null), this.stopLocalAudioMonitoring(), this.stopAgentAudioMonitoring(), this._interruptionTimeout && (clearTimeout(this._interruptionTimeout), this._interruptionTimeout = null), (i = this.callManager) == null || i.hangUp(), (e = this.orbRenderer) == null || e.destroy(), this.orbRenderer = null;
42562
+ var i, e, t;
42563
+ this.animationId !== null && (cancelAnimationFrame(this.animationId), this.animationId = null), this.stopLocalAudioMonitoring(), this.stopAgentAudioMonitoring(), this._interruptionTimeout && (clearTimeout(this._interruptionTimeout), this._interruptionTimeout = null), (i = this.callManager) == null || i.hangUp(), (e = this.orbRenderer) == null || e.destroy(), this.orbRenderer = null, (t = this.soundManager) == null || t.destroy();
42403
42564
  }
42404
42565
  startIdleAnimation() {
42405
42566
  this.animationId !== null && cancelAnimationFrame(this.animationId);
@@ -42471,7 +42632,7 @@ let Ft = class extends es {
42471
42632
  }, 3e3);
42472
42633
  }
42473
42634
  } else
42474
- this.callStatus = "connecting", this.currentState = "listening", (t = this.orbRenderer) == null || t.setState("listening"), await new Promise((s) => setTimeout(s, 1500)), this.callStatus = "active", this.currentState = "speaking", (n = this.orbRenderer) == null || n.setState("speaking"), this.startActiveAnimation(), this.dispatchEvent(new CustomEvent("call-start", {
42635
+ this.callStatus = "connecting", this.currentState = "listening", (t = this.orbRenderer) == null || t.setState("listening"), await new Promise((s) => setTimeout(s, 1500)), this.callStatus = "active", this.currentState = "speaking", (n = this.orbRenderer) == null || n.setState("speaking"), this.startActiveAnimation(), this.soundManager.playCallStartSound(), this.dispatchEvent(new CustomEvent("call-start", {
42475
42636
  detail: { agentId: "demo", timestamp: Date.now() },
42476
42637
  bubbles: !0,
42477
42638
  composed: !0
@@ -42482,7 +42643,7 @@ let Ft = class extends es {
42482
42643
  */
42483
42644
  async endCall() {
42484
42645
  var i;
42485
- this.callStatus = "ending", this.callManager && await this.callManager.hangUp(), this.callStatus = "idle", this.currentState = "idle", (i = this.orbRenderer) == null || i.setState("idle"), this.startIdleAnimation(), this.dispatchEvent(new CustomEvent("call-end", {
42646
+ this.callStatus = "ending", this.callManager ? await this.callManager.hangUp() : (this.soundManager.playCallEndSound(), this.callStatus = "idle", this.currentState = "idle", (i = this.orbRenderer) == null || i.setState("idle"), this.startIdleAnimation()), this.dispatchEvent(new CustomEvent("call-end", {
42486
42647
  detail: { timestamp: Date.now() },
42487
42648
  bubbles: !0,
42488
42649
  composed: !0
@@ -42893,14 +43054,14 @@ export {
42893
43054
  _u as SoundManager,
42894
43055
  ew as applyTheme,
42895
43056
  Si as darkPresets,
42896
- bw as darkThemes,
43057
+ Sw as darkThemes,
42897
43058
  QM as detectSystemTheme,
42898
- vw as getColorPreset,
42899
- yw as getPresetNames,
43059
+ bw as getColorPreset,
43060
+ _w as getPresetNames,
42900
43061
  Jo as getTheme,
42901
- Sw as getThemeNames,
43062
+ Tw as getThemeNames,
42902
43063
  xi as lightPresets,
42903
- _w as lightThemes,
43064
+ xw as lightThemes,
42904
43065
  da as themes,
42905
- xw as watchSystemTheme
43066
+ Cw as watchSystemTheme
42906
43067
  };