@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,208 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Accordion,
|
|
4
|
+
AccordionProps,
|
|
5
|
+
AccordionControlProps,
|
|
6
|
+
AccordionItemProps,
|
|
7
|
+
AccordionPanelProps,
|
|
8
|
+
ThemeIcon,
|
|
9
|
+
Group,
|
|
10
|
+
Text,
|
|
11
|
+
Badge,
|
|
12
|
+
} from '@mantine/core';
|
|
13
|
+
|
|
14
|
+
// =============================================================================
|
|
15
|
+
// Types
|
|
16
|
+
// =============================================================================
|
|
17
|
+
|
|
18
|
+
export interface ArchbaseExpansionPanelItem {
|
|
19
|
+
/** ID único do painel */
|
|
20
|
+
id: string;
|
|
21
|
+
/** Título do painel */
|
|
22
|
+
title: string;
|
|
23
|
+
/** Descrição opcional */
|
|
24
|
+
description?: string;
|
|
25
|
+
/** Ícone opcional */
|
|
26
|
+
icon?: ReactNode;
|
|
27
|
+
/** Badge opcional */
|
|
28
|
+
badge?: string | number;
|
|
29
|
+
/** Cor do badge */
|
|
30
|
+
badgeColor?: string;
|
|
31
|
+
/** Conteúdo do painel */
|
|
32
|
+
content: ReactNode;
|
|
33
|
+
/** Se o painel está desabilitado */
|
|
34
|
+
disabled?: boolean;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface ArchbaseExpansionPanelProps extends Omit<AccordionProps<true>, 'children' | 'multiple' | 'value' | 'defaultValue' | 'onChange'> {
|
|
38
|
+
/** Array de painéis */
|
|
39
|
+
panels: ArchbaseExpansionPanelItem[];
|
|
40
|
+
/** Permitir múltiplos painéis abertos */
|
|
41
|
+
multiple?: boolean;
|
|
42
|
+
/** Valor padrão (IDs dos painéis abertos) */
|
|
43
|
+
defaultValue?: string | string[];
|
|
44
|
+
/** Valor controlado */
|
|
45
|
+
value?: string | string[] | null;
|
|
46
|
+
/** Callback ao mudar */
|
|
47
|
+
onChange?: (value: string | string[] | null) => void;
|
|
48
|
+
/** Variante visual */
|
|
49
|
+
variant?: 'default' | 'contained' | 'filled' | 'separated';
|
|
50
|
+
/** Tamanho do chevron */
|
|
51
|
+
chevronSize?: number;
|
|
52
|
+
/** Posição do chevron */
|
|
53
|
+
chevronPosition?: 'left' | 'right';
|
|
54
|
+
/** Duração da transição em ms */
|
|
55
|
+
transitionDuration?: number;
|
|
56
|
+
/** Desabilitar todos os painéis */
|
|
57
|
+
disabled?: boolean;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// =============================================================================
|
|
61
|
+
// ArchbaseExpansionPanel Component
|
|
62
|
+
// =============================================================================
|
|
63
|
+
|
|
64
|
+
export function ArchbaseExpansionPanel({
|
|
65
|
+
panels,
|
|
66
|
+
multiple = false,
|
|
67
|
+
defaultValue,
|
|
68
|
+
value,
|
|
69
|
+
onChange,
|
|
70
|
+
variant = 'default',
|
|
71
|
+
chevronSize = 20,
|
|
72
|
+
chevronPosition = 'right',
|
|
73
|
+
transitionDuration = 200,
|
|
74
|
+
disabled = false,
|
|
75
|
+
...mantineProps
|
|
76
|
+
}: ArchbaseExpansionPanelProps) {
|
|
77
|
+
// Render control with icon, title, description and badge
|
|
78
|
+
const renderControl = (panel: ArchbaseExpansionPanelItem) => (
|
|
79
|
+
<Accordion.Control disabled={disabled || panel.disabled}>
|
|
80
|
+
<Group gap="sm" wrap="nowrap">
|
|
81
|
+
{panel.icon && (
|
|
82
|
+
<ThemeIcon variant="light" size="md">
|
|
83
|
+
{panel.icon}
|
|
84
|
+
</ThemeIcon>
|
|
85
|
+
)}
|
|
86
|
+
<div style={{ flex: 1 }}>
|
|
87
|
+
<Group gap="xs">
|
|
88
|
+
<Text fw={500}>{panel.title}</Text>
|
|
89
|
+
{panel.badge !== undefined && (
|
|
90
|
+
<Badge size="sm" color={panel.badgeColor}>
|
|
91
|
+
{panel.badge}
|
|
92
|
+
</Badge>
|
|
93
|
+
)}
|
|
94
|
+
</Group>
|
|
95
|
+
{panel.description && (
|
|
96
|
+
<Text size="sm" c="dimmed">
|
|
97
|
+
{panel.description}
|
|
98
|
+
</Text>
|
|
99
|
+
)}
|
|
100
|
+
</div>
|
|
101
|
+
</Group>
|
|
102
|
+
</Accordion.Control>
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
// Render accordion based on multiple mode
|
|
106
|
+
if (multiple) {
|
|
107
|
+
return (
|
|
108
|
+
<Accordion
|
|
109
|
+
multiple
|
|
110
|
+
variant={variant}
|
|
111
|
+
chevronSize={chevronSize}
|
|
112
|
+
chevronPosition={chevronPosition}
|
|
113
|
+
transitionDuration={transitionDuration}
|
|
114
|
+
defaultValue={defaultValue as string[] | undefined}
|
|
115
|
+
value={value as string[] | undefined}
|
|
116
|
+
onChange={onChange as ((value: string[]) => void) | undefined}
|
|
117
|
+
{...mantineProps}
|
|
118
|
+
>
|
|
119
|
+
{panels.map((panel) => (
|
|
120
|
+
<Accordion.Item key={panel.id} value={panel.id}>
|
|
121
|
+
{renderControl(panel)}
|
|
122
|
+
<Accordion.Panel>{panel.content}</Accordion.Panel>
|
|
123
|
+
</Accordion.Item>
|
|
124
|
+
))}
|
|
125
|
+
</Accordion>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<Accordion
|
|
131
|
+
variant={variant}
|
|
132
|
+
chevronSize={chevronSize}
|
|
133
|
+
chevronPosition={chevronPosition}
|
|
134
|
+
transitionDuration={transitionDuration}
|
|
135
|
+
defaultValue={defaultValue as string | undefined}
|
|
136
|
+
value={value as string | null | undefined}
|
|
137
|
+
onChange={onChange as ((value: string | null) => void) | undefined}
|
|
138
|
+
{...mantineProps}
|
|
139
|
+
>
|
|
140
|
+
{panels.map((panel) => (
|
|
141
|
+
<Accordion.Item key={panel.id} value={panel.id}>
|
|
142
|
+
{renderControl(panel)}
|
|
143
|
+
<Accordion.Panel>{panel.content}</Accordion.Panel>
|
|
144
|
+
</Accordion.Item>
|
|
145
|
+
))}
|
|
146
|
+
</Accordion>
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// =============================================================================
|
|
151
|
+
// ArchbaseExpansionPanelControlled (Wrapper simplificado para uso controlado)
|
|
152
|
+
// =============================================================================
|
|
153
|
+
|
|
154
|
+
export interface ArchbaseExpansionPanelControlledProps
|
|
155
|
+
extends Omit<ArchbaseExpansionPanelProps, 'value' | 'onChange' | 'defaultValue'> {
|
|
156
|
+
/** IDs dos painéis abertos */
|
|
157
|
+
openPanels: string[];
|
|
158
|
+
/** Callback ao abrir/fechar painéis */
|
|
159
|
+
onOpenPanelsChange: (panels: string[]) => void;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function ArchbaseExpansionPanelControlled({
|
|
163
|
+
openPanels,
|
|
164
|
+
onOpenPanelsChange,
|
|
165
|
+
...props
|
|
166
|
+
}: ArchbaseExpansionPanelControlledProps) {
|
|
167
|
+
return (
|
|
168
|
+
<ArchbaseExpansionPanel
|
|
169
|
+
multiple
|
|
170
|
+
value={openPanels}
|
|
171
|
+
onChange={(value) => onOpenPanelsChange(value as string[])}
|
|
172
|
+
{...props}
|
|
173
|
+
/>
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// =============================================================================
|
|
178
|
+
// ArchbaseExpansionPanelSingle (Wrapper para accordion único)
|
|
179
|
+
// =============================================================================
|
|
180
|
+
|
|
181
|
+
export interface ArchbaseExpansionPanelSingleProps
|
|
182
|
+
extends Omit<ArchbaseExpansionPanelProps, 'multiple' | 'value' | 'onChange' | 'defaultValue'> {
|
|
183
|
+
/** ID do painel aberto */
|
|
184
|
+
openPanel?: string | null;
|
|
185
|
+
/** Callback ao abrir/fechar */
|
|
186
|
+
onOpenPanelChange?: (panel: string | null) => void;
|
|
187
|
+
/** Painel aberto por padrão */
|
|
188
|
+
defaultOpenPanel?: string;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function ArchbaseExpansionPanelSingle({
|
|
192
|
+
openPanel,
|
|
193
|
+
onOpenPanelChange,
|
|
194
|
+
defaultOpenPanel,
|
|
195
|
+
...props
|
|
196
|
+
}: ArchbaseExpansionPanelSingleProps) {
|
|
197
|
+
return (
|
|
198
|
+
<ArchbaseExpansionPanel
|
|
199
|
+
multiple={false}
|
|
200
|
+
value={openPanel}
|
|
201
|
+
onChange={onOpenPanelChange as ((value: string | string[] | null) => void) | undefined}
|
|
202
|
+
defaultValue={defaultOpenPanel}
|
|
203
|
+
{...props}
|
|
204
|
+
/>
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export default ArchbaseExpansionPanel;
|
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
import React, { useState, useCallback, useRef, useEffect, ReactNode } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Box,
|
|
4
|
+
Paper,
|
|
5
|
+
Group,
|
|
6
|
+
Text,
|
|
7
|
+
ActionIcon,
|
|
8
|
+
Tooltip,
|
|
9
|
+
CloseButton,
|
|
10
|
+
useMantineTheme,
|
|
11
|
+
} from '@mantine/core';
|
|
12
|
+
import { useElementSize, useMouse, useWindowEvent } from '@mantine/hooks';
|
|
13
|
+
import {
|
|
14
|
+
IconMinus,
|
|
15
|
+
IconSquare,
|
|
16
|
+
IconMaximize,
|
|
17
|
+
IconArrowsMinimize,
|
|
18
|
+
IconGripVertical,
|
|
19
|
+
} from '@tabler/icons-react';
|
|
20
|
+
|
|
21
|
+
// =============================================================================
|
|
22
|
+
// Types
|
|
23
|
+
// =============================================================================
|
|
24
|
+
|
|
25
|
+
export interface ArchbaseFloatingPanelProps {
|
|
26
|
+
/** ID único do painel */
|
|
27
|
+
id?: string;
|
|
28
|
+
/** Conteúdo do painel */
|
|
29
|
+
children: ReactNode;
|
|
30
|
+
/** Título do painel */
|
|
31
|
+
title?: string;
|
|
32
|
+
/** Ícone do título */
|
|
33
|
+
icon?: ReactNode;
|
|
34
|
+
/** Largura inicial */
|
|
35
|
+
width?: number;
|
|
36
|
+
/** Altura inicial */
|
|
37
|
+
height?: number;
|
|
38
|
+
/** Posição X inicial */
|
|
39
|
+
initialX?: number;
|
|
40
|
+
/** Posição Y inicial */
|
|
41
|
+
initialY?: number;
|
|
42
|
+
/** Se pode redimensionar */
|
|
43
|
+
resizable?: boolean;
|
|
44
|
+
/** Se pode minimizar */
|
|
45
|
+
minimizable?: boolean;
|
|
46
|
+
/** Se pode maximizar */
|
|
47
|
+
maximizable?: boolean;
|
|
48
|
+
/** Se pode fechar */
|
|
49
|
+
closable?: boolean;
|
|
50
|
+
/** Callback ao fechar */
|
|
51
|
+
onClose?: () => void;
|
|
52
|
+
/** Callback ao minimizar */
|
|
53
|
+
onMinimize?: () => void;
|
|
54
|
+
/** Callback ao maximizar */
|
|
55
|
+
onMaximize?: () => void;
|
|
56
|
+
/** Callback ao restaurar */
|
|
57
|
+
onRestore?: () => void;
|
|
58
|
+
/** Callback ao mover */
|
|
59
|
+
onMove?: (x: number, y: number) => void;
|
|
60
|
+
/** Callback ao redimensionar */
|
|
61
|
+
onResize?: (width: number, height: number) => void;
|
|
62
|
+
/** Cor do header */
|
|
63
|
+
headerColor?: string;
|
|
64
|
+
/** Se o painel está inicialmente visível */
|
|
65
|
+
defaultVisible?: boolean;
|
|
66
|
+
/** Z-index */
|
|
67
|
+
zIndex?: number;
|
|
68
|
+
/** Tamanho mínimo */
|
|
69
|
+
minWidth?: number;
|
|
70
|
+
minHeight?: number;
|
|
71
|
+
/** Tamanho máximo */
|
|
72
|
+
maxWidth?: number;
|
|
73
|
+
maxHeight?: number;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface ArchbaseFloatingPanelState {
|
|
77
|
+
x: number;
|
|
78
|
+
y: number;
|
|
79
|
+
width: number;
|
|
80
|
+
height: number;
|
|
81
|
+
minimized: boolean;
|
|
82
|
+
maximized: boolean;
|
|
83
|
+
visible: boolean;
|
|
84
|
+
zIndex: number;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// =============================================================================
|
|
88
|
+
// Z-Index Manager
|
|
89
|
+
// =============================================================================
|
|
90
|
+
|
|
91
|
+
let globalZIndex = 1000;
|
|
92
|
+
function getNextZIndex(): number {
|
|
93
|
+
return ++globalZIndex;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// =============================================================================
|
|
97
|
+
// ArchbaseFloatingPanel Component
|
|
98
|
+
// =============================================================================
|
|
99
|
+
|
|
100
|
+
export function ArchbaseFloatingPanel({
|
|
101
|
+
id,
|
|
102
|
+
children,
|
|
103
|
+
title = 'Painel',
|
|
104
|
+
icon,
|
|
105
|
+
width: initialWidth = 400,
|
|
106
|
+
height: initialHeight = 300,
|
|
107
|
+
initialX = 100,
|
|
108
|
+
initialY = 100,
|
|
109
|
+
resizable = true,
|
|
110
|
+
minimizable = true,
|
|
111
|
+
maximizable = true,
|
|
112
|
+
closable = true,
|
|
113
|
+
onClose,
|
|
114
|
+
onMinimize,
|
|
115
|
+
onMaximize,
|
|
116
|
+
onRestore,
|
|
117
|
+
onMove,
|
|
118
|
+
onResize,
|
|
119
|
+
headerColor,
|
|
120
|
+
defaultVisible = true,
|
|
121
|
+
zIndex: initialZIndex,
|
|
122
|
+
minWidth = 200,
|
|
123
|
+
minHeight = 100,
|
|
124
|
+
maxWidth,
|
|
125
|
+
maxHeight,
|
|
126
|
+
}: ArchbaseFloatingPanelProps) {
|
|
127
|
+
const theme = useMantineTheme();
|
|
128
|
+
const panelRef = useRef<HTMLDivElement>(null);
|
|
129
|
+
|
|
130
|
+
// State
|
|
131
|
+
const [state, setState] = useState<ArchbaseFloatingPanelState>({
|
|
132
|
+
x: initialX,
|
|
133
|
+
y: initialY,
|
|
134
|
+
width: initialWidth,
|
|
135
|
+
height: initialHeight,
|
|
136
|
+
minimized: false,
|
|
137
|
+
maximized: false,
|
|
138
|
+
visible: defaultVisible,
|
|
139
|
+
zIndex: initialZIndex || getNextZIndex(),
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
143
|
+
const [isResizing, setIsResizing] = useState(false);
|
|
144
|
+
const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 });
|
|
145
|
+
const [savedState, setSavedState] = useState<Partial<ArchbaseFloatingPanelState>>({});
|
|
146
|
+
|
|
147
|
+
// Drag handlers
|
|
148
|
+
const handleMouseDown = useCallback((e: React.MouseEvent) => {
|
|
149
|
+
if ((e.target as HTMLElement).closest('.panel-controls')) return;
|
|
150
|
+
|
|
151
|
+
setIsDragging(true);
|
|
152
|
+
setDragOffset({
|
|
153
|
+
x: e.clientX - state.x,
|
|
154
|
+
y: e.clientY - state.y,
|
|
155
|
+
});
|
|
156
|
+
setState((prev) => ({ ...prev, zIndex: getNextZIndex() }));
|
|
157
|
+
}, [state.x, state.y]);
|
|
158
|
+
|
|
159
|
+
const handleMouseMove = useCallback((e: MouseEvent) => {
|
|
160
|
+
if (isDragging) {
|
|
161
|
+
const newX = e.clientX - dragOffset.x;
|
|
162
|
+
const newY = Math.max(0, e.clientY - dragOffset.y);
|
|
163
|
+
|
|
164
|
+
setState((prev) => ({ ...prev, x: newX, y: newY }));
|
|
165
|
+
onMove?.(newX, newY);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (isResizing) {
|
|
169
|
+
const rect = panelRef.current?.getBoundingClientRect();
|
|
170
|
+
if (!rect) return;
|
|
171
|
+
|
|
172
|
+
let newWidth = e.clientX - rect.left;
|
|
173
|
+
let newHeight = e.clientY - rect.top;
|
|
174
|
+
|
|
175
|
+
// Apply constraints
|
|
176
|
+
newWidth = Math.max(minWidth, newWidth);
|
|
177
|
+
newHeight = Math.max(minHeight, newHeight);
|
|
178
|
+
if (maxWidth) newWidth = Math.min(maxWidth, newWidth);
|
|
179
|
+
if (maxHeight) newHeight = Math.min(maxHeight, newHeight);
|
|
180
|
+
|
|
181
|
+
setState((prev) => ({ ...prev, width: newWidth, height: newHeight }));
|
|
182
|
+
onResize?.(newWidth, newHeight);
|
|
183
|
+
}
|
|
184
|
+
}, [isDragging, isResizing, dragOffset, minWidth, minHeight, maxWidth, maxHeight, onMove, onResize]);
|
|
185
|
+
|
|
186
|
+
const handleMouseUp = useCallback(() => {
|
|
187
|
+
setIsDragging(false);
|
|
188
|
+
setIsResizing(false);
|
|
189
|
+
}, []);
|
|
190
|
+
|
|
191
|
+
// Attach/detach global listeners
|
|
192
|
+
useEffect(() => {
|
|
193
|
+
if (isDragging || isResizing) {
|
|
194
|
+
window.addEventListener('mousemove', handleMouseMove);
|
|
195
|
+
window.addEventListener('mouseup', handleMouseUp);
|
|
196
|
+
return () => {
|
|
197
|
+
window.removeEventListener('mousemove', handleMouseMove);
|
|
198
|
+
window.removeEventListener('mouseup', handleMouseUp);
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
}, [isDragging, isResizing, handleMouseMove, handleMouseUp]);
|
|
202
|
+
|
|
203
|
+
// Actions
|
|
204
|
+
const handleMinimize = useCallback(() => {
|
|
205
|
+
if (state.minimized) {
|
|
206
|
+
setState((prev) => ({
|
|
207
|
+
...prev,
|
|
208
|
+
...savedState,
|
|
209
|
+
minimized: false,
|
|
210
|
+
}));
|
|
211
|
+
onRestore?.();
|
|
212
|
+
} else {
|
|
213
|
+
setSavedState({
|
|
214
|
+
height: state.height,
|
|
215
|
+
y: state.y,
|
|
216
|
+
});
|
|
217
|
+
setState((prev) => ({
|
|
218
|
+
...prev,
|
|
219
|
+
minimized: true,
|
|
220
|
+
maximized: false,
|
|
221
|
+
}));
|
|
222
|
+
onMinimize?.();
|
|
223
|
+
}
|
|
224
|
+
}, [state.minimized, state.height, state.y, savedState, onMinimize, onRestore]);
|
|
225
|
+
|
|
226
|
+
const handleMaximize = useCallback(() => {
|
|
227
|
+
if (state.maximized) {
|
|
228
|
+
setState((prev) => ({
|
|
229
|
+
...prev,
|
|
230
|
+
...savedState,
|
|
231
|
+
maximized: false,
|
|
232
|
+
}));
|
|
233
|
+
onRestore?.();
|
|
234
|
+
} else {
|
|
235
|
+
setSavedState({
|
|
236
|
+
x: state.x,
|
|
237
|
+
y: state.y,
|
|
238
|
+
width: state.width,
|
|
239
|
+
height: state.height,
|
|
240
|
+
});
|
|
241
|
+
setState((prev) => ({
|
|
242
|
+
...prev,
|
|
243
|
+
x: 0,
|
|
244
|
+
y: 0,
|
|
245
|
+
width: window.innerWidth,
|
|
246
|
+
height: window.innerHeight,
|
|
247
|
+
maximized: true,
|
|
248
|
+
minimized: false,
|
|
249
|
+
}));
|
|
250
|
+
onMaximize?.();
|
|
251
|
+
}
|
|
252
|
+
}, [state.maximized, state.x, state.y, state.width, state.height, savedState, onMaximize, onRestore]);
|
|
253
|
+
|
|
254
|
+
const handleClose = useCallback(() => {
|
|
255
|
+
setState((prev) => ({ ...prev, visible: false }));
|
|
256
|
+
onClose?.();
|
|
257
|
+
}, [onClose]);
|
|
258
|
+
|
|
259
|
+
const handleFocus = useCallback(() => {
|
|
260
|
+
setState((prev) => ({ ...prev, zIndex: getNextZIndex() }));
|
|
261
|
+
}, []);
|
|
262
|
+
|
|
263
|
+
if (!state.visible) return null;
|
|
264
|
+
|
|
265
|
+
const effectiveHeight = state.minimized ? 40 : state.height;
|
|
266
|
+
|
|
267
|
+
return (
|
|
268
|
+
<Paper
|
|
269
|
+
ref={panelRef}
|
|
270
|
+
id={id}
|
|
271
|
+
shadow="lg"
|
|
272
|
+
radius="sm"
|
|
273
|
+
onMouseDown={handleFocus}
|
|
274
|
+
style={{
|
|
275
|
+
position: 'fixed',
|
|
276
|
+
left: state.x,
|
|
277
|
+
top: state.y,
|
|
278
|
+
width: state.width,
|
|
279
|
+
height: effectiveHeight,
|
|
280
|
+
zIndex: state.zIndex,
|
|
281
|
+
overflow: 'hidden',
|
|
282
|
+
display: 'flex',
|
|
283
|
+
flexDirection: 'column',
|
|
284
|
+
transition: isDragging || isResizing ? 'none' : 'all 0.2s ease',
|
|
285
|
+
cursor: isDragging ? 'grabbing' : 'default',
|
|
286
|
+
}}
|
|
287
|
+
>
|
|
288
|
+
{/* Header */}
|
|
289
|
+
<Box
|
|
290
|
+
onMouseDown={handleMouseDown}
|
|
291
|
+
style={{
|
|
292
|
+
padding: '8px 12px',
|
|
293
|
+
backgroundColor: headerColor || theme.colors.blue[6],
|
|
294
|
+
color: 'white',
|
|
295
|
+
cursor: isDragging ? 'grabbing' : 'grab',
|
|
296
|
+
userSelect: 'none',
|
|
297
|
+
display: 'flex',
|
|
298
|
+
alignItems: 'center',
|
|
299
|
+
justifyContent: 'space-between',
|
|
300
|
+
flexShrink: 0,
|
|
301
|
+
}}
|
|
302
|
+
>
|
|
303
|
+
<Group gap="xs">
|
|
304
|
+
{icon}
|
|
305
|
+
<Text fw={500} size="sm">
|
|
306
|
+
{title}
|
|
307
|
+
</Text>
|
|
308
|
+
</Group>
|
|
309
|
+
|
|
310
|
+
<Group gap={4} className="panel-controls">
|
|
311
|
+
{minimizable && (
|
|
312
|
+
<Tooltip label={state.minimized ? 'Restaurar' : 'Minimizar'}>
|
|
313
|
+
<ActionIcon
|
|
314
|
+
variant="subtle"
|
|
315
|
+
color="white"
|
|
316
|
+
size="sm"
|
|
317
|
+
onClick={handleMinimize}
|
|
318
|
+
>
|
|
319
|
+
{state.minimized ? <IconArrowsMinimize size={14} /> : <IconMinus size={14} />}
|
|
320
|
+
</ActionIcon>
|
|
321
|
+
</Tooltip>
|
|
322
|
+
)}
|
|
323
|
+
{maximizable && (
|
|
324
|
+
<Tooltip label={state.maximized ? 'Restaurar' : 'Maximizar'}>
|
|
325
|
+
<ActionIcon
|
|
326
|
+
variant="subtle"
|
|
327
|
+
color="white"
|
|
328
|
+
size="sm"
|
|
329
|
+
onClick={handleMaximize}
|
|
330
|
+
>
|
|
331
|
+
{state.maximized ? <IconArrowsMinimize size={14} /> : <IconMaximize size={14} />}
|
|
332
|
+
</ActionIcon>
|
|
333
|
+
</Tooltip>
|
|
334
|
+
)}
|
|
335
|
+
{closable && (
|
|
336
|
+
<CloseButton
|
|
337
|
+
variant="subtle"
|
|
338
|
+
color="white"
|
|
339
|
+
size="sm"
|
|
340
|
+
onClick={handleClose}
|
|
341
|
+
/>
|
|
342
|
+
)}
|
|
343
|
+
</Group>
|
|
344
|
+
</Box>
|
|
345
|
+
|
|
346
|
+
{/* Content */}
|
|
347
|
+
{!state.minimized && (
|
|
348
|
+
<Box
|
|
349
|
+
style={{
|
|
350
|
+
flex: 1,
|
|
351
|
+
overflow: 'auto',
|
|
352
|
+
padding: 12,
|
|
353
|
+
}}
|
|
354
|
+
>
|
|
355
|
+
{children}
|
|
356
|
+
</Box>
|
|
357
|
+
)}
|
|
358
|
+
|
|
359
|
+
{/* Resize handle */}
|
|
360
|
+
{resizable && !state.minimized && !state.maximized && (
|
|
361
|
+
<Box
|
|
362
|
+
onMouseDown={(e) => {
|
|
363
|
+
e.stopPropagation();
|
|
364
|
+
setIsResizing(true);
|
|
365
|
+
setState((prev) => ({ ...prev, zIndex: getNextZIndex() }));
|
|
366
|
+
}}
|
|
367
|
+
style={{
|
|
368
|
+
position: 'absolute',
|
|
369
|
+
right: 0,
|
|
370
|
+
bottom: 0,
|
|
371
|
+
width: 16,
|
|
372
|
+
height: 16,
|
|
373
|
+
cursor: 'se-resize',
|
|
374
|
+
display: 'flex',
|
|
375
|
+
alignItems: 'center',
|
|
376
|
+
justifyContent: 'center',
|
|
377
|
+
}}
|
|
378
|
+
>
|
|
379
|
+
<IconGripVertical
|
|
380
|
+
size={12}
|
|
381
|
+
style={{ transform: 'rotate(-45deg)', opacity: 0.5 }}
|
|
382
|
+
/>
|
|
383
|
+
</Box>
|
|
384
|
+
)}
|
|
385
|
+
</Paper>
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// =============================================================================
|
|
390
|
+
// useArchbaseFloatingPanel Hook
|
|
391
|
+
// =============================================================================
|
|
392
|
+
|
|
393
|
+
export interface UseArchbaseFloatingPanelOptions {
|
|
394
|
+
/** ID do painel */
|
|
395
|
+
id?: string;
|
|
396
|
+
/** Título */
|
|
397
|
+
title?: string;
|
|
398
|
+
/** Largura inicial */
|
|
399
|
+
width?: number;
|
|
400
|
+
/** Altura inicial */
|
|
401
|
+
height?: number;
|
|
402
|
+
/** Posição inicial */
|
|
403
|
+
initialPosition?: { x: number; y: number };
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
export interface UseArchbaseFloatingPanelReturn {
|
|
407
|
+
/** Se o painel está visível */
|
|
408
|
+
isOpen: boolean;
|
|
409
|
+
/** Abrir o painel */
|
|
410
|
+
open: () => void;
|
|
411
|
+
/** Fechar o painel */
|
|
412
|
+
close: () => void;
|
|
413
|
+
/** Toggle visibilidade */
|
|
414
|
+
toggle: () => void;
|
|
415
|
+
/** Props para o painel */
|
|
416
|
+
panelProps: Partial<ArchbaseFloatingPanelProps>;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
export function useArchbaseFloatingPanel(
|
|
420
|
+
options: UseArchbaseFloatingPanelOptions = {}
|
|
421
|
+
): UseArchbaseFloatingPanelReturn {
|
|
422
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
423
|
+
|
|
424
|
+
const open = useCallback(() => setIsOpen(true), []);
|
|
425
|
+
const close = useCallback(() => setIsOpen(false), []);
|
|
426
|
+
const toggle = useCallback(() => setIsOpen((prev) => !prev), []);
|
|
427
|
+
|
|
428
|
+
const panelProps: Partial<ArchbaseFloatingPanelProps> = {
|
|
429
|
+
id: options.id,
|
|
430
|
+
title: options.title,
|
|
431
|
+
width: options.width,
|
|
432
|
+
height: options.height,
|
|
433
|
+
initialX: options.initialPosition?.x,
|
|
434
|
+
initialY: options.initialPosition?.y,
|
|
435
|
+
defaultVisible: isOpen,
|
|
436
|
+
onClose: close,
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
return {
|
|
440
|
+
isOpen,
|
|
441
|
+
open,
|
|
442
|
+
close,
|
|
443
|
+
toggle,
|
|
444
|
+
panelProps,
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
export default ArchbaseFloatingPanel;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Container Components
|
|
2
|
+
|
|
3
|
+
export { ArchbaseExpansionPanel, ArchbaseExpansionPanelControlled, ArchbaseExpansionPanelSingle } from './ArchbaseExpansionPanel';
|
|
4
|
+
export type {
|
|
5
|
+
ArchbaseExpansionPanelProps,
|
|
6
|
+
ArchbaseExpansionPanelItem,
|
|
7
|
+
ArchbaseExpansionPanelControlledProps,
|
|
8
|
+
ArchbaseExpansionPanelSingleProps,
|
|
9
|
+
} from './ArchbaseExpansionPanel';
|
|
10
|
+
|
|
11
|
+
export { ArchbaseFloatingPanel, useArchbaseFloatingPanel } from './ArchbaseFloatingPanel';
|
|
12
|
+
export type {
|
|
13
|
+
ArchbaseFloatingPanelProps,
|
|
14
|
+
ArchbaseFloatingPanelState,
|
|
15
|
+
UseArchbaseFloatingPanelOptions,
|
|
16
|
+
UseArchbaseFloatingPanelReturn,
|
|
17
|
+
} from './ArchbaseFloatingPanel';
|
|
@@ -76,7 +76,7 @@ export const GridPagination: React.FC<PaginationProps> = ({
|
|
|
76
76
|
<Group className="archbase-data-grid-pagination" gap="lg" justify="space-between">
|
|
77
77
|
{/* Informações sobre registros */}
|
|
78
78
|
{showRecordInfo && (
|
|
79
|
-
<Text size="sm"
|
|
79
|
+
<Text size="sm" c="dimmed">
|
|
80
80
|
{safeTotalRecords === 0 ? (
|
|
81
81
|
tString('archbase:Nenhum registro')
|
|
82
82
|
) : (
|
|
@@ -89,7 +89,7 @@ export const GridPagination: React.FC<PaginationProps> = ({
|
|
|
89
89
|
{/* Seletor de tamanho de página */}
|
|
90
90
|
{showPageSizeSelector && (
|
|
91
91
|
<Group gap="xs">
|
|
92
|
-
<Text size="sm"
|
|
92
|
+
<Text size="sm" c="dimmed">{labels.pageSize || tString('archbase:Registros por página')}:</Text>
|
|
93
93
|
<Select
|
|
94
94
|
size="xs"
|
|
95
95
|
value={safePageSize.toString()}
|