@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,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';