@autobe/ui 0.19.1 → 0.20.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 (92) hide show
  1. package/lib/AutoBeChatUploadSendButton.d.ts +15 -0
  2. package/lib/AutoBeChatUploadSendButton.js +38 -0
  3. package/lib/AutoBeChatUploadSendButton.js.map +1 -0
  4. package/lib/AutoBeFileUploadBox.d.ts +10 -0
  5. package/lib/AutoBeFileUploadBox.js +68 -0
  6. package/lib/AutoBeFileUploadBox.js.map +1 -0
  7. package/lib/AutoBeVoiceRecoderButton.d.ts +11 -0
  8. package/lib/AutoBeVoiceRecoderButton.js +58 -0
  9. package/lib/AutoBeVoiceRecoderButton.js.map +1 -0
  10. package/lib/events/AutoBeCompleteEventMovie.d.ts +7 -0
  11. package/lib/events/AutoBeCompleteEventMovie.js +210 -0
  12. package/lib/events/AutoBeCompleteEventMovie.js.map +1 -0
  13. package/lib/events/AutoBeProgressEventMovie.js +2 -61
  14. package/lib/events/AutoBeProgressEventMovie.js.map +1 -1
  15. package/lib/events/AutoBeScenarioEventMovie.js +2 -44
  16. package/lib/events/AutoBeScenarioEventMovie.js.map +1 -1
  17. package/lib/events/AutoBeValidateEventMovie.d.ts +6 -0
  18. package/lib/events/AutoBeValidateEventMovie.js +115 -0
  19. package/lib/events/AutoBeValidateEventMovie.js.map +1 -0
  20. package/lib/events/common/CollapsibleEventGroup.d.ts +28 -0
  21. package/lib/events/common/CollapsibleEventGroup.js +89 -0
  22. package/lib/events/common/CollapsibleEventGroup.js.map +1 -0
  23. package/lib/events/common/EventCard.d.ts +13 -0
  24. package/lib/events/common/EventCard.js +43 -0
  25. package/lib/events/common/EventCard.js.map +1 -0
  26. package/lib/events/common/EventContent.d.ts +11 -0
  27. package/lib/events/common/EventContent.js +14 -0
  28. package/lib/events/common/EventContent.js.map +1 -0
  29. package/lib/events/common/EventHeader.d.ts +15 -0
  30. package/lib/events/common/EventHeader.js +41 -0
  31. package/lib/events/common/EventHeader.js.map +1 -0
  32. package/lib/events/common/EventIcon.d.ts +11 -0
  33. package/lib/events/common/EventIcon.js +50 -0
  34. package/lib/events/common/EventIcon.js.map +1 -0
  35. package/lib/events/common/ProgressBar.d.ts +14 -0
  36. package/lib/events/common/ProgressBar.js +33 -0
  37. package/lib/events/common/ProgressBar.js.map +1 -0
  38. package/lib/events/common/index.d.ts +6 -0
  39. package/lib/events/common/index.js +16 -0
  40. package/lib/events/common/index.js.map +1 -0
  41. package/lib/events/groups/ValidateEventGroup.d.ts +12 -0
  42. package/lib/events/groups/ValidateEventGroup.js +78 -0
  43. package/lib/events/groups/ValidateEventGroup.js.map +1 -0
  44. package/lib/events/groups/index.d.ts +1 -0
  45. package/lib/events/groups/index.js +6 -0
  46. package/lib/events/groups/index.js.map +1 -0
  47. package/lib/events/index.d.ts +5 -0
  48. package/lib/events/index.js +25 -1
  49. package/lib/events/index.js.map +1 -1
  50. package/lib/events/utils/eventGrouper.d.ts +20 -0
  51. package/lib/events/utils/eventGrouper.js +74 -0
  52. package/lib/events/utils/eventGrouper.js.map +1 -0
  53. package/lib/events/utils/index.d.ts +1 -0
  54. package/lib/events/utils/index.js +6 -0
  55. package/lib/events/utils/index.js.map +1 -0
  56. package/lib/index.d.ts +3 -0
  57. package/lib/index.js +7 -1
  58. package/lib/index.js.map +1 -1
  59. package/lib/utils/AutoBeFileUploader.d.ts +28 -0
  60. package/lib/utils/AutoBeFileUploader.js +237 -0
  61. package/lib/utils/AutoBeFileUploader.js.map +1 -0
  62. package/lib/utils/AutoBeVoiceRecorder.d.ts +7 -0
  63. package/lib/utils/AutoBeVoiceRecorder.js +94 -0
  64. package/lib/utils/AutoBeVoiceRecorder.js.map +1 -0
  65. package/lib/utils/index.d.ts +3 -0
  66. package/lib/utils/index.js +20 -0
  67. package/lib/utils/index.js.map +1 -0
  68. package/package.json +17 -2
  69. package/src/AutoBeChatUploadSendButton.tsx +66 -0
  70. package/src/AutoBeFileUploadBox.tsx +124 -0
  71. package/src/AutoBeVoiceRecoderButton.tsx +100 -0
  72. package/src/events/AutoBeCompleteEventMovie.tsx +402 -0
  73. package/src/events/AutoBeProgressEventMovie.tsx +12 -125
  74. package/src/events/AutoBeScenarioEventMovie.tsx +5 -93
  75. package/src/events/AutoBeValidateEventMovie.tsx +326 -0
  76. package/src/events/README.md +169 -0
  77. package/src/events/common/CollapsibleEventGroup.tsx +220 -0
  78. package/src/events/common/EventCard.tsx +61 -0
  79. package/src/events/common/EventContent.tsx +31 -0
  80. package/src/events/common/EventHeader.tsx +85 -0
  81. package/src/events/common/EventIcon.tsx +82 -0
  82. package/src/events/common/ProgressBar.tsx +63 -0
  83. package/src/events/common/index.ts +13 -0
  84. package/src/events/groups/ValidateEventGroup.tsx +150 -0
  85. package/src/events/groups/index.ts +4 -0
  86. package/src/events/index.ts +14 -0
  87. package/src/events/utils/eventGrouper.tsx +118 -0
  88. package/src/events/utils/index.ts +1 -0
  89. package/src/index.ts +6 -0
  90. package/src/utils/AutoBeFileUploader.ts +279 -0
  91. package/src/utils/AutoBeVoiceRecorder.ts +95 -0
  92. package/src/utils/index.ts +3 -0
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.AutoBeVoiceRecorder = void 0;
13
+ const AutoBeFileUploader_1 = require("./AutoBeFileUploader");
14
+ var AutoBeVoiceRecorder;
15
+ (function (AutoBeVoiceRecorder) {
16
+ AutoBeVoiceRecorder.start = (onComplete) => __awaiter(this, void 0, void 0, function* () {
17
+ const stream = yield navigator.mediaDevices.getUserMedia({
18
+ audio: true,
19
+ });
20
+ const recorder = new MediaRecorder(stream);
21
+ const chunks = [];
22
+ recorder.ondataavailable = (event) => {
23
+ if (event.data.size > 0)
24
+ chunks.push(event.data);
25
+ };
26
+ recorder.onstop = () => __awaiter(this, void 0, void 0, function* () {
27
+ try {
28
+ const audioBlob = new Blob(chunks, { type: "audio/webm" });
29
+ const wavBlob = yield convertToWav(audioBlob);
30
+ const audioFile = new File([wavBlob], `recording-${Date.now()}.wav`, {
31
+ type: "audio/wav",
32
+ });
33
+ const base64 = yield AutoBeFileUploader_1.AutoBeFileUploader.convertToBase64(audioFile);
34
+ const content = {
35
+ type: "audio",
36
+ data: base64,
37
+ format: "wav",
38
+ };
39
+ onComplete({
40
+ file: audioFile,
41
+ content,
42
+ });
43
+ }
44
+ finally {
45
+ stream.getTracks().forEach((track) => track.stop());
46
+ }
47
+ });
48
+ return recorder;
49
+ });
50
+ })(AutoBeVoiceRecorder || (exports.AutoBeVoiceRecorder = AutoBeVoiceRecorder = {}));
51
+ const convertToWav = (audioBlob) => __awaiter(void 0, void 0, void 0, function* () {
52
+ const audioContext = new AudioContext();
53
+ const arrayBuffer = yield audioBlob.arrayBuffer();
54
+ const audioBuffer = yield audioContext.decodeAudioData(arrayBuffer);
55
+ // Create WAV file
56
+ const length = audioBuffer.length;
57
+ const sampleRate = audioBuffer.sampleRate;
58
+ const numberOfChannels = audioBuffer.numberOfChannels;
59
+ // Calculate WAV file size
60
+ const wavLength = 44 + length * numberOfChannels * 2;
61
+ const buffer = new ArrayBuffer(wavLength);
62
+ const view = new DataView(buffer);
63
+ // WAV file header
64
+ const writeString = (offset, string) => {
65
+ for (let i = 0; i < string.length; i++) {
66
+ view.setUint8(offset + i, string.charCodeAt(i));
67
+ }
68
+ };
69
+ writeString(0, "RIFF");
70
+ view.setUint32(4, wavLength - 8, true);
71
+ writeString(8, "WAVE");
72
+ writeString(12, "fmt ");
73
+ view.setUint32(16, 16, true); // fmt chunk size
74
+ view.setUint16(20, 1, true); // PCM format
75
+ view.setUint16(22, numberOfChannels, true);
76
+ view.setUint32(24, sampleRate, true);
77
+ view.setUint32(28, sampleRate * numberOfChannels * 2, true); // byte rate
78
+ view.setUint16(32, numberOfChannels * 2, true); // block align
79
+ view.setUint16(34, 16, true); // bits per sample
80
+ writeString(36, "data");
81
+ view.setUint32(40, length * numberOfChannels * 2, true);
82
+ // Write audio data
83
+ let offset = 44;
84
+ for (let i = 0; i < length; i++) {
85
+ for (let channel = 0; channel < numberOfChannels; channel++) {
86
+ const sample = audioBuffer.getChannelData(channel)[i];
87
+ const value = Math.max(-1, Math.min(1, sample));
88
+ view.setInt16(offset, value * 0x7fff, true);
89
+ offset += 2;
90
+ }
91
+ }
92
+ return new Blob([buffer], { type: "audio/wav" });
93
+ });
94
+ //# sourceMappingURL=AutoBeVoiceRecorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AutoBeVoiceRecorder.js","sourceRoot":"","sources":["../../src/utils/AutoBeVoiceRecorder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * from "./AutoBeFileUploader";
2
+ export * from "./AutoBeVoiceRecorder";
3
+ export * from "./time";
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./AutoBeFileUploader"), exports);
18
+ __exportStar(require("./AutoBeVoiceRecorder"), exports);
19
+ __exportStar(require("./time"), exports);
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,uDAAqC;AACrC,wDAAsC;AACtC,yCAAuB"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@autobe/ui",
3
3
  "type": "commonjs",
4
- "version": "0.19.1",
4
+ "version": "0.20.0",
5
5
  "description": "AutoBE UI",
6
6
  "author": "Wrtn Technologies",
7
7
  "homepage": "https://wrtnlabs.io/autobe",
@@ -13,13 +13,28 @@
13
13
  "url": "https://github.com/wrtnlabs/autobe/issues"
14
14
  },
15
15
  "main": "lib/index.js",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./src/index.ts",
19
+ "import": "./src/index.ts"
20
+ },
21
+ "./utils": {
22
+ "types": "./src/utils/index.ts",
23
+ "import": "./src/utils/index.ts"
24
+ }
25
+ },
16
26
  "devDependencies": {
17
27
  "@types/react": "^19.1.10",
18
28
  "@types/react-dom": "^19.1.5",
19
29
  "react": "^19.1.1",
20
30
  "react-dom": "^19.1.1",
21
31
  "typescript": "~5.9.2",
22
- "@autobe/interface": "0.19.1"
32
+ "@autobe/interface": "0.20.0"
33
+ },
34
+ "dependencies": {
35
+ "@stackblitz/sdk": "^1.11.0",
36
+ "jszip": "^3.10.1",
37
+ "tstl": "^3.0.0"
23
38
  },
24
39
  "scripts": {
25
40
  "build": "tsc",
@@ -0,0 +1,66 @@
1
+ /** Props interface for AutoBeChatUploadSendButton component */
2
+ interface IAutoBeChatUploadSendButtonProps {
3
+ /** Function to trigger conversation */
4
+ onClick?: (event: React.MouseEvent<HTMLButtonElement>) => Promise<void>;
5
+ /** Whether the button is enabled */
6
+ enabled: boolean;
7
+ }
8
+
9
+ /**
10
+ * Chat upload send button component for triggering conversations
11
+ *
12
+ * @param props - Component props
13
+ * @returns JSX element representing the send button
14
+ */
15
+ export const AutoBeChatUploadSendButton = (
16
+ props: IAutoBeChatUploadSendButtonProps,
17
+ ) => {
18
+ const baseStyles: React.CSSProperties = {
19
+ padding: "6px",
20
+ border: "none",
21
+ borderRadius: "50%", // 4px에서 50%로 변경하여 둥글게
22
+ backgroundColor: props.enabled ? "#1976d2" : "#e0e0e0",
23
+ color: props.enabled ? "#ffffff" : "#9e9e9e",
24
+ cursor: props.enabled ? "pointer" : "not-allowed",
25
+ display: "inline-flex",
26
+ alignItems: "center",
27
+ justifyContent: "center",
28
+ transition: "background-color 0.3s ease",
29
+ outline: "none",
30
+ width: "32px",
31
+ height: "32px",
32
+ };
33
+
34
+ const hoverStyles: React.CSSProperties = {
35
+ ...baseStyles,
36
+ backgroundColor: props.enabled ? "#1565c0" : "#e0e0e0",
37
+ };
38
+
39
+ return (
40
+ <button
41
+ style={baseStyles}
42
+ onClick={(e) => void props.onClick?.(e)}
43
+ disabled={!props.enabled}
44
+ onMouseEnter={(e) => {
45
+ if (props.enabled) {
46
+ Object.assign(e.currentTarget.style, hoverStyles);
47
+ }
48
+ }}
49
+ onMouseLeave={(e) => {
50
+ Object.assign(e.currentTarget.style, baseStyles);
51
+ }}
52
+ >
53
+ <svg
54
+ width="16"
55
+ height="16"
56
+ viewBox="0 0 24 24"
57
+ fill="currentColor"
58
+ style={{ display: "block" }}
59
+ >
60
+ <path d="M4 12l1.41 1.41L11 7.83V20h2V7.83l5.59 5.58L20 12l-8-8-8 8z" />
61
+ </svg>
62
+ </button>
63
+ );
64
+ };
65
+
66
+ export default AutoBeChatUploadSendButton;
@@ -0,0 +1,124 @@
1
+ import { ReactNode, useState } from "react";
2
+
3
+ export const AutoBeFileUploadBox = (props: AutoBeFileUploadBox.IProps) => {
4
+ const [isHovered, setIsHovered] = useState(false);
5
+
6
+ const hasError = !!props.extensionError;
7
+
8
+ const getButtonStyles = () => {
9
+ const baseStyles = {
10
+ display: "inline-flex",
11
+ alignItems: "center",
12
+ justifyContent: "center",
13
+ width: "40px",
14
+ height: "40px",
15
+ padding: "0",
16
+ border: "1px solid",
17
+ borderRadius: "50%",
18
+ cursor: props.enabled ? "pointer" : "not-allowed",
19
+ backgroundColor: hasError ? "#fef2f2" : "transparent",
20
+ borderColor: hasError ? "#f87171" : isHovered ? "#3b82f6" : "#d1d5db",
21
+ opacity: props.enabled ? 1 : 0.5,
22
+ transition: "all 0.3s ease",
23
+ position: "relative" as const,
24
+ };
25
+
26
+ if (isHovered && props.enabled) {
27
+ return {
28
+ ...baseStyles,
29
+ backgroundColor: hasError ? "#fef2f2" : "#f3f4f6",
30
+ borderColor: hasError ? "#f87171" : "#3b82f6",
31
+ };
32
+ }
33
+
34
+ return baseStyles;
35
+ };
36
+
37
+ const iconColor = hasError ? "#ef4444" : "#6b7280";
38
+
39
+ return (
40
+ <div style={{ position: "relative", display: "inline-block" }}>
41
+ <button
42
+ onClick={props.onClick}
43
+ disabled={!props.enabled}
44
+ style={getButtonStyles()}
45
+ onMouseEnter={() => {
46
+ setIsHovered(true);
47
+ }}
48
+ onMouseLeave={() => {
49
+ setIsHovered(false);
50
+ }}
51
+ >
52
+ {hasError ? (
53
+ // Error Icon (SVG)
54
+ <svg
55
+ width="20"
56
+ height="20"
57
+ viewBox="0 0 24 24"
58
+ fill="currentColor"
59
+ style={{ color: iconColor }}
60
+ >
61
+ <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z" />
62
+ </svg>
63
+ ) : (
64
+ // Add Icon (SVG)
65
+ <svg
66
+ width="20"
67
+ height="20"
68
+ viewBox="0 0 24 24"
69
+ fill="currentColor"
70
+ style={{ color: iconColor }}
71
+ >
72
+ <path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
73
+ </svg>
74
+ )}
75
+ </button>
76
+
77
+ {/* Custom Tooltip - Always show when there's an error */}
78
+ {hasError && (
79
+ <div
80
+ style={{
81
+ position: "absolute",
82
+ bottom: "100%",
83
+ left: "50%",
84
+ transform: "translateX(-50%)",
85
+ marginBottom: "8px",
86
+ padding: "8px 12px",
87
+ backgroundColor: "#ef4444",
88
+ color: "#ffffff",
89
+ borderRadius: "6px",
90
+ fontSize: "14px",
91
+ whiteSpace: "nowrap",
92
+ zIndex: 1000,
93
+ boxShadow: "0 2px 8px rgba(0, 0, 0, 0.15)",
94
+ }}
95
+ >
96
+ {props.extensionError}
97
+ {/* Tooltip Arrow */}
98
+ <div
99
+ style={{
100
+ position: "absolute",
101
+ top: "100%",
102
+ left: "50%",
103
+ transform: "translateX(-50%)",
104
+ width: 0,
105
+ height: 0,
106
+ borderLeft: "6px solid transparent",
107
+ borderRight: "6px solid transparent",
108
+ borderTop: "6px solid #ef4444",
109
+ }}
110
+ />
111
+ </div>
112
+ )}
113
+ </div>
114
+ );
115
+ };
116
+
117
+ export default AutoBeFileUploadBox;
118
+ export namespace AutoBeFileUploadBox {
119
+ export interface IProps {
120
+ extensionError: ReactNode | null;
121
+ onClick: () => void;
122
+ enabled: boolean;
123
+ }
124
+ }
@@ -0,0 +1,100 @@
1
+ import { AutoBeUserMessageAudioContent } from "@autobe/interface";
2
+ import { useState } from "react";
3
+
4
+ import { AutoBeVoiceRecorder } from "./utils/AutoBeVoiceRecorder";
5
+
6
+ export const AutoBeVoiceRecoderButton = (
7
+ props: AutoBeVoiceRecoderButton.IProps,
8
+ ) => {
9
+ const [isRecording, setIsRecording] = useState(false);
10
+ const [mediaRecorder, setMediaRecorder] = useState<MediaRecorder | null>(
11
+ null,
12
+ );
13
+
14
+ const startRecording = async () => {
15
+ const recorder = await AutoBeVoiceRecorder.start(props.onComplete);
16
+ recorder.start();
17
+ setMediaRecorder(recorder);
18
+ setIsRecording(true);
19
+ };
20
+
21
+ const stopRecording = () => {
22
+ if (mediaRecorder && mediaRecorder.state !== "inactive") {
23
+ mediaRecorder.stop();
24
+ setIsRecording(false);
25
+ }
26
+ };
27
+
28
+ const baseStyles: React.CSSProperties = {
29
+ padding: "6px",
30
+ border: "1px solid",
31
+ borderColor: isRecording ? "#f44336" : "#e0e0e0",
32
+ borderRadius: "4px",
33
+ backgroundColor: isRecording ? "#ffebee" : "transparent",
34
+ color: isRecording ? "#f44336" : "#1976d2",
35
+ cursor: props.enabled ? "pointer" : "not-allowed",
36
+ display: "inline-flex",
37
+ alignItems: "center",
38
+ justifyContent: "center",
39
+ transition: "all 0.3s ease",
40
+ outline: "none",
41
+ width: "32px",
42
+ height: "32px",
43
+ opacity: props.enabled ? 1 : 0.5,
44
+ };
45
+
46
+ const hoverStyles: React.CSSProperties = {
47
+ ...baseStyles,
48
+ backgroundColor: isRecording ? "#f44336" : "#f5f5f5",
49
+ borderColor: isRecording ? "#d32f2f" : "#1976d2",
50
+ color: isRecording ? "#ffffff" : "#1976d2",
51
+ };
52
+
53
+ return (
54
+ <button
55
+ style={baseStyles}
56
+ onClick={isRecording ? stopRecording : () => void startRecording()}
57
+ disabled={!props.enabled}
58
+ onMouseEnter={(e) => {
59
+ if (props.enabled) {
60
+ Object.assign(e.currentTarget.style, hoverStyles);
61
+ }
62
+ }}
63
+ onMouseLeave={(e) => {
64
+ Object.assign(e.currentTarget.style, baseStyles);
65
+ }}
66
+ >
67
+ {isRecording ? (
68
+ <svg
69
+ width="16"
70
+ height="16"
71
+ viewBox="0 0 24 24"
72
+ fill="currentColor"
73
+ style={{ display: "block" }}
74
+ >
75
+ <path d="M6 6h12v12H6z" />
76
+ </svg>
77
+ ) : (
78
+ <svg
79
+ width="16"
80
+ height="16"
81
+ viewBox="0 0 24 24"
82
+ fill="currentColor"
83
+ style={{ display: "block" }}
84
+ >
85
+ <path d="M12 2c1.1 0 2 .9 2 2v6c0 1.1-.9 2-2 2s-2-.9-2-2V4c0-1.1.9-2 2-2zm5.3 6.7c.4-.4 1-.4 1.4 0 .4.4.4 1 0 1.4l-1.9 1.9c.03.33.05.66.05 1v.5c0 2.8-2.2 5-5 5s-5-2.2-5-5v-.5c0-.34.02-.67.05-1L4.9 10.1c-.4-.4-.4-1 0-1.4.4-.4 1-.4 1.4 0l1.9 1.9c1.8-1.6 4.3-1.6 6.1 0l1.9-1.9zM19 10.5v.5c0 3.9-3.1 7-7 7s-7-3.1-7-7v-.5c0-.8.7-1.5 1.5-1.5s1.5.7 1.5 1.5v.5c0 2.2 1.8 4 4 4s4-1.8 4-4v-.5c0-.8.7-1.5 1.5-1.5s1.5.7 1.5 1.5z" />
86
+ </svg>
87
+ )}
88
+ </button>
89
+ );
90
+ };
91
+
92
+ export namespace AutoBeVoiceRecoderButton {
93
+ export interface IProps {
94
+ enabled: boolean;
95
+ onComplete: (content: {
96
+ file: File;
97
+ content: AutoBeUserMessageAudioContent;
98
+ }) => void;
99
+ }
100
+ }