@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,439 @@
|
|
|
1
|
+
import React, { useCallback, useMemo, useState } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
DatePickerInput,
|
|
4
|
+
DatePickerInputProps,
|
|
5
|
+
DatesRangeValue,
|
|
6
|
+
DateValue,
|
|
7
|
+
} from '@mantine/dates';
|
|
8
|
+
import {
|
|
9
|
+
Box,
|
|
10
|
+
Button,
|
|
11
|
+
Group,
|
|
12
|
+
Popover,
|
|
13
|
+
Stack,
|
|
14
|
+
Text,
|
|
15
|
+
Divider,
|
|
16
|
+
SimpleGrid,
|
|
17
|
+
} from '@mantine/core';
|
|
18
|
+
import { IconCalendar } from '@tabler/icons-react';
|
|
19
|
+
import 'dayjs/locale/pt-br';
|
|
20
|
+
|
|
21
|
+
// =============================================================================
|
|
22
|
+
// Types
|
|
23
|
+
// =============================================================================
|
|
24
|
+
|
|
25
|
+
export interface DateRangePreset {
|
|
26
|
+
/** Identificador único */
|
|
27
|
+
id: string;
|
|
28
|
+
/** Label exibido */
|
|
29
|
+
label: string;
|
|
30
|
+
/** Função que retorna o range */
|
|
31
|
+
getValue: () => [Date, Date];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface ArchbaseMultiViewCalendarProps
|
|
35
|
+
extends Omit<
|
|
36
|
+
DatePickerInputProps<'range'>,
|
|
37
|
+
'value' | 'onChange' | 'type' | 'numberOfColumns' | 'presets'
|
|
38
|
+
> {
|
|
39
|
+
/** Valor atual [startDate, endDate] */
|
|
40
|
+
value?: DatesRangeValue;
|
|
41
|
+
/** Callback ao mudar */
|
|
42
|
+
onChange?: (value: DatesRangeValue) => void;
|
|
43
|
+
/** Número de colunas (meses visíveis) */
|
|
44
|
+
numberOfColumns?: number;
|
|
45
|
+
/** Presets de data rápidos */
|
|
46
|
+
presets?: DateRangePreset[];
|
|
47
|
+
/** Mostrar presets */
|
|
48
|
+
showPresets?: boolean;
|
|
49
|
+
/** Locale (padrão: pt-BR) */
|
|
50
|
+
locale?: string;
|
|
51
|
+
/** Formato de exibição */
|
|
52
|
+
valueFormat?: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// =============================================================================
|
|
56
|
+
// Utilities
|
|
57
|
+
// =============================================================================
|
|
58
|
+
|
|
59
|
+
function toDate(value: DateValue): Date | null {
|
|
60
|
+
if (!value) return null;
|
|
61
|
+
if (value instanceof Date) return value;
|
|
62
|
+
return new Date(value);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function formatDate(value: DateValue, locale: string = 'pt-BR'): string {
|
|
66
|
+
const date = toDate(value);
|
|
67
|
+
if (!date) return '';
|
|
68
|
+
return date.toLocaleDateString(locale);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// =============================================================================
|
|
72
|
+
// Default Presets
|
|
73
|
+
// =============================================================================
|
|
74
|
+
|
|
75
|
+
export const defaultDatePresets: DateRangePreset[] = [
|
|
76
|
+
{
|
|
77
|
+
id: 'today',
|
|
78
|
+
label: 'Hoje',
|
|
79
|
+
getValue: () => {
|
|
80
|
+
const today = new Date();
|
|
81
|
+
today.setHours(0, 0, 0, 0);
|
|
82
|
+
const endOfDay = new Date(today);
|
|
83
|
+
endOfDay.setHours(23, 59, 59, 999);
|
|
84
|
+
return [today, endOfDay];
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
id: 'yesterday',
|
|
89
|
+
label: 'Ontem',
|
|
90
|
+
getValue: () => {
|
|
91
|
+
const yesterday = new Date();
|
|
92
|
+
yesterday.setDate(yesterday.getDate() - 1);
|
|
93
|
+
yesterday.setHours(0, 0, 0, 0);
|
|
94
|
+
const endOfYesterday = new Date(yesterday);
|
|
95
|
+
endOfYesterday.setHours(23, 59, 59, 999);
|
|
96
|
+
return [yesterday, endOfYesterday];
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: 'last7days',
|
|
101
|
+
label: 'Últimos 7 dias',
|
|
102
|
+
getValue: () => {
|
|
103
|
+
const end = new Date();
|
|
104
|
+
end.setHours(23, 59, 59, 999);
|
|
105
|
+
const start = new Date();
|
|
106
|
+
start.setDate(start.getDate() - 6);
|
|
107
|
+
start.setHours(0, 0, 0, 0);
|
|
108
|
+
return [start, end];
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
id: 'last30days',
|
|
113
|
+
label: 'Últimos 30 dias',
|
|
114
|
+
getValue: () => {
|
|
115
|
+
const end = new Date();
|
|
116
|
+
end.setHours(23, 59, 59, 999);
|
|
117
|
+
const start = new Date();
|
|
118
|
+
start.setDate(start.getDate() - 29);
|
|
119
|
+
start.setHours(0, 0, 0, 0);
|
|
120
|
+
return [start, end];
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
id: 'thisWeek',
|
|
125
|
+
label: 'Esta semana',
|
|
126
|
+
getValue: () => {
|
|
127
|
+
const today = new Date();
|
|
128
|
+
const dayOfWeek = today.getDay();
|
|
129
|
+
const start = new Date(today);
|
|
130
|
+
start.setDate(today.getDate() - dayOfWeek);
|
|
131
|
+
start.setHours(0, 0, 0, 0);
|
|
132
|
+
const end = new Date(start);
|
|
133
|
+
end.setDate(start.getDate() + 6);
|
|
134
|
+
end.setHours(23, 59, 59, 999);
|
|
135
|
+
return [start, end];
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
id: 'lastWeek',
|
|
140
|
+
label: 'Semana passada',
|
|
141
|
+
getValue: () => {
|
|
142
|
+
const today = new Date();
|
|
143
|
+
const dayOfWeek = today.getDay();
|
|
144
|
+
const start = new Date(today);
|
|
145
|
+
start.setDate(today.getDate() - dayOfWeek - 7);
|
|
146
|
+
start.setHours(0, 0, 0, 0);
|
|
147
|
+
const end = new Date(start);
|
|
148
|
+
end.setDate(start.getDate() + 6);
|
|
149
|
+
end.setHours(23, 59, 59, 999);
|
|
150
|
+
return [start, end];
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
id: 'thisMonth',
|
|
155
|
+
label: 'Este mês',
|
|
156
|
+
getValue: () => {
|
|
157
|
+
const start = new Date();
|
|
158
|
+
start.setDate(1);
|
|
159
|
+
start.setHours(0, 0, 0, 0);
|
|
160
|
+
const end = new Date(start.getFullYear(), start.getMonth() + 1, 0);
|
|
161
|
+
end.setHours(23, 59, 59, 999);
|
|
162
|
+
return [start, end];
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
id: 'lastMonth',
|
|
167
|
+
label: 'Mês passado',
|
|
168
|
+
getValue: () => {
|
|
169
|
+
const start = new Date();
|
|
170
|
+
start.setMonth(start.getMonth() - 1);
|
|
171
|
+
start.setDate(1);
|
|
172
|
+
start.setHours(0, 0, 0, 0);
|
|
173
|
+
const end = new Date(start.getFullYear(), start.getMonth() + 1, 0);
|
|
174
|
+
end.setHours(23, 59, 59, 999);
|
|
175
|
+
return [start, end];
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
id: 'thisYear',
|
|
180
|
+
label: 'Este ano',
|
|
181
|
+
getValue: () => {
|
|
182
|
+
const start = new Date(new Date().getFullYear(), 0, 1);
|
|
183
|
+
start.setHours(0, 0, 0, 0);
|
|
184
|
+
const end = new Date(new Date().getFullYear(), 11, 31);
|
|
185
|
+
end.setHours(23, 59, 59, 999);
|
|
186
|
+
return [start, end];
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
id: 'lastYear',
|
|
191
|
+
label: 'Ano passado',
|
|
192
|
+
getValue: () => {
|
|
193
|
+
const year = new Date().getFullYear() - 1;
|
|
194
|
+
const start = new Date(year, 0, 1);
|
|
195
|
+
start.setHours(0, 0, 0, 0);
|
|
196
|
+
const end = new Date(year, 11, 31);
|
|
197
|
+
end.setHours(23, 59, 59, 999);
|
|
198
|
+
return [start, end];
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
];
|
|
202
|
+
|
|
203
|
+
// =============================================================================
|
|
204
|
+
// ArchbaseMultiViewCalendar Component
|
|
205
|
+
// =============================================================================
|
|
206
|
+
|
|
207
|
+
export function ArchbaseMultiViewCalendar({
|
|
208
|
+
value,
|
|
209
|
+
onChange,
|
|
210
|
+
numberOfColumns = 2,
|
|
211
|
+
presets = defaultDatePresets,
|
|
212
|
+
showPresets = true,
|
|
213
|
+
locale = 'pt-BR',
|
|
214
|
+
valueFormat = 'DD/MM/YYYY',
|
|
215
|
+
...props
|
|
216
|
+
}: ArchbaseMultiViewCalendarProps) {
|
|
217
|
+
const handleChange = useCallback(
|
|
218
|
+
(newValue: DatesRangeValue) => {
|
|
219
|
+
onChange?.(newValue);
|
|
220
|
+
},
|
|
221
|
+
[onChange]
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
return (
|
|
225
|
+
<DatePickerInput
|
|
226
|
+
{...props}
|
|
227
|
+
type="range"
|
|
228
|
+
value={value}
|
|
229
|
+
onChange={handleChange}
|
|
230
|
+
numberOfColumns={numberOfColumns}
|
|
231
|
+
locale={locale}
|
|
232
|
+
valueFormat={valueFormat}
|
|
233
|
+
leftSection={<IconCalendar size={16} />}
|
|
234
|
+
popoverProps={{
|
|
235
|
+
...props.popoverProps,
|
|
236
|
+
width: showPresets ? 'auto' : undefined,
|
|
237
|
+
}}
|
|
238
|
+
/>
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// =============================================================================
|
|
243
|
+
// ArchbaseMultiViewCalendarWithPresets Component
|
|
244
|
+
// =============================================================================
|
|
245
|
+
|
|
246
|
+
export interface ArchbaseMultiViewCalendarWithPresetsProps
|
|
247
|
+
extends Omit<ArchbaseMultiViewCalendarProps, 'showPresets'> {
|
|
248
|
+
/** Presets de data rápidos */
|
|
249
|
+
presets?: DateRangePreset[];
|
|
250
|
+
/** Label para seção de presets */
|
|
251
|
+
presetsLabel?: string;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export function ArchbaseMultiViewCalendarWithPresets({
|
|
255
|
+
value,
|
|
256
|
+
onChange,
|
|
257
|
+
numberOfColumns = 2,
|
|
258
|
+
presets = defaultDatePresets,
|
|
259
|
+
presetsLabel = 'Períodos rápidos',
|
|
260
|
+
locale = 'pt-BR',
|
|
261
|
+
valueFormat = 'DD/MM/YYYY',
|
|
262
|
+
...props
|
|
263
|
+
}: ArchbaseMultiViewCalendarWithPresetsProps) {
|
|
264
|
+
const [opened, setOpened] = useState(false);
|
|
265
|
+
|
|
266
|
+
const handleChange = useCallback(
|
|
267
|
+
(newValue: DatesRangeValue) => {
|
|
268
|
+
onChange?.(newValue);
|
|
269
|
+
},
|
|
270
|
+
[onChange]
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
const handlePresetClick = useCallback(
|
|
274
|
+
(preset: DateRangePreset) => {
|
|
275
|
+
const [start, end] = preset.getValue();
|
|
276
|
+
onChange?.([start, end]);
|
|
277
|
+
setOpened(false);
|
|
278
|
+
},
|
|
279
|
+
[onChange]
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
const displayValue = useMemo(() => {
|
|
283
|
+
if (!value || !value[0] || !value[1]) {
|
|
284
|
+
return props.placeholder || 'Selecione um período';
|
|
285
|
+
}
|
|
286
|
+
const startStr = formatDate(value[0], locale);
|
|
287
|
+
const endStr = formatDate(value[1], locale);
|
|
288
|
+
return `${startStr} - ${endStr}`;
|
|
289
|
+
}, [value, props.placeholder, locale]);
|
|
290
|
+
|
|
291
|
+
// Find matching preset
|
|
292
|
+
const activePreset = useMemo(() => {
|
|
293
|
+
if (!value || !value[0] || !value[1]) return null;
|
|
294
|
+
const startDate = toDate(value[0]);
|
|
295
|
+
const endDate = toDate(value[1]);
|
|
296
|
+
if (!startDate || !endDate) return null;
|
|
297
|
+
|
|
298
|
+
const start = startDate.toDateString();
|
|
299
|
+
const end = endDate.toDateString();
|
|
300
|
+
|
|
301
|
+
return presets.find((preset) => {
|
|
302
|
+
const [presetStart, presetEnd] = preset.getValue();
|
|
303
|
+
return presetStart.toDateString() === start && presetEnd.toDateString() === end;
|
|
304
|
+
});
|
|
305
|
+
}, [value, presets]);
|
|
306
|
+
|
|
307
|
+
return (
|
|
308
|
+
<Popover
|
|
309
|
+
opened={opened}
|
|
310
|
+
onChange={setOpened}
|
|
311
|
+
width="auto"
|
|
312
|
+
position="bottom-start"
|
|
313
|
+
shadow="md"
|
|
314
|
+
>
|
|
315
|
+
<Popover.Target>
|
|
316
|
+
<Button
|
|
317
|
+
variant="default"
|
|
318
|
+
leftSection={<IconCalendar size={16} />}
|
|
319
|
+
onClick={() => setOpened((o) => !o)}
|
|
320
|
+
>
|
|
321
|
+
{activePreset ? activePreset.label : displayValue}
|
|
322
|
+
</Button>
|
|
323
|
+
</Popover.Target>
|
|
324
|
+
|
|
325
|
+
<Popover.Dropdown>
|
|
326
|
+
<Group align="flex-start" gap="md" wrap="nowrap">
|
|
327
|
+
{/* Presets */}
|
|
328
|
+
<Stack gap="xs" style={{ minWidth: 150 }}>
|
|
329
|
+
<Text size="xs" fw={500} c="dimmed">
|
|
330
|
+
{presetsLabel}
|
|
331
|
+
</Text>
|
|
332
|
+
{presets.map((preset) => (
|
|
333
|
+
<Button
|
|
334
|
+
key={preset.id}
|
|
335
|
+
variant={activePreset?.id === preset.id ? 'light' : 'subtle'}
|
|
336
|
+
size="xs"
|
|
337
|
+
justify="flex-start"
|
|
338
|
+
onClick={() => handlePresetClick(preset)}
|
|
339
|
+
>
|
|
340
|
+
{preset.label}
|
|
341
|
+
</Button>
|
|
342
|
+
))}
|
|
343
|
+
</Stack>
|
|
344
|
+
|
|
345
|
+
<Divider orientation="vertical" />
|
|
346
|
+
|
|
347
|
+
{/* Calendar */}
|
|
348
|
+
<Box>
|
|
349
|
+
<DatePickerInput
|
|
350
|
+
type="range"
|
|
351
|
+
value={value}
|
|
352
|
+
onChange={handleChange}
|
|
353
|
+
numberOfColumns={numberOfColumns}
|
|
354
|
+
locale={locale}
|
|
355
|
+
valueFormat={valueFormat}
|
|
356
|
+
/>
|
|
357
|
+
</Box>
|
|
358
|
+
</Group>
|
|
359
|
+
</Popover.Dropdown>
|
|
360
|
+
</Popover>
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// =============================================================================
|
|
365
|
+
// ArchbaseDateRangeQuickPicker Component
|
|
366
|
+
// =============================================================================
|
|
367
|
+
|
|
368
|
+
export interface ArchbaseDateRangeQuickPickerProps {
|
|
369
|
+
/** Valor atual [startDate, endDate] */
|
|
370
|
+
value?: DatesRangeValue;
|
|
371
|
+
/** Callback ao mudar */
|
|
372
|
+
onChange?: (value: DatesRangeValue) => void;
|
|
373
|
+
/** Presets disponíveis */
|
|
374
|
+
presets?: DateRangePreset[];
|
|
375
|
+
/** Colunas de presets */
|
|
376
|
+
columns?: number;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
export function ArchbaseDateRangeQuickPicker({
|
|
380
|
+
value,
|
|
381
|
+
onChange,
|
|
382
|
+
presets = defaultDatePresets.slice(0, 6),
|
|
383
|
+
columns = 3,
|
|
384
|
+
}: ArchbaseDateRangeQuickPickerProps) {
|
|
385
|
+
const handlePresetClick = useCallback(
|
|
386
|
+
(preset: DateRangePreset) => {
|
|
387
|
+
const [start, end] = preset.getValue();
|
|
388
|
+
onChange?.([start, end]);
|
|
389
|
+
},
|
|
390
|
+
[onChange]
|
|
391
|
+
);
|
|
392
|
+
|
|
393
|
+
// Find active preset
|
|
394
|
+
const activePresetId = useMemo(() => {
|
|
395
|
+
if (!value || !value[0] || !value[1]) return null;
|
|
396
|
+
const startDate = toDate(value[0]);
|
|
397
|
+
const endDate = toDate(value[1]);
|
|
398
|
+
if (!startDate || !endDate) return null;
|
|
399
|
+
|
|
400
|
+
const start = startDate.toDateString();
|
|
401
|
+
const end = endDate.toDateString();
|
|
402
|
+
|
|
403
|
+
const found = presets.find((preset) => {
|
|
404
|
+
const [presetStart, presetEnd] = preset.getValue();
|
|
405
|
+
return presetStart.toDateString() === start && presetEnd.toDateString() === end;
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
return found?.id ?? null;
|
|
409
|
+
}, [value, presets]);
|
|
410
|
+
|
|
411
|
+
return (
|
|
412
|
+
<SimpleGrid cols={columns} spacing="xs">
|
|
413
|
+
{presets.map((preset) => (
|
|
414
|
+
<Button
|
|
415
|
+
key={preset.id}
|
|
416
|
+
variant={activePresetId === preset.id ? 'filled' : 'light'}
|
|
417
|
+
size="xs"
|
|
418
|
+
onClick={() => handlePresetClick(preset)}
|
|
419
|
+
>
|
|
420
|
+
{preset.label}
|
|
421
|
+
</Button>
|
|
422
|
+
))}
|
|
423
|
+
</SimpleGrid>
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// =============================================================================
|
|
428
|
+
// Utility: Create Custom Preset
|
|
429
|
+
// =============================================================================
|
|
430
|
+
|
|
431
|
+
export function createDatePreset(
|
|
432
|
+
id: string,
|
|
433
|
+
label: string,
|
|
434
|
+
getValue: () => [Date, Date]
|
|
435
|
+
): DateRangePreset {
|
|
436
|
+
return { id, label, getValue };
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
export default ArchbaseMultiViewCalendar;
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import React, { forwardRef, useCallback, useState, useRef } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
NumberInput,
|
|
4
|
+
NumberInputProps,
|
|
5
|
+
MantineSize,
|
|
6
|
+
} from '@mantine/core';
|
|
7
|
+
import { ArchbaseDataSource, DataSourceEvent, DataSourceEventNames } from '@archbase/data';
|
|
8
|
+
import { useArchbaseDidMount, useArchbaseDidUpdate, useArchbaseWillUnmount } from '@archbase/core';
|
|
9
|
+
|
|
10
|
+
export interface ArchbaseNumberStepperProps<T extends object, ID>
|
|
11
|
+
extends Omit<NumberInputProps, 'value' | 'onChange'> {
|
|
12
|
+
/** Fonte de dados */
|
|
13
|
+
dataSource?: ArchbaseDataSource<T, ID>;
|
|
14
|
+
/** Campo do DataSource */
|
|
15
|
+
dataField?: string;
|
|
16
|
+
/** Valor controlado */
|
|
17
|
+
value?: number | string;
|
|
18
|
+
/** Valor padrão */
|
|
19
|
+
defaultValue?: number | string;
|
|
20
|
+
/** Callback de mudança */
|
|
21
|
+
onChange?: (value: number | string) => void;
|
|
22
|
+
/** Valor mínimo */
|
|
23
|
+
min?: number;
|
|
24
|
+
/** Valor máximo */
|
|
25
|
+
max?: number;
|
|
26
|
+
/** Passo de incremento */
|
|
27
|
+
step?: number;
|
|
28
|
+
/** Número de casas decimais */
|
|
29
|
+
decimalScale?: number;
|
|
30
|
+
/** Se deve fixar casas decimais */
|
|
31
|
+
fixedDecimalScale?: boolean;
|
|
32
|
+
/** Separador de milhar */
|
|
33
|
+
thousandSeparator?: string | boolean;
|
|
34
|
+
/** Separador decimal */
|
|
35
|
+
decimalSeparator?: string;
|
|
36
|
+
/** Prefixo */
|
|
37
|
+
prefix?: string;
|
|
38
|
+
/** Sufixo */
|
|
39
|
+
suffix?: string;
|
|
40
|
+
/** Comportamento ao atingir limite */
|
|
41
|
+
clampBehavior?: 'strict' | 'blur' | 'none';
|
|
42
|
+
/** Se permite valores negativos */
|
|
43
|
+
allowNegative?: boolean;
|
|
44
|
+
/** Se permite entrada decimal */
|
|
45
|
+
allowDecimal?: boolean;
|
|
46
|
+
/** Se deve esconder controles */
|
|
47
|
+
hideControls?: boolean;
|
|
48
|
+
/** Tamanho */
|
|
49
|
+
size?: MantineSize;
|
|
50
|
+
/** Se está desabilitado */
|
|
51
|
+
disabled?: boolean;
|
|
52
|
+
/** Se é somente leitura */
|
|
53
|
+
readOnly?: boolean;
|
|
54
|
+
/** Label */
|
|
55
|
+
label?: string;
|
|
56
|
+
/** Descrição */
|
|
57
|
+
description?: string;
|
|
58
|
+
/** Erro */
|
|
59
|
+
error?: string | boolean;
|
|
60
|
+
/** Se é obrigatório */
|
|
61
|
+
required?: boolean;
|
|
62
|
+
/** Placeholder */
|
|
63
|
+
placeholder?: string;
|
|
64
|
+
/** Largura */
|
|
65
|
+
width?: number | string;
|
|
66
|
+
/** Classe CSS */
|
|
67
|
+
className?: string;
|
|
68
|
+
/** Estilo */
|
|
69
|
+
style?: React.CSSProperties;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function ArchbaseNumberStepperInner<T extends object, ID>(
|
|
73
|
+
{
|
|
74
|
+
dataSource,
|
|
75
|
+
dataField,
|
|
76
|
+
value: controlledValue,
|
|
77
|
+
defaultValue,
|
|
78
|
+
onChange,
|
|
79
|
+
min,
|
|
80
|
+
max,
|
|
81
|
+
step = 1,
|
|
82
|
+
decimalScale = 0,
|
|
83
|
+
fixedDecimalScale = false,
|
|
84
|
+
thousandSeparator = '.',
|
|
85
|
+
decimalSeparator = ',',
|
|
86
|
+
prefix,
|
|
87
|
+
suffix,
|
|
88
|
+
clampBehavior = 'blur',
|
|
89
|
+
allowNegative = true,
|
|
90
|
+
allowDecimal = true,
|
|
91
|
+
hideControls = false,
|
|
92
|
+
size = 'sm',
|
|
93
|
+
disabled = false,
|
|
94
|
+
readOnly = false,
|
|
95
|
+
label,
|
|
96
|
+
description,
|
|
97
|
+
error,
|
|
98
|
+
required,
|
|
99
|
+
placeholder,
|
|
100
|
+
width,
|
|
101
|
+
className,
|
|
102
|
+
style,
|
|
103
|
+
...rest
|
|
104
|
+
}: ArchbaseNumberStepperProps<T, ID>,
|
|
105
|
+
ref: React.Ref<HTMLInputElement>
|
|
106
|
+
) {
|
|
107
|
+
const [internalValue, setInternalValue] = useState<number | string>(defaultValue ?? '');
|
|
108
|
+
const innerComponentRef = useRef<any>(null);
|
|
109
|
+
|
|
110
|
+
// Determina o valor atual
|
|
111
|
+
const currentValue = controlledValue !== undefined ? controlledValue : internalValue;
|
|
112
|
+
|
|
113
|
+
const loadDataSourceFieldValue = useCallback(() => {
|
|
114
|
+
if (dataSource && dataField) {
|
|
115
|
+
const fieldValue = dataSource.getFieldValue(dataField);
|
|
116
|
+
setInternalValue(fieldValue ?? '');
|
|
117
|
+
}
|
|
118
|
+
}, [dataSource, dataField]);
|
|
119
|
+
|
|
120
|
+
const fieldChangedListener = useCallback(() => {
|
|
121
|
+
loadDataSourceFieldValue();
|
|
122
|
+
}, [loadDataSourceFieldValue]);
|
|
123
|
+
|
|
124
|
+
const dataSourceEvent = useCallback(
|
|
125
|
+
(event: DataSourceEvent<T>) => {
|
|
126
|
+
if (dataSource && dataField) {
|
|
127
|
+
if (
|
|
128
|
+
event.type === DataSourceEventNames.dataChanged ||
|
|
129
|
+
event.type === DataSourceEventNames.recordChanged ||
|
|
130
|
+
event.type === DataSourceEventNames.afterScroll ||
|
|
131
|
+
event.type === DataSourceEventNames.afterCancel
|
|
132
|
+
) {
|
|
133
|
+
loadDataSourceFieldValue();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
[dataSource, dataField, loadDataSourceFieldValue]
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
useArchbaseDidMount(() => {
|
|
141
|
+
loadDataSourceFieldValue();
|
|
142
|
+
if (dataSource && dataField) {
|
|
143
|
+
dataSource.addListener(dataSourceEvent);
|
|
144
|
+
dataSource.addFieldChangeListener(dataField, fieldChangedListener);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
useArchbaseWillUnmount(() => {
|
|
149
|
+
if (dataSource && dataField) {
|
|
150
|
+
dataSource.removeListener(dataSourceEvent);
|
|
151
|
+
dataSource.removeFieldChangeListener(dataField, fieldChangedListener);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
useArchbaseDidUpdate(() => {
|
|
156
|
+
loadDataSourceFieldValue();
|
|
157
|
+
}, []);
|
|
158
|
+
|
|
159
|
+
const handleChange = useCallback(
|
|
160
|
+
(val: number | string) => {
|
|
161
|
+
// Atualiza DataSource se disponível
|
|
162
|
+
if (dataSource && dataField && !dataSource.isBrowsing()) {
|
|
163
|
+
dataSource.setFieldValue(dataField, val);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Atualiza valor interno se não controlado
|
|
167
|
+
if (controlledValue === undefined) {
|
|
168
|
+
setInternalValue(val);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Callback
|
|
172
|
+
onChange?.(val);
|
|
173
|
+
},
|
|
174
|
+
[controlledValue, dataField, dataSource, onChange]
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
const isReadOnly = readOnly || (dataSource ? dataSource.isBrowsing() : false);
|
|
178
|
+
|
|
179
|
+
return (
|
|
180
|
+
<NumberInput
|
|
181
|
+
ref={ref}
|
|
182
|
+
value={currentValue}
|
|
183
|
+
onChange={handleChange}
|
|
184
|
+
min={min}
|
|
185
|
+
max={max}
|
|
186
|
+
step={step}
|
|
187
|
+
decimalScale={decimalScale}
|
|
188
|
+
fixedDecimalScale={fixedDecimalScale}
|
|
189
|
+
thousandSeparator={thousandSeparator}
|
|
190
|
+
decimalSeparator={decimalSeparator}
|
|
191
|
+
prefix={prefix}
|
|
192
|
+
suffix={suffix}
|
|
193
|
+
clampBehavior={clampBehavior}
|
|
194
|
+
allowNegative={allowNegative}
|
|
195
|
+
allowDecimal={allowDecimal}
|
|
196
|
+
hideControls={hideControls}
|
|
197
|
+
size={size}
|
|
198
|
+
disabled={disabled}
|
|
199
|
+
readOnly={isReadOnly}
|
|
200
|
+
label={label}
|
|
201
|
+
description={description}
|
|
202
|
+
error={error}
|
|
203
|
+
required={required}
|
|
204
|
+
placeholder={placeholder}
|
|
205
|
+
className={className}
|
|
206
|
+
style={{ ...style, width }}
|
|
207
|
+
{...rest}
|
|
208
|
+
/>
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export const ArchbaseNumberStepper = forwardRef(ArchbaseNumberStepperInner) as <
|
|
213
|
+
T extends object = any,
|
|
214
|
+
ID = string
|
|
215
|
+
>(
|
|
216
|
+
props: ArchbaseNumberStepperProps<T, ID> & { ref?: React.Ref<HTMLInputElement> }
|
|
217
|
+
) => React.ReactElement;
|
|
218
|
+
|
|
219
|
+
(ArchbaseNumberStepper as any).displayName = 'ArchbaseNumberStepper';
|