@intentai/react 2.1.0 → 2.1.2

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/dist/index.js CHANGED
@@ -116,15 +116,32 @@ var useAudioLevel = (isRecording) => {
116
116
  const [audioLevel, setAudioLevel] = (0, import_react.useState)(0);
117
117
  const analyserRef = (0, import_react.useRef)(null);
118
118
  const animationRef = (0, import_react.useRef)();
119
+ const streamRef = (0, import_react.useRef)(null);
120
+ const audioContextRef = (0, import_react.useRef)(null);
119
121
  (0, import_react.useEffect)(() => {
120
122
  if (!isRecording) {
121
123
  setAudioLevel(0);
124
+ if (animationRef.current) {
125
+ cancelAnimationFrame(animationRef.current);
126
+ animationRef.current = void 0;
127
+ }
128
+ if (streamRef.current) {
129
+ streamRef.current.getTracks().forEach((track) => track.stop());
130
+ streamRef.current = null;
131
+ }
132
+ if (audioContextRef.current) {
133
+ audioContextRef.current.close();
134
+ audioContextRef.current = null;
135
+ }
136
+ analyserRef.current = null;
122
137
  return;
123
138
  }
124
139
  const initAudio = async () => {
125
140
  try {
126
141
  const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
142
+ streamRef.current = stream;
127
143
  const audioContext = new AudioContext();
144
+ audioContextRef.current = audioContext;
128
145
  const source = audioContext.createMediaStreamSource(stream);
129
146
  const analyser = audioContext.createAnalyser();
130
147
  analyser.fftSize = 256;
@@ -148,6 +165,12 @@ var useAudioLevel = (isRecording) => {
148
165
  if (animationRef.current) {
149
166
  cancelAnimationFrame(animationRef.current);
150
167
  }
168
+ if (streamRef.current) {
169
+ streamRef.current.getTracks().forEach((track) => track.stop());
170
+ }
171
+ if (audioContextRef.current) {
172
+ audioContextRef.current.close();
173
+ }
151
174
  };
152
175
  }, [isRecording]);
153
176
  return audioLevel;
@@ -340,35 +363,33 @@ var AmbientOrb = ({ audioLevel, isRecording }) => {
340
363
  style: { transformOrigin: "center" }
341
364
  }
342
365
  ),
343
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("g", { transform: "translate(58, 55)", children: [
344
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
345
- import_framer_motion.motion.path,
346
- {
347
- d: "M20 4a6 6 0 0 0-6 6v16a6 6 0 0 0 12 0V10a6 6 0 0 0-6-6z",
348
- fill: "none",
349
- stroke: "white",
350
- strokeWidth: "2.5",
351
- strokeLinecap: "round",
352
- animate: {
353
- opacity: isRecording ? [1, 0.7, 1] : 1
354
- },
355
- transition: {
356
- duration: 1,
357
- repeat: isRecording ? Infinity : 0
358
- }
359
- }
360
- ),
361
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
362
- "path",
363
- {
364
- d: "M32 20v4a14 14 0 0 1-28 0v-4M20 38v10M12 48h16",
365
- fill: "none",
366
- stroke: "white",
367
- strokeWidth: "2.5",
368
- strokeLinecap: "round"
369
- }
370
- )
371
- ] }),
366
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("g", { transform: "translate(70, 70)", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
367
+ import_framer_motion.motion.g,
368
+ {
369
+ animate: {
370
+ opacity: isRecording ? [1, 0.7, 1] : 1
371
+ },
372
+ transition: {
373
+ duration: 1,
374
+ repeat: isRecording ? Infinity : 0
375
+ },
376
+ children: [
377
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "-8", y: "-20", width: "16", height: "26", rx: "8", fill: "white" }),
378
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
379
+ "path",
380
+ {
381
+ d: "M-14 0 v6 a14 14 0 0 0 28 0 v-6",
382
+ fill: "none",
383
+ stroke: "white",
384
+ strokeWidth: "3",
385
+ strokeLinecap: "round"
386
+ }
387
+ ),
388
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "0", y1: "20", x2: "0", y2: "28", stroke: "white", strokeWidth: "3", strokeLinecap: "round" }),
389
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "-8", y1: "28", x2: "8", y2: "28", stroke: "white", strokeWidth: "3", strokeLinecap: "round" })
390
+ ]
391
+ }
392
+ ) }),
372
393
  particles.map((particle) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
373
394
  import_framer_motion.motion.circle,
374
395
  {
@@ -1472,7 +1493,7 @@ var PremiumVoiceWidget = ({
1472
1493
  marginTop: 12,
1473
1494
  marginBottom: 0
1474
1495
  },
1475
- children: "Press and hold to record your feedback"
1496
+ children: "Click Record to start"
1476
1497
  }
1477
1498
  )
1478
1499
  ]
@@ -1488,8 +1509,7 @@ var PremiumVoiceWidget = ({
1488
1509
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1489
1510
  MagneticButton,
1490
1511
  {
1491
- onPressStart: handleStartRecording,
1492
- onPressEnd: handleStopRecording,
1512
+ onClick: isRecording ? handleStopRecording : handleStartRecording,
1493
1513
  variant: isRecording ? "recording" : "primary",
1494
1514
  children: isRecording ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1495
1515
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -1498,20 +1518,17 @@ var PremiumVoiceWidget = ({
1498
1518
  animate: { scale: [1, 1.2, 1] },
1499
1519
  transition: { duration: 1, repeat: Infinity },
1500
1520
  style: {
1501
- width: 8,
1502
- height: 8,
1503
- borderRadius: "50%",
1521
+ width: 10,
1522
+ height: 10,
1523
+ borderRadius: 2,
1504
1524
  background: "white"
1505
1525
  }
1506
1526
  }
1507
1527
  ),
1508
- "Recording... Release to stop"
1509
- ] }) : transcription ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1510
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: 16, height: 16, viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 3a2.5 2.5 0 0 0-2.5 2.5v5a2.5 2.5 0 0 0 5 0v-5A2.5 2.5 0 0 0 12 3z" }) }),
1511
- "Hold to record more"
1528
+ "Stop Recording"
1512
1529
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1513
1530
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: 16, height: 16, viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 3a2.5 2.5 0 0 0-2.5 2.5v5a2.5 2.5 0 0 0 5 0v-5A2.5 2.5 0 0 0 12 3z" }) }),
1514
- "Hold to Record"
1531
+ transcription ? "Record Again" : "Record"
1515
1532
  ] })
1516
1533
  }
1517
1534
  )
package/dist/index.mjs CHANGED
@@ -98,15 +98,32 @@ var useAudioLevel = (isRecording) => {
98
98
  const [audioLevel, setAudioLevel] = useState(0);
99
99
  const analyserRef = useRef(null);
100
100
  const animationRef = useRef();
101
+ const streamRef = useRef(null);
102
+ const audioContextRef = useRef(null);
101
103
  useEffect(() => {
102
104
  if (!isRecording) {
103
105
  setAudioLevel(0);
106
+ if (animationRef.current) {
107
+ cancelAnimationFrame(animationRef.current);
108
+ animationRef.current = void 0;
109
+ }
110
+ if (streamRef.current) {
111
+ streamRef.current.getTracks().forEach((track) => track.stop());
112
+ streamRef.current = null;
113
+ }
114
+ if (audioContextRef.current) {
115
+ audioContextRef.current.close();
116
+ audioContextRef.current = null;
117
+ }
118
+ analyserRef.current = null;
104
119
  return;
105
120
  }
106
121
  const initAudio = async () => {
107
122
  try {
108
123
  const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
124
+ streamRef.current = stream;
109
125
  const audioContext = new AudioContext();
126
+ audioContextRef.current = audioContext;
110
127
  const source = audioContext.createMediaStreamSource(stream);
111
128
  const analyser = audioContext.createAnalyser();
112
129
  analyser.fftSize = 256;
@@ -130,6 +147,12 @@ var useAudioLevel = (isRecording) => {
130
147
  if (animationRef.current) {
131
148
  cancelAnimationFrame(animationRef.current);
132
149
  }
150
+ if (streamRef.current) {
151
+ streamRef.current.getTracks().forEach((track) => track.stop());
152
+ }
153
+ if (audioContextRef.current) {
154
+ audioContextRef.current.close();
155
+ }
133
156
  };
134
157
  }, [isRecording]);
135
158
  return audioLevel;
@@ -322,35 +345,33 @@ var AmbientOrb = ({ audioLevel, isRecording }) => {
322
345
  style: { transformOrigin: "center" }
323
346
  }
324
347
  ),
325
- /* @__PURE__ */ jsxs("g", { transform: "translate(58, 55)", children: [
326
- /* @__PURE__ */ jsx(
327
- motion.path,
328
- {
329
- d: "M20 4a6 6 0 0 0-6 6v16a6 6 0 0 0 12 0V10a6 6 0 0 0-6-6z",
330
- fill: "none",
331
- stroke: "white",
332
- strokeWidth: "2.5",
333
- strokeLinecap: "round",
334
- animate: {
335
- opacity: isRecording ? [1, 0.7, 1] : 1
336
- },
337
- transition: {
338
- duration: 1,
339
- repeat: isRecording ? Infinity : 0
340
- }
341
- }
342
- ),
343
- /* @__PURE__ */ jsx(
344
- "path",
345
- {
346
- d: "M32 20v4a14 14 0 0 1-28 0v-4M20 38v10M12 48h16",
347
- fill: "none",
348
- stroke: "white",
349
- strokeWidth: "2.5",
350
- strokeLinecap: "round"
351
- }
352
- )
353
- ] }),
348
+ /* @__PURE__ */ jsx("g", { transform: "translate(70, 70)", children: /* @__PURE__ */ jsxs(
349
+ motion.g,
350
+ {
351
+ animate: {
352
+ opacity: isRecording ? [1, 0.7, 1] : 1
353
+ },
354
+ transition: {
355
+ duration: 1,
356
+ repeat: isRecording ? Infinity : 0
357
+ },
358
+ children: [
359
+ /* @__PURE__ */ jsx("rect", { x: "-8", y: "-20", width: "16", height: "26", rx: "8", fill: "white" }),
360
+ /* @__PURE__ */ jsx(
361
+ "path",
362
+ {
363
+ d: "M-14 0 v6 a14 14 0 0 0 28 0 v-6",
364
+ fill: "none",
365
+ stroke: "white",
366
+ strokeWidth: "3",
367
+ strokeLinecap: "round"
368
+ }
369
+ ),
370
+ /* @__PURE__ */ jsx("line", { x1: "0", y1: "20", x2: "0", y2: "28", stroke: "white", strokeWidth: "3", strokeLinecap: "round" }),
371
+ /* @__PURE__ */ jsx("line", { x1: "-8", y1: "28", x2: "8", y2: "28", stroke: "white", strokeWidth: "3", strokeLinecap: "round" })
372
+ ]
373
+ }
374
+ ) }),
354
375
  particles.map((particle) => /* @__PURE__ */ jsx(
355
376
  motion.circle,
356
377
  {
@@ -1454,7 +1475,7 @@ var PremiumVoiceWidget = ({
1454
1475
  marginTop: 12,
1455
1476
  marginBottom: 0
1456
1477
  },
1457
- children: "Press and hold to record your feedback"
1478
+ children: "Click Record to start"
1458
1479
  }
1459
1480
  )
1460
1481
  ]
@@ -1470,8 +1491,7 @@ var PremiumVoiceWidget = ({
1470
1491
  /* @__PURE__ */ jsx(
1471
1492
  MagneticButton,
1472
1493
  {
1473
- onPressStart: handleStartRecording,
1474
- onPressEnd: handleStopRecording,
1494
+ onClick: isRecording ? handleStopRecording : handleStartRecording,
1475
1495
  variant: isRecording ? "recording" : "primary",
1476
1496
  children: isRecording ? /* @__PURE__ */ jsxs(Fragment, { children: [
1477
1497
  /* @__PURE__ */ jsx(
@@ -1480,20 +1500,17 @@ var PremiumVoiceWidget = ({
1480
1500
  animate: { scale: [1, 1.2, 1] },
1481
1501
  transition: { duration: 1, repeat: Infinity },
1482
1502
  style: {
1483
- width: 8,
1484
- height: 8,
1485
- borderRadius: "50%",
1503
+ width: 10,
1504
+ height: 10,
1505
+ borderRadius: 2,
1486
1506
  background: "white"
1487
1507
  }
1488
1508
  }
1489
1509
  ),
1490
- "Recording... Release to stop"
1491
- ] }) : transcription ? /* @__PURE__ */ jsxs(Fragment, { children: [
1492
- /* @__PURE__ */ jsx("svg", { width: 16, height: 16, viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M12 3a2.5 2.5 0 0 0-2.5 2.5v5a2.5 2.5 0 0 0 5 0v-5A2.5 2.5 0 0 0 12 3z" }) }),
1493
- "Hold to record more"
1510
+ "Stop Recording"
1494
1511
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1495
1512
  /* @__PURE__ */ jsx("svg", { width: 16, height: 16, viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M12 3a2.5 2.5 0 0 0-2.5 2.5v5a2.5 2.5 0 0 0 5 0v-5A2.5 2.5 0 0 0 12 3z" }) }),
1496
- "Hold to Record"
1513
+ transcription ? "Record Again" : "Record"
1497
1514
  ] })
1498
1515
  }
1499
1516
  )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentai/react",
3
- "version": "2.1.0",
3
+ "version": "2.1.2",
4
4
  "description": "React component for Intent AI feedback widget - easily collect user feedback with AI-powered analysis",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org",