@etus/ui 0.4.0-beta.5 → 0.4.0-beta.7

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 (86) hide show
  1. package/dist/{chunk-2HM5Z2YP.js → chunk-2YWWZEPE.js} +3 -3
  2. package/dist/{chunk-2HM5Z2YP.js.map → chunk-2YWWZEPE.js.map} +1 -1
  3. package/dist/{chunk-F6ZKBK5B.js → chunk-5GE3BQA7.js} +9 -4
  4. package/dist/chunk-5GE3BQA7.js.map +1 -0
  5. package/dist/{chunk-QZWKXUZP.js → chunk-6ELVWWIA.js} +3 -3
  6. package/dist/{chunk-QZWKXUZP.js.map → chunk-6ELVWWIA.js.map} +1 -1
  7. package/dist/{chunk-3RJEA2MM.js → chunk-6HEURMY3.js} +102 -65
  8. package/dist/chunk-6HEURMY3.js.map +1 -0
  9. package/dist/{chunk-ZS2WS5NJ.js → chunk-AVR3LVOQ.js} +48 -3
  10. package/dist/chunk-AVR3LVOQ.js.map +1 -0
  11. package/dist/{chunk-HT5XM6XK.js → chunk-FCT6FEEZ.js} +4 -4
  12. package/dist/{chunk-HT5XM6XK.js.map → chunk-FCT6FEEZ.js.map} +1 -1
  13. package/dist/{chunk-XXFKDEFH.js → chunk-JUTPDS4E.js} +7 -11
  14. package/dist/chunk-JUTPDS4E.js.map +1 -0
  15. package/dist/{chunk-DDR24GOP.js → chunk-L3Z5FAJE.js} +67 -51
  16. package/dist/chunk-L3Z5FAJE.js.map +1 -0
  17. package/dist/{chunk-RVUO7SDG.js → chunk-LS3WD6IZ.js} +63 -28
  18. package/dist/chunk-LS3WD6IZ.js.map +1 -0
  19. package/dist/{chunk-32IJQOUV.js → chunk-OTSK2KAI.js} +3 -3
  20. package/dist/{chunk-32IJQOUV.js.map → chunk-OTSK2KAI.js.map} +1 -1
  21. package/dist/{chunk-5YDFC74M.js → chunk-XD5LE64P.js} +7 -6
  22. package/dist/chunk-XD5LE64P.js.map +1 -0
  23. package/dist/{chunk-CSXT7SKR.js → chunk-YCEZH35U.js} +18 -4
  24. package/dist/chunk-YCEZH35U.js.map +1 -0
  25. package/dist/{chunk-2D6OFVPN.js → chunk-YWA63YN3.js} +22 -2
  26. package/dist/chunk-YWA63YN3.js.map +1 -0
  27. package/dist/{chunk-CP2PEDG2.js → chunk-Z4KW5VW6.js} +3 -3
  28. package/dist/chunk-Z4KW5VW6.js.map +1 -0
  29. package/dist/components/advanced/Calendar/index.js +1 -1
  30. package/dist/components/advanced/EventCalendar/index.js +1 -1
  31. package/dist/components/advanced/FilterBuilder/index.js +1 -1
  32. package/dist/components/advanced/ReportBuilder/index.js +2 -2
  33. package/dist/components/advanced/index.js +13 -13
  34. package/dist/components/data-display/Carousel/index.js +1 -1
  35. package/dist/components/data-display/ChartCard/index.js +1 -3
  36. package/dist/components/data-display/DashboardFilterbar/index.js +3 -3
  37. package/dist/components/data-display/DataTable/FilterBuilder/index.js +1 -1
  38. package/dist/components/data-display/DataTable/index.js +1 -1
  39. package/dist/components/data-display/ImageGallery/index.js +8 -1
  40. package/dist/components/data-display/KPICard/index.js +2 -2
  41. package/dist/components/data-display/index.js +25 -25
  42. package/dist/components/feedback/AlertDialog/index.js +1 -1
  43. package/dist/components/feedback/ConfirmModal/index.js +1 -1
  44. package/dist/components/feedback/Modal/index.js +1 -1
  45. package/dist/components/feedback/index.js +5 -5
  46. package/dist/components/forms/ColorPicker/index.js +1 -1
  47. package/dist/components/forms/DatePicker/index.js +2 -2
  48. package/dist/components/forms/DateRangePicker/index.js +2 -2
  49. package/dist/components/forms/InputGroup/index.js +1 -1
  50. package/dist/components/forms/InputOTPField/index.js +2 -2
  51. package/dist/components/forms/Slider/index.js +1 -1
  52. package/dist/components/forms/index.js +24 -24
  53. package/dist/components/index.js +121 -121
  54. package/dist/components/layout/Panel/index.js +2 -1
  55. package/dist/components/layout/index.js +4 -4
  56. package/dist/components/navigation/Menu/index.js +2 -1
  57. package/dist/components/navigation/MobileSidebar/index.js +1 -1
  58. package/dist/components/navigation/Pagination/index.js +1 -1
  59. package/dist/components/navigation/Sidebar/index.js +3 -3
  60. package/dist/components/navigation/Toolbar/index.js +1 -1
  61. package/dist/components/navigation/index.js +12 -11
  62. package/dist/components/primitives/Button/index.js +1 -1
  63. package/dist/components/primitives/ConfirmButton/index.js +1 -1
  64. package/dist/components/primitives/index.js +10 -10
  65. package/dist/components/workflow/ApprovalFlow/index.js +1 -1
  66. package/dist/components/workflow/CommentSystem/index.js +1 -1
  67. package/dist/components/workflow/Dashboard/index.js +1 -1
  68. package/dist/components/workflow/DashboardBuilder/index.js +1 -1
  69. package/dist/components/workflow/KanbanBoard/index.js +1 -1
  70. package/dist/components/workflow/ReportGenerator/index.js +1 -1
  71. package/dist/components/workflow/Wizard/index.js +1 -1
  72. package/dist/components/workflow/index.js +9 -9
  73. package/dist/index.d.ts +163 -58
  74. package/dist/index.js +123 -123
  75. package/dist/styles.css +19 -9
  76. package/package.json +2 -2
  77. package/dist/chunk-2D6OFVPN.js.map +0 -1
  78. package/dist/chunk-3RJEA2MM.js.map +0 -1
  79. package/dist/chunk-5YDFC74M.js.map +0 -1
  80. package/dist/chunk-CP2PEDG2.js.map +0 -1
  81. package/dist/chunk-CSXT7SKR.js.map +0 -1
  82. package/dist/chunk-DDR24GOP.js.map +0 -1
  83. package/dist/chunk-F6ZKBK5B.js.map +0 -1
  84. package/dist/chunk-RVUO7SDG.js.map +0 -1
  85. package/dist/chunk-XXFKDEFH.js.map +0 -1
  86. package/dist/chunk-ZS2WS5NJ.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/layout/Panel/Panel.variants.ts","../src/components/layout/Panel/Panel.tsx"],"names":[],"mappings":"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","file":"chunk-JUTPDS4E.js","sourcesContent":["import { cva, type VariantProps } from \"class-variance-authority\"\n\n/**\n * Panel variant styles\n * Layout container for sidebars, inspectors, and section panels\n */\nexport const panelVariants = cva(\n [\"flex flex-col rounded-[var(--panel-root-radius)]\"],\n {\n variants: {\n /**\n * Visual variant of the panel\n * - default: Background with subtle border\n * - subtle: Muted background, no border\n * - outlined: Border only, no background\n * - elevated: With light shadow\n * - inset: Inner shadow effect\n */\n variant: {\n default: \"bg-[color:var(--panel-variant-default-bg)] border border-[color:var(--panel-root-border-color)]\",\n subtle: \"bg-[color:var(--panel-variant-subtle-bg)]\",\n outlined: \"border border-[color:var(--panel-root-border-color)] bg-transparent\",\n elevated: \"bg-[color:var(--panel-variant-elevated-bg)] shadow-[var(--panel-root-shadow)]\",\n inset: \"bg-[color:var(--panel-variant-subtle-bg)] shadow-inner\",\n },\n /**\n * Width of the panel\n * - xs: 240px (compact sidebar)\n * - sm: 280px (standard sidebar)\n * - md: 320px (medium panel)\n * - lg: 400px (wide panel)\n * - xl: 480px (extra wide panel)\n * - auto: Content width\n * - full: 100% width\n */\n size: {\n xs: \"w-[var(--panel-size-xs)]\",\n sm: \"w-[var(--panel-size-sm)]\",\n md: \"w-[var(--panel-size-md)]\",\n lg: \"w-[var(--panel-size-lg)]\",\n xl: \"w-[var(--panel-size-xl)]\",\n auto: \"w-auto\",\n full: \"w-full\",\n },\n /**\n * Position variant for styling based on panel placement\n * - left: Left-positioned panel (sidebar)\n * - right: Right-positioned panel (inspector)\n * - top: Top-positioned panel\n * - bottom: Bottom-positioned panel\n * - center: Centered panel\n */\n position: {\n left: \"border-r\",\n right: \"border-l\",\n top: \"border-b\",\n bottom: \"border-t\",\n center: \"\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"auto\",\n },\n})\n\n/**\n * PanelHeader variant styles\n * Header section with padding and shrink behavior\n */\nexport const panelHeaderVariants = cva([\n \"px-[var(--panel-header-padding-x)] py-[var(--panel-header-padding-y)] shrink-0\",\n])\n\n/**\n * PanelContent variant styles\n * Main content area with flex-grow. When `scrollable`, the content is routed\n * through the ScrollArea component; `min-h-0` lets the flex child shrink so the\n * ScrollArea can establish its own scroll viewport.\n */\nexport const panelContentVariants = cva([\"flex-1\"], {\n variants: {\n scrollable: {\n true: \"min-h-0\",\n false: \"\",\n },\n },\n defaultVariants: {\n scrollable: false,\n },\n})\n\n/**\n * PanelFooter variant styles\n * Footer section with padding and shrink behavior\n */\nexport const panelFooterVariants = cva([\n \"px-[var(--panel-footer-padding-x)] py-[var(--panel-footer-padding-y)] shrink-0\",\n])\n\nexport type PanelVariantProps = VariantProps<typeof panelVariants>\nexport type PanelContentVariantProps = VariantProps<typeof panelContentVariants>\n","import type {\n PanelContentProps,\n PanelFooterProps,\n PanelHeaderProps,\n PanelProps,\n} from \"./Panel.types\"\n\nimport { cn } from \"../../../lib/utils\"\nimport { ScrollArea } from \"../ScrollArea\"\nimport {\n panelContentVariants,\n panelFooterVariants,\n panelHeaderVariants,\n panelVariants,\n} from \"./Panel.variants\"\n\nfunction Panel({\n as: Component = \"div\",\n variant,\n size,\n position,\n className,\n ...props\n}: PanelProps) {\n return (\n <Component\n className={cn(panelVariants({ variant, size, position }), className)}\n data-slot=\"panel\"\n {...props}\n />\n )\n}\n\nfunction PanelHeader({ className, ...props }: PanelHeaderProps) {\n return (\n <div\n className={cn(panelHeaderVariants(), className)}\n data-slot=\"panel-header\"\n {...props}\n />\n )\n}\n\nfunction PanelContent({\n scrollable = false,\n className,\n children,\n ...props\n}: PanelContentProps) {\n return (\n <div\n className={cn(panelContentVariants({ scrollable }), className)}\n data-slot=\"panel-content\"\n {...props}\n >\n {scrollable ? <ScrollArea className=\"size-full\">{children}</ScrollArea> : children}\n </div>\n )\n}\n\nfunction PanelFooter({ className, ...props }: PanelFooterProps) {\n return (\n <div\n className={cn(panelFooterVariants(), className)}\n data-slot=\"panel-footer\"\n {...props}\n />\n )\n}\n\nexport { Panel, PanelContent, PanelFooter, PanelHeader }\n"]}
@@ -1,4 +1,3 @@
1
- import { LineChart } from './chunk-XV6NXXXP.js';
2
1
  import { SkeletonLoader } from './chunk-QHKOBGLW.js';
3
2
  import { Badge } from './chunk-TNROOKX3.js';
4
3
  import { cn } from './chunk-HRNDJU7D.js';
@@ -7,13 +6,13 @@ import { cva } from 'class-variance-authority';
7
6
  import { jsxs, jsx } from 'react/jsx-runtime';
8
7
 
9
8
  var chartCardVariants = cva(
10
- "transition",
9
+ "rounded-[var(--chart-card-radius)] bg-[color:var(--chart-card-bg)] px-[var(--chart-card-padding-x)] pt-[var(--chart-card-padding-top)] pb-[var(--chart-card-padding-bottom)] text-[color:var(--chart-card-fg)] transition",
11
10
  {
12
11
  variants: {
13
12
  variant: {
14
13
  default: "",
15
- outlined: "border border-border rounded-lg p-4",
16
- elevated: "bg-card rounded-lg p-4 shadow-sm"
14
+ outlined: "border border-[color:var(--chart-card-border)]",
15
+ elevated: "shadow-sm"
17
16
  }
18
17
  },
19
18
  defaultVariants: {
@@ -25,19 +24,19 @@ var chartCardHeaderVariants = cva(
25
24
  "flex items-center justify-between gap-x-2"
26
25
  );
27
26
  var chartCardTitleVariants = cva(
28
- "font-bold text-foreground sm:text-sm"
27
+ "text-[length:var(--chart-card-title-size)] font-[var(--chart-card-title-weight)] leading-[var(--chart-card-title-line-height)] text-[color:var(--chart-card-title-color)]"
29
28
  );
30
29
  var chartCardValueContainerVariants = cva(
31
30
  "mt-2 flex items-baseline justify-between"
32
31
  );
33
32
  var chartCardValueVariants = cva(
34
- "text-xl text-foreground"
33
+ "text-[length:var(--chart-card-value-size)] text-[color:var(--chart-card-value-color)]"
35
34
  );
36
35
  var chartCardPreviousValueVariants = cva(
37
- "text-sm text-muted-foreground"
36
+ "text-sm text-[color:var(--chart-card-previous-color)]"
38
37
  );
39
38
  var chartCardChartVariants = cva(
40
- "mt-6"
39
+ "mt-[var(--chart-card-gap)] h-[var(--chart-card-chart-height)] [&>*]:h-full"
41
40
  );
42
41
  var defaultFormatter = (value) => String(value);
43
42
  function getBadgeColor(value) {
@@ -56,20 +55,22 @@ function formatPercentage(value) {
56
55
  return `${sign}${(value * 100).toFixed(1)}%`;
57
56
  }
58
57
  function ChartCard({
59
- title,
60
- data,
61
- config,
62
- valueFormatter = defaultFormatter,
58
+ badge,
59
+ chart,
60
+ chartHeight,
61
+ className,
63
62
  comparisonPeriod = "no-comparison",
63
+ data,
64
+ emptyMessage,
65
+ featuredIcon,
66
+ footer,
67
+ headerAction,
64
68
  isThumbnail = false,
65
69
  loading = false,
66
- badge,
67
- chartHeight = "h-32",
68
- showTooltip = true,
69
- xAxisKey = "formattedDate",
70
- emptyMessage,
70
+ tabs,
71
+ title,
72
+ valueFormatter = defaultFormatter,
71
73
  variant,
72
- className,
73
74
  ...props
74
75
  }) {
75
76
  const isEmpty = !loading && data.length === 0;
@@ -85,10 +86,11 @@ function ChartCard({
85
86
  }
86
87
  return (totalValue - totalPreviousValue) / totalPreviousValue;
87
88
  }, [comparisonPeriod, totalPreviousValue, totalValue]);
88
- const series = React.useMemo(() => {
89
- return comparisonPeriod === "no-comparison" ? ["value"] : ["value", "previousValue"];
90
- }, [comparisonPeriod]);
91
89
  const showComparison = comparisonPeriod !== "no-comparison";
90
+ const titleLead = /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
91
+ featuredIcon && /* @__PURE__ */ jsx("span", { "data-slot": "chart-card-featured-icon", children: featuredIcon }),
92
+ /* @__PURE__ */ jsx("h3", { className: cn(chartCardTitleVariants()), "data-slot": "chart-card-title", children: title })
93
+ ] });
92
94
  if (isEmpty) {
93
95
  return /* @__PURE__ */ jsxs(
94
96
  "article",
@@ -99,14 +101,17 @@ function ChartCard({
99
101
  "data-slot": "chart-card",
100
102
  ...props,
101
103
  children: [
102
- /* @__PURE__ */ jsx("div", { className: cn(chartCardHeaderVariants()), children: /* @__PURE__ */ jsx("h3", { className: cn(chartCardTitleVariants()), children: title }) }),
104
+ /* @__PURE__ */ jsxs("div", { className: cn(chartCardHeaderVariants()), "data-slot": "chart-card-header", children: [
105
+ titleLead,
106
+ headerAction && /* @__PURE__ */ jsx("span", { "data-slot": "chart-card-header-action", children: headerAction })
107
+ ] }),
103
108
  /* @__PURE__ */ jsx(
104
109
  "div",
105
110
  {
106
111
  className: cn(
107
112
  chartCardChartVariants(),
108
113
  chartHeight,
109
- "flex items-center justify-center text-sm text-muted-foreground"
114
+ "flex items-center justify-center text-[length:var(--chart-card-empty-state-caption-size)] text-[color:var(--chart-card-empty-state-caption-color)]"
110
115
  ),
111
116
  "data-slot": "chart-card-empty",
112
117
  children: emptyMessage ?? "No data available"
@@ -125,11 +130,18 @@ function ChartCard({
125
130
  "data-slot": "chart-card",
126
131
  ...props,
127
132
  children: [
128
- /* @__PURE__ */ jsxs("div", { className: cn(chartCardHeaderVariants()), children: [
133
+ /* @__PURE__ */ jsxs("div", { className: cn(chartCardHeaderVariants()), "data-slot": "chart-card-header", children: [
129
134
  /* @__PURE__ */ jsx(SkeletonLoader, { className: "h-4 w-24" }),
130
135
  /* @__PURE__ */ jsx(SkeletonLoader, { className: "h-5 w-12" })
131
136
  ] }),
132
- /* @__PURE__ */ jsx("div", { className: cn(chartCardValueContainerVariants()), children: /* @__PURE__ */ jsx(SkeletonLoader, { className: "h-7 w-32" }) }),
137
+ /* @__PURE__ */ jsx(
138
+ "div",
139
+ {
140
+ className: cn(chartCardValueContainerVariants()),
141
+ "data-slot": "chart-card-value",
142
+ children: /* @__PURE__ */ jsx(SkeletonLoader, { className: "h-7 w-32" })
143
+ }
144
+ ),
133
145
  /* @__PURE__ */ jsx("div", { className: cn(chartCardChartVariants(), chartHeight), children: /* @__PURE__ */ jsx(SkeletonLoader, { className: "h-full w-full" }) })
134
146
  ]
135
147
  }
@@ -143,34 +155,38 @@ function ChartCard({
143
155
  "data-slot": "chart-card",
144
156
  ...props,
145
157
  children: [
146
- /* @__PURE__ */ jsx("div", { className: cn(chartCardHeaderVariants()), children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
147
- /* @__PURE__ */ jsx("h3", { className: cn(chartCardTitleVariants()), children: title }),
148
- showComparison && (badge ?? /* @__PURE__ */ jsx(Badge, { color: getBadgeColor(evolution), size: "sm", children: formatPercentage(evolution) }))
149
- ] }) }),
150
- /* @__PURE__ */ jsxs("div", { className: cn(chartCardValueContainerVariants()), children: [
151
- /* @__PURE__ */ jsx("p", { className: cn(chartCardValueVariants()), children: valueFormatter(totalValue) }),
152
- showComparison && /* @__PURE__ */ jsxs("p", { className: cn(chartCardPreviousValueVariants()), children: [
153
- "from ",
154
- valueFormatter(totalPreviousValue)
155
- ] })
158
+ /* @__PURE__ */ jsxs("div", { className: cn(chartCardHeaderVariants()), "data-slot": "chart-card-header", children: [
159
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
160
+ featuredIcon && /* @__PURE__ */ jsx("span", { "data-slot": "chart-card-featured-icon", children: featuredIcon }),
161
+ /* @__PURE__ */ jsx("h3", { className: cn(chartCardTitleVariants()), "data-slot": "chart-card-title", children: title }),
162
+ showComparison && (badge ?? /* @__PURE__ */ jsx(Badge, { color: getBadgeColor(evolution), size: "sm", children: formatPercentage(evolution) }))
163
+ ] }),
164
+ headerAction && /* @__PURE__ */ jsx("span", { "data-slot": "chart-card-header-action", children: headerAction })
156
165
  ] }),
157
- !isThumbnail && data.length > 0 && /* @__PURE__ */ jsx(
158
- LineChart,
166
+ /* @__PURE__ */ jsxs(
167
+ "div",
168
+ {
169
+ className: cn(chartCardValueContainerVariants()),
170
+ "data-slot": "chart-card-value",
171
+ children: [
172
+ /* @__PURE__ */ jsx("p", { className: cn(chartCardValueVariants()), children: valueFormatter(totalValue) }),
173
+ showComparison && /* @__PURE__ */ jsxs("p", { className: cn(chartCardPreviousValueVariants()), children: [
174
+ "from ",
175
+ valueFormatter(totalPreviousValue)
176
+ ] })
177
+ ]
178
+ }
179
+ ),
180
+ tabs && /* @__PURE__ */ jsx("div", { className: "mt-[var(--chart-card-gap)]", "data-slot": "chart-card-tabs", children: tabs }),
181
+ !isThumbnail && chart && /* @__PURE__ */ jsx(
182
+ "div",
159
183
  {
160
- autoMinValue: true,
161
- startEndOnly: true,
162
184
  className: cn(chartCardChartVariants(), chartHeight),
163
- config,
164
- data,
165
- series,
166
- showLegend: false,
167
- showTooltip,
168
- showYAxis: false,
169
- xAxisKey,
170
- xAxisTickFormatter: (value) => String(value),
171
- yAxisTickFormatter: (value) => valueFormatter(Number(value))
185
+ "data-slot": "chart-card-chart",
186
+ children: chart
172
187
  }
173
- )
188
+ ),
189
+ footer && /* @__PURE__ */ jsx("div", { className: "mt-[var(--chart-card-gap)]", "data-slot": "chart-card-footer", children: footer })
174
190
  ]
175
191
  }
176
192
  );
@@ -178,5 +194,5 @@ function ChartCard({
178
194
  ChartCard.displayName = "ChartCard";
179
195
 
180
196
  export { ChartCard, chartCardChartVariants, chartCardHeaderVariants, chartCardPreviousValueVariants, chartCardTitleVariants, chartCardValueContainerVariants, chartCardValueVariants, chartCardVariants };
181
- //# sourceMappingURL=chunk-DDR24GOP.js.map
182
- //# sourceMappingURL=chunk-DDR24GOP.js.map
197
+ //# sourceMappingURL=chunk-L3Z5FAJE.js.map
198
+ //# sourceMappingURL=chunk-L3Z5FAJE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/data-display/ChartCard/ChartCard.variants.ts","../src/components/data-display/ChartCard/ChartCard.tsx"],"names":[],"mappings":"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","file":"chunk-L3Z5FAJE.js","sourcesContent":["// ChartCard/ChartCard.variants.ts\nimport { cva } from \"class-variance-authority\"\n\n/**\n * ChartCard container variants.\n *\n * Consumes the `--chart-card-*` component tokens (DES-1253). The Figma container\n * is flat — background + radius + asymmetric padding, no border or shadow — so the\n * base styles render that container and `outlined` / `elevated` are code-only\n * extensions (documented in the README) layered on top.\n */\nexport const chartCardVariants = cva(\n \"rounded-[var(--chart-card-radius)] bg-[color:var(--chart-card-bg)] px-[var(--chart-card-padding-x)] pt-[var(--chart-card-padding-top)] pb-[var(--chart-card-padding-bottom)] text-[color:var(--chart-card-fg)] transition\",\n {\n variants: {\n variant: {\n default: \"\",\n outlined: \"border border-[color:var(--chart-card-border)]\",\n elevated: \"shadow-sm\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\n/**\n * ChartCard header (Title Row) — leading group (featured icon + title + badge)\n * and an optional trailing overflow action.\n */\nexport const chartCardHeaderVariants = cva(\n \"flex items-center justify-between gap-x-2\"\n)\n\n/**\n * ChartCard title — Figma Heading/H5 (18px / 24px / SemiBold), tokenised.\n */\nexport const chartCardTitleVariants = cva(\n \"text-[length:var(--chart-card-title-size)] font-[var(--chart-card-title-weight)] leading-[var(--chart-card-title-line-height)] text-[color:var(--chart-card-title-color)]\"\n)\n\n/**\n * ChartCard value container.\n */\nexport const chartCardValueContainerVariants = cva(\n \"mt-2 flex items-baseline justify-between\"\n)\n\n/**\n * ChartCard KPI value text — tokenised size + color.\n */\nexport const chartCardValueVariants = cva(\n \"text-[length:var(--chart-card-value-size)] text-[color:var(--chart-card-value-color)]\"\n)\n\n/**\n * ChartCard previous-value caption.\n */\nexport const chartCardPreviousValueVariants = cva(\n \"text-sm text-[color:var(--chart-card-previous-color)]\"\n)\n\n/**\n * ChartCard chart-slot wrapper — 24px row gap + tokenised area height\n * (`--chart-card-chart-height`). The injected chart fills the area via\n * `[&>*]:h-full`; the `chartHeight` prop overrides the height.\n */\nexport const chartCardChartVariants = cva(\n \"mt-[var(--chart-card-gap)] h-[var(--chart-card-chart-height)] [&>*]:h-full\"\n)\n","// ChartCard/ChartCard.tsx\n\"use client\"\n\nimport type { ChartCardProps, ChartCardValueFormatter } from \"./ChartCard.types\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"../../../lib/utils\"\nimport { Badge } from \"../../primitives/Badge\"\nimport { SkeletonLoader } from \"../../primitives/SkeletonLoader\"\nimport {\n chartCardChartVariants,\n chartCardHeaderVariants,\n chartCardPreviousValueVariants,\n chartCardTitleVariants,\n chartCardValueContainerVariants,\n chartCardValueVariants,\n chartCardVariants,\n} from \"./ChartCard.variants\"\n\n/**\n * Default value formatter (returns value as string)\n */\nconst defaultFormatter: ChartCardValueFormatter = (value) => String(value)\n\n/**\n * Get badge color based on evolution percentage\n */\nfunction getBadgeColor(value: number): \"destructive\" | \"muted\" | \"success\" | \"warning\" {\n if (value > 0) {\n return \"success\"\n } else if (value < 0) {\n if (value < -50) {\n return \"warning\"\n }\n return \"destructive\"\n }\n return \"muted\"\n}\n\n/**\n * Format percentage for display\n */\nfunction formatPercentage(value: number): string {\n const sign = value > 0 ? \"+\" : \"\"\n return `${sign}${(value * 100).toFixed(1)}%`\n}\n\n/**\n * ChartCard - Dashboard KPI widget with a chart-agnostic slot.\n *\n * Renders a KPI value with an auto evolution badge and optional comparison\n * period. The chart itself is **injected by the consumer** via the `chart`\n * slot — ChartCard ships no default chart (DES-1253). The Title Row exposes\n * `featuredIcon` + `headerAction` (overflow) slots, with optional `tabs` and\n * `footer` composition slots below.\n *\n * @example\n * ```tsx\n * const data = [\n * { formattedDate: \"01/01\", value: 1000, previousValue: 900 },\n * { formattedDate: \"02/01\", value: 1200, previousValue: 1100 },\n * ]\n *\n * <ChartCard\n * title=\"Revenue\"\n * data={data}\n * comparisonPeriod=\"previous-year\"\n * valueFormatter={(v) => `$${v.toLocaleString()}`}\n * chart={\n * <LineChart\n * className=\"h-full\"\n * data={data}\n * config={{ value: { label: \"Current\" } }}\n * series={[\"value\"]}\n * />\n * }\n * />\n * ```\n */\nfunction ChartCard({\n badge,\n chart,\n chartHeight,\n className,\n comparisonPeriod = \"no-comparison\",\n data,\n emptyMessage,\n featuredIcon,\n footer,\n headerAction,\n isThumbnail = false,\n loading = false,\n tabs,\n title,\n valueFormatter = defaultFormatter,\n variant,\n ...props\n}: ChartCardProps) {\n const isEmpty = !loading && data.length === 0\n\n // Calculate totals\n const totalValue = React.useMemo(() => {\n return data.reduce((acc, item) => acc + (item.value ?? 0), 0)\n }, [data])\n\n const totalPreviousValue = React.useMemo(() => {\n return data.reduce((acc, item) => acc + (item.previousValue ?? 0), 0)\n }, [data])\n\n // Calculate evolution percentage\n const evolution = React.useMemo(() => {\n if (comparisonPeriod === \"no-comparison\" || totalPreviousValue === 0) {\n return 0\n }\n return (totalValue - totalPreviousValue) / totalPreviousValue\n }, [comparisonPeriod, totalPreviousValue, totalValue])\n\n // Show comparison UI elements\n const showComparison = comparisonPeriod !== \"no-comparison\"\n\n // Title Row leading slots (featured icon + title), shared across states.\n const titleLead = (\n <div className=\"flex items-center gap-x-2\">\n {featuredIcon && (\n <span data-slot=\"chart-card-featured-icon\">{featuredIcon}</span>\n )}\n <h3 className={cn(chartCardTitleVariants())} data-slot=\"chart-card-title\">\n {title}\n </h3>\n </div>\n )\n\n // Empty state (DES-1254 item 3 — Figma Empty State)\n if (isEmpty) {\n return (\n <article\n aria-label={`${title}: empty`}\n className={cn(chartCardVariants({ variant }), className)}\n data-empty=\"true\"\n data-slot=\"chart-card\"\n {...props}\n >\n <div className={cn(chartCardHeaderVariants())} data-slot=\"chart-card-header\">\n {titleLead}\n {headerAction && (\n <span data-slot=\"chart-card-header-action\">{headerAction}</span>\n )}\n </div>\n <div\n className={cn(\n chartCardChartVariants(),\n chartHeight,\n \"flex items-center justify-center text-[length:var(--chart-card-empty-state-caption-size)] text-[color:var(--chart-card-empty-state-caption-color)]\"\n )}\n data-slot=\"chart-card-empty\"\n >\n {emptyMessage ?? \"No data available\"}\n </div>\n </article>\n )\n }\n\n // Loading state\n if (loading) {\n return (\n <article\n aria-busy=\"true\"\n className={cn(chartCardVariants({ variant }), className)}\n data-slot=\"chart-card\"\n {...props}\n >\n <div className={cn(chartCardHeaderVariants())} data-slot=\"chart-card-header\">\n <SkeletonLoader className=\"h-4 w-24\" />\n <SkeletonLoader className=\"h-5 w-12\" />\n </div>\n <div\n className={cn(chartCardValueContainerVariants())}\n data-slot=\"chart-card-value\"\n >\n <SkeletonLoader className=\"h-7 w-32\" />\n </div>\n <div className={cn(chartCardChartVariants(), chartHeight)}>\n <SkeletonLoader className=\"h-full w-full\" />\n </div>\n </article>\n )\n }\n\n return (\n <article\n aria-label={`${title}: ${valueFormatter(totalValue)}`}\n className={cn(chartCardVariants({ variant }), className)}\n data-slot=\"chart-card\"\n {...props}\n >\n {/* Title Row — featured icon + title + badge / overflow action */}\n <div className={cn(chartCardHeaderVariants())} data-slot=\"chart-card-header\">\n <div className=\"flex items-center gap-x-2\">\n {featuredIcon && (\n <span data-slot=\"chart-card-featured-icon\">{featuredIcon}</span>\n )}\n <h3 className={cn(chartCardTitleVariants())} data-slot=\"chart-card-title\">\n {title}\n </h3>\n {showComparison && (\n badge ?? (\n <Badge color={getBadgeColor(evolution)} size=\"sm\">\n {formatPercentage(evolution)}\n </Badge>\n )\n )}\n </div>\n {headerAction && (\n <span data-slot=\"chart-card-header-action\">{headerAction}</span>\n )}\n </div>\n\n {/* Value display */}\n <div\n className={cn(chartCardValueContainerVariants())}\n data-slot=\"chart-card-value\"\n >\n <p className={cn(chartCardValueVariants())}>\n {valueFormatter(totalValue)}\n </p>\n {showComparison && (\n <p className={cn(chartCardPreviousValueVariants())}>\n from {valueFormatter(totalPreviousValue)}\n </p>\n )}\n </div>\n\n {/* Tabs row slot (Figma showTabs) */}\n {tabs && (\n <div className=\"mt-[var(--chart-card-gap)]\" data-slot=\"chart-card-tabs\">\n {tabs}\n </div>\n )}\n\n {/* Chart slot — injected by the consumer (chart-agnostic) */}\n {!isThumbnail && chart && (\n <div\n className={cn(chartCardChartVariants(), chartHeight)}\n data-slot=\"chart-card-chart\"\n >\n {chart}\n </div>\n )}\n\n {/* Card Footer slot (Figma showCardFooter — trend + total) */}\n {footer && (\n <div className=\"mt-[var(--chart-card-gap)]\" data-slot=\"chart-card-footer\">\n {footer}\n </div>\n )}\n </article>\n )\n}\n\nChartCard.displayName = \"ChartCard\"\n\nexport { ChartCard }\n"]}
@@ -4,7 +4,7 @@ import { Popover, PopoverTrigger, PopoverContent } from './chunk-AFCSDND5.js';
4
4
  import { Button } from './chunk-ONQCNOLU.js';
5
5
  import { cn } from './chunk-HRNDJU7D.js';
6
6
  import { format, startOfDay, isBefore, isAfter, setMinutes, setHours } from 'date-fns';
7
- import { XIcon, CalendarIcon } from 'lucide-react';
7
+ import { CalendarIcon, XIcon } from 'lucide-react';
8
8
  import * as React from 'react';
9
9
  import { cva } from 'class-variance-authority';
10
10
  import { jsxs, jsx } from 'react/jsx-runtime';
@@ -40,6 +40,40 @@ var datePickerTriggerVariants = cva(
40
40
  }
41
41
  }
42
42
  );
43
+ var datePickerClearButtonVariants = cva(
44
+ [
45
+ "absolute top-1/2 inline-flex size-4 -translate-y-1/2 items-center justify-center rounded-sm outline-none",
46
+ "text-muted-foreground opacity-70 transition-opacity",
47
+ "hover:opacity-100 focus-visible:opacity-100",
48
+ "focus-visible:ring-[color:var(--date-picker-trigger-ring-primary)]/50 focus-visible:ring-[length:var(--date-picker-trigger-ring-width)]"
49
+ ],
50
+ {
51
+ variants: {
52
+ size: {
53
+ sm: "",
54
+ md: "",
55
+ lg: ""
56
+ },
57
+ variant: {
58
+ default: "",
59
+ filled: "",
60
+ flushed: ""
61
+ }
62
+ },
63
+ compoundVariants: [
64
+ // Non-flushed variants inset the trailing slot by the trigger's px token
65
+ { variant: ["default", "filled"], size: "sm", className: "right-[var(--date-picker-trigger-padding-x-sm)]" },
66
+ { variant: ["default", "filled"], size: "md", className: "right-[var(--date-picker-trigger-padding-x-md)]" },
67
+ { variant: ["default", "filled"], size: "lg", className: "right-[var(--date-picker-trigger-padding-x-lg)]" },
68
+ // Flushed removes horizontal padding, so the slot sits at the edge
69
+ { variant: "flushed", className: "right-0" }
70
+ ],
71
+ defaultVariants: {
72
+ size: "md",
73
+ variant: "default"
74
+ }
75
+ }
76
+ );
43
77
  function to12Hour(hours) {
44
78
  const period = hours >= 12 ? "PM" : "AM";
45
79
  let hour12 = hours % 12;
@@ -68,6 +102,8 @@ function getMinuteOptions(step) {
68
102
  function DatePicker({
69
103
  ref,
70
104
  className,
105
+ align = "start",
106
+ dialogLabel = "Choose date",
71
107
  value,
72
108
  defaultValue,
73
109
  placeholder = "Select date",
@@ -212,7 +248,8 @@ function DatePicker({
212
248
  const hourOptions = React.useMemo(() => getHourOptions(timeUse12Hour), [timeUse12Hour]);
213
249
  const minuteOptions = React.useMemo(() => getMinuteOptions(timeMinuteStep), [timeMinuteStep]);
214
250
  const displayHour = timeUse12Hour ? to12Hour(currentHours).hour12 : currentHours;
215
- const showClearButton = clearable && selectedDate && !disabled && !readOnly;
251
+ const hasValue = Boolean(selectedDate);
252
+ const showClearButton = clearable && hasValue && !disabled && !readOnly;
216
253
  const isDateDisabled = React.useCallback(
217
254
  (date) => {
218
255
  const normalizedDate = startOfDay(date);
@@ -243,13 +280,14 @@ function DatePicker({
243
280
  !displayValue && "text-muted-foreground"
244
281
  ),
245
282
  "aria-describedby": ariaDescribedby,
283
+ "aria-disabled": readOnly || void 0,
246
284
  "aria-expanded": open,
247
285
  "aria-haspopup": "dialog",
248
286
  "aria-invalid": invalid,
249
287
  "aria-label": ariaLabel,
250
288
  "aria-labelledby": ariaLabelledby,
251
- "aria-readonly": readOnly,
252
289
  "aria-required": required,
290
+ "data-has-value": hasValue,
253
291
  "data-readonly": readOnly || void 0,
254
292
  "data-size": size,
255
293
  "data-slot": "date-picker-trigger",
@@ -257,38 +295,24 @@ function DatePicker({
257
295
  "data-variant": variant,
258
296
  disabled,
259
297
  id,
260
- role: "combobox",
261
298
  type: "button",
262
299
  children: [
263
300
  /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: displayValue ?? placeholder }),
264
- /* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-1", children: [
265
- showClearButton && /* @__PURE__ */ jsx(
266
- "span",
267
- {
268
- "aria-label": "Clear date",
269
- className: "rounded-sm opacity-50 hover:opacity-100 focus:outline-none",
270
- "data-slot": "date-picker-clear",
271
- role: "button",
272
- tabIndex: 0,
273
- onClick: handleClear,
274
- onKeyDown: (e) => {
275
- if (e.key === "Enter" || e.key === " ") {
276
- e.preventDefault();
277
- handleClear(e);
278
- }
279
- },
280
- children: /* @__PURE__ */ jsx(XIcon, { className: "size-4" })
281
- }
282
- ),
283
- /* @__PURE__ */ jsx(CalendarIcon, { className: "size-4 opacity-50" })
284
- ] })
301
+ /* @__PURE__ */ jsx(
302
+ CalendarIcon,
303
+ {
304
+ "aria-hidden": "true",
305
+ className: cn("size-4 shrink-0 opacity-50", showClearButton && "invisible")
306
+ }
307
+ )
285
308
  ]
286
309
  }
287
310
  ) }),
288
311
  /* @__PURE__ */ jsxs(
289
312
  PopoverContent,
290
313
  {
291
- align: "start",
314
+ align,
315
+ "aria-label": dialogLabel,
292
316
  className: "w-auto p-0",
293
317
  "data-slot": "date-picker-calendar",
294
318
  children: [
@@ -444,6 +468,17 @@ function DatePicker({
444
468
  }
445
469
  )
446
470
  ] }),
471
+ showClearButton && /* @__PURE__ */ jsx(
472
+ "button",
473
+ {
474
+ "aria-label": "Clear date",
475
+ className: cn(datePickerClearButtonVariants({ size, variant })),
476
+ "data-slot": "date-picker-clear",
477
+ type: "button",
478
+ onClick: handleClear,
479
+ children: /* @__PURE__ */ jsx(XIcon, { className: "size-4" })
480
+ }
481
+ ),
447
482
  name && /* @__PURE__ */ jsx(
448
483
  "input",
449
484
  {
@@ -456,5 +491,5 @@ function DatePicker({
456
491
  }
457
492
 
458
493
  export { DatePicker, datePickerTriggerVariants };
459
- //# sourceMappingURL=chunk-RVUO7SDG.js.map
460
- //# sourceMappingURL=chunk-RVUO7SDG.js.map
494
+ //# sourceMappingURL=chunk-LS3WD6IZ.js.map
495
+ //# sourceMappingURL=chunk-LS3WD6IZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/forms/DatePicker/DatePicker.variants.ts","../src/components/forms/DatePicker/DatePicker.tsx"],"names":["format","formatDate"],"mappings":";;;;;;;;;;;AAKO,IAAM,yBAAA,GAA4B,GAAA;AAAA;AAAA,EAEvC;AAAA,IACE,gLAAA;AAAA,IACA,WAAA;AAAA,IACA,mCAAA;AAAA,IACA,qPAAA;AAAA,IACA,8MAAA;AAAA,IACA,wGAAA;AAAA,IACA,2FAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA,MACR,IAAA,EAAM;AAAA,QACJ,EAAA,EAAI,qLAAA;AAAA,QACJ,EAAA,EAAI,qLAAA;AAAA,QACJ,EAAA,EAAI;AAAA,OACN;AAAA,MACA,OAAA,EAAS;AAAA,QACP,OAAA,EAAS,yCAAA;AAAA,QACT,MAAA,EAAQ,6BAAA;AAAA,QACR,OAAA,EAAS;AAAA;AACX,KACF;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,IAAA,EAAM,IAAA;AAAA,MACN,OAAA,EAAS;AAAA;AACX;AAEJ;AAUO,IAAM,6BAAA,GAAgC,GAAA;AAAA,EAC3C;AAAA,IACE,0GAAA;AAAA,IACA,qDAAA;AAAA,IACA,6CAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA,MACR,IAAA,EAAM;AAAA,QACJ,EAAA,EAAI,EAAA;AAAA,QACJ,EAAA,EAAI,EAAA;AAAA,QACJ,EAAA,EAAI;AAAA,OACN;AAAA,MACA,OAAA,EAAS;AAAA,QACP,OAAA,EAAS,EAAA;AAAA,QACT,MAAA,EAAQ,EAAA;AAAA,QACR,OAAA,EAAS;AAAA;AACX,KACF;AAAA,IACA,gBAAA,EAAkB;AAAA;AAAA,MAEhB,EAAE,SAAS,CAAC,SAAA,EAAW,QAAQ,CAAA,EAAG,IAAA,EAAM,IAAA,EAAM,SAAA,EAAW,iDAAA,EAAkD;AAAA,MAC3G,EAAE,SAAS,CAAC,SAAA,EAAW,QAAQ,CAAA,EAAG,IAAA,EAAM,IAAA,EAAM,SAAA,EAAW,iDAAA,EAAkD;AAAA,MAC3G,EAAE,SAAS,CAAC,SAAA,EAAW,QAAQ,CAAA,EAAG,IAAA,EAAM,IAAA,EAAM,SAAA,EAAW,iDAAA,EAAkD;AAAA;AAAA,MAE3G,EAAE,OAAA,EAAS,SAAA,EAAW,SAAA,EAAW,SAAA;AAAU,KAC7C;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,IAAA,EAAM,IAAA;AAAA,MACN,OAAA,EAAS;AAAA;AACX;AAEJ,CAAA;AC1DA,SAAS,SAAS,KAAA,EAAwD;AACxE,EAAA,MAAM,MAAA,GAAS,KAAA,IAAS,EAAA,GAAK,IAAA,GAAO,IAAA;AACpC,EAAA,IAAI,SAAS,KAAA,GAAQ,EAAA;AACrB,EAAA,IAAI,MAAA,KAAW,GAAG,MAAA,GAAS,EAAA;AAC3B,EAAA,OAAO,EAAE,QAAQ,MAAA,EAAO;AAC1B;AAKA,SAAS,QAAA,CAAS,QAAgB,MAAA,EAA6B;AAC7D,EAAA,IAAI,WAAW,IAAA,EAAM;AACnB,IAAA,OAAO,MAAA,KAAW,KAAK,CAAA,GAAI,MAAA;AAAA,EAC7B;AACA,EAAA,OAAO,MAAA,KAAW,EAAA,GAAK,EAAA,GAAK,MAAA,GAAS,EAAA;AACvC;AAKA,SAAS,eAAe,SAAA,EAA8B;AACpD,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,OAAO,CAAC,EAAA,EAAI,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,EAAA,EAAI,EAAE,CAAA;AAAA,EAC/C;AACA,EAAA,OAAO,KAAA,CAAM,KAAK,EAAE,MAAA,EAAQ,IAAG,EAAG,CAAC,CAAA,EAAG,CAAA,KAAM,CAAC,CAAA;AAC/C;AAKA,SAAS,iBAAiB,IAAA,EAAwB;AAChD,EAAA,MAAM,UAAoB,EAAC;AAC3B,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,EAAA,EAAI,KAAK,IAAA,EAAM;AACjC,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACA,EAAA,OAAO,OAAA;AACT;AAEA,SAAS,UAAA,CAAW;AAAA,EAClB,GAAA;AAAA,EACA,SAAA;AAAA,EACA,KAAA,GAAQ,OAAA;AAAA,EACR,WAAA,GAAc,aAAA;AAAA,EACd,KAAA;AAAA,EACA,YAAA;AAAA,EACA,WAAA,GAAc,aAAA;AAAA,EACd,QAAA,GAAW,KAAA;AAAA,EACX,aAAA;AAAA,EACA,QAAA,GAAW,KAAA;AAAA,EACX,cAAA,GAAiB,KAAA;AAAA,EACjB,SAAA,GAAY,KAAA;AAAA,EACZ,SAAA,GAAY,MAAA;AAAA,EACZ,cAAA,GAAiB,CAAA;AAAA,EACjB,aAAA,GAAgB,KAAA;AAAA,EAChB,UAAA,GAAa,OAAA;AAAA,EACb,OAAA;AAAA,EACA,OAAA;AAAA,UACAA,QAAA,GAAS,KAAA;AAAA,EACT,MAAA;AAAA,EACA,QAAA;AAAA,EACA,YAAA;AAAA,EACA,OAAA;AAAA,EACA,IAAA,GAAO,IAAA;AAAA,EACP,OAAA,GAAU,SAAA;AAAA,EACV,QAAA,GAAW,KAAA;AAAA,EACX,OAAA,GAAU,KAAA;AAAA,EACV,SAAA,GAAY,KAAA;AAAA,EACZ,aAAA;AAAA,EACA,EAAA;AAAA,EACA,IAAA;AAAA,EACA,YAAA,EAAc,SAAA;AAAA,EACd,iBAAA,EAAmB,cAAA;AAAA,EACnB,kBAAA,EAAoB,eAAA;AAAA,EACpB,GAAG;AACL,CAAA,EAAoB;AAClB,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAU,eAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAU,eAA2B,YAAY,CAAA;AAGrF,EAAA,MAAM,CAAC,aAAA,EAAe,gBAAgB,CAAA,GAAU,KAAA,CAAA,QAAA;AAAA,IAC9C,YAAA,GAAe,YAAA,CAAa,QAAA,EAAS,GAAI;AAAA,GAC3C;AACA,EAAA,MAAM,CAAC,eAAA,EAAiB,kBAAkB,CAAA,GAAU,KAAA,CAAA,QAAA;AAAA,IAClD,YAAA,GAAe,YAAA,CAAa,UAAA,EAAW,GAAI;AAAA,GAC7C;AACA,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAU,KAAA,CAAA,QAAA;AAAA,IAAsB,MACtE,YAAA,GAAe,QAAA,CAAS,aAAa,QAAA,EAAU,EAAE,MAAA,GAAS;AAAA,GAC5D;AAGA,EAAA,MAAM,WAAA,GAAoB,aAAuB,IAAI,CAAA;AACrD,EAAA,MAAM,aAAA,GAAsB,aAAuB,IAAI,CAAA;AAGvD,EAAA,MAAM,eAAe,KAAA,IAAS,YAAA;AAG9B,EAAA,MAAM,YAAA,GAAe,YAAA,GAAe,YAAA,CAAa,QAAA,EAAS,GAAI,aAAA;AAC9D,EAAA,MAAM,cAAA,GAAiB,YAAA,GAAe,YAAA,CAAa,UAAA,EAAW,GAAI,eAAA;AAClE,EAAA,MAAM,gBAAgB,YAAA,GAClB,QAAA,CAAS,aAAa,QAAA,EAAU,EAAE,MAAA,GAClC,cAAA;AAGJ,EAAA,MAAM,eAAe,YAAA,IAAgB,OAAA;AAGrC,EAAM,gBAAU,MAAM;AACpB,IAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,cAAA,EAAgB;AAE9B,IAAA,MAAM,SAAA,GAAY,WAAW,MAAM;AACjC,MAAA,MAAM,YAAA,GAAe,WAAA,CAAY,OAAA,EAAS,aAAA,CAAc,wBAAwB,CAAA;AAChF,MAAA,YAAA,EAAc,eAAe,EAAE,KAAA,EAAO,QAAA,EAAU,QAAA,EAAU,WAAW,CAAA;AAErE,MAAA,MAAM,cAAA,GAAiB,aAAA,CAAc,OAAA,EAAS,aAAA,CAAc,wBAAwB,CAAA;AACpF,MAAA,cAAA,EAAgB,eAAe,EAAE,KAAA,EAAO,QAAA,EAAU,QAAA,EAAU,WAAW,CAAA;AAAA,IACzE,GAAG,CAAC,CAAA;AAEJ,IAAA,OAAO,MAAM;AAAE,MAAA,YAAA,CAAa,SAAS,CAAA;AAAA,IAAE,CAAA;AAAA,EACzC,GAAG,CAAC,IAAA,EAAM,cAAA,EAAgB,YAAA,EAAc,cAAc,CAAC,CAAA;AAEvD,EAAA,MAAM,eAAA,GAAkB,CAAC,IAAA,EAAwB,KAAA,EAAe,OAAA,KAAsC;AACpG,IAAA,IAAI,CAAC,MAAM,OAAO,MAAA;AAClB,IAAA,OAAO,UAAA,CAAW,QAAA,CAAS,IAAA,EAAM,KAAK,GAAG,OAAO,CAAA;AAAA,EAClD,CAAA;AAEA,EAAA,MAAM,YAAA,GAAe,CAAC,IAAA,KAA2B;AAC/C,IAAA,IAAI,SAAA,GAAY,IAAA;AAChB,IAAA,IAAI,kBAAkB,IAAA,EAAM;AAE1B,MAAA,SAAA,GAAY,eAAA,CAAgB,IAAA,EAAM,YAAA,EAAc,cAAc,CAAA;AAAA,IAChE;AAEA,IAAA,IAAI,UAAU,MAAA,EAAW;AACvB,MAAA,eAAA,CAAgB,SAAS,CAAA;AAAA,IAC3B;AACA,IAAA,QAAA,GAAW,SAAS,CAAA;AAGpB,IAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,MAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,IACf;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,gBAAA,GAAmB,CAAC,KAAA,EAAe,OAAA,KAAoB;AAC3D,IAAA,IAAI,UAAU,MAAA,EAAW;AACvB,MAAA,gBAAA,CAAiB,KAAK,CAAA;AACtB,MAAA,kBAAA,CAAmB,OAAO,CAAA;AAAA,IAC5B;AAEA,IAAA,IAAI,YAAA,EAAc;AAChB,MAAA,MAAM,OAAA,GAAU,eAAA,CAAgB,YAAA,EAAc,KAAA,EAAO,OAAO,CAAA;AAC5D,MAAA,IAAI,UAAU,MAAA,EAAW;AACvB,QAAA,eAAA,CAAgB,OAAO,CAAA;AAAA,MACzB;AACA,MAAA,QAAA,GAAW,OAAO,CAAA;AAAA,IACpB;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,gBAAA,GAAmB,CAAC,IAAA,KAAiB;AACzC,IAAA,IAAI,QAAA,GAAW,IAAA;AACf,IAAA,IAAI,aAAA,EAAe;AACjB,MAAA,QAAA,GAAW,QAAA,CAAS,MAAM,aAAa,CAAA;AAAA,IACzC;AACA,IAAA,IAAI,UAAU,MAAA,EAAW;AACvB,MAAA,gBAAA,CAAiB,QAAQ,CAAA;AAAA,IAC3B;AACA,IAAA,gBAAA,CAAiB,UAAU,cAAc,CAAA;AAAA,EAC3C,CAAA;AAEA,EAAA,MAAM,kBAAA,GAAqB,CAAC,MAAA,KAAmB;AAC7C,IAAA,IAAI,UAAU,MAAA,EAAW;AACvB,MAAA,kBAAA,CAAmB,MAAM,CAAA;AAAA,IAC3B;AACA,IAAA,gBAAA,CAAiB,cAAc,MAAM,CAAA;AAAA,EACvC,CAAA;AAEA,EAAA,MAAM,kBAAA,GAAqB,CAAC,MAAA,KAAwB;AAClD,IAAA,IAAI,UAAU,MAAA,EAAW;AACvB,MAAA,iBAAA,CAAkB,MAAM,CAAA;AAAA,IAC1B;AACA,IAAA,MAAM,SAAS,aAAA,GACX,YAAA,GAAe,MAAM,EAAA,GACrB,QAAA,CAAS,YAAY,CAAA,CAAE,MAAA;AAC3B,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,MAAA,EAAQ,MAAM,CAAA;AACxC,IAAA,IAAI,UAAU,MAAA,EAAW;AACvB,MAAA,gBAAA,CAAiB,QAAQ,CAAA;AAAA,IAC3B;AACA,IAAA,gBAAA,CAAiB,UAAU,cAAc,CAAA;AAAA,EAC3C,CAAA;AAEA,EAAA,MAAM,gBAAA,GAAmB,CAAC,MAAA,KAAoB;AAE5C,IAAA,IAAI,YAAY,MAAA,EAAQ;AAExB,IAAA,OAAA,CAAQ,MAAM,CAAA;AACd,IAAA,YAAA,GAAe,MAAM,CAAA;AAAA,EACvB,CAAA;AAEA,EAAA,MAAM,WAAA,GAAc,CAAC,KAAA,KAA4B;AAC/C,IAAA,KAAA,CAAM,eAAA,EAAgB;AACtB,IAAA,IAAI,UAAU,MAAA,EAAW;AACvB,MAAA,eAAA,CAAgB,MAAS,CAAA;AAAA,IAC3B;AACA,IAAA,QAAA,IAAW;AACX,IAAA,OAAA,IAAU;AAAA,EACZ,CAAA;AAGA,EAAA,MAAM,YAAA,GAAqB,cAAQ,MAAM;AACvC,IAAA,IAAI,CAAC,cAAc,OAAO,IAAA;AAE1B,IAAA,MAAM,OAAA,GAAUC,OAAW,YAAA,EAAcD,QAAA,EAAQ,SAAS,EAAE,MAAA,KAAW,MAAS,CAAA;AAEhF,IAAA,IAAI,cAAA,EAAgB;AAClB,MAAA,MAAM,OAAA,GAAU,aAAA,GACZ,CAAA,EAAG,MAAA,CAAO,SAAS,YAAY,CAAA,CAAE,MAAM,CAAC,IAAI,cAAA,CAAe,QAAA,EAAS,CAAE,QAAA,CAAS,GAAG,GAAG,CAAC,CAAA,CAAA,EAAI,aAAa,KACvG,CAAA,EAAG,YAAA,CAAa,QAAA,EAAS,CAAE,SAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA,EAAI,eAAe,QAAA,EAAS,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA;AAC7F,MAAA,OAAO,CAAA,EAAG,OAAO,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA;AAAA,IAC9B;AAEA,IAAA,OAAO,OAAA;AAAA,EACT,CAAA,EAAG,CAAC,YAAA,EAAcA,QAAA,EAAQ,MAAA,EAAQ,gBAAgB,aAAA,EAAe,YAAA,EAAc,cAAA,EAAgB,aAAa,CAAC,CAAA;AAG7G,EAAA,MAAM,WAAA,GAAoB,cAAQ,MAAM,cAAA,CAAe,aAAa,CAAA,EAAG,CAAC,aAAa,CAAC,CAAA;AACtF,EAAA,MAAM,aAAA,GAAsB,cAAQ,MAAM,gBAAA,CAAiB,cAAc,CAAA,EAAG,CAAC,cAAc,CAAC,CAAA;AAG5F,EAAA,MAAM,WAAA,GAAc,aAAA,GAChB,QAAA,CAAS,YAAY,EAAE,MAAA,GACvB,YAAA;AAIJ,EAAA,MAAM,QAAA,GAAW,QAAQ,YAAY,CAAA;AAErC,EAAA,MAAM,eAAA,GAAkB,SAAA,IAAa,QAAA,IAAY,CAAC,YAAY,CAAC,QAAA;AAG/D,EAAA,MAAM,cAAA,GAAuB,KAAA,CAAA,WAAA;AAAA,IAC3B,CAAC,IAAA,KAAwB;AACvB,MAAA,MAAM,cAAA,GAAiB,WAAW,IAAI,CAAA;AACtC,MAAA,IAAI,WAAW,QAAA,CAAS,cAAA,EAAgB,WAAW,OAAO,CAAC,GAAG,OAAO,IAAA;AACrE,MAAA,IAAI,WAAW,OAAA,CAAQ,cAAA,EAAgB,WAAW,OAAO,CAAC,GAAG,OAAO,IAAA;AACpE,MAAA,IAAI,aAAA,GAAgB,IAAI,CAAA,EAAG,OAAO,IAAA;AAClC,MAAA,OAAO,KAAA;AAAA,IACT,CAAA;AAAA,IACA,CAAC,OAAA,EAAS,OAAA,EAAS,aAAa;AAAA,GAClC;AAGA,EAAA,MAAM,eAAA,GAAwB,cAAQ,MAAM;AAC1C,IAAA,OAAO,cAAA,iBAAe,IAAI,IAAA,EAAM,CAAA;AAAA,EAClC,CAAA,EAAG,CAAC,cAAc,CAAC,CAAA;AAGnB,EAAA,MAAM,oBAAoB,MAAM;AAC9B,IAAA,MAAM,KAAA,GAAQ,UAAA,iBAAW,IAAI,IAAA,EAAM,CAAA;AACnC,IAAA,IAAI,CAAC,cAAA,CAAe,KAAK,CAAA,EAAG;AAC1B,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB;AAAA,EACF,CAAA;AAEA,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,UAAA,EAAY,SAAS,CAAA,EAAG,WAAA,EAAU,aAAA,EAAe,GAAG,KAAA,EACrE,QAAA,EAAA;AAAA,oBAAA,IAAA,CAAC,OAAA,EAAA,EAAQ,IAAA,EAAY,YAAA,EAAc,gBAAA,EACjC,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,cAAA,EAAA,EAAe,SAAO,IAAA,EACrB,QAAA,kBAAA,IAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,GAAA;AAAA,UACA,SAAA,EAAW,EAAA;AAAA,YACT,yBAAA,CAA0B,EAAE,IAAA,EAAM,OAAA,EAAS,CAAA;AAAA,YAC3C,CAAC,YAAA,IAAgB;AAAA,WACnB;AAAA,UACA,kBAAA,EAAkB,eAAA;AAAA,UAClB,iBAAe,QAAA,IAAY,MAAA;AAAA,UAC3B,eAAA,EAAe,IAAA;AAAA,UACf,eAAA,EAAc,QAAA;AAAA,UACd,cAAA,EAAc,OAAA;AAAA,UACd,YAAA,EAAY,SAAA;AAAA,UACZ,iBAAA,EAAiB,cAAA;AAAA,UACjB,eAAA,EAAe,QAAA;AAAA,UACf,gBAAA,EAAgB,QAAA;AAAA,UAChB,iBAAe,QAAA,IAAY,MAAA;AAAA,UAC3B,WAAA,EAAW,IAAA;AAAA,UACX,WAAA,EAAU,qBAAA;AAAA,UACV,YAAA,EAAY,OAAO,MAAA,GAAS,QAAA;AAAA,UAC5B,cAAA,EAAc,OAAA;AAAA,UACd,QAAA;AAAA,UACA,EAAA;AAAA,UACA,IAAA,EAAK,QAAA;AAAA,UAEL,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,iBAAA,EACb,QAAA,EAAA,YAAA,IAAgB,WAAA,EACnB,CAAA;AAAA,4BACA,GAAA;AAAA,cAAC,YAAA;AAAA,cAAA;AAAA,gBACC,aAAA,EAAY,MAAA;AAAA,gBACZ,SAAA,EAAW,EAAA,CAAG,4BAAA,EAA8B,eAAA,IAAmB,WAAW;AAAA;AAAA;AAC5E;AAAA;AAAA,OACF,EACF,CAAA;AAAA,sBACA,IAAA;AAAA,QAAC,cAAA;AAAA,QAAA;AAAA,UACC,KAAA;AAAA,UACA,YAAA,EAAY,WAAA;AAAA,UACZ,SAAA,EAAU,YAAA;AAAA,UACV,WAAA,EAAU,sBAAA;AAAA,UAEV,QAAA,EAAA;AAAA,4BAAA,GAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBACC,SAAA,EAAS,IAAA;AAAA,gBACT,QACE,SAAA,mBACE,GAAA,CAAC,SAAI,SAAA,EAAU,4BAAA,EAA6B,aAAU,oBAAA,EACpD,QAAA,kBAAA,GAAA;AAAA,kBAAC,MAAA;AAAA,kBAAA;AAAA,oBACC,SAAA,EAAU,QAAA;AAAA,oBACV,QAAA,EAAU,eAAA;AAAA,oBACV,IAAA,EAAK,IAAA;AAAA,oBACL,OAAA,EAAQ,OAAA;AAAA,oBACR,OAAA,EAAS,iBAAA;AAAA,oBAER,QAAA,EAAA;AAAA;AAAA,mBAEL,CAAA,GACE,MAAA;AAAA,gBAEN,YAAA;AAAA,gBACA,QAAA,EAAU,cAAA;AAAA,gBACV,MAAA;AAAA,gBACA,IAAA,EAAK,QAAA;AAAA,gBACL,QAAA,EAAU,YAAA;AAAA,gBACV,QAAA,EAAU,YAAA;AAAA,gBACT,GAAG;AAAA;AAAA,aACN;AAAA,YAGC,cAAA,oBACC,IAAA;AAAA,cAAC,KAAA;AAAA,cAAA;AAAA,gBACC,SAAA,EAAU,wBAAA;AAAA,gBACV,WAAA,EAAU,kBAAA;AAAA,gBAEV,QAAA,EAAA;AAAA,kCAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qDAAA,EACZ,QAAA,EAAA,SAAA,EACH,CAAA;AAAA,kCACA,IAAA;AAAA,oBAAC,KAAA;AAAA,oBAAA;AAAA,sBACC,YAAA,EAAW,gBAAA;AAAA,sBACX,SAAA,EAAU,sCAAA;AAAA,sBACV,IAAA,EAAK,SAAA;AAAA,sBAGL,QAAA,EAAA;AAAA,wCAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,eAAA,EACb,QAAA,EAAA;AAAA,0CAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4EAAA,EACZ,QAAA,EAAA,aAAA,GAAgB,SAAS,OAAA,EAC5B,CAAA;AAAA,0CACA,GAAA,CAAC,UAAA,EAAA,EAAW,SAAA,EAAU,MAAA,EACpB,QAAA,kBAAA,GAAA;AAAA,4BAAC,KAAA;AAAA,4BAAA;AAAA,8BACC,GAAA,EAAK,WAAA;AAAA,8BACL,YAAA,EAAW,OAAA;AAAA,8BACX,SAAA,EAAU,iCAAA;AAAA,8BACV,IAAA,EAAK,OAAA;AAAA,8BAEJ,QAAA,EAAA,WAAA,CAAY,GAAA,CAAI,CAAC,IAAA,KAAS;AACzB,gCAAA,MAAM,aAAa,WAAA,KAAgB,IAAA;AACnC,gCAAA,uBACE,GAAA;AAAA,kCAAC,QAAA;AAAA,kCAAA;AAAA,oCAEC,SAAA,EAAW,EAAA;AAAA,sCACT,8DAAA;AAAA,sCACA,8CAAA;AAAA,sCACA,iEAAA;AAAA,sCACA,UAAA,IAAc;AAAA,qCAChB;AAAA,oCACA,eAAA,EAAe,UAAA;AAAA,oCACf,eAAA,EAAe,UAAA;AAAA,oCACf,IAAA,EAAK,QAAA;AAAA,oCACL,IAAA,EAAK,QAAA;AAAA,oCACL,SAAS,MAAM;AAAE,sCAAA,gBAAA,CAAiB,IAAI,CAAA;AAAA,oCAAG,CAAA;AAAA,oCAExC,0BAAgB,IAAA,GAAO,IAAA,CAAK,UAAS,CAAE,QAAA,CAAS,GAAG,GAAG;AAAA,mCAAA;AAAA,kCAblD;AAAA,iCAcP;AAAA,8BAEJ,CAAC;AAAA;AAAA,2BACH,EACF;AAAA,yBAAA,EACF,CAAA;AAAA,wCAGA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,eAAA,EACb,QAAA,EAAA;AAAA,0CAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4EAAA,EAA6E,QAAA,EAAA,KAAA,EAE5F,CAAA;AAAA,0CACA,GAAA,CAAC,UAAA,EAAA,EAAW,SAAA,EAAU,MAAA,EACpB,QAAA,kBAAA,GAAA;AAAA,4BAAC,KAAA;AAAA,4BAAA;AAAA,8BACC,GAAA,EAAK,aAAA;AAAA,8BACL,YAAA,EAAW,SAAA;AAAA,8BACX,SAAA,EAAU,iCAAA;AAAA,8BACV,IAAA,EAAK,OAAA;AAAA,8BAEJ,QAAA,EAAA,aAAA,CAAc,GAAA,CAAI,CAAC,MAAA,KAAW;AAC7B,gCAAA,MAAM,aAAa,cAAA,KAAmB,MAAA;AACtC,gCAAA,uBACE,GAAA;AAAA,kCAAC,QAAA;AAAA,kCAAA;AAAA,oCAEC,SAAA,EAAW,EAAA;AAAA,sCACT,8DAAA;AAAA,sCACA,8CAAA;AAAA,sCACA,iEAAA;AAAA,sCACA,UAAA,IAAc;AAAA,qCAChB;AAAA,oCACA,eAAA,EAAe,UAAA;AAAA,oCACf,eAAA,EAAe,UAAA;AAAA,oCACf,IAAA,EAAK,QAAA;AAAA,oCACL,IAAA,EAAK,QAAA;AAAA,oCACL,SAAS,MAAM;AAAE,sCAAA,kBAAA,CAAmB,MAAM,CAAA;AAAA,oCAAG,CAAA;AAAA,oCAE5C,QAAA,EAAA,MAAA,CAAO,QAAA,EAAS,CAAE,QAAA,CAAS,GAAG,GAAG;AAAA,mCAAA;AAAA,kCAb7B;AAAA,iCAcP;AAAA,8BAEJ,CAAC;AAAA;AAAA,2BACH,EACF;AAAA,yBAAA,EACF,CAAA;AAAA,wBAGC,aAAA,oBACC,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,eAAA,EACb,QAAA,EAAA;AAAA,0CAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4EAAA,EAA6E,QAAA,EAAA,MAAA,EAE5F,CAAA;AAAA,0CACA,GAAA;AAAA,4BAAC,KAAA;AAAA,4BAAA;AAAA,8BACC,YAAA,EAAW,QAAA;AAAA,8BACX,SAAA,EAAU,iCAAA;AAAA,8BACV,IAAA,EAAK,OAAA;AAAA,8BAEH,WAAC,IAAA,EAAM,IAAI,CAAA,CAAY,GAAA,CAAI,CAAC,MAAA,KAAW;AACvC,gCAAA,MAAM,aAAa,aAAA,KAAkB,MAAA;AACrC,gCAAA,uBACE,GAAA;AAAA,kCAAC,QAAA;AAAA,kCAAA;AAAA,oCAEC,SAAA,EAAW,EAAA;AAAA,sCACT,8DAAA;AAAA,sCACA,8CAAA;AAAA,sCACA,iEAAA;AAAA,sCACA,UAAA,IAAc;AAAA,qCAChB;AAAA,oCACA,eAAA,EAAe,UAAA;AAAA,oCACf,eAAA,EAAe,UAAA;AAAA,oCACf,IAAA,EAAK,QAAA;AAAA,oCACL,IAAA,EAAK,QAAA;AAAA,oCACL,SAAS,MAAM;AAAE,sCAAA,kBAAA,CAAmB,MAAM,CAAA;AAAA,oCAAG,CAAA;AAAA,oCAE5C,QAAA,EAAA;AAAA,mCAAA;AAAA,kCAbI;AAAA,iCAcP;AAAA,8BAEJ,CAAC;AAAA;AAAA;AACH,yBAAA,EACF;AAAA;AAAA;AAAA;AAEJ;AAAA;AAAA;AACF;AAAA;AAAA;AAEJ,KAAA,EACF,CAAA;AAAA,IACC,eAAA,oBACC,GAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,YAAA,EAAW,YAAA;AAAA,QACX,WAAW,EAAA,CAAG,6BAAA,CAA8B,EAAE,IAAA,EAAM,OAAA,EAAS,CAAC,CAAA;AAAA,QAC9D,WAAA,EAAU,mBAAA;AAAA,QACV,IAAA,EAAK,QAAA;AAAA,QACL,OAAA,EAAS,WAAA;AAAA,QAET,QAAA,kBAAA,GAAA,CAAC,KAAA,EAAA,EAAM,SAAA,EAAU,QAAA,EAAS;AAAA;AAAA,KAC5B;AAAA,IAED,IAAA,oBACC,GAAA;AAAA,MAAC,OAAA;AAAA,MAAA;AAAA,QACC,IAAA;AAAA,QACA,IAAA,EAAK,QAAA;AAAA,QACL,KAAA,EAAO,YAAA,EAAc,WAAA,EAAY,IAAK;AAAA;AAAA;AACxC,GAAA,EAEJ,CAAA;AAEJ","file":"chunk-LS3WD6IZ.js","sourcesContent":["import { cva, type VariantProps } from \"class-variance-authority\"\n\n/**\n * DatePicker trigger variant styles using CVA\n */\nexport const datePickerTriggerVariants = cva(\n // Base styles\n [\n \"inline-flex w-full items-center justify-between gap-2 rounded-[var(--date-picker-trigger-radius)] border bg-transparent font-normal transition-[color,box-shadow] outline-none\",\n \"text-left\",\n \"placeholder:text-muted-foreground\",\n \"disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-[color:var(--date-picker-trigger-disabled-bg)] disabled:text-[color:var(--date-picker-trigger-disabled-fg)] disabled:border-[color:var(--date-picker-trigger-disabled-border)]\",\n \"focus-visible:border-[color:var(--date-picker-trigger-border-focus)] focus-visible:ring-[color:var(--date-picker-trigger-ring-primary)]/50 focus-visible:ring-[length:var(--date-picker-trigger-ring-width)]\",\n \"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n \"data-[state=open]:border-ring data-[state=open]:ring-ring/50 data-[state=open]:ring-[3px]\",\n \"min-w-[var(--date-picker-trigger-min-width)]\",\n ],\n {\n variants: {\n size: {\n sm: \"h-[var(--date-picker-trigger-height-sm)] px-[var(--date-picker-trigger-padding-x-sm)] py-[var(--date-picker-trigger-padding-y-sm)] text-[length:var(--date-picker-trigger-text-sm)]\",\n md: \"h-[var(--date-picker-trigger-height-md)] px-[var(--date-picker-trigger-padding-x-md)] py-[var(--date-picker-trigger-padding-y-md)] text-[length:var(--date-picker-trigger-text-md)]\",\n lg: \"h-[var(--date-picker-trigger-height-lg)] px-[var(--date-picker-trigger-padding-x-lg)] py-[var(--date-picker-trigger-padding-y-lg)] text-[length:var(--date-picker-trigger-text-lg)]\",\n },\n variant: {\n default: \"border-input shadow-xs dark:bg-input/30\",\n filled: \"border-transparent bg-muted\",\n flushed: \"rounded-none border-x-0 border-t-0 border-b-input px-0\",\n },\n },\n defaultVariants: {\n size: \"md\",\n variant: \"default\",\n },\n }\n)\n\n/**\n * DatePicker clear button styles using CVA.\n *\n * The clear control is a sibling of the trigger (never nested inside the\n * trigger button — button-in-button is invalid). It is absolutely positioned\n * so it overlays the trigger's trailing-icon slot, sitting at the same inset\n * as the calendar icon for each size/variant.\n */\nexport const datePickerClearButtonVariants = cva(\n [\n \"absolute top-1/2 inline-flex size-4 -translate-y-1/2 items-center justify-center rounded-sm outline-none\",\n \"text-muted-foreground opacity-70 transition-opacity\",\n \"hover:opacity-100 focus-visible:opacity-100\",\n \"focus-visible:ring-[color:var(--date-picker-trigger-ring-primary)]/50 focus-visible:ring-[length:var(--date-picker-trigger-ring-width)]\",\n ],\n {\n variants: {\n size: {\n sm: \"\",\n md: \"\",\n lg: \"\",\n },\n variant: {\n default: \"\",\n filled: \"\",\n flushed: \"\",\n },\n },\n compoundVariants: [\n // Non-flushed variants inset the trailing slot by the trigger's px token\n { variant: [\"default\", \"filled\"], size: \"sm\", className: \"right-[var(--date-picker-trigger-padding-x-sm)]\" },\n { variant: [\"default\", \"filled\"], size: \"md\", className: \"right-[var(--date-picker-trigger-padding-x-md)]\" },\n { variant: [\"default\", \"filled\"], size: \"lg\", className: \"right-[var(--date-picker-trigger-padding-x-lg)]\" },\n // Flushed removes horizontal padding, so the slot sits at the edge\n { variant: \"flushed\", className: \"right-0\" },\n ],\n defaultVariants: {\n size: \"md\",\n variant: \"default\",\n },\n }\n)\n\nexport type DatePickerTriggerVariantProps = VariantProps<typeof datePickerTriggerVariants>\n","import type { DatePickerProps } from \"./DatePicker.types\"\n\nimport { format as formatDate, isAfter, isBefore, setHours, setMinutes, startOfDay } from \"date-fns\"\nimport { CalendarIcon, XIcon } from \"lucide-react\"\nimport * as React from \"react\"\n\nimport { cn } from \"../../../lib/utils\"\nimport { Calendar } from \"../../advanced/Calendar\"\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../../feedback/Popover\"\nimport { ScrollArea } from \"../../layout/ScrollArea\"\nimport { Button } from \"../../primitives/Button\"\nimport { datePickerClearButtonVariants, datePickerTriggerVariants } from \"./DatePicker.variants\"\n\n/**\n * Convert 24h hours to 12h format with period\n */\nfunction to12Hour(hours: number): { hour12: number; period: \"AM\" | \"PM\" } {\n const period = hours >= 12 ? \"PM\" : \"AM\"\n let hour12 = hours % 12\n if (hour12 === 0) hour12 = 12\n return { hour12, period }\n}\n\n/**\n * Convert 12h format to 24h hours\n */\nfunction to24Hour(hour12: number, period: \"AM\" | \"PM\"): number {\n if (period === \"AM\") {\n return hour12 === 12 ? 0 : hour12\n }\n return hour12 === 12 ? 12 : hour12 + 12\n}\n\n/**\n * Generate array of hour options\n */\nfunction getHourOptions(use12Hour: boolean): number[] {\n if (use12Hour) {\n return [12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]\n }\n return Array.from({ length: 24 }, (_, i) => i)\n}\n\n/**\n * Generate array of minute options based on step\n */\nfunction getMinuteOptions(step: number): number[] {\n const options: number[] = []\n for (let i = 0; i < 60; i += step) {\n options.push(i)\n }\n return options\n}\n\nfunction DatePicker({\n ref,\n className,\n align = \"start\",\n dialogLabel = \"Choose date\",\n value,\n defaultValue,\n placeholder = \"Select date\",\n disabled = false,\n disabledDates,\n readOnly = false,\n showTimePicker = false,\n showToday = false,\n timeLabel = \"Time\",\n timeMinuteStep = 1,\n timeUse12Hour = false,\n todayLabel = \"Today\",\n minDate,\n maxDate,\n format = \"PPP\",\n locale,\n onChange,\n onOpenChange,\n onClear,\n size = \"md\",\n variant = \"default\",\n required = false,\n invalid = false,\n clearable = false,\n calendarProps,\n id,\n name,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledby,\n \"aria-describedby\": ariaDescribedby,\n ...props\n}: DatePickerProps) {\n const [open, setOpen] = React.useState(false)\n const [internalDate, setInternalDate] = React.useState<Date | undefined>(defaultValue)\n\n // Time state for when showTimePicker is enabled\n const [internalHours, setInternalHours] = React.useState<number>(\n defaultValue ? defaultValue.getHours() : 0\n )\n const [internalMinutes, setInternalMinutes] = React.useState<number>(\n defaultValue ? defaultValue.getMinutes() : 0\n )\n const [internalPeriod, setInternalPeriod] = React.useState<\"AM\" | \"PM\">(() =>\n defaultValue ? to12Hour(defaultValue.getHours()).period : \"AM\"\n )\n\n // Refs for auto-scrolling time columns\n const hourListRef = React.useRef<HTMLDivElement>(null)\n const minuteListRef = React.useRef<HTMLDivElement>(null)\n\n // Use controlled value if provided, otherwise use internal state\n const selectedDate = value ?? internalDate\n\n // Get time from selected date or internal state\n const currentHours = selectedDate ? selectedDate.getHours() : internalHours\n const currentMinutes = selectedDate ? selectedDate.getMinutes() : internalMinutes\n const currentPeriod = selectedDate\n ? to12Hour(selectedDate.getHours()).period\n : internalPeriod\n\n // Compute defaultMonth once for clarity\n const defaultMonth = selectedDate ?? minDate\n\n // Scroll to selected time items when popover opens\n React.useEffect(() => {\n if (!open || !showTimePicker) return\n\n const timeoutId = setTimeout(() => {\n const selectedHour = hourListRef.current?.querySelector('[data-selected=\"true\"]')\n selectedHour?.scrollIntoView({ block: \"center\", behavior: \"instant\" })\n\n const selectedMinute = minuteListRef.current?.querySelector('[data-selected=\"true\"]')\n selectedMinute?.scrollIntoView({ block: \"center\", behavior: \"instant\" })\n }, 0)\n\n return () => { clearTimeout(timeoutId) }\n }, [open, showTimePicker, currentHours, currentMinutes])\n\n const applyTimeToDate = (date: Date | undefined, hours: number, minutes: number): Date | undefined => {\n if (!date) return undefined\n return setMinutes(setHours(date, hours), minutes)\n }\n\n const handleSelect = (date: Date | undefined) => {\n let finalDate = date\n if (showTimePicker && date) {\n // Apply current time to the selected date\n finalDate = applyTimeToDate(date, currentHours, currentMinutes)\n }\n\n if (value === undefined) {\n setInternalDate(finalDate)\n }\n onChange?.(finalDate)\n\n // Only close if not showing time picker, or close after date selection\n if (!showTimePicker) {\n setOpen(false)\n }\n }\n\n const handleTimeChange = (hours: number, minutes: number) => {\n if (value === undefined) {\n setInternalHours(hours)\n setInternalMinutes(minutes)\n }\n\n if (selectedDate) {\n const newDate = applyTimeToDate(selectedDate, hours, minutes)\n if (value === undefined) {\n setInternalDate(newDate)\n }\n onChange?.(newDate)\n }\n }\n\n const handleHourSelect = (hour: number) => {\n let newHours = hour\n if (timeUse12Hour) {\n newHours = to24Hour(hour, currentPeriod)\n }\n if (value === undefined) {\n setInternalHours(newHours)\n }\n handleTimeChange(newHours, currentMinutes)\n }\n\n const handleMinuteSelect = (minute: number) => {\n if (value === undefined) {\n setInternalMinutes(minute)\n }\n handleTimeChange(currentHours, minute)\n }\n\n const handlePeriodSelect = (period: \"AM\" | \"PM\") => {\n if (value === undefined) {\n setInternalPeriod(period)\n }\n const hour12 = timeUse12Hour\n ? currentHours % 12 || 12\n : to12Hour(currentHours).hour12\n const newHours = to24Hour(hour12, period)\n if (value === undefined) {\n setInternalHours(newHours)\n }\n handleTimeChange(newHours, currentMinutes)\n }\n\n const handleOpenChange = (isOpen: boolean) => {\n // Don't open if readOnly\n if (readOnly && isOpen) return\n\n setOpen(isOpen)\n onOpenChange?.(isOpen)\n }\n\n const handleClear = (event: React.MouseEvent) => {\n event.stopPropagation()\n if (value === undefined) {\n setInternalDate(undefined)\n }\n onChange?.()\n onClear?.()\n }\n\n // Format display value with time if showTimePicker is enabled\n const displayValue = React.useMemo(() => {\n if (!selectedDate) return null\n\n const dateStr = formatDate(selectedDate, format, locale ? { locale } : undefined)\n\n if (showTimePicker) {\n const timeStr = timeUse12Hour\n ? `${String(to12Hour(currentHours).hour12)}:${currentMinutes.toString().padStart(2, \"0\")} ${currentPeriod}`\n : `${currentHours.toString().padStart(2, \"0\")}:${currentMinutes.toString().padStart(2, \"0\")}`\n return `${dateStr} ${timeStr}`\n }\n\n return dateStr\n }, [selectedDate, format, locale, showTimePicker, timeUse12Hour, currentHours, currentMinutes, currentPeriod])\n\n // Memoize time options\n const hourOptions = React.useMemo(() => getHourOptions(timeUse12Hour), [timeUse12Hour])\n const minuteOptions = React.useMemo(() => getMinuteOptions(timeMinuteStep), [timeMinuteStep])\n\n // Calculate display hour for matching in 12h mode\n const displayHour = timeUse12Hour\n ? to12Hour(currentHours).hour12\n : currentHours\n\n // Signal for the filled field state (date selected). The `filled` style\n // variant is independent — this is the data hook consumers/tests rely on.\n const hasValue = Boolean(selectedDate)\n\n const showClearButton = clearable && hasValue && !disabled && !readOnly\n\n // Combined date disabled check\n const isDateDisabled = React.useCallback(\n (date: Date): boolean => {\n const normalizedDate = startOfDay(date)\n if (minDate && isBefore(normalizedDate, startOfDay(minDate))) return true\n if (maxDate && isAfter(normalizedDate, startOfDay(maxDate))) return true\n if (disabledDates?.(date)) return true\n return false\n },\n [minDate, maxDate, disabledDates]\n )\n\n // Check if today is disabled\n const isTodayDisabled = React.useMemo(() => {\n return isDateDisabled(new Date())\n }, [isDateDisabled])\n\n // Handle selecting today\n const handleSelectToday = () => {\n const today = startOfDay(new Date())\n if (!isDateDisabled(today)) {\n handleSelect(today)\n }\n }\n\n return (\n <div className={cn(\"relative\", className)} data-slot=\"date-picker\" {...props}>\n <Popover open={open} onOpenChange={handleOpenChange}>\n <PopoverTrigger asChild>\n <button\n ref={ref}\n className={cn(\n datePickerTriggerVariants({ size, variant }),\n !displayValue && \"text-muted-foreground\"\n )}\n aria-describedby={ariaDescribedby}\n aria-disabled={readOnly || undefined}\n aria-expanded={open}\n aria-haspopup=\"dialog\"\n aria-invalid={invalid}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n aria-required={required}\n data-has-value={hasValue}\n data-readonly={readOnly || undefined}\n data-size={size}\n data-slot=\"date-picker-trigger\"\n data-state={open ? \"open\" : \"closed\"}\n data-variant={variant}\n disabled={disabled}\n id={id}\n type=\"button\"\n >\n <span className=\"flex-1 truncate\">\n {displayValue ?? placeholder}\n </span>\n <CalendarIcon\n aria-hidden=\"true\"\n className={cn(\"size-4 shrink-0 opacity-50\", showClearButton && \"invisible\")}\n />\n </button>\n </PopoverTrigger>\n <PopoverContent\n align={align}\n aria-label={dialogLabel}\n className=\"w-auto p-0\"\n data-slot=\"date-picker-calendar\"\n >\n <Calendar\n autoFocus\n footer={\n showToday ? (\n <div className=\"border-t border-border p-2\" data-slot=\"date-picker-footer\">\n <Button\n className=\"w-full\"\n disabled={isTodayDisabled}\n size=\"sm\"\n variant=\"ghost\"\n onClick={handleSelectToday}\n >\n {todayLabel}\n </Button>\n </div>\n ) : undefined\n }\n defaultMonth={defaultMonth}\n disabled={isDateDisabled}\n locale={locale}\n mode=\"single\"\n selected={selectedDate}\n onSelect={handleSelect}\n {...calendarProps}\n />\n\n {/* Time Picker Section */}\n {showTimePicker && (\n <div\n className=\"border-t border-border\"\n data-slot=\"date-picker-time\"\n >\n <div className=\"px-3 py-2 text-xs font-medium text-muted-foreground\">\n {timeLabel}\n </div>\n <div\n aria-label=\"Time selection\"\n className=\"flex divide-x border-t border-border\"\n role=\"listbox\"\n >\n {/* Hours Column */}\n <div className=\"flex flex-col\">\n <div className=\"px-2 py-1.5 text-xs font-medium text-muted-foreground text-center border-b\">\n {timeUse12Hour ? \"Hour\" : \"Hours\"}\n </div>\n <ScrollArea className=\"h-36\">\n <div\n ref={hourListRef}\n aria-label=\"Hours\"\n className=\"flex flex-col items-stretch p-1\"\n role=\"group\"\n >\n {hourOptions.map((hour) => {\n const isSelected = displayHour === hour\n return (\n <button\n key={hour}\n className={cn(\n \"flex h-8 w-12 items-center justify-center rounded-sm text-sm\",\n \"hover:bg-accent hover:text-accent-foreground\",\n \"focus:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n isSelected && \"bg-primary text-primary-foreground\"\n )}\n aria-selected={isSelected}\n data-selected={isSelected}\n role=\"option\"\n type=\"button\"\n onClick={() => { handleHourSelect(hour); }}\n >\n {timeUse12Hour ? hour : hour.toString().padStart(2, \"0\")}\n </button>\n )\n })}\n </div>\n </ScrollArea>\n </div>\n\n {/* Minutes Column */}\n <div className=\"flex flex-col\">\n <div className=\"px-2 py-1.5 text-xs font-medium text-muted-foreground text-center border-b\">\n Min\n </div>\n <ScrollArea className=\"h-36\">\n <div\n ref={minuteListRef}\n aria-label=\"Minutes\"\n className=\"flex flex-col items-stretch p-1\"\n role=\"group\"\n >\n {minuteOptions.map((minute) => {\n const isSelected = currentMinutes === minute\n return (\n <button\n key={minute}\n className={cn(\n \"flex h-8 w-12 items-center justify-center rounded-sm text-sm\",\n \"hover:bg-accent hover:text-accent-foreground\",\n \"focus:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n isSelected && \"bg-primary text-primary-foreground\"\n )}\n aria-selected={isSelected}\n data-selected={isSelected}\n role=\"option\"\n type=\"button\"\n onClick={() => { handleMinuteSelect(minute); }}\n >\n {minute.toString().padStart(2, \"0\")}\n </button>\n )\n })}\n </div>\n </ScrollArea>\n </div>\n\n {/* AM/PM Column (12-hour mode only) */}\n {timeUse12Hour && (\n <div className=\"flex flex-col\">\n <div className=\"px-2 py-1.5 text-xs font-medium text-muted-foreground text-center border-b\">\n &nbsp;\n </div>\n <div\n aria-label=\"Period\"\n className=\"flex flex-col items-stretch p-1\"\n role=\"group\"\n >\n {([\"AM\", \"PM\"] as const).map((period) => {\n const isSelected = currentPeriod === period\n return (\n <button\n key={period}\n className={cn(\n \"flex h-8 w-12 items-center justify-center rounded-sm text-sm\",\n \"hover:bg-accent hover:text-accent-foreground\",\n \"focus:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n isSelected && \"bg-primary text-primary-foreground\"\n )}\n aria-selected={isSelected}\n data-selected={isSelected}\n role=\"option\"\n type=\"button\"\n onClick={() => { handlePeriodSelect(period); }}\n >\n {period}\n </button>\n )\n })}\n </div>\n </div>\n )}\n </div>\n </div>\n )}\n </PopoverContent>\n </Popover>\n {showClearButton && (\n <button\n aria-label=\"Clear date\"\n className={cn(datePickerClearButtonVariants({ size, variant }))}\n data-slot=\"date-picker-clear\"\n type=\"button\"\n onClick={handleClear}\n >\n <XIcon className=\"size-4\" />\n </button>\n )}\n {name && (\n <input\n name={name}\n type=\"hidden\"\n value={selectedDate?.toISOString() ?? \"\"}\n />\n )}\n </div>\n )\n}\n\nexport { DatePicker }\n"]}
@@ -1,7 +1,7 @@
1
1
  import { Sparkline } from './chunk-2VHARFMD.js';
2
- import { Card, CardHeader, CardContent, CardTitle } from './chunk-K45MMHLA.js';
3
2
  import { ProgressBar } from './chunk-UFRMZ3M6.js';
4
3
  import { SkeletonLoader } from './chunk-QHKOBGLW.js';
4
+ import { Card, CardHeader, CardContent, CardTitle } from './chunk-K45MMHLA.js';
5
5
  import { Badge } from './chunk-TNROOKX3.js';
6
6
  import { cn } from './chunk-HRNDJU7D.js';
7
7
  import { Minus, ArrowDown, ArrowUp } from 'lucide-react';
@@ -222,5 +222,5 @@ function KPICardGroup({
222
222
  }
223
223
 
224
224
  export { KPICard, KPICardGroup };
225
- //# sourceMappingURL=chunk-32IJQOUV.js.map
226
- //# sourceMappingURL=chunk-32IJQOUV.js.map
225
+ //# sourceMappingURL=chunk-OTSK2KAI.js.map
226
+ //# sourceMappingURL=chunk-OTSK2KAI.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/data-display/KPICard/KPICard.tsx"],"names":[],"mappings":"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","file":"chunk-32IJQOUV.js","sourcesContent":["import type {\n KPICardGroupProps,\n KPICardProps,\n KPICardTrend,\n} from \"./KPICard.types\"\n\nimport { ArrowDown, ArrowUp, Minus } from \"lucide-react\"\n\nimport { cn } from \"../../../lib/utils\"\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n} from \"../../layout/Card\"\nimport { Badge } from \"../../primitives/Badge\"\nimport { ProgressBar } from \"../../primitives/ProgressBar\"\nimport { SkeletonLoader } from \"../../primitives/SkeletonLoader\"\nimport { Sparkline } from \"../Sparkline\"\n\n/**\n * Size configuration for typography\n */\nconst sizeConfig = {\n sm: {\n value: \"text-[length:var(--kpi-card-value-size-sm)] font-[number:var(--kpi-card-value-weight)]\",\n padding: \"p-4\",\n },\n md: {\n value: \"text-[length:var(--kpi-card-value-size-md)] font-[number:var(--kpi-card-value-weight)]\",\n padding: \"p-6\",\n },\n lg: {\n value: \"text-[length:var(--kpi-card-value-size-lg)] font-[number:var(--kpi-card-value-weight)]\",\n padding: \"p-6\",\n },\n} as const\n\n/**\n * Trend icons mapping\n */\nconst TrendIcons = {\n up: ArrowUp,\n down: ArrowDown,\n neutral: Minus,\n} as const\n\n/**\n * Trend colors mapping using design tokens\n */\nconst trendColors = {\n up: \"text-success\",\n down: \"text-destructive\",\n neutral: \"text-muted-foreground\",\n} as const\n\n/**\n * KPICard - Key Performance Indicator Card\n *\n * Dashboard component that displays important metrics prominently.\n * Combines main value, comparison/delta, mini chart, and contextual metadata\n * in a layout optimized for quick visualization.\n *\n * @example\n * ```tsx\n * <KPICard\n * title=\"Revenue\"\n * value=\"$45,231.89\"\n * delta={20.1}\n * deltaLabel=\"from last month\"\n * />\n * ```\n */\nfunction KPICard({\n title,\n value,\n delta,\n deltaLabel,\n trend,\n sparkline,\n icon,\n featuredIcon,\n dropdownIcon,\n helpText,\n progressBar,\n swap,\n showBadge = true,\n action,\n variant = \"default\",\n size = \"md\",\n loading = false,\n className,\n ...props\n}: KPICardProps) {\n // Auto-detect trend direction if not provided\n const computedTrend: KPICardTrend = trend ?? (delta !== undefined\n ? delta > 0 ? \"up\" : delta < 0 ? \"down\" : \"neutral\"\n : \"neutral\")\n\n const TrendIcon = TrendIcons[computedTrend]\n const trendColor = trendColors[computedTrend]\n const sizeStyles = sizeConfig[size]\n const sparklineColor =\n computedTrend === \"up\"\n ? \"var(--kpi-card-sparkline-up)\"\n : computedTrend === \"down\"\n ? \"var(--kpi-card-sparkline-down)\"\n : \"var(--kpi-card-sparkline-neutral)\"\n\n // Variant styles\n const variantStyles = {\n default: \"\",\n ghost: \"border-none shadow-none bg-transparent\",\n highlight: \"border-primary/50 bg-primary/5\",\n }\n\n if (loading) {\n return (\n <Card\n className={cn(variantStyles[variant], className)}\n data-slot=\"kpi-card\"\n {...props}\n >\n <CardHeader className=\"flex flex-row items-center justify-between pb-2\">\n <SkeletonLoader className=\"h-4 w-24\" />\n <SkeletonLoader className=\"size-4\" />\n </CardHeader>\n <CardContent>\n <SkeletonLoader className=\"mb-2 h-8 w-32\" />\n <SkeletonLoader className=\"h-4 w-20\" />\n </CardContent>\n </Card>\n )\n }\n\n return (\n <Card\n className={cn(variantStyles[variant], className)}\n data-slot=\"kpi-card\"\n {...props}\n >\n <CardHeader className=\"flex flex-row items-center justify-between pb-2\">\n <div className=\"flex items-center gap-1.5\">\n <CardTitle className=\"text-sm font-medium text-muted-foreground\">\n {title}\n </CardTitle>\n {helpText && (\n <span\n className=\"text-xs text-muted-foreground\"\n data-slot=\"kpi-card-help-text\"\n >\n {helpText}\n </span>\n )}\n </div>\n <div className=\"flex items-center gap-2\">\n {featuredIcon && (\n <span\n className=\"inline-flex size-10 items-center justify-center rounded-full bg-primary/10 text-primary [&_svg]:size-5\"\n data-slot=\"kpi-card-featured-icon\"\n >\n {featuredIcon}\n </span>\n )}\n {icon && !featuredIcon && (\n <span className=\"text-muted-foreground\" data-slot=\"kpi-card-icon\">\n {icon}\n </span>\n )}\n {dropdownIcon && (\n <span\n className=\"text-muted-foreground\"\n data-slot=\"kpi-card-dropdown-icon\"\n >\n {dropdownIcon}\n </span>\n )}\n {action && !icon && !featuredIcon && !dropdownIcon && (\n <span data-slot=\"kpi-card-action\">{action}</span>\n )}\n </div>\n </CardHeader>\n <CardContent>\n <div className=\"flex items-end justify-between\">\n <div>\n <div\n className={cn(sizeStyles.value, \"tabular-nums\")}\n data-slot=\"kpi-card-value\"\n >\n {value}\n </div>\n {delta !== undefined && (\n <div\n className={cn(\"mt-1 flex items-center gap-2\", trendColor)}\n data-slot=\"kpi-card-delta\"\n data-trend={computedTrend}\n >\n {showBadge ? (\n <Badge\n color={\n computedTrend === \"up\"\n ? \"success\"\n : computedTrend === \"down\"\n ? \"destructive\"\n : \"muted\"\n }\n leadingIcon={<TrendIcon aria-hidden=\"true\" />}\n size=\"sm\"\n type=\"pill-color\"\n >\n {Math.abs(delta)}%\n </Badge>\n ) : (\n <span className={cn(\"flex items-center text-xs\", trendColor)}>\n <TrendIcon aria-hidden=\"true\" className=\"mr-1 size-3\" />\n <span className=\"font-medium\">{Math.abs(delta)}%</span>\n </span>\n )}\n {deltaLabel && (\n <span className=\"text-xs text-muted-foreground\">\n {deltaLabel}\n </span>\n )}\n {swap && (\n <span className=\"ml-auto\" data-slot=\"kpi-card-swap\">\n {swap}\n </span>\n )}\n </div>\n )}\n </div>\n {sparkline && sparkline.length > 0 && (\n <Sparkline\n aria-hidden=\"true\"\n color={sparklineColor}\n data={sparkline}\n data-slot=\"kpi-card-sparkline\"\n height={32}\n style={{ opacity: \"var(--kpi-card-sparkline-opacity)\" }}\n variant=\"bar\"\n width={96}\n />\n )}\n </div>\n {progressBar !== undefined && (\n <div className=\"mt-3\" data-slot=\"kpi-card-progress\">\n {typeof progressBar === \"number\" ? (\n <ProgressBar value={progressBar} />\n ) : (\n progressBar\n )}\n </div>\n )}\n </CardContent>\n {/* Screen reader summary */}\n <span className=\"sr-only\">\n {title}: {value}\n {delta !== undefined && `, ${computedTrend === \"up\" ? \"up\" : computedTrend === \"down\" ? \"down\" : \"unchanged\"} ${String(Math.abs(delta))}%`}\n {deltaLabel && ` ${deltaLabel}`}\n </span>\n </Card>\n )\n}\n\n/**\n * KPICardGroup — Multiple KPIs composition (Figma Type=Multiple KPIs)\n *\n * Wrapper que diagramra múltiplos `KPICard` em layout horizontal ou vertical.\n *\n * @example\n * ```tsx\n * <KPICardGroup orientation=\"horizontal\" gap=\"md\">\n * <KPICard title=\"Revenue\" value=\"$45k\" delta={12} />\n * <KPICard title=\"Orders\" value={1240} delta={-3} />\n * <KPICard title=\"Users\" value={892} delta={8} />\n * </KPICardGroup>\n * ```\n */\nfunction KPICardGroup({\n children,\n orientation = \"horizontal\",\n gap = \"md\",\n className,\n ...props\n}: KPICardGroupProps) {\n const gapClasses = {\n sm: \"gap-2\",\n md: \"gap-4\",\n lg: \"gap-6\",\n } as const\n\n return (\n <div\n className={cn(\n \"flex\",\n orientation === \"horizontal\"\n ? \"flex-row [&>*]:flex-1\"\n : \"flex-col\",\n gapClasses[gap],\n className\n )}\n data-orientation={orientation}\n data-slot=\"kpi-card-group\"\n {...props}\n >\n {children}\n </div>\n )\n}\n\nexport { KPICard, KPICardGroup }\n"]}
1
+ {"version":3,"sources":["../src/components/data-display/KPICard/KPICard.tsx"],"names":[],"mappings":"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","file":"chunk-OTSK2KAI.js","sourcesContent":["import type {\n KPICardGroupProps,\n KPICardProps,\n KPICardTrend,\n} from \"./KPICard.types\"\n\nimport { ArrowDown, ArrowUp, Minus } from \"lucide-react\"\n\nimport { cn } from \"../../../lib/utils\"\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n} from \"../../layout/Card\"\nimport { Badge } from \"../../primitives/Badge\"\nimport { ProgressBar } from \"../../primitives/ProgressBar\"\nimport { SkeletonLoader } from \"../../primitives/SkeletonLoader\"\nimport { Sparkline } from \"../Sparkline\"\n\n/**\n * Size configuration for typography\n */\nconst sizeConfig = {\n sm: {\n value: \"text-[length:var(--kpi-card-value-size-sm)] font-[number:var(--kpi-card-value-weight)]\",\n padding: \"p-4\",\n },\n md: {\n value: \"text-[length:var(--kpi-card-value-size-md)] font-[number:var(--kpi-card-value-weight)]\",\n padding: \"p-6\",\n },\n lg: {\n value: \"text-[length:var(--kpi-card-value-size-lg)] font-[number:var(--kpi-card-value-weight)]\",\n padding: \"p-6\",\n },\n} as const\n\n/**\n * Trend icons mapping\n */\nconst TrendIcons = {\n up: ArrowUp,\n down: ArrowDown,\n neutral: Minus,\n} as const\n\n/**\n * Trend colors mapping using design tokens\n */\nconst trendColors = {\n up: \"text-success\",\n down: \"text-destructive\",\n neutral: \"text-muted-foreground\",\n} as const\n\n/**\n * KPICard - Key Performance Indicator Card\n *\n * Dashboard component that displays important metrics prominently.\n * Combines main value, comparison/delta, mini chart, and contextual metadata\n * in a layout optimized for quick visualization.\n *\n * @example\n * ```tsx\n * <KPICard\n * title=\"Revenue\"\n * value=\"$45,231.89\"\n * delta={20.1}\n * deltaLabel=\"from last month\"\n * />\n * ```\n */\nfunction KPICard({\n title,\n value,\n delta,\n deltaLabel,\n trend,\n sparkline,\n icon,\n featuredIcon,\n dropdownIcon,\n helpText,\n progressBar,\n swap,\n showBadge = true,\n action,\n variant = \"default\",\n size = \"md\",\n loading = false,\n className,\n ...props\n}: KPICardProps) {\n // Auto-detect trend direction if not provided\n const computedTrend: KPICardTrend = trend ?? (delta !== undefined\n ? delta > 0 ? \"up\" : delta < 0 ? \"down\" : \"neutral\"\n : \"neutral\")\n\n const TrendIcon = TrendIcons[computedTrend]\n const trendColor = trendColors[computedTrend]\n const sizeStyles = sizeConfig[size]\n const sparklineColor =\n computedTrend === \"up\"\n ? \"var(--kpi-card-sparkline-up)\"\n : computedTrend === \"down\"\n ? \"var(--kpi-card-sparkline-down)\"\n : \"var(--kpi-card-sparkline-neutral)\"\n\n // Variant styles\n const variantStyles = {\n default: \"\",\n ghost: \"border-none shadow-none bg-transparent\",\n highlight: \"border-primary/50 bg-primary/5\",\n }\n\n if (loading) {\n return (\n <Card\n className={cn(variantStyles[variant], className)}\n data-slot=\"kpi-card\"\n {...props}\n >\n <CardHeader className=\"flex flex-row items-center justify-between pb-2\">\n <SkeletonLoader className=\"h-4 w-24\" />\n <SkeletonLoader className=\"size-4\" />\n </CardHeader>\n <CardContent>\n <SkeletonLoader className=\"mb-2 h-8 w-32\" />\n <SkeletonLoader className=\"h-4 w-20\" />\n </CardContent>\n </Card>\n )\n }\n\n return (\n <Card\n className={cn(variantStyles[variant], className)}\n data-slot=\"kpi-card\"\n {...props}\n >\n <CardHeader className=\"flex flex-row items-center justify-between pb-2\">\n <div className=\"flex items-center gap-1.5\">\n <CardTitle className=\"text-sm font-medium text-muted-foreground\">\n {title}\n </CardTitle>\n {helpText && (\n <span\n className=\"text-xs text-muted-foreground\"\n data-slot=\"kpi-card-help-text\"\n >\n {helpText}\n </span>\n )}\n </div>\n <div className=\"flex items-center gap-2\">\n {featuredIcon && (\n <span\n className=\"inline-flex size-10 items-center justify-center rounded-full bg-primary/10 text-primary [&_svg]:size-5\"\n data-slot=\"kpi-card-featured-icon\"\n >\n {featuredIcon}\n </span>\n )}\n {icon && !featuredIcon && (\n <span className=\"text-muted-foreground\" data-slot=\"kpi-card-icon\">\n {icon}\n </span>\n )}\n {dropdownIcon && (\n <span\n className=\"text-muted-foreground\"\n data-slot=\"kpi-card-dropdown-icon\"\n >\n {dropdownIcon}\n </span>\n )}\n {action && !icon && !featuredIcon && !dropdownIcon && (\n <span data-slot=\"kpi-card-action\">{action}</span>\n )}\n </div>\n </CardHeader>\n <CardContent>\n <div className=\"flex items-end justify-between\">\n <div>\n <div\n className={cn(sizeStyles.value, \"tabular-nums\")}\n data-slot=\"kpi-card-value\"\n >\n {value}\n </div>\n {delta !== undefined && (\n <div\n className={cn(\"mt-1 flex items-center gap-2\", trendColor)}\n data-slot=\"kpi-card-delta\"\n data-trend={computedTrend}\n >\n {showBadge ? (\n <Badge\n color={\n computedTrend === \"up\"\n ? \"success\"\n : computedTrend === \"down\"\n ? \"destructive\"\n : \"muted\"\n }\n leadingIcon={<TrendIcon aria-hidden=\"true\" />}\n size=\"sm\"\n type=\"pill-color\"\n >\n {Math.abs(delta)}%\n </Badge>\n ) : (\n <span className={cn(\"flex items-center text-xs\", trendColor)}>\n <TrendIcon aria-hidden=\"true\" className=\"mr-1 size-3\" />\n <span className=\"font-medium\">{Math.abs(delta)}%</span>\n </span>\n )}\n {deltaLabel && (\n <span className=\"text-xs text-muted-foreground\">\n {deltaLabel}\n </span>\n )}\n {swap && (\n <span className=\"ml-auto\" data-slot=\"kpi-card-swap\">\n {swap}\n </span>\n )}\n </div>\n )}\n </div>\n {sparkline && sparkline.length > 0 && (\n <Sparkline\n aria-hidden=\"true\"\n color={sparklineColor}\n data={sparkline}\n data-slot=\"kpi-card-sparkline\"\n height={32}\n style={{ opacity: \"var(--kpi-card-sparkline-opacity)\" }}\n variant=\"bar\"\n width={96}\n />\n )}\n </div>\n {progressBar !== undefined && (\n <div className=\"mt-3\" data-slot=\"kpi-card-progress\">\n {typeof progressBar === \"number\" ? (\n <ProgressBar value={progressBar} />\n ) : (\n progressBar\n )}\n </div>\n )}\n </CardContent>\n {/* Screen reader summary */}\n <span className=\"sr-only\">\n {title}: {value}\n {delta !== undefined && `, ${computedTrend === \"up\" ? \"up\" : computedTrend === \"down\" ? \"down\" : \"unchanged\"} ${String(Math.abs(delta))}%`}\n {deltaLabel && ` ${deltaLabel}`}\n </span>\n </Card>\n )\n}\n\n/**\n * KPICardGroup — Multiple KPIs composition (Figma Type=Multiple KPIs)\n *\n * Wrapper que diagramra múltiplos `KPICard` em layout horizontal ou vertical.\n *\n * @example\n * ```tsx\n * <KPICardGroup orientation=\"horizontal\" gap=\"md\">\n * <KPICard title=\"Revenue\" value=\"$45k\" delta={12} />\n * <KPICard title=\"Orders\" value={1240} delta={-3} />\n * <KPICard title=\"Users\" value={892} delta={8} />\n * </KPICardGroup>\n * ```\n */\nfunction KPICardGroup({\n children,\n orientation = \"horizontal\",\n gap = \"md\",\n className,\n ...props\n}: KPICardGroupProps) {\n const gapClasses = {\n sm: \"gap-2\",\n md: \"gap-4\",\n lg: \"gap-6\",\n } as const\n\n return (\n <div\n className={cn(\n \"flex\",\n orientation === \"horizontal\"\n ? \"flex-row [&>*]:flex-1\"\n : \"flex-col\",\n gapClasses[gap],\n className\n )}\n data-orientation={orientation}\n data-slot=\"kpi-card-group\"\n {...props}\n >\n {children}\n </div>\n )\n}\n\nexport { KPICard, KPICardGroup }\n"]}