@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.
- package/dist/buttons/ArchbaseSpeedDial.d.ts +59 -0
- package/dist/buttons/index.d.ts +2 -0
- package/dist/charts/ArchbaseArcGauge.d.ts +55 -0
- package/dist/charts/ArchbaseGantt.d.ts +70 -0
- package/dist/charts/ArchbaseLinearGauge.d.ts +55 -0
- package/dist/charts/ArchbaseResourceTimeline.d.ts +61 -0
- package/dist/charts/ArchbaseSparkline.d.ts +45 -0
- package/dist/charts/index.d.ts +10 -0
- package/dist/containers/ArchbaseExpansionPanel.d.ts +60 -0
- package/dist/containers/ArchbaseFloatingPanel.d.ts +91 -0
- package/dist/containers/index.d.ts +4 -0
- package/dist/datagrid/export/ArchbaseDataGridExcelExport.d.ts +67 -0
- package/dist/datagrid/export/index.d.ts +2 -0
- package/dist/datagrid/index.d.ts +1 -0
- package/dist/display/ArchbaseAnimationWrapper.d.ts +73 -0
- package/dist/display/ArchbaseBarcodeGenerator.d.ts +50 -0
- package/dist/display/ArchbaseCarousel.d.ts +100 -0
- package/dist/display/ArchbaseCodeViewer.d.ts +63 -0
- package/dist/display/ArchbaseDiffViewer.d.ts +41 -0
- package/dist/display/ArchbaseJsonTree.d.ts +34 -0
- package/dist/display/ArchbaseLightbox.d.ts +89 -0
- package/dist/display/ArchbaseMarquee.d.ts +46 -0
- package/dist/display/ArchbasePhotoAlbum.d.ts +58 -0
- package/dist/display/ArchbaseQRCode.d.ts +44 -0
- package/dist/display/ArchbaseTooltipRich.d.ts +82 -0
- package/dist/display/ArchbaseVirtualList.d.ts +116 -0
- package/dist/display/index.d.ts +24 -0
- package/dist/editors/ArchbaseAIPromptInput.d.ts +69 -0
- package/dist/editors/ArchbaseAsyncMultiSelect.d.ts +1 -1
- package/dist/editors/ArchbaseAsyncSelect.d.ts +1 -1
- package/dist/editors/ArchbaseBarcodeScanner.d.ts +63 -0
- package/dist/editors/ArchbaseCepInput.d.ts +26 -0
- package/dist/editors/ArchbaseColorGradientPicker.d.ts +80 -0
- package/dist/editors/ArchbaseCpfCnpjInput.d.ts +21 -0
- package/dist/editors/ArchbaseCurrencyInput.d.ts +25 -0
- package/dist/editors/ArchbaseDualListbox.d.ts +61 -0
- package/dist/editors/ArchbaseInPlaceEditor.d.ts +67 -0
- package/dist/editors/ArchbaseLightGrid.d.ts +56 -0
- package/dist/editors/ArchbaseMentionInput.d.ts +75 -0
- package/dist/editors/ArchbaseMultiEmail.d.ts +53 -0
- package/dist/editors/ArchbaseMultiViewCalendar.d.ts +47 -0
- package/dist/editors/ArchbaseNumberStepper.d.ts +66 -0
- package/dist/editors/ArchbaseOTPInput.d.ts +27 -0
- package/dist/editors/ArchbasePhoneInput.d.ts +52 -0
- package/dist/editors/ArchbaseRangeSlider.d.ts +22 -0
- package/dist/editors/ArchbaseSignaturePad.d.ts +60 -0
- package/dist/editors/ArchbaseSpeechToTextInput.d.ts +106 -0
- package/dist/editors/ArchbaseSpreadsheet.d.ts +56 -0
- package/dist/editors/ArchbaseTagInput.d.ts +55 -0
- package/dist/editors/index.d.ts +40 -0
- package/dist/feedback/ArchbaseChunkProgressBar.d.ts +35 -0
- package/dist/feedback/ArchbaseRipple.d.ts +43 -0
- package/dist/feedback/ArchbaseSkeleton.d.ts +115 -0
- package/dist/feedback/index.d.ts +6 -0
- package/dist/filters/ArchbaseColumnSelector.d.ts +38 -0
- package/dist/filters/index.d.ts +2 -0
- package/dist/forms/ArchbaseFieldArray.d.ts +80 -0
- package/dist/forms/ArchbaseFormWizard.d.ts +73 -0
- package/dist/forms/ArchbaseStepper.d.ts +51 -0
- package/dist/forms/index.d.ts +8 -0
- package/dist/forms/useArchbaseFormWizard.d.ts +74 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/useArchbaseConfirm.d.ts +59 -0
- package/dist/image/editor/index.d.ts +43 -4
- package/dist/image/index.d.ts +1 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +22510 -13820
- package/dist/list/ArchbaseTreeList.d.ts +76 -0
- package/dist/list/index.d.ts +2 -0
- package/dist/navigation/ArchbaseActionSheet.d.ts +70 -0
- package/dist/navigation/ArchbaseAppBar.d.ts +63 -0
- package/dist/navigation/ArchbaseBottomNavigation.d.ts +61 -0
- package/dist/navigation/ArchbaseContextMenu.d.ts +76 -0
- package/dist/navigation/ArchbaseKeyboardShortcuts.d.ts +85 -0
- package/dist/navigation/ArchbaseSpotlight.d.ts +69 -0
- package/dist/navigation/index.d.ts +12 -0
- package/dist/notification/ArchbaseNotificationCenter.d.ts +56 -0
- package/dist/notification/index.d.ts +2 -0
- package/dist/onboarding/ArchbaseOnboardingTour.d.ts +27 -76
- package/dist/viewers/ArchbaseDocViewer.d.ts +40 -0
- package/dist/viewers/ArchbasePdfBuilder.d.ts +53 -0
- package/dist/viewers/ArchbaseXmlViewer.d.ts +36 -0
- package/dist/viewers/index.d.ts +6 -0
- package/package.json +41 -18
- package/src/buttons/ArchbaseSpeedDial.tsx +282 -0
- package/src/buttons/index.ts +3 -0
- package/src/charts/ArchbaseArcGauge.tsx +325 -0
- package/src/charts/ArchbaseGantt.tsx +494 -0
- package/src/charts/ArchbaseLinearGauge.tsx +288 -0
- package/src/charts/ArchbaseResourceTimeline.tsx +433 -0
- package/src/charts/ArchbaseSparkline.tsx +193 -0
- package/src/charts/index.ts +20 -1
- package/src/containers/ArchbaseExpansionPanel.tsx +208 -0
- package/src/containers/ArchbaseFloatingPanel.tsx +448 -0
- package/src/containers/index.ts +17 -0
- package/src/datagrid/components/pagination/grid-pagination.tsx +2 -2
- package/src/datagrid/export/ArchbaseDataGridExcelExport.tsx +293 -0
- package/src/datagrid/export/index.ts +8 -0
- package/src/datagrid/index.tsx +2 -0
- package/src/display/ArchbaseAnimationWrapper.tsx +272 -0
- package/src/display/ArchbaseBarcodeGenerator.tsx +303 -0
- package/src/display/ArchbaseCarousel.tsx +679 -0
- package/src/display/ArchbaseCodeViewer.tsx +271 -0
- package/src/display/ArchbaseDiffViewer.tsx +108 -0
- package/src/display/ArchbaseJsonTree.tsx +150 -0
- package/src/display/ArchbaseLightbox.tsx +279 -0
- package/src/display/ArchbaseMarquee.tsx +268 -0
- package/src/display/ArchbasePhotoAlbum.tsx +415 -0
- package/src/display/ArchbaseQRCode.tsx +137 -0
- package/src/display/ArchbaseTooltipRich.tsx +317 -0
- package/src/display/ArchbaseVirtualList.tsx +618 -0
- package/src/display/index.ts +94 -1
- package/src/editors/ArchbaseAIPromptInput.tsx +432 -0
- package/src/editors/ArchbaseBarcodeScanner.tsx +570 -0
- package/src/editors/ArchbaseCepInput.tsx +173 -0
- package/src/editors/ArchbaseColorGradientPicker.tsx +460 -0
- package/src/editors/ArchbaseCpfCnpjInput.tsx +193 -0
- package/src/editors/ArchbaseCurrencyInput.tsx +100 -0
- package/src/editors/ArchbaseDualListbox.tsx +671 -0
- package/src/editors/ArchbaseInPlaceEditor.tsx +406 -0
- package/src/editors/ArchbaseLightGrid.tsx +538 -0
- package/src/editors/ArchbaseMentionInput.tsx +384 -0
- package/src/editors/ArchbaseMultiEmail.tsx +367 -0
- package/src/editors/ArchbaseMultiViewCalendar.tsx +439 -0
- package/src/editors/ArchbaseNumberStepper.tsx +219 -0
- package/src/editors/ArchbaseOTPInput.tsx +133 -0
- package/src/editors/ArchbaseOperationHoursEditor.tsx +1 -1
- package/src/editors/ArchbasePhoneInput.tsx +355 -0
- package/src/editors/ArchbaseRangeSlider.tsx +109 -0
- package/src/editors/ArchbaseSignaturePad.tsx +425 -0
- package/src/editors/ArchbaseSpeechToTextInput.tsx +444 -0
- package/src/editors/ArchbaseSpreadsheet.tsx +388 -0
- package/src/editors/ArchbaseTagInput.tsx +326 -0
- package/src/editors/index.tsx +92 -0
- package/src/feedback/ArchbaseChunkProgressBar.tsx +156 -0
- package/src/feedback/ArchbaseRipple.tsx +278 -0
- package/src/feedback/ArchbaseSkeleton.tsx +419 -0
- package/src/feedback/index.ts +22 -1
- package/src/filters/ArchbaseColumnSelector.tsx +268 -0
- package/src/filters/index.ts +2 -0
- package/src/forms/ArchbaseFieldArray.tsx +305 -0
- package/src/forms/ArchbaseFormWizard.tsx +284 -0
- package/src/forms/ArchbaseStepper.tsx +137 -0
- package/src/forms/index.ts +24 -2
- package/src/forms/useArchbaseFormWizard.ts +283 -0
- package/src/hooks/index.ts +12 -0
- package/src/hooks/useArchbaseConfirm.ts +293 -0
- package/src/image/editor/functions/image-processing.ts +5 -0
- package/src/image/editor/index.tsx +305 -391
- package/src/image/index.ts +1 -0
- package/src/index.ts +3 -0
- package/src/list/ArchbaseTreeList.tsx +422 -0
- package/src/list/index.ts +3 -0
- package/src/navigation/ArchbaseActionSheet.tsx +301 -0
- package/src/navigation/ArchbaseAppBar.tsx +233 -0
- package/src/navigation/ArchbaseBottomNavigation.tsx +243 -0
- package/src/navigation/ArchbaseContextMenu.tsx +298 -0
- package/src/navigation/ArchbaseKeyboardShortcuts.tsx +472 -0
- package/src/navigation/ArchbaseSpotlight.tsx +483 -0
- package/src/navigation/index.ts +48 -1
- package/src/notification/ArchbaseNotificationCenter.tsx +502 -0
- package/src/notification/index.ts +2 -0
- package/src/onboarding/ArchbaseOnboardingTour.tsx +229 -102
- package/src/viewers/ArchbaseDocViewer.tsx +584 -0
- package/src/viewers/ArchbasePdfBuilder.tsx +291 -0
- package/src/viewers/ArchbaseXmlViewer.tsx +142 -0
- 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;
|