@archbase/components 3.0.25 → 4.0.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.
Files changed (168) hide show
  1. package/dist/buttons/ArchbaseSpeedDial.d.ts +59 -0
  2. package/dist/buttons/index.d.ts +2 -0
  3. package/dist/charts/ArchbaseArcGauge.d.ts +55 -0
  4. package/dist/charts/ArchbaseGantt.d.ts +70 -0
  5. package/dist/charts/ArchbaseLinearGauge.d.ts +55 -0
  6. package/dist/charts/ArchbaseResourceTimeline.d.ts +61 -0
  7. package/dist/charts/ArchbaseSparkline.d.ts +45 -0
  8. package/dist/charts/index.d.ts +10 -0
  9. package/dist/containers/ArchbaseExpansionPanel.d.ts +60 -0
  10. package/dist/containers/ArchbaseFloatingPanel.d.ts +91 -0
  11. package/dist/containers/index.d.ts +4 -0
  12. package/dist/datagrid/export/ArchbaseDataGridExcelExport.d.ts +67 -0
  13. package/dist/datagrid/export/index.d.ts +2 -0
  14. package/dist/datagrid/index.d.ts +1 -0
  15. package/dist/display/ArchbaseAnimationWrapper.d.ts +73 -0
  16. package/dist/display/ArchbaseBarcodeGenerator.d.ts +50 -0
  17. package/dist/display/ArchbaseCarousel.d.ts +100 -0
  18. package/dist/display/ArchbaseCodeViewer.d.ts +63 -0
  19. package/dist/display/ArchbaseDiffViewer.d.ts +41 -0
  20. package/dist/display/ArchbaseJsonTree.d.ts +34 -0
  21. package/dist/display/ArchbaseLightbox.d.ts +89 -0
  22. package/dist/display/ArchbaseMarquee.d.ts +46 -0
  23. package/dist/display/ArchbasePhotoAlbum.d.ts +58 -0
  24. package/dist/display/ArchbaseQRCode.d.ts +44 -0
  25. package/dist/display/ArchbaseTooltipRich.d.ts +82 -0
  26. package/dist/display/ArchbaseVirtualList.d.ts +116 -0
  27. package/dist/display/index.d.ts +24 -0
  28. package/dist/editors/ArchbaseAIPromptInput.d.ts +69 -0
  29. package/dist/editors/ArchbaseAsyncMultiSelect.d.ts +1 -1
  30. package/dist/editors/ArchbaseAsyncSelect.d.ts +1 -1
  31. package/dist/editors/ArchbaseBarcodeScanner.d.ts +63 -0
  32. package/dist/editors/ArchbaseCepInput.d.ts +26 -0
  33. package/dist/editors/ArchbaseColorGradientPicker.d.ts +80 -0
  34. package/dist/editors/ArchbaseCpfCnpjInput.d.ts +21 -0
  35. package/dist/editors/ArchbaseCurrencyInput.d.ts +25 -0
  36. package/dist/editors/ArchbaseDualListbox.d.ts +61 -0
  37. package/dist/editors/ArchbaseInPlaceEditor.d.ts +67 -0
  38. package/dist/editors/ArchbaseLightGrid.d.ts +56 -0
  39. package/dist/editors/ArchbaseMentionInput.d.ts +75 -0
  40. package/dist/editors/ArchbaseMultiEmail.d.ts +53 -0
  41. package/dist/editors/ArchbaseMultiViewCalendar.d.ts +47 -0
  42. package/dist/editors/ArchbaseNumberStepper.d.ts +66 -0
  43. package/dist/editors/ArchbaseOTPInput.d.ts +27 -0
  44. package/dist/editors/ArchbasePhoneInput.d.ts +52 -0
  45. package/dist/editors/ArchbaseRangeSlider.d.ts +22 -0
  46. package/dist/editors/ArchbaseSignaturePad.d.ts +60 -0
  47. package/dist/editors/ArchbaseSpeechToTextInput.d.ts +106 -0
  48. package/dist/editors/ArchbaseSpreadsheet.d.ts +56 -0
  49. package/dist/editors/ArchbaseTagInput.d.ts +55 -0
  50. package/dist/editors/index.d.ts +40 -0
  51. package/dist/feedback/ArchbaseChunkProgressBar.d.ts +35 -0
  52. package/dist/feedback/ArchbaseRipple.d.ts +43 -0
  53. package/dist/feedback/ArchbaseSkeleton.d.ts +115 -0
  54. package/dist/feedback/index.d.ts +6 -0
  55. package/dist/filters/ArchbaseColumnSelector.d.ts +38 -0
  56. package/dist/filters/index.d.ts +2 -0
  57. package/dist/forms/ArchbaseFieldArray.d.ts +80 -0
  58. package/dist/forms/ArchbaseFormWizard.d.ts +73 -0
  59. package/dist/forms/ArchbaseStepper.d.ts +51 -0
  60. package/dist/forms/index.d.ts +8 -0
  61. package/dist/forms/useArchbaseFormWizard.d.ts +74 -0
  62. package/dist/hooks/index.d.ts +2 -0
  63. package/dist/hooks/useArchbaseConfirm.d.ts +59 -0
  64. package/dist/image/editor/index.d.ts +43 -4
  65. package/dist/image/index.d.ts +1 -0
  66. package/dist/index.css +1 -1
  67. package/dist/index.d.ts +1 -0
  68. package/dist/index.js +22510 -13820
  69. package/dist/list/ArchbaseTreeList.d.ts +76 -0
  70. package/dist/list/index.d.ts +2 -0
  71. package/dist/navigation/ArchbaseActionSheet.d.ts +70 -0
  72. package/dist/navigation/ArchbaseAppBar.d.ts +63 -0
  73. package/dist/navigation/ArchbaseBottomNavigation.d.ts +61 -0
  74. package/dist/navigation/ArchbaseContextMenu.d.ts +76 -0
  75. package/dist/navigation/ArchbaseKeyboardShortcuts.d.ts +85 -0
  76. package/dist/navigation/ArchbaseSpotlight.d.ts +69 -0
  77. package/dist/navigation/index.d.ts +12 -0
  78. package/dist/notification/ArchbaseNotificationCenter.d.ts +56 -0
  79. package/dist/notification/index.d.ts +2 -0
  80. package/dist/onboarding/ArchbaseOnboardingTour.d.ts +27 -76
  81. package/dist/viewers/ArchbaseDocViewer.d.ts +40 -0
  82. package/dist/viewers/ArchbasePdfBuilder.d.ts +53 -0
  83. package/dist/viewers/ArchbaseXmlViewer.d.ts +36 -0
  84. package/dist/viewers/index.d.ts +6 -0
  85. package/package.json +41 -18
  86. package/src/buttons/ArchbaseSpeedDial.tsx +282 -0
  87. package/src/buttons/index.ts +3 -0
  88. package/src/charts/ArchbaseArcGauge.tsx +325 -0
  89. package/src/charts/ArchbaseGantt.tsx +494 -0
  90. package/src/charts/ArchbaseLinearGauge.tsx +288 -0
  91. package/src/charts/ArchbaseResourceTimeline.tsx +433 -0
  92. package/src/charts/ArchbaseSparkline.tsx +193 -0
  93. package/src/charts/index.ts +20 -1
  94. package/src/containers/ArchbaseExpansionPanel.tsx +208 -0
  95. package/src/containers/ArchbaseFloatingPanel.tsx +448 -0
  96. package/src/containers/index.ts +17 -0
  97. package/src/datagrid/components/pagination/grid-pagination.tsx +2 -2
  98. package/src/datagrid/export/ArchbaseDataGridExcelExport.tsx +293 -0
  99. package/src/datagrid/export/index.ts +8 -0
  100. package/src/datagrid/index.tsx +2 -0
  101. package/src/display/ArchbaseAnimationWrapper.tsx +272 -0
  102. package/src/display/ArchbaseBarcodeGenerator.tsx +303 -0
  103. package/src/display/ArchbaseCarousel.tsx +679 -0
  104. package/src/display/ArchbaseCodeViewer.tsx +271 -0
  105. package/src/display/ArchbaseDiffViewer.tsx +108 -0
  106. package/src/display/ArchbaseJsonTree.tsx +150 -0
  107. package/src/display/ArchbaseLightbox.tsx +279 -0
  108. package/src/display/ArchbaseMarquee.tsx +268 -0
  109. package/src/display/ArchbasePhotoAlbum.tsx +415 -0
  110. package/src/display/ArchbaseQRCode.tsx +137 -0
  111. package/src/display/ArchbaseTooltipRich.tsx +317 -0
  112. package/src/display/ArchbaseVirtualList.tsx +618 -0
  113. package/src/display/index.ts +94 -1
  114. package/src/editors/ArchbaseAIPromptInput.tsx +432 -0
  115. package/src/editors/ArchbaseBarcodeScanner.tsx +570 -0
  116. package/src/editors/ArchbaseCepInput.tsx +173 -0
  117. package/src/editors/ArchbaseColorGradientPicker.tsx +460 -0
  118. package/src/editors/ArchbaseCpfCnpjInput.tsx +193 -0
  119. package/src/editors/ArchbaseCurrencyInput.tsx +100 -0
  120. package/src/editors/ArchbaseDualListbox.tsx +671 -0
  121. package/src/editors/ArchbaseInPlaceEditor.tsx +406 -0
  122. package/src/editors/ArchbaseLightGrid.tsx +538 -0
  123. package/src/editors/ArchbaseMentionInput.tsx +384 -0
  124. package/src/editors/ArchbaseMultiEmail.tsx +367 -0
  125. package/src/editors/ArchbaseMultiViewCalendar.tsx +439 -0
  126. package/src/editors/ArchbaseNumberStepper.tsx +219 -0
  127. package/src/editors/ArchbaseOTPInput.tsx +133 -0
  128. package/src/editors/ArchbaseOperationHoursEditor.tsx +1 -1
  129. package/src/editors/ArchbasePhoneInput.tsx +355 -0
  130. package/src/editors/ArchbaseRangeSlider.tsx +109 -0
  131. package/src/editors/ArchbaseSignaturePad.tsx +425 -0
  132. package/src/editors/ArchbaseSpeechToTextInput.tsx +444 -0
  133. package/src/editors/ArchbaseSpreadsheet.tsx +388 -0
  134. package/src/editors/ArchbaseTagInput.tsx +326 -0
  135. package/src/editors/index.tsx +92 -0
  136. package/src/feedback/ArchbaseChunkProgressBar.tsx +156 -0
  137. package/src/feedback/ArchbaseRipple.tsx +278 -0
  138. package/src/feedback/ArchbaseSkeleton.tsx +419 -0
  139. package/src/feedback/index.ts +22 -1
  140. package/src/filters/ArchbaseColumnSelector.tsx +268 -0
  141. package/src/filters/index.ts +2 -0
  142. package/src/forms/ArchbaseFieldArray.tsx +305 -0
  143. package/src/forms/ArchbaseFormWizard.tsx +284 -0
  144. package/src/forms/ArchbaseStepper.tsx +137 -0
  145. package/src/forms/index.ts +24 -2
  146. package/src/forms/useArchbaseFormWizard.ts +283 -0
  147. package/src/hooks/index.ts +12 -0
  148. package/src/hooks/useArchbaseConfirm.ts +293 -0
  149. package/src/image/editor/functions/image-processing.ts +5 -0
  150. package/src/image/editor/index.tsx +305 -391
  151. package/src/image/index.ts +1 -0
  152. package/src/index.ts +3 -0
  153. package/src/list/ArchbaseTreeList.tsx +422 -0
  154. package/src/list/index.ts +3 -0
  155. package/src/navigation/ArchbaseActionSheet.tsx +301 -0
  156. package/src/navigation/ArchbaseAppBar.tsx +233 -0
  157. package/src/navigation/ArchbaseBottomNavigation.tsx +243 -0
  158. package/src/navigation/ArchbaseContextMenu.tsx +298 -0
  159. package/src/navigation/ArchbaseKeyboardShortcuts.tsx +472 -0
  160. package/src/navigation/ArchbaseSpotlight.tsx +483 -0
  161. package/src/navigation/index.ts +48 -1
  162. package/src/notification/ArchbaseNotificationCenter.tsx +502 -0
  163. package/src/notification/index.ts +2 -0
  164. package/src/onboarding/ArchbaseOnboardingTour.tsx +229 -102
  165. package/src/viewers/ArchbaseDocViewer.tsx +584 -0
  166. package/src/viewers/ArchbasePdfBuilder.tsx +291 -0
  167. package/src/viewers/ArchbaseXmlViewer.tsx +142 -0
  168. package/src/viewers/index.ts +12 -0
@@ -0,0 +1,444 @@
1
+ import React, { useCallback, useState, useEffect, useRef } from 'react';
2
+ import {
3
+ TextInput,
4
+ TextInputProps,
5
+ Textarea,
6
+ TextareaProps,
7
+ ActionIcon,
8
+ Tooltip,
9
+ Box,
10
+ Text,
11
+ Loader,
12
+ } from '@mantine/core';
13
+ import { IconMicrophone, IconMicrophoneOff, IconPlayerStop } from '@tabler/icons-react';
14
+
15
+ // =============================================================================
16
+ // Types
17
+ // =============================================================================
18
+
19
+ interface SpeechRecognitionEvent {
20
+ resultIndex: number;
21
+ results: SpeechRecognitionResultList;
22
+ }
23
+
24
+ interface SpeechRecognitionErrorEvent {
25
+ error: string;
26
+ message: string;
27
+ }
28
+
29
+ interface SpeechRecognition extends EventTarget {
30
+ continuous: boolean;
31
+ interimResults: boolean;
32
+ lang: string;
33
+ start: () => void;
34
+ stop: () => void;
35
+ abort: () => void;
36
+ onresult: ((event: SpeechRecognitionEvent) => void) | null;
37
+ onerror: ((event: SpeechRecognitionErrorEvent) => void) | null;
38
+ onend: (() => void) | null;
39
+ onstart: (() => void) | null;
40
+ }
41
+
42
+ declare global {
43
+ interface Window {
44
+ SpeechRecognition: new () => SpeechRecognition;
45
+ webkitSpeechRecognition: new () => SpeechRecognition;
46
+ }
47
+ }
48
+
49
+ export interface UseArchbaseSpeechToTextOptions {
50
+ /** Idioma (padrão: pt-BR) */
51
+ lang?: string;
52
+ /** Modo contínuo */
53
+ continuous?: boolean;
54
+ /** Resultados intermediários */
55
+ interimResults?: boolean;
56
+ /** Callback ao obter transcrição */
57
+ onTranscript?: (transcript: string, isFinal: boolean) => void;
58
+ /** Callback em caso de erro */
59
+ onError?: (error: string) => void;
60
+ /** Callback ao iniciar */
61
+ onStart?: () => void;
62
+ /** Callback ao parar */
63
+ onEnd?: () => void;
64
+ }
65
+
66
+ export interface UseArchbaseSpeechToTextReturn {
67
+ /** Se está gravando */
68
+ isListening: boolean;
69
+ /** Transcrição atual */
70
+ transcript: string;
71
+ /** Se o browser suporta */
72
+ isSupported: boolean;
73
+ /** Último erro */
74
+ error: string | null;
75
+ /** Iniciar gravação */
76
+ start: () => void;
77
+ /** Parar gravação */
78
+ stop: () => void;
79
+ /** Limpar transcrição */
80
+ clear: () => void;
81
+ }
82
+
83
+ // =============================================================================
84
+ // Hook useArchbaseSpeechToText
85
+ // =============================================================================
86
+
87
+ export function useArchbaseSpeechToText({
88
+ lang = 'pt-BR',
89
+ continuous = false,
90
+ interimResults = true,
91
+ onTranscript,
92
+ onError,
93
+ onStart,
94
+ onEnd,
95
+ }: UseArchbaseSpeechToTextOptions = {}): UseArchbaseSpeechToTextReturn {
96
+ const [isListening, setIsListening] = useState(false);
97
+ const [transcript, setTranscript] = useState('');
98
+ const [error, setError] = useState<string | null>(null);
99
+ const recognitionRef = useRef<SpeechRecognition | null>(null);
100
+
101
+ const isSupported = typeof window !== 'undefined' &&
102
+ (!!window.SpeechRecognition || !!window.webkitSpeechRecognition);
103
+
104
+ useEffect(() => {
105
+ if (!isSupported) return;
106
+
107
+ const SpeechRecognitionClass = window.SpeechRecognition || window.webkitSpeechRecognition;
108
+ const recognition = new SpeechRecognitionClass();
109
+
110
+ recognition.continuous = continuous;
111
+ recognition.interimResults = interimResults;
112
+ recognition.lang = lang;
113
+
114
+ recognition.onresult = (event: SpeechRecognitionEvent) => {
115
+ let finalTranscript = '';
116
+ let interimTranscript = '';
117
+
118
+ for (let i = event.resultIndex; i < event.results.length; i++) {
119
+ const result = event.results[i];
120
+ if (result.isFinal) {
121
+ finalTranscript += result[0].transcript;
122
+ } else {
123
+ interimTranscript += result[0].transcript;
124
+ }
125
+ }
126
+
127
+ const currentTranscript = finalTranscript || interimTranscript;
128
+ setTranscript(prev => finalTranscript ? prev + finalTranscript : prev);
129
+ onTranscript?.(currentTranscript, !!finalTranscript);
130
+ };
131
+
132
+ recognition.onerror = (event: SpeechRecognitionErrorEvent) => {
133
+ const errorMessage = getErrorMessage(event.error);
134
+ setError(errorMessage);
135
+ onError?.(errorMessage);
136
+ setIsListening(false);
137
+ };
138
+
139
+ recognition.onend = () => {
140
+ setIsListening(false);
141
+ onEnd?.();
142
+ };
143
+
144
+ recognition.onstart = () => {
145
+ setIsListening(true);
146
+ setError(null);
147
+ onStart?.();
148
+ };
149
+
150
+ recognitionRef.current = recognition;
151
+
152
+ return () => {
153
+ recognition.abort();
154
+ };
155
+ }, [lang, continuous, interimResults, onTranscript, onError, onStart, onEnd, isSupported]);
156
+
157
+ const start = useCallback(() => {
158
+ if (!recognitionRef.current || isListening) return;
159
+ setTranscript('');
160
+ setError(null);
161
+ try {
162
+ recognitionRef.current.start();
163
+ } catch (e) {
164
+ // Already started
165
+ }
166
+ }, [isListening]);
167
+
168
+ const stop = useCallback(() => {
169
+ if (!recognitionRef.current || !isListening) return;
170
+ recognitionRef.current.stop();
171
+ }, [isListening]);
172
+
173
+ const clear = useCallback(() => {
174
+ setTranscript('');
175
+ setError(null);
176
+ }, []);
177
+
178
+ return {
179
+ isListening,
180
+ transcript,
181
+ isSupported,
182
+ error,
183
+ start,
184
+ stop,
185
+ clear,
186
+ };
187
+ }
188
+
189
+ function getErrorMessage(error: string): string {
190
+ const messages: Record<string, string> = {
191
+ 'no-speech': 'Nenhuma fala detectada',
192
+ 'audio-capture': 'Microfone não disponível',
193
+ 'not-allowed': 'Permissão de microfone negada',
194
+ 'network': 'Erro de conexão',
195
+ 'aborted': 'Gravação cancelada',
196
+ 'language-not-supported': 'Idioma não suportado',
197
+ 'service-not-allowed': 'Serviço não permitido',
198
+ };
199
+ return messages[error] || `Erro: ${error}`;
200
+ }
201
+
202
+ // =============================================================================
203
+ // ArchbaseSpeechToTextButton Component
204
+ // =============================================================================
205
+
206
+ export interface ArchbaseSpeechToTextButtonProps {
207
+ /** Callback ao obter transcrição */
208
+ onTranscript: (transcript: string) => void;
209
+ /** Idioma (padrão: pt-BR) */
210
+ lang?: string;
211
+ /** Modo contínuo */
212
+ continuous?: boolean;
213
+ /** Desabilitado */
214
+ disabled?: boolean;
215
+ /** Tamanho do botão */
216
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
217
+ /** Cor */
218
+ color?: string;
219
+ /** Tooltip quando desabilitado/não suportado */
220
+ unsupportedTooltip?: string;
221
+ }
222
+
223
+ export function ArchbaseSpeechToTextButton({
224
+ onTranscript,
225
+ lang = 'pt-BR',
226
+ continuous = false,
227
+ disabled = false,
228
+ size = 'md',
229
+ color = 'blue',
230
+ unsupportedTooltip = 'Reconhecimento de voz não suportado neste navegador',
231
+ }: ArchbaseSpeechToTextButtonProps) {
232
+ const {
233
+ isListening,
234
+ isSupported,
235
+ error,
236
+ start,
237
+ stop,
238
+ } = useArchbaseSpeechToText({
239
+ lang,
240
+ continuous,
241
+ onTranscript: (text, isFinal) => {
242
+ if (isFinal) {
243
+ onTranscript(text);
244
+ }
245
+ },
246
+ });
247
+
248
+ const handleClick = useCallback(() => {
249
+ if (isListening) {
250
+ stop();
251
+ } else {
252
+ start();
253
+ }
254
+ }, [isListening, start, stop]);
255
+
256
+ if (!isSupported) {
257
+ return (
258
+ <Tooltip label={unsupportedTooltip}>
259
+ <ActionIcon
260
+ variant="light"
261
+ color="gray"
262
+ size={size}
263
+ disabled
264
+ >
265
+ <IconMicrophoneOff size={16} />
266
+ </ActionIcon>
267
+ </Tooltip>
268
+ );
269
+ }
270
+
271
+ return (
272
+ <Tooltip label={isListening ? 'Parar gravação' : 'Gravar voz'}>
273
+ <ActionIcon
274
+ variant={isListening ? 'filled' : 'light'}
275
+ color={isListening ? 'red' : color}
276
+ size={size}
277
+ disabled={disabled}
278
+ onClick={handleClick}
279
+ style={{
280
+ animation: isListening ? 'pulse 1.5s infinite' : undefined,
281
+ }}
282
+ >
283
+ {isListening ? <IconPlayerStop size={16} /> : <IconMicrophone size={16} />}
284
+ </ActionIcon>
285
+ </Tooltip>
286
+ );
287
+ }
288
+
289
+ // =============================================================================
290
+ // ArchbaseSpeechToTextInput Component
291
+ // =============================================================================
292
+
293
+ export interface ArchbaseSpeechToTextInputProps extends Omit<TextInputProps, 'value' | 'onChange'> {
294
+ /** Valor atual */
295
+ value?: string;
296
+ /** Callback ao mudar */
297
+ onChange?: (value: string) => void;
298
+ /** Idioma (padrão: pt-BR) */
299
+ lang?: string;
300
+ /** Modo contínuo */
301
+ continuous?: boolean;
302
+ /** Substituir ou anexar transcrição */
303
+ mode?: 'replace' | 'append';
304
+ /** Mostrar indicador de gravação */
305
+ showRecordingIndicator?: boolean;
306
+ }
307
+
308
+ export function ArchbaseSpeechToTextInput({
309
+ value = '',
310
+ onChange,
311
+ lang = 'pt-BR',
312
+ continuous = false,
313
+ mode = 'append',
314
+ showRecordingIndicator = true,
315
+ ...props
316
+ }: ArchbaseSpeechToTextInputProps) {
317
+ const handleTranscript = useCallback(
318
+ (transcript: string) => {
319
+ if (mode === 'replace') {
320
+ onChange?.(transcript);
321
+ } else {
322
+ onChange?.(value ? `${value} ${transcript}` : transcript);
323
+ }
324
+ },
325
+ [onChange, value, mode]
326
+ );
327
+
328
+ const {
329
+ isListening,
330
+ isSupported,
331
+ } = useArchbaseSpeechToText({ lang, continuous });
332
+
333
+ return (
334
+ <TextInput
335
+ {...props}
336
+ value={value}
337
+ onChange={(e) => onChange?.(e.target.value)}
338
+ rightSection={
339
+ <Box style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
340
+ {showRecordingIndicator && isListening && (
341
+ <Box
342
+ style={{
343
+ width: 8,
344
+ height: 8,
345
+ borderRadius: '50%',
346
+ backgroundColor: 'var(--mantine-color-red-6)',
347
+ animation: 'pulse 1s infinite',
348
+ }}
349
+ />
350
+ )}
351
+ <ArchbaseSpeechToTextButton
352
+ onTranscript={handleTranscript}
353
+ lang={lang}
354
+ continuous={continuous}
355
+ size="xs"
356
+ />
357
+ </Box>
358
+ }
359
+ rightSectionWidth={isListening ? 52 : 36}
360
+ />
361
+ );
362
+ }
363
+
364
+ // =============================================================================
365
+ // ArchbaseSpeechToTextArea Component
366
+ // =============================================================================
367
+
368
+ export interface ArchbaseSpeechToTextAreaProps extends Omit<TextareaProps, 'value' | 'onChange'> {
369
+ /** Valor atual */
370
+ value?: string;
371
+ /** Callback ao mudar */
372
+ onChange?: (value: string) => void;
373
+ /** Idioma (padrão: pt-BR) */
374
+ lang?: string;
375
+ /** Modo contínuo */
376
+ continuous?: boolean;
377
+ /** Substituir ou anexar transcrição */
378
+ mode?: 'replace' | 'append';
379
+ }
380
+
381
+ export function ArchbaseSpeechToTextArea({
382
+ value = '',
383
+ onChange,
384
+ lang = 'pt-BR',
385
+ continuous = true,
386
+ mode = 'append',
387
+ ...props
388
+ }: ArchbaseSpeechToTextAreaProps) {
389
+ const handleTranscript = useCallback(
390
+ (transcript: string) => {
391
+ if (mode === 'replace') {
392
+ onChange?.(transcript);
393
+ } else {
394
+ onChange?.(value ? `${value} ${transcript}` : transcript);
395
+ }
396
+ },
397
+ [onChange, value, mode]
398
+ );
399
+
400
+ return (
401
+ <Box style={{ position: 'relative' }}>
402
+ <Textarea
403
+ {...props}
404
+ value={value}
405
+ onChange={(e) => onChange?.(e.target.value)}
406
+ />
407
+ <Box
408
+ style={{
409
+ position: 'absolute',
410
+ right: 8,
411
+ bottom: 8,
412
+ }}
413
+ >
414
+ <ArchbaseSpeechToTextButton
415
+ onTranscript={handleTranscript}
416
+ lang={lang}
417
+ continuous={continuous}
418
+ size="sm"
419
+ />
420
+ </Box>
421
+ </Box>
422
+ );
423
+ }
424
+
425
+ // =============================================================================
426
+ // CSS Keyframes (inject via style tag)
427
+ // =============================================================================
428
+
429
+ const pulseKeyframes = `
430
+ @keyframes pulse {
431
+ 0% { opacity: 1; transform: scale(1); }
432
+ 50% { opacity: 0.7; transform: scale(1.1); }
433
+ 100% { opacity: 1; transform: scale(1); }
434
+ }
435
+ `;
436
+
437
+ // Inject keyframes
438
+ if (typeof document !== 'undefined') {
439
+ const style = document.createElement('style');
440
+ style.textContent = pulseKeyframes;
441
+ document.head.appendChild(style);
442
+ }
443
+
444
+ export default ArchbaseSpeechToTextInput;