@tiny-codes/react-easy 1.4.8 → 1.4.10

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 (56) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/es/hooks/index.d.ts +3 -0
  3. package/es/hooks/index.js +3 -0
  4. package/es/hooks/index.js.map +1 -1
  5. package/es/hooks/useAudioPlayer.d.ts +7 -0
  6. package/es/hooks/useAudioPlayer.js +13 -0
  7. package/es/hooks/useAudioPlayer.js.map +1 -0
  8. package/es/hooks/useSSE.d.ts +26 -0
  9. package/es/hooks/useSSE.js +147 -0
  10. package/es/hooks/useSSE.js.map +1 -0
  11. package/es/hooks/useUserMedia.d.ts +11 -4
  12. package/es/hooks/useUserMedia.js +10 -8
  13. package/es/hooks/useUserMedia.js.map +1 -1
  14. package/es/utils/AudioPlayer.d.ts +166 -0
  15. package/es/utils/AudioPlayer.js +457 -0
  16. package/es/utils/AudioPlayer.js.map +1 -0
  17. package/es/utils/base64.d.ts +48 -0
  18. package/es/utils/base64.js +139 -0
  19. package/es/utils/base64.js.map +1 -0
  20. package/es/utils/crypto.d.ts +0 -30
  21. package/es/utils/crypto.js +8 -93
  22. package/es/utils/crypto.js.map +1 -1
  23. package/es/utils/index.d.ts +5 -1
  24. package/es/utils/index.js +5 -1
  25. package/es/utils/index.js.map +1 -1
  26. package/es/utils/stream.d.ts +17 -10
  27. package/es/utils/stream.js +13 -5
  28. package/es/utils/stream.js.map +1 -1
  29. package/lib/hooks/index.d.ts +3 -0
  30. package/lib/hooks/index.js +8 -0
  31. package/lib/hooks/index.js.map +2 -2
  32. package/lib/hooks/useAudioPlayer.d.ts +7 -0
  33. package/lib/hooks/useAudioPlayer.js +42 -0
  34. package/lib/hooks/useAudioPlayer.js.map +7 -0
  35. package/lib/hooks/useSSE.d.ts +26 -0
  36. package/lib/hooks/useSSE.js +128 -0
  37. package/lib/hooks/useSSE.js.map +7 -0
  38. package/lib/hooks/useUserMedia.d.ts +11 -4
  39. package/lib/hooks/useUserMedia.js +9 -7
  40. package/lib/hooks/useUserMedia.js.map +2 -2
  41. package/lib/utils/AudioPlayer.d.ts +166 -0
  42. package/lib/utils/AudioPlayer.js +305 -0
  43. package/lib/utils/AudioPlayer.js.map +7 -0
  44. package/lib/utils/base64.d.ts +48 -0
  45. package/lib/utils/base64.js +120 -0
  46. package/lib/utils/base64.js.map +7 -0
  47. package/lib/utils/crypto.d.ts +0 -30
  48. package/lib/utils/crypto.js +7 -66
  49. package/lib/utils/crypto.js.map +2 -2
  50. package/lib/utils/index.d.ts +5 -1
  51. package/lib/utils/index.js +28 -3
  52. package/lib/utils/index.js.map +2 -2
  53. package/lib/utils/stream.d.ts +17 -10
  54. package/lib/utils/stream.js +9 -4
  55. package/lib/utils/stream.js.map +2 -2
  56. package/package.json +2 -1
@@ -15,11 +15,13 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
15
15
  export var StreamTimeSlicerClass = /*#__PURE__*/function () {
16
16
  function StreamTimeSlicerClass(options) {
17
17
  _classCallCheck(this, StreamTimeSlicerClass);
18
- _defineProperty(this, "timeSlice", void 0);
18
+ _defineProperty(this, "sliceMode", void 0);
19
+ _defineProperty(this, "value", void 0);
19
20
  _defineProperty(this, "onSlice", void 0);
20
21
  _defineProperty(this, "channelChunks", []);
21
22
  _defineProperty(this, "startTs", null);
22
- this.timeSlice = options.timeSlice;
23
+ this.sliceMode = options.sliceMode;
24
+ this.value = options.value;
23
25
  this.onSlice = options.onSlice;
24
26
  }
25
27
  _createClass(StreamTimeSlicerClass, [{
@@ -31,8 +33,14 @@ export var StreamTimeSlicerClass = /*#__PURE__*/function () {
31
33
  key: "shouldEmit",
32
34
  value: function shouldEmit(currentTs) {
33
35
  if (this.startTs == null) return false;
34
- if (this.timeSlice <= 0) return true;
35
- return currentTs - this.startTs >= this.timeSlice;
36
+ if (this.value <= 0) return true;
37
+ if (this.sliceMode === 'time') {
38
+ return currentTs - this.startTs >= this.value;
39
+ } else {
40
+ return this.channelChunks.reduce(function (acc, arr) {
41
+ return acc + arr.length;
42
+ }, 0) >= this.value;
43
+ }
36
44
  }
37
45
  }, {
38
46
  key: "emit",
@@ -93,7 +101,7 @@ export var StreamTimeSlicerClass = /*#__PURE__*/function () {
93
101
  _this.channelChunks[i].push(ch);
94
102
  });
95
103
  this.emit(false);
96
- if (this.timeSlice <= 0) this.emit(true); // immediate output mode
104
+ if (this.value <= 0) this.emit(true); // immediate output mode
97
105
  }
98
106
  }, {
99
107
  key: "flush",
@@ -1 +1 @@
1
- {"version":3,"names":["StreamTimeSlicerClass","options","_classCallCheck","_defineProperty","timeSlice","onSlice","_createClass","key","value","now","performance","Date","shouldEmit","currentTs","startTs","emit","force","arguments","length","undefined","channelChunks","every","arr","i","merged","map","chArr","total","reduce","s","a","out","Float32Array","offset","_iterator","_createForOfIteratorHelper","_step","n","done","seg","set","err","e","f","sliceDur","push","channels","_this","forEach","ch","flush","reset","duration"],"sources":["../../src/utils/stream.ts"],"sourcesContent":["/**\n * - **EN:** A stream time slicer for splitting audio streams into fixed time segments\n * - **CN:** 一个数据流时间切片器,用于将音频流分成固定时间段\n */\nexport class StreamTimeSlicerClass implements StreamTimeSlicer {\n timeSlice: number;\n private readonly onSlice: (channels: Float32Array[], sliceDurationMs: number) => void;\n private channelChunks: Float32Array[][] = [];\n private startTs: number | null = null;\n\n constructor(options: StreamTimeSlicerOptions) {\n this.timeSlice = options.timeSlice;\n this.onSlice = options.onSlice;\n }\n\n private now() {\n return typeof performance !== 'undefined' ? performance.now() : Date.now();\n }\n\n private shouldEmit(currentTs: number) {\n if (this.startTs == null) return false;\n if (this.timeSlice <= 0) return true;\n return currentTs - this.startTs >= this.timeSlice;\n }\n\n private emit(force = false) {\n if (this.startTs == null) return;\n const currentTs = this.now();\n if (!force && !this.shouldEmit(currentTs)) return;\n\n // reset start time\n if (this.channelChunks.length === 0 || this.channelChunks.every((arr) => arr.length === 0)) {\n this.startTs = null;\n for (let i = 0; i < this.channelChunks.length; i++) this.channelChunks[i] = [];\n return;\n }\n\n // Merge each channel\n const merged: Float32Array[] = this.channelChunks.map((chArr) => {\n const total = chArr.reduce((s, a) => s + a.length, 0);\n const out = new Float32Array(total);\n let offset = 0;\n for (const seg of chArr) {\n out.set(seg, offset);\n offset += seg.length;\n }\n return out;\n });\n\n const sliceDur = this.startTs != null ? currentTs - this.startTs : 0;\n this.onSlice(merged, sliceDur);\n\n // Reset start time\n for (let i = 0; i < this.channelChunks.length; i++) this.channelChunks[i] = [];\n this.startTs = null;\n }\n\n push(channels: Float32Array[]) {\n if (!channels || channels.length === 0) return;\n if (this.startTs == null) this.startTs = this.now();\n\n while (this.channelChunks.length < channels.length) {\n this.channelChunks.push([]);\n }\n channels.forEach((ch, i) => {\n this.channelChunks[i].push(ch);\n });\n\n this.emit(false);\n if (this.timeSlice <= 0) this.emit(true); // immediate output mode\n }\n\n flush() {\n this.emit(true);\n }\n\n reset() {\n for (let i = 0; i < this.channelChunks.length; i++) this.channelChunks[i] = [];\n this.startTs = null;\n }\n\n duration() {\n return this.startTs == null ? 0 : this.now() - this.startTs;\n }\n}\nexport interface StreamTimeSlicerOptions {\n /**\n * - **EN:** Duration of each slice (ms)\n * - **CN:** 分片时长(ms)\n */\n timeSlice: number;\n /**\n * - **EN:** Callback when a slice is reached\n * - **CN:** 达到分片时回调\n *\n * @param channels - Multi-channel data, each channel is a Float32Array | 多通道数据,每个通道是一个\n * Float32Array\n * @param sliceDuration - Duration of the slice (ms) | 分片时长(ms)\n */\n onSlice: (channels: Float32Array[], sliceDuration: number) => void;\n}\n\n/**\n * - **EN:** stream time slicer\n * - **CN:** 数据流时间切片器\n */\nexport interface StreamTimeSlicer {\n /**\n * - **EN:** Duration of each slice (ms)\n * - **CN:** 每个分片的时长(毫秒)\n */\n timeSlice: number;\n /**\n * - **EN:** Push a frame (multi-channel data obtained from the same callback)\n * - **CN:** 推入一帧(同一次回调得到的多通道)\n *\n * @param channels - Multi-channel data, each channel is a Float32Array | 多通道数据,每个通道是一个\n * Float32Array\n */\n push: (channels: Float32Array[]) => void;\n /**\n * - **EN:** Force output the current accumulation (output even if not enough timeSlice)\n * - **CN:** 强制输出当前累积(不足 timeSlice 也输出)\n */\n flush: () => void;\n /**\n * - **EN:** Clear the cache (do not output)\n * - **CN:** 清空缓存(不输出)\n */\n reset: () => void;\n /**\n * - **EN:** Get the accumulated duration from start to current (ms)\n * - **CN:** 获取从开始到当前已累计的时长(ms)\n */\n duration: () => number;\n}\n"],"mappings":"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"}
1
+ {"version":3,"names":["StreamTimeSlicerClass","options","_classCallCheck","_defineProperty","sliceMode","value","onSlice","_createClass","key","now","performance","Date","shouldEmit","currentTs","startTs","channelChunks","reduce","acc","arr","length","emit","force","arguments","undefined","every","i","merged","map","chArr","total","s","a","out","Float32Array","offset","_iterator","_createForOfIteratorHelper","_step","n","done","seg","set","err","e","f","sliceDur","push","channels","_this","forEach","ch","flush","reset","duration"],"sources":["../../src/utils/stream.ts"],"sourcesContent":["/**\n * - **EN:** A stream time slicer for splitting audio streams into fixed time segments\n * - **CN:** 一个数据流时间切片器,用于将音频流分成固定时间段\n */\nexport class StreamTimeSlicerClass implements StreamTimeSlicer {\n public sliceMode: StreamTimeSlicerOptions['sliceMode'];\n public value: StreamTimeSlicerOptions['value'];\n private readonly onSlice: (channels: Float32Array[], sliceDurationMs: number) => void;\n private channelChunks: Float32Array[][] = [];\n private startTs: number | null = null;\n\n constructor(options: StreamTimeSlicerOptions) {\n this.sliceMode = options.sliceMode;\n this.value = options.value;\n this.onSlice = options.onSlice;\n }\n\n private now() {\n return typeof performance !== 'undefined' ? performance.now() : Date.now();\n }\n\n private shouldEmit(currentTs: number) {\n if (this.startTs == null) return false;\n if (this.value <= 0) return true;\n if (this.sliceMode === 'time') {\n return currentTs - this.startTs >= this.value;\n } else {\n return this.channelChunks.reduce((acc, arr) => acc + arr.length, 0) >= this.value;\n }\n }\n\n private emit(force = false) {\n if (this.startTs == null) return;\n const currentTs = this.now();\n if (!force && !this.shouldEmit(currentTs)) return;\n\n // reset start time\n if (this.channelChunks.length === 0 || this.channelChunks.every((arr) => arr.length === 0)) {\n this.startTs = null;\n for (let i = 0; i < this.channelChunks.length; i++) this.channelChunks[i] = [];\n return;\n }\n\n // Merge each channel\n const merged: Float32Array[] = this.channelChunks.map((chArr) => {\n const total = chArr.reduce((s, a) => s + a.length, 0);\n const out = new Float32Array(total);\n let offset = 0;\n for (const seg of chArr) {\n out.set(seg, offset);\n offset += seg.length;\n }\n return out;\n });\n\n const sliceDur = this.startTs != null ? currentTs - this.startTs : 0;\n this.onSlice(merged, sliceDur);\n\n // Reset start time\n for (let i = 0; i < this.channelChunks.length; i++) this.channelChunks[i] = [];\n this.startTs = null;\n }\n\n push(channels: Float32Array[]) {\n if (!channels || channels.length === 0) return;\n if (this.startTs == null) this.startTs = this.now();\n\n while (this.channelChunks.length < channels.length) {\n this.channelChunks.push([]);\n }\n channels.forEach((ch, i) => {\n this.channelChunks[i].push(ch);\n });\n\n this.emit(false);\n if (this.value <= 0) this.emit(true); // immediate output mode\n }\n\n flush() {\n this.emit(true);\n }\n\n reset() {\n for (let i = 0; i < this.channelChunks.length; i++) this.channelChunks[i] = [];\n this.startTs = null;\n }\n\n duration() {\n return this.startTs == null ? 0 : this.now() - this.startTs;\n }\n}\nexport interface StreamTimeSlicerOptions {\n /**\n * - **EN:** Mode of slicing\n *\n * - 'time': slice by time (ms)\n * - 'size': slice by size (bytes)\n * - **CN:** 切片模式\n *\n * - 'time': 按时间切片(毫秒)\n * - 'size': 按大小切片(字节)\n */\n sliceMode: 'time' | 'size';\n /**\n * - **EN:** Value for slicing (ms or bytes)\n * - **CN:** 切片值(毫秒或字节)\n */\n value: number;\n /**\n * - **EN:** Callback when a slice is reached\n * - **CN:** 达到分片时回调\n *\n * @param channels - Multi-channel data, each channel is a Float32Array | 多通道数据,每个通道是一个\n * Float32Array\n * @param sliceDuration - Duration of the slice (ms) | 分片时长(ms)\n */\n onSlice: (channels: Float32Array[], sliceDuration: number) => void;\n}\n\n/**\n * - **EN:** stream time slicer\n * - **CN:** 数据流时间切片器\n */\nexport interface StreamTimeSlicer\n extends Readonly<Pick<StreamTimeSlicerOptions, 'sliceMode'>>,\n Pick<StreamTimeSlicerOptions, 'value'> {\n /**\n * - **EN:** Push a frame (multi-channel data obtained from the same callback)\n * - **CN:** 推入一帧(同一次回调得到的多通道)\n *\n * @param channels - Multi-channel data, each channel is a Float32Array | 多通道数据,每个通道是一个\n * Float32Array\n */\n push: (channels: Float32Array[]) => void;\n /**\n * - **EN:** Force output the current accumulation (output even if not enough timeSlice)\n * - **CN:** 强制输出当前累积(不足 timeSlice 也输出)\n */\n flush: () => void;\n /**\n * - **EN:** Clear the cache (do not output)\n * - **CN:** 清空缓存(不输出)\n */\n reset: () => void;\n /**\n * - **EN:** Get the accumulated duration from start to current (ms)\n * - **CN:** 获取从开始到当前已累计的时长(ms)\n */\n duration: () => number;\n}\n"],"mappings":"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"}
@@ -1,5 +1,8 @@
1
+ export { default as useAudioPlayer } from './useAudioPlayer';
1
2
  export { default as useRefValue } from './useRefValue';
2
3
  export { default as useRefFunction } from './useRefFunction';
4
+ export * from './useSSE';
5
+ export { default as useSSE } from './useSSE';
3
6
  export * from './useStompSocket';
4
7
  export { default as useStompSocket } from './useStompSocket';
5
8
  export type { ValidatorRuleMap } from './useValidators';
@@ -30,8 +30,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/hooks/index.ts
31
31
  var hooks_exports = {};
32
32
  __export(hooks_exports, {
33
+ useAudioPlayer: () => import_useAudioPlayer.default,
33
34
  useRefFunction: () => import_useRefFunction.default,
34
35
  useRefValue: () => import_useRefValue.default,
36
+ useSSE: () => import_useSSE.default,
35
37
  useStompSocket: () => import_useStompSocket.default,
36
38
  useUserMedia: () => import_useUserMedia.default,
37
39
  useValidator: () => import_useValidator.default,
@@ -39,8 +41,11 @@ __export(hooks_exports, {
39
41
  useValidators: () => import_useValidators.default
40
42
  });
41
43
  module.exports = __toCommonJS(hooks_exports);
44
+ var import_useAudioPlayer = __toESM(require("./useAudioPlayer"));
42
45
  var import_useRefValue = __toESM(require("./useRefValue"));
43
46
  var import_useRefFunction = __toESM(require("./useRefFunction"));
47
+ __reExport(hooks_exports, require("./useSSE"), module.exports);
48
+ var import_useSSE = __toESM(require("./useSSE"));
44
49
  __reExport(hooks_exports, require("./useStompSocket"), module.exports);
45
50
  var import_useStompSocket = __toESM(require("./useStompSocket"));
46
51
  var import_useValidators = __toESM(require("./useValidators"));
@@ -50,13 +55,16 @@ __reExport(hooks_exports, require("./useUserMedia"), module.exports);
50
55
  var import_useUserMedia = __toESM(require("./useUserMedia"));
51
56
  // Annotate the CommonJS export names for ESM import in node:
52
57
  0 && (module.exports = {
58
+ useAudioPlayer,
53
59
  useRefFunction,
54
60
  useRefValue,
61
+ useSSE,
55
62
  useStompSocket,
56
63
  useUserMedia,
57
64
  useValidator,
58
65
  useValidatorBuilder,
59
66
  useValidators,
67
+ ...require("./useSSE"),
60
68
  ...require("./useStompSocket"),
61
69
  ...require("./useUserMedia")
62
70
  });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/hooks/index.ts"],
4
- "sourcesContent": ["export { default as useRefValue } from './useRefValue';\nexport { default as useRefFunction } from './useRefFunction';\nexport * from './useStompSocket';\nexport { default as useStompSocket } from './useStompSocket';\nexport type { ValidatorRuleMap } from './useValidators';\nexport { default as useValidators } from './useValidators';\nexport { default as useValidator } from './useValidator';\nexport type { Validator, RuleRegExpFlags, ValidatorRule, BuilderOptions } from './useValidatorBuilder';\nexport { default as useValidatorBuilder } from './useValidatorBuilder';\nexport * from './useUserMedia';\nexport { default as useUserMedia } from './useUserMedia';\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAAuC;AACvC,4BAA0C;AAC1C,0BAAc,6BAFd;AAGA,4BAA0C;AAE1C,2BAAyC;AACzC,0BAAwC;AAExC,iCAA+C;AAC/C,0BAAc,2BATd;AAUA,0BAAwC;",
4
+ "sourcesContent": ["export { default as useAudioPlayer } from './useAudioPlayer';\nexport { default as useRefValue } from './useRefValue';\nexport { default as useRefFunction } from './useRefFunction';\nexport * from './useSSE';\nexport { default as useSSE } from './useSSE';\nexport * from './useStompSocket';\nexport { default as useStompSocket } from './useStompSocket';\nexport type { ValidatorRuleMap } from './useValidators';\nexport { default as useValidators } from './useValidators';\nexport { default as useValidator } from './useValidator';\nexport type { Validator, RuleRegExpFlags, ValidatorRule, BuilderOptions } from './useValidatorBuilder';\nexport { default as useValidatorBuilder } from './useValidatorBuilder';\nexport * from './useUserMedia';\nexport { default as useUserMedia } from './useUserMedia';\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAA0C;AAC1C,yBAAuC;AACvC,4BAA0C;AAC1C,0BAAc,qBAHd;AAIA,oBAAkC;AAClC,0BAAc,6BALd;AAMA,4BAA0C;AAE1C,2BAAyC;AACzC,0BAAwC;AAExC,iCAA+C;AAC/C,0BAAc,2BAZd;AAaA,0BAAwC;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,7 @@
1
+ import AudioPlayer, { type AudioPlayerInit } from '../utils/AudioPlayer';
2
+ /**
3
+ * - **EN:** A hook that provides an instance of the AudioPlayer class for managing audio playback.
4
+ * - **CN:** 一个提供AudioPlayer类实例的钩子,用于管理音频播放。
5
+ */
6
+ declare const useAudioPlayer: (props?: AudioPlayerInit) => AudioPlayer;
7
+ export default useAudioPlayer;
@@ -0,0 +1,42 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+
29
+ // src/hooks/useAudioPlayer.ts
30
+ var useAudioPlayer_exports = {};
31
+ __export(useAudioPlayer_exports, {
32
+ default: () => useAudioPlayer_default
33
+ });
34
+ module.exports = __toCommonJS(useAudioPlayer_exports);
35
+ var import_react = require("react");
36
+ var import_AudioPlayer = __toESM(require("../utils/AudioPlayer"));
37
+ var useAudioPlayer = (props) => {
38
+ const ref = (0, import_react.useRef)(new import_AudioPlayer.default(props));
39
+ return ref.current;
40
+ };
41
+ var useAudioPlayer_default = useAudioPlayer;
42
+ //# sourceMappingURL=useAudioPlayer.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/hooks/useAudioPlayer.ts"],
4
+ "sourcesContent": ["import { useRef } from 'react';\nimport AudioPlayer, { type AudioPlayerInit } from '../utils/AudioPlayer';\n\n/**\n * - **EN:** A hook that provides an instance of the AudioPlayer class for managing audio playback.\n * - **CN:** 一个提供AudioPlayer类实例的钩子,用于管理音频播放。\n */\nconst useAudioPlayer = (props?: AudioPlayerInit): AudioPlayer => {\n const ref = useRef<AudioPlayer>(new AudioPlayer(props));\n return ref.current;\n};\n\nexport default useAudioPlayer;\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAuB;AACvB,yBAAkD;AAMlD,IAAM,iBAAiB,CAAC,UAAyC;AAC/D,QAAM,UAAM,qBAAoB,IAAI,mBAAAA,QAAY,KAAK,CAAC;AACtD,SAAO,IAAI;AACb;AAEA,IAAO,yBAAQ;",
6
+ "names": ["AudioPlayer"]
7
+ }
@@ -0,0 +1,26 @@
1
+ import type { EventSourceMessage, FetchEventSourceInit } from '@microsoft/fetch-event-source';
2
+ export interface UseSSEProps<T = any> {
3
+ /** The URL to connect to */
4
+ url: RequestInfo;
5
+ /** Options for the connection. */
6
+ connectOptions?: Omit<FetchEventSourceInit, 'onmessage' | 'onerror' | 'onclose'>;
7
+ /** Automatically connect to the SSE channel. Default is `false`. */
8
+ autoConnect?: boolean;
9
+ /** Automatically close the connection when the component unmounts. Default is `true`. */
10
+ autoClose?: boolean;
11
+ /** Function to parse the incoming message. If not provided, the default JSON parser will be used. */
12
+ parseMessage?: (original: EventSourceMessage) => T;
13
+ /** Callback function to handle incoming messages. */
14
+ onMessage?: (messageData: T) => void;
15
+ /** Callback function to handle errors. */
16
+ onError?: (error: any) => void;
17
+ /** Callback function to handle connection closure. */
18
+ onClose?: () => void;
19
+ }
20
+ declare const useSSE: <T = any>(props: UseSSEProps<T>) => {
21
+ connect: (options?: FetchEventSourceInit & Partial<Pick<UseSSEProps, 'url'>>) => Promise<void>;
22
+ close: () => void;
23
+ isRequesting: boolean;
24
+ isConnected: boolean;
25
+ };
26
+ export default useSSE;
@@ -0,0 +1,128 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+
29
+ // src/hooks/useSSE.ts
30
+ var useSSE_exports = {};
31
+ __export(useSSE_exports, {
32
+ default: () => useSSE_default
33
+ });
34
+ module.exports = __toCommonJS(useSSE_exports);
35
+ var import_react = require("react");
36
+ var import_fetch_event_source = require("@microsoft/fetch-event-source");
37
+ var import_useRefFunction = __toESM(require("./useRefFunction"));
38
+ var import_useRefValue = __toESM(require("./useRefValue"));
39
+ var useSSE = (props) => {
40
+ const { url, autoConnect, connectOptions, onMessage, parseMessage, onError, onClose } = props;
41
+ const autoConnectRef = (0, import_useRefValue.default)(autoConnect);
42
+ const [isRequesting, setIsRequesting] = (0, import_react.useState)(false);
43
+ const isRequestingRef = (0, import_useRefValue.default)(isRequesting);
44
+ const [isConnected, setIsConnected] = (0, import_react.useState)(false);
45
+ const abortCtrlRef = (0, import_react.useRef)(void 0);
46
+ const connect = (0, import_useRefFunction.default)(async (options) => {
47
+ const {
48
+ url: connectUrl = url,
49
+ headers = {},
50
+ onopen,
51
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
52
+ onmessage,
53
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
54
+ onclose,
55
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
56
+ onerror,
57
+ ...restOptions
58
+ } = { ...connectOptions, ...options };
59
+ abortCtrlRef.current = new AbortController();
60
+ try {
61
+ setIsRequesting(true);
62
+ setIsConnected(false);
63
+ await (0, import_fetch_event_source.fetchEventSource)(connectUrl, {
64
+ method: "post",
65
+ signal: abortCtrlRef.current.signal,
66
+ openWhenHidden: true,
67
+ onopen: async (response) => {
68
+ setIsConnected(true);
69
+ onopen == null ? void 0 : onopen(response);
70
+ },
71
+ onmessage(event) {
72
+ if (!isRequestingRef.current) {
73
+ setIsRequesting(false);
74
+ }
75
+ try {
76
+ let parsed;
77
+ if (parseMessage) {
78
+ parsed = parseMessage(event);
79
+ } else {
80
+ parsed = event.data ? JSON.parse(event.data) : void 0;
81
+ }
82
+ if (parsed != null) {
83
+ onMessage == null ? void 0 : onMessage(parsed);
84
+ }
85
+ } catch (error) {
86
+ console.error("Error parsing message data:", error);
87
+ console.log("The underlying event:", event);
88
+ }
89
+ },
90
+ onerror(error) {
91
+ setIsRequesting(false);
92
+ onError == null ? void 0 : onError(error);
93
+ },
94
+ onclose() {
95
+ setIsRequesting(false);
96
+ onClose == null ? void 0 : onClose();
97
+ },
98
+ headers: {
99
+ "Content-Type": "application/json",
100
+ ...headers
101
+ },
102
+ ...restOptions
103
+ });
104
+ } finally {
105
+ setIsRequesting(false);
106
+ }
107
+ });
108
+ const close = (0, import_useRefFunction.default)(() => {
109
+ setIsConnected(false);
110
+ if (isConnected && abortCtrlRef.current) {
111
+ abortCtrlRef.current.abort();
112
+ }
113
+ });
114
+ (0, import_react.useEffect)(() => {
115
+ if (autoConnectRef.current) {
116
+ connect();
117
+ }
118
+ return close;
119
+ }, []);
120
+ return {
121
+ connect,
122
+ close,
123
+ isRequesting,
124
+ isConnected
125
+ };
126
+ };
127
+ var useSSE_default = useSSE;
128
+ //# sourceMappingURL=useSSE.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/hooks/useSSE.ts"],
4
+ "sourcesContent": ["import { useEffect, useRef, useState } from 'react';\nimport type { EventSourceMessage, FetchEventSourceInit } from '@microsoft/fetch-event-source';\nimport { fetchEventSource } from '@microsoft/fetch-event-source';\nimport useRefFunction from './useRefFunction';\nimport useRefValue from './useRefValue';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface UseSSEProps<T = any> {\n /** The URL to connect to */\n url: RequestInfo;\n /** Options for the connection. */\n connectOptions?: Omit<FetchEventSourceInit, 'onmessage' | 'onerror' | 'onclose'>;\n /** Automatically connect to the SSE channel. Default is `false`. */\n autoConnect?: boolean;\n /** Automatically close the connection when the component unmounts. Default is `true`. */\n autoClose?: boolean;\n /** Function to parse the incoming message. If not provided, the default JSON parser will be used. */\n parseMessage?: (original: EventSourceMessage) => T;\n /** Callback function to handle incoming messages. */\n onMessage?: (messageData: T) => void;\n /** Callback function to handle errors. */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onError?: (error: any) => void;\n /** Callback function to handle connection closure. */\n onClose?: () => void;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst useSSE = <T = any>(props: UseSSEProps<T>) => {\n const { url, autoConnect, connectOptions, onMessage, parseMessage, onError, onClose } = props;\n const autoConnectRef = useRefValue(autoConnect);\n const [isRequesting, setIsRequesting] = useState(false);\n const isRequestingRef = useRefValue(isRequesting);\n const [isConnected, setIsConnected] = useState<boolean>(false);\n const abortCtrlRef = useRef<AbortController | undefined>(undefined);\n\n const connect = useRefFunction(async (options?: FetchEventSourceInit & Partial<Pick<UseSSEProps, 'url'>>) => {\n const {\n url: connectUrl = url,\n headers = {},\n onopen,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onmessage,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onclose,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onerror,\n ...restOptions\n } = { ...connectOptions, ...options };\n abortCtrlRef.current = new AbortController();\n try {\n setIsRequesting(true);\n setIsConnected(false);\n await fetchEventSource(connectUrl, {\n method: 'post',\n signal: abortCtrlRef.current.signal,\n openWhenHidden: true,\n onopen: async (response: Response) => {\n setIsConnected(true);\n onopen?.(response);\n },\n onmessage(event) {\n if (!isRequestingRef.current) {\n setIsRequesting(false);\n }\n try {\n let parsed: T;\n if (parseMessage) {\n parsed = parseMessage(event);\n } else {\n parsed = event.data ? JSON.parse(event.data) : undefined;\n }\n if (parsed != null) {\n onMessage?.(parsed);\n }\n } catch (error) {\n console.error('Error parsing message data:', error);\n console.log('The underlying event:', event);\n }\n },\n onerror(error) {\n setIsRequesting(false);\n onError?.(error);\n },\n onclose() {\n setIsRequesting(false);\n onClose?.();\n },\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n ...restOptions,\n });\n } finally {\n setIsRequesting(false);\n }\n });\n\n const close = useRefFunction(() => {\n setIsConnected(false);\n if (isConnected && abortCtrlRef.current) {\n abortCtrlRef.current.abort();\n }\n });\n\n useEffect(() => {\n if (autoConnectRef.current) {\n connect();\n }\n return close;\n }, []);\n\n // 清理函数\n return {\n connect,\n close,\n isRequesting,\n isConnected,\n };\n};\n\nexport default useSSE;\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA4C;AAE5C,gCAAiC;AACjC,4BAA2B;AAC3B,yBAAwB;AAwBxB,IAAM,SAAS,CAAU,UAA0B;AACjD,QAAM,EAAE,KAAK,aAAa,gBAAgB,WAAW,cAAc,SAAS,QAAQ,IAAI;AACxF,QAAM,qBAAiB,mBAAAA,SAAY,WAAW;AAC9C,QAAM,CAAC,cAAc,eAAe,QAAI,uBAAS,KAAK;AACtD,QAAM,sBAAkB,mBAAAA,SAAY,YAAY;AAChD,QAAM,CAAC,aAAa,cAAc,QAAI,uBAAkB,KAAK;AAC7D,QAAM,mBAAe,qBAAoC,MAAS;AAElE,QAAM,cAAU,sBAAAC,SAAe,OAAO,YAAuE;AAC3G,UAAM;AAAA,MACJ,KAAK,aAAa;AAAA,MAClB,UAAU,CAAC;AAAA,MACX;AAAA;AAAA,MAEA;AAAA;AAAA,MAEA;AAAA;AAAA,MAEA;AAAA,MACA,GAAG;AAAA,IACL,IAAI,EAAE,GAAG,gBAAgB,GAAG,QAAQ;AACpC,iBAAa,UAAU,IAAI,gBAAgB;AAC3C,QAAI;AACF,sBAAgB,IAAI;AACpB,qBAAe,KAAK;AACpB,gBAAM,4CAAiB,YAAY;AAAA,QACjC,QAAQ;AAAA,QACR,QAAQ,aAAa,QAAQ;AAAA,QAC7B,gBAAgB;AAAA,QAChB,QAAQ,OAAO,aAAuB;AACpC,yBAAe,IAAI;AACnB,2CAAS;AAAA,QACX;AAAA,QACA,UAAU,OAAO;AACf,cAAI,CAAC,gBAAgB,SAAS;AAC5B,4BAAgB,KAAK;AAAA,UACvB;AACA,cAAI;AACF,gBAAI;AACJ,gBAAI,cAAc;AAChB,uBAAS,aAAa,KAAK;AAAA,YAC7B,OAAO;AACL,uBAAS,MAAM,OAAO,KAAK,MAAM,MAAM,IAAI,IAAI;AAAA,YACjD;AACA,gBAAI,UAAU,MAAM;AAClB,qDAAY;AAAA,YACd;AAAA,UACF,SAAS,OAAP;AACA,oBAAQ,MAAM,+BAA+B,KAAK;AAClD,oBAAQ,IAAI,yBAAyB,KAAK;AAAA,UAC5C;AAAA,QACF;AAAA,QACA,QAAQ,OAAO;AACb,0BAAgB,KAAK;AACrB,6CAAU;AAAA,QACZ;AAAA,QACA,UAAU;AACR,0BAAgB,KAAK;AACrB;AAAA,QACF;AAAA,QACA,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,GAAG;AAAA,QACL;AAAA,QACA,GAAG;AAAA,MACL,CAAC;AAAA,IACH,UAAE;AACA,sBAAgB,KAAK;AAAA,IACvB;AAAA,EACF,CAAC;AAED,QAAM,YAAQ,sBAAAA,SAAe,MAAM;AACjC,mBAAe,KAAK;AACpB,QAAI,eAAe,aAAa,SAAS;AACvC,mBAAa,QAAQ,MAAM;AAAA,IAC7B;AAAA,EACF,CAAC;AAED,8BAAU,MAAM;AACd,QAAI,eAAe,SAAS;AAC1B,cAAQ;AAAA,IACV;AACA,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAGL,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAO,iBAAQ;",
6
+ "names": ["useRefValue", "useRefFunction"]
7
+ }
@@ -1,3 +1,4 @@
1
+ import { type StreamTimeSlicerOptions } from '../utils/stream';
1
2
  export interface UseUserMediaProps {
2
3
  /**
3
4
  * - **EN:** The media constraints for the audio and video stream.
@@ -58,11 +59,17 @@ export interface UseUserMediaProps {
58
59
  */
59
60
  disabled?: boolean;
60
61
  /**
61
- * - **EN:** The slicing time period (milliseconds) for each fragment of the audio and video stream,
62
- * each time slice will trigger the `onStreamChunk` callback. Default is `500`.
63
- * - **CN:** 媒体流每个分片的切片时间段(毫秒),每个时间分片会触发一次 `onStreamChunk` 回调,默认值为 `500`。
62
+ * - **EN:** The slicing mode for the audio and video stream.
63
+ * - **CN:** 媒体流的切片模式。
64
64
  */
65
- streamSliceMs?: number;
65
+ streamSliceMode?: StreamTimeSlicerOptions['sliceMode'];
66
+ /**
67
+ * - **EN:** The slicing value (milliseconds or bytes) for the audio and video stream, when
68
+ * `streamSliceMode` is `time`, it represents milliseconds, and when it is `size`, it represents
69
+ * bytes.
70
+ * - **CN:** 媒体流切片的切片值(毫秒或字节),当 `streamSliceMode` 为 `time` 时表示毫秒,为 `size` 时表示字节。
71
+ */
72
+ streamSliceValue?: StreamTimeSlicerOptions['value'];
66
73
  /**
67
74
  * - **EN:** The silence detection threshold (0-1) for the audio stream, below which the audio is
68
75
  * considered silent. Default is `0`.
@@ -46,7 +46,8 @@ var useUserMedia = (props) => {
46
46
  media,
47
47
  pcmAudioOptions,
48
48
  disabled,
49
- streamSliceMs = 500,
49
+ streamSliceMode = "time",
50
+ streamSliceValue,
50
51
  soundDetectionThreshold = 0,
51
52
  soundDetectionTimeout = 3e3,
52
53
  onStartRecording,
@@ -85,7 +86,8 @@ var useUserMedia = (props) => {
85
86
  const onPcmStreamChunkRef = (0, import_useRefValue.default)(onPcmStreamChunk);
86
87
  const pcmStreamSlicerRef = (0, import_react.useRef)(
87
88
  new import_stream.StreamTimeSlicerClass({
88
- timeSlice: streamSliceMs,
89
+ sliceMode: streamSliceMode,
90
+ value: streamSliceValue || 0,
89
91
  onSlice: (channels) => {
90
92
  var _a2;
91
93
  (_a2 = onPcmStreamChunkRef.current) == null ? void 0 : _a2.call(onPcmStreamChunkRef, channels, pcmSampleRateRef.current);
@@ -138,8 +140,8 @@ var useUserMedia = (props) => {
138
140
  onStreamChunk == null ? void 0 : onStreamChunk(event.data);
139
141
  }
140
142
  };
141
- if (streamSliceMs) {
142
- recorder.start(streamSliceMs);
143
+ if (streamSliceMode === "time" && streamSliceValue) {
144
+ recorder.start(streamSliceValue);
143
145
  } else {
144
146
  recorder.start();
145
147
  }
@@ -352,10 +354,10 @@ var useUserMedia = (props) => {
352
354
  }
353
355
  }, [disabled, isRecording]);
354
356
  (0, import_react.useEffect)(() => {
355
- if (streamSliceMs && pcmStreamSlicerRef.current.timeSlice !== streamSliceMs) {
356
- pcmStreamSlicerRef.current.timeSlice = streamSliceMs;
357
+ if (streamSliceValue && pcmStreamSlicerRef.current.value !== streamSliceValue) {
358
+ pcmStreamSlicerRef.current.value = streamSliceValue;
357
359
  }
358
- }, [streamSliceMs]);
360
+ }, [streamSliceValue]);
359
361
  (0, import_react.useEffect)(() => {
360
362
  if (includeAudio && mediaStream && !isSpeakingRef.current) {
361
363
  try {