@tree-ia/design-system 1.3.0

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/index.mjs ADDED
@@ -0,0 +1,2927 @@
1
+ import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { createPortal } from "react-dom";
4
+ import { AlertTriangle, Check, CheckCircle, ChevronDown, ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight, Info, LogOut, Moon, Sun, User, X, XCircle } from "lucide-react";
5
+ import { Bar, Line } from "react-chartjs-2";
6
+ import { BarElement, CategoryScale, Chart, Filler, Legend, LineElement, LinearScale, PointElement, Title as Title$1, Tooltip } from "chart.js";
7
+
8
+ //#region src/components/Loading/index.tsx
9
+ const sizeMap = {
10
+ sm: "dashboard-spinner-sm",
11
+ md: "dashboard-spinner-md",
12
+ lg: "dashboard-spinner-lg"
13
+ };
14
+ function Loading({ size = "md", className = "", text, textColor, color, variant = "spinner", fullscreen = false }) {
15
+ const variantClass = variant === "border" ? "dashboard-spinner-border" : "dashboard-spinner";
16
+ const spinnerStyle = color ? { borderTopColor: color } : void 0;
17
+ const spinner = /* @__PURE__ */ jsxs("div", {
18
+ className: `flex flex-col items-center justify-center gap-4 ${className}`,
19
+ children: [/* @__PURE__ */ jsx("div", {
20
+ className: `${variantClass} ${sizeMap[size]}`,
21
+ style: spinnerStyle
22
+ }), text && /* @__PURE__ */ jsx("p", {
23
+ className: "text-sm font-medium animate-pulse",
24
+ style: { color: textColor || color || "var(--dashboard-primary)" },
25
+ children: text
26
+ })]
27
+ });
28
+ if (fullscreen) return /* @__PURE__ */ jsx("div", {
29
+ className: "fixed inset-0 z-50 flex items-center justify-center bg-[var(--dashboard-background,#f2f2f2)]/80 backdrop-blur-sm",
30
+ children: spinner
31
+ });
32
+ return spinner;
33
+ }
34
+
35
+ //#endregion
36
+ //#region src/components/Button/index.tsx
37
+ const cn$18 = (...classes) => classes.filter(Boolean).join(" ");
38
+ function Button({ children, variant = "primary", size = "md", isLoading = false, icon, iconPosition = "left", className, disabled, ...props }) {
39
+ const baseStyles = "font-medium rounded-lg transition-all duration-200 cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed inline-flex items-center justify-center";
40
+ const variantStyles = {
41
+ primary: "bg-[var(--dashboard-primary,#37a501)] text-white hover:opacity-90",
42
+ secondary: "bg-[var(--dashboard-text-secondary,#6b7280)]/20 text-[var(--dashboard-text-primary,#2d2d2d)] hover:bg-[var(--dashboard-text-secondary,#6b7280)]/30",
43
+ danger: "bg-[var(--dashboard-status-danger,#EF4444)] text-white hover:opacity-90",
44
+ ghost: "bg-transparent hover:bg-[var(--dashboard-text-secondary,#6b7280)]/10 text-[var(--dashboard-text-primary,#2d2d2d)]"
45
+ };
46
+ const sizeStyles = {
47
+ sm: "px-2 py-1 text-xs sm:px-3 sm:py-1.5 sm:text-sm",
48
+ md: "px-3 py-1.5 text-sm sm:px-4 sm:py-2 sm:text-base",
49
+ lg: "px-4 py-2 text-base sm:px-6 sm:py-3 sm:text-lg"
50
+ };
51
+ const iconOnlySizeStyles = {
52
+ sm: "w-7 h-7 sm:w-8 sm:h-8",
53
+ md: "w-9 h-9 sm:w-10 sm:h-10",
54
+ lg: "w-10 h-10 sm:w-12 sm:h-12"
55
+ };
56
+ const isIconOnly = !!icon && (children === void 0 || children === null || typeof children === "string" && children.trim() === "");
57
+ return /* @__PURE__ */ jsx("button", {
58
+ className: cn$18(baseStyles, variantStyles[variant], isIconOnly ? iconOnlySizeStyles[size] : sizeStyles[size], className),
59
+ disabled: disabled || isLoading,
60
+ ...props,
61
+ children: isLoading ? /* @__PURE__ */ jsxs("span", {
62
+ className: "flex items-center gap-2",
63
+ children: [/* @__PURE__ */ jsx(Loading, {
64
+ size: "sm",
65
+ color: "currentColor"
66
+ }), "Carregando..."]
67
+ }) : isIconOnly ? icon : /* @__PURE__ */ jsxs(Fragment, { children: [
68
+ icon && iconPosition === "left" && /* @__PURE__ */ jsx("span", {
69
+ className: "mr-2",
70
+ children: icon
71
+ }),
72
+ children,
73
+ icon && iconPosition === "right" && /* @__PURE__ */ jsx("span", {
74
+ className: "ml-2",
75
+ children: icon
76
+ })
77
+ ] })
78
+ });
79
+ }
80
+
81
+ //#endregion
82
+ //#region src/components/Input/index.tsx
83
+ const cn$17 = (...classes) => classes.filter(Boolean).join(" ");
84
+ const Input = React.forwardRef(({ className, type = "text", label, error, children, id, ...props }, ref) => {
85
+ const inputId = id || (label ? `input-${label.toLowerCase().replace(/\s+/g, "-")}` : void 0);
86
+ return /* @__PURE__ */ jsxs("div", {
87
+ className: "w-full",
88
+ children: [
89
+ label && /* @__PURE__ */ jsx("label", {
90
+ htmlFor: inputId,
91
+ className: "block text-sm font-medium text-[var(--dashboard-text-primary,#2d2d2d)] mb-1",
92
+ children: label
93
+ }),
94
+ /* @__PURE__ */ jsxs("div", {
95
+ className: "relative flex items-center w-full",
96
+ children: [/* @__PURE__ */ jsx("input", {
97
+ type,
98
+ id: inputId,
99
+ className: cn$17("flex h-10 w-full rounded-md border border-[var(--dashboard-text-secondary,#6b7280)]/30 bg-[var(--dashboard-surface,#ffffff)] px-3 py-2 text-sm text-[var(--dashboard-text-primary,#2d2d2d)] shadow-sm transition-colors duration-200 focus:border-[var(--dashboard-primary,#37a501)] placeholder:text-[var(--dashboard-text-secondary,#6b7280)] focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50", error ? "border-[var(--dashboard-status-danger,#EF4444)] focus:border-[var(--dashboard-status-danger,#EF4444)]" : void 0, children ? "pr-10" : void 0, className),
100
+ ref,
101
+ ...props
102
+ }), children && /* @__PURE__ */ jsx("div", {
103
+ className: "absolute right-3 flex items-center",
104
+ children
105
+ })]
106
+ }),
107
+ error && /* @__PURE__ */ jsx("p", {
108
+ className: "text-[var(--dashboard-status-danger,#EF4444)] text-xs mt-1",
109
+ children: error
110
+ })
111
+ ]
112
+ });
113
+ });
114
+ Input.displayName = "Input";
115
+
116
+ //#endregion
117
+ //#region src/components/Dropdown/index.tsx
118
+ function Dropdown({ options, value, onChange, label, placeholder = "Selecione uma opção", disabled = false, className = "", containerClassName = "", fullWidth = false, size = "medium", error, variant = "default", customDropdownHeight, icon, fitContent = false, isActive = false }) {
119
+ const [isOpen, setIsOpen] = useState(false);
120
+ const [isVisible, setIsVisible] = useState(false);
121
+ const [position, setPosition] = useState({
122
+ top: 0,
123
+ left: 0,
124
+ width: 0
125
+ });
126
+ const dropdownRef = useRef(null);
127
+ const selectedOption = options.find((option) => option.value === value);
128
+ const selectedStyle = {
129
+ small: {
130
+ container: "h-8 px-2",
131
+ text: "text-xs",
132
+ wrapper: "space-y-1",
133
+ label: "text-sm",
134
+ iconPadding: "pl-8"
135
+ },
136
+ medium: {
137
+ container: "h-10 px-3",
138
+ text: "text-sm",
139
+ wrapper: "space-y-2",
140
+ label: "text-base",
141
+ iconPadding: "pl-10"
142
+ },
143
+ large: {
144
+ container: "h-12 px-4",
145
+ text: "text-lg",
146
+ wrapper: "space-y-3",
147
+ label: "text-lg",
148
+ iconPadding: "pl-12"
149
+ }
150
+ }[size];
151
+ const variantStyles = {
152
+ default: "rounded-lg border border-[var(--dashboard-text-secondary,#6b7280)]/30 hover:border-[var(--dashboard-text-secondary,#6b7280)]/50 focus:outline-none focus:ring-2 focus:ring-[var(--dashboard-primary,#37a501)] focus:border-transparent",
153
+ underline: "border-b border-[var(--dashboard-text-secondary,#6b7280)]/30 rounded-none hover:border-b-[var(--dashboard-text-secondary,#6b7280)]/50",
154
+ simple: "rounded-lg border border-[var(--dashboard-text-secondary,#6b7280)]/20 hover:border-[var(--dashboard-text-secondary,#6b7280)]/30 focus:outline-none",
155
+ compact: "rounded-full hover:bg-[var(--dashboard-text-secondary,#6b7280)]/20 focus:outline-none"
156
+ };
157
+ const variantBackgrounds = {
158
+ default: "bg-[var(--dashboard-surface,#ffffff)]",
159
+ underline: "bg-transparent",
160
+ simple: "bg-[var(--dashboard-surface,#ffffff)]",
161
+ compact: "bg-[var(--dashboard-text-secondary,#6b7280)]/10"
162
+ };
163
+ const calculatePosition = () => {
164
+ if (dropdownRef.current) {
165
+ const rect = dropdownRef.current.getBoundingClientRect();
166
+ setPosition({
167
+ top: rect.bottom + 4,
168
+ left: rect.left,
169
+ width: rect.width
170
+ });
171
+ }
172
+ };
173
+ const toggleDropdown = () => {
174
+ if (!disabled) if (isOpen) handleClose();
175
+ else {
176
+ calculatePosition();
177
+ setIsVisible(true);
178
+ setTimeout(() => setIsOpen(true), 10);
179
+ }
180
+ };
181
+ const handleClose = () => {
182
+ setIsOpen(false);
183
+ setTimeout(() => setIsVisible(false), 150);
184
+ };
185
+ const handleSelect = (option) => {
186
+ onChange(option.value);
187
+ handleClose();
188
+ };
189
+ useEffect(() => {
190
+ const handleClickOutside = (event) => {
191
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
192
+ const portal = document.querySelector(".dashboard-dropdown-portal");
193
+ if (portal && !portal.contains(event.target)) {
194
+ if (isOpen) handleClose();
195
+ }
196
+ }
197
+ };
198
+ document.addEventListener("mousedown", handleClickOutside);
199
+ return () => document.removeEventListener("mousedown", handleClickOutside);
200
+ }, [isOpen]);
201
+ useEffect(() => {
202
+ const handleResize = () => {
203
+ if (isOpen) calculatePosition();
204
+ };
205
+ const handleScroll = (event) => {
206
+ if (isOpen) {
207
+ const portal = document.querySelector(".dashboard-dropdown-portal");
208
+ if (!portal || !portal.contains(event.target)) handleClose();
209
+ }
210
+ };
211
+ window.addEventListener("resize", handleResize);
212
+ window.addEventListener("scroll", handleScroll, true);
213
+ return () => {
214
+ window.removeEventListener("resize", handleResize);
215
+ window.removeEventListener("scroll", handleScroll, true);
216
+ };
217
+ }, [isOpen]);
218
+ return /* @__PURE__ */ jsxs("div", {
219
+ className: `${selectedStyle.wrapper} ${containerClassName} ${fullWidth ? "w-full" : fitContent ? "w-fit" : ""}`,
220
+ children: [
221
+ label && /* @__PURE__ */ jsx("label", {
222
+ className: `block text-[var(--dashboard-text-primary,#2d2d2d)] ${selectedStyle.label}`,
223
+ children: label
224
+ }),
225
+ /* @__PURE__ */ jsxs("div", {
226
+ ref: dropdownRef,
227
+ className: "relative",
228
+ children: [
229
+ icon && /* @__PURE__ */ jsx("div", {
230
+ className: "absolute left-3 top-1/2 transform -translate-y-1/2 text-[var(--dashboard-text-secondary,#6b7280)] h-4 w-4 pointer-events-none",
231
+ children: icon
232
+ }),
233
+ /* @__PURE__ */ jsxs("div", {
234
+ onClick: toggleDropdown,
235
+ className: `flex ${fullWidth ? "w-full" : fitContent ? "w-fit" : "w-full"} items-center justify-between ${selectedStyle.container} ${icon ? selectedStyle.iconPadding : ""} ${error ? "rounded-lg border border-[var(--dashboard-status-danger,#EF4444)]" : disabled ? "border-[var(--dashboard-text-secondary,#6b7280)]/30 bg-[var(--dashboard-text-secondary,#6b7280)]/10" : isActive ? "rounded-lg border border-[var(--dashboard-primary,#37a501)]" : variantStyles[variant]} ${className} cursor-pointer transition-colors duration-200 ${disabled ? "bg-[var(--dashboard-text-secondary,#6b7280)]/10" : selectedOption?.backgroundColor || variantBackgrounds[variant]}`,
236
+ style: selectedOption?.backgroundColor ? { backgroundColor: selectedOption.backgroundColor } : void 0,
237
+ children: [/* @__PURE__ */ jsx("span", {
238
+ className: `block truncate select-none ${selectedStyle.text} ${selectedOption ? selectedOption.color ? "" : "text-[var(--dashboard-text-primary,#2d2d2d)]" : "text-[var(--dashboard-text-secondary,#6b7280)]"} ${disabled ? "text-[var(--dashboard-text-secondary,#6b7280)] opacity-50" : ""}`,
239
+ style: selectedOption?.color ? { color: selectedOption.color } : void 0,
240
+ children: selectedOption ? selectedOption.label : placeholder
241
+ }), /* @__PURE__ */ jsx(ChevronDown, { className: `h-4 w-4 text-[var(--dashboard-text-secondary,#6b7280)] transition-transform duration-200 ${isOpen ? "rotate-180 transform" : ""}` })]
242
+ }),
243
+ isVisible && typeof document !== "undefined" && createPortal(/* @__PURE__ */ jsx("div", {
244
+ className: `dashboard-dropdown-portal overflow-y-auto rounded-lg border border-[var(--dashboard-text-secondary,#6b7280)]/20 bg-[var(--dashboard-surface,#ffffff)] shadow-lg transition-all duration-200 ease-in-out ${isOpen ? `opacity-100 ${customDropdownHeight || "max-h-60"}` : "max-h-0 opacity-0"}`,
245
+ style: {
246
+ position: "fixed",
247
+ top: position.top,
248
+ left: position.left,
249
+ width: position.width,
250
+ zIndex: 9999
251
+ },
252
+ children: /* @__PURE__ */ jsx("ul", {
253
+ className: "py-1",
254
+ children: options.length > 0 ? options.map((option) => {
255
+ const isSelected = option.value === value;
256
+ return /* @__PURE__ */ jsxs("li", {
257
+ "data-modal-ignore": true,
258
+ onClick: () => handleSelect(option),
259
+ className: `cursor-pointer px-3 py-2 text-left select-none hover:bg-[var(--dashboard-text-secondary,#6b7280)]/10 transition-colors flex items-center justify-between ${isSelected ? "text-[var(--dashboard-primary,#37a501)] font-medium" : "text-[var(--dashboard-text-primary,#2d2d2d)]"} ${selectedStyle.text}`,
260
+ children: [/* @__PURE__ */ jsx("span", { children: option.label }), isSelected && /* @__PURE__ */ jsx(Check, { className: "h-4 w-4 text-[var(--dashboard-primary,#37a501)]" })]
261
+ }, option.value);
262
+ }) : /* @__PURE__ */ jsx("li", {
263
+ className: `px-3 py-2 text-[var(--dashboard-text-secondary,#6b7280)] italic ${selectedStyle.text}`,
264
+ children: "Não há opções disponíveis"
265
+ })
266
+ })
267
+ }), document.body)
268
+ ]
269
+ }),
270
+ error && /* @__PURE__ */ jsx("p", {
271
+ className: `mt-1 ${selectedStyle.text} text-[var(--dashboard-status-danger,#EF4444)]`,
272
+ children: error
273
+ })
274
+ ]
275
+ });
276
+ }
277
+
278
+ //#endregion
279
+ //#region src/components/Table/index.tsx
280
+ function Table({ columns, data, onRowClick, isLoading = false, emptyMessage = "Nenhum registro encontrado", emptyIcon, loadingComponent, emptyComponent, keyExtractor, className = "" }) {
281
+ if (isLoading) return loadingComponent ? /* @__PURE__ */ jsx(Fragment, { children: loadingComponent }) : /* @__PURE__ */ jsx(TableSkeleton, {});
282
+ if (data.length === 0) return emptyComponent ? /* @__PURE__ */ jsx(Fragment, { children: emptyComponent }) : /* @__PURE__ */ jsx(TableEmpty, {
283
+ message: emptyMessage,
284
+ icon: emptyIcon
285
+ });
286
+ return /* @__PURE__ */ jsx("div", {
287
+ className: `overflow-x-auto bg-[var(--dashboard-surface,#ffffff)] rounded-lg shadow-sm border border-[var(--dashboard-text-secondary,#6b7280)]/20 ${className}`,
288
+ children: /* @__PURE__ */ jsxs("table", {
289
+ className: "min-w-full divide-y divide-[var(--dashboard-text-secondary,#6b7280)]/20",
290
+ children: [/* @__PURE__ */ jsx(TableHeader, { columns }), /* @__PURE__ */ jsx(TableBody, {
291
+ columns,
292
+ data,
293
+ onRowClick,
294
+ keyExtractor
295
+ })]
296
+ })
297
+ });
298
+ }
299
+ function TableHeader({ columns }) {
300
+ const alignClass = (align) => align === "center" ? "text-center" : align === "right" ? "text-right" : "text-left";
301
+ return /* @__PURE__ */ jsx("thead", {
302
+ className: "bg-[var(--dashboard-text-secondary,#6b7280)]/5",
303
+ children: /* @__PURE__ */ jsx("tr", { children: columns.map((column) => /* @__PURE__ */ jsx("th", {
304
+ scope: "col",
305
+ className: `px-6 py-3 text-xs font-semibold text-[var(--dashboard-text-secondary,#6b7280)] uppercase tracking-wider ${alignClass(column.align)} ${column.width ? `w-[${column.width}]` : ""}`,
306
+ children: column.header
307
+ }, column.key)) })
308
+ });
309
+ }
310
+ function TableBody({ columns, data, onRowClick, keyExtractor }) {
311
+ const alignClass = (align) => align === "center" ? "text-center" : align === "right" ? "text-right" : "text-left";
312
+ return /* @__PURE__ */ jsx("tbody", {
313
+ className: "bg-[var(--dashboard-surface,#ffffff)] divide-y divide-[var(--dashboard-text-secondary,#6b7280)]/20",
314
+ children: data.map((item) => /* @__PURE__ */ jsx("tr", {
315
+ onClick: () => onRowClick?.(item),
316
+ className: `hover:bg-[var(--dashboard-text-secondary,#6b7280)]/5 transition-colors duration-150 ${onRowClick ? "cursor-pointer" : ""}`,
317
+ children: columns.map((column) => /* @__PURE__ */ jsx("td", {
318
+ className: `px-6 py-4 whitespace-nowrap text-sm ${alignClass(column.align)}`,
319
+ children: column.render(item)
320
+ }, column.key))
321
+ }, keyExtractor(item)))
322
+ });
323
+ }
324
+ function TableSkeleton() {
325
+ return /* @__PURE__ */ jsx("div", {
326
+ className: "bg-[var(--dashboard-surface,#ffffff)] rounded-lg shadow-sm border border-[var(--dashboard-text-secondary,#6b7280)]/20 p-6",
327
+ children: /* @__PURE__ */ jsx("div", {
328
+ className: "flex items-center justify-center h-64",
329
+ children: /* @__PURE__ */ jsx(Loading, {
330
+ size: "lg",
331
+ text: "Carregando dados..."
332
+ })
333
+ })
334
+ });
335
+ }
336
+ function TableEmpty({ message, icon }) {
337
+ return /* @__PURE__ */ jsx("div", {
338
+ className: "bg-[var(--dashboard-surface,#ffffff)] rounded-lg shadow-sm border border-[var(--dashboard-text-secondary,#6b7280)]/20 p-12",
339
+ children: /* @__PURE__ */ jsxs("div", {
340
+ className: "text-center",
341
+ children: [icon || /* @__PURE__ */ jsx("svg", {
342
+ className: "mx-auto h-12 w-12 text-[var(--dashboard-text-secondary,#6b7280)]",
343
+ fill: "none",
344
+ stroke: "currentColor",
345
+ viewBox: "0 0 24 24",
346
+ children: /* @__PURE__ */ jsx("path", {
347
+ strokeLinecap: "round",
348
+ strokeLinejoin: "round",
349
+ strokeWidth: 2,
350
+ d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
351
+ })
352
+ }), /* @__PURE__ */ jsx("p", {
353
+ className: "mt-4 text-[var(--dashboard-text-secondary,#6b7280)]",
354
+ children: message
355
+ })]
356
+ })
357
+ });
358
+ }
359
+
360
+ //#endregion
361
+ //#region src/components/Modal/index.tsx
362
+ function Modal({ isOpen, onClose, onSave, title = "", children, showFooter = false, saveButtonText = "Salvar", cancelButtonText = "Cancelar", size = "medium", disableSaveButton = false, saveButtonVariant = "primary", closeOnEscape = true, closeOnOverlayClick = true }) {
363
+ const [isClosing, setIsClosing] = useState(false);
364
+ const [shouldRender, setShouldRender] = useState(isOpen);
365
+ const modalRef = useRef(null);
366
+ const prevIsOpenRef = useRef(false);
367
+ const sizeClasses = {
368
+ small: "max-w-sm",
369
+ medium: "max-w-md",
370
+ large: "max-w-lg",
371
+ largeXl: "max-w-4xl",
372
+ extraLarge: "max-w-screen-xl"
373
+ };
374
+ useEffect(() => {
375
+ if (isOpen && !prevIsOpenRef.current) {
376
+ setShouldRender(true);
377
+ setIsClosing(false);
378
+ } else if (!isOpen && prevIsOpenRef.current) {
379
+ setIsClosing(true);
380
+ const timer = setTimeout(() => {
381
+ setShouldRender(false);
382
+ setIsClosing(false);
383
+ }, 150);
384
+ return () => clearTimeout(timer);
385
+ }
386
+ prevIsOpenRef.current = isOpen;
387
+ }, [isOpen]);
388
+ const handleClose = useCallback(() => {
389
+ setIsClosing(true);
390
+ setTimeout(() => {
391
+ setIsClosing(false);
392
+ onClose();
393
+ }, 150);
394
+ }, [onClose]);
395
+ useEffect(() => {
396
+ if (!closeOnOverlayClick) return;
397
+ const handleClickOutside = (event) => {
398
+ const target = event.target;
399
+ if (modalRef.current && !modalRef.current.contains(event.target) && !target.closest("[data-modal-ignore]")) handleClose();
400
+ };
401
+ if (shouldRender && !isClosing) {
402
+ document.addEventListener("mousedown", handleClickOutside);
403
+ document.body.style.overflow = "hidden";
404
+ }
405
+ return () => {
406
+ document.removeEventListener("mousedown", handleClickOutside);
407
+ if (!shouldRender) document.body.style.overflow = "auto";
408
+ };
409
+ }, [
410
+ shouldRender,
411
+ isClosing,
412
+ handleClose,
413
+ closeOnOverlayClick
414
+ ]);
415
+ useEffect(() => {
416
+ if (!closeOnEscape) return;
417
+ const handleEscKey = (event) => {
418
+ if (event.key === "Escape") handleClose();
419
+ };
420
+ if (shouldRender && !isClosing) document.addEventListener("keydown", handleEscKey);
421
+ return () => {
422
+ document.removeEventListener("keydown", handleEscKey);
423
+ };
424
+ }, [
425
+ shouldRender,
426
+ isClosing,
427
+ handleClose,
428
+ closeOnEscape
429
+ ]);
430
+ if (!shouldRender && !isOpen) return null;
431
+ return /* @__PURE__ */ jsx("div", {
432
+ className: `fixed inset-0 z-[10000] flex items-center justify-center bg-black/50 backdrop-blur-sm p-4 ${isClosing ? "dashboard-animate-fade-out" : "dashboard-animate-fade-in"}`,
433
+ "aria-modal": "true",
434
+ role: "dialog",
435
+ "aria-labelledby": title ? "modal-title" : void 0,
436
+ children: /* @__PURE__ */ jsxs("div", {
437
+ ref: modalRef,
438
+ className: `w-full rounded-lg bg-[var(--dashboard-surface,#ffffff)] border border-[var(--dashboard-text-secondary,#6b7280)]/20 shadow-xl ${sizeClasses[size]} flex max-h-[90vh] flex-col transition-transform duration-200 ease-in-out ${isClosing ? "scale-95 opacity-0" : "scale-100 opacity-100"}`,
439
+ children: [
440
+ /* @__PURE__ */ jsxs("div", {
441
+ className: "flex h-fit items-center justify-between border-b border-[var(--dashboard-text-secondary,#6b7280)]/20 p-4",
442
+ children: [title && /* @__PURE__ */ jsx("h2", {
443
+ id: "modal-title",
444
+ className: "text-xl font-semibold text-[var(--dashboard-text-primary,#2d2d2d)]",
445
+ children: title
446
+ }), /* @__PURE__ */ jsx(Button, {
447
+ variant: "ghost",
448
+ size: "sm",
449
+ onClick: handleClose,
450
+ className: "ml-auto rounded-md",
451
+ "aria-label": "Fechar modal",
452
+ icon: /* @__PURE__ */ jsx(X, { className: "h-5 w-5" })
453
+ })]
454
+ }),
455
+ /* @__PURE__ */ jsx("div", {
456
+ className: "flex-grow overflow-y-auto p-6",
457
+ children
458
+ }),
459
+ showFooter && /* @__PURE__ */ jsxs("div", {
460
+ className: "flex justify-end gap-3 border-t border-[var(--dashboard-text-secondary,#6b7280)]/20 p-4",
461
+ children: [/* @__PURE__ */ jsx(Button, {
462
+ variant: "secondary",
463
+ onClick: handleClose,
464
+ size: "md",
465
+ children: cancelButtonText
466
+ }), /* @__PURE__ */ jsx(Button, {
467
+ variant: saveButtonVariant,
468
+ onClick: onSave,
469
+ disabled: disableSaveButton,
470
+ size: "md",
471
+ children: saveButtonText
472
+ })]
473
+ })
474
+ ]
475
+ })
476
+ });
477
+ }
478
+
479
+ //#endregion
480
+ //#region src/components/Card/index.tsx
481
+ function Card({ children, className = "", title, subtitle, icon, headerActions, showDivider = false }) {
482
+ return /* @__PURE__ */ jsx("div", {
483
+ className: `bg-[var(--dashboard-surface,#ffffff)] rounded-lg shadow-sm border border-[var(--dashboard-text-secondary,#6b7280)]/20 ${className}`,
484
+ children: /* @__PURE__ */ jsxs("div", {
485
+ className: "p-4",
486
+ children: [title && /* @__PURE__ */ jsxs("div", {
487
+ className: showDivider ? "mb-4" : "mb-3",
488
+ children: [
489
+ /* @__PURE__ */ jsxs("div", {
490
+ className: "flex items-center justify-between",
491
+ children: [/* @__PURE__ */ jsxs("div", {
492
+ className: "flex items-center gap-2",
493
+ children: [icon && /* @__PURE__ */ jsx("div", {
494
+ className: "text-[var(--dashboard-text-secondary,#6b7280)]",
495
+ children: icon
496
+ }), /* @__PURE__ */ jsx("h3", {
497
+ className: `${showDivider ? "font-medium" : "text-base font-semibold"} text-[var(--dashboard-text-primary,#2d2d2d)] truncate`,
498
+ children: title
499
+ })]
500
+ }), headerActions && /* @__PURE__ */ jsx("div", {
501
+ className: "flex gap-2",
502
+ children: headerActions
503
+ })]
504
+ }),
505
+ subtitle && /* @__PURE__ */ jsx("p", {
506
+ className: "text-sm text-[var(--dashboard-text-secondary,#6b7280)] mt-1",
507
+ children: subtitle
508
+ }),
509
+ showDivider && /* @__PURE__ */ jsx("div", { className: "w-full h-px bg-[var(--dashboard-text-secondary,#6b7280)]/20 mt-4" })
510
+ ]
511
+ }), children]
512
+ })
513
+ });
514
+ }
515
+
516
+ //#endregion
517
+ //#region src/components/Toast/index.tsx
518
+ const typeConfig = {
519
+ success: {
520
+ bg: "bg-[var(--dashboard-status-success,#10B981)]",
521
+ icon: CheckCircle
522
+ },
523
+ error: {
524
+ bg: "bg-[var(--dashboard-status-danger,#EF4444)]",
525
+ icon: XCircle
526
+ },
527
+ warning: {
528
+ bg: "bg-[var(--dashboard-status-warning,#f59e0b)]",
529
+ icon: AlertTriangle
530
+ },
531
+ info: {
532
+ bg: "bg-[var(--dashboard-status-info,#3b82f6)]",
533
+ icon: Info
534
+ }
535
+ };
536
+ function Toast({ title, subtitle, type = "success", duration = 4e3, onClose, showProgress = true }) {
537
+ const [exiting, setExiting] = useState(false);
538
+ const handleClose = useCallback(() => {
539
+ setExiting(true);
540
+ setTimeout(onClose, 200);
541
+ }, [onClose]);
542
+ useEffect(() => {
543
+ if (duration <= 0) return;
544
+ const timer = setTimeout(() => {
545
+ handleClose();
546
+ }, duration);
547
+ return () => clearTimeout(timer);
548
+ }, [duration, handleClose]);
549
+ const { bg, icon: Icon } = typeConfig[type];
550
+ return /* @__PURE__ */ jsxs("div", {
551
+ className: `${bg} text-white rounded-lg shadow-xl shadow-black/15 overflow-hidden ${exiting ? "dashboard-toast-exit" : "dashboard-toast-enter"}`,
552
+ role: "alert",
553
+ children: [/* @__PURE__ */ jsxs("div", {
554
+ className: "flex items-start gap-3 p-4",
555
+ children: [
556
+ /* @__PURE__ */ jsx(Icon, { className: "w-5 h-5 mt-0.5 shrink-0" }),
557
+ /* @__PURE__ */ jsxs("div", {
558
+ className: "flex-1 min-w-0",
559
+ children: [/* @__PURE__ */ jsx("p", {
560
+ className: "font-semibold text-sm",
561
+ children: title
562
+ }), subtitle && /* @__PURE__ */ jsx("p", {
563
+ className: "text-xs opacity-90 mt-0.5",
564
+ children: subtitle
565
+ })]
566
+ }),
567
+ /* @__PURE__ */ jsx("button", {
568
+ onClick: handleClose,
569
+ className: "shrink-0 hover:opacity-75 transition-opacity cursor-pointer",
570
+ "aria-label": "Fechar",
571
+ children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4" })
572
+ })
573
+ ]
574
+ }), showProgress && duration > 0 && !exiting && /* @__PURE__ */ jsx("div", {
575
+ className: "h-0.5 bg-white/20",
576
+ children: /* @__PURE__ */ jsx("div", {
577
+ className: "h-full bg-white/60",
578
+ style: { animation: `dashboard-toast-progress ${duration}ms linear forwards` }
579
+ })
580
+ })]
581
+ });
582
+ }
583
+
584
+ //#endregion
585
+ //#region src/components/Pagination/index.tsx
586
+ function Pagination({ currentPage, totalPages, onPageChange, itemsPerPage, totalItems, onItemsPerPageChange, itemsPerPageOptions = [
587
+ 10,
588
+ 20,
589
+ 30,
590
+ 50
591
+ ], showPageInfo = true, compact = false, className = "" }) {
592
+ const startItem = (currentPage - 1) * itemsPerPage + 1;
593
+ const endItem = Math.min(currentPage * itemsPerPage, totalItems);
594
+ const getPageNumbers = () => {
595
+ const pages = [];
596
+ const maxVisible = compact ? 3 : 5;
597
+ const halfVisible = Math.floor(maxVisible / 2);
598
+ if (totalPages <= maxVisible + 2) for (let i = 1; i <= totalPages; i++) pages.push(i);
599
+ else {
600
+ pages.push(1);
601
+ let startPage = Math.max(2, currentPage - halfVisible);
602
+ let endPage = Math.min(totalPages - 1, currentPage + halfVisible);
603
+ if (currentPage <= halfVisible + 1) endPage = maxVisible;
604
+ else if (currentPage >= totalPages - halfVisible) startPage = totalPages - maxVisible + 1;
605
+ if (startPage > 2) pages.push("...");
606
+ for (let i = startPage; i <= endPage; i++) pages.push(i);
607
+ if (endPage < totalPages - 1) pages.push("...");
608
+ if (totalPages > 1) pages.push(totalPages);
609
+ }
610
+ return pages;
611
+ };
612
+ const pageNumbers = getPageNumbers();
613
+ const canGoPrevious = currentPage > 1;
614
+ const canGoNext = currentPage < totalPages;
615
+ const handlePageClick = (page) => {
616
+ if (typeof page === "number" && page !== currentPage) onPageChange(page);
617
+ };
618
+ const dropdownOptions = itemsPerPageOptions.map((opt) => ({
619
+ value: String(opt),
620
+ label: String(opt)
621
+ }));
622
+ return /* @__PURE__ */ jsxs("div", {
623
+ className: `flex items-center justify-between gap-4 flex-wrap px-4 py-3 border-t border-[var(--dashboard-text-secondary,#6b7280)]/20 ${className}`,
624
+ children: [
625
+ onItemsPerPageChange && !compact && /* @__PURE__ */ jsxs("div", {
626
+ className: "hidden md:flex items-center gap-2",
627
+ children: [/* @__PURE__ */ jsx(Dropdown, {
628
+ options: dropdownOptions,
629
+ value: String(itemsPerPage),
630
+ onChange: (val) => onItemsPerPageChange(Number(val)),
631
+ size: "small",
632
+ variant: "compact",
633
+ fitContent: true
634
+ }), /* @__PURE__ */ jsx("span", {
635
+ className: "text-sm text-[var(--dashboard-text-secondary,#6b7280)]",
636
+ children: "Itens por página"
637
+ })]
638
+ }),
639
+ showPageInfo && /* @__PURE__ */ jsx("div", {
640
+ className: "text-sm text-[var(--dashboard-text-secondary,#6b7280)]",
641
+ children: totalItems > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("span", {
642
+ className: "hidden sm:inline",
643
+ children: [
644
+ "Mostrando ",
645
+ startItem,
646
+ " - ",
647
+ endItem,
648
+ " de ",
649
+ totalItems,
650
+ " itens"
651
+ ]
652
+ }), /* @__PURE__ */ jsxs("span", {
653
+ className: "sm:hidden",
654
+ children: [
655
+ startItem,
656
+ "-",
657
+ endItem,
658
+ " de ",
659
+ totalItems
660
+ ]
661
+ })] }) : /* @__PURE__ */ jsx("span", { children: "Nenhum item encontrado" })
662
+ }),
663
+ /* @__PURE__ */ jsxs("div", {
664
+ className: "flex items-center gap-1",
665
+ children: [
666
+ !compact && /* @__PURE__ */ jsx("div", {
667
+ className: "hidden md:block",
668
+ children: /* @__PURE__ */ jsx(Button, {
669
+ variant: "ghost",
670
+ size: "sm",
671
+ onClick: () => handlePageClick(1),
672
+ disabled: !canGoPrevious,
673
+ icon: /* @__PURE__ */ jsx(ChevronsLeft, { size: 16 }),
674
+ "aria-label": "Primeira página"
675
+ })
676
+ }),
677
+ /* @__PURE__ */ jsx(Button, {
678
+ variant: "ghost",
679
+ size: "sm",
680
+ onClick: () => handlePageClick(currentPage - 1),
681
+ disabled: !canGoPrevious,
682
+ icon: /* @__PURE__ */ jsx(ChevronLeft, { size: 16 }),
683
+ "aria-label": "Página anterior"
684
+ }),
685
+ /* @__PURE__ */ jsx("div", {
686
+ className: "flex items-center gap-1",
687
+ children: pageNumbers.map((page, index) => /* @__PURE__ */ jsx(React.Fragment, { children: page === "..." ? /* @__PURE__ */ jsx("span", {
688
+ className: "px-2 text-[var(--dashboard-text-secondary,#6b7280)]",
689
+ children: "..."
690
+ }) : /* @__PURE__ */ jsx(Button, {
691
+ variant: page === currentPage ? "primary" : "ghost",
692
+ size: "sm",
693
+ onClick: () => handlePageClick(page),
694
+ className: `min-w-[32px] h-8 !px-2 ${page === currentPage ? "font-medium" : ""}`,
695
+ "aria-label": `Página ${page}`,
696
+ "aria-current": page === currentPage ? "page" : void 0,
697
+ children: page
698
+ }) }, `${page}-${index}`))
699
+ }),
700
+ /* @__PURE__ */ jsx(Button, {
701
+ variant: "ghost",
702
+ size: "sm",
703
+ onClick: () => handlePageClick(currentPage + 1),
704
+ disabled: !canGoNext,
705
+ icon: /* @__PURE__ */ jsx(ChevronRight, { size: 16 }),
706
+ "aria-label": "Próxima página"
707
+ }),
708
+ !compact && /* @__PURE__ */ jsx("div", {
709
+ className: "hidden md:block",
710
+ children: /* @__PURE__ */ jsx(Button, {
711
+ variant: "ghost",
712
+ size: "sm",
713
+ onClick: () => handlePageClick(totalPages),
714
+ disabled: !canGoNext,
715
+ icon: /* @__PURE__ */ jsx(ChevronsRight, { size: 16 }),
716
+ "aria-label": "Última página"
717
+ })
718
+ })
719
+ ]
720
+ })
721
+ ]
722
+ });
723
+ }
724
+
725
+ //#endregion
726
+ //#region src/components/FormField/index.tsx
727
+ function FormField({ label, name, type = "text", value, onChange, error, required = false, placeholder, disabled = false, className = "" }) {
728
+ return /* @__PURE__ */ jsxs("div", {
729
+ className,
730
+ children: [
731
+ /* @__PURE__ */ jsxs("label", {
732
+ htmlFor: name,
733
+ className: "block text-sm font-medium text-[var(--dashboard-text-primary,#2d2d2d)] mb-1",
734
+ children: [
735
+ label,
736
+ " ",
737
+ required && /* @__PURE__ */ jsx("span", {
738
+ className: "text-[var(--dashboard-status-danger,#EF4444)]",
739
+ children: "*"
740
+ })
741
+ ]
742
+ }),
743
+ /* @__PURE__ */ jsx(Input, {
744
+ type,
745
+ id: name,
746
+ name,
747
+ value,
748
+ onChange: (e) => onChange(e.target.value),
749
+ disabled,
750
+ placeholder,
751
+ className: error ? "border-[var(--dashboard-status-danger,#EF4444)] focus:border-[var(--dashboard-status-danger,#EF4444)]" : ""
752
+ }),
753
+ error && /* @__PURE__ */ jsx("p", {
754
+ className: "text-[var(--dashboard-status-danger,#EF4444)] text-xs mt-1",
755
+ children: error
756
+ })
757
+ ]
758
+ });
759
+ }
760
+
761
+ //#endregion
762
+ //#region src/components/Tabs/index.tsx
763
+ const cn$16 = (...classes) => classes.filter(Boolean).join(" ");
764
+ function Tabs({ tabs, activeTab, onChange, variant = "underline", className }) {
765
+ if (variant === "pill") return /* @__PURE__ */ jsx("div", {
766
+ className: cn$16("flex flex-wrap gap-2", className),
767
+ role: "tablist",
768
+ children: tabs.map((tab) => {
769
+ const isActive = activeTab === tab.id;
770
+ return /* @__PURE__ */ jsxs("button", {
771
+ onClick: () => onChange(tab.id),
772
+ className: cn$16("flex items-center gap-2 px-4 py-2 rounded-full text-sm font-medium transition-colors cursor-pointer", isActive ? "bg-[var(--dashboard-primary,#37a501)] text-white" : "bg-[var(--dashboard-text-secondary,#6b7280)]/10 text-[var(--dashboard-text-secondary,#6b7280)] hover:bg-[var(--dashboard-text-secondary,#6b7280)]/20"),
773
+ role: "tab",
774
+ "aria-selected": isActive,
775
+ children: [
776
+ tab.icon && /* @__PURE__ */ jsx("span", {
777
+ className: "flex-shrink-0",
778
+ children: tab.icon
779
+ }),
780
+ tab.label,
781
+ tab.count !== void 0 && /* @__PURE__ */ jsx("span", {
782
+ className: cn$16("ml-1 text-xs rounded-full px-1.5 py-0.5", isActive ? "bg-white/20 text-white" : "bg-[var(--dashboard-text-secondary,#6b7280)]/10 text-[var(--dashboard-text-secondary,#6b7280)]"),
783
+ children: tab.count
784
+ })
785
+ ]
786
+ }, tab.id);
787
+ })
788
+ });
789
+ return /* @__PURE__ */ jsx("div", {
790
+ className: cn$16("border-b border-[var(--dashboard-text-secondary,#6b7280)]/20", className),
791
+ children: /* @__PURE__ */ jsx("nav", {
792
+ className: "flex gap-6",
793
+ "aria-label": "Tabs",
794
+ children: tabs.map((tab) => {
795
+ const isActive = activeTab === tab.id;
796
+ return /* @__PURE__ */ jsxs("button", {
797
+ onClick: () => onChange(tab.id),
798
+ className: cn$16("relative pb-3 px-1 text-sm font-medium transition-colors border-b-2 flex items-center gap-2 cursor-pointer", isActive ? "text-[var(--dashboard-primary,#37a501)] border-[var(--dashboard-primary,#37a501)]" : "text-[var(--dashboard-text-secondary,#6b7280)] hover:text-[var(--dashboard-text-primary,#2d2d2d)] border-transparent"),
799
+ role: "tab",
800
+ "aria-selected": isActive,
801
+ children: [
802
+ tab.icon && /* @__PURE__ */ jsx("span", {
803
+ className: "flex-shrink-0",
804
+ children: tab.icon
805
+ }),
806
+ tab.label,
807
+ tab.count !== void 0 && /* @__PURE__ */ jsx("span", {
808
+ className: cn$16("ml-1 text-xs rounded-full px-1.5 py-0.5", isActive ? "bg-[var(--dashboard-primary,#37a501)]/10 text-[var(--dashboard-primary,#37a501)]" : "bg-[var(--dashboard-text-secondary,#6b7280)]/10 text-[var(--dashboard-text-secondary,#6b7280)]"),
809
+ children: tab.count
810
+ })
811
+ ]
812
+ }, tab.id);
813
+ })
814
+ })
815
+ });
816
+ }
817
+
818
+ //#endregion
819
+ //#region src/components/DateRangePicker/index.tsx
820
+ const cn$15 = (...classes) => classes.filter(Boolean).join(" ");
821
+ const locales = {
822
+ pt: {
823
+ months: [
824
+ "Janeiro",
825
+ "Fevereiro",
826
+ "Março",
827
+ "Abril",
828
+ "Maio",
829
+ "Junho",
830
+ "Julho",
831
+ "Agosto",
832
+ "Setembro",
833
+ "Outubro",
834
+ "Novembro",
835
+ "Dezembro"
836
+ ],
837
+ weekDays: [
838
+ "D",
839
+ "S",
840
+ "T",
841
+ "Q",
842
+ "Q",
843
+ "S",
844
+ "S"
845
+ ],
846
+ prevMonth: "Mês anterior",
847
+ nextMonth: "Próximo mês"
848
+ },
849
+ en: {
850
+ months: [
851
+ "January",
852
+ "February",
853
+ "March",
854
+ "April",
855
+ "May",
856
+ "June",
857
+ "July",
858
+ "August",
859
+ "September",
860
+ "October",
861
+ "November",
862
+ "December"
863
+ ],
864
+ weekDays: [
865
+ "S",
866
+ "M",
867
+ "T",
868
+ "W",
869
+ "T",
870
+ "F",
871
+ "S"
872
+ ],
873
+ prevMonth: "Previous month",
874
+ nextMonth: "Next month"
875
+ }
876
+ };
877
+ function DateRangePicker({ value, onChange, locale = "pt", className }) {
878
+ const [currentMonth, setCurrentMonth] = useState(/* @__PURE__ */ new Date());
879
+ const l = locales[locale];
880
+ const getDaysInMonth = (date) => {
881
+ const year = date.getFullYear();
882
+ const month = date.getMonth();
883
+ const firstDay = new Date(year, month, 1);
884
+ const daysInMonth = new Date(year, month + 1, 0).getDate();
885
+ const startDayOfWeek = firstDay.getDay();
886
+ const days = [];
887
+ for (let i = 0; i < startDayOfWeek; i++) days.push(null);
888
+ for (let i = 1; i <= daysInMonth; i++) days.push(i);
889
+ return days;
890
+ };
891
+ const handleDayClick = (day) => {
892
+ const selectedDate = new Date(currentMonth.getFullYear(), currentMonth.getMonth(), day);
893
+ if (!value.start || value.start && value.end) onChange({
894
+ start: selectedDate,
895
+ end: null
896
+ });
897
+ else if (value.start && !value.end) if (selectedDate >= value.start) onChange({
898
+ start: value.start,
899
+ end: selectedDate
900
+ });
901
+ else onChange({
902
+ start: selectedDate,
903
+ end: value.start
904
+ });
905
+ };
906
+ const isDateInRange = (day) => {
907
+ if (!value.start || !value.end) return false;
908
+ const date = new Date(currentMonth.getFullYear(), currentMonth.getMonth(), day);
909
+ return date > value.start && date < value.end;
910
+ };
911
+ const isStartDate = (day) => {
912
+ if (!value.start) return false;
913
+ return new Date(currentMonth.getFullYear(), currentMonth.getMonth(), day).getTime() === value.start.getTime();
914
+ };
915
+ const isEndDate = (day) => {
916
+ if (!value.end) return false;
917
+ return new Date(currentMonth.getFullYear(), currentMonth.getMonth(), day).getTime() === value.end.getTime();
918
+ };
919
+ const previousMonth = () => {
920
+ setCurrentMonth(new Date(currentMonth.getFullYear(), currentMonth.getMonth() - 1));
921
+ };
922
+ const nextMonth = () => {
923
+ setCurrentMonth(new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1));
924
+ };
925
+ const days = getDaysInMonth(currentMonth);
926
+ return /* @__PURE__ */ jsxs("div", {
927
+ className: cn$15("w-64 bg-[var(--dashboard-surface,#ffffff)] rounded-lg p-4 shadow-sm border border-[var(--dashboard-text-secondary,#6b7280)]/20", className),
928
+ children: [/* @__PURE__ */ jsxs("div", {
929
+ className: "flex items-center justify-between mb-4",
930
+ children: [
931
+ /* @__PURE__ */ jsx("button", {
932
+ onClick: previousMonth,
933
+ className: "p-1 hover:bg-[var(--dashboard-text-secondary,#6b7280)]/10 rounded transition-colors cursor-pointer",
934
+ "aria-label": l.prevMonth,
935
+ children: /* @__PURE__ */ jsx(ChevronLeft, { className: "w-4 h-4 text-[var(--dashboard-text-primary,#2d2d2d)]" })
936
+ }),
937
+ /* @__PURE__ */ jsxs("h2", {
938
+ className: "text-base font-semibold text-[var(--dashboard-text-primary,#2d2d2d)]",
939
+ children: [
940
+ l.months[currentMonth.getMonth()],
941
+ " ",
942
+ currentMonth.getFullYear()
943
+ ]
944
+ }),
945
+ /* @__PURE__ */ jsx("button", {
946
+ onClick: nextMonth,
947
+ className: "p-1 hover:bg-[var(--dashboard-text-secondary,#6b7280)]/10 rounded transition-colors cursor-pointer",
948
+ "aria-label": l.nextMonth,
949
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "w-4 h-4 text-[var(--dashboard-text-primary,#2d2d2d)]" })
950
+ })
951
+ ]
952
+ }), /* @__PURE__ */ jsxs("div", {
953
+ className: "grid grid-cols-7",
954
+ children: [l.weekDays.map((day, index) => /* @__PURE__ */ jsx("div", {
955
+ className: "h-8 w-8 flex items-center justify-center text-xs font-medium text-[var(--dashboard-text-secondary,#6b7280)]",
956
+ children: day
957
+ }, index)), days.map((day, index) => {
958
+ if (day === null) return /* @__PURE__ */ jsx("div", { className: "h-8 w-8" }, `empty-${index}`);
959
+ const inRange = isDateInRange(day);
960
+ const isStart = isStartDate(day);
961
+ const isEnd = isEndDate(day);
962
+ const isSelected = isStart || isEnd;
963
+ return /* @__PURE__ */ jsxs("div", {
964
+ className: "relative h-8 w-8",
965
+ children: [value.start && value.end && (inRange || isStart || isEnd) && /* @__PURE__ */ jsx("div", { className: cn$15("absolute inset-0 bg-[var(--dashboard-text-secondary,#6b7280)]/10", isStart && "rounded-l-full", isEnd && "rounded-r-full") }), /* @__PURE__ */ jsx("button", {
966
+ onClick: () => handleDayClick(day),
967
+ className: cn$15("relative h-8 w-8 flex items-center justify-center text-xs font-medium transition-colors z-10 rounded-full cursor-pointer", isSelected ? "bg-[var(--dashboard-primary,#37a501)] text-white hover:opacity-90" : "text-[var(--dashboard-text-primary,#2d2d2d)] hover:bg-[var(--dashboard-text-secondary,#6b7280)]/20"),
968
+ children: day
969
+ })]
970
+ }, day);
971
+ })]
972
+ })]
973
+ });
974
+ }
975
+
976
+ //#endregion
977
+ //#region src/components/Title/index.tsx
978
+ const cn$14 = (...classes) => classes.filter(Boolean).join(" ");
979
+ const defaultSizeByLevel = {
980
+ 1: "text-2xl sm:text-3xl md:text-4xl lg:text-5xl",
981
+ 2: "text-xl sm:text-2xl md:text-3xl lg:text-4xl",
982
+ 3: "text-lg sm:text-xl md:text-2xl lg:text-3xl",
983
+ 4: "text-base sm:text-lg md:text-xl lg:text-2xl",
984
+ 5: "text-sm sm:text-base md:text-lg lg:text-xl",
985
+ 6: "text-xs sm:text-sm md:text-base lg:text-lg"
986
+ };
987
+ const customSizes = {
988
+ xs: "text-xs sm:text-sm",
989
+ sm: "text-sm sm:text-base",
990
+ md: "text-base sm:text-lg",
991
+ lg: "text-lg sm:text-xl md:text-2xl",
992
+ xl: "text-xl sm:text-2xl md:text-3xl",
993
+ "2xl": "text-2xl sm:text-3xl md:text-4xl",
994
+ "3xl": "text-3xl sm:text-4xl md:text-5xl lg:text-6xl"
995
+ };
996
+ const weightStyles = {
997
+ normal: "font-normal",
998
+ medium: "font-medium",
999
+ semibold: "font-semibold",
1000
+ bold: "font-bold",
1001
+ extrabold: "font-extrabold"
1002
+ };
1003
+ const alignStyles = {
1004
+ left: "text-left",
1005
+ center: "text-center",
1006
+ right: "text-right"
1007
+ };
1008
+ function Title({ children, level = 1, size, weight = "bold", align = "left", color, className, ...props }) {
1009
+ const Tag = `h${level}`;
1010
+ const sizeClass = size ? customSizes[size] : defaultSizeByLevel[level];
1011
+ const colorClass = color || "text-[var(--dashboard-text-primary,#2d2d2d)]";
1012
+ return /* @__PURE__ */ jsx(Tag, {
1013
+ className: cn$14(sizeClass, weightStyles[weight], alignStyles[align], colorClass, className),
1014
+ ...props,
1015
+ children
1016
+ });
1017
+ }
1018
+
1019
+ //#endregion
1020
+ //#region src/components/ToggleSwitch/index.tsx
1021
+ const cn$13 = (...classes) => classes.filter(Boolean).join(" ");
1022
+ const sizeConfig$1 = {
1023
+ sm: {
1024
+ track: "h-5 w-9",
1025
+ thumb: "h-3 w-3",
1026
+ translateOn: "translate-x-5",
1027
+ translateOff: "translate-x-1"
1028
+ },
1029
+ md: {
1030
+ track: "h-6 w-11",
1031
+ thumb: "h-4 w-4",
1032
+ translateOn: "translate-x-6",
1033
+ translateOff: "translate-x-1"
1034
+ },
1035
+ lg: {
1036
+ track: "h-7 w-14",
1037
+ thumb: "h-5 w-5",
1038
+ translateOn: "translate-x-8",
1039
+ translateOff: "translate-x-1"
1040
+ }
1041
+ };
1042
+ function ToggleSwitch({ enabled, onChange, disabled = false, size = "md", label, className }) {
1043
+ const config = sizeConfig$1[size];
1044
+ return /* @__PURE__ */ jsxs("div", {
1045
+ className: cn$13("inline-flex items-center gap-2", className),
1046
+ children: [/* @__PURE__ */ jsx("button", {
1047
+ type: "button",
1048
+ role: "switch",
1049
+ "aria-checked": enabled,
1050
+ "aria-label": label,
1051
+ disabled,
1052
+ onClick: () => onChange(!enabled),
1053
+ className: cn$13("relative inline-flex items-center rounded-full transition-colors outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--dashboard-primary,#37a501)]", config.track, enabled ? "bg-[var(--dashboard-primary,#37a501)]" : "bg-[var(--dashboard-text-secondary,#6b7280)]/30", disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"),
1054
+ children: /* @__PURE__ */ jsx("span", { className: cn$13("inline-block transform rounded-full bg-white shadow-sm transition-transform", config.thumb, enabled ? config.translateOn : config.translateOff) })
1055
+ }), label && /* @__PURE__ */ jsx("span", {
1056
+ className: cn$13("text-sm text-[var(--dashboard-text-primary,#2d2d2d)]", disabled && "opacity-50"),
1057
+ children: label
1058
+ })]
1059
+ });
1060
+ }
1061
+
1062
+ //#endregion
1063
+ //#region src/components/BadgeStatus/index.tsx
1064
+ const cn$12 = (...classes) => classes.filter(Boolean).join(" ");
1065
+ const variantStyles = {
1066
+ success: {
1067
+ color: "text-[var(--dashboard-status-success,#10B981)]",
1068
+ bgColor: "bg-[var(--dashboard-status-success,#10B981)]/10"
1069
+ },
1070
+ warning: {
1071
+ color: "text-[var(--dashboard-status-warning,#f59e0b)]",
1072
+ bgColor: "bg-[var(--dashboard-status-warning,#f59e0b)]/10"
1073
+ },
1074
+ danger: {
1075
+ color: "text-[var(--dashboard-status-danger,#EF4444)]",
1076
+ bgColor: "bg-[var(--dashboard-status-danger,#EF4444)]/10"
1077
+ },
1078
+ info: {
1079
+ color: "text-[var(--dashboard-status-info,#3b82f6)]",
1080
+ bgColor: "bg-[var(--dashboard-status-info,#3b82f6)]/10"
1081
+ },
1082
+ neutral: {
1083
+ color: "text-[var(--dashboard-text-secondary,#6b7280)]",
1084
+ bgColor: "bg-[var(--dashboard-text-secondary,#6b7280)]/10"
1085
+ }
1086
+ };
1087
+ const sizeClasses = {
1088
+ sm: "px-2 py-0.5 text-xs",
1089
+ md: "px-3 py-1 text-sm"
1090
+ };
1091
+ function BadgeStatus({ label, variant = "neutral", color, bgColor, size = "md", className }) {
1092
+ const styles = variantStyles[variant];
1093
+ const useCustomColors = color || bgColor;
1094
+ return /* @__PURE__ */ jsx("span", {
1095
+ className: cn$12("inline-flex items-center rounded-full font-medium whitespace-nowrap", sizeClasses[size], !useCustomColors && styles.color, !useCustomColors && styles.bgColor, className),
1096
+ style: useCustomColors ? {
1097
+ color: color || void 0,
1098
+ backgroundColor: bgColor || void 0
1099
+ } : void 0,
1100
+ children: label
1101
+ });
1102
+ }
1103
+
1104
+ //#endregion
1105
+ //#region src/components/Sidebar/index.tsx
1106
+ const cn$11 = (...classes) => classes.filter(Boolean).join(" ");
1107
+ function DefaultLink({ href, className, children }) {
1108
+ return /* @__PURE__ */ jsx("a", {
1109
+ href,
1110
+ className,
1111
+ children
1112
+ });
1113
+ }
1114
+ function Sidebar({ menuItems, logo, collapsedLogo, currentPath, linkComponent: LinkComponent = DefaultLink, isCollapsed = false, onToggleCollapse, user, onUserClick, onLogout, logoutLabel = "Sair", className }) {
1115
+ const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
1116
+ const cubicBezier = "cubic-bezier(0.4, 0, 0.2, 1)";
1117
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("header", {
1118
+ className: "xl:hidden fixed top-0 left-0 right-0 z-40 bg-[var(--dashboard-background,#f2f2f2)] border-b border-[var(--dashboard-text-secondary,#6b7280)]/20",
1119
+ children: [/* @__PURE__ */ jsxs("div", {
1120
+ className: "flex items-center justify-center px-4 h-16 relative",
1121
+ children: [/* @__PURE__ */ jsx("div", {
1122
+ className: "flex items-center",
1123
+ children: logo
1124
+ }), /* @__PURE__ */ jsx("button", {
1125
+ onClick: () => setIsMobileMenuOpen(!isMobileMenuOpen),
1126
+ className: "absolute right-4 inline-flex items-center justify-center rounded-lg text-sm font-medium transition-colors cursor-pointer bg-[var(--dashboard-primary,#37a501)]/10 text-[var(--dashboard-text-primary,#2d2d2d)] hover:bg-[var(--dashboard-primary,#37a501)]/20 h-10 w-10",
1127
+ "aria-label": "Menu",
1128
+ "aria-expanded": isMobileMenuOpen,
1129
+ children: /* @__PURE__ */ jsx(ChevronDown, {
1130
+ size: 24,
1131
+ className: `transition-transform duration-200 ${isMobileMenuOpen ? "rotate-180" : ""}`
1132
+ })
1133
+ })]
1134
+ }), /* @__PURE__ */ jsx("nav", {
1135
+ className: `absolute top-16 left-0 right-0 bg-[var(--dashboard-background,#f2f2f2)] border-b border-[var(--dashboard-text-secondary,#6b7280)]/20 shadow-lg transition-all duration-200 overflow-hidden ${isMobileMenuOpen ? "max-h-[500px]" : "max-h-0"}`,
1136
+ children: /* @__PURE__ */ jsxs("div", {
1137
+ className: "px-4 py-2",
1138
+ children: [menuItems.map((item) => {
1139
+ const Icon = item.icon;
1140
+ const isActive = currentPath === item.href;
1141
+ return /* @__PURE__ */ jsx(LinkComponent, {
1142
+ href: item.href,
1143
+ className: "block",
1144
+ children: /* @__PURE__ */ jsxs("div", {
1145
+ className: cn$11("w-full flex items-center justify-start px-4 py-3 rounded-lg text-sm font-medium transition-colors mb-1 cursor-pointer", isActive ? "bg-[var(--dashboard-primary,#37a501)]/15 text-[var(--dashboard-primary,#37a501)]" : "text-[var(--dashboard-text-primary,#2d2d2d)] hover:bg-[var(--dashboard-primary,#37a501)]/5"),
1146
+ children: [/* @__PURE__ */ jsx(Icon, {
1147
+ size: 20,
1148
+ className: "mr-3 flex-shrink-0"
1149
+ }), /* @__PURE__ */ jsx("span", {
1150
+ className: "whitespace-nowrap",
1151
+ children: item.label
1152
+ })]
1153
+ })
1154
+ }, item.id);
1155
+ }), /* @__PURE__ */ jsxs("div", {
1156
+ className: "mt-2 pt-2 border-t border-[var(--dashboard-text-secondary,#6b7280)]/20 space-y-2",
1157
+ children: [user && /* @__PURE__ */ jsxs("button", {
1158
+ onClick: onUserClick,
1159
+ className: "w-full flex items-center px-4 py-3 rounded-lg bg-[var(--dashboard-text-secondary,#6b7280)]/10 hover:bg-[var(--dashboard-text-secondary,#6b7280)]/20 transition-colors cursor-pointer",
1160
+ children: [/* @__PURE__ */ jsx("div", {
1161
+ className: "flex items-center justify-center w-8 h-8 rounded-full bg-[var(--dashboard-primary,#37a501)]/20 text-[var(--dashboard-text-primary,#2d2d2d)] flex-shrink-0",
1162
+ children: /* @__PURE__ */ jsx(User, { size: 16 })
1163
+ }), /* @__PURE__ */ jsxs("div", {
1164
+ className: "ml-3 text-left",
1165
+ children: [
1166
+ user.subtitle && /* @__PURE__ */ jsx("p", {
1167
+ className: "text-xs text-[var(--dashboard-text-secondary,#6b7280)] whitespace-nowrap truncate",
1168
+ children: user.subtitle
1169
+ }),
1170
+ /* @__PURE__ */ jsx("p", {
1171
+ className: "text-sm font-medium text-[var(--dashboard-text-primary,#2d2d2d)] whitespace-nowrap truncate",
1172
+ children: user.name
1173
+ }),
1174
+ /* @__PURE__ */ jsx("p", {
1175
+ className: "text-xs text-[var(--dashboard-text-secondary,#6b7280)] whitespace-nowrap truncate",
1176
+ children: user.email
1177
+ })
1178
+ ]
1179
+ })]
1180
+ }), onLogout && /* @__PURE__ */ jsxs("button", {
1181
+ onClick: onLogout,
1182
+ className: "w-full flex items-center justify-start px-4 py-3 rounded-lg text-sm font-medium transition-colors cursor-pointer text-[var(--dashboard-text-primary,#2d2d2d)] hover:bg-[var(--dashboard-primary,#37a501)]/5",
1183
+ children: [/* @__PURE__ */ jsx(LogOut, {
1184
+ size: 20,
1185
+ className: "mr-3 flex-shrink-0"
1186
+ }), /* @__PURE__ */ jsx("span", {
1187
+ className: "whitespace-nowrap",
1188
+ children: logoutLabel
1189
+ })]
1190
+ })]
1191
+ })]
1192
+ })
1193
+ })]
1194
+ }), /* @__PURE__ */ jsxs("aside", {
1195
+ className: cn$11("hidden xl:flex xl:flex-col xl:fixed xl:left-0 xl:top-0 xl:h-screen bg-[var(--dashboard-background,#f2f2f2)] border-r border-[var(--dashboard-text-secondary,#6b7280)]/20 overflow-visible", isCollapsed ? "xl:w-[109px]" : "xl:w-[280px]", className),
1196
+ style: { transition: `width 400ms ${cubicBezier}` },
1197
+ children: [onToggleCollapse && /* @__PURE__ */ jsxs("button", {
1198
+ onClick: onToggleCollapse,
1199
+ className: "absolute top-16 -right-[18px] -translate-y-1/2 z-50 flex items-center justify-center cursor-pointer",
1200
+ "aria-label": isCollapsed ? "Expandir sidebar" : "Recolher sidebar",
1201
+ style: {
1202
+ width: "20px",
1203
+ height: "193px"
1204
+ },
1205
+ children: [/* @__PURE__ */ jsx("svg", {
1206
+ xmlns: "http://www.w3.org/2000/svg",
1207
+ width: "20",
1208
+ height: "193",
1209
+ viewBox: "0 0 20 193",
1210
+ fill: "none",
1211
+ className: "absolute inset-0",
1212
+ children: /* @__PURE__ */ jsx("path", {
1213
+ d: "M10.2036 118.86C14.8518 115.918 19.5 107.801 19.5 95.9116C19.5 84.0223 15.672 76.4939 10.2036 72.9634C4.73505 69.4329 2.54765 63.5488 1.72738 55.8994L1.72738 136.512C2.82108 125.921 5.55533 121.802 10.2036 118.86Z",
1214
+ fill: "var(--dashboard-background,#f2f2f2)"
1215
+ })
1216
+ }), /* @__PURE__ */ jsx("svg", {
1217
+ xmlns: "http://www.w3.org/2000/svg",
1218
+ width: "12",
1219
+ height: "12",
1220
+ viewBox: "0 0 12 12",
1221
+ fill: "none",
1222
+ className: `relative z-10 ${isCollapsed ? "" : "rotate-180"}`,
1223
+ style: { transition: `transform 400ms ${cubicBezier}` },
1224
+ children: /* @__PURE__ */ jsx("path", {
1225
+ d: "M4.5 2L8.5 6L4.5 10",
1226
+ stroke: "var(--dashboard-text-primary,#2d2d2d)",
1227
+ strokeWidth: "2",
1228
+ strokeLinecap: "round",
1229
+ strokeLinejoin: "round"
1230
+ })
1231
+ })]
1232
+ }), /* @__PURE__ */ jsxs("div", {
1233
+ className: "flex flex-col h-full overflow-y-auto",
1234
+ children: [
1235
+ /* @__PURE__ */ jsxs("div", {
1236
+ className: "flex justify-center items-center py-6 px-4 border-b border-[var(--dashboard-text-secondary,#6b7280)]/20 overflow-hidden relative",
1237
+ children: [collapsedLogo && /* @__PURE__ */ jsx("div", {
1238
+ className: "absolute inset-0 flex items-center justify-center",
1239
+ style: {
1240
+ opacity: isCollapsed ? 1 : 0,
1241
+ transition: `opacity 400ms ${cubicBezier}`,
1242
+ pointerEvents: isCollapsed ? "auto" : "none"
1243
+ },
1244
+ children: collapsedLogo
1245
+ }), /* @__PURE__ */ jsx("div", {
1246
+ className: "flex items-center justify-center",
1247
+ style: {
1248
+ opacity: !isCollapsed || !collapsedLogo ? 1 : 0,
1249
+ transition: `opacity 400ms ${cubicBezier}`,
1250
+ pointerEvents: !isCollapsed || !collapsedLogo ? "auto" : "none"
1251
+ },
1252
+ children: logo
1253
+ })]
1254
+ }),
1255
+ /* @__PURE__ */ jsx("nav", {
1256
+ className: "flex-1 px-4 py-4 space-y-2 overflow-y-auto",
1257
+ children: menuItems.map((item) => {
1258
+ const Icon = item.icon;
1259
+ const isActive = currentPath === item.href;
1260
+ return /* @__PURE__ */ jsx(LinkComponent, {
1261
+ href: item.href,
1262
+ className: "block",
1263
+ children: /* @__PURE__ */ jsxs("div", {
1264
+ className: cn$11("w-full flex items-center px-4 py-3 rounded-lg text-sm font-medium cursor-pointer", isCollapsed ? "justify-center" : "justify-start", isActive ? "bg-[var(--dashboard-primary,#37a501)]/15 text-[var(--dashboard-primary,#37a501)]" : "text-[var(--dashboard-text-primary,#2d2d2d)] hover:bg-[var(--dashboard-primary,#37a501)]/5"),
1265
+ style: { transition: "background-color 200ms, color 200ms" },
1266
+ title: isCollapsed ? item.label : void 0,
1267
+ children: [/* @__PURE__ */ jsx(Icon, {
1268
+ size: 20,
1269
+ style: {
1270
+ marginRight: isCollapsed ? 0 : "0.75rem",
1271
+ transition: `margin 400ms ${cubicBezier}`
1272
+ }
1273
+ }), /* @__PURE__ */ jsx("span", {
1274
+ className: "whitespace-nowrap overflow-hidden",
1275
+ style: {
1276
+ width: isCollapsed ? 0 : "auto",
1277
+ opacity: isCollapsed ? 0 : 1,
1278
+ transition: `width 400ms ${cubicBezier}, opacity 400ms ${cubicBezier}`
1279
+ },
1280
+ children: item.label
1281
+ })]
1282
+ })
1283
+ }, item.id);
1284
+ })
1285
+ }),
1286
+ /* @__PURE__ */ jsxs("footer", {
1287
+ className: "p-4 border-t border-[var(--dashboard-text-secondary,#6b7280)]/20 space-y-2",
1288
+ children: [user && /* @__PURE__ */ jsxs("button", {
1289
+ onClick: onUserClick,
1290
+ className: cn$11("w-full flex items-center px-4 py-3 rounded-lg bg-[var(--dashboard-text-secondary,#6b7280)]/10 hover:bg-[var(--dashboard-text-secondary,#6b7280)]/20 transition-colors cursor-pointer", isCollapsed ? "justify-center" : "justify-start"),
1291
+ title: isCollapsed ? `${user.subtitle ? user.subtitle + " - " : ""}${user.name}` : void 0,
1292
+ children: [/* @__PURE__ */ jsx("div", {
1293
+ className: "flex items-center justify-center w-8 h-8 rounded-full bg-[var(--dashboard-primary,#37a501)]/20 text-[var(--dashboard-text-primary,#2d2d2d)] flex-shrink-0",
1294
+ children: /* @__PURE__ */ jsx(User, { size: 16 })
1295
+ }), /* @__PURE__ */ jsxs("div", {
1296
+ className: "ml-3 overflow-hidden text-left",
1297
+ style: {
1298
+ width: isCollapsed ? 0 : "auto",
1299
+ opacity: isCollapsed ? 0 : 1,
1300
+ transition: `width 400ms ${cubicBezier}, opacity 400ms ${cubicBezier}`
1301
+ },
1302
+ children: [
1303
+ user.subtitle && /* @__PURE__ */ jsx("p", {
1304
+ className: "text-xs text-[var(--dashboard-text-secondary,#6b7280)] whitespace-nowrap truncate",
1305
+ children: user.subtitle
1306
+ }),
1307
+ /* @__PURE__ */ jsx("p", {
1308
+ className: "text-sm font-medium text-[var(--dashboard-text-primary,#2d2d2d)] whitespace-nowrap truncate",
1309
+ children: user.name
1310
+ }),
1311
+ /* @__PURE__ */ jsx("p", {
1312
+ className: "text-xs text-[var(--dashboard-text-secondary,#6b7280)] whitespace-nowrap truncate",
1313
+ children: user.email
1314
+ })
1315
+ ]
1316
+ })]
1317
+ }), onLogout && /* @__PURE__ */ jsxs("button", {
1318
+ onClick: onLogout,
1319
+ className: cn$11("w-full flex items-center px-4 py-3 rounded-lg text-sm font-medium cursor-pointer text-[var(--dashboard-text-primary,#2d2d2d)] hover:bg-[var(--dashboard-primary,#37a501)]/5", isCollapsed ? "justify-center" : "justify-start"),
1320
+ style: { transition: "background-color 200ms" },
1321
+ title: isCollapsed ? logoutLabel : void 0,
1322
+ children: [/* @__PURE__ */ jsx(LogOut, {
1323
+ size: 20,
1324
+ style: {
1325
+ marginRight: isCollapsed ? 0 : "0.75rem",
1326
+ transition: `margin 400ms ${cubicBezier}`
1327
+ }
1328
+ }), /* @__PURE__ */ jsx("span", {
1329
+ className: "whitespace-nowrap overflow-hidden",
1330
+ style: {
1331
+ width: isCollapsed ? 0 : "auto",
1332
+ opacity: isCollapsed ? 0 : 1,
1333
+ transition: `width 400ms ${cubicBezier}, opacity 400ms ${cubicBezier}`
1334
+ },
1335
+ children: logoutLabel
1336
+ })]
1337
+ })]
1338
+ })
1339
+ ]
1340
+ })]
1341
+ })] });
1342
+ }
1343
+
1344
+ //#endregion
1345
+ //#region src/hooks/useTheme.ts
1346
+ const ThemeContext = createContext(null);
1347
+ function useTheme() {
1348
+ const context = useContext(ThemeContext);
1349
+ if (!context) throw new Error("useTheme must be used within a DashboardProvider");
1350
+ return context;
1351
+ }
1352
+
1353
+ //#endregion
1354
+ //#region src/components/ThemeSwitcher/index.tsx
1355
+ const cn$10 = (...classes) => classes.filter(Boolean).join(" ");
1356
+ function ThemeSwitcher({ className }) {
1357
+ const { resolvedTheme, setTheme } = useTheme();
1358
+ const toggle = () => {
1359
+ setTheme(resolvedTheme === "dark" ? "light" : "dark");
1360
+ };
1361
+ return /* @__PURE__ */ jsxs("button", {
1362
+ type: "button",
1363
+ onClick: toggle,
1364
+ className: cn$10("relative inline-flex items-center justify-center h-9 w-9 rounded-md border border-[var(--dashboard-text-secondary,#6b7280)]/30 bg-[var(--dashboard-surface,#ffffff)] shadow-sm transition-colors cursor-pointer hover:bg-[var(--dashboard-text-secondary,#6b7280)]/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--dashboard-primary,#37a501)] focus-visible:ring-offset-2", className),
1365
+ "aria-label": "Alternar tema",
1366
+ children: [
1367
+ /* @__PURE__ */ jsx(Sun, { className: "h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" }),
1368
+ /* @__PURE__ */ jsx(Moon, { className: "absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" }),
1369
+ /* @__PURE__ */ jsx("span", {
1370
+ className: "sr-only",
1371
+ children: "Alternar tema"
1372
+ })
1373
+ ]
1374
+ });
1375
+ }
1376
+
1377
+ //#endregion
1378
+ //#region src/components/KPICard/index.tsx
1379
+ const cn$9 = (...classes) => classes.filter(Boolean).join(" ");
1380
+ function formatValue(value, format) {
1381
+ switch (format) {
1382
+ case "currency": return new Intl.NumberFormat("pt-BR", {
1383
+ style: "currency",
1384
+ currency: "BRL"
1385
+ }).format(value);
1386
+ case "percentage": return `${value.toFixed(1)}%`;
1387
+ case "rating": return `${value.toFixed(1)}/5.0`;
1388
+ default: return new Intl.NumberFormat("pt-BR").format(value);
1389
+ }
1390
+ }
1391
+ const trendConfigs = {
1392
+ up: {
1393
+ icon: "↑",
1394
+ color: "text-[var(--dashboard-status-success,#10B981)] bg-[var(--dashboard-status-success,#10B981)]/10"
1395
+ },
1396
+ down: {
1397
+ icon: "↓",
1398
+ color: "text-[var(--dashboard-status-danger,#EF4444)] bg-[var(--dashboard-status-danger,#EF4444)]/10"
1399
+ },
1400
+ stable: {
1401
+ icon: "→",
1402
+ color: "text-[var(--dashboard-text-secondary,#6b7280)] bg-[var(--dashboard-text-secondary,#6b7280)]/10"
1403
+ }
1404
+ };
1405
+ function KPICard({ title, value, variation, trend, format = "number", benchmark, isLoading, className }) {
1406
+ if (isLoading) return /* @__PURE__ */ jsx(KPICardSkeleton, { className });
1407
+ const trendConfig = trendConfigs[trend];
1408
+ return /* @__PURE__ */ jsxs("div", {
1409
+ className: cn$9("h-full w-full bg-[var(--dashboard-surface,#ffffff)] rounded-lg shadow-sm p-6 border border-[var(--dashboard-text-secondary,#6b7280)]/20 hover:shadow-md transition-all duration-200 flex flex-col", className),
1410
+ children: [/* @__PURE__ */ jsxs("div", {
1411
+ className: "flex justify-between items-start mb-4",
1412
+ children: [/* @__PURE__ */ jsx("h3", {
1413
+ className: "text-sm font-medium text-[var(--dashboard-text-secondary,#6b7280)] whitespace-nowrap",
1414
+ children: title
1415
+ }), benchmark && /* @__PURE__ */ jsx("span", {
1416
+ className: "text-xs text-[var(--dashboard-text-secondary,#6b7280)]/60 ml-2 whitespace-nowrap flex-shrink-0",
1417
+ title: "Benchmark de referência",
1418
+ children: benchmark
1419
+ })]
1420
+ }), /* @__PURE__ */ jsxs("div", {
1421
+ className: "flex items-center gap-3 flex-1",
1422
+ children: [/* @__PURE__ */ jsx("p", {
1423
+ className: "text-3xl font-bold text-[var(--dashboard-text-primary,#2d2d2d)] whitespace-nowrap",
1424
+ children: formatValue(value, format)
1425
+ }), /* @__PURE__ */ jsxs("div", {
1426
+ className: cn$9("inline-flex items-center gap-1 px-2 py-1 rounded-md flex-shrink-0", trendConfig.color),
1427
+ children: [/* @__PURE__ */ jsx("span", {
1428
+ className: "text-lg",
1429
+ children: trendConfig.icon
1430
+ }), /* @__PURE__ */ jsxs("span", {
1431
+ className: "text-sm font-medium whitespace-nowrap",
1432
+ children: [Math.abs(variation).toFixed(1), "%"]
1433
+ })]
1434
+ })]
1435
+ })]
1436
+ });
1437
+ }
1438
+ function KPICardSkeleton({ className }) {
1439
+ return /* @__PURE__ */ jsxs("div", {
1440
+ className: cn$9("h-full bg-[var(--dashboard-surface,#ffffff)] rounded-lg shadow-sm p-6 border border-[var(--dashboard-text-secondary,#6b7280)]/20 animate-pulse flex flex-col", className),
1441
+ children: [/* @__PURE__ */ jsx("div", { className: "h-4 bg-[var(--dashboard-text-secondary,#6b7280)]/20 rounded w-2/3 mb-4" }), /* @__PURE__ */ jsxs("div", {
1442
+ className: "flex items-center gap-3 flex-1",
1443
+ children: [/* @__PURE__ */ jsx("div", { className: "h-8 bg-[var(--dashboard-text-secondary,#6b7280)]/20 rounded w-1/2" }), /* @__PURE__ */ jsx("div", { className: "h-6 bg-[var(--dashboard-text-secondary,#6b7280)]/20 rounded w-1/4" })]
1444
+ })]
1445
+ });
1446
+ }
1447
+
1448
+ //#endregion
1449
+ //#region src/components/PageLayout/index.tsx
1450
+ const cn$8 = (...classes) => classes.filter(Boolean).join(" ");
1451
+ function PageLayout({ title, description, headerActions, children, contentPadding = true, sidebar, sidebarCollapsed = false, sidebarWidth = 280, sidebarCollapsedWidth = 109, className }) {
1452
+ const marginLeft = sidebar ? sidebarCollapsed ? `max(0px, ${sidebarCollapsedWidth}px)` : `max(0px, ${sidebarWidth}px)` : "0px";
1453
+ return /* @__PURE__ */ jsxs("div", {
1454
+ className: cn$8("min-h-screen bg-[var(--dashboard-background,#f2f2f2)]", className),
1455
+ children: [sidebar, /* @__PURE__ */ jsxs("main", {
1456
+ className: cn$8("pt-16 xl:pt-0", !sidebar && "pt-0"),
1457
+ style: {
1458
+ marginLeft,
1459
+ transition: "margin-left 400ms cubic-bezier(0.4, 0, 0.2, 1)"
1460
+ },
1461
+ children: [
1462
+ /* @__PURE__ */ jsx("style", { children: `
1463
+ @media (max-width: 1279px) {
1464
+ main {
1465
+ margin-left: 0 !important;
1466
+ }
1467
+ }
1468
+ ` }),
1469
+ /* @__PURE__ */ jsxs("div", {
1470
+ className: "border-b border-[var(--dashboard-text-secondary,#6b7280)]/20 px-6 py-4 bg-[var(--dashboard-surface,#ffffff)]",
1471
+ children: [/* @__PURE__ */ jsxs("div", {
1472
+ className: "mb-4",
1473
+ children: [/* @__PURE__ */ jsx("h1", {
1474
+ className: "text-2xl font-bold text-[var(--dashboard-text-primary,#2d2d2d)]",
1475
+ children: title
1476
+ }), description && /* @__PURE__ */ jsx("p", {
1477
+ className: "text-sm text-[var(--dashboard-text-secondary,#6b7280)] mt-1",
1478
+ children: description
1479
+ })]
1480
+ }), headerActions && /* @__PURE__ */ jsx("div", { children: headerActions })]
1481
+ }),
1482
+ /* @__PURE__ */ jsx("div", {
1483
+ className: contentPadding ? "p-6" : "",
1484
+ children
1485
+ })
1486
+ ]
1487
+ })]
1488
+ });
1489
+ }
1490
+
1491
+ //#endregion
1492
+ //#region src/components/ComparisonLineChart/index.tsx
1493
+ Chart.register(CategoryScale, LinearScale, PointElement, LineElement, Title$1, Tooltip, Legend, Filler);
1494
+ const cn$7 = (...classes) => classes.filter(Boolean).join(" ");
1495
+ function ComparisonLineChart({ labels, currentPeriodData, previousPeriodData, currentPeriodLabel = "Período atual", previousPeriodLabel = "Período anterior", title, color, height = 300, className }) {
1496
+ const primaryColor = color || (typeof document !== "undefined" ? getComputedStyle(document.documentElement).getPropertyValue("--dashboard-primary").trim() : "") || "#37a501";
1497
+ const data = {
1498
+ labels,
1499
+ datasets: [{
1500
+ label: currentPeriodLabel,
1501
+ data: currentPeriodData,
1502
+ borderColor: primaryColor,
1503
+ backgroundColor: `${primaryColor}1a`,
1504
+ borderWidth: 2,
1505
+ tension: .4,
1506
+ fill: true,
1507
+ pointRadius: 0,
1508
+ pointHoverRadius: 6,
1509
+ pointHoverBackgroundColor: primaryColor,
1510
+ pointHoverBorderColor: "#fff",
1511
+ pointHoverBorderWidth: 2
1512
+ }, {
1513
+ label: previousPeriodLabel,
1514
+ data: previousPeriodData,
1515
+ borderColor: `${primaryColor}66`,
1516
+ backgroundColor: `${primaryColor}0d`,
1517
+ borderWidth: 2,
1518
+ tension: .4,
1519
+ fill: true,
1520
+ pointRadius: 0,
1521
+ pointHoverRadius: 6,
1522
+ pointHoverBackgroundColor: `${primaryColor}66`,
1523
+ pointHoverBorderColor: "#fff",
1524
+ pointHoverBorderWidth: 2
1525
+ }]
1526
+ };
1527
+ const options = {
1528
+ responsive: true,
1529
+ maintainAspectRatio: false,
1530
+ plugins: {
1531
+ legend: {
1532
+ display: true,
1533
+ position: "bottom",
1534
+ labels: {
1535
+ usePointStyle: true,
1536
+ boxWidth: 6,
1537
+ boxHeight: 6,
1538
+ padding: 15,
1539
+ font: { size: 11 },
1540
+ color: "var(--dashboard-text-secondary, #6b7280)"
1541
+ }
1542
+ },
1543
+ tooltip: {
1544
+ backgroundColor: "rgba(45, 45, 45, 0.95)",
1545
+ titleColor: "#fff",
1546
+ bodyColor: "#fff",
1547
+ borderColor: primaryColor,
1548
+ borderWidth: 1,
1549
+ padding: 12,
1550
+ displayColors: true,
1551
+ usePointStyle: true,
1552
+ boxWidth: 6,
1553
+ boxHeight: 6,
1554
+ titleFont: {
1555
+ size: 12,
1556
+ weight: "bold"
1557
+ },
1558
+ bodyFont: { size: 11 }
1559
+ }
1560
+ },
1561
+ scales: {
1562
+ x: {
1563
+ grid: { display: false },
1564
+ ticks: {
1565
+ color: "var(--dashboard-text-secondary, #6b7280)",
1566
+ font: { size: 11 }
1567
+ }
1568
+ },
1569
+ y: {
1570
+ beginAtZero: true,
1571
+ grid: {
1572
+ color: "rgba(0, 0, 0, 0.05)",
1573
+ drawBorder: false
1574
+ },
1575
+ ticks: {
1576
+ color: "var(--dashboard-text-secondary, #6b7280)",
1577
+ font: { size: 11 },
1578
+ precision: 0
1579
+ }
1580
+ }
1581
+ },
1582
+ interaction: {
1583
+ intersect: false,
1584
+ mode: "index"
1585
+ }
1586
+ };
1587
+ return /* @__PURE__ */ jsxs("div", {
1588
+ className: cn$7("bg-[var(--dashboard-surface,#ffffff)] rounded-lg shadow-sm border border-[var(--dashboard-text-secondary,#6b7280)]/20 p-6", className),
1589
+ children: [title && /* @__PURE__ */ jsx("h3", {
1590
+ className: "text-base font-semibold mb-4 text-[var(--dashboard-text-primary,#2d2d2d)]",
1591
+ children: title
1592
+ }), /* @__PURE__ */ jsx("div", {
1593
+ style: { height },
1594
+ children: /* @__PURE__ */ jsx(Line, {
1595
+ data,
1596
+ options
1597
+ })
1598
+ })]
1599
+ });
1600
+ }
1601
+
1602
+ //#endregion
1603
+ //#region src/components/HorizontalBarChart/index.tsx
1604
+ Chart.register(CategoryScale, LinearScale, BarElement, Title$1, Tooltip, Legend);
1605
+ const cn$6 = (...classes) => classes.filter(Boolean).join(" ");
1606
+ function HorizontalBarChart({ labels, datasets, tabs, title, titleIcon, color, valueLabel = "itens", valueLabelSingular, bestItemLabel = "Melhor item", className }) {
1607
+ const [activeTab, setActiveTab] = useState((tabs ? tabs.map((t) => t.id) : Object.keys(datasets))[0]);
1608
+ const [isMobile, setIsMobile] = useState(false);
1609
+ useEffect(() => {
1610
+ const check = () => setIsMobile(window.innerWidth < 640);
1611
+ check();
1612
+ window.addEventListener("resize", check);
1613
+ return () => window.removeEventListener("resize", check);
1614
+ }, []);
1615
+ const activeData = datasets[activeTab] || [];
1616
+ const maxValue = Math.max(...activeData);
1617
+ const bestLabel = labels[activeData.indexOf(maxValue)];
1618
+ const singular = valueLabelSingular || valueLabel.replace(/s$/, "");
1619
+ const primaryColor = color || (typeof document !== "undefined" ? getComputedStyle(document.documentElement).getPropertyValue("--dashboard-primary").trim() : "") || "#37a501";
1620
+ const minBarValue = maxValue > 0 ? maxValue * .02 : .05;
1621
+ const chartData = {
1622
+ labels,
1623
+ datasets: [{
1624
+ label: valueLabel,
1625
+ data: activeData.map((v) => v === 0 ? minBarValue : v),
1626
+ backgroundColor: primaryColor,
1627
+ borderRadius: isMobile ? 8 : 4,
1628
+ barThickness: isMobile ? 36 : 24
1629
+ }]
1630
+ };
1631
+ const options = {
1632
+ indexAxis: "y",
1633
+ responsive: true,
1634
+ maintainAspectRatio: false,
1635
+ layout: { padding: {
1636
+ right: isMobile ? 35 : 30,
1637
+ left: isMobile ? 10 : 0,
1638
+ top: isMobile ? 15 : 0,
1639
+ bottom: isMobile ? 15 : 0
1640
+ } },
1641
+ plugins: {
1642
+ legend: { display: false },
1643
+ tooltip: {
1644
+ backgroundColor: "rgba(45, 45, 45, 0.95)",
1645
+ titleColor: "#fff",
1646
+ bodyColor: "#fff",
1647
+ borderColor: primaryColor,
1648
+ borderWidth: 1,
1649
+ padding: isMobile ? 6 : 12,
1650
+ displayColors: false,
1651
+ titleFont: {
1652
+ size: isMobile ? 10 : 12,
1653
+ weight: "bold"
1654
+ },
1655
+ bodyFont: { size: isMobile ? 9 : 11 },
1656
+ callbacks: { label: (context) => {
1657
+ const realValue = activeData[context.dataIndex];
1658
+ return realValue === 1 ? `${realValue} ${singular}` : `${realValue} ${valueLabel}`;
1659
+ } }
1660
+ }
1661
+ },
1662
+ scales: {
1663
+ x: {
1664
+ beginAtZero: true,
1665
+ border: { display: false },
1666
+ grid: { display: false },
1667
+ ticks: { display: false }
1668
+ },
1669
+ y: {
1670
+ grid: { display: false },
1671
+ ticks: {
1672
+ color: "var(--dashboard-text-secondary, #6b7280)",
1673
+ font: { size: isMobile ? 16 : 13 },
1674
+ padding: isMobile ? 12 : 4
1675
+ }
1676
+ }
1677
+ }
1678
+ };
1679
+ return /* @__PURE__ */ jsxs("div", {
1680
+ className: cn$6("bg-[var(--dashboard-surface,#ffffff)] rounded-lg shadow-sm border border-[var(--dashboard-text-secondary,#6b7280)]/20 p-5 sm:p-6 min-h-[850px] sm:h-full flex flex-col", className),
1681
+ children: [
1682
+ title && /* @__PURE__ */ jsxs("div", {
1683
+ className: "flex items-center gap-2 mb-4",
1684
+ children: [titleIcon, /* @__PURE__ */ jsx("h3", {
1685
+ className: "text-base font-semibold text-[var(--dashboard-text-primary,#2d2d2d)]",
1686
+ children: title
1687
+ })]
1688
+ }),
1689
+ tabs && tabs.length > 1 && /* @__PURE__ */ jsx("div", {
1690
+ className: "flex gap-2 mb-4 flex-wrap",
1691
+ children: tabs.map((tab) => /* @__PURE__ */ jsx("button", {
1692
+ onClick: () => setActiveTab(tab.id),
1693
+ className: cn$6("px-3.5 py-2 sm:px-4 sm:py-2 rounded-full text-sm font-medium transition-colors whitespace-nowrap cursor-pointer", activeTab === tab.id ? "bg-[var(--dashboard-primary,#37a501)] text-white" : "bg-[var(--dashboard-text-secondary,#6b7280)]/10 text-[var(--dashboard-text-secondary,#6b7280)] hover:bg-[var(--dashboard-text-secondary,#6b7280)]/20"),
1694
+ children: tab.label
1695
+ }, tab.id))
1696
+ }),
1697
+ maxValue > 0 && /* @__PURE__ */ jsxs("div", {
1698
+ className: "mb-4",
1699
+ children: [/* @__PURE__ */ jsx("p", {
1700
+ className: "text-sm sm:text-base text-[var(--dashboard-text-secondary,#6b7280)] mb-1",
1701
+ children: bestItemLabel
1702
+ }), /* @__PURE__ */ jsxs("p", {
1703
+ className: "text-xl sm:text-2xl font-semibold text-[var(--dashboard-text-primary,#2d2d2d)]",
1704
+ children: [
1705
+ bestLabel,
1706
+ " ",
1707
+ /* @__PURE__ */ jsxs("span", {
1708
+ className: "text-base font-normal text-[var(--dashboard-text-secondary,#6b7280)]",
1709
+ children: [
1710
+ maxValue,
1711
+ " ",
1712
+ maxValue === 1 ? singular : valueLabel
1713
+ ]
1714
+ })
1715
+ ]
1716
+ })]
1717
+ }),
1718
+ /* @__PURE__ */ jsx("div", {
1719
+ className: "flex-1 min-h-0",
1720
+ children: /* @__PURE__ */ jsx(Bar, {
1721
+ data: chartData,
1722
+ options
1723
+ }, `chart-${isMobile ? "m" : "d"}`)
1724
+ })
1725
+ ]
1726
+ });
1727
+ }
1728
+
1729
+ //#endregion
1730
+ //#region src/components/VerticalBarChart/index.tsx
1731
+ Chart.register(CategoryScale, LinearScale, BarElement, Title$1, Tooltip, Legend);
1732
+ const cn$5 = (...classes) => classes.filter(Boolean).join(" ");
1733
+ function VerticalBarChart({ labels, data: values, title, titleIcon, color, valueLabel = "itens", valueLabelSingular, bestItemLabel = "Melhor item", labelMaxChars = 3, className }) {
1734
+ const maxValue = Math.max(...values);
1735
+ const bestLabel = labels[values.indexOf(maxValue)];
1736
+ const singular = valueLabelSingular || valueLabel.replace(/s$/, "");
1737
+ const primaryColor = color || (typeof document !== "undefined" ? getComputedStyle(document.documentElement).getPropertyValue("--dashboard-primary").trim() : "") || "#37a501";
1738
+ const chartData = {
1739
+ labels,
1740
+ datasets: [{
1741
+ label: valueLabel,
1742
+ data: values,
1743
+ backgroundColor: primaryColor,
1744
+ borderRadius: {
1745
+ topLeft: 4,
1746
+ topRight: 4
1747
+ },
1748
+ barThickness: 40
1749
+ }]
1750
+ };
1751
+ const options = {
1752
+ responsive: true,
1753
+ maintainAspectRatio: false,
1754
+ plugins: {
1755
+ legend: { display: false },
1756
+ tooltip: {
1757
+ backgroundColor: "rgba(45, 45, 45, 0.95)",
1758
+ titleColor: "#fff",
1759
+ bodyColor: "#fff",
1760
+ borderColor: primaryColor,
1761
+ borderWidth: 1,
1762
+ padding: 12,
1763
+ displayColors: false,
1764
+ titleFont: {
1765
+ size: 12,
1766
+ weight: "bold"
1767
+ },
1768
+ bodyFont: { size: 11 },
1769
+ callbacks: { label: (context) => {
1770
+ const v = context.parsed.y ?? 0;
1771
+ return v === 1 ? `${v} ${singular}` : `${v} ${valueLabel}`;
1772
+ } }
1773
+ }
1774
+ },
1775
+ scales: {
1776
+ x: {
1777
+ grid: { display: false },
1778
+ ticks: {
1779
+ color: "var(--dashboard-text-secondary, #6b7280)",
1780
+ font: { size: 11 },
1781
+ callback: (_value, index) => {
1782
+ return labels[index] ? labels[index].substring(0, labelMaxChars) : String(_value);
1783
+ }
1784
+ }
1785
+ },
1786
+ y: {
1787
+ beginAtZero: true,
1788
+ border: { display: false },
1789
+ grid: { display: false },
1790
+ ticks: { display: false }
1791
+ }
1792
+ }
1793
+ };
1794
+ return /* @__PURE__ */ jsxs("div", {
1795
+ className: cn$5("bg-[var(--dashboard-surface,#ffffff)] rounded-lg shadow-sm border border-[var(--dashboard-text-secondary,#6b7280)]/20 p-6 flex-1 flex flex-col", className),
1796
+ children: [
1797
+ title && /* @__PURE__ */ jsxs("div", {
1798
+ className: "flex items-center gap-2 mb-4",
1799
+ children: [titleIcon, /* @__PURE__ */ jsx("h3", {
1800
+ className: "text-base font-semibold text-[var(--dashboard-text-primary,#2d2d2d)]",
1801
+ children: title
1802
+ })]
1803
+ }),
1804
+ bestLabel && maxValue > 0 && /* @__PURE__ */ jsxs("div", {
1805
+ className: "mb-4",
1806
+ children: [/* @__PURE__ */ jsx("p", {
1807
+ className: "text-sm text-[var(--dashboard-text-secondary,#6b7280)] mb-1",
1808
+ children: bestItemLabel
1809
+ }), /* @__PURE__ */ jsxs("p", {
1810
+ className: "text-lg font-semibold text-[var(--dashboard-text-primary,#2d2d2d)]",
1811
+ children: [
1812
+ bestLabel,
1813
+ " ",
1814
+ /* @__PURE__ */ jsxs("span", {
1815
+ className: "text-sm font-normal text-[var(--dashboard-text-secondary,#6b7280)]",
1816
+ children: [
1817
+ maxValue,
1818
+ " ",
1819
+ maxValue === 1 ? singular : valueLabel
1820
+ ]
1821
+ })
1822
+ ]
1823
+ })]
1824
+ }),
1825
+ /* @__PURE__ */ jsx("div", {
1826
+ className: "flex-1 min-h-0 relative",
1827
+ children: /* @__PURE__ */ jsx(Bar, {
1828
+ data: chartData,
1829
+ options
1830
+ })
1831
+ })
1832
+ ]
1833
+ });
1834
+ }
1835
+
1836
+ //#endregion
1837
+ //#region src/components/ProgressBarList/index.tsx
1838
+ const cn$4 = (...classes) => classes.filter(Boolean).join(" ");
1839
+ function ProgressBarList({ items, title, titleIcon, color, valueLabel = "itens", valueLabelSingular, sortByValue = true, formatValue, className }) {
1840
+ const sortedItems = sortByValue ? [...items].sort((a, b) => b.value - a.value) : items;
1841
+ const maxValue = Math.max(...items.map((i) => i.value));
1842
+ const singular = valueLabelSingular || valueLabel.replace(/s$/, "");
1843
+ const primaryColor = color || (typeof document !== "undefined" ? getComputedStyle(document.documentElement).getPropertyValue("--dashboard-primary").trim() : "") || "#37a501";
1844
+ const defaultFormat = (v) => `${v} ${v === 1 ? singular : valueLabel}`;
1845
+ const fmt = formatValue || defaultFormat;
1846
+ return /* @__PURE__ */ jsxs("div", {
1847
+ className: cn$4("bg-[var(--dashboard-surface,#ffffff)] rounded-lg shadow-sm border border-[var(--dashboard-text-secondary,#6b7280)]/20 p-6 flex-1 flex flex-col", className),
1848
+ children: [title && /* @__PURE__ */ jsxs("div", {
1849
+ className: "flex items-center gap-2 mb-4",
1850
+ children: [titleIcon, /* @__PURE__ */ jsx("h3", {
1851
+ className: "text-base font-semibold text-[var(--dashboard-text-primary,#2d2d2d)]",
1852
+ children: title
1853
+ })]
1854
+ }), /* @__PURE__ */ jsx("div", {
1855
+ className: "space-y-6 flex-1 flex flex-col justify-center",
1856
+ children: sortedItems.map((item, index) => /* @__PURE__ */ jsxs("div", {
1857
+ className: "flex items-center gap-4",
1858
+ children: [/* @__PURE__ */ jsxs("div", {
1859
+ className: "flex items-center gap-4 min-w-[180px]",
1860
+ children: [item.icon && /* @__PURE__ */ jsx("div", {
1861
+ className: "w-10 h-10 rounded-lg flex items-center justify-center flex-shrink-0",
1862
+ style: { backgroundColor: primaryColor },
1863
+ children: /* @__PURE__ */ jsx("div", {
1864
+ className: "w-6 h-6 text-white",
1865
+ children: item.icon
1866
+ })
1867
+ }), /* @__PURE__ */ jsx("span", {
1868
+ className: "text-base font-medium text-[var(--dashboard-text-secondary,#6b7280)]",
1869
+ children: item.label
1870
+ })]
1871
+ }), /* @__PURE__ */ jsxs("div", {
1872
+ className: "flex items-center gap-4 flex-1",
1873
+ children: [/* @__PURE__ */ jsx("div", {
1874
+ className: "flex-1 bg-[var(--dashboard-text-secondary,#6b7280)]/10 rounded-full h-3 overflow-hidden",
1875
+ children: /* @__PURE__ */ jsx("div", {
1876
+ className: "h-full transition-all duration-500 rounded-full",
1877
+ style: {
1878
+ width: maxValue > 0 ? `${item.value / maxValue * 100}%` : "0%",
1879
+ backgroundColor: primaryColor
1880
+ }
1881
+ })
1882
+ }), /* @__PURE__ */ jsx("span", {
1883
+ className: "text-base font-bold min-w-[90px] text-right",
1884
+ style: { color: primaryColor },
1885
+ children: fmt(item.value)
1886
+ })]
1887
+ })]
1888
+ }, index))
1889
+ })]
1890
+ });
1891
+ }
1892
+
1893
+ //#endregion
1894
+ //#region src/components/MetricPanel/index.tsx
1895
+ Chart.register(CategoryScale, LinearScale, PointElement, LineElement, Title$1, Tooltip, Legend, Filler);
1896
+ const cn$3 = (...classes) => classes.filter(Boolean).join(" ");
1897
+ function MetricPanel({ title, titleIcon: TitleIcon, metrics, chartData, color, secondaryColor, onActionClick, actionLabel, isLoading = false, className }) {
1898
+ const [selectedMetricKey, setSelectedMetricKey] = useState(metrics[0]?.key);
1899
+ const [isMobile, setIsMobile] = useState(false);
1900
+ useEffect(() => {
1901
+ const check = () => setIsMobile(window.innerWidth < 768);
1902
+ check();
1903
+ window.addEventListener("resize", check);
1904
+ return () => window.removeEventListener("resize", check);
1905
+ }, []);
1906
+ const currentMetric = metrics.find((m) => m.key === selectedMetricKey) || metrics[0];
1907
+ const primaryColor = color || (typeof document !== "undefined" ? getComputedStyle(document.documentElement).getPropertyValue("--dashboard-primary").trim() : "") || "#37a501";
1908
+ const secColor = secondaryColor || `${primaryColor}66`;
1909
+ const data = {
1910
+ labels: chartData.labels,
1911
+ datasets: [{
1912
+ label: currentMetric.currentLabel,
1913
+ data: chartData.metrics[currentMetric.key]?.currentPeriod || [],
1914
+ borderColor: primaryColor,
1915
+ borderWidth: isMobile ? 3.5 : 3,
1916
+ tension: 0,
1917
+ fill: false,
1918
+ pointRadius: 0,
1919
+ pointHoverRadius: isMobile ? 10 : 8,
1920
+ pointHoverBackgroundColor: primaryColor,
1921
+ pointHoverBorderColor: "#fff",
1922
+ pointHoverBorderWidth: 3
1923
+ }, {
1924
+ label: currentMetric.previousLabel,
1925
+ data: chartData.metrics[currentMetric.key]?.previousPeriod || [],
1926
+ borderColor: secColor,
1927
+ borderWidth: isMobile ? 3.5 : 3,
1928
+ tension: 0,
1929
+ fill: false,
1930
+ pointRadius: 0,
1931
+ pointHoverRadius: 0
1932
+ }]
1933
+ };
1934
+ const options = {
1935
+ responsive: true,
1936
+ maintainAspectRatio: false,
1937
+ layout: { padding: {
1938
+ left: isMobile ? 10 : 50,
1939
+ right: isMobile ? 10 : 50,
1940
+ top: isMobile ? 20 : 40,
1941
+ bottom: isMobile ? 10 : 20
1942
+ } },
1943
+ plugins: {
1944
+ legend: {
1945
+ display: true,
1946
+ position: "bottom",
1947
+ onClick: () => {},
1948
+ labels: {
1949
+ usePointStyle: true,
1950
+ boxWidth: isMobile ? 8 : 6,
1951
+ boxHeight: isMobile ? 8 : 6,
1952
+ padding: isMobile ? 12 : 15,
1953
+ font: {
1954
+ size: isMobile ? 13 : 11,
1955
+ weight: isMobile ? "bold" : "normal"
1956
+ },
1957
+ color: "var(--dashboard-text-secondary, #6b7280)"
1958
+ }
1959
+ },
1960
+ tooltip: {
1961
+ backgroundColor: "rgba(45, 45, 45, 0.95)",
1962
+ titleColor: "#fff",
1963
+ bodyColor: "#fff",
1964
+ borderColor: primaryColor,
1965
+ borderWidth: 1,
1966
+ padding: 12
1967
+ }
1968
+ },
1969
+ scales: {
1970
+ x: {
1971
+ border: { display: false },
1972
+ grid: { display: false },
1973
+ ticks: {
1974
+ color: "var(--dashboard-text-secondary, #6b7280)",
1975
+ font: { size: isMobile ? 12 : 11 }
1976
+ }
1977
+ },
1978
+ y: {
1979
+ beginAtZero: true,
1980
+ border: { display: false },
1981
+ grid: { color: "rgba(0, 0, 0, 0.05)" },
1982
+ ticks: {
1983
+ display: false,
1984
+ count: 5
1985
+ }
1986
+ }
1987
+ },
1988
+ interaction: {
1989
+ intersect: false,
1990
+ mode: "index"
1991
+ }
1992
+ };
1993
+ return /* @__PURE__ */ jsxs("div", {
1994
+ className: cn$3("bg-[var(--dashboard-surface,#ffffff)] rounded-lg shadow-sm border border-[var(--dashboard-text-secondary,#6b7280)]/20", className),
1995
+ style: { overflow: "visible" },
1996
+ children: [
1997
+ /* @__PURE__ */ jsxs("div", {
1998
+ className: "flex items-center justify-between p-4 md:p-6 pb-3 md:pb-4 border-b border-[var(--dashboard-text-secondary,#6b7280)]/10",
1999
+ children: [/* @__PURE__ */ jsxs("h2", {
2000
+ className: "flex items-center gap-2 text-lg md:text-xl font-bold text-[var(--dashboard-text-primary,#2d2d2d)]",
2001
+ children: [/* @__PURE__ */ jsx(TitleIcon, { className: "w-5 h-5 md:w-6 md:h-6" }), title]
2002
+ }), onActionClick && actionLabel && /* @__PURE__ */ jsx("button", {
2003
+ onClick: onActionClick,
2004
+ className: "px-3 md:px-4 py-1.5 md:py-2 text-xs md:text-sm font-medium border rounded-lg transition-colors cursor-pointer",
2005
+ style: {
2006
+ color: primaryColor,
2007
+ borderColor: primaryColor
2008
+ },
2009
+ children: actionLabel
2010
+ })]
2011
+ }),
2012
+ /* @__PURE__ */ jsx("div", {
2013
+ className: "p-4 md:p-6 pb-3 md:pb-4",
2014
+ children: /* @__PURE__ */ jsx("div", {
2015
+ className: "grid grid-cols-1 sm:grid-cols-2 gap-3 md:gap-4",
2016
+ style: { gridTemplateColumns: !isMobile && metrics.length <= 4 ? `repeat(${metrics.length}, minmax(min-content, 1fr))` : void 0 },
2017
+ children: metrics.map((metric) => /* @__PURE__ */ jsx(KPICard, {
2018
+ title: metric.label,
2019
+ value: metric.kpiValue.current,
2020
+ variation: metric.kpiValue.variation,
2021
+ trend: metric.kpiValue.trend,
2022
+ format: metric.format,
2023
+ isLoading
2024
+ }, metric.key))
2025
+ })
2026
+ }),
2027
+ /* @__PURE__ */ jsx("div", {
2028
+ className: "px-4 md:px-6 pt-3 md:pt-4",
2029
+ children: /* @__PURE__ */ jsx("div", {
2030
+ className: "flex flex-wrap justify-center gap-2 md:gap-3",
2031
+ children: metrics.map((metric) => {
2032
+ const Icon = metric.icon;
2033
+ return /* @__PURE__ */ jsxs("button", {
2034
+ onClick: () => setSelectedMetricKey(metric.key),
2035
+ className: cn$3("flex items-center gap-2 px-4 md:px-6 py-2 rounded-full text-sm font-medium transition-colors cursor-pointer", selectedMetricKey === metric.key ? "bg-[var(--dashboard-surface,#ffffff)] border-2 text-[var(--dashboard-primary,#37a501)]" : "bg-[var(--dashboard-surface,#ffffff)] border border-[var(--dashboard-text-secondary,#6b7280)]/30 text-[var(--dashboard-text-secondary,#6b7280)] hover:border-[var(--dashboard-text-secondary,#6b7280)]/50"),
2036
+ style: selectedMetricKey === metric.key ? {
2037
+ borderColor: primaryColor,
2038
+ color: primaryColor
2039
+ } : void 0,
2040
+ children: [/* @__PURE__ */ jsx(Icon, { className: "w-4 h-4" }), metric.label]
2041
+ }, metric.key);
2042
+ })
2043
+ })
2044
+ }),
2045
+ /* @__PURE__ */ jsx("div", {
2046
+ className: "px-4 md:px-6 pb-4 md:pb-6",
2047
+ style: {
2048
+ overflow: "visible",
2049
+ position: "relative",
2050
+ zIndex: 10
2051
+ },
2052
+ children: /* @__PURE__ */ jsx("div", {
2053
+ className: "h-[260px]",
2054
+ style: {
2055
+ overflow: "visible",
2056
+ position: "relative",
2057
+ zIndex: 10
2058
+ },
2059
+ children: isLoading ? /* @__PURE__ */ jsx("div", {
2060
+ className: "flex items-center justify-center h-full",
2061
+ children: /* @__PURE__ */ jsxs("div", {
2062
+ className: "text-center",
2063
+ children: [/* @__PURE__ */ jsx("div", {
2064
+ className: "animate-spin rounded-full h-12 w-12 border-b-2 mx-auto mb-4",
2065
+ style: { borderColor: primaryColor }
2066
+ }), /* @__PURE__ */ jsx("p", {
2067
+ className: "text-[var(--dashboard-text-secondary,#6b7280)]",
2068
+ children: "Carregando gráfico..."
2069
+ })]
2070
+ })
2071
+ }) : /* @__PURE__ */ jsx(Line, {
2072
+ data,
2073
+ options
2074
+ })
2075
+ })
2076
+ })
2077
+ ]
2078
+ });
2079
+ }
2080
+
2081
+ //#endregion
2082
+ //#region src/components/FilterBar/index.tsx
2083
+ const cn$2 = (...classes) => classes.filter(Boolean).join(" ");
2084
+ function FilterBar({ searchValue, onSearchChange, searchPlaceholder = "Buscar...", children, actions, className }) {
2085
+ return /* @__PURE__ */ jsxs("div", {
2086
+ className: cn$2("flex flex-col gap-3 sm:flex-row sm:items-center sm:flex-wrap", className),
2087
+ children: [
2088
+ onSearchChange !== void 0 && /* @__PURE__ */ jsx("div", {
2089
+ className: "flex-1 min-w-[200px]",
2090
+ children: /* @__PURE__ */ jsxs("div", {
2091
+ className: "relative flex items-center w-full",
2092
+ children: [/* @__PURE__ */ jsx("svg", {
2093
+ className: "absolute left-3 h-4 w-4 text-[var(--dashboard-text-secondary,#6b7280)]",
2094
+ fill: "none",
2095
+ stroke: "currentColor",
2096
+ viewBox: "0 0 24 24",
2097
+ children: /* @__PURE__ */ jsx("path", {
2098
+ strokeLinecap: "round",
2099
+ strokeLinejoin: "round",
2100
+ strokeWidth: 2,
2101
+ d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
2102
+ })
2103
+ }), /* @__PURE__ */ jsx("input", {
2104
+ type: "text",
2105
+ value: searchValue || "",
2106
+ onChange: (e) => onSearchChange(e.target.value),
2107
+ placeholder: searchPlaceholder,
2108
+ className: "flex h-10 w-full rounded-md border border-[var(--dashboard-text-secondary,#6b7280)]/30 bg-[var(--dashboard-surface,#ffffff)] pl-10 pr-3 py-2 text-sm text-[var(--dashboard-text-primary,#2d2d2d)] shadow-sm transition-colors duration-200 focus:border-[var(--dashboard-primary,#37a501)] placeholder:text-[var(--dashboard-text-secondary,#6b7280)] focus-visible:outline-none"
2109
+ })]
2110
+ })
2111
+ }),
2112
+ children && /* @__PURE__ */ jsx("div", {
2113
+ className: "flex flex-wrap items-center gap-2",
2114
+ children
2115
+ }),
2116
+ actions && /* @__PURE__ */ jsx("div", {
2117
+ className: "flex items-center gap-2 sm:ml-auto",
2118
+ children: actions
2119
+ })
2120
+ ]
2121
+ });
2122
+ }
2123
+
2124
+ //#endregion
2125
+ //#region src/components/Checkbox/index.tsx
2126
+ const cn$1 = (...classes) => classes.filter(Boolean).join(" ");
2127
+ const sizeConfig = {
2128
+ sm: {
2129
+ box: 16,
2130
+ radius: 4,
2131
+ icon: {
2132
+ w: 6,
2133
+ h: 10,
2134
+ left: 3,
2135
+ top: 0,
2136
+ border: 2
2137
+ },
2138
+ gap: 8,
2139
+ text: 13
2140
+ },
2141
+ md: {
2142
+ box: 22,
2143
+ radius: 6,
2144
+ icon: {
2145
+ w: 8,
2146
+ h: 14,
2147
+ left: 4.5,
2148
+ top: 0,
2149
+ border: 2
2150
+ },
2151
+ gap: 10,
2152
+ text: 14
2153
+ },
2154
+ lg: {
2155
+ box: 28,
2156
+ radius: 7,
2157
+ icon: {
2158
+ w: 10,
2159
+ h: 17,
2160
+ left: 6,
2161
+ top: 0,
2162
+ border: 2.5
2163
+ },
2164
+ gap: 12,
2165
+ text: 15
2166
+ }
2167
+ };
2168
+ function Checkbox({ name, id, label, checked = false, onChange, disabled = false, size = "md", primaryColor, className, children }) {
2169
+ const inputId = id || name;
2170
+ const cfg = sizeConfig[size];
2171
+ const resolvedColor = primaryColor || "var(--dashboard-primary, #37A501)";
2172
+ return /* @__PURE__ */ jsxs("label", {
2173
+ htmlFor: inputId,
2174
+ className: cn$1("inline-flex items-center cursor-pointer select-none", disabled && "opacity-50 cursor-not-allowed", className),
2175
+ style: { gap: cfg.gap },
2176
+ children: [
2177
+ /* @__PURE__ */ jsx("input", {
2178
+ type: "checkbox",
2179
+ id: inputId,
2180
+ name,
2181
+ checked,
2182
+ onChange: (e) => onChange?.(e.target.checked),
2183
+ disabled,
2184
+ className: "sr-only peer"
2185
+ }),
2186
+ /* @__PURE__ */ jsx("span", {
2187
+ className: "relative shrink-0 transition-all duration-200",
2188
+ style: {
2189
+ width: cfg.box,
2190
+ height: cfg.box,
2191
+ borderRadius: cfg.radius,
2192
+ backgroundColor: checked ? resolvedColor : "transparent",
2193
+ border: checked ? `2px solid ${resolvedColor}` : "2px solid rgba(45,45,45,0.2)",
2194
+ boxShadow: checked ? `0 1px 3px color-mix(in srgb, ${resolvedColor} 25%, transparent)` : "none"
2195
+ },
2196
+ "aria-hidden": "true",
2197
+ children: /* @__PURE__ */ jsx("span", {
2198
+ className: "absolute transition-opacity duration-150",
2199
+ style: {
2200
+ opacity: checked ? 1 : 0,
2201
+ left: cfg.icon.left,
2202
+ top: cfg.icon.top,
2203
+ width: cfg.icon.w,
2204
+ height: cfg.icon.h,
2205
+ borderRight: `${cfg.icon.border}px solid #fff`,
2206
+ borderBottom: `${cfg.icon.border}px solid #fff`,
2207
+ transform: "rotate(45deg)"
2208
+ }
2209
+ })
2210
+ }),
2211
+ (children || label) && /* @__PURE__ */ jsx("span", {
2212
+ className: "leading-none",
2213
+ style: {
2214
+ fontSize: cfg.text,
2215
+ color: "var(--dashboard-text-primary, #2d2d2d)"
2216
+ },
2217
+ children: children || label
2218
+ })
2219
+ ]
2220
+ });
2221
+ }
2222
+
2223
+ //#endregion
2224
+ //#region src/components/AuthLayout/index.tsx
2225
+ const cn = (...classes) => classes.filter(Boolean).join(" ");
2226
+ /** Resolves a CSS color value (including var() references) to a computed hex/rgb string */
2227
+ function useResolvedColor(cssValue) {
2228
+ const [resolved, setResolved] = useState(cssValue);
2229
+ useEffect(() => {
2230
+ if (!cssValue.startsWith("var(")) {
2231
+ setResolved(cssValue);
2232
+ return;
2233
+ }
2234
+ const probe = document.createElement("span");
2235
+ probe.style.display = "none";
2236
+ probe.style.color = cssValue;
2237
+ document.body.appendChild(probe);
2238
+ const computed = getComputedStyle(probe).color;
2239
+ if (computed) setResolved(computed);
2240
+ document.body.removeChild(probe);
2241
+ }, [cssValue]);
2242
+ useEffect(() => {
2243
+ if (!cssValue.startsWith("var(")) return;
2244
+ const observer = new MutationObserver(() => {
2245
+ const probe = document.createElement("span");
2246
+ probe.style.display = "none";
2247
+ probe.style.color = cssValue;
2248
+ document.body.appendChild(probe);
2249
+ const computed = getComputedStyle(probe).color;
2250
+ if (computed) setResolved(computed);
2251
+ document.body.removeChild(probe);
2252
+ });
2253
+ observer.observe(document.documentElement, {
2254
+ attributes: true,
2255
+ attributeFilter: ["style"]
2256
+ });
2257
+ return () => observer.disconnect();
2258
+ }, [cssValue]);
2259
+ return resolved;
2260
+ }
2261
+ function AuthInput({ name, label, type = "text", placeholder, required, minLength, value, onChange, error, resolvedColor, computedColor, disabled }) {
2262
+ return /* @__PURE__ */ jsxs("div", { children: [
2263
+ label && /* @__PURE__ */ jsx("label", {
2264
+ htmlFor: name,
2265
+ className: "block text-sm font-medium text-[#2d2d2d] mb-1.5",
2266
+ children: label
2267
+ }),
2268
+ /* @__PURE__ */ jsx("input", {
2269
+ type,
2270
+ id: name,
2271
+ name,
2272
+ placeholder,
2273
+ required,
2274
+ minLength,
2275
+ value,
2276
+ onChange,
2277
+ disabled,
2278
+ className: "w-full h-12 rounded-lg border-2 border-[#2d2d2d]/20 bg-transparent px-4 text-sm text-[#2d2d2d] placeholder:text-[#2d2d2d]/60 focus:outline-none transition-all disabled:opacity-50 disabled:cursor-not-allowed",
2279
+ style: { ...error ? { borderColor: "var(--dashboard-status-danger, #EF4444)" } : {} },
2280
+ onFocus: (e) => {
2281
+ e.target.style.borderColor = resolvedColor;
2282
+ e.target.style.boxShadow = `0 0 0 3px color-mix(in srgb, ${computedColor} 20%, transparent)`;
2283
+ },
2284
+ onBlur: (e) => {
2285
+ e.target.style.borderColor = "";
2286
+ e.target.style.boxShadow = "";
2287
+ }
2288
+ }),
2289
+ error && /* @__PURE__ */ jsx("p", {
2290
+ className: "text-xs mt-1 text-[var(--dashboard-status-danger,#EF4444)]",
2291
+ children: error
2292
+ })
2293
+ ] });
2294
+ }
2295
+ function PasswordInput({ value, onChange, placeholder, name, required, minLength, error, resolvedColor, computedColor, disabled }) {
2296
+ const [visible, setVisible] = useState(false);
2297
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("div", {
2298
+ className: "relative",
2299
+ children: [/* @__PURE__ */ jsx("input", {
2300
+ type: visible ? "text" : "password",
2301
+ id: name,
2302
+ name,
2303
+ placeholder,
2304
+ required,
2305
+ minLength,
2306
+ value,
2307
+ onChange,
2308
+ disabled,
2309
+ className: "w-full h-12 rounded-lg border-2 border-[#2d2d2d]/20 bg-transparent px-4 pr-11 text-sm text-[#2d2d2d] placeholder:text-[#2d2d2d]/60 focus:outline-none transition-all disabled:opacity-50 disabled:cursor-not-allowed",
2310
+ onFocus: (e) => {
2311
+ e.target.style.borderColor = resolvedColor;
2312
+ e.target.style.boxShadow = `0 0 0 3px color-mix(in srgb, ${computedColor} 20%, transparent)`;
2313
+ },
2314
+ onBlur: (e) => {
2315
+ e.target.style.borderColor = "";
2316
+ e.target.style.boxShadow = "";
2317
+ }
2318
+ }), /* @__PURE__ */ jsx("button", {
2319
+ type: "button",
2320
+ onClick: () => setVisible((v) => !v),
2321
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-[#2d2d2d]/50 hover:text-[#2d2d2d] transition-colors cursor-pointer bg-transparent border-none p-0",
2322
+ tabIndex: -1,
2323
+ "aria-label": visible ? "Ocultar senha" : "Mostrar senha",
2324
+ disabled,
2325
+ children: visible ? /* @__PURE__ */ jsxs("svg", {
2326
+ xmlns: "http://www.w3.org/2000/svg",
2327
+ width: "20",
2328
+ height: "20",
2329
+ viewBox: "0 0 24 24",
2330
+ fill: "none",
2331
+ stroke: "currentColor",
2332
+ strokeWidth: "2",
2333
+ strokeLinecap: "round",
2334
+ strokeLinejoin: "round",
2335
+ children: [
2336
+ /* @__PURE__ */ jsx("path", { d: "M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94" }),
2337
+ /* @__PURE__ */ jsx("path", { d: "M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19" }),
2338
+ /* @__PURE__ */ jsx("line", {
2339
+ x1: "1",
2340
+ y1: "1",
2341
+ x2: "23",
2342
+ y2: "23"
2343
+ })
2344
+ ]
2345
+ }) : /* @__PURE__ */ jsxs("svg", {
2346
+ xmlns: "http://www.w3.org/2000/svg",
2347
+ width: "20",
2348
+ height: "20",
2349
+ viewBox: "0 0 24 24",
2350
+ fill: "none",
2351
+ stroke: "currentColor",
2352
+ strokeWidth: "2",
2353
+ strokeLinecap: "round",
2354
+ strokeLinejoin: "round",
2355
+ children: [/* @__PURE__ */ jsx("path", { d: "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" }), /* @__PURE__ */ jsx("circle", {
2356
+ cx: "12",
2357
+ cy: "12",
2358
+ r: "3"
2359
+ })]
2360
+ })
2361
+ })]
2362
+ }), error && /* @__PURE__ */ jsx("p", {
2363
+ className: "text-xs mt-1 text-[var(--dashboard-status-danger,#EF4444)]",
2364
+ children: error
2365
+ })] });
2366
+ }
2367
+ function AuthLayout({ logo, title, subtitle, error, success, fields, values, onFieldChange, onSubmit, submitLabel = "Acessar", loadingLabel = "Entrando...", isLoading = false, checkbox, primaryLink, secondaryLink, extraContent, headerContent, beforeSubmitContent, footerContent, headline, branding, cardPosition = "right", cardOffsetRight = 256, background, cardStyle, primaryColor, titleColor, titleAlign = "center", className }) {
2368
+ const resolvedColor = primaryColor || "var(--dashboard-primary, #ff521d)";
2369
+ const computedColor = useResolvedColor(resolvedColor);
2370
+ const bgCss = {
2371
+ backgroundColor: background?.color || "#1a1a1a",
2372
+ ...background?.style
2373
+ };
2374
+ const cardCss = {
2375
+ backgroundColor: cardStyle?.background || "var(--dashboard-secondary, #faf3e1)",
2376
+ borderRadius: cardStyle?.borderRadius ?? 16,
2377
+ boxShadow: cardStyle?.shadow ?? "0 0 0 1px rgb(0 0 0 / 0.08), 0 0 12px 4px rgb(0 0 0 / 0.25), 0 0 28px 10px rgb(0 0 0 / 0.20)",
2378
+ maxWidth: cardStyle?.maxWidth ?? 420,
2379
+ padding: cardStyle?.padding ?? 32,
2380
+ border: cardStyle?.border || "none",
2381
+ width: "100%"
2382
+ };
2383
+ function handleSubmit(e) {
2384
+ e.preventDefault();
2385
+ onSubmit(values);
2386
+ }
2387
+ function renderLink(link, extraClass) {
2388
+ const style = { color: resolvedColor };
2389
+ if (link.onClick) return /* @__PURE__ */ jsx("button", {
2390
+ type: "button",
2391
+ onClick: link.onClick,
2392
+ className: cn("bg-transparent border-none cursor-pointer hover:opacity-80 text-sm font-semibold p-0 transition-colors", extraClass),
2393
+ style,
2394
+ children: link.label
2395
+ });
2396
+ return /* @__PURE__ */ jsx("a", {
2397
+ href: link.href,
2398
+ className: cn("hover:opacity-80 text-sm font-semibold transition-colors", extraClass),
2399
+ style,
2400
+ children: link.label
2401
+ });
2402
+ }
2403
+ return /* @__PURE__ */ jsxs("div", {
2404
+ className: cn("fixed inset-0 flex select-none overflow-hidden", className),
2405
+ style: bgCss,
2406
+ children: [
2407
+ branding && branding.logos.length > 0 && /* @__PURE__ */ jsx("div", {
2408
+ className: "relative hidden w-1/3 lg:block",
2409
+ children: /* @__PURE__ */ jsx("div", {
2410
+ className: "absolute bottom-12 left-12 z-20",
2411
+ children: /* @__PURE__ */ jsx("div", {
2412
+ className: "flex gap-4 items-center",
2413
+ children: branding.logos.map((brandLogo, i) => /* @__PURE__ */ jsx(React.Fragment, { children: brandLogo }, i))
2414
+ })
2415
+ })
2416
+ }),
2417
+ background?.imageElement ? /* @__PURE__ */ jsx("div", {
2418
+ className: "absolute inset-0 z-0",
2419
+ children: background.imageElement
2420
+ }) : background?.image ? /* @__PURE__ */ jsx("img", {
2421
+ src: background.image,
2422
+ alt: "",
2423
+ className: "absolute inset-0 z-0 h-full w-full object-cover",
2424
+ draggable: false
2425
+ }) : null,
2426
+ (background?.image || background?.imageElement) && /* @__PURE__ */ jsx("div", {
2427
+ className: "absolute inset-0 z-10",
2428
+ style: { backgroundColor: `rgba(0,0,0,${background?.overlayOpacity ?? .2})` }
2429
+ }),
2430
+ headline && /* @__PURE__ */ jsx("div", {
2431
+ className: "absolute top-12 left-8 z-20 max-w-md hidden lg:block",
2432
+ children: /* @__PURE__ */ jsx("h1", {
2433
+ className: "text-4xl font-bold mb-4 leading-tight",
2434
+ style: { color: headline.color || "#faf3e1" },
2435
+ children: headline.highlight ? (() => {
2436
+ const idx = headline.text.indexOf(headline.highlight);
2437
+ if (idx === -1) return /* @__PURE__ */ jsxs(Fragment, { children: [
2438
+ headline.text,
2439
+ /* @__PURE__ */ jsx("br", {}),
2440
+ /* @__PURE__ */ jsx("span", {
2441
+ style: { color: headline.highlightColor || resolvedColor },
2442
+ children: headline.highlight
2443
+ })
2444
+ ] });
2445
+ const before = headline.text.slice(0, idx);
2446
+ const after = headline.text.slice(idx + headline.highlight.length);
2447
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2448
+ before,
2449
+ /* @__PURE__ */ jsx("span", {
2450
+ style: { color: headline.highlightColor || resolvedColor },
2451
+ children: headline.highlight
2452
+ }),
2453
+ after
2454
+ ] });
2455
+ })() : headline.text
2456
+ })
2457
+ }),
2458
+ /* @__PURE__ */ jsx("style", { children: `
2459
+ .auth-card-container {
2460
+ padding-left: 1rem;
2461
+ padding-right: 1rem;
2462
+ justify-content: center;
2463
+ align-content: center;
2464
+ }
2465
+ @media (min-width: 1024px) {
2466
+ .auth-card-container[data-position="right"] {
2467
+ justify-content: flex-end;
2468
+ padding-right: ${cardOffsetRight}px;
2469
+ }
2470
+ .auth-card-container[data-position="left"] {
2471
+ justify-content: flex-start;
2472
+ padding-left: ${cardOffsetRight}px;
2473
+ }
2474
+ .auth-card-container[data-position="center"] {
2475
+ justify-content: center;
2476
+ }
2477
+ }
2478
+ ` }),
2479
+ /* @__PURE__ */ jsx("div", {
2480
+ className: "auth-card-container relative z-30 flex w-full items-center py-8",
2481
+ "data-position": cardPosition,
2482
+ children: /* @__PURE__ */ jsxs("div", {
2483
+ style: {
2484
+ ...cardCss,
2485
+ maxHeight: "calc(100vh - 64px)",
2486
+ overflowY: "auto"
2487
+ },
2488
+ children: [
2489
+ /* @__PURE__ */ jsxs("div", {
2490
+ className: `mb-8 ${titleAlign === "center" ? "text-center" : titleAlign === "right" ? "text-right" : "text-left"}`,
2491
+ children: [
2492
+ logo && /* @__PURE__ */ jsx("div", {
2493
+ className: `mb-4 flex ${titleAlign === "center" ? "justify-center" : titleAlign === "right" ? "justify-end" : "justify-start"}`,
2494
+ children: logo
2495
+ }),
2496
+ /* @__PURE__ */ jsx("h2", {
2497
+ className: "text-2xl font-bold mb-2",
2498
+ style: { color: titleColor || "var(--dashboard-text-primary, #111827)" },
2499
+ children: title
2500
+ }),
2501
+ subtitle && /* @__PURE__ */ jsx("p", {
2502
+ className: "text-sm text-gray-600",
2503
+ children: subtitle
2504
+ })
2505
+ ]
2506
+ }),
2507
+ headerContent,
2508
+ error && /* @__PURE__ */ jsx("div", {
2509
+ className: "p-3 rounded-lg text-sm text-center mb-5 bg-red-50 text-red-700 border border-red-200",
2510
+ children: error
2511
+ }),
2512
+ success && /* @__PURE__ */ jsx("div", {
2513
+ className: "p-3 rounded-lg text-sm text-center mb-5 bg-green-50 text-green-700 border border-green-200",
2514
+ children: success
2515
+ }),
2516
+ /* @__PURE__ */ jsxs("form", {
2517
+ onSubmit: handleSubmit,
2518
+ className: "space-y-5",
2519
+ children: [
2520
+ fields.map((field) => field.type === "password" ? /* @__PURE__ */ jsx(PasswordInput, {
2521
+ name: field.name,
2522
+ placeholder: field.placeholder || field.label,
2523
+ required: field.required,
2524
+ minLength: field.minLength,
2525
+ value: values[field.name] || "",
2526
+ onChange: (e) => onFieldChange(field.name, e.target.value),
2527
+ error: field.error,
2528
+ resolvedColor,
2529
+ computedColor,
2530
+ disabled: isLoading
2531
+ }, field.name) : /* @__PURE__ */ jsx(AuthInput, {
2532
+ name: field.name,
2533
+ label: field.label,
2534
+ type: field.type || "text",
2535
+ placeholder: field.placeholder || field.label,
2536
+ required: field.required,
2537
+ minLength: field.minLength,
2538
+ value: values[field.name] || "",
2539
+ onChange: (e) => onFieldChange(field.name, e.target.value),
2540
+ error: field.error,
2541
+ resolvedColor,
2542
+ computedColor,
2543
+ disabled: isLoading
2544
+ }, field.name)),
2545
+ checkbox && /* @__PURE__ */ jsx(Checkbox, {
2546
+ name: checkbox.name,
2547
+ label: checkbox.label,
2548
+ checked: checkbox.checked || false,
2549
+ onChange: (val) => checkbox.onChange?.(val),
2550
+ disabled: isLoading,
2551
+ primaryColor: resolvedColor,
2552
+ size: "sm"
2553
+ }),
2554
+ beforeSubmitContent,
2555
+ /* @__PURE__ */ jsx("button", {
2556
+ type: "submit",
2557
+ disabled: isLoading,
2558
+ className: "w-full h-12 rounded-lg px-5 text-base font-bold text-white transition-all focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed shadow-lg hover:shadow-xl hover:opacity-90",
2559
+ style: {
2560
+ backgroundColor: resolvedColor,
2561
+ "--tw-ring-color": resolvedColor
2562
+ },
2563
+ children: isLoading ? loadingLabel : submitLabel
2564
+ })
2565
+ ]
2566
+ }),
2567
+ extraContent && /* @__PURE__ */ jsx("div", {
2568
+ className: "mt-5",
2569
+ children: extraContent
2570
+ }),
2571
+ (primaryLink || secondaryLink) && /* @__PURE__ */ jsxs("div", {
2572
+ className: "mt-6 text-center",
2573
+ children: [primaryLink && /* @__PURE__ */ jsx("p", {
2574
+ className: "text-sm text-gray-600",
2575
+ children: renderLink(primaryLink)
2576
+ }), secondaryLink && /* @__PURE__ */ jsxs("p", {
2577
+ className: `text-sm text-gray-600 ${primaryLink ? "mt-6" : ""}`,
2578
+ children: [secondaryLink.prefix && /* @__PURE__ */ jsxs(Fragment, { children: [secondaryLink.prefix, " "] }), renderLink(secondaryLink)]
2579
+ })]
2580
+ }),
2581
+ footerContent && /* @__PURE__ */ jsx("div", {
2582
+ className: "mt-6",
2583
+ children: footerContent
2584
+ })
2585
+ ]
2586
+ })
2587
+ })
2588
+ ]
2589
+ });
2590
+ }
2591
+
2592
+ //#endregion
2593
+ //#region src/components/CodeInput/index.tsx
2594
+ function CodeInput({ length = 6, value, onChange, disabled = false, error = false, primaryColor, className = "" }) {
2595
+ const resolvedColor = primaryColor || "var(--dashboard-primary, #ff521d)";
2596
+ const inputsRef = useRef([]);
2597
+ const digits = value.split("").concat(Array(length).fill("")).slice(0, length);
2598
+ const focusInput = useCallback((idx) => {
2599
+ const clamped = Math.max(0, Math.min(idx, length - 1));
2600
+ inputsRef.current[clamped]?.focus();
2601
+ }, [length]);
2602
+ const updateValue = useCallback((idx, digit) => {
2603
+ const arr = value.split("").concat(Array(length).fill("")).slice(0, length);
2604
+ arr[idx] = digit;
2605
+ onChange(arr.join("").replace(/\s+$/g, ""));
2606
+ }, [
2607
+ value,
2608
+ length,
2609
+ onChange
2610
+ ]);
2611
+ const handleInput = useCallback((idx, char) => {
2612
+ if (!/^\d$/.test(char)) return;
2613
+ updateValue(idx, char);
2614
+ if (idx < length - 1) focusInput(idx + 1);
2615
+ }, [
2616
+ updateValue,
2617
+ focusInput,
2618
+ length
2619
+ ]);
2620
+ const handleKeyDown = useCallback((idx, e) => {
2621
+ if (e.key === "Backspace") {
2622
+ e.preventDefault();
2623
+ if (digits[idx] && digits[idx] !== "") updateValue(idx, "");
2624
+ else if (idx > 0) {
2625
+ updateValue(idx - 1, "");
2626
+ focusInput(idx - 1);
2627
+ }
2628
+ } else if (e.key === "ArrowLeft" && idx > 0) {
2629
+ e.preventDefault();
2630
+ focusInput(idx - 1);
2631
+ } else if (e.key === "ArrowRight" && idx < length - 1) {
2632
+ e.preventDefault();
2633
+ focusInput(idx + 1);
2634
+ }
2635
+ }, [
2636
+ digits,
2637
+ updateValue,
2638
+ focusInput,
2639
+ length
2640
+ ]);
2641
+ const handlePaste = useCallback((e) => {
2642
+ e.preventDefault();
2643
+ const pasted = e.clipboardData.getData("text").replace(/\D/g, "").slice(0, length);
2644
+ if (pasted.length > 0) {
2645
+ onChange(pasted);
2646
+ focusInput(Math.min(pasted.length, length - 1));
2647
+ }
2648
+ }, [
2649
+ length,
2650
+ onChange,
2651
+ focusInput
2652
+ ]);
2653
+ return /* @__PURE__ */ jsx("div", {
2654
+ className: `flex justify-center gap-2 sm:gap-3 ${className}`,
2655
+ children: Array.from({ length }).map((_, idx) => /* @__PURE__ */ jsx("input", {
2656
+ ref: (el) => {
2657
+ inputsRef.current[idx] = el;
2658
+ },
2659
+ type: "text",
2660
+ inputMode: "numeric",
2661
+ autoComplete: "one-time-code",
2662
+ maxLength: 1,
2663
+ disabled,
2664
+ value: digits[idx] || "",
2665
+ onChange: (e) => {
2666
+ handleInput(idx, e.target.value.slice(-1));
2667
+ },
2668
+ onKeyDown: (e) => handleKeyDown(idx, e),
2669
+ onPaste: handlePaste,
2670
+ onFocus: (e) => {
2671
+ e.target.select();
2672
+ e.target.style.borderColor = resolvedColor;
2673
+ e.target.style.boxShadow = `0 0 0 3px color-mix(in srgb, ${resolvedColor} 20%, transparent)`;
2674
+ },
2675
+ onBlur: (e) => {
2676
+ e.target.style.borderColor = "";
2677
+ e.target.style.boxShadow = "";
2678
+ },
2679
+ className: "w-10 h-11 sm:w-11 sm:h-12 text-center text-lg sm:text-xl font-bold rounded-lg border-2 bg-transparent text-[#2d2d2d] transition-all focus:outline-none disabled:opacity-50 disabled:cursor-not-allowed",
2680
+ style: { borderColor: error ? "var(--dashboard-status-danger, #EF4444)" : "rgba(45,45,45,0.2)" }
2681
+ }, idx))
2682
+ });
2683
+ }
2684
+
2685
+ //#endregion
2686
+ //#region src/config/defaults.ts
2687
+ const defaultConfig = {
2688
+ name: "Dashboard",
2689
+ colors: {
2690
+ primary: "#37A501",
2691
+ secondary: "#f0f0f0",
2692
+ background: "#F2F2F2",
2693
+ surface: "#FFFFFF",
2694
+ textPrimary: "#2d2d2d",
2695
+ textSecondary: "#6b7280",
2696
+ statusSuccess: "#10B981",
2697
+ statusDanger: "#EF4444",
2698
+ statusWarning: "#F59E0B",
2699
+ statusInfo: "#3B82F6",
2700
+ statusNeutral: "#6B7280"
2701
+ },
2702
+ components: {
2703
+ modal: {
2704
+ closeOnEscape: true,
2705
+ closeOnOverlayClick: true
2706
+ },
2707
+ toast: {
2708
+ duration: 3e3,
2709
+ position: "top-right"
2710
+ },
2711
+ notification: { duration: 5e3 },
2712
+ pagination: {
2713
+ itemsPerPageOptions: [
2714
+ 10,
2715
+ 20,
2716
+ 30,
2717
+ 50
2718
+ ],
2719
+ defaultItemsPerPage: 10
2720
+ }
2721
+ }
2722
+ };
2723
+
2724
+ //#endregion
2725
+ //#region src/config/createConfig.ts
2726
+ function deepMerge(target, source) {
2727
+ const result = { ...target };
2728
+ const src = source;
2729
+ for (const key in src) {
2730
+ const sourceVal = src[key];
2731
+ const targetVal = result[key];
2732
+ if (sourceVal !== null && sourceVal !== void 0 && typeof sourceVal === "object" && !Array.isArray(sourceVal) && typeof targetVal === "object" && targetVal !== null && !Array.isArray(targetVal)) result[key] = deepMerge(targetVal, sourceVal);
2733
+ else if (sourceVal !== void 0) result[key] = sourceVal;
2734
+ }
2735
+ return result;
2736
+ }
2737
+ function createConfig(overrides = {}) {
2738
+ return deepMerge(defaultConfig, overrides);
2739
+ }
2740
+
2741
+ //#endregion
2742
+ //#region src/hooks/useConfig.ts
2743
+ const ConfigContext = createContext(null);
2744
+ function useConfig() {
2745
+ const config = useContext(ConfigContext);
2746
+ if (!config) throw new Error("useConfig must be used within a DashboardProvider");
2747
+ return config;
2748
+ }
2749
+
2750
+ //#endregion
2751
+ //#region src/providers/ThemeProvider.tsx
2752
+ function ThemeProvider({ children }) {
2753
+ const [theme, setThemeState] = useState("system");
2754
+ const [resolvedTheme, setResolvedTheme] = useState("light");
2755
+ useEffect(() => {
2756
+ const savedTheme = localStorage.getItem("dashboard-theme");
2757
+ if (savedTheme) setThemeState(savedTheme);
2758
+ const systemPreference = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
2759
+ const currentTheme = savedTheme || "system";
2760
+ const resolved = currentTheme === "system" ? systemPreference : currentTheme;
2761
+ setResolvedTheme(resolved);
2762
+ document.documentElement.classList.toggle("dark", resolved === "dark");
2763
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
2764
+ const handleChange = (e) => {
2765
+ const current = localStorage.getItem("dashboard-theme");
2766
+ if (!current || current === "system") {
2767
+ const newResolved = e.matches ? "dark" : "light";
2768
+ setResolvedTheme(newResolved);
2769
+ document.documentElement.classList.toggle("dark", newResolved === "dark");
2770
+ }
2771
+ };
2772
+ mediaQuery.addEventListener("change", handleChange);
2773
+ return () => mediaQuery.removeEventListener("change", handleChange);
2774
+ }, []);
2775
+ const setTheme = (newTheme) => {
2776
+ setThemeState(newTheme);
2777
+ localStorage.setItem("dashboard-theme", newTheme);
2778
+ const systemPreference = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
2779
+ const resolved = newTheme === "system" ? systemPreference : newTheme;
2780
+ setResolvedTheme(resolved);
2781
+ document.documentElement.classList.toggle("dark", resolved === "dark");
2782
+ };
2783
+ return /* @__PURE__ */ jsx(ThemeContext.Provider, {
2784
+ value: {
2785
+ theme,
2786
+ setTheme,
2787
+ resolvedTheme
2788
+ },
2789
+ children
2790
+ });
2791
+ }
2792
+
2793
+ //#endregion
2794
+ //#region src/hooks/useLoading.ts
2795
+ const LoadingContext = createContext(null);
2796
+ function useLoading() {
2797
+ const context = useContext(LoadingContext);
2798
+ if (!context) throw new Error("useLoading must be used within a DashboardProvider");
2799
+ return context;
2800
+ }
2801
+
2802
+ //#endregion
2803
+ //#region src/providers/LoadingProvider.tsx
2804
+ function LoadingProvider({ children }) {
2805
+ const [isLoading, setIsLoading] = useState(false);
2806
+ const showLoading = () => setIsLoading(true);
2807
+ const hideLoading = () => setIsLoading(false);
2808
+ return /* @__PURE__ */ jsxs(LoadingContext.Provider, {
2809
+ value: {
2810
+ isLoading,
2811
+ showLoading,
2812
+ hideLoading
2813
+ },
2814
+ children: [children, isLoading && /* @__PURE__ */ jsx(Loading, {
2815
+ size: "lg",
2816
+ text: "Carregando...",
2817
+ fullscreen: true
2818
+ })]
2819
+ });
2820
+ }
2821
+
2822
+ //#endregion
2823
+ //#region src/hooks/useNotifications.ts
2824
+ const NotificationsContext = createContext(null);
2825
+ function useNotifications() {
2826
+ const context = useContext(NotificationsContext);
2827
+ if (!context) throw new Error("useNotifications must be used within a DashboardProvider");
2828
+ return context;
2829
+ }
2830
+
2831
+ //#endregion
2832
+ //#region src/providers/NotificationsProvider.tsx
2833
+ function NotificationsProvider({ children }) {
2834
+ const [notifications, setNotifications] = useState([]);
2835
+ const timersRef = useRef(/* @__PURE__ */ new Map());
2836
+ const config = useConfig();
2837
+ useEffect(() => {
2838
+ return () => {
2839
+ timersRef.current.forEach((timer) => clearTimeout(timer));
2840
+ };
2841
+ }, []);
2842
+ const removeNotification = useCallback((id) => {
2843
+ const timer = timersRef.current.get(id);
2844
+ if (timer) {
2845
+ clearTimeout(timer);
2846
+ timersRef.current.delete(id);
2847
+ }
2848
+ setNotifications((prev) => prev.filter((n) => n.id !== id));
2849
+ }, []);
2850
+ const addNotification = useCallback((notification) => {
2851
+ const id = Math.random().toString(36).substring(2, 9);
2852
+ const newNotification = {
2853
+ ...notification,
2854
+ id
2855
+ };
2856
+ setNotifications((prev) => [...prev, newNotification]);
2857
+ }, []);
2858
+ const clearNotifications = useCallback(() => {
2859
+ timersRef.current.forEach((timer) => clearTimeout(timer));
2860
+ timersRef.current.clear();
2861
+ setNotifications([]);
2862
+ }, []);
2863
+ const duration = config.components.notification.duration;
2864
+ return /* @__PURE__ */ jsxs(NotificationsContext.Provider, {
2865
+ value: {
2866
+ notifications,
2867
+ addNotification,
2868
+ removeNotification,
2869
+ clearNotifications
2870
+ },
2871
+ children: [children, notifications.length > 0 && /* @__PURE__ */ jsx("div", {
2872
+ className: "fixed w-full max-w-[400px] px-4 z-50 top-4 left-1/2 -translate-x-1/2 sm:top-5 sm:right-4 sm:left-auto sm:translate-x-0 flex flex-col gap-2",
2873
+ children: notifications.map((notification) => /* @__PURE__ */ jsx(Toast, {
2874
+ title: notification.title,
2875
+ subtitle: notification.subtitle,
2876
+ type: notification.type,
2877
+ duration,
2878
+ onClose: () => removeNotification(notification.id)
2879
+ }, notification.id))
2880
+ })]
2881
+ });
2882
+ }
2883
+
2884
+ //#endregion
2885
+ //#region src/providers/DashboardProvider.tsx
2886
+ function CSSVarsInjector({ config }) {
2887
+ useEffect(() => {
2888
+ const root = document.documentElement;
2889
+ const { colors } = config;
2890
+ root.style.setProperty("--dashboard-primary", colors.primary);
2891
+ root.style.setProperty("--dashboard-secondary", colors.secondary);
2892
+ root.style.setProperty("--dashboard-background", colors.background);
2893
+ root.style.setProperty("--dashboard-surface", colors.surface);
2894
+ root.style.setProperty("--dashboard-text-primary", colors.textPrimary);
2895
+ root.style.setProperty("--dashboard-text-secondary", colors.textSecondary);
2896
+ root.style.setProperty("--dashboard-status-success", colors.statusSuccess);
2897
+ root.style.setProperty("--dashboard-status-danger", colors.statusDanger);
2898
+ root.style.setProperty("--dashboard-status-warning", colors.statusWarning);
2899
+ root.style.setProperty("--dashboard-status-info", colors.statusInfo);
2900
+ root.style.setProperty("--dashboard-status-neutral", colors.statusNeutral);
2901
+ return () => {
2902
+ root.style.removeProperty("--dashboard-primary");
2903
+ root.style.removeProperty("--dashboard-secondary");
2904
+ root.style.removeProperty("--dashboard-background");
2905
+ root.style.removeProperty("--dashboard-surface");
2906
+ root.style.removeProperty("--dashboard-text-primary");
2907
+ root.style.removeProperty("--dashboard-text-secondary");
2908
+ root.style.removeProperty("--dashboard-status-success");
2909
+ root.style.removeProperty("--dashboard-status-danger");
2910
+ root.style.removeProperty("--dashboard-status-warning");
2911
+ root.style.removeProperty("--dashboard-status-info");
2912
+ root.style.removeProperty("--dashboard-status-neutral");
2913
+ };
2914
+ }, [config]);
2915
+ return null;
2916
+ }
2917
+ function DashboardProvider({ config: configOverrides, children }) {
2918
+ const config = useMemo(() => createConfig(configOverrides), [configOverrides]);
2919
+ return /* @__PURE__ */ jsxs(ConfigContext.Provider, {
2920
+ value: config,
2921
+ children: [/* @__PURE__ */ jsx(CSSVarsInjector, { config }), /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(LoadingProvider, { children: /* @__PURE__ */ jsx(NotificationsProvider, { children }) }) })]
2922
+ });
2923
+ }
2924
+
2925
+ //#endregion
2926
+ export { AuthLayout, BadgeStatus, Button, Card, Checkbox, CodeInput, ComparisonLineChart, DashboardProvider, DateRangePicker, Dropdown, FilterBar, FormField, HorizontalBarChart, Input, KPICard, Loading, LoadingProvider, MetricPanel, Modal, NotificationsProvider, PageLayout, Pagination, ProgressBarList, Sidebar, Table, TableBody, TableEmpty, TableHeader, TableSkeleton, Tabs, ThemeProvider, ThemeSwitcher, Title, Toast, ToggleSwitch, VerticalBarChart, createConfig, defaultConfig, useConfig, useLoading, useNotifications, useTheme };
2927
+ //# sourceMappingURL=index.mjs.map