@thunderphone/widget 0.2.3 → 0.3.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.
@@ -789,7 +789,7 @@ var ThunderPhone = (() => {
789
789
  }
790
790
  return element;
791
791
  };
792
- function createElement3(type, config, children) {
792
+ function createElement4(type, config, children) {
793
793
  var propName;
794
794
  var props = {};
795
795
  var key = null;
@@ -1888,7 +1888,7 @@ var ThunderPhone = (() => {
1888
1888
  error("React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s", typeString, info);
1889
1889
  }
1890
1890
  }
1891
- var element = createElement3.apply(this, arguments);
1891
+ var element = createElement4.apply(this, arguments);
1892
1892
  if (element == null) {
1893
1893
  return element;
1894
1894
  }
@@ -16553,7 +16553,7 @@ var ThunderPhone = (() => {
16553
16553
  }
16554
16554
  }
16555
16555
  }
16556
- function createElement3(type, props, rootContainerElement, parentNamespace) {
16556
+ function createElement4(type, props, rootContainerElement, parentNamespace) {
16557
16557
  var isCustomComponentTag;
16558
16558
  var ownerDocument = getOwnerDocumentFromRootContainer(rootContainerElement);
16559
16559
  var domElement;
@@ -17423,7 +17423,7 @@ var ThunderPhone = (() => {
17423
17423
  }
17424
17424
  parentNamespace = hostContextDev.namespace;
17425
17425
  }
17426
- var domElement = createElement3(type, props, rootContainerInstance, parentNamespace);
17426
+ var domElement = createElement4(type, props, rootContainerInstance, parentNamespace);
17427
17427
  precacheFiberNode(internalInstanceHandle, domElement);
17428
17428
  updateFiberProps(domElement, props);
17429
17429
  return domElement;
@@ -31669,7 +31669,78 @@ var ThunderPhone = (() => {
31669
31669
  var import_react4 = __toESM(require_react());
31670
31670
  var import_client = __toESM(require_client());
31671
31671
 
31672
- // src/ThunderPhoneWidget.tsx
31672
+ // src/WidgetButton.tsx
31673
+ var import_jsx_runtime = __toESM(require_jsx_runtime());
31674
+ function WidgetButton({ state, muted, onClick, onMuteToggle }) {
31675
+ if (state === "connected") {
31676
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "tp-button-group", children: [
31677
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "tp-button tp-button--mute", onClick: onMuteToggle, type: "button", children: muted ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { className: "tp-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
31678
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "1", y1: "1", x2: "23", y2: "23" }),
31679
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M9 9v3a3 3 0 0 0 5.12 2.12M15 9.34V4a3 3 0 0 0-5.94-.6" }),
31680
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M17 16.95A7 7 0 0 1 5 12v-2m14 0v2c0 .76-.13 1.49-.36 2.18" }),
31681
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "12", y1: "19", x2: "12", y2: "23" }),
31682
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "8", y1: "23", x2: "16", y2: "23" })
31683
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { className: "tp-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
31684
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" }),
31685
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
31686
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "12", y1: "19", x2: "12", y2: "23" }),
31687
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "8", y1: "23", x2: "16", y2: "23" })
31688
+ ] }) }),
31689
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "tp-button tp-button--end", onClick, type: "button", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { className: "tp-icon", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "6", y: "6", width: "12", height: "12", rx: "2" }) }) })
31690
+ ] });
31691
+ }
31692
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
31693
+ "button",
31694
+ {
31695
+ className: `tp-button tp-button--start ${state === "connecting" ? "tp-button--loading" : ""}`,
31696
+ onClick,
31697
+ disabled: state === "connecting",
31698
+ type: "button",
31699
+ children: state === "connecting" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { className: "tp-icon tp-spin", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { className: "tp-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
31700
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" }),
31701
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
31702
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "12", y1: "19", x2: "12", y2: "23" }),
31703
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "8", y1: "23", x2: "16", y2: "23" })
31704
+ ] })
31705
+ }
31706
+ );
31707
+ }
31708
+
31709
+ // src/WidgetStatus.tsx
31710
+ var import_react = __toESM(require_react());
31711
+ var import_jsx_runtime2 = __toESM(require_jsx_runtime());
31712
+ function WidgetStatus({ state, agentName, errorMessage }) {
31713
+ const [elapsed, setElapsed] = (0, import_react.useState)(0);
31714
+ (0, import_react.useEffect)(() => {
31715
+ if (state !== "connected") {
31716
+ setElapsed(0);
31717
+ return;
31718
+ }
31719
+ const interval = setInterval(() => setElapsed((s) => s + 1), 1e3);
31720
+ return () => clearInterval(interval);
31721
+ }, [state]);
31722
+ const formatTime = (seconds) => {
31723
+ const m = Math.floor(seconds / 60);
31724
+ const s = seconds % 60;
31725
+ return `${m}:${s.toString().padStart(2, "0")}`;
31726
+ };
31727
+ const statusText = {
31728
+ idle: "Ready",
31729
+ connecting: "Connecting...",
31730
+ connected: formatTime(elapsed),
31731
+ disconnected: "Disconnected",
31732
+ error: "Unable to connect"
31733
+ };
31734
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "tp-status", children: [
31735
+ agentName && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "tp-status__name", children: agentName }),
31736
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: `tp-status__text tp-status--${state}`, children: [
31737
+ state === "connected" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "tp-status__dot" }),
31738
+ errorMessage && state === "error" ? errorMessage : statusText[state]
31739
+ ] })
31740
+ ] });
31741
+ }
31742
+
31743
+ // src/useThunderPhone.ts
31673
31744
  var import_react3 = __toESM(require_react());
31674
31745
 
31675
31746
  // node_modules/livekit-client/dist/livekit-client.esm.mjs
@@ -57364,12 +57435,12 @@ var ThunderPhone = (() => {
57364
57435
  });
57365
57436
 
57366
57437
  // src/AudioHandler.tsx
57367
- var import_react = __toESM(require_react());
57368
- var import_jsx_runtime = __toESM(require_jsx_runtime());
57438
+ var import_react2 = __toESM(require_react());
57439
+ var import_jsx_runtime3 = __toESM(require_jsx_runtime());
57369
57440
  function AudioHandler({ onAgentConnected, onDisconnected }) {
57370
57441
  const room = ua();
57371
- const audioRef = (0, import_react.useRef)(null);
57372
- (0, import_react.useEffect)(() => {
57442
+ const audioRef = (0, import_react2.useRef)(null);
57443
+ (0, import_react2.useEffect)(() => {
57373
57444
  if (room.remoteParticipants.size > 0) {
57374
57445
  onAgentConnected();
57375
57446
  }
@@ -57402,78 +57473,7 @@ var ThunderPhone = (() => {
57402
57473
  room.off(RoomEvent.TrackSubscribed, attachTrack);
57403
57474
  };
57404
57475
  }, [room, onAgentConnected, onDisconnected]);
57405
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("audio", { ref: audioRef, autoPlay: true });
57406
- }
57407
-
57408
- // src/WidgetButton.tsx
57409
- var import_jsx_runtime2 = __toESM(require_jsx_runtime());
57410
- function WidgetButton({ state, muted, onClick, onMuteToggle }) {
57411
- if (state === "connected") {
57412
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "tp-button-group", children: [
57413
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "tp-button tp-button--mute", onClick: onMuteToggle, type: "button", children: muted ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { className: "tp-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
57414
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "1", y1: "1", x2: "23", y2: "23" }),
57415
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M9 9v3a3 3 0 0 0 5.12 2.12M15 9.34V4a3 3 0 0 0-5.94-.6" }),
57416
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M17 16.95A7 7 0 0 1 5 12v-2m14 0v2c0 .76-.13 1.49-.36 2.18" }),
57417
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "12", y1: "19", x2: "12", y2: "23" }),
57418
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "8", y1: "23", x2: "16", y2: "23" })
57419
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { className: "tp-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
57420
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" }),
57421
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
57422
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "12", y1: "19", x2: "12", y2: "23" }),
57423
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "8", y1: "23", x2: "16", y2: "23" })
57424
- ] }) }),
57425
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "tp-button tp-button--end", onClick, type: "button", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "tp-icon", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "6", y: "6", width: "12", height: "12", rx: "2" }) }) })
57426
- ] });
57427
- }
57428
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
57429
- "button",
57430
- {
57431
- className: `tp-button tp-button--start ${state === "connecting" ? "tp-button--loading" : ""}`,
57432
- onClick,
57433
- disabled: state === "connecting",
57434
- type: "button",
57435
- children: state === "connecting" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "tp-icon tp-spin", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { className: "tp-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
57436
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" }),
57437
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
57438
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "12", y1: "19", x2: "12", y2: "23" }),
57439
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "8", y1: "23", x2: "16", y2: "23" })
57440
- ] })
57441
- }
57442
- );
57443
- }
57444
-
57445
- // src/WidgetStatus.tsx
57446
- var import_react2 = __toESM(require_react());
57447
- var import_jsx_runtime3 = __toESM(require_jsx_runtime());
57448
- function WidgetStatus({ state, agentName, errorMessage }) {
57449
- const [elapsed, setElapsed] = (0, import_react2.useState)(0);
57450
- (0, import_react2.useEffect)(() => {
57451
- if (state !== "connected") {
57452
- setElapsed(0);
57453
- return;
57454
- }
57455
- const interval = setInterval(() => setElapsed((s) => s + 1), 1e3);
57456
- return () => clearInterval(interval);
57457
- }, [state]);
57458
- const formatTime = (seconds) => {
57459
- const m = Math.floor(seconds / 60);
57460
- const s = seconds % 60;
57461
- return `${m}:${s.toString().padStart(2, "0")}`;
57462
- };
57463
- const statusText = {
57464
- idle: "Ready",
57465
- connecting: "Connecting...",
57466
- connected: formatTime(elapsed),
57467
- disconnected: "Disconnected",
57468
- error: "Unable to connect"
57469
- };
57470
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "tp-status", children: [
57471
- agentName && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "tp-status__name", children: agentName }),
57472
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: `tp-status__text tp-status--${state}`, children: [
57473
- state === "connected" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "tp-status__dot" }),
57474
- errorMessage && state === "error" ? errorMessage : statusText[state]
57475
- ] })
57476
- ] });
57476
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("audio", { ref: audioRef, autoPlay: true });
57477
57477
  }
57478
57478
 
57479
57479
  // src/api.ts
@@ -57505,95 +57505,109 @@ var ThunderPhone = (() => {
57505
57505
  return response.json();
57506
57506
  }
57507
57507
 
57508
- // src/ThunderPhoneWidget.tsx
57509
- var import_jsx_runtime4 = __toESM(require_jsx_runtime());
57510
- function ThunderPhoneWidget({
57511
- apiKey,
57512
- agentId,
57513
- apiBase,
57514
- onConnect,
57515
- onDisconnect,
57516
- onError,
57517
- className
57518
- }) {
57508
+ // src/useThunderPhone.ts
57509
+ function useThunderPhone(opts) {
57519
57510
  const [state, setState] = (0, import_react3.useState)("idle");
57520
57511
  const [session, setSession] = (0, import_react3.useState)(null);
57521
57512
  const [muted, setMuted] = (0, import_react3.useState)(false);
57522
- const [errorMessage, setErrorMessage] = (0, import_react3.useState)();
57523
- const handleConnect = (0, import_react3.useCallback)(async () => {
57513
+ const [error, setError] = (0, import_react3.useState)();
57514
+ const handleDisconnect = (0, import_react3.useCallback)(() => {
57515
+ setState("disconnected");
57516
+ setSession(null);
57517
+ setMuted(false);
57518
+ opts.onDisconnect?.();
57519
+ setTimeout(() => setState("idle"), 1500);
57520
+ }, [opts.onDisconnect]);
57521
+ const handleAgentConnected = (0, import_react3.useCallback)(() => {
57522
+ setState("connected");
57523
+ opts.onConnect?.();
57524
+ }, [opts.onConnect]);
57525
+ const connect = (0, import_react3.useCallback)(async () => {
57524
57526
  if (state === "connecting" || state === "connected") return;
57525
57527
  setState("connecting");
57526
- setErrorMessage(void 0);
57528
+ setError(void 0);
57527
57529
  try {
57528
- const sess = await createWidgetSession(apiKey, agentId, apiBase);
57530
+ const sess = await createWidgetSession(opts.apiKey, opts.agentId, opts.apiBase);
57529
57531
  setSession(sess);
57530
57532
  } catch (err) {
57531
57533
  setState("error");
57532
57534
  if (err instanceof WidgetAPIError) {
57533
- setErrorMessage(err.message);
57534
- onError?.({ error: err.code, message: err.message });
57535
+ setError(err.message);
57536
+ opts.onError?.({ error: err.code, message: err.message });
57535
57537
  } else {
57536
- setErrorMessage("Unable to connect.");
57537
- onError?.({ error: "unknown", message: "Unable to connect." });
57538
+ setError("Unable to connect.");
57539
+ opts.onError?.({ error: "unknown", message: "Unable to connect." });
57538
57540
  }
57539
57541
  }
57540
- }, [apiKey, agentId, apiBase, state, onError]);
57541
- const handleDisconnect = (0, import_react3.useCallback)(() => {
57542
- setState("disconnected");
57543
- setSession(null);
57544
- setMuted(false);
57545
- onDisconnect?.();
57546
- setTimeout(() => setState("idle"), 1500);
57547
- }, [onDisconnect]);
57548
- const handleAgentConnected = (0, import_react3.useCallback)(() => {
57549
- setState("connected");
57550
- onConnect?.();
57551
- }, [onConnect]);
57542
+ }, [opts.apiKey, opts.agentId, opts.apiBase, state, opts.onError]);
57543
+ const disconnect = (0, import_react3.useCallback)(() => {
57544
+ handleDisconnect();
57545
+ }, [handleDisconnect]);
57546
+ const toggleMute = (0, import_react3.useCallback)(() => setMuted((m) => !m), []);
57547
+ const audio = session ? (0, import_react3.createElement)(
57548
+ W,
57549
+ {
57550
+ token: session.token,
57551
+ serverUrl: session.server_url,
57552
+ audio: !muted,
57553
+ video: false,
57554
+ connect: true
57555
+ },
57556
+ (0, import_react3.createElement)(AudioHandler, {
57557
+ onAgentConnected: handleAgentConnected,
57558
+ onDisconnected: handleDisconnect
57559
+ })
57560
+ ) : null;
57561
+ return {
57562
+ state,
57563
+ connect,
57564
+ disconnect,
57565
+ toggleMute,
57566
+ isMuted: muted,
57567
+ error,
57568
+ agentName: session?.agent_name,
57569
+ audio
57570
+ };
57571
+ }
57572
+
57573
+ // src/ThunderPhoneWidget.tsx
57574
+ var import_jsx_runtime4 = __toESM(require_jsx_runtime());
57575
+ function ThunderPhoneWidget({
57576
+ apiKey,
57577
+ agentId,
57578
+ apiBase,
57579
+ onConnect,
57580
+ onDisconnect,
57581
+ onError,
57582
+ className
57583
+ }) {
57584
+ const phone = useThunderPhone({ apiKey, agentId, apiBase, onConnect, onDisconnect, onError });
57552
57585
  const handleClick = () => {
57553
- if (state === "connected") {
57554
- handleDisconnect();
57555
- } else if (state === "idle" || state === "error" || state === "disconnected") {
57556
- handleConnect();
57586
+ if (phone.state === "connected") {
57587
+ phone.disconnect();
57588
+ } else if (phone.state === "idle" || phone.state === "error" || phone.state === "disconnected") {
57589
+ phone.connect();
57557
57590
  }
57558
57591
  };
57559
- const handleMuteToggle = (0, import_react3.useCallback)(() => {
57560
- setMuted((m) => !m);
57561
- }, []);
57562
57592
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `tp-widget ${className || ""}`, children: [
57563
57593
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
57564
57594
  WidgetStatus,
57565
57595
  {
57566
- state,
57567
- agentName: session?.agent_name || null,
57568
- errorMessage
57596
+ state: phone.state,
57597
+ agentName: phone.agentName || null,
57598
+ errorMessage: phone.error
57569
57599
  }
57570
57600
  ),
57571
57601
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
57572
57602
  WidgetButton,
57573
57603
  {
57574
- state,
57575
- muted,
57604
+ state: phone.state,
57605
+ muted: phone.isMuted,
57576
57606
  onClick: handleClick,
57577
- onMuteToggle: handleMuteToggle
57607
+ onMuteToggle: phone.toggleMute
57578
57608
  }
57579
57609
  ),
57580
- session && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
57581
- W,
57582
- {
57583
- token: session.token,
57584
- serverUrl: session.server_url,
57585
- audio: !muted,
57586
- video: false,
57587
- connect: true,
57588
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
57589
- AudioHandler,
57590
- {
57591
- onAgentConnected: handleAgentConnected,
57592
- onDisconnected: handleDisconnect
57593
- }
57594
- )
57595
- }
57596
- )
57610
+ phone.audio
57597
57611
  ] });
57598
57612
  }
57599
57613