@ttoss/components 2.14.25 → 2.14.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/index.d.mts +910 -0
  2. package/dist/index.mjs +3074 -0
  3. package/package.json +17 -100
  4. package/dist/Accordion/index.d.mts +0 -157
  5. package/dist/Accordion/index.mjs +0 -175
  6. package/dist/DatePicker/index.d.mts +0 -26
  7. package/dist/DatePicker/index.mjs +0 -339
  8. package/dist/Drawer/index.d.mts +0 -17
  9. package/dist/Drawer/index.mjs +0 -66
  10. package/dist/EnhancedTitle/index.d.mts +0 -107
  11. package/dist/EnhancedTitle/index.mjs +0 -234
  12. package/dist/FileUploader/index.d.mts +0 -77
  13. package/dist/FileUploader/index.mjs +0 -386
  14. package/dist/InstallPwa/index.d.mts +0 -13
  15. package/dist/InstallPwa/index.mjs +0 -64
  16. package/dist/JsonEditor/index.d.mts +0 -3
  17. package/dist/JsonEditor/index.mjs +0 -3
  18. package/dist/JsonView/index.d.mts +0 -3
  19. package/dist/JsonView/index.mjs +0 -3
  20. package/dist/List/index.d.mts +0 -16
  21. package/dist/List/index.mjs +0 -34
  22. package/dist/LockedOverlay/index.d.mts +0 -162
  23. package/dist/LockedOverlay/index.mjs +0 -386
  24. package/dist/Markdown/index.d.mts +0 -16
  25. package/dist/Markdown/index.mjs +0 -26
  26. package/dist/Menu/index.d.mts +0 -16
  27. package/dist/Menu/index.mjs +0 -136
  28. package/dist/MetricCard/index.d.mts +0 -153
  29. package/dist/MetricCard/index.mjs +0 -408
  30. package/dist/Modal/index.d.mts +0 -11
  31. package/dist/Modal/index.mjs +0 -64
  32. package/dist/NavList/index.d.mts +0 -64
  33. package/dist/NavList/index.mjs +0 -252
  34. package/dist/NotificationCard/index.d.mts +0 -22
  35. package/dist/NotificationCard/index.mjs +0 -173
  36. package/dist/NotificationsMenu/index.d.mts +0 -47
  37. package/dist/NotificationsMenu/index.mjs +0 -380
  38. package/dist/Search/index.d.mts +0 -18
  39. package/dist/Search/index.mjs +0 -31
  40. package/dist/SpotlightCard/index.d.mts +0 -36
  41. package/dist/SpotlightCard/index.mjs +0 -219
  42. package/dist/Table/index.d.mts +0 -17
  43. package/dist/Table/index.mjs +0 -64
  44. package/dist/Tabs/index.d.mts +0 -17
  45. package/dist/Tabs/index.mjs +0 -87
  46. package/dist/Toast/index.d.mts +0 -8
  47. package/dist/Toast/index.mjs +0 -43
package/dist/index.mjs ADDED
@@ -0,0 +1,3074 @@
1
+ /** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
2
+ import { Badge, BaseStyles, Box, Button, Card, CloseButton, Divider, Flex, Heading, IconButton, Input, Label, Link, Stack, Tag, Text, TooltipIcon, keyframes, useResponsiveValue, useTheme } from "@ttoss/ui";
3
+ import * as React from "react";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+ import { Icon } from "@ttoss/react-icons";
6
+ import { DayPicker } from "react-day-picker";
7
+ import { ptBR } from "react-day-picker/locale";
8
+ import DrawerUi from "react-modern-drawer";
9
+ import { defineMessages, useI18n } from "@ttoss/react-i18n";
10
+ import { JsonEditor } from "json-edit-react";
11
+ import { JsonView } from "react-json-view-lite";
12
+ import ReactMarkdown from "react-markdown";
13
+ import rehypeRaw from "rehype-raw";
14
+ import remarkGfm from "remark-gfm";
15
+ import { css } from "@theme-ui/css";
16
+ import ReactModal from "react-modal";
17
+ import { useDebounce } from "@ttoss/react-hooks";
18
+ import { createCell, createColumnHelper, flexRender, getCoreRowModel, useReactTable } from "@tanstack/react-table";
19
+ import { Tab, TabList, TabPanel, Tabs as Tabs$1 } from "react-tabs";
20
+ import { css as css$1 } from "@emotion/css";
21
+ import { ToastContainer as ToastContainer$1, toast as toast$1 } from "react-toastify";
22
+
23
+ //#region src/components/Accordion/Accordion.tsx
24
+ /**
25
+ * Accessible accordion component with collapsible content sections.
26
+ *
27
+ * This component provides a simplified API for creating expandable/collapsible
28
+ * content sections. It uses design tokens from @ttoss/theme for consistent styling
29
+ * and follows WAI-ARIA accordion pattern for accessibility.
30
+ *
31
+ * @example
32
+ * ```tsx
33
+ * <Accordion
34
+ * items={[
35
+ * {
36
+ * title: 'Section 1',
37
+ * content: 'Content for section 1',
38
+ * },
39
+ * {
40
+ * title: 'Section 2',
41
+ * content: 'Content for section 2',
42
+ * },
43
+ * ]}
44
+ * />
45
+ * ```
46
+ *
47
+ * @example
48
+ * ```tsx
49
+ * <Accordion
50
+ * multiple
51
+ * defaultExpanded={[0, 1]}
52
+ * items={[
53
+ * {
54
+ * id: 'item-1',
55
+ * title: 'Pre-expanded Section 1',
56
+ * content: <div>Rich content</div>,
57
+ * },
58
+ * {
59
+ * id: 'item-2',
60
+ * title: 'Pre-expanded Section 2',
61
+ * content: <p>More content</p>,
62
+ * },
63
+ * ]}
64
+ * onAccordionChange={(expanded) => console.log('Expanded items:', expanded)}
65
+ * />
66
+ * ```
67
+ *
68
+ * @example
69
+ * ```tsx
70
+ * // Custom rendering with renderItem
71
+ * <Accordion
72
+ * items={items}
73
+ * renderItem={({ item, isExpanded, toggle, ids }) => (
74
+ * <CustomAccordionItem
75
+ * item={item}
76
+ * isExpanded={isExpanded}
77
+ * onToggle={toggle}
78
+ * headingId={ids.headingId}
79
+ * panelId={ids.panelId}
80
+ * />
81
+ * )}
82
+ * />
83
+ * ```
84
+ */
85
+ var Accordion = ({
86
+ items,
87
+ multiple = false,
88
+ defaultExpanded,
89
+ onAccordionChange,
90
+ renderItem,
91
+ sx,
92
+ ...boxProps
93
+ }) => {
94
+ const [expandedIndices, setExpandedIndices] = React.useState(() => {
95
+ if (defaultExpanded === void 0) return [];
96
+ return Array.isArray(defaultExpanded) ? defaultExpanded : [defaultExpanded];
97
+ });
98
+ const toggleItem = React.useCallback(index => {
99
+ setExpandedIndices(prev => {
100
+ const isExpanded = prev.includes(index);
101
+ let newExpanded;
102
+ if (isExpanded) newExpanded = prev.filter(i => {
103
+ return i !== index;
104
+ });else newExpanded = multiple ? [...prev, index] : [index];
105
+ onAccordionChange?.(newExpanded);
106
+ return newExpanded;
107
+ });
108
+ }, [multiple, onAccordionChange]);
109
+ return /* @__PURE__ */jsx(Box, {
110
+ sx: {
111
+ display: "flex",
112
+ flexDirection: "column",
113
+ gap: 2,
114
+ ...sx
115
+ },
116
+ ...boxProps,
117
+ children: items.map((item, index) => {
118
+ const isExpanded = expandedIndices.includes(index);
119
+ const itemId = item.id || `accordion-item-${index}`;
120
+ const headingId = `${itemId}-heading`;
121
+ const panelId = `${itemId}-panel`;
122
+ if (renderItem) return /* @__PURE__ */jsx(React.Fragment, {
123
+ children: renderItem({
124
+ item,
125
+ index,
126
+ isExpanded,
127
+ toggle: () => {
128
+ return toggleItem(index);
129
+ },
130
+ ids: {
131
+ itemId,
132
+ headingId,
133
+ panelId
134
+ }
135
+ })
136
+ }, itemId);
137
+ return /* @__PURE__ */jsxs(Box, {
138
+ sx: {
139
+ border: "sm",
140
+ borderColor: "display.border.muted.default",
141
+ borderRadius: "md",
142
+ overflow: "hidden"
143
+ },
144
+ children: [/* @__PURE__ */jsx(Button, {
145
+ id: headingId,
146
+ type: "button",
147
+ disabled: item.disabled,
148
+ onClick: () => {
149
+ toggleItem(index);
150
+ },
151
+ "aria-expanded": isExpanded,
152
+ "aria-controls": panelId,
153
+ rightIcon: isExpanded ? "chevron-up" : "chevron-down",
154
+ sx: {
155
+ width: "100%",
156
+ justifyContent: "space-between",
157
+ backgroundColor: isExpanded ? "display.background.muted.default" : "display.background.primary.default",
158
+ color: item.disabled ? "display.text.muted.default" : "display.text.primary.default",
159
+ fontWeight: 500,
160
+ border: "none",
161
+ borderRadius: 0,
162
+ transition: "background-color 0.2s ease",
163
+ "&:hover:not(:disabled)": {
164
+ backgroundColor: "display.background.muted.default"
165
+ },
166
+ "&:focus": {
167
+ outline: "none",
168
+ boxShadow: theme => {
169
+ return `inset 0 0 0 1px ${theme.colors?.input?.border?.accent?.default || "currentColor"}`;
170
+ }
171
+ }
172
+ },
173
+ children: item.title
174
+ }), isExpanded && /* @__PURE__ */jsx(Box, {
175
+ id: panelId,
176
+ role: "region",
177
+ "aria-labelledby": headingId,
178
+ sx: {
179
+ padding: 4,
180
+ borderTop: "sm",
181
+ borderColor: "display.border.muted.default",
182
+ backgroundColor: "display.background.primary.default"
183
+ },
184
+ children: item.content
185
+ })]
186
+ }, itemId);
187
+ })
188
+ });
189
+ };
190
+
191
+ //#endregion
192
+ //#region src/components/DatePicker/DatePicker.tsx
193
+ var formatDate = date => {
194
+ return date.toLocaleDateString("pt-BR");
195
+ };
196
+ var DatePicker = ({
197
+ label,
198
+ value,
199
+ presets,
200
+ onChange,
201
+ disabled
202
+ }) => {
203
+ const [date, setDate] = React.useState(value);
204
+ const [pickerSelection, setPickerSelection] = React.useState(value);
205
+ const [isOpen, setIsOpen] = React.useState(false);
206
+ const containerRef = React.useRef(null);
207
+ const isResettingRangeRef = React.useRef(false);
208
+ React.useEffect(() => {
209
+ setDate(value);
210
+ }, [value]);
211
+ React.useEffect(() => {
212
+ if (isOpen) setPickerSelection(date);
213
+ }, [isOpen, date]);
214
+ React.useEffect(() => {
215
+ const handleClickOutside = event => {
216
+ if (containerRef.current && !containerRef.current.contains(event.target)) setIsOpen(false);
217
+ };
218
+ if (isOpen) document.addEventListener("mousedown", handleClickOutside);
219
+ return () => {
220
+ document.removeEventListener("mousedown", handleClickOutside);
221
+ };
222
+ }, [isOpen]);
223
+ const commitSelection = range => {
224
+ setDate(range);
225
+ onChange?.(range);
226
+ };
227
+ const handlePresetClick = preset => {
228
+ commitSelection(preset.getValue());
229
+ setIsOpen(false);
230
+ };
231
+ const handleDayPickerSelect = selected => {
232
+ if (isResettingRangeRef.current && !selected && pickerSelection?.from && !pickerSelection?.to) {
233
+ commitSelection({
234
+ from: pickerSelection.from,
235
+ to: pickerSelection.from
236
+ });
237
+ setIsOpen(false);
238
+ return;
239
+ }
240
+ isResettingRangeRef.current = false;
241
+ const hadFullRange = date?.from && date?.to;
242
+ const hadPartialPicker = pickerSelection?.from && !pickerSelection?.to;
243
+ if (hadFullRange && !hadPartialPicker && selected?.from && selected?.to) {
244
+ setPickerSelection({
245
+ from: selected.from.getTime() === date?.from?.getTime() ? selected.to : selected.from,
246
+ to: void 0
247
+ });
248
+ return;
249
+ }
250
+ setPickerSelection(selected);
251
+ if (selected?.from && selected?.to) {
252
+ commitSelection(selected);
253
+ setIsOpen(false);
254
+ } else if (!selected?.from && !selected?.to) commitSelection(void 0);
255
+ };
256
+ const handleDayClick = day => {
257
+ if (date?.from && date?.to) {
258
+ isResettingRangeRef.current = true;
259
+ setPickerSelection({
260
+ from: day,
261
+ to: void 0
262
+ });
263
+ }
264
+ };
265
+ return /* @__PURE__ */jsxs(Flex, {
266
+ ref: containerRef,
267
+ sx: {
268
+ flexDirection: "column",
269
+ gap: "1",
270
+ position: "relative"
271
+ },
272
+ children: [label && /* @__PURE__ */jsx(Label, {
273
+ children: label
274
+ }), /* @__PURE__ */jsx(Button, {
275
+ disabled,
276
+ variant: "secondary",
277
+ onClick: () => {
278
+ return setIsOpen(!isOpen);
279
+ },
280
+ sx: {
281
+ width: "100%",
282
+ justifyContent: "space-between",
283
+ fontSize: ["14px", "14px"],
284
+ fontWeight: 400,
285
+ backgroundColor: "white",
286
+ padding: "8px 12px",
287
+ borderRadius: "lg",
288
+ border: "md",
289
+ borderColor: "display.border.muted.default",
290
+ height: "40px",
291
+ minWidth: ["auto", "240px"],
292
+ "&:disabled": {
293
+ borderColor: "display.border.muted.default"
294
+ }
295
+ },
296
+ children: date?.from ? date.to ? /* @__PURE__ */jsxs(Text, {
297
+ sx: {
298
+ fontSize: ["12px", "14px"],
299
+ overflow: "hidden",
300
+ textOverflow: "ellipsis",
301
+ whiteSpace: "nowrap"
302
+ },
303
+ children: [formatDate(date.from), " - ", formatDate(date.to)]
304
+ }) : /* @__PURE__ */jsx(Text, {
305
+ sx: {
306
+ fontSize: ["12px", "14px"],
307
+ overflow: "hidden",
308
+ textOverflow: "ellipsis",
309
+ whiteSpace: "nowrap"
310
+ },
311
+ children: formatDate(date.from)
312
+ }) : /* @__PURE__ */jsx(Text, {
313
+ sx: {
314
+ fontSize: ["12px", "14px"]
315
+ },
316
+ children: "Selecione o período"
317
+ })
318
+ }), isOpen && /* @__PURE__ */jsxs(Fragment, {
319
+ children: [/* @__PURE__ */jsx(Box, {
320
+ sx: {
321
+ display: ["block", "none"],
322
+ position: "fixed",
323
+ top: 0,
324
+ left: 0,
325
+ right: 0,
326
+ bottom: 0,
327
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
328
+ zIndex: 49
329
+ },
330
+ onClick: () => {
331
+ return setIsOpen(false);
332
+ }
333
+ }), /* @__PURE__ */jsxs(Box, {
334
+ sx: {
335
+ position: ["fixed", "absolute"],
336
+ top: ["auto", "calc(100% + 4px)"],
337
+ bottom: ["0", "auto"],
338
+ left: ["0", "0"],
339
+ right: ["0", "auto"],
340
+ width: ["100%", "auto"],
341
+ maxWidth: ["100%", "650px"],
342
+ zIndex: 50,
343
+ backgroundColor: "white",
344
+ border: "1px solid",
345
+ borderColor: "display.border.muted.default",
346
+ borderRadius: ["16px 16px 0 0", "8px"],
347
+ boxShadow: ["0 -4px 6px -1px rgba(0, 0, 0, 0.1)", "0 4px 6px -1px rgba(0, 0, 0, 0.1)"],
348
+ overflow: "hidden",
349
+ maxHeight: ["80vh", "none"],
350
+ display: "flex",
351
+ flexDirection: "column"
352
+ },
353
+ children: [/* @__PURE__ */jsxs(Flex, {
354
+ sx: {
355
+ display: ["flex", "none"],
356
+ justifyContent: "space-between",
357
+ alignItems: "center",
358
+ padding: "12px 16px",
359
+ borderBottom: "1px solid",
360
+ borderColor: "display.border.muted.default"
361
+ },
362
+ children: [/* @__PURE__ */jsx(Text, {
363
+ sx: {
364
+ fontSize: "16px",
365
+ fontWeight: 600
366
+ },
367
+ children: label || "Selecione o período"
368
+ }), /* @__PURE__ */jsx(Button, {
369
+ variant: "ghost",
370
+ onClick: () => {
371
+ return setIsOpen(false);
372
+ },
373
+ sx: {
374
+ padding: "4px",
375
+ minWidth: "auto",
376
+ width: "32px",
377
+ height: "32px"
378
+ },
379
+ children: /* @__PURE__ */jsx(Icon, {
380
+ icon: "mdi:close",
381
+ size: 20
382
+ })
383
+ })]
384
+ }), /* @__PURE__ */jsxs(Flex, {
385
+ sx: {
386
+ minHeight: "300px",
387
+ flexDirection: ["column", "row"],
388
+ maxHeight: ["calc(80vh - 60px)", "none"],
389
+ overflow: ["auto", "visible"]
390
+ },
391
+ children: [presets && presets.length > 0 && /* @__PURE__ */jsx(Flex, {
392
+ sx: {
393
+ flexDirection: ["row", "column"],
394
+ gap: "4px",
395
+ padding: ["8px", "12px"],
396
+ borderRight: ["none", "1px solid"],
397
+ borderBottom: ["1px solid", "none"],
398
+ borderColor: "display.border.muted.default",
399
+ backgroundColor: "navigation.background.muted.default",
400
+ minWidth: ["auto", "140px"],
401
+ width: ["100%", "auto"],
402
+ overflowX: ["auto", "visible"],
403
+ overflowY: ["visible", "auto"],
404
+ flexWrap: ["nowrap", "wrap"],
405
+ "@media (max-width: 768px)": {
406
+ "&::-webkit-scrollbar": {
407
+ display: "none"
408
+ },
409
+ scrollbarWidth: "none"
410
+ }
411
+ },
412
+ children: presets?.map(preset => {
413
+ return /* @__PURE__ */jsx(Button, {
414
+ variant: "ghost",
415
+ onClick: () => {
416
+ return handlePresetClick(preset);
417
+ },
418
+ sx: {
419
+ justifyContent: ["center", "flex-start"],
420
+ fontSize: ["12px", "14px"],
421
+ fontWeight: 400,
422
+ padding: ["6px 8px", "8px 12px"],
423
+ color: "display.text.secondary.default",
424
+ backgroundColor: "transparent",
425
+ whiteSpace: "nowrap",
426
+ minWidth: ["auto", "auto"],
427
+ flexShrink: 0,
428
+ "&:hover": {
429
+ backgroundColor: "input.background.muted.active"
430
+ }
431
+ },
432
+ children: preset.label
433
+ }, preset.label);
434
+ })
435
+ }), /* @__PURE__ */jsx(Box, {
436
+ sx: {
437
+ padding: ["12px", "16px"],
438
+ flex: 1,
439
+ overflow: "auto",
440
+ "& .rdp": {
441
+ margin: 0
442
+ },
443
+ "& .rdp-month": {
444
+ width: "100%"
445
+ },
446
+ "& .rdp-day_button": {
447
+ borderRadius: "50% !important",
448
+ border: "none",
449
+ fontSize: ["12px", "14px"],
450
+ width: ["32px", "36px"],
451
+ height: ["32px", "36px"],
452
+ cursor: "pointer"
453
+ },
454
+ "& .rdp-range_start .rdp-day_button": {
455
+ backgroundColor: "action.background.accent.default",
456
+ color: "black"
457
+ },
458
+ "& .rdp-range_end .rdp-day_button": {
459
+ backgroundColor: "action.background.accent.default",
460
+ color: "black"
461
+ },
462
+ "& .rdp-day_button:hover": {
463
+ backgroundColor: "action.background.primary.default",
464
+ color: "action.text.primary.default"
465
+ },
466
+ "& .rdp-day_selected": {
467
+ backgroundColor: "action.background.accent.default",
468
+ color: "white",
469
+ fontWeight: 600
470
+ },
471
+ "& .rdp-day_range_middle": {
472
+ backgroundColor: "action.background.accent.default",
473
+ color: "white"
474
+ },
475
+ "& .rdp-day_range_start, & .rdp-day_range_end": {
476
+ backgroundColor: "action.background.accent.default",
477
+ color: "white",
478
+ fontWeight: 600
479
+ },
480
+ "& .rdp-weekday": {
481
+ fontSize: ["10px", "12px"],
482
+ fontWeight: 500,
483
+ color: "display.text.muted.default"
484
+ },
485
+ "& .rdp-month_caption": {
486
+ fontSize: ["12px", "14px"],
487
+ fontWeight: 600,
488
+ marginBottom: ["12px", "16px"]
489
+ },
490
+ "@media (max-width: 768px)": {
491
+ "& .rdp-caption": {
492
+ marginBottom: "8px"
493
+ },
494
+ "& .rdp-table": {
495
+ width: "100%"
496
+ }
497
+ }
498
+ },
499
+ children: /* @__PURE__ */jsx(DayPicker, {
500
+ disabled,
501
+ mode: "range",
502
+ locale: ptBR,
503
+ selected: pickerSelection?.from ? {
504
+ from: pickerSelection.from,
505
+ to: pickerSelection.to ?? pickerSelection.from
506
+ } : void 0,
507
+ onSelect: selected => {
508
+ return handleDayPickerSelect(selected);
509
+ },
510
+ onDayClick: handleDayClick,
511
+ weekStartsOn: 1,
512
+ showOutsideDays: true
513
+ })
514
+ })]
515
+ })]
516
+ })]
517
+ })]
518
+ });
519
+ };
520
+
521
+ //#endregion
522
+ //#region src/components/Drawer/Drawer.tsx
523
+ var Drawer = ({
524
+ children,
525
+ sx,
526
+ ...props
527
+ }) => {
528
+ return /* @__PURE__ */jsx(Box, {
529
+ "data-testid": "drawer-container",
530
+ sx: {
531
+ /**
532
+ * https://github.com/Farzin-Firoozi/react-modern-drawer/blob/master/src/styles.css
533
+ */
534
+ zIndex: "overlay",
535
+ width: "100%",
536
+ height: "100%",
537
+ ".EZDrawer__checkbox": {
538
+ display: "none"
539
+ },
540
+ ".EZDrawer__checkbox:checked ~ .EZDrawer__overlay": {
541
+ display: "block",
542
+ opacity: 1
543
+ },
544
+ ".EZDrawer__checkbox:checked ~ .EZDrawer__container": {
545
+ visibility: "visible",
546
+ transform: "translate3d(0, 0, 0) !important"
547
+ },
548
+ ".EZDrawer__overlay ": {
549
+ display: "none",
550
+ height: "100vh",
551
+ left: "0",
552
+ position: "fixed",
553
+ top: "0",
554
+ width: "100%"
555
+ },
556
+ ".EZDrawer__container": {
557
+ position: "fixed",
558
+ visibility: "hidden",
559
+ backgroundColor: "navigation.background.muted.default",
560
+ transition: "all",
561
+ boxShadow: "0 0 10px 5px rgba(0, 0, 0, 0.1)",
562
+ paddingX: "6",
563
+ overflowY: "auto"
564
+ },
565
+ ...sx
566
+ },
567
+ children: /* @__PURE__ */jsx(DrawerUi, {
568
+ ...props,
569
+ children: /* @__PURE__ */jsx(Box, {
570
+ sx: {
571
+ width: "100%",
572
+ height: "100%"
573
+ },
574
+ children
575
+ })
576
+ })
577
+ });
578
+ };
579
+
580
+ //#endregion
581
+ //#region src/components/EnhancedTitle/EnhancedTitle.styles.ts
582
+ var gradientFlow = keyframes({
583
+ "0%": {
584
+ backgroundPosition: "0% 50%"
585
+ },
586
+ "50%": {
587
+ backgroundPosition: "100% 50%"
588
+ },
589
+ "100%": {
590
+ backgroundPosition: "0% 50%"
591
+ }
592
+ });
593
+ var getAccentGradientBackground = t => {
594
+ const theme = t;
595
+ const start = theme.colors?.action?.background?.accent?.default || theme.colors?.input?.background?.accent?.default;
596
+ if (!start) return void 0;
597
+ return `linear-gradient(270deg, ${start}, ${theme.colors?.action?.background?.accent?.active || theme.colors?.input?.background?.accent?.active || start}, ${start})`;
598
+ };
599
+ var getPrimaryGradientBackground = t => {
600
+ const theme = t;
601
+ const start = theme.colors?.action?.background?.primary?.default;
602
+ if (!start) return void 0;
603
+ return `linear-gradient(270deg, ${start}, ${theme.colors?.action?.background?.secondary?.default || start}, ${start})`;
604
+ };
605
+ /**
606
+ * Returns style configuration for the icon wrapper based on variant.
607
+ */
608
+ var getEnhancedTitleIconSx = variant => {
609
+ return {
610
+ flexShrink: 0,
611
+ alignItems: "center",
612
+ justifyContent: "center",
613
+ borderRadius: "2xl",
614
+ border: "md",
615
+ width: "56px",
616
+ height: "56px",
617
+ ...{
618
+ "spotlight-accent": {
619
+ backgroundColor: "input.background.accent.default",
620
+ color: "action.text.accent.default",
621
+ borderColor: "display.border.muted.default",
622
+ background: getAccentGradientBackground,
623
+ backgroundSize: "400% 400%",
624
+ animation: `${gradientFlow} 6s ease infinite`
625
+ },
626
+ "spotlight-primary": {
627
+ backgroundColor: "action.background.primary.default",
628
+ color: "display.text.accent.default",
629
+ borderColor: "display.border.muted.default",
630
+ background: getPrimaryGradientBackground,
631
+ backgroundSize: "400% 400%",
632
+ animation: `${gradientFlow} 6s ease infinite`
633
+ },
634
+ primary: {
635
+ backgroundColor: "action.background.primary.default",
636
+ color: "action.text.primary.default",
637
+ borderColor: "display.border.muted.default"
638
+ },
639
+ secondary: {
640
+ backgroundColor: "action.background.secondary.default",
641
+ color: "action.text.primary.default",
642
+ borderColor: "display.border.muted.default"
643
+ },
644
+ accent: {
645
+ backgroundColor: "action.background.accent.default",
646
+ color: "action.text.accent.default",
647
+ borderColor: "display.border.muted.default"
648
+ },
649
+ positive: {
650
+ backgroundColor: "display.bg.positive.boldest",
651
+ color: "display.fg.positive.bolder",
652
+ borderColor: "display.border.muted.default"
653
+ },
654
+ negative: {
655
+ backgroundColor: "display.bg.negative.boldest",
656
+ color: "display.fg.negative.bolder",
657
+ borderColor: "display.border.muted.default"
658
+ },
659
+ informative: {
660
+ backgroundColor: "display.bg.informative.boldest",
661
+ color: "display.fg.informative.bolder",
662
+ borderColor: "display.border.muted.default"
663
+ },
664
+ muted: {
665
+ backgroundColor: "display.bg.muted.boldest",
666
+ color: "display.fg.muted.bolder",
667
+ borderColor: "display.border.muted.default"
668
+ }
669
+ }[variant]
670
+ };
671
+ };
672
+
673
+ //#endregion
674
+ //#region src/components/EnhancedTitle/EnhancedTitle.tsx
675
+ /**
676
+ * EnhancedTitle component renders a structured title section with icon, badges, and metadata.
677
+ *
678
+ * This component is useful for displaying rich title sections with status indicators,
679
+ * feature tags, and supplementary information in a consistent layout.
680
+ *
681
+ * @example
682
+ * ```tsx
683
+ * <EnhancedTitle
684
+ * icon="fluent:shield-24-filled"
685
+ * title="Starter Plan"
686
+ * frontTitle="R$ 49,90/mês"
687
+ * description="Perfect for small teams"
688
+ * variant="primary"
689
+ * topBadges={[
690
+ * { label: 'Active', variant: 'positive', icon: 'fluent:checkmark-circle-24-filled' }
691
+ * ]}
692
+ * bottomBadges={[
693
+ * { label: 'OneClick Tracking', icon: 'fluent:checkmark-24-filled' }
694
+ * ]}
695
+ * />
696
+ * ```
697
+ *
698
+ * @example
699
+ * ```tsx
700
+ * <EnhancedTitle
701
+ * title="Pro Plan"
702
+ * frontTitle="$99/month"
703
+ * variant="accent"
704
+ * topBadges={[
705
+ * { label: 'Most Popular', variant: 'informative' }
706
+ * ]}
707
+ * />
708
+ * ```
709
+ */
710
+ var EnhancedTitle = ({
711
+ variant = "spotlight-primary",
712
+ icon,
713
+ title,
714
+ description,
715
+ frontTitle,
716
+ topBadges = [],
717
+ bottomBadges = []
718
+ }) => {
719
+ return /* @__PURE__ */jsx(Stack, {
720
+ sx: {
721
+ paddingY: "6",
722
+ paddingX: "6",
723
+ width: "full"
724
+ },
725
+ children: /* @__PURE__ */jsxs(Flex, {
726
+ sx: {
727
+ gap: "6",
728
+ alignItems: "flex-start",
729
+ flexDirection: ["column", "row"]
730
+ },
731
+ children: [icon && /* @__PURE__ */jsx(Flex, {
732
+ sx: getEnhancedTitleIconSx(variant),
733
+ children: /* @__PURE__ */jsx(Icon, {
734
+ icon,
735
+ width: 24,
736
+ height: 24
737
+ })
738
+ }), /* @__PURE__ */jsxs(Flex, {
739
+ sx: {
740
+ flexDirection: "column",
741
+ gap: ["4", "5"],
742
+ flex: 1
743
+ },
744
+ children: [topBadges.length > 0 && /* @__PURE__ */jsx(Flex, {
745
+ sx: {
746
+ flexWrap: "wrap",
747
+ gap: "2",
748
+ alignItems: "center"
749
+ },
750
+ children: topBadges.map((badge, index) => {
751
+ return /* @__PURE__ */jsx(Badge, {
752
+ icon: badge.icon,
753
+ variant: badge.variant ?? "muted",
754
+ sx: {
755
+ borderRadius: "full"
756
+ },
757
+ children: badge.label
758
+ }, index);
759
+ })
760
+ }), /* @__PURE__ */jsxs(Flex, {
761
+ sx: {
762
+ flexDirection: ["column", "row"],
763
+ alignItems: ["flex-start", "baseline"],
764
+ gap: ["1", "3"]
765
+ },
766
+ children: [/* @__PURE__ */jsx(Heading, {
767
+ as: "h2",
768
+ sx: {
769
+ fontSize: "4xl",
770
+ fontWeight: "semibold",
771
+ color: "display.text.primary.default"
772
+ },
773
+ children: title
774
+ }), frontTitle && /* @__PURE__ */jsx(Text, {
775
+ sx: {
776
+ fontSize: "xl",
777
+ color: "display.text.secondary.default"
778
+ },
779
+ children: frontTitle
780
+ })]
781
+ }), description && /* @__PURE__ */jsx(Text, {
782
+ sx: {
783
+ fontSize: "md",
784
+ color: "display.text.secondary.default"
785
+ },
786
+ children: description
787
+ }), bottomBadges.length > 0 && /* @__PURE__ */jsx(Flex, {
788
+ sx: {
789
+ flexWrap: "wrap",
790
+ gap: "2"
791
+ },
792
+ children: bottomBadges.map((badge, index) => {
793
+ return /* @__PURE__ */jsx(Badge, {
794
+ icon: badge.icon ?? "fluent:checkmark-24-filled",
795
+ variant: badge.variant ?? "muted",
796
+ sx: {
797
+ borderRadius: "full"
798
+ },
799
+ children: badge.label
800
+ }, index);
801
+ })
802
+ })]
803
+ })]
804
+ })
805
+ });
806
+ };
807
+
808
+ //#endregion
809
+ //#region src/components/FileUploader/FileUploader.tsx
810
+ var FileUploader = ({
811
+ onUpload,
812
+ onUploadStart,
813
+ onUploadProgress,
814
+ onUploadComplete,
815
+ onUploadError,
816
+ onFilesChange,
817
+ onRemove,
818
+ accept,
819
+ multiple = true,
820
+ maxSize = 10 * 1024 * 1024,
821
+ maxFiles = 5,
822
+ disabled = false,
823
+ autoUpload = true,
824
+ retryAttempts = 2,
825
+ placeholder,
826
+ error,
827
+ children,
828
+ showFileList = true,
829
+ FileListComponent,
830
+ files: uploadedFiles = []
831
+ }) => {
832
+ const {
833
+ intl
834
+ } = useI18n();
835
+ const [files, setFiles] = React.useState([]);
836
+ const [isDragOver, setIsDragOver] = React.useState(false);
837
+ const fileInputRef = React.useRef(null);
838
+ const formatFileSize = bytes => {
839
+ if (bytes === 0) return "0 Bytes";
840
+ const k = 1024;
841
+ const sizes = ["Bytes", "KB", "MB", "GB"];
842
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
843
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
844
+ };
845
+ const validateFiles = newFiles => {
846
+ const fileArray = Array.from(newFiles);
847
+ const validFiles = [];
848
+ const currentFileCount = files.length;
849
+ if (currentFileCount >= maxFiles) return [];
850
+ for (const file of fileArray) {
851
+ if (maxSize && file.size > maxSize) continue;
852
+ if (validFiles.length + currentFileCount >= maxFiles) break;
853
+ validFiles.push(file);
854
+ }
855
+ return validFiles;
856
+ };
857
+ const updateFileState = React.useCallback((file, updates) => {
858
+ setFiles(prevFiles => {
859
+ const newFiles = prevFiles.map(f => {
860
+ return f.file === file ? {
861
+ ...f,
862
+ ...updates
863
+ } : f;
864
+ });
865
+ onFilesChange?.(newFiles);
866
+ return newFiles;
867
+ });
868
+ }, [onFilesChange]);
869
+ const uploadFile = React.useCallback(async (fileState, attempts = 0) => {
870
+ try {
871
+ onUploadStart?.(fileState.file);
872
+ updateFileState(fileState.file, {
873
+ status: "uploading",
874
+ progress: 0
875
+ });
876
+ const result = await onUpload(fileState.file, progress => {
877
+ updateFileState(fileState.file, {
878
+ progress
879
+ });
880
+ onUploadProgress?.(fileState.file, progress);
881
+ });
882
+ updateFileState(fileState.file, {
883
+ status: "completed",
884
+ progress: 100,
885
+ result
886
+ });
887
+ onUploadComplete?.(fileState.file, result);
888
+ } catch (error_) {
889
+ const error = error_;
890
+ if (attempts < retryAttempts) setTimeout(() => {
891
+ return uploadFile(fileState, attempts + 1);
892
+ }, 1e3 * (attempts + 1));else {
893
+ updateFileState(fileState.file, {
894
+ status: "error",
895
+ error
896
+ });
897
+ onUploadError?.(fileState.file, error);
898
+ }
899
+ }
900
+ }, [onUpload, onUploadStart, onUploadProgress, onUploadComplete, onUploadError, retryAttempts, updateFileState]);
901
+ const addFiles = newFiles => {
902
+ const newFileStates = newFiles.map(file => {
903
+ return {
904
+ file,
905
+ status: "pending"
906
+ };
907
+ });
908
+ setFiles(prevFiles => {
909
+ const updatedFiles = [...prevFiles, ...newFileStates];
910
+ onFilesChange?.(updatedFiles);
911
+ return updatedFiles;
912
+ });
913
+ if (autoUpload) for (const fileState of newFileStates) uploadFile(fileState);
914
+ };
915
+ const handleFileChange = event => {
916
+ if (event.target.files) addFiles(validateFiles(event.target.files));
917
+ };
918
+ const handleDrop = event => {
919
+ event.preventDefault();
920
+ setIsDragOver(false);
921
+ if (disabled || files.length >= maxFiles) return;
922
+ const droppedFiles = event.dataTransfer.files;
923
+ if (droppedFiles) addFiles(validateFiles(droppedFiles));
924
+ };
925
+ const handleDragOver = event => {
926
+ event.preventDefault();
927
+ if (!disabled && files.length < maxFiles) setIsDragOver(true);
928
+ };
929
+ const handleDragLeave = event => {
930
+ event.preventDefault();
931
+ setIsDragOver(false);
932
+ };
933
+ const handleClick = () => {
934
+ if (!disabled && files.length < maxFiles && fileInputRef.current) fileInputRef.current.click();
935
+ };
936
+ const handleRemoveFile = React.useCallback(index => {
937
+ const fileToRemove = uploadedFiles[index];
938
+ onRemove?.(fileToRemove, index);
939
+ }, [uploadedFiles, onRemove]);
940
+ const isUploading = files.some(f => {
941
+ return f.status === "uploading";
942
+ });
943
+ const isMaxFilesReached = files.length >= maxFiles;
944
+ const fileListNode = React.useMemo(() => {
945
+ if (!showFileList || files.length === 0 && uploadedFiles.length === 0) return null;
946
+ if (FileListComponent) return /* @__PURE__ */jsx(FileListComponent, {
947
+ files: uploadedFiles,
948
+ onRemove: handleRemoveFile
949
+ });
950
+ return /* @__PURE__ */jsx(Stack, {
951
+ sx: {
952
+ gap: 1,
953
+ width: "100%"
954
+ },
955
+ children: uploadedFiles.map((file, index) => {
956
+ return /* @__PURE__ */jsxs(Flex, {
957
+ sx: {
958
+ width: "full",
959
+ alignItems: "center",
960
+ justifyContent: "space-between",
961
+ p: 2,
962
+ backgroundColor: "display.background.secondary.default",
963
+ borderRadius: "md",
964
+ gap: 2
965
+ },
966
+ children: [/* @__PURE__ */jsxs(Flex, {
967
+ sx: {
968
+ alignItems: "center",
969
+ gap: 2,
970
+ flex: 1
971
+ },
972
+ children: [file.imageUrl && /* @__PURE__ */jsx(Box, {
973
+ sx: {
974
+ width: 32,
975
+ height: 32
976
+ },
977
+ children: /* @__PURE__ */jsx("img", {
978
+ src: file.imageUrl,
979
+ alt: file.name,
980
+ style: {
981
+ width: "100%",
982
+ height: "100%",
983
+ objectFit: "cover",
984
+ borderRadius: 4
985
+ }
986
+ })
987
+ }), /* @__PURE__ */jsx(Box, {
988
+ sx: {
989
+ flex: 1
990
+ },
991
+ children: /* @__PURE__ */jsx("a", {
992
+ href: file.url,
993
+ target: "_blank",
994
+ rel: "noopener noreferrer",
995
+ style: {
996
+ textDecoration: "none",
997
+ color: "inherit"
998
+ },
999
+ children: /* @__PURE__ */jsx(Text, {
1000
+ variant: "body",
1001
+ sx: {
1002
+ fontWeight: "medium",
1003
+ "&:hover": {
1004
+ textDecoration: "underline",
1005
+ color: "primary.default"
1006
+ }
1007
+ },
1008
+ children: file.name
1009
+ })
1010
+ })
1011
+ })]
1012
+ }), /* @__PURE__ */jsx(Button, {
1013
+ variant: "destructive",
1014
+ onClick: () => {
1015
+ return handleRemoveFile(index);
1016
+ },
1017
+ sx: {
1018
+ fontSize: "sm",
1019
+ color: "text.muted",
1020
+ "&:hover": {
1021
+ color: "error.default"
1022
+ }
1023
+ },
1024
+ children: intl.formatMessage({
1025
+ id: "G/yZLu",
1026
+ defaultMessage: [{
1027
+ "type": 0,
1028
+ "value": "Remove"
1029
+ }]
1030
+ })
1031
+ })]
1032
+ }, file.id);
1033
+ })
1034
+ });
1035
+ }, [files.length, uploadedFiles, handleRemoveFile, intl, showFileList, FileListComponent]);
1036
+ const placeholderTexts = React.useMemo(() => {
1037
+ const texts = [];
1038
+ if (isUploading) texts.push(intl.formatMessage({
1039
+ id: "JEsxDw",
1040
+ defaultMessage: [{
1041
+ "type": 0,
1042
+ "value": "Uploading..."
1043
+ }]
1044
+ }));else if (isMaxFilesReached) texts.push(intl.formatMessage({
1045
+ id: "eRShvB",
1046
+ defaultMessage: [{
1047
+ "type": 0,
1048
+ "value": "Maximum files reached"
1049
+ }]
1050
+ }));else texts.push(placeholder || intl.formatMessage({
1051
+ id: "gy0Ynb",
1052
+ defaultMessage: [{
1053
+ "type": 0,
1054
+ "value": "Click or drag files here"
1055
+ }]
1056
+ }));
1057
+ if (!isUploading && !isMaxFilesReached) {
1058
+ if (accept) texts.push(accept);
1059
+ if (maxSize) texts.push(`Max ${formatFileSize(maxSize)}`);
1060
+ if (multiple && maxFiles) texts.push(intl.formatMessage({
1061
+ id: "fOOwej",
1062
+ defaultMessage: [{
1063
+ "type": 6,
1064
+ "value": "max_files",
1065
+ "options": {
1066
+ "one": {
1067
+ "value": [{
1068
+ "type": 0,
1069
+ "value": "Up to "
1070
+ }, {
1071
+ "type": 7
1072
+ }, {
1073
+ "type": 0,
1074
+ "value": " file"
1075
+ }]
1076
+ },
1077
+ "other": {
1078
+ "value": [{
1079
+ "type": 0,
1080
+ "value": "Up to "
1081
+ }, {
1082
+ "type": 7
1083
+ }, {
1084
+ "type": 0,
1085
+ "value": " files"
1086
+ }]
1087
+ }
1088
+ },
1089
+ "offset": 0,
1090
+ "pluralType": "cardinal"
1091
+ }]
1092
+ }, {
1093
+ max_files: maxFiles
1094
+ }));
1095
+ }
1096
+ return texts.filter(Boolean).join(" • ");
1097
+ }, [isUploading, isMaxFilesReached, intl, placeholder, accept, maxSize, multiple, maxFiles]);
1098
+ return /* @__PURE__ */jsxs(Stack, {
1099
+ sx: {
1100
+ gap: 3,
1101
+ justifyContent: "stretch",
1102
+ width: "100%"
1103
+ },
1104
+ children: [/* @__PURE__ */jsxs(Box, {
1105
+ onDrop: handleDrop,
1106
+ onDragOver: handleDragOver,
1107
+ onDragLeave: handleDragLeave,
1108
+ onClick: handleClick,
1109
+ sx: {
1110
+ width: "100%",
1111
+ border: "2px dashed",
1112
+ borderColor: error ? "error.default" : isDragOver ? "primary.default" : "display.border.muted.default",
1113
+ borderRadius: "xl",
1114
+ padding: 6,
1115
+ textAlign: "center",
1116
+ cursor: disabled || isUploading || isMaxFilesReached ? "not-allowed" : "pointer",
1117
+ backgroundColor: isDragOver ? "primary.muted" : "display.background.secondary.default",
1118
+ transition: "all 0.2s ease",
1119
+ opacity: disabled || isMaxFilesReached ? .6 : 1,
1120
+ "&:hover": {
1121
+ borderColor: !disabled && !isUploading && !error && !isMaxFilesReached ? "primary.default" : void 0,
1122
+ backgroundColor: !disabled && !isUploading && !isMaxFilesReached ? "primary.muted" : void 0
1123
+ }
1124
+ },
1125
+ children: [/* @__PURE__ */jsx("input", {
1126
+ ref: fileInputRef,
1127
+ type: "file",
1128
+ accept,
1129
+ multiple,
1130
+ onChange: handleFileChange,
1131
+ disabled: disabled || isUploading || isMaxFilesReached,
1132
+ style: {
1133
+ display: "none"
1134
+ }
1135
+ }), children || /* @__PURE__ */jsxs(Flex, {
1136
+ sx: {
1137
+ flexDirection: "column",
1138
+ alignItems: "center",
1139
+ gap: 3,
1140
+ justifyContent: "center"
1141
+ },
1142
+ children: [/* @__PURE__ */jsx(Text, {
1143
+ sx: {
1144
+ fontSize: "2xl"
1145
+ },
1146
+ children: intl.formatMessage({
1147
+ id: "XKyo5X",
1148
+ defaultMessage: [{
1149
+ "type": 0,
1150
+ "value": "File Upload"
1151
+ }]
1152
+ })
1153
+ }), /* @__PURE__ */jsx(Box, {
1154
+ sx: {
1155
+ textAlign: "center"
1156
+ },
1157
+ children: /* @__PURE__ */jsx(Text, {
1158
+ variant: "body",
1159
+ sx: {
1160
+ color: "text.default",
1161
+ mb: 1
1162
+ },
1163
+ children: placeholderTexts
1164
+ })
1165
+ }), !isUploading && !isMaxFilesReached && /* @__PURE__ */jsx(Button, {
1166
+ variant: "secondary",
1167
+ disabled,
1168
+ children: intl.formatMessage({
1169
+ id: "fDCMA6",
1170
+ defaultMessage: [{
1171
+ "type": 0,
1172
+ "value": "Select Files"
1173
+ }]
1174
+ })
1175
+ })]
1176
+ })]
1177
+ }), error && /* @__PURE__ */jsx(Text, {
1178
+ variant: "caption",
1179
+ sx: {
1180
+ color: "error.default"
1181
+ },
1182
+ children: error
1183
+ }), fileListNode]
1184
+ });
1185
+ };
1186
+
1187
+ //#endregion
1188
+ //#region src/components/InstallPwa/InstallPwa.tsx
1189
+ var InstallPwaUi = ({
1190
+ onInstall
1191
+ }) => {
1192
+ return /* @__PURE__ */jsx(Flex, {
1193
+ sx: {
1194
+ position: "absolute",
1195
+ bottom: 4,
1196
+ width: "100%",
1197
+ justifyContent: "center"
1198
+ },
1199
+ children: /* @__PURE__ */jsxs(Flex, {
1200
+ sx: {
1201
+ backgroundColor: "background",
1202
+ justifyContent: "center",
1203
+ alignItems: "center",
1204
+ gap: 3,
1205
+ width: "auto",
1206
+ border: "1px solid",
1207
+ borderColor: "muted",
1208
+ borderRadius: 1,
1209
+ padding: 4
1210
+ },
1211
+ children: [/* @__PURE__ */jsx(Text, {
1212
+ children: "Deseja instalar o nosso aplicativo?"
1213
+ }), /* @__PURE__ */jsx(Button, {
1214
+ onClick: onInstall,
1215
+ children: "Instalar"
1216
+ })]
1217
+ })
1218
+ });
1219
+ };
1220
+ var InstallPwa = () => {
1221
+ const [supportsPwa, setSupportsPwa] = React.useState(false);
1222
+ const [promptInstall, setPromptInstall] = React.useState(null);
1223
+ React.useEffect(() => {
1224
+ const handler = e => {
1225
+ e.preventDefault();
1226
+ setSupportsPwa(true);
1227
+ setPromptInstall(e);
1228
+ };
1229
+ window.addEventListener("beforeinstallprompt", handler);
1230
+ return () => {
1231
+ return window.removeEventListener("transitionend", handler);
1232
+ };
1233
+ }, []);
1234
+ const onInstall = e => {
1235
+ e.preventDefault();
1236
+ if (!promptInstall) return;
1237
+ promptInstall.prompt();
1238
+ };
1239
+ if (!supportsPwa) return null;
1240
+ return /* @__PURE__ */jsx(InstallPwaUi, {
1241
+ onInstall
1242
+ });
1243
+ };
1244
+
1245
+ //#endregion
1246
+ //#region src/components/List/List.tsx
1247
+ var List = React.forwardRef(({
1248
+ children,
1249
+ ...props
1250
+ }, ref) => {
1251
+ return /* @__PURE__ */jsx("ul", {
1252
+ ...props,
1253
+ ref,
1254
+ children
1255
+ });
1256
+ });
1257
+ List.displayName = "List";
1258
+
1259
+ //#endregion
1260
+ //#region src/components/List/ListItem.tsx
1261
+ var ListItem = React.forwardRef((props, ref) => {
1262
+ const {
1263
+ children,
1264
+ ...rest
1265
+ } = props;
1266
+ return /* @__PURE__ */jsx("li", {
1267
+ ...rest,
1268
+ ref,
1269
+ children
1270
+ });
1271
+ });
1272
+ ListItem.displayName = "ListItem";
1273
+
1274
+ //#endregion
1275
+ //#region src/components/SpotlightCard/SpotlightCard.tsx
1276
+ var SpotlightCard = ({
1277
+ icon,
1278
+ title,
1279
+ badge,
1280
+ description,
1281
+ firstButton,
1282
+ secondButton,
1283
+ variant = "accent"
1284
+ }) => {
1285
+ const gradientFlow = keyframes({
1286
+ "0%": {
1287
+ backgroundPosition: "0% 50%"
1288
+ },
1289
+ "50%": {
1290
+ backgroundPosition: "100% 50%"
1291
+ },
1292
+ "100%": {
1293
+ backgroundPosition: "0% 50%"
1294
+ }
1295
+ });
1296
+ const hasButtons = !!firstButton || !!secondButton;
1297
+ const isAccent = variant === "accent";
1298
+ const textColorToken = isAccent ? "action.text.accent.default" : "action.text.primary.default";
1299
+ const iconColorToken = isAccent ? "action.text.accent.default" : "display.text.accent.default";
1300
+ const iconBgToken = isAccent ? "rgba(255,255,255,0.3)" : "action.background.secondary.default";
1301
+ const badgeBgToken = isAccent ? "action.background.primary.default" : "action.background.accent.default";
1302
+ const badgeTextToken = isAccent ? "action.text.primary.default" : "action.text.accent.default";
1303
+ const btnPrimaryVariant = isAccent ? "primary" : "accent";
1304
+ const btnPrimaryColorToken = isAccent ? "action.text.primary.default" : "action.text.accent.default";
1305
+ const btnSecondaryColorToken = textColorToken;
1306
+ const btnSecondaryBorderColorToken = isAccent ? "currentColor" : "display.border.muted.default";
1307
+ const renderButton = (prop, config) => {
1308
+ if (!prop) return null;
1309
+ if (React.isValidElement(prop)) return prop;
1310
+ if (typeof prop !== "object") return prop;
1311
+ const {
1312
+ sx,
1313
+ ...rest
1314
+ } = prop;
1315
+ const {
1316
+ variant: defaultVariant,
1317
+ textColor,
1318
+ styles = {}
1319
+ } = config;
1320
+ return /* @__PURE__ */jsx(Button, {
1321
+ variant: defaultVariant,
1322
+ sx: {
1323
+ display: "flex",
1324
+ alignItems: "center",
1325
+ justifyContent: "center",
1326
+ gap: "2",
1327
+ px: "6",
1328
+ py: "3",
1329
+ fontSize: "15px",
1330
+ fontWeight: "bold",
1331
+ whiteSpace: "nowrap",
1332
+ transition: "all 0.2s",
1333
+ color: textColor,
1334
+ ...styles,
1335
+ ...sx
1336
+ },
1337
+ ...rest
1338
+ });
1339
+ };
1340
+ return /* @__PURE__ */jsxs(Card, {
1341
+ sx: {
1342
+ display: "flex",
1343
+ flexDirection: ["row"],
1344
+ flexWrap: "nowrap",
1345
+ alignItems: "center",
1346
+ justifyContent: "space-between",
1347
+ background: t => {
1348
+ const theme = t;
1349
+ const bgStart = isAccent ? theme.colors?.action?.background?.accent?.default : theme.colors?.action?.background?.primary?.default;
1350
+ const bgMiddle = isAccent ? theme.colors?.action?.background?.accent?.active : theme.colors?.action?.background?.secondary?.default;
1351
+ if (isAccent) return `linear-gradient(270deg, transparent 0%, rgba(255,255,255,0.4) 50%, transparent 100%),
1352
+ linear-gradient(0deg, ${bgStart}, ${bgStart})`;
1353
+ return `linear-gradient(270deg, ${bgStart}, ${bgMiddle}, ${bgStart})`;
1354
+ },
1355
+ backgroundSize: isAccent ? "200% 100%, auto" : "400% 400%",
1356
+ animation: `${gradientFlow} 6s ease infinite`,
1357
+ width: "100%",
1358
+ minHeight: "104px",
1359
+ borderRadius: "xl",
1360
+ boxShadow: "0 4px 20px rgba(0,0,0,0.1)",
1361
+ py: "7",
1362
+ px: "8",
1363
+ gap: "5",
1364
+ color: textColorToken,
1365
+ overflow: "hidden",
1366
+ borderWidth: "1px",
1367
+ borderStyle: "solid",
1368
+ borderColor: isAccent ? "transparent" : "display.border.muted.default"
1369
+ },
1370
+ "data-testid": "spotlight-card",
1371
+ children: [/* @__PURE__ */jsxs(Flex, {
1372
+ sx: {
1373
+ alignItems: "center",
1374
+ gap: "5",
1375
+ flex: 1,
1376
+ minWidth: 0
1377
+ },
1378
+ children: [/* @__PURE__ */jsx(Box, {
1379
+ sx: {
1380
+ width: 64,
1381
+ height: 64,
1382
+ borderRadius: "2xl",
1383
+ backgroundColor: iconBgToken,
1384
+ display: "flex",
1385
+ alignItems: "center",
1386
+ justifyContent: "center",
1387
+ flexShrink: 0,
1388
+ color: iconColorToken
1389
+ },
1390
+ children: /* @__PURE__ */jsx(Icon, {
1391
+ icon,
1392
+ width: 32
1393
+ })
1394
+ }), /* @__PURE__ */jsxs(Box, {
1395
+ sx: {
1396
+ minWidth: 0
1397
+ },
1398
+ children: [/* @__PURE__ */jsxs(Text, {
1399
+ as: "div",
1400
+ sx: {
1401
+ fontFamily: "mono",
1402
+ fontSize: "32px",
1403
+ lineHeight: 1.1,
1404
+ color: "inherit",
1405
+ whiteSpace: "nowrap",
1406
+ display: "flex",
1407
+ alignItems: "center",
1408
+ gap: "3"
1409
+ },
1410
+ children: [title, badge && /* @__PURE__ */jsx(Box, {
1411
+ as: "span",
1412
+ sx: {
1413
+ backgroundColor: badgeBgToken,
1414
+ color: badgeTextToken,
1415
+ fontFamily: "mono",
1416
+ fontWeight: "bold",
1417
+ fontSize: "11px",
1418
+ lineHeight: 1,
1419
+ paddingX: "6px",
1420
+ paddingY: "3px",
1421
+ borderRadius: "md",
1422
+ textTransform: "uppercase",
1423
+ letterSpacing: "0.05em",
1424
+ display: "inline-flex",
1425
+ alignItems: "center",
1426
+ boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
1427
+ transform: "translateY(3px)"
1428
+ },
1429
+ children: badge
1430
+ })]
1431
+ }), /* @__PURE__ */jsx(Text, {
1432
+ as: "div",
1433
+ sx: {
1434
+ fontFamily: "body",
1435
+ fontWeight: 400,
1436
+ fontSize: "16px",
1437
+ color: "inherit",
1438
+ opacity: .9,
1439
+ mt: "1",
1440
+ overflow: "hidden",
1441
+ textOverflow: "ellipsis",
1442
+ display: "-webkit-box",
1443
+ WebkitLineClamp: 2,
1444
+ WebkitBoxOrient: "vertical"
1445
+ },
1446
+ children: description
1447
+ })]
1448
+ })]
1449
+ }), hasButtons && /* @__PURE__ */jsxs(Flex, {
1450
+ sx: {
1451
+ gap: "4",
1452
+ alignItems: "center",
1453
+ flexShrink: 0,
1454
+ ml: "auto"
1455
+ },
1456
+ children: [renderButton(firstButton, {
1457
+ variant: btnPrimaryVariant,
1458
+ textColor: btnPrimaryColorToken,
1459
+ styles: {
1460
+ ":hover": {
1461
+ transform: "translateY(-1px)"
1462
+ }
1463
+ }
1464
+ }), renderButton(secondButton, {
1465
+ variant: "secondary",
1466
+ textColor: btnSecondaryColorToken,
1467
+ styles: {
1468
+ backgroundColor: "transparent",
1469
+ borderWidth: "1px",
1470
+ borderStyle: "solid",
1471
+ borderColor: btnSecondaryBorderColorToken,
1472
+ opacity: isAccent ? .6 : 1,
1473
+ cursor: "pointer",
1474
+ ":hover": {
1475
+ backgroundColor: "rgba(255,255,255,0.2)",
1476
+ opacity: 1,
1477
+ borderColor: btnSecondaryBorderColorToken
1478
+ }
1479
+ }
1480
+ })]
1481
+ })]
1482
+ });
1483
+ };
1484
+ SpotlightCard.displayName = "SpotlightCard";
1485
+
1486
+ //#endregion
1487
+ //#region src/components/LockedOverlay/LockedOverlay.tsx
1488
+ /**
1489
+ * LockedOverlay is a component for blocking and displaying locked features or restricted content
1490
+ * within a specific container.
1491
+ *
1492
+ * This component renders as an absolutely positioned overlay that blocks the parent container's content.
1493
+ * The parent container must have `position: relative` for proper positioning.
1494
+ *
1495
+ * Unlike a modal, this component blocks only its parent container, not the entire viewport,
1496
+ * making it ideal for blocking specific sections like Layout.Main, Layout.Main.Body, etc.
1497
+ *
1498
+ * @example
1499
+ * ```tsx
1500
+ * // Parent container must have position: relative
1501
+ * <Layout.Main sx={{ position: 'relative' }}>
1502
+ * <LockedOverlay
1503
+ * isOpen={isOpen}
1504
+ * onRequestClose={() => setIsOpen(false)}
1505
+ * header={{
1506
+ * icon: "fluent:lock-closed-24-filled",
1507
+ * title: "Premium Feature",
1508
+ * description: "Available in Pro plan only",
1509
+ * variant: "primary"
1510
+ * }}
1511
+ * actions={[
1512
+ * {
1513
+ * label: "Upgrade Now",
1514
+ * icon: "fluent-emoji-high-contrast:sparkles",
1515
+ * variant: "primary",
1516
+ * onClick: handleUpgrade
1517
+ * },
1518
+ * {
1519
+ * label: "Learn More",
1520
+ * icon: "fluent:arrow-right-16-regular",
1521
+ * variant: "accent",
1522
+ * onClick: handleLearnMore
1523
+ * }
1524
+ * ]}
1525
+ * >
1526
+ * <Text>This feature is only available for Pro users.</Text>
1527
+ * </LockedOverlay>
1528
+ * </Layout.Main>
1529
+ * ```
1530
+ *
1531
+ * @example
1532
+ * ```tsx
1533
+ * // Blocking a specific section with custom zIndex
1534
+ * <Box sx={{ position: 'relative' }}>
1535
+ * <LockedOverlay
1536
+ * isOpen={isOpen}
1537
+ * zIndex={10}
1538
+ * header={{
1539
+ * icon: "fluent:lock-closed-24-filled",
1540
+ * title: "Feature Locked",
1541
+ * description: "Unlock this feature"
1542
+ * }}
1543
+ * >
1544
+ * <Text>Content here</Text>
1545
+ * </LockedOverlay>
1546
+ * </Box>
1547
+ * ```
1548
+ */
1549
+ var LockedOverlay = ({
1550
+ isOpen,
1551
+ onRequestClose,
1552
+ header,
1553
+ firstButton,
1554
+ secondButton,
1555
+ children,
1556
+ actions,
1557
+ sx,
1558
+ zIndex = 1
1559
+ }) => {
1560
+ const content = /* @__PURE__ */jsxs(Card, {
1561
+ className: "lockedoverlay-card",
1562
+ role: "dialog",
1563
+ "aria-modal": true,
1564
+ sx: {
1565
+ width: "full",
1566
+ maxWidth: "620px",
1567
+ borderRadius: "lg",
1568
+ overflow: "auto",
1569
+ border: "none",
1570
+ boxShadow: "none"
1571
+ },
1572
+ children: [/* @__PURE__ */jsx(Flex, {
1573
+ sx: {
1574
+ width: "full",
1575
+ paddingX: "6",
1576
+ paddingY: "4"
1577
+ },
1578
+ children: /* @__PURE__ */jsx(SpotlightCard, {
1579
+ icon: header.icon,
1580
+ title: header.title,
1581
+ description: header.description,
1582
+ variant: header.variant || "primary",
1583
+ firstButton,
1584
+ secondButton
1585
+ })
1586
+ }), /* @__PURE__ */jsxs(Card.Body, {
1587
+ sx: {
1588
+ px: ["5", "7"],
1589
+ py: ["6", "7"],
1590
+ gap: "6",
1591
+ width: "full"
1592
+ },
1593
+ children: [children, actions && actions.length > 0 && /* @__PURE__ */jsx(Card.Footer, {
1594
+ children: /* @__PURE__ */jsx(Flex, {
1595
+ className: "lockedoverlay-footer",
1596
+ sx: {
1597
+ flexDirection: "column",
1598
+ gap: "4",
1599
+ alignItems: "center",
1600
+ width: "full",
1601
+ paddingX: "6",
1602
+ marginTop: "8"
1603
+ },
1604
+ children: actions.map((action, index) => {
1605
+ return /* @__PURE__ */jsxs(Button, {
1606
+ variant: action.variant,
1607
+ onClick: action.onClick,
1608
+ sx: {
1609
+ width: "full",
1610
+ justifyContent: "center"
1611
+ },
1612
+ children: [action.icon && /* @__PURE__ */jsx(Icon, {
1613
+ icon: action.icon
1614
+ }), action.label]
1615
+ }, index);
1616
+ })
1617
+ })
1618
+ })]
1619
+ })]
1620
+ });
1621
+ if (!isOpen) return null;
1622
+ return /* @__PURE__ */jsx(Flex, {
1623
+ "data-testid": "lockedoverlay-overlay",
1624
+ onClick: () => {
1625
+ return onRequestClose?.();
1626
+ },
1627
+ sx: {
1628
+ position: "absolute",
1629
+ inset: 0,
1630
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
1631
+ display: "flex",
1632
+ justifyContent: "center",
1633
+ alignItems: "center",
1634
+ zIndex,
1635
+ ...sx
1636
+ },
1637
+ children: /* @__PURE__ */jsx(Flex, {
1638
+ onClick: event => {
1639
+ event.stopPropagation();
1640
+ },
1641
+ sx: {
1642
+ width: "full",
1643
+ maxWidth: ["95%", "90%", "620px"],
1644
+ maxHeight: "90%",
1645
+ justifyContent: "center",
1646
+ overflow: "auto"
1647
+ },
1648
+ children: content
1649
+ })
1650
+ });
1651
+ };
1652
+
1653
+ //#endregion
1654
+ //#region src/components/Markdown/Markdown.tsx
1655
+ var Markdown = ({
1656
+ children,
1657
+ sx,
1658
+ ...props
1659
+ }) => {
1660
+ return /* @__PURE__ */jsx(BaseStyles, {
1661
+ sx,
1662
+ children: /* @__PURE__ */jsx(ReactMarkdown, {
1663
+ rehypePlugins: [rehypeRaw],
1664
+ remarkPlugins: [remarkGfm],
1665
+ ...props,
1666
+ children
1667
+ })
1668
+ });
1669
+ };
1670
+
1671
+ //#endregion
1672
+ //#region src/components/Menu/Menu.tsx
1673
+ var Menu = ({
1674
+ children,
1675
+ sx,
1676
+ menuIcon = "menu-open"
1677
+ }) => {
1678
+ const [isOpen, setIsOpen] = React.useState(false);
1679
+ const [stylePos, setStylePos] = React.useState({});
1680
+ const triggerRef = React.useRef(null);
1681
+ const panelRef = React.useRef(null);
1682
+ const toggle = () => {
1683
+ return setIsOpen(v => {
1684
+ return !v;
1685
+ });
1686
+ };
1687
+ React.useEffect(() => {
1688
+ if (!isOpen) return;
1689
+ const onDocClick = e => {
1690
+ const t = e.target;
1691
+ if (panelRef.current && !panelRef.current.contains(t) && triggerRef.current && !triggerRef.current.contains(t)) setIsOpen(false);
1692
+ };
1693
+ document.addEventListener("mousedown", onDocClick);
1694
+ return () => {
1695
+ return document.removeEventListener("mousedown", onDocClick);
1696
+ };
1697
+ }, [isOpen]);
1698
+ React.useLayoutEffect(() => {
1699
+ if (!isOpen) return;
1700
+ let rafId = 0;
1701
+ const getWidth = () => {
1702
+ const w = sx?.width ?? sx?.maxWidth ?? sx?.minWidth;
1703
+ return Array.isArray(w) ? w[w.length - 1] : w;
1704
+ };
1705
+ const compute = () => {
1706
+ const trigger = triggerRef.current;
1707
+ const panel = panelRef.current;
1708
+ if (!trigger || !panel) return;
1709
+ const width = getWidth();
1710
+ if (width) panel.style.width = typeof width === "number" ? `${width}px` : String(width);
1711
+ const tr = trigger.getBoundingClientRect();
1712
+ const pr = panel.getBoundingClientRect();
1713
+ const vw = window.innerWidth,
1714
+ vh = window.innerHeight,
1715
+ m = 8;
1716
+ if (pr.width === 0) {
1717
+ rafId = requestAnimationFrame(compute);
1718
+ return;
1719
+ }
1720
+ const left = Math.max(m, Math.min(tr.left + tr.width / 2 - pr.width / 2, vw - pr.width - m));
1721
+ const top = vh - tr.bottom < pr.height + m ? Math.max(m, tr.top - pr.height - m) : tr.bottom + m;
1722
+ setStylePos({
1723
+ position: "fixed",
1724
+ left: `${left}px`,
1725
+ top: `${top}px`,
1726
+ zIndex: 9999,
1727
+ ...(width && {
1728
+ width: typeof width === "number" ? `${width}px` : String(width)
1729
+ })
1730
+ });
1731
+ };
1732
+ rafId = requestAnimationFrame(compute);
1733
+ const onResizeScroll = () => {
1734
+ return rafId = requestAnimationFrame(compute);
1735
+ };
1736
+ window.addEventListener("resize", onResizeScroll);
1737
+ window.addEventListener("scroll", onResizeScroll, true);
1738
+ return () => {
1739
+ cancelAnimationFrame(rafId);
1740
+ window.removeEventListener("resize", onResizeScroll);
1741
+ window.removeEventListener("scroll", onResizeScroll, true);
1742
+ };
1743
+ }, [isOpen, sx]);
1744
+ const panel = isOpen ? /* @__PURE__ */jsx(Flex, {
1745
+ ref: panelRef,
1746
+ sx: {
1747
+ width: ["280px", "320px"],
1748
+ maxHeight: "400px",
1749
+ flexDirection: "column",
1750
+ gap: "3",
1751
+ padding: "3",
1752
+ backgroundColor: "input.background.muted.default",
1753
+ borderRadius: "xl",
1754
+ boxShadow: "xl",
1755
+ overflowY: "auto",
1756
+ border: "md",
1757
+ borderColor: "display.border.muted.default",
1758
+ ...sx
1759
+ },
1760
+ style: {
1761
+ pointerEvents: "auto",
1762
+ ...stylePos
1763
+ },
1764
+ children: /* @__PURE__ */jsx(Box, {
1765
+ as: "nav",
1766
+ children
1767
+ })
1768
+ }) : null;
1769
+ return /* @__PURE__ */jsx(Flex, {
1770
+ sx: {
1771
+ position: "relative",
1772
+ display: "inline-block"
1773
+ },
1774
+ children: /* @__PURE__ */jsxs(Box, {
1775
+ sx: {
1776
+ position: "relative"
1777
+ },
1778
+ children: [/* @__PURE__ */jsx("button", {
1779
+ ref: triggerRef,
1780
+ onClick: toggle,
1781
+ "aria-haspopup": "true",
1782
+ "aria-expanded": isOpen,
1783
+ style: {
1784
+ background: "transparent",
1785
+ border: 0,
1786
+ padding: 4,
1787
+ cursor: "pointer",
1788
+ display: "inline-flex",
1789
+ alignItems: "center",
1790
+ justifyContent: "center"
1791
+ },
1792
+ children: /* @__PURE__ */jsx(Icon, {
1793
+ icon: menuIcon
1794
+ })
1795
+ }), isOpen && panel]
1796
+ })
1797
+ });
1798
+ };
1799
+
1800
+ //#endregion
1801
+ //#region src/components/MetricCard/MetricCard.tsx
1802
+ var messages = defineMessages({
1803
+ ofMax: {
1804
+ id: "oYpm71",
1805
+ defaultMessage: [{
1806
+ "type": 0,
1807
+ "value": "of "
1808
+ }, {
1809
+ "type": 1,
1810
+ "value": "max"
1811
+ }]
1812
+ },
1813
+ percentageUsed: {
1814
+ id: "zr0OS6",
1815
+ defaultMessage: [{
1816
+ "type": 1,
1817
+ "value": "percentage"
1818
+ }, {
1819
+ "type": 0,
1820
+ "value": "% used"
1821
+ }]
1822
+ },
1823
+ unlimited: {
1824
+ id: "rskBv4",
1825
+ defaultMessage: [{
1826
+ "type": 0,
1827
+ "value": "Unlimited"
1828
+ }]
1829
+ },
1830
+ infinity: {
1831
+ id: "0EjvY6",
1832
+ defaultMessage: [{
1833
+ "type": 0,
1834
+ "value": "∞"
1835
+ }]
1836
+ },
1837
+ nearLimit: {
1838
+ id: "1DbX9V",
1839
+ defaultMessage: [{
1840
+ "type": 0,
1841
+ "value": "Near limit"
1842
+ }]
1843
+ },
1844
+ reachedLimit: {
1845
+ id: "4NwCn9",
1846
+ defaultMessage: [{
1847
+ "type": 0,
1848
+ "value": "Reached limit"
1849
+ }]
1850
+ }
1851
+ });
1852
+ /**
1853
+ * Icon wrapper for metric cards.
1854
+ */
1855
+ var MetricIconWrapper = ({
1856
+ icon
1857
+ }) => {
1858
+ return /* @__PURE__ */jsx(Flex, {
1859
+ sx: {
1860
+ alignItems: "center",
1861
+ justifyContent: "center",
1862
+ borderRadius: "full",
1863
+ border: "md",
1864
+ borderColor: "display.border.muted.default",
1865
+ backgroundColor: "display.background.muted.default",
1866
+ color: "display.text.secondary.default",
1867
+ width: "48px",
1868
+ height: "48px",
1869
+ flexShrink: 0
1870
+ },
1871
+ children: icon && /* @__PURE__ */jsx(Icon, {
1872
+ icon
1873
+ })
1874
+ });
1875
+ };
1876
+ /**
1877
+ * Card header with label, tooltip, and optional clickable icon.
1878
+ */
1879
+ var MetricCardHeader = ({
1880
+ label,
1881
+ tooltip,
1882
+ isClickable
1883
+ }) => {
1884
+ const isTooltipAction = typeof tooltip === "function";
1885
+ const tooltipText = typeof tooltip === "string" ? tooltip : void 0;
1886
+ return /* @__PURE__ */jsxs(Flex, {
1887
+ sx: {
1888
+ alignItems: "center",
1889
+ gap: "2"
1890
+ },
1891
+ children: [/* @__PURE__ */jsx(Text, {
1892
+ sx: {
1893
+ fontSize: "sm",
1894
+ fontWeight: "medium",
1895
+ color: "display.text.secondary.default"
1896
+ },
1897
+ children: label
1898
+ }), tooltipText && /* @__PURE__ */jsx(TooltipIcon, {
1899
+ icon: "fluent:info-24-regular",
1900
+ tooltip: {
1901
+ children: tooltipText
1902
+ },
1903
+ variant: "info"
1904
+ }), isTooltipAction && /* @__PURE__ */jsx(Text, {
1905
+ onClick: e => {
1906
+ e.stopPropagation();
1907
+ tooltip();
1908
+ },
1909
+ sx: {
1910
+ fontSize: "sm",
1911
+ color: "display.text.secondary.default",
1912
+ cursor: "pointer",
1913
+ ":hover": {
1914
+ color: "action.text.primary.default"
1915
+ }
1916
+ },
1917
+ children: /* @__PURE__ */jsx(Icon, {
1918
+ icon: "fluent:info-24-regular",
1919
+ inline: true
1920
+ })
1921
+ }), isClickable && /* @__PURE__ */jsx(Text, {
1922
+ sx: {
1923
+ fontSize: "sm",
1924
+ color: "display.text.secondary.default"
1925
+ },
1926
+ children: /* @__PURE__ */jsx(Icon, {
1927
+ icon: "fluent:open-24-regular",
1928
+ inline: true
1929
+ })
1930
+ })]
1931
+ });
1932
+ };
1933
+ /**
1934
+ * Renders the content for a date metric.
1935
+ */
1936
+ var DateMetricContent = ({
1937
+ metric
1938
+ }) => {
1939
+ return /* @__PURE__ */jsxs(Fragment, {
1940
+ children: [/* @__PURE__ */jsx(Text, {
1941
+ sx: {
1942
+ fontSize: "2xl",
1943
+ fontWeight: "bold",
1944
+ color: "display.text.primary.default"
1945
+ },
1946
+ children: metric.date
1947
+ }), metric.remainingDaysMessage && /* @__PURE__ */jsxs(Flex, {
1948
+ sx: {
1949
+ alignItems: "center",
1950
+ gap: "2"
1951
+ },
1952
+ children: [/* @__PURE__ */jsx(Text, {
1953
+ sx: {
1954
+ fontSize: "sm",
1955
+ color: metric.isWarning ? "feedback.text.caution.default" : "display.text.secondary.default"
1956
+ },
1957
+ children: /* @__PURE__ */jsx(Icon, {
1958
+ icon: metric.isWarning ? "fluent:warning-24-regular" : "fluent:clock-24-regular",
1959
+ inline: true
1960
+ })
1961
+ }), /* @__PURE__ */jsx(Text, {
1962
+ sx: {
1963
+ fontSize: "sm",
1964
+ color: metric.isWarning ? "feedback.text.caution.default" : "display.text.secondary.default"
1965
+ },
1966
+ children: metric.remainingDaysMessage
1967
+ })]
1968
+ })]
1969
+ });
1970
+ };
1971
+ /**
1972
+ * Renders the content for a percentage metric.
1973
+ */
1974
+ var PercentageMetricContent = ({
1975
+ metric
1976
+ }) => {
1977
+ const {
1978
+ intl
1979
+ } = useI18n();
1980
+ const percentage = metric.max === null || metric.max <= 0 ? null : Math.min(Math.round(metric.current / metric.max * 100), 100);
1981
+ const formatValue = metric.formatValue || (val => {
1982
+ return val.toString();
1983
+ });
1984
+ const showAlert = percentage !== null && metric.showAlertThreshold !== void 0 && percentage >= metric.showAlertThreshold;
1985
+ const isOverLimit = percentage !== null && percentage >= 100;
1986
+ const maxText = metric.max !== null ? formatValue(metric.max) : intl.formatMessage(messages.infinity);
1987
+ return /* @__PURE__ */jsxs(Fragment, {
1988
+ children: [/* @__PURE__ */jsxs(Flex, {
1989
+ sx: {
1990
+ alignItems: "baseline",
1991
+ justifyContent: "space-between",
1992
+ gap: "2"
1993
+ },
1994
+ children: [/* @__PURE__ */jsx(Text, {
1995
+ sx: {
1996
+ fontSize: "2xl",
1997
+ fontWeight: "bold",
1998
+ color: "display.text.primary.default"
1999
+ },
2000
+ children: formatValue(metric.current)
2001
+ }), /* @__PURE__ */jsx(Text, {
2002
+ sx: {
2003
+ fontSize: "sm",
2004
+ color: "display.text.secondary.default"
2005
+ },
2006
+ children: intl.formatMessage(messages.ofMax, {
2007
+ max: maxText
2008
+ })
2009
+ })]
2010
+ }), /* @__PURE__ */jsx(Box, {
2011
+ sx: {
2012
+ width: "full",
2013
+ height: "8px",
2014
+ backgroundColor: "display.background.secondary.default",
2015
+ borderRadius: "full",
2016
+ overflow: "hidden"
2017
+ },
2018
+ children: /* @__PURE__ */jsx(Box, {
2019
+ sx: {
2020
+ height: "full",
2021
+ width: percentage !== null ? `${percentage}%` : "100%",
2022
+ backgroundColor: "action.background.primary.default",
2023
+ borderRadius: "full",
2024
+ transition: "width 0.5s ease-out"
2025
+ }
2026
+ })
2027
+ }), /* @__PURE__ */jsxs(Flex, {
2028
+ sx: {
2029
+ alignItems: "center",
2030
+ justifyContent: "space-between",
2031
+ fontSize: "xs"
2032
+ },
2033
+ children: [/* @__PURE__ */jsx(Text, {
2034
+ sx: {
2035
+ color: "display.text.secondary.default"
2036
+ },
2037
+ children: percentage !== null ? intl.formatMessage(messages.percentageUsed, {
2038
+ percentage
2039
+ }) : intl.formatMessage(messages.unlimited)
2040
+ }), showAlert && !isOverLimit && /* @__PURE__ */jsxs(Flex, {
2041
+ sx: {
2042
+ alignItems: "center",
2043
+ gap: "1",
2044
+ color: "feedback.text.caution.default"
2045
+ },
2046
+ children: [/* @__PURE__ */jsx(Icon, {
2047
+ icon: "fluent:warning-24-regular"
2048
+ }), /* @__PURE__ */jsx(Text, {
2049
+ sx: {
2050
+ fontWeight: "medium"
2051
+ },
2052
+ children: intl.formatMessage(messages.nearLimit)
2053
+ })]
2054
+ }), showAlert && isOverLimit && /* @__PURE__ */jsxs(Flex, {
2055
+ sx: {
2056
+ alignItems: "center",
2057
+ gap: "1",
2058
+ color: "feedback.text.negative.default"
2059
+ },
2060
+ children: [/* @__PURE__ */jsx(Icon, {
2061
+ icon: "fluent:warning-24-regular"
2062
+ }), /* @__PURE__ */jsx(Text, {
2063
+ sx: {
2064
+ fontWeight: "medium",
2065
+ color: "feedback.text.negative.default"
2066
+ },
2067
+ children: intl.formatMessage(messages.reachedLimit)
2068
+ })]
2069
+ })]
2070
+ })]
2071
+ });
2072
+ };
2073
+ /**
2074
+ * Renders the content for a number metric.
2075
+ */
2076
+ var NumberMetricContent = ({
2077
+ metric
2078
+ }) => {
2079
+ const {
2080
+ intl
2081
+ } = useI18n();
2082
+ const formatValue = metric.formatValue || (val => {
2083
+ return val.toString();
2084
+ });
2085
+ const maxText = metric.max !== null ? formatValue(metric.max) : intl.formatMessage(messages.infinity);
2086
+ return /* @__PURE__ */jsxs(Fragment, {
2087
+ children: [/* @__PURE__ */jsxs(Flex, {
2088
+ sx: {
2089
+ alignItems: "baseline",
2090
+ gap: "3"
2091
+ },
2092
+ children: [/* @__PURE__ */jsx(Text, {
2093
+ sx: {
2094
+ fontSize: "2xl",
2095
+ fontWeight: "bold",
2096
+ color: "display.text.primary.default"
2097
+ },
2098
+ children: formatValue(metric.current)
2099
+ }), /* @__PURE__ */jsx(Text, {
2100
+ sx: {
2101
+ fontSize: "sm",
2102
+ color: "display.text.secondary.default"
2103
+ },
2104
+ children: intl.formatMessage(messages.ofMax, {
2105
+ max: maxText
2106
+ })
2107
+ })]
2108
+ }), metric.footerText && /* @__PURE__ */jsx(Text, {
2109
+ sx: {
2110
+ fontSize: "xs",
2111
+ color: "display.text.secondary.default",
2112
+ lineHeight: "relaxed",
2113
+ maxWidth: "300px"
2114
+ },
2115
+ children: metric.footerText
2116
+ })]
2117
+ });
2118
+ };
2119
+ /**
2120
+ * MetricCard component displays a metric in a consistent card layout.
2121
+ *
2122
+ * It supports three metric types:
2123
+ * - **date**: displays a date and optional remaining-days message
2124
+ * - **percentage**: displays current/max values and a progress bar
2125
+ * - **number**: displays current/max values and an optional footer text
2126
+ *
2127
+ * @example
2128
+ * ```tsx
2129
+ * <MetricCard
2130
+ * metric={{
2131
+ * type: 'date',
2132
+ * label: 'Renewal date',
2133
+ * date: '31/12/2025',
2134
+ * icon: 'fluent:calendar-24-regular',
2135
+ * remainingDaysMessage: '10 days remaining',
2136
+ * }}
2137
+ * />
2138
+ * ```
2139
+ *
2140
+ * @example
2141
+ * ```tsx
2142
+ * <MetricCard
2143
+ * metric={{
2144
+ * type: 'percentage',
2145
+ * label: 'Plan usage',
2146
+ * current: 350,
2147
+ * max: 1000,
2148
+ * icon: 'fluent:gauge-24-regular',
2149
+ * showAlertThreshold: 80,
2150
+ * }}
2151
+ * />
2152
+ * ```
2153
+ */
2154
+ var MetricCard = ({
2155
+ metric,
2156
+ isLoading = false
2157
+ }) => {
2158
+ if (isLoading) return null;
2159
+ const isClickable = Boolean(metric.onClick || metric.helpArticleAction);
2160
+ return /* @__PURE__ */jsx(Card, {
2161
+ onClick: metric.onClick || metric.helpArticleAction,
2162
+ sx: {
2163
+ backgroundColor: "display.background.muted.default",
2164
+ padding: "6",
2165
+ cursor: isClickable ? "pointer" : "default",
2166
+ transition: "all 0.2s ease",
2167
+ minWidth: ["full", "full", "400px"],
2168
+ ":hover": {
2169
+ transform: "scale(1.01)"
2170
+ }
2171
+ },
2172
+ children: /* @__PURE__ */jsxs(Flex, {
2173
+ sx: {
2174
+ gap: "4",
2175
+ width: "full"
2176
+ },
2177
+ children: [/* @__PURE__ */jsx(MetricIconWrapper, {
2178
+ icon: metric.icon
2179
+ }), /* @__PURE__ */jsxs(Flex, {
2180
+ sx: {
2181
+ flex: 1,
2182
+ flexDirection: "column",
2183
+ gap: "2"
2184
+ },
2185
+ children: [/* @__PURE__ */jsx(MetricCardHeader, {
2186
+ label: metric.label,
2187
+ tooltip: metric.tooltip,
2188
+ isClickable
2189
+ }), metric.type === "date" && /* @__PURE__ */jsx(DateMetricContent, {
2190
+ metric
2191
+ }), metric.type === "percentage" && /* @__PURE__ */jsx(PercentageMetricContent, {
2192
+ metric
2193
+ }), metric.type === "number" && /* @__PURE__ */jsx(NumberMetricContent, {
2194
+ metric
2195
+ })]
2196
+ })]
2197
+ })
2198
+ });
2199
+ };
2200
+
2201
+ //#endregion
2202
+ //#region src/components/Modal/Modal.tsx
2203
+ ReactModal.defaultStyles = {
2204
+ overlay: {},
2205
+ content: {}
2206
+ };
2207
+ var Modal = props => {
2208
+ const {
2209
+ theme
2210
+ } = useTheme();
2211
+ const space = theme.space;
2212
+ const padding = useResponsiveValue([space?.["4"], space?.["5"], space?.["5"]]) || 0;
2213
+ const style = {
2214
+ overlay: css({
2215
+ position: "fixed",
2216
+ top: 0,
2217
+ left: 0,
2218
+ right: 0,
2219
+ bottom: 0,
2220
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
2221
+ display: "flex",
2222
+ justifyContent: "center",
2223
+ alignItems: "center",
2224
+ zIndex: "modal",
2225
+ ...props.style?.overlay
2226
+ })(theme),
2227
+ content: css({
2228
+ /**
2229
+ * Theme
2230
+ */
2231
+ backgroundColor: "surface",
2232
+ padding,
2233
+ border: "default",
2234
+ borderColor: "surface",
2235
+ borderRadius: "default",
2236
+ /**
2237
+ * General
2238
+ */
2239
+ WebkitOverflowScrolling: "touch",
2240
+ overflow: "auto",
2241
+ position: "relative",
2242
+ top: "0px",
2243
+ left: "0px",
2244
+ right: "0px",
2245
+ bottom: "0px",
2246
+ maxHeight: "90%",
2247
+ maxWidth: "90%",
2248
+ ...props.style?.content
2249
+ })(theme)
2250
+ };
2251
+ return /* @__PURE__ */jsx(ReactModal, {
2252
+ ...props,
2253
+ style
2254
+ });
2255
+ };
2256
+ Modal.setAppElement = ReactModal.setAppElement;
2257
+
2258
+ //#endregion
2259
+ //#region src/components/NavList/NavList.tsx
2260
+ var getVariantStyles = variant => {
2261
+ switch (variant) {
2262
+ case "sidebar":
2263
+ return {
2264
+ container: {
2265
+ flexDirection: "column",
2266
+ gap: "1",
2267
+ width: "full"
2268
+ },
2269
+ item: {
2270
+ backgroundColor: "transparent",
2271
+ padding: "3",
2272
+ borderRadius: "none",
2273
+ fontSize: "md",
2274
+ transition: "background-color 0.15s ease",
2275
+ "&:hover": {
2276
+ backgroundColor: "navigation.background.muted.hover",
2277
+ textDecoration: "none"
2278
+ }
2279
+ },
2280
+ activeItem: {
2281
+ backgroundColor: "navigation.background.muted.default",
2282
+ borderLeft: "4px solid",
2283
+ borderColor: "navigation.border.primary.default",
2284
+ paddingLeft: "calc(0.75rem - 4px)"
2285
+ },
2286
+ icon: {
2287
+ size: 20
2288
+ },
2289
+ groupLabel: {
2290
+ fontSize: "xs",
2291
+ fontWeight: "bold",
2292
+ color: "navigation.text.muted.default",
2293
+ textTransform: "uppercase",
2294
+ marginBottom: "2",
2295
+ marginTop: "4"
2296
+ }
2297
+ };
2298
+ case "menu":
2299
+ return {
2300
+ container: {
2301
+ flexDirection: "column",
2302
+ gap: "1",
2303
+ width: "full"
2304
+ },
2305
+ item: {
2306
+ backgroundColor: "transparent",
2307
+ borderRadius: "md",
2308
+ padding: "2",
2309
+ fontSize: "md",
2310
+ transition: "all 0.2s ease",
2311
+ "&:hover": {
2312
+ backgroundColor: "navigation.background.muted.hover",
2313
+ transform: "translateX(4px)",
2314
+ textDecoration: "none"
2315
+ }
2316
+ },
2317
+ activeItem: {
2318
+ backgroundColor: "navigation.background.muted.default",
2319
+ fontWeight: "bold"
2320
+ },
2321
+ icon: {
2322
+ size: 18
2323
+ },
2324
+ groupLabel: {
2325
+ fontSize: "sm",
2326
+ fontWeight: "semibold",
2327
+ color: "display.text.secondary.default",
2328
+ marginBottom: "2",
2329
+ marginTop: "3"
2330
+ }
2331
+ };
2332
+ case "dropdown":
2333
+ return {
2334
+ container: {
2335
+ flexDirection: "column",
2336
+ gap: "1",
2337
+ width: "full"
2338
+ },
2339
+ item: {
2340
+ backgroundColor: "transparent",
2341
+ padding: "2",
2342
+ fontSize: "sm",
2343
+ borderBottom: "sm",
2344
+ borderColor: "display.border.muted.default",
2345
+ transition: "background-color 0.1s ease",
2346
+ "&:hover": {
2347
+ backgroundColor: "navigation.background.muted.hover",
2348
+ textDecoration: "none"
2349
+ }
2350
+ },
2351
+ activeItem: {
2352
+ backgroundColor: "navigation.background.muted.default",
2353
+ fontWeight: "semibold"
2354
+ },
2355
+ icon: {
2356
+ size: 16
2357
+ },
2358
+ groupLabel: {
2359
+ fontSize: "xs",
2360
+ fontWeight: "medium",
2361
+ color: "display.text.secondary.default",
2362
+ marginBottom: "1",
2363
+ marginTop: "2",
2364
+ paddingX: "2"
2365
+ }
2366
+ };
2367
+ default:
2368
+ return getVariantStyles("menu");
2369
+ }
2370
+ };
2371
+ var NavListItemComponent = ({
2372
+ item,
2373
+ onItemClick,
2374
+ variantStyles,
2375
+ iconSize,
2376
+ LinkComponent = Link,
2377
+ showDivider = false
2378
+ }) => {
2379
+ const handleClick = event => {
2380
+ if (item.disabled) {
2381
+ event.preventDefault();
2382
+ return;
2383
+ }
2384
+ item.onClick?.(event);
2385
+ onItemClick?.(item);
2386
+ };
2387
+ const itemStyles = {
2388
+ ...variantStyles.item,
2389
+ ...(item.active ? variantStyles.activeItem : {}),
2390
+ ...(item.disabled ? {
2391
+ opacity: .5,
2392
+ cursor: "not-allowed",
2393
+ pointerEvents: "none"
2394
+ } : {})
2395
+ };
2396
+ const isDefaultLink = LinkComponent === Link;
2397
+ const linkContent = /* @__PURE__ */jsxs(Flex, {
2398
+ sx: {
2399
+ alignItems: "center",
2400
+ gap: "2",
2401
+ color: "navigation.text.primary.default"
2402
+ },
2403
+ children: [item.icon && /* @__PURE__ */jsx(Icon, {
2404
+ icon: item.icon,
2405
+ width: iconSize ?? variantStyles.icon.size,
2406
+ height: iconSize ?? variantStyles.icon.size
2407
+ }), /* @__PURE__ */jsx(Text, {
2408
+ children: item.label
2409
+ })]
2410
+ });
2411
+ return /* @__PURE__ */jsxs(Fragment, {
2412
+ children: [isDefaultLink ? /* @__PURE__ */jsx(LinkComponent, {
2413
+ href: item.href,
2414
+ onClick: handleClick,
2415
+ sx: itemStyles,
2416
+ "aria-disabled": item.disabled,
2417
+ "aria-current": item.active ? "page" : void 0,
2418
+ quiet: true,
2419
+ children: linkContent
2420
+ }) : /* @__PURE__ */jsx(Link, {
2421
+ as: LinkComponent,
2422
+ href: item.href,
2423
+ onClick: handleClick,
2424
+ sx: itemStyles,
2425
+ "aria-disabled": item.disabled,
2426
+ "aria-current": item.active ? "page" : void 0,
2427
+ quiet: true,
2428
+ children: linkContent
2429
+ }), showDivider && /* @__PURE__ */jsx(Divider, {
2430
+ sx: {
2431
+ marginY: "2"
2432
+ }
2433
+ })]
2434
+ });
2435
+ };
2436
+ var NavList = ({
2437
+ items = [],
2438
+ groups = [],
2439
+ variant = "menu",
2440
+ onItemClick,
2441
+ sx,
2442
+ iconSize,
2443
+ LinkComponent
2444
+ }) => {
2445
+ const variantStyles = getVariantStyles(variant);
2446
+ const processedGroups = React.useMemo(() => {
2447
+ if (groups.length > 0) return groups;
2448
+ if (items.length > 0) {
2449
+ const groupedItems = items.reduce((acc, item) => {
2450
+ const groupKey = item.group || "__ungrouped__";
2451
+ if (!acc[groupKey]) acc[groupKey] = [];
2452
+ acc[groupKey].push(item);
2453
+ return acc;
2454
+ }, {});
2455
+ return Object.entries(groupedItems).map(([key, groupItems]) => {
2456
+ return {
2457
+ id: key,
2458
+ label: key === "__ungrouped__" ? void 0 : key,
2459
+ items: groupItems,
2460
+ divider: false
2461
+ };
2462
+ });
2463
+ }
2464
+ return [];
2465
+ }, [items, groups]);
2466
+ return /* @__PURE__ */jsx(Flex, {
2467
+ as: "nav",
2468
+ sx: {
2469
+ ...variantStyles.container,
2470
+ ...sx
2471
+ },
2472
+ role: "navigation",
2473
+ children: processedGroups.map((group, groupIndex) => {
2474
+ return /* @__PURE__ */jsxs(React.Fragment, {
2475
+ children: [group.label && /* @__PURE__ */jsx(Text, {
2476
+ sx: variantStyles.groupLabel,
2477
+ as: "div",
2478
+ role: "heading",
2479
+ children: group.label
2480
+ }), /* @__PURE__ */jsx(Flex, {
2481
+ sx: {
2482
+ flexDirection: "column",
2483
+ gap: variantStyles.container.gap
2484
+ },
2485
+ children: group.items.map((item, itemIndex) => {
2486
+ const isLastItem = itemIndex === group.items.length - 1;
2487
+ return /* @__PURE__ */jsx(NavListItemComponent, {
2488
+ item,
2489
+ onItemClick,
2490
+ variantStyles,
2491
+ iconSize,
2492
+ LinkComponent,
2493
+ showDivider: item.divider || isLastItem && group.divider
2494
+ }, item.id || `${group.id}-item-${itemIndex}`);
2495
+ })
2496
+ })]
2497
+ }, group.id || `group-${groupIndex}`);
2498
+ })
2499
+ });
2500
+ };
2501
+ NavList.displayName = "NavList";
2502
+
2503
+ //#endregion
2504
+ //#region src/components/NotificationCard/NotificationCard.tsx
2505
+ var NotificationCard = props => {
2506
+ const sxMap = {
2507
+ success: {
2508
+ card: {
2509
+ backgroundColor: "feedback.background.positive.default",
2510
+ borderColor: "feedback.border.positive.default"
2511
+ }
2512
+ },
2513
+ error: {
2514
+ card: {
2515
+ backgroundColor: "feedback.background.negative.default",
2516
+ borderColor: "feedback.border.negative.default"
2517
+ }
2518
+ },
2519
+ warning: {
2520
+ card: {
2521
+ backgroundColor: "feedback.background.caution.default",
2522
+ borderColor: "feedback.border.caution.default"
2523
+ }
2524
+ },
2525
+ info: {
2526
+ card: {
2527
+ backgroundColor: "feedback.background.primary.default",
2528
+ borderColor: "feedback.border.primary.default"
2529
+ }
2530
+ },
2531
+ neutral: {
2532
+ card: {
2533
+ backgroundColor: "feedback.background.primary.default",
2534
+ borderColor: "feedback.border.primary.default"
2535
+ }
2536
+ }
2537
+ };
2538
+ const icon = {
2539
+ success: "success-circle",
2540
+ error: "error",
2541
+ warning: "warning-alt",
2542
+ info: "info",
2543
+ neutral: "info"
2544
+ };
2545
+ const hasCaption = Boolean(props.caption);
2546
+ const hasActions = Boolean(props.actions && props.actions.length > 0);
2547
+ const hasTitle = Boolean(props.title);
2548
+ const shouldCenterVerticallyWithoutTitle = !hasCaption && !hasActions && !hasTitle;
2549
+ const shouldCenterVerticallyWithTitle = !hasCaption && !hasActions && hasTitle;
2550
+ const shouldAddMinHeight = !hasCaption && !hasActions;
2551
+ return /* @__PURE__ */jsxs(Card, {
2552
+ sx: {
2553
+ ...sxMap[props.type].card,
2554
+ width: "full"
2555
+ },
2556
+ children: [props.title && /* @__PURE__ */jsxs(Card.Title, {
2557
+ sx: {
2558
+ display: "flex",
2559
+ justifyContent: "space-between",
2560
+ alignItems: "center",
2561
+ fontSize: ["md", "xl"],
2562
+ paddingY: ["1", "2", "4"],
2563
+ paddingX: ["2", "4", "8"]
2564
+ },
2565
+ children: [/* @__PURE__ */jsxs(Text, {
2566
+ sx: {
2567
+ display: "inline-flex",
2568
+ alignItems: "flex-start",
2569
+ gap: "2",
2570
+ flexDirection: "row",
2571
+ flexWrap: "wrap"
2572
+ },
2573
+ children: [/* @__PURE__ */jsxs(Box, {
2574
+ sx: {
2575
+ display: "flex",
2576
+ alignItems: "center",
2577
+ gap: "2"
2578
+ },
2579
+ children: [/* @__PURE__ */jsx(Icon, {
2580
+ icon: icon[props.type]
2581
+ }), props.title]
2582
+ }), props.tags && (Array.isArray(props.tags) ? props.tags.length > 0 : true) && (Array.isArray(props.tags) ? props.tags.map((tag, index) => {
2583
+ return /* @__PURE__ */jsx(Tag, {
2584
+ children: tag
2585
+ }, index);
2586
+ }) : /* @__PURE__ */jsx(Tag, {
2587
+ children: props.tags
2588
+ }))]
2589
+ }), props.onClose && /* @__PURE__ */jsx(Box, {
2590
+ sx: {
2591
+ marginLeft: "auto"
2592
+ },
2593
+ children: /* @__PURE__ */jsx(CloseButton, {
2594
+ onClick: props.onClose
2595
+ })
2596
+ })]
2597
+ }), /* @__PURE__ */jsxs(Card.Body, {
2598
+ sx: {
2599
+ ...sxMap[props.type].card,
2600
+ display: "flex",
2601
+ flexDirection: "column",
2602
+ gap: "2",
2603
+ paddingY: ["1", "2", "4"],
2604
+ paddingX: ["2", "4", "8"]
2605
+ },
2606
+ children: [/* @__PURE__ */jsx(Box, {
2607
+ sx: {
2608
+ display: "flex",
2609
+ justifyContent: "space-between",
2610
+ minHeight: shouldAddMinHeight ? "40px" : "auto",
2611
+ alignItems: shouldCenterVerticallyWithoutTitle ? "center" : shouldCenterVerticallyWithTitle ? "center" : "flex-start",
2612
+ width: "100%",
2613
+ gap: "4"
2614
+ },
2615
+ children: /* @__PURE__ */jsx(Box, {
2616
+ sx: {
2617
+ flex: 1
2618
+ },
2619
+ children: /* @__PURE__ */jsx(Text, {
2620
+ sx: {
2621
+ fontSize: ["sm", "md"]
2622
+ },
2623
+ children: props.message
2624
+ })
2625
+ })
2626
+ }), props.actions && props.actions.length > 0 && /* @__PURE__ */jsx(Box, {
2627
+ sx: {
2628
+ display: "flex",
2629
+ flexDirection: "column",
2630
+ gap: 2,
2631
+ mt: 2
2632
+ },
2633
+ children: props.actions.map((action, index) => {
2634
+ return action.action === "open_url" ? /* @__PURE__ */jsx(Link, {
2635
+ href: action.url,
2636
+ target: "_blank",
2637
+ rel: "noopener noreferrer",
2638
+ sx: {
2639
+ color: "action.text.accent.default",
2640
+ cursor: "pointer"
2641
+ },
2642
+ children: action.label || "Acessar"
2643
+ }, index) : null;
2644
+ })
2645
+ }), props.caption && /* @__PURE__ */jsx(Box, {
2646
+ sx: {
2647
+ whiteSpace: "nowrap",
2648
+ mt: 6
2649
+ },
2650
+ children: /* @__PURE__ */jsx(Text, {
2651
+ sx: {
2652
+ fontSize: "xs",
2653
+ color: "text.secondary"
2654
+ },
2655
+ children: props.caption
2656
+ })
2657
+ }), !props.title && props.onClose && /* @__PURE__ */jsx(Box, {
2658
+ sx: {
2659
+ alignSelf: "flex-end"
2660
+ },
2661
+ children: /* @__PURE__ */jsx(CloseButton, {
2662
+ onClick: props.onClose
2663
+ })
2664
+ })]
2665
+ })]
2666
+ });
2667
+ };
2668
+
2669
+ //#endregion
2670
+ //#region src/components/NotificationsMenu/NotificationsMenu.tsx
2671
+ var NotificationsMenu = ({
2672
+ notifications,
2673
+ defaultOpen = false,
2674
+ hasMore = false,
2675
+ onLoadMore,
2676
+ onOpenChange,
2677
+ count,
2678
+ onClose,
2679
+ onClearAll
2680
+ }) => {
2681
+ const [isOpen, setIsOpen] = React.useState(defaultOpen);
2682
+ const [openToLeft, setOpenToLeft] = React.useState(false);
2683
+ const buttonRef = React.useRef(null);
2684
+ const containerRef = React.useRef(null);
2685
+ const loadMoreRef = React.useRef(null);
2686
+ const [showCount, setShowCount] = React.useState(true);
2687
+ const togglePanel = () => {
2688
+ setIsOpen(prev => {
2689
+ const next = !prev;
2690
+ onOpenChange?.(next);
2691
+ return next;
2692
+ });
2693
+ };
2694
+ React.useEffect(() => {
2695
+ if (!isOpen || !buttonRef.current) return;
2696
+ const rect = buttonRef.current.getBoundingClientRect();
2697
+ const spaceRight = window.innerWidth - rect.right;
2698
+ const spaceLeft = rect.left;
2699
+ setShowCount(false);
2700
+ setOpenToLeft(spaceRight < 500 && spaceLeft > spaceRight);
2701
+ }, [isOpen]);
2702
+ React.useEffect(() => {
2703
+ if (!hasMore || !onLoadMore || !loadMoreRef.current) return;
2704
+ const observer = new IntersectionObserver(entries => {
2705
+ if (entries[0].isIntersecting) onLoadMore();
2706
+ }, {
2707
+ root: null,
2708
+ rootMargin: "0px",
2709
+ threshold: 1
2710
+ });
2711
+ observer.observe(loadMoreRef.current);
2712
+ return () => {
2713
+ if (loadMoreRef.current) observer.unobserve(loadMoreRef.current);
2714
+ };
2715
+ }, [hasMore, onLoadMore, notifications.length]);
2716
+ React.useEffect(() => {
2717
+ if (!isOpen) return;
2718
+ const handleClickOutside = event => {
2719
+ if (containerRef.current && !containerRef.current.contains(event.target) && buttonRef.current && !buttonRef.current.contains(event.target)) {
2720
+ setIsOpen(false);
2721
+ onOpenChange?.(false);
2722
+ onClose?.();
2723
+ }
2724
+ };
2725
+ document.addEventListener("mousedown", handleClickOutside);
2726
+ return () => {
2727
+ document.removeEventListener("mousedown", handleClickOutside);
2728
+ };
2729
+ }, [isOpen, onOpenChange, onClose]);
2730
+ return /* @__PURE__ */jsx(Flex, {
2731
+ sx: {
2732
+ position: "relative",
2733
+ justifyContent: "flex-start"
2734
+ },
2735
+ children: /* @__PURE__ */jsxs(Box, {
2736
+ sx: {
2737
+ position: "relative"
2738
+ },
2739
+ children: [/* @__PURE__ */jsxs(IconButton, {
2740
+ ref: buttonRef,
2741
+ variant: "ghost",
2742
+ sx: {
2743
+ position: "relative",
2744
+ borderRadius: "full",
2745
+ padding: 1,
2746
+ transition: "background-color 0.3s ease",
2747
+ "&:hover": {
2748
+ backgroundColor: "action.background.muted.default"
2749
+ }
2750
+ },
2751
+ onClick: togglePanel,
2752
+ children: [/* @__PURE__ */jsx(Box, {
2753
+ sx: {
2754
+ color: "display.text.muted.default"
2755
+ },
2756
+ children: /* @__PURE__ */jsx(Icon, {
2757
+ icon: "mdi:bell-outline",
2758
+ width: 22,
2759
+ height: 22
2760
+ })
2761
+ }), count > 0 && showCount && /* @__PURE__ */jsx(Box, {
2762
+ sx: {
2763
+ position: "absolute",
2764
+ top: "-2px",
2765
+ right: "-2px",
2766
+ minWidth: "14px",
2767
+ height: "14px",
2768
+ paddingX: 1,
2769
+ borderRadius: "full",
2770
+ backgroundColor: "action.background.negative.default",
2771
+ color: "feedback.text.primary.default",
2772
+ fontSize: "10px",
2773
+ fontWeight: "bold",
2774
+ display: "flex",
2775
+ alignItems: "center",
2776
+ justifyContent: "center",
2777
+ lineHeight: 1
2778
+ },
2779
+ children: count > 99 ? "99+" : count
2780
+ })]
2781
+ }), isOpen && /* @__PURE__ */jsx("div", {
2782
+ ref: containerRef,
2783
+ children: /* @__PURE__ */jsx(Card, {
2784
+ sx: {
2785
+ position: "absolute",
2786
+ top: "calc(100% + 8px)",
2787
+ left: openToLeft ? "auto" : 0,
2788
+ right: openToLeft ? 0 : "auto",
2789
+ width: notifications.length === 0 ? ["60vw", "300px"] : ["90vw", "600px"],
2790
+ maxHeight: "550px",
2791
+ overflowY: "auto",
2792
+ zIndex: "modal",
2793
+ padding: 0,
2794
+ boxShadow: "xl",
2795
+ borderRadius: "2xl",
2796
+ backgroundColor: "display.background.secondary.default"
2797
+ },
2798
+ children: /* @__PURE__ */jsx(Box, {
2799
+ sx: {
2800
+ width: "100%"
2801
+ },
2802
+ children: /* @__PURE__ */jsxs(Flex, {
2803
+ sx: {
2804
+ flexDirection: "column",
2805
+ gap: 4
2806
+ },
2807
+ children: [notifications.length > 0 && onClearAll && /* @__PURE__ */jsx(Flex, {
2808
+ sx: {
2809
+ justifyContent: "flex-end",
2810
+ p: 2,
2811
+ marginBottom: -2
2812
+ },
2813
+ children: /* @__PURE__ */jsxs(Button, {
2814
+ variant: "ghost",
2815
+ sx: {
2816
+ borderRadius: "md",
2817
+ padding: 1,
2818
+ paddingLeft: 10,
2819
+ paddingRight: 10,
2820
+ fontSize: "md",
2821
+ color: "display.text.muted.default",
2822
+ border: "1px solid",
2823
+ borderColor: "display.border.default",
2824
+ transition: "all 0.2s ease",
2825
+ display: "flex",
2826
+ alignItems: "center",
2827
+ "&:hover": {
2828
+ backgroundColor: "action.background.muted.default",
2829
+ color: "display.text.default",
2830
+ borderColor: "action.border.default"
2831
+ }
2832
+ },
2833
+ onClick: onClearAll,
2834
+ children: [/* @__PURE__ */jsx(Icon, {
2835
+ icon: "delete",
2836
+ width: 16,
2837
+ height: 16
2838
+ }), /* @__PURE__ */jsx(Text, {
2839
+ sx: {
2840
+ ml: -1,
2841
+ marginTop: -.4,
2842
+ fontSize: "sm"
2843
+ },
2844
+ children: "Limpar Tudo"
2845
+ })]
2846
+ })
2847
+ }), notifications.length === 0 ? /* @__PURE__ */jsx(Text, {
2848
+ sx: {
2849
+ color: "display.text.muted.default",
2850
+ textAlign: "center",
2851
+ p: 4
2852
+ },
2853
+ children: "Nenhuma notificação"
2854
+ }) : notifications.map(notification => {
2855
+ return /* @__PURE__ */jsx(NotificationCard, {
2856
+ ...notification,
2857
+ onClose: () => {
2858
+ notification.onClose?.();
2859
+ onClose?.();
2860
+ }
2861
+ }, notification.id);
2862
+ }), hasMore && /* @__PURE__ */jsx("div", {
2863
+ ref: loadMoreRef,
2864
+ style: {
2865
+ height: 1
2866
+ }
2867
+ })]
2868
+ })
2869
+ })
2870
+ })
2871
+ })]
2872
+ })
2873
+ });
2874
+ };
2875
+
2876
+ //#endregion
2877
+ //#region src/components/Search/Search.tsx
2878
+ var Search = ({
2879
+ value,
2880
+ defaultValue,
2881
+ loading,
2882
+ onChange,
2883
+ ...props
2884
+ }) => {
2885
+ const [text, setText] = React.useState(value ?? defaultValue);
2886
+ const debouncedValue = useDebounce(text, 500);
2887
+ React.useEffect(() => {
2888
+ onChange(debouncedValue);
2889
+ }, [debouncedValue, onChange]);
2890
+ return /* @__PURE__ */jsx(Input, {
2891
+ leadingIcon: loading ? "loading" : "search",
2892
+ defaultValue: text,
2893
+ onChange: e => {
2894
+ return setText(e.target.value);
2895
+ },
2896
+ ...props
2897
+ });
2898
+ };
2899
+
2900
+ //#endregion
2901
+ //#region src/components/Table/Table.tsx
2902
+ var Table = props => {
2903
+ return /* @__PURE__ */jsx(Box, {
2904
+ as: "table",
2905
+ ...props
2906
+ });
2907
+ };
2908
+ var TableHead = props => {
2909
+ return /* @__PURE__ */jsx(Box, {
2910
+ as: "thead",
2911
+ ...props
2912
+ });
2913
+ };
2914
+ var TableBody = props => {
2915
+ return /* @__PURE__ */jsx(Box, {
2916
+ as: "tbody",
2917
+ ...props
2918
+ });
2919
+ };
2920
+ var TableRow = props => {
2921
+ return /* @__PURE__ */jsx(Box, {
2922
+ as: "tr",
2923
+ ...props
2924
+ });
2925
+ };
2926
+ var TableCell = props => {
2927
+ return /* @__PURE__ */jsx(Box, {
2928
+ as: "td",
2929
+ ...props
2930
+ });
2931
+ };
2932
+ var TableHeader = props => {
2933
+ return /* @__PURE__ */jsx(Box, {
2934
+ as: "th",
2935
+ ...props
2936
+ });
2937
+ };
2938
+ var TableCaption = props => {
2939
+ return /* @__PURE__ */jsx(Box, {
2940
+ as: "caption",
2941
+ ...props
2942
+ });
2943
+ };
2944
+ var TableFooter = props => {
2945
+ return /* @__PURE__ */jsx(Box, {
2946
+ as: "tfoot",
2947
+ ...props
2948
+ });
2949
+ };
2950
+ Table.Head = TableHead;
2951
+ Table.Body = TableBody;
2952
+ Table.Row = TableRow;
2953
+ Table.Cell = TableCell;
2954
+ Table.Header = TableHeader;
2955
+ Table.Caption = TableCaption;
2956
+ Table.Footer = TableFooter;
2957
+
2958
+ //#endregion
2959
+ //#region src/components/Tabs/Tabs.tsx
2960
+ var Tabs = props => {
2961
+ const {
2962
+ sx: customSx,
2963
+ ...restProps
2964
+ } = props;
2965
+ return /* @__PURE__ */jsx(Box, {
2966
+ sx: ({
2967
+ colors
2968
+ }) => {
2969
+ const themeColors = colors;
2970
+ /**
2971
+ * https://github.com/reactjs/react-tabs/blob/main/style/react-tabs.css
2972
+ */
2973
+ return {
2974
+ /**
2975
+ * Tabs
2976
+ */
2977
+ ".react-tabs": {
2978
+ WebkitTapHighlightColor: "transparent"
2979
+ },
2980
+ ".react-tabs__tab-list": {
2981
+ borderBottom: "md",
2982
+ borderColor: themeColors?.input?.border?.muted?.default,
2983
+ paddingLeft: 0
2984
+ },
2985
+ ".react-tabs__tab--selected": {
2986
+ backgroundColor: "transparent",
2987
+ border: "none",
2988
+ borderBottom: "lg",
2989
+ borderColor: themeColors?.input?.border?.accent?.default
2990
+ },
2991
+ ".react-tabs__tab": {
2992
+ color: themeColors?.input?.text?.secondary?.default,
2993
+ display: "inline-flex",
2994
+ alignItems: "center",
2995
+ gap: "2",
2996
+ padding: "3",
2997
+ cursor: "pointer",
2998
+ position: "relative",
2999
+ listStyle: "none"
3000
+ },
3001
+ ".react-tabs__tab--disabled": {
3002
+ cursor: "not-allowed",
3003
+ color: themeColors?.input?.text?.muted?.default
3004
+ },
3005
+ ".react-tabs__tab:focus": {
3006
+ outline: "none"
3007
+ },
3008
+ ".react-tabs__tab:focus:after": {
3009
+ position: "absolute",
3010
+ height: "min",
3011
+ left: "-2",
3012
+ right: "-2",
3013
+ bottom: "-3"
3014
+ },
3015
+ ".react-tabs__tab-panel": {
3016
+ display: "none"
3017
+ },
3018
+ ".react-tabs__tab-panel--selected": {
3019
+ display: "block"
3020
+ },
3021
+ ...customSx
3022
+ };
3023
+ },
3024
+ ...restProps,
3025
+ children: /* @__PURE__ */jsx(Tabs$1, {
3026
+ ...restProps,
3027
+ children: props.children
3028
+ })
3029
+ });
3030
+ };
3031
+ Tabs.TabList = TabList;
3032
+ /**
3033
+ * Tab default props
3034
+ * https://github.com/reactjs/react-tabs/blob/main/src/components/Tab.js
3035
+ */
3036
+ Tabs.Tab = Tab;
3037
+ Tabs.TabPanel = TabPanel;
3038
+
3039
+ //#endregion
3040
+ //#region src/components/Toast/Toast.tsx
3041
+ var ToastContainer = props => {
3042
+ const {
3043
+ theme
3044
+ } = useTheme();
3045
+ const className = React.useMemo(() => {
3046
+ return css$1(css({
3047
+ ".Toastify__toast-container": {}
3048
+ })(theme));
3049
+ }, [theme]);
3050
+ return /* @__PURE__ */jsx(Box, {
3051
+ className,
3052
+ sx: ({
3053
+ colors,
3054
+ fonts
3055
+ }) => {
3056
+ const themeColors = colors;
3057
+ /**
3058
+ * https://fkhadra.github.io/react-toastify/how-to-style#override-css-variables
3059
+ */
3060
+ return {
3061
+ "--toastify-font-family": fonts?.body,
3062
+ "--toastify-color-light": themeColors?.feedback?.background?.primary?.default
3063
+ };
3064
+ },
3065
+ children: /* @__PURE__ */jsx(ToastContainer$1, {
3066
+ className,
3067
+ ...props
3068
+ })
3069
+ });
3070
+ };
3071
+ var toast = toast$1;
3072
+
3073
+ //#endregion
3074
+ export { Accordion, DatePicker, Drawer, EnhancedTitle, FileUploader, InstallPwa, InstallPwaUi, JsonEditor, JsonView, List, ListItem, LockedOverlay, Markdown, Menu, MetricCard, Modal, NavList, NotificationCard, NotificationsMenu, Search, SpotlightCard, Table, Tabs, ToastContainer, createCell, createColumnHelper, flexRender, getCoreRowModel, toast, useReactTable };