@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,472 @@
1
+ import React, {
2
+ createContext,
3
+ useContext,
4
+ useState,
5
+ useCallback,
6
+ useEffect,
7
+ useMemo,
8
+ ReactNode,
9
+ } from 'react';
10
+ import {
11
+ Modal,
12
+ Table,
13
+ Text,
14
+ Badge,
15
+ Group,
16
+ Stack,
17
+ Kbd,
18
+ Box,
19
+ TextInput,
20
+ ScrollArea,
21
+ Title,
22
+ } from '@mantine/core';
23
+ import { useHotkeys, useDisclosure } from '@mantine/hooks';
24
+ import { IconKeyboard, IconSearch } from '@tabler/icons-react';
25
+
26
+ // =============================================================================
27
+ // Types
28
+ // =============================================================================
29
+
30
+ export interface KeyboardShortcut {
31
+ /** Identificador único */
32
+ id: string;
33
+ /** Combinação de teclas (formato Mantine: 'mod+K', 'shift+Enter', etc.) */
34
+ keys: string;
35
+ /** Handler do atalho */
36
+ handler: () => void;
37
+ /** Descrição do atalho */
38
+ description: string;
39
+ /** Grupo do atalho */
40
+ group?: string;
41
+ /** Se o atalho está desabilitado */
42
+ disabled?: boolean;
43
+ /** Escopo (global ou específico) */
44
+ scope?: string;
45
+ }
46
+
47
+ export interface ArchbaseKeyboardShortcutsContextValue {
48
+ /** Atalhos registrados */
49
+ shortcuts: KeyboardShortcut[];
50
+ /** Registrar um atalho */
51
+ registerShortcut: (shortcut: KeyboardShortcut) => void;
52
+ /** Remover um atalho */
53
+ unregisterShortcut: (id: string) => void;
54
+ /** Atualizar um atalho */
55
+ updateShortcut: (id: string, updates: Partial<KeyboardShortcut>) => void;
56
+ /** Abrir modal de ajuda */
57
+ openHelpModal: () => void;
58
+ /** Fechar modal de ajuda */
59
+ closeHelpModal: () => void;
60
+ /** Se o modal está aberto */
61
+ isHelpModalOpen: boolean;
62
+ }
63
+
64
+ export interface ArchbaseKeyboardShortcutsProviderProps {
65
+ children: ReactNode;
66
+ /** Tecla para abrir o modal de ajuda (padrão: '?') */
67
+ helpKey?: string;
68
+ /** Desabilitar modal de ajuda */
69
+ disableHelpModal?: boolean;
70
+ /** Atalhos iniciais */
71
+ initialShortcuts?: Omit<KeyboardShortcut, 'id'>[];
72
+ }
73
+
74
+ export interface ArchbaseKeyboardShortcutsModalProps {
75
+ /** Se o modal está aberto */
76
+ opened: boolean;
77
+ /** Callback ao fechar */
78
+ onClose: () => void;
79
+ /** Atalhos a exibir */
80
+ shortcuts: KeyboardShortcut[];
81
+ /** Título do modal */
82
+ title?: string;
83
+ /** Mostrar campo de busca */
84
+ searchable?: boolean;
85
+ }
86
+
87
+ export interface UseArchbaseRegisterShortcutOptions {
88
+ /** Descrição do atalho */
89
+ description: string;
90
+ /** Grupo do atalho */
91
+ group?: string;
92
+ /** Se o atalho está desabilitado */
93
+ disabled?: boolean;
94
+ /** Escopo do atalho */
95
+ scope?: string;
96
+ }
97
+
98
+ // =============================================================================
99
+ // Context
100
+ // =============================================================================
101
+
102
+ const ArchbaseKeyboardShortcutsContext = createContext<ArchbaseKeyboardShortcutsContextValue | null>(null);
103
+
104
+ export function useArchbaseKeyboardShortcuts(): ArchbaseKeyboardShortcutsContextValue {
105
+ const context = useContext(ArchbaseKeyboardShortcutsContext);
106
+ if (!context) {
107
+ throw new Error('useArchbaseKeyboardShortcuts must be used within ArchbaseKeyboardShortcutsProvider');
108
+ }
109
+ return context;
110
+ }
111
+
112
+ // =============================================================================
113
+ // Utilities
114
+ // =============================================================================
115
+
116
+ let shortcutIdCounter = 0;
117
+ function generateShortcutId(): string {
118
+ return `shortcut-${++shortcutIdCounter}`;
119
+ }
120
+
121
+ function parseKeys(keys: string): string[] {
122
+ return keys.split('+').map((key) => {
123
+ const lowerKey = key.toLowerCase().trim();
124
+ switch (lowerKey) {
125
+ case 'mod':
126
+ return navigator.platform.includes('Mac') ? 'Cmd' : 'Ctrl';
127
+ case 'ctrl':
128
+ return 'Ctrl';
129
+ case 'alt':
130
+ return 'Alt';
131
+ case 'shift':
132
+ return 'Shift';
133
+ case 'enter':
134
+ return 'Enter';
135
+ case 'escape':
136
+ case 'esc':
137
+ return 'Esc';
138
+ case 'space':
139
+ return 'Space';
140
+ case 'backspace':
141
+ return 'Backspace';
142
+ case 'delete':
143
+ return 'Del';
144
+ case 'arrowup':
145
+ return '↑';
146
+ case 'arrowdown':
147
+ return '↓';
148
+ case 'arrowleft':
149
+ return '←';
150
+ case 'arrowright':
151
+ return '→';
152
+ default:
153
+ return key.toUpperCase();
154
+ }
155
+ });
156
+ }
157
+
158
+ function KeyDisplay({ keys }: { keys: string }) {
159
+ const parsedKeys = parseKeys(keys);
160
+
161
+ return (
162
+ <Group gap={4}>
163
+ {parsedKeys.map((key, index) => (
164
+ <React.Fragment key={index}>
165
+ <Kbd size="sm">{key}</Kbd>
166
+ {index < parsedKeys.length - 1 && (
167
+ <Text size="xs" c="dimmed">+</Text>
168
+ )}
169
+ </React.Fragment>
170
+ ))}
171
+ </Group>
172
+ );
173
+ }
174
+
175
+ // =============================================================================
176
+ // ArchbaseKeyboardShortcutsProvider
177
+ // =============================================================================
178
+
179
+ export function ArchbaseKeyboardShortcutsProvider({
180
+ children,
181
+ helpKey = 'shift+?',
182
+ disableHelpModal = false,
183
+ initialShortcuts = [],
184
+ }: ArchbaseKeyboardShortcutsProviderProps) {
185
+ const [shortcuts, setShortcuts] = useState<KeyboardShortcut[]>(() =>
186
+ initialShortcuts.map((s) => ({ ...s, id: generateShortcutId() }))
187
+ );
188
+ const [helpModalOpened, { open: openHelpModal, close: closeHelpModal }] = useDisclosure(false);
189
+
190
+ const registerShortcut = useCallback((shortcut: KeyboardShortcut) => {
191
+ setShortcuts((prev) => {
192
+ // Remove existing shortcut with same id
193
+ const filtered = prev.filter((s) => s.id !== shortcut.id);
194
+ return [...filtered, shortcut];
195
+ });
196
+ }, []);
197
+
198
+ const unregisterShortcut = useCallback((id: string) => {
199
+ setShortcuts((prev) => prev.filter((s) => s.id !== id));
200
+ }, []);
201
+
202
+ const updateShortcut = useCallback((id: string, updates: Partial<KeyboardShortcut>) => {
203
+ setShortcuts((prev) =>
204
+ prev.map((s) => (s.id === id ? { ...s, ...updates } : s))
205
+ );
206
+ }, []);
207
+
208
+ // Register help modal shortcut
209
+ useHotkeys([
210
+ [helpKey, () => !disableHelpModal && openHelpModal()],
211
+ ]);
212
+
213
+ // Register all shortcuts with useHotkeys
214
+ const hotkeyBindings = useMemo(() => {
215
+ return shortcuts
216
+ .filter((s) => !s.disabled)
217
+ .map((s) => [s.keys, s.handler] as [string, () => void]);
218
+ }, [shortcuts]);
219
+
220
+ useHotkeys(hotkeyBindings);
221
+
222
+ const contextValue = useMemo<ArchbaseKeyboardShortcutsContextValue>(
223
+ () => ({
224
+ shortcuts,
225
+ registerShortcut,
226
+ unregisterShortcut,
227
+ updateShortcut,
228
+ openHelpModal,
229
+ closeHelpModal,
230
+ isHelpModalOpen: helpModalOpened,
231
+ }),
232
+ [shortcuts, registerShortcut, unregisterShortcut, updateShortcut, openHelpModal, closeHelpModal, helpModalOpened]
233
+ );
234
+
235
+ return (
236
+ <ArchbaseKeyboardShortcutsContext.Provider value={contextValue}>
237
+ {children}
238
+ {!disableHelpModal && (
239
+ <ArchbaseKeyboardShortcutsModal
240
+ opened={helpModalOpened}
241
+ onClose={closeHelpModal}
242
+ shortcuts={shortcuts}
243
+ />
244
+ )}
245
+ </ArchbaseKeyboardShortcutsContext.Provider>
246
+ );
247
+ }
248
+
249
+ // =============================================================================
250
+ // ArchbaseKeyboardShortcutsModal
251
+ // =============================================================================
252
+
253
+ export function ArchbaseKeyboardShortcutsModal({
254
+ opened,
255
+ onClose,
256
+ shortcuts,
257
+ title = 'Atalhos de Teclado',
258
+ searchable = true,
259
+ }: ArchbaseKeyboardShortcutsModalProps) {
260
+ const [search, setSearch] = useState('');
261
+
262
+ // Group shortcuts
263
+ const groupedShortcuts = useMemo(() => {
264
+ const filtered = search
265
+ ? shortcuts.filter(
266
+ (s) =>
267
+ s.description.toLowerCase().includes(search.toLowerCase()) ||
268
+ s.keys.toLowerCase().includes(search.toLowerCase()) ||
269
+ s.group?.toLowerCase().includes(search.toLowerCase())
270
+ )
271
+ : shortcuts;
272
+
273
+ const groups: Record<string, KeyboardShortcut[]> = {};
274
+ filtered.forEach((shortcut) => {
275
+ const group = shortcut.group || 'Geral';
276
+ if (!groups[group]) {
277
+ groups[group] = [];
278
+ }
279
+ groups[group].push(shortcut);
280
+ });
281
+
282
+ return groups;
283
+ }, [shortcuts, search]);
284
+
285
+ const groupNames = Object.keys(groupedShortcuts).sort();
286
+
287
+ return (
288
+ <Modal
289
+ opened={opened}
290
+ onClose={onClose}
291
+ title={
292
+ <Group gap="xs">
293
+ <IconKeyboard size={20} />
294
+ <Title order={4}>{title}</Title>
295
+ </Group>
296
+ }
297
+ size="lg"
298
+ centered
299
+ >
300
+ <Stack gap="md">
301
+ {searchable && (
302
+ <TextInput
303
+ placeholder="Buscar atalhos..."
304
+ leftSection={<IconSearch size={16} />}
305
+ value={search}
306
+ onChange={(e) => setSearch(e.target.value)}
307
+ />
308
+ )}
309
+
310
+ <ScrollArea.Autosize mah={400}>
311
+ {groupNames.length === 0 ? (
312
+ <Text c="dimmed" ta="center" py="xl">
313
+ Nenhum atalho encontrado
314
+ </Text>
315
+ ) : (
316
+ <Stack gap="lg">
317
+ {groupNames.map((groupName) => (
318
+ <Box key={groupName}>
319
+ <Badge variant="light" mb="xs">
320
+ {groupName}
321
+ </Badge>
322
+ <Table striped highlightOnHover withTableBorder>
323
+ <Table.Tbody>
324
+ {groupedShortcuts[groupName].map((shortcut) => (
325
+ <Table.Tr
326
+ key={shortcut.id}
327
+ style={{
328
+ opacity: shortcut.disabled ? 0.5 : 1,
329
+ }}
330
+ >
331
+ <Table.Td style={{ width: 140 }}>
332
+ <KeyDisplay keys={shortcut.keys} />
333
+ </Table.Td>
334
+ <Table.Td>
335
+ <Text size="sm">{shortcut.description}</Text>
336
+ </Table.Td>
337
+ </Table.Tr>
338
+ ))}
339
+ </Table.Tbody>
340
+ </Table>
341
+ </Box>
342
+ ))}
343
+ </Stack>
344
+ )}
345
+ </ScrollArea.Autosize>
346
+
347
+ <Text size="xs" c="dimmed" ta="center">
348
+ Pressione <Kbd size="xs">Shift</Kbd> + <Kbd size="xs">?</Kbd> para abrir esta ajuda
349
+ </Text>
350
+ </Stack>
351
+ </Modal>
352
+ );
353
+ }
354
+
355
+ // =============================================================================
356
+ // useArchbaseRegisterShortcut Hook
357
+ // =============================================================================
358
+
359
+ export function useArchbaseRegisterShortcut(
360
+ keys: string,
361
+ handler: () => void,
362
+ options: UseArchbaseRegisterShortcutOptions
363
+ ): void {
364
+ const { registerShortcut, unregisterShortcut } = useArchbaseKeyboardShortcuts();
365
+
366
+ useEffect(() => {
367
+ const id = generateShortcutId();
368
+ const shortcut: KeyboardShortcut = {
369
+ id,
370
+ keys,
371
+ handler,
372
+ description: options.description,
373
+ group: options.group,
374
+ disabled: options.disabled,
375
+ scope: options.scope,
376
+ };
377
+
378
+ registerShortcut(shortcut);
379
+
380
+ return () => {
381
+ unregisterShortcut(id);
382
+ };
383
+ }, [keys, handler, options.description, options.group, options.disabled, options.scope, registerShortcut, unregisterShortcut]);
384
+ }
385
+
386
+ // =============================================================================
387
+ // useArchbaseShortcutScope Hook
388
+ // =============================================================================
389
+
390
+ export interface UseArchbaseShortcutScopeReturn {
391
+ /** Registrar atalho no escopo */
392
+ register: (keys: string, handler: () => void, description: string, group?: string) => () => void;
393
+ /** Desabilitar todos os atalhos do escopo */
394
+ disable: () => void;
395
+ /** Habilitar todos os atalhos do escopo */
396
+ enable: () => void;
397
+ }
398
+
399
+ export function useArchbaseShortcutScope(scope: string): UseArchbaseShortcutScopeReturn {
400
+ const { registerShortcut, unregisterShortcut, updateShortcut, shortcuts } = useArchbaseKeyboardShortcuts();
401
+ const [registeredIds, setRegisteredIds] = useState<string[]>([]);
402
+
403
+ const register = useCallback(
404
+ (keys: string, handler: () => void, description: string, group?: string) => {
405
+ const id = generateShortcutId();
406
+ const shortcut: KeyboardShortcut = {
407
+ id,
408
+ keys,
409
+ handler,
410
+ description,
411
+ group,
412
+ scope,
413
+ };
414
+
415
+ registerShortcut(shortcut);
416
+ setRegisteredIds((prev) => [...prev, id]);
417
+
418
+ return () => {
419
+ unregisterShortcut(id);
420
+ setRegisteredIds((prev) => prev.filter((i) => i !== id));
421
+ };
422
+ },
423
+ [scope, registerShortcut, unregisterShortcut]
424
+ );
425
+
426
+ const disable = useCallback(() => {
427
+ registeredIds.forEach((id) => updateShortcut(id, { disabled: true }));
428
+ }, [registeredIds, updateShortcut]);
429
+
430
+ const enable = useCallback(() => {
431
+ registeredIds.forEach((id) => updateShortcut(id, { disabled: false }));
432
+ }, [registeredIds, updateShortcut]);
433
+
434
+ // Cleanup on unmount
435
+ useEffect(() => {
436
+ return () => {
437
+ registeredIds.forEach((id) => unregisterShortcut(id));
438
+ };
439
+ }, []);
440
+
441
+ return { register, disable, enable };
442
+ }
443
+
444
+ // =============================================================================
445
+ // Convenience Components
446
+ // =============================================================================
447
+
448
+ export interface ArchbaseShortcutHintProps {
449
+ /** Combinação de teclas */
450
+ keys: string;
451
+ /** Tamanho */
452
+ size?: 'xs' | 'sm' | 'md';
453
+ }
454
+
455
+ export function ArchbaseShortcutHint({ keys, size = 'sm' }: ArchbaseShortcutHintProps) {
456
+ const parsedKeys = parseKeys(keys);
457
+
458
+ return (
459
+ <Group gap={2}>
460
+ {parsedKeys.map((key, index) => (
461
+ <React.Fragment key={index}>
462
+ <Kbd size={size}>{key}</Kbd>
463
+ {index < parsedKeys.length - 1 && (
464
+ <Text size="xs" c="dimmed">+</Text>
465
+ )}
466
+ </React.Fragment>
467
+ ))}
468
+ </Group>
469
+ );
470
+ }
471
+
472
+ export default ArchbaseKeyboardShortcutsProvider;