@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,432 @@
1
+ import React, { forwardRef, useCallback, useState, useRef, KeyboardEvent, ReactNode } from 'react';
2
+ import {
3
+ Textarea,
4
+ TextareaProps,
5
+ ActionIcon,
6
+ Group,
7
+ Stack,
8
+ Text,
9
+ Box,
10
+ Loader,
11
+ Badge,
12
+ Menu,
13
+ MantineColor,
14
+ MantineSize,
15
+ } from '@mantine/core';
16
+ import { IconSend, IconMicrophone, IconChevronUp, IconChevronDown, IconSparkles } from '@tabler/icons-react';
17
+
18
+ export interface ArchbaseAIPromptSuggestion {
19
+ /** ID único */
20
+ id: string;
21
+ /** Texto da sugestão */
22
+ text: string;
23
+ /** Ícone opcional */
24
+ icon?: ReactNode;
25
+ /** Categoria */
26
+ category?: string;
27
+ }
28
+
29
+ export interface ArchbaseAIPromptInputProps extends Omit<TextareaProps, 'onSubmit'> {
30
+ /** Callback ao enviar (Enter) */
31
+ onSubmit?: (value: string) => void | Promise<void>;
32
+ /** Se está carregando/processando */
33
+ loading?: boolean;
34
+ /** Placeholder */
35
+ placeholder?: string;
36
+ /** Sugestões rápidas */
37
+ suggestions?: ArchbaseAIPromptSuggestion[];
38
+ /** Se deve mostrar sugestões */
39
+ showSuggestions?: boolean;
40
+ /** Histórico de prompts */
41
+ history?: string[];
42
+ /** Se deve habilitar navegação no histórico */
43
+ enableHistory?: boolean;
44
+ /** Máximo de caracteres */
45
+ maxLength?: number;
46
+ /** Se deve mostrar contador */
47
+ showCounter?: boolean;
48
+ /** Se deve habilitar voice input */
49
+ enableVoice?: boolean;
50
+ /** Callback de voice input */
51
+ onVoiceInput?: (transcript: string) => void;
52
+ /** Cor do botão enviar */
53
+ submitColor?: MantineColor;
54
+ /** Ícone do botão enviar */
55
+ submitIcon?: ReactNode;
56
+ /** Tamanho */
57
+ size?: MantineSize;
58
+ /** Mínimo de linhas */
59
+ minRows?: number;
60
+ /** Máximo de linhas */
61
+ maxRows?: number;
62
+ /** Se deve auto-expandir */
63
+ autosize?: boolean;
64
+ /** Se está desabilitado */
65
+ disabled?: boolean;
66
+ /** Classe CSS */
67
+ className?: string;
68
+ /** Estilo */
69
+ style?: React.CSSProperties;
70
+ }
71
+
72
+ export const ArchbaseAIPromptInput = forwardRef<HTMLTextAreaElement, ArchbaseAIPromptInputProps>(
73
+ (
74
+ {
75
+ onSubmit,
76
+ loading = false,
77
+ placeholder = 'Digite sua mensagem...',
78
+ suggestions = [],
79
+ showSuggestions = true,
80
+ history = [],
81
+ enableHistory = true,
82
+ maxLength,
83
+ showCounter = true,
84
+ enableVoice = false,
85
+ onVoiceInput,
86
+ submitColor = 'blue',
87
+ submitIcon,
88
+ size = 'md',
89
+ minRows = 1,
90
+ maxRows = 6,
91
+ autosize = true,
92
+ disabled = false,
93
+ className,
94
+ style,
95
+ ...rest
96
+ },
97
+ ref
98
+ ) => {
99
+ const [value, setValue] = useState('');
100
+ const [historyIndex, setHistoryIndex] = useState(-1);
101
+ const [isRecording, setIsRecording] = useState(false);
102
+ const [showSuggestionsMenu, setShowSuggestionsMenu] = useState(false);
103
+ const textareaRef = useRef<HTMLTextAreaElement>(null);
104
+
105
+ const handleSubmit = useCallback(async () => {
106
+ if (!value.trim() || loading || disabled) return;
107
+
108
+ const trimmedValue = value.trim();
109
+ setValue('');
110
+ setHistoryIndex(-1);
111
+
112
+ if (onSubmit) {
113
+ await onSubmit(trimmedValue);
114
+ }
115
+ }, [disabled, loading, onSubmit, value]);
116
+
117
+ const handleKeyDown = useCallback(
118
+ (event: KeyboardEvent<HTMLTextAreaElement>) => {
119
+ // Enter sem Shift envia
120
+ if (event.key === 'Enter' && !event.shiftKey) {
121
+ event.preventDefault();
122
+ handleSubmit();
123
+ return;
124
+ }
125
+
126
+ // Navegação no histórico
127
+ if (enableHistory && history.length > 0) {
128
+ if (event.key === 'ArrowUp' && event.ctrlKey) {
129
+ event.preventDefault();
130
+ const newIndex = Math.min(historyIndex + 1, history.length - 1);
131
+ setHistoryIndex(newIndex);
132
+ setValue(history[history.length - 1 - newIndex] || '');
133
+ } else if (event.key === 'ArrowDown' && event.ctrlKey) {
134
+ event.preventDefault();
135
+ const newIndex = Math.max(historyIndex - 1, -1);
136
+ setHistoryIndex(newIndex);
137
+ setValue(newIndex === -1 ? '' : history[history.length - 1 - newIndex] || '');
138
+ }
139
+ }
140
+ },
141
+ [enableHistory, handleSubmit, history, historyIndex]
142
+ );
143
+
144
+ const handleVoiceClick = useCallback(() => {
145
+ if (!('webkitSpeechRecognition' in window) && !('SpeechRecognition' in window)) {
146
+ console.warn('Speech recognition not supported');
147
+ return;
148
+ }
149
+
150
+ const SpeechRecognition = (window as any).SpeechRecognition || (window as any).webkitSpeechRecognition;
151
+ const recognition = new SpeechRecognition();
152
+
153
+ recognition.lang = 'pt-BR';
154
+ recognition.continuous = false;
155
+ recognition.interimResults = false;
156
+
157
+ recognition.onstart = () => setIsRecording(true);
158
+ recognition.onend = () => setIsRecording(false);
159
+ recognition.onerror = () => setIsRecording(false);
160
+
161
+ recognition.onresult = (event: any) => {
162
+ const transcript = event.results[0][0].transcript;
163
+ setValue((prev) => prev + (prev ? ' ' : '') + transcript);
164
+ onVoiceInput?.(transcript);
165
+ };
166
+
167
+ if (isRecording) {
168
+ recognition.stop();
169
+ } else {
170
+ recognition.start();
171
+ }
172
+ }, [isRecording, onVoiceInput]);
173
+
174
+ const handleSuggestionClick = useCallback((suggestion: ArchbaseAIPromptSuggestion) => {
175
+ setValue(suggestion.text);
176
+ setShowSuggestionsMenu(false);
177
+ textareaRef.current?.focus();
178
+ }, []);
179
+
180
+ const charCount = value.length;
181
+ const isOverLimit = maxLength ? charCount > maxLength : false;
182
+
183
+ return (
184
+ <Stack gap="xs" className={className} style={style}>
185
+ {/* Suggestions */}
186
+ {showSuggestions && suggestions.length > 0 && (
187
+ <Group gap="xs">
188
+ {suggestions.slice(0, 4).map((suggestion) => (
189
+ <Badge
190
+ key={suggestion.id}
191
+ variant="light"
192
+ color="gray"
193
+ size="sm"
194
+ style={{ cursor: 'pointer' }}
195
+ onClick={() => handleSuggestionClick(suggestion)}
196
+ leftSection={suggestion.icon}
197
+ >
198
+ {suggestion.text.length > 30 ? suggestion.text.slice(0, 30) + '...' : suggestion.text}
199
+ </Badge>
200
+ ))}
201
+ {suggestions.length > 4 && (
202
+ <Menu opened={showSuggestionsMenu} onChange={setShowSuggestionsMenu}>
203
+ <Menu.Target>
204
+ <Badge
205
+ variant="light"
206
+ color="blue"
207
+ size="sm"
208
+ style={{ cursor: 'pointer' }}
209
+ leftSection={<IconSparkles size={12} />}
210
+ >
211
+ +{suggestions.length - 4} mais
212
+ </Badge>
213
+ </Menu.Target>
214
+ <Menu.Dropdown>
215
+ {suggestions.slice(4).map((suggestion) => (
216
+ <Menu.Item
217
+ key={suggestion.id}
218
+ leftSection={suggestion.icon}
219
+ onClick={() => handleSuggestionClick(suggestion)}
220
+ >
221
+ {suggestion.text}
222
+ </Menu.Item>
223
+ ))}
224
+ </Menu.Dropdown>
225
+ </Menu>
226
+ )}
227
+ </Group>
228
+ )}
229
+
230
+ {/* Input area */}
231
+ <Box
232
+ style={{
233
+ position: 'relative',
234
+ border: '1px solid var(--mantine-color-gray-4)',
235
+ borderRadius: 'var(--mantine-radius-md)',
236
+ backgroundColor: 'var(--mantine-color-body)',
237
+ padding: '8px 12px',
238
+ }}
239
+ >
240
+ <Textarea
241
+ ref={ref || textareaRef}
242
+ value={value}
243
+ onChange={(e) => setValue(e.target.value)}
244
+ onKeyDown={handleKeyDown}
245
+ placeholder={placeholder}
246
+ autosize={autosize}
247
+ minRows={minRows}
248
+ maxRows={maxRows}
249
+ size={size}
250
+ disabled={disabled || loading}
251
+ variant="unstyled"
252
+ styles={{
253
+ input: {
254
+ paddingRight: 80,
255
+ },
256
+ }}
257
+ {...rest}
258
+ />
259
+
260
+ {/* Actions */}
261
+ <Group
262
+ gap={4}
263
+ style={{
264
+ position: 'absolute',
265
+ right: 8,
266
+ bottom: 8,
267
+ }}
268
+ >
269
+ {/* Voice button */}
270
+ {enableVoice && (
271
+ <ActionIcon
272
+ variant={isRecording ? 'filled' : 'subtle'}
273
+ color={isRecording ? 'red' : 'gray'}
274
+ size={size}
275
+ onClick={handleVoiceClick}
276
+ disabled={disabled || loading}
277
+ >
278
+ <IconMicrophone size={18} />
279
+ </ActionIcon>
280
+ )}
281
+
282
+ {/* History navigation */}
283
+ {enableHistory && history.length > 0 && (
284
+ <Group gap={0}>
285
+ <ActionIcon
286
+ variant="subtle"
287
+ color="gray"
288
+ size="xs"
289
+ onClick={() => {
290
+ const newIndex = Math.min(historyIndex + 1, history.length - 1);
291
+ setHistoryIndex(newIndex);
292
+ setValue(history[history.length - 1 - newIndex] || '');
293
+ }}
294
+ disabled={historyIndex >= history.length - 1}
295
+ >
296
+ <IconChevronUp size={14} />
297
+ </ActionIcon>
298
+ <ActionIcon
299
+ variant="subtle"
300
+ color="gray"
301
+ size="xs"
302
+ onClick={() => {
303
+ const newIndex = Math.max(historyIndex - 1, -1);
304
+ setHistoryIndex(newIndex);
305
+ setValue(newIndex === -1 ? '' : history[history.length - 1 - newIndex] || '');
306
+ }}
307
+ disabled={historyIndex <= -1}
308
+ >
309
+ <IconChevronDown size={14} />
310
+ </ActionIcon>
311
+ </Group>
312
+ )}
313
+
314
+ {/* Submit button */}
315
+ <ActionIcon
316
+ variant="filled"
317
+ color={submitColor}
318
+ size={size}
319
+ onClick={handleSubmit}
320
+ disabled={!value.trim() || loading || disabled || isOverLimit}
321
+ >
322
+ {loading ? (
323
+ <Loader size="xs" color="white" />
324
+ ) : (
325
+ submitIcon || <IconSend size={18} />
326
+ )}
327
+ </ActionIcon>
328
+ </Group>
329
+ </Box>
330
+
331
+ {/* Counter */}
332
+ {showCounter && maxLength && (
333
+ <Text size="xs" c={isOverLimit ? 'red' : 'dimmed'} ta="right">
334
+ {charCount}/{maxLength}
335
+ </Text>
336
+ )}
337
+ </Stack>
338
+ );
339
+ }
340
+ );
341
+
342
+ ArchbaseAIPromptInput.displayName = 'ArchbaseAIPromptInput';
343
+
344
+ // ================== Hook para histórico de prompts ==================
345
+
346
+ export interface UseArchbasePromptHistoryOptions {
347
+ maxHistory?: number;
348
+ storageKey?: string;
349
+ }
350
+
351
+ export interface UseArchbasePromptHistoryReturn {
352
+ history: string[];
353
+ addToHistory: (prompt: string) => void;
354
+ clearHistory: () => void;
355
+ currentIndex: number;
356
+ navigateUp: () => string | null;
357
+ navigateDown: () => string | null;
358
+ resetNavigation: () => void;
359
+ }
360
+
361
+ export function useArchbasePromptHistory(
362
+ options: UseArchbasePromptHistoryOptions = {}
363
+ ): UseArchbasePromptHistoryReturn {
364
+ const { maxHistory = 50, storageKey } = options;
365
+ const [history, setHistory] = useState<string[]>(() => {
366
+ if (storageKey && typeof window !== 'undefined') {
367
+ const stored = localStorage.getItem(storageKey);
368
+ return stored ? JSON.parse(stored) : [];
369
+ }
370
+ return [];
371
+ });
372
+ const [currentIndex, setCurrentIndex] = useState(-1);
373
+
374
+ const addToHistory = useCallback(
375
+ (prompt: string) => {
376
+ const trimmed = prompt.trim();
377
+ if (!trimmed) return;
378
+
379
+ setHistory((prev) => {
380
+ const filtered = prev.filter((p) => p !== trimmed);
381
+ const newHistory = [trimmed, ...filtered].slice(0, maxHistory);
382
+
383
+ if (storageKey) {
384
+ localStorage.setItem(storageKey, JSON.stringify(newHistory));
385
+ }
386
+
387
+ return newHistory;
388
+ });
389
+ setCurrentIndex(-1);
390
+ },
391
+ [maxHistory, storageKey]
392
+ );
393
+
394
+ const clearHistory = useCallback(() => {
395
+ setHistory([]);
396
+ setCurrentIndex(-1);
397
+ if (storageKey) {
398
+ localStorage.removeItem(storageKey);
399
+ }
400
+ }, [storageKey]);
401
+
402
+ const navigateUp = useCallback(() => {
403
+ if (currentIndex >= history.length - 1) return null;
404
+ const newIndex = currentIndex + 1;
405
+ setCurrentIndex(newIndex);
406
+ return history[newIndex];
407
+ }, [currentIndex, history]);
408
+
409
+ const navigateDown = useCallback(() => {
410
+ if (currentIndex <= 0) {
411
+ setCurrentIndex(-1);
412
+ return null;
413
+ }
414
+ const newIndex = currentIndex - 1;
415
+ setCurrentIndex(newIndex);
416
+ return history[newIndex];
417
+ }, [currentIndex, history]);
418
+
419
+ const resetNavigation = useCallback(() => {
420
+ setCurrentIndex(-1);
421
+ }, []);
422
+
423
+ return {
424
+ history,
425
+ addToHistory,
426
+ clearHistory,
427
+ currentIndex,
428
+ navigateUp,
429
+ navigateDown,
430
+ resetNavigation,
431
+ };
432
+ }