@enact-ui/charts 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/api-schema.json +169 -0
  2. package/dist/__tests__/recharts-mock.d.ts +2 -0
  3. package/dist/__tests__/recharts-mock.d.ts.map +1 -0
  4. package/dist/__tests__/recharts-mock.js +19 -0
  5. package/dist/__tests__/recharts-mock.js.map +1 -0
  6. package/dist/__tests__/test-utils.d.ts +76 -0
  7. package/dist/__tests__/test-utils.d.ts.map +1 -0
  8. package/dist/__tests__/test-utils.js +89 -0
  9. package/dist/__tests__/test-utils.js.map +1 -0
  10. package/dist/components/activity-gauges.demo.d.ts +5 -0
  11. package/dist/components/activity-gauges.demo.d.ts.map +1 -1
  12. package/dist/components/activity-gauges.demo.js +25 -11
  13. package/dist/components/activity-gauges.demo.js.map +1 -1
  14. package/dist/components/activity-gauges.story.d.ts +6 -22
  15. package/dist/components/activity-gauges.story.d.ts.map +1 -1
  16. package/dist/components/activity-gauges.story.js +19 -11
  17. package/dist/components/activity-gauges.story.js.map +1 -1
  18. package/dist/components/bar-charts.demo.d.ts +6 -0
  19. package/dist/components/bar-charts.demo.d.ts.map +1 -1
  20. package/dist/components/bar-charts.demo.js +24 -11
  21. package/dist/components/bar-charts.demo.js.map +1 -1
  22. package/dist/components/bar-charts.story.d.ts +6 -18
  23. package/dist/components/bar-charts.story.d.ts.map +1 -1
  24. package/dist/components/bar-charts.story.js +19 -9
  25. package/dist/components/bar-charts.story.js.map +1 -1
  26. package/dist/components/charts-base.d.ts +0 -8
  27. package/dist/components/charts-base.d.ts.map +1 -1
  28. package/dist/components/charts-base.js +2 -28
  29. package/dist/components/charts-base.js.map +1 -1
  30. package/dist/components/line-charts.demo.d.ts +6 -0
  31. package/dist/components/line-charts.demo.d.ts.map +1 -1
  32. package/dist/components/line-charts.demo.js +32 -18
  33. package/dist/components/line-charts.demo.js.map +1 -1
  34. package/dist/components/line-charts.story.d.ts +6 -22
  35. package/dist/components/line-charts.story.d.ts.map +1 -1
  36. package/dist/components/line-charts.story.js +19 -11
  37. package/dist/components/line-charts.story.js.map +1 -1
  38. package/dist/components/pie-charts.demo.d.ts +5 -0
  39. package/dist/components/pie-charts.demo.d.ts.map +1 -1
  40. package/dist/components/pie-charts.demo.js +20 -4
  41. package/dist/components/pie-charts.demo.js.map +1 -1
  42. package/dist/components/pie-charts.story.d.ts +6 -26
  43. package/dist/components/pie-charts.story.d.ts.map +1 -1
  44. package/dist/components/pie-charts.story.js +19 -13
  45. package/dist/components/pie-charts.story.js.map +1 -1
  46. package/dist/components/progress-circles.demo.d.ts +7 -0
  47. package/dist/components/progress-circles.demo.d.ts.map +1 -1
  48. package/dist/components/progress-circles.demo.js +11 -6
  49. package/dist/components/progress-circles.demo.js.map +1 -1
  50. package/dist/components/progress-circles.story.d.ts +6 -38
  51. package/dist/components/progress-circles.story.d.ts.map +1 -1
  52. package/dist/components/progress-circles.story.js +23 -19
  53. package/dist/components/progress-circles.story.js.map +1 -1
  54. package/dist/components/radar-charts.demo.d.ts +6 -3
  55. package/dist/components/radar-charts.demo.d.ts.map +1 -1
  56. package/dist/components/radar-charts.demo.js +18 -10
  57. package/dist/components/radar-charts.demo.js.map +1 -1
  58. package/dist/components/radar-charts.story.d.ts +6 -10
  59. package/dist/components/radar-charts.story.d.ts.map +1 -1
  60. package/dist/components/radar-charts.story.js +10 -5
  61. package/dist/components/radar-charts.story.js.map +1 -1
  62. package/dist/components/relationship-graph.d.ts +64 -0
  63. package/dist/components/relationship-graph.d.ts.map +1 -0
  64. package/dist/components/relationship-graph.demo.d.ts +2 -0
  65. package/dist/components/relationship-graph.demo.d.ts.map +1 -0
  66. package/dist/components/relationship-graph.demo.js +61 -0
  67. package/dist/components/relationship-graph.demo.js.map +1 -0
  68. package/dist/components/relationship-graph.js +381 -0
  69. package/dist/components/relationship-graph.js.map +1 -0
  70. package/dist/components/relationship-graph.story.d.ts +6 -0
  71. package/dist/components/relationship-graph.story.d.ts.map +1 -0
  72. package/dist/components/relationship-graph.story.js +13 -0
  73. package/dist/components/relationship-graph.story.js.map +1 -0
  74. package/dist/components/trend-indicator.d.ts +40 -0
  75. package/dist/components/trend-indicator.d.ts.map +1 -0
  76. package/dist/components/trend-indicator.demo.d.ts +2 -0
  77. package/dist/components/trend-indicator.demo.d.ts.map +1 -0
  78. package/dist/components/trend-indicator.demo.js +7 -0
  79. package/dist/components/trend-indicator.demo.js.map +1 -0
  80. package/dist/components/trend-indicator.js +50 -0
  81. package/dist/components/trend-indicator.js.map +1 -0
  82. package/dist/components/trend-indicator.story.d.ts +6 -0
  83. package/dist/components/trend-indicator.story.d.ts.map +1 -0
  84. package/dist/components/trend-indicator.story.js +13 -0
  85. package/dist/components/trend-indicator.story.js.map +1 -0
  86. package/dist/index.d.ts +9 -1
  87. package/dist/index.d.ts.map +1 -1
  88. package/dist/index.js +1852 -9
  89. package/dist/index.js.map +1 -1
  90. package/dist/index.mjs +1837 -9
  91. package/dist/index.mjs.map +1 -1
  92. package/dist/utils/chart-utils.d.ts +9 -0
  93. package/dist/utils/chart-utils.d.ts.map +1 -0
  94. package/dist/utils/chart-utils.js +26 -0
  95. package/dist/utils/chart-utils.js.map +1 -0
  96. package/package.json +8 -3
package/dist/index.mjs CHANGED
@@ -1,6 +1,8 @@
1
- // src/components/charts-base.tsx
2
- import { cx } from "@enact-ui/react";
3
- import { jsx, jsxs } from "react/jsx-runtime";
1
+ // src/components/bar-charts.demo.tsx
2
+ import { useBreakpoint } from "@enact-ui/react";
3
+ import { Bar, CartesianGrid, ComposedChart, Label, Legend, Line, BarChart as RechartsBarChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts";
4
+
5
+ // src/utils/chart-utils.ts
4
6
  var selectEvenlySpacedItems = (dataArray, count) => {
5
7
  if (!dataArray || dataArray.length === 0) {
6
8
  return [];
@@ -19,6 +21,10 @@ var selectEvenlySpacedItems = (dataArray, count) => {
19
21
  }
20
22
  return selectedItems;
21
23
  };
24
+
25
+ // src/components/charts-base.tsx
26
+ import { cx } from "@enact-ui/react";
27
+ import { jsx, jsxs } from "react/jsx-runtime";
22
28
  var ChartLegendContent = ({ reversed, payload, align, layout, className }) => {
23
29
  payload = reversed ? payload?.toReversed() : payload;
24
30
  return /* @__PURE__ */ jsx(
@@ -29,7 +35,7 @@ var ChartLegendContent = ({ reversed, payload, align, layout, className }) => {
29
35
  layout === "vertical" ? `flex-col gap-1 pl-4 ${align === "center" ? "items-center" : align === "right" ? "items-start" : "items-start"}` : `flex-row gap-3 ${align === "center" ? "justify-center" : align === "right" ? "justify-end" : "justify-start"}`,
30
36
  className
31
37
  ),
32
- children: payload?.map((entry, index) => /* @__PURE__ */ jsxs("li", { className: "text-muted flex items-center gap-2 text-sm", children: [
38
+ children: payload?.map((entry, index) => /* @__PURE__ */ jsxs("li", { className: "text-content-tertiary flex items-center gap-2 text-sm", children: [
33
39
  /* @__PURE__ */ jsx("span", { className: cx("h-2 w-2 rounded-full bg-current", entry.payload?.className) }),
34
40
  entry.value
35
41
  ] }, entry.value ?? index))
@@ -46,22 +52,1844 @@ var ChartTooltipContent = ({ active, payload, label, isRadialChart, isPieChart,
46
52
  let secondaryTitle = isSingleDataPoint ? isRadialChart ? payload[0].payload.name : isPieChart ? payload[0].name : label : payload;
47
53
  title = isSingleDataPoint && formatter ? formatter(title, payload?.[0].name || label, payload[0], 0, payload) : labelFormatter ? labelFormatter(title, payload) : title;
48
54
  secondaryTitle = isSingleDataPoint && labelFormatter ? labelFormatter(secondaryTitle, payload) : secondaryTitle;
49
- return /* @__PURE__ */ jsxs("div", { className: "bg-base-solid flex flex-col gap-0.5 rounded-lg px-3 py-2 shadow-lg", children: [
50
- /* @__PURE__ */ jsx("p", { className: "text-xs font-semibold text-white", children: title }),
51
- !secondaryTitle ? null : Array.isArray(secondaryTitle) ? /* @__PURE__ */ jsx("div", { children: secondaryTitle.map((entry, index) => /* @__PURE__ */ jsx("p", { className: cx("text-xs text-tooltip-supporting-text"), children: `${entry.name}: ${formatter ? formatter(entry.value, entry.name, entry, index, entry.payload) : entry.value}` }, entry.name ?? index)) }) : /* @__PURE__ */ jsx("p", { className: "text-xs text-tooltip-supporting-text", children: secondaryTitle })
55
+ return /* @__PURE__ */ jsxs("div", { className: "bg-primary-solid flex flex-col gap-0.5 rounded-lg px-3 py-2 shadow-lg", children: [
56
+ /* @__PURE__ */ jsx("p", { className: "text-xs font-semibold text-content-on-brand", children: title }),
57
+ !secondaryTitle ? null : Array.isArray(secondaryTitle) ? /* @__PURE__ */ jsx("div", { children: secondaryTitle.map((entry, index) => /* @__PURE__ */ jsx("p", { className: cx("text-xs text-content-tertiary"), children: `${entry.name}: ${formatter ? formatter(entry.value, entry.name, entry, index, entry.payload) : entry.value}` }, entry.name ?? index)) }) : /* @__PURE__ */ jsx("p", { className: "text-xs text-content-tertiary", children: secondaryTitle })
52
58
  ] });
53
59
  };
54
- var ChartActiveDot = ({ cx: cx2 = 0, cy = 0 }) => {
60
+ var ChartActiveDot = ({ cx: cx5 = 0, cy = 0 }) => {
55
61
  const size = 12;
56
- return /* @__PURE__ */ jsxs("svg", { x: cx2 - size / 2, y: cy - size / 2, width: size, height: size, viewBox: "0 0 12 12", fill: "none", children: [
62
+ return /* @__PURE__ */ jsxs("svg", { x: cx5 - size / 2, y: cy - size / 2, width: size, height: size, viewBox: "0 0 12 12", fill: "none", children: [
57
63
  /* @__PURE__ */ jsx("title", { children: "Active data point indicator" }),
58
64
  /* @__PURE__ */ jsx("rect", { x: "2", y: "2", width: "8", height: "8", rx: "6", className: "stroke-brand-medium fill-bg-base", strokeWidth: "2" })
59
65
  ] });
60
66
  };
67
+
68
+ // src/components/bar-charts.demo.tsx
69
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
70
+ var barData = [
71
+ // collapse-start
72
+ {
73
+ month: new Date(2025, 0, 1),
74
+ A: 300,
75
+ B: 200,
76
+ C: 350
77
+ },
78
+ {
79
+ month: new Date(2025, 1, 1),
80
+ A: 320,
81
+ B: 300,
82
+ C: 300
83
+ },
84
+ {
85
+ month: new Date(2025, 2, 1),
86
+ A: 300,
87
+ B: 200,
88
+ C: 240
89
+ },
90
+ {
91
+ month: new Date(2025, 3, 1),
92
+ A: 240,
93
+ B: 300,
94
+ C: 280
95
+ },
96
+ {
97
+ month: new Date(2025, 4, 1),
98
+ A: 320,
99
+ B: 280,
100
+ C: 100
101
+ },
102
+ {
103
+ month: new Date(2025, 5, 1),
104
+ A: 330,
105
+ B: 300,
106
+ C: 130
107
+ },
108
+ {
109
+ month: new Date(2025, 6, 1),
110
+ A: 300,
111
+ B: 200,
112
+ C: 100
113
+ },
114
+ {
115
+ month: new Date(2025, 7, 1),
116
+ A: 350,
117
+ B: 300,
118
+ C: 200
119
+ },
120
+ {
121
+ month: new Date(2025, 8, 1),
122
+ A: 300,
123
+ B: 200,
124
+ C: 100
125
+ },
126
+ {
127
+ month: new Date(2025, 9, 1),
128
+ A: 200,
129
+ B: 300,
130
+ C: 280
131
+ },
132
+ {
133
+ month: new Date(2025, 10, 1),
134
+ A: 240,
135
+ B: 300,
136
+ C: 300
137
+ },
138
+ {
139
+ month: new Date(2025, 11, 1),
140
+ A: 200,
141
+ B: 400,
142
+ C: 350
143
+ }
144
+ // collapse-end
145
+ ];
146
+ var BarChart = () => {
147
+ const isDesktop = useBreakpoint("lg");
148
+ const colors = {
149
+ A: "text-content-brand",
150
+ B: "text-content-brand",
151
+ C: "text-content-tertiary"
152
+ };
153
+ return /* @__PURE__ */ jsx2(ResponsiveContainer, { className: "h-60!", children: /* @__PURE__ */ jsxs2(
154
+ RechartsBarChart,
155
+ {
156
+ data: barData,
157
+ className: "text-content-tertiary [&_.recharts-text]:text-xs",
158
+ margin: {
159
+ left: 4,
160
+ right: 0,
161
+ top: isDesktop ? 12 : 6,
162
+ bottom: 18
163
+ },
164
+ children: [
165
+ /* @__PURE__ */ jsx2(CartesianGrid, { vertical: false, stroke: "currentColor", className: "text-content-tertiary" }),
166
+ /* @__PURE__ */ jsx2(
167
+ Legend,
168
+ {
169
+ verticalAlign: "top",
170
+ align: "right",
171
+ layout: isDesktop ? "vertical" : "horizontal",
172
+ content: /* @__PURE__ */ jsx2(ChartLegendContent, { className: "-translate-y-2" })
173
+ }
174
+ ),
175
+ /* @__PURE__ */ jsx2(
176
+ XAxis,
177
+ {
178
+ fill: "currentColor",
179
+ axisLine: false,
180
+ tickLine: false,
181
+ tickMargin: 11,
182
+ interval: "preserveStartEnd",
183
+ dataKey: "month",
184
+ tickFormatter: (value) => value.toLocaleDateString(void 0, { month: "short" }),
185
+ children: /* @__PURE__ */ jsx2(Label, { value: "Month", fill: "currentColor", className: "!text-xs font-medium", position: "bottom" })
186
+ }
187
+ ),
188
+ /* @__PURE__ */ jsx2(
189
+ YAxis,
190
+ {
191
+ fill: "currentColor",
192
+ axisLine: false,
193
+ tickLine: false,
194
+ interval: "preserveStartEnd",
195
+ tickFormatter: (value) => Number(value).toLocaleString(),
196
+ children: /* @__PURE__ */ jsx2(
197
+ Label,
198
+ {
199
+ value: "Active users",
200
+ fill: "currentColor",
201
+ className: "!text-xs font-medium",
202
+ style: { textAnchor: "middle" },
203
+ angle: -90,
204
+ position: "insideLeft"
205
+ }
206
+ )
207
+ }
208
+ ),
209
+ /* @__PURE__ */ jsx2(
210
+ Tooltip,
211
+ {
212
+ content: /* @__PURE__ */ jsx2(ChartTooltipContent, {}),
213
+ formatter: (value) => Number(value).toLocaleString(),
214
+ labelFormatter: (value) => value.toLocaleDateString(void 0, { month: "short", year: "numeric" }),
215
+ cursor: {
216
+ className: "fill-gray-light_hover/20"
217
+ }
218
+ }
219
+ ),
220
+ /* @__PURE__ */ jsx2(
221
+ Bar,
222
+ {
223
+ isAnimationActive: false,
224
+ ...colors.A !== void 0 && { className: colors.A },
225
+ dataKey: "A",
226
+ name: "Series 1",
227
+ type: "monotone",
228
+ stackId: "a",
229
+ fill: "currentColor",
230
+ maxBarSize: isDesktop ? 32 : 16
231
+ }
232
+ ),
233
+ /* @__PURE__ */ jsx2(
234
+ Bar,
235
+ {
236
+ isAnimationActive: false,
237
+ ...colors.B !== void 0 && { className: colors.B },
238
+ dataKey: "B",
239
+ name: "Series 2",
240
+ type: "monotone",
241
+ stackId: "a",
242
+ fill: "currentColor",
243
+ maxBarSize: isDesktop ? 32 : 16
244
+ }
245
+ ),
246
+ /* @__PURE__ */ jsx2(
247
+ Bar,
248
+ {
249
+ isAnimationActive: false,
250
+ ...colors.C !== void 0 && { className: colors.C },
251
+ dataKey: "C",
252
+ name: "Series 3",
253
+ type: "monotone",
254
+ stackId: "a",
255
+ fill: "currentColor",
256
+ maxBarSize: isDesktop ? 32 : 16,
257
+ radius: [6, 6, 0, 0]
258
+ }
259
+ )
260
+ ]
261
+ }
262
+ ) });
263
+ };
264
+ var BarChart02 = () => {
265
+ const colors = {
266
+ A: "text-content-brand",
267
+ B: "text-brand-subtle"
268
+ };
269
+ const data = [
270
+ // collapse-start
271
+ { A: 633, B: 190, date: "2025-01-01" },
272
+ { A: 443, B: 228, date: "2025-01-08" },
273
+ { A: 506, B: 225, date: "2025-01-15" },
274
+ { A: 316, B: 227, date: "2025-01-22" },
275
+ { A: 760, B: 209, date: "2025-01-29" },
276
+ { A: 950, B: 220, date: "2025-02-05" },
277
+ { A: 760, B: 224, date: "2025-02-12" },
278
+ { A: 570, B: 279, date: "2025-02-19" },
279
+ { A: 253, B: 296, date: "2025-02-26" },
280
+ { A: 380, B: 263, date: "2025-03-05" },
281
+ { A: 443, B: 333, date: "2025-03-12" },
282
+ { A: 443, B: 306, date: "2025-03-19" },
283
+ { A: 316, B: 315, date: "2025-03-26" },
284
+ { A: 190, B: 325, date: "2025-04-02" },
285
+ { A: 380, B: 367, date: "2025-04-09" },
286
+ { A: 506, B: 372, date: "2025-04-16" },
287
+ { A: 443, B: 374, date: "2025-04-23" },
288
+ { A: 696, B: 278, date: "2025-04-30" },
289
+ { A: 950, B: 258, date: "2025-05-07" },
290
+ { A: 633, B: 357, date: "2025-05-14" },
291
+ { A: 570, B: 372, date: "2025-05-21" },
292
+ { A: 253, B: 404, date: "2025-05-28" },
293
+ { A: 316, B: 314, date: "2025-06-04" },
294
+ { A: 380, B: 359, date: "2025-06-11" },
295
+ { A: 253, B: 400, date: "2025-06-18" },
296
+ { A: 190, B: 381, date: "2025-06-25" },
297
+ { A: 316, B: 427, date: "2025-07-02" },
298
+ { A: 633, B: 371, date: "2025-07-09" },
299
+ { A: 570, B: 382, date: "2025-07-16" },
300
+ { A: 760, B: 383, date: "2025-07-23" },
301
+ { A: 950, B: 361, date: "2025-07-30" },
302
+ { A: 696, B: 405, date: "2025-08-06" },
303
+ { A: 570, B: 400, date: "2025-08-13" },
304
+ { A: 443, B: 391, date: "2025-08-20" },
305
+ { A: 316, B: 425, date: "2025-08-27" },
306
+ { A: 253, B: 406, date: "2025-09-03" },
307
+ { A: 380, B: 472, date: "2025-09-10" },
308
+ { A: 633, B: 477, date: "2025-09-17" },
309
+ { A: 570, B: 465, date: "2025-09-24" },
310
+ { A: 443, B: 488, date: "2025-10-01" },
311
+ { A: 380, B: 501, date: "2025-10-08" },
312
+ { A: 316, B: 615, date: "2025-10-15" },
313
+ { A: 570, B: 612, date: "2025-10-22" },
314
+ { A: 506, B: 673, date: "2025-10-29" },
315
+ { A: 443, B: 630, date: "2025-11-05" },
316
+ { A: 760, B: 630, date: "2025-11-12" },
317
+ { A: 443, B: 597, date: "2025-11-19" },
318
+ { A: 506, B: 572, date: "2025-11-26" },
319
+ { A: 316, B: 636, date: "2025-12-03" },
320
+ { A: 633, B: 664, date: "2025-12-10" },
321
+ { A: 380, B: 742, date: "2025-12-17" },
322
+ { A: 633, B: 808, date: "2025-12-24" }
323
+ // collapse-end
324
+ ];
325
+ return /* @__PURE__ */ jsx2("div", { className: "flex h-60 flex-col gap-2", children: /* @__PURE__ */ jsx2(ResponsiveContainer, { className: "h-full", children: /* @__PURE__ */ jsxs2(
326
+ ComposedChart,
327
+ {
328
+ data,
329
+ margin: {
330
+ left: 4,
331
+ right: 0,
332
+ top: 12,
333
+ bottom: 18
334
+ },
335
+ className: "text-content-tertiary [&_.recharts-text]:text-xs",
336
+ children: [
337
+ /* @__PURE__ */ jsx2(CartesianGrid, { vertical: false, stroke: "currentColor", className: "text-content-tertiary" }),
338
+ /* @__PURE__ */ jsx2(
339
+ XAxis,
340
+ {
341
+ fill: "currentColor",
342
+ axisLine: false,
343
+ tickLine: false,
344
+ tickMargin: 12,
345
+ interval: "preserveStartEnd",
346
+ dataKey: "date",
347
+ tickFormatter: (value) => new Date(value).toLocaleDateString(void 0, { month: "short" }),
348
+ ticks: selectEvenlySpacedItems(data, 12).map((item) => item.date),
349
+ children: /* @__PURE__ */ jsx2(Label, { value: "Month", fill: "currentColor", className: "!text-xs font-medium", position: "bottom" })
350
+ }
351
+ ),
352
+ /* @__PURE__ */ jsx2(
353
+ YAxis,
354
+ {
355
+ fill: "currentColor",
356
+ axisLine: false,
357
+ tickLine: false,
358
+ interval: "preserveStartEnd",
359
+ tickFormatter: (value) => Number(value).toLocaleString(),
360
+ children: /* @__PURE__ */ jsx2(
361
+ Label,
362
+ {
363
+ value: "Active users",
364
+ fill: "currentColor",
365
+ className: "!text-xs font-medium",
366
+ style: { textAnchor: "middle" },
367
+ angle: -90,
368
+ position: "insideLeft"
369
+ }
370
+ )
371
+ }
372
+ ),
373
+ /* @__PURE__ */ jsx2(
374
+ Tooltip,
375
+ {
376
+ content: /* @__PURE__ */ jsx2(ChartTooltipContent, {}),
377
+ formatter: (value) => Number(value).toLocaleString(),
378
+ labelFormatter: (value) => {
379
+ const date = new Date(value);
380
+ const endDate = new Date(date);
381
+ endDate.setDate(date.getDate() + 6);
382
+ if (date.getMonth() === endDate.getMonth()) {
383
+ return `${date.toLocaleDateString(void 0, { month: "long" })} ${date.getDate()}-${endDate.getDate()}, ${endDate.getFullYear()}`;
384
+ }
385
+ return `${date.toLocaleDateString(void 0, { month: "short", day: "numeric" })} - ${endDate.toLocaleDateString(void 0, { month: "short", day: "numeric", year: "numeric" })}`;
386
+ },
387
+ cursor: {
388
+ className: "fill-gray-light_hover/20"
389
+ }
390
+ }
391
+ ),
392
+ /* @__PURE__ */ jsx2(
393
+ Bar,
394
+ {
395
+ isAnimationActive: false,
396
+ ...colors.A !== void 0 && { className: colors.A },
397
+ name: "Mobile",
398
+ dataKey: "A",
399
+ type: "monotone",
400
+ stackId: "a",
401
+ fill: "currentColor",
402
+ maxBarSize: 12,
403
+ radius: [4, 4, 0, 0]
404
+ }
405
+ ),
406
+ /* @__PURE__ */ jsx2(
407
+ Line,
408
+ {
409
+ isAnimationActive: false,
410
+ ...colors.B !== void 0 && { className: colors.B },
411
+ dataKey: "B",
412
+ name: "Desktop",
413
+ type: "monotone",
414
+ stroke: "currentColor",
415
+ strokeWidth: 2,
416
+ strokeDasharray: "0.1 8",
417
+ strokeLinecap: "round",
418
+ activeDot: false,
419
+ dot: false
420
+ }
421
+ )
422
+ ]
423
+ }
424
+ ) }) });
425
+ };
426
+ var BarChart03 = () => {
427
+ const colors = {
428
+ A: "text-content-brand",
429
+ B: "text-brand-subtle"
430
+ };
431
+ const data = [
432
+ // collapse-start
433
+ { A: 633, B: 190, date: "2025-01-01" },
434
+ { A: 443, B: 228, date: "2025-01-08" },
435
+ { A: 506, B: 225, date: "2025-01-15" },
436
+ { A: 316, B: 227, date: "2025-01-22" },
437
+ { A: 760, B: 209, date: "2025-01-29" },
438
+ { A: 950, B: 220, date: "2025-02-05" },
439
+ { A: 760, B: 224, date: "2025-02-12" },
440
+ { A: 570, B: 279, date: "2025-02-19" },
441
+ { A: 253, B: 296, date: "2025-02-26" },
442
+ { A: 380, B: 263, date: "2025-03-05" },
443
+ { A: 443, B: 333, date: "2025-03-12" },
444
+ { A: 443, B: 306, date: "2025-03-19" },
445
+ { A: 316, B: 315, date: "2025-03-26" },
446
+ { A: 190, B: 325, date: "2025-04-02" },
447
+ { A: 380, B: 367, date: "2025-04-09" },
448
+ { A: 506, B: 372, date: "2025-04-16" },
449
+ { A: 443, B: 374, date: "2025-04-23" },
450
+ { A: 696, B: 278, date: "2025-04-30" },
451
+ { A: 950, B: 258, date: "2025-05-07" },
452
+ { A: 633, B: 357, date: "2025-05-14" },
453
+ { A: 570, B: 372, date: "2025-05-21" },
454
+ { A: 253, B: 404, date: "2025-05-28" },
455
+ { A: 316, B: 314, date: "2025-06-04" },
456
+ { A: 380, B: 359, date: "2025-06-11" },
457
+ { A: 253, B: 400, date: "2025-06-18" },
458
+ { A: 190, B: 381, date: "2025-06-25" },
459
+ { A: 316, B: 427, date: "2025-07-02" },
460
+ { A: 633, B: 371, date: "2025-07-09" },
461
+ { A: 570, B: 382, date: "2025-07-16" },
462
+ { A: 760, B: 383, date: "2025-07-23" },
463
+ { A: 950, B: 361, date: "2025-07-30" },
464
+ { A: 696, B: 405, date: "2025-08-06" },
465
+ { A: 570, B: 400, date: "2025-08-13" },
466
+ { A: 443, B: 391, date: "2025-08-20" },
467
+ { A: 316, B: 425, date: "2025-08-27" },
468
+ { A: 253, B: 406, date: "2025-09-03" },
469
+ { A: 380, B: 472, date: "2025-09-10" },
470
+ { A: 633, B: 477, date: "2025-09-17" },
471
+ { A: 570, B: 465, date: "2025-09-24" },
472
+ { A: 443, B: 488, date: "2025-10-01" },
473
+ { A: 380, B: 501, date: "2025-10-08" },
474
+ { A: 316, B: 615, date: "2025-10-15" },
475
+ { A: 570, B: 612, date: "2025-10-22" },
476
+ { A: 506, B: 673, date: "2025-10-29" },
477
+ { A: 443, B: 630, date: "2025-11-05" },
478
+ { A: 760, B: 630, date: "2025-11-12" },
479
+ { A: 443, B: 597, date: "2025-11-19" },
480
+ { A: 506, B: 572, date: "2025-11-26" },
481
+ { A: 316, B: 636, date: "2025-12-03" },
482
+ { A: 633, B: 664, date: "2025-12-10" },
483
+ { A: 380, B: 742, date: "2025-12-17" },
484
+ { A: 633, B: 808, date: "2025-12-24" }
485
+ // collapse-end
486
+ ];
487
+ return /* @__PURE__ */ jsx2("div", { className: "flex h-60 flex-col gap-2", children: /* @__PURE__ */ jsx2(ResponsiveContainer, { className: "h-full", children: /* @__PURE__ */ jsxs2(
488
+ ComposedChart,
489
+ {
490
+ data,
491
+ margin: {
492
+ left: 4,
493
+ right: 0,
494
+ top: 12,
495
+ bottom: 18
496
+ },
497
+ className: "text-content-tertiary [&_.recharts-text]:text-xs",
498
+ children: [
499
+ /* @__PURE__ */ jsx2(CartesianGrid, { vertical: false, stroke: "currentColor", className: "text-content-tertiary" }),
500
+ /* @__PURE__ */ jsx2(
501
+ XAxis,
502
+ {
503
+ fill: "currentColor",
504
+ axisLine: false,
505
+ tickLine: false,
506
+ tickMargin: 12,
507
+ interval: "preserveStartEnd",
508
+ dataKey: "date",
509
+ tickFormatter: (value) => new Date(value).toLocaleDateString(void 0, { month: "short" }),
510
+ ticks: selectEvenlySpacedItems(data, 12).map((item) => item.date),
511
+ children: /* @__PURE__ */ jsx2(Label, { value: "Month", fill: "currentColor", className: "!text-xs font-medium", position: "bottom" })
512
+ }
513
+ ),
514
+ /* @__PURE__ */ jsx2(
515
+ YAxis,
516
+ {
517
+ fill: "currentColor",
518
+ axisLine: false,
519
+ tickLine: false,
520
+ interval: "preserveStartEnd",
521
+ tickFormatter: (value) => Number(value).toLocaleString(),
522
+ children: /* @__PURE__ */ jsx2(
523
+ Label,
524
+ {
525
+ value: "Active users",
526
+ fill: "currentColor",
527
+ className: "!text-xs font-medium",
528
+ style: { textAnchor: "middle" },
529
+ angle: -90,
530
+ position: "insideLeft"
531
+ }
532
+ )
533
+ }
534
+ ),
535
+ /* @__PURE__ */ jsx2(
536
+ Tooltip,
537
+ {
538
+ content: /* @__PURE__ */ jsx2(ChartTooltipContent, {}),
539
+ formatter: (value) => Number(value).toLocaleString(),
540
+ labelFormatter: (value) => {
541
+ const date = new Date(value);
542
+ const endDate = new Date(date);
543
+ endDate.setDate(date.getDate() + 6);
544
+ if (date.getMonth() === endDate.getMonth()) {
545
+ return `${date.toLocaleDateString(void 0, { month: "long" })} ${date.getDate()}-${endDate.getDate()}, ${endDate.getFullYear()}`;
546
+ }
547
+ return `${date.toLocaleDateString(void 0, { month: "short", day: "numeric" })} - ${endDate.toLocaleDateString(void 0, { month: "short", day: "numeric", year: "numeric" })}`;
548
+ },
549
+ cursor: {
550
+ className: "fill-gray-light_hover/20"
551
+ }
552
+ }
553
+ ),
554
+ /* @__PURE__ */ jsx2(
555
+ Bar,
556
+ {
557
+ isAnimationActive: false,
558
+ ...colors.A !== void 0 && { className: colors.A },
559
+ name: "Mobile",
560
+ dataKey: "A",
561
+ type: "monotone",
562
+ stackId: "a",
563
+ fill: "currentColor",
564
+ maxBarSize: 8,
565
+ radius: [4, 4, 0, 0]
566
+ }
567
+ ),
568
+ /* @__PURE__ */ jsx2(
569
+ Line,
570
+ {
571
+ isAnimationActive: false,
572
+ ...colors.B !== void 0 && { className: colors.B },
573
+ dataKey: "B",
574
+ name: "Desktop",
575
+ type: "monotone",
576
+ stroke: "currentColor",
577
+ strokeWidth: 2,
578
+ strokeDasharray: "0.1 8",
579
+ strokeLinecap: "round",
580
+ activeDot: false,
581
+ dot: false
582
+ }
583
+ )
584
+ ]
585
+ }
586
+ ) }) });
587
+ };
588
+
589
+ // src/components/line-charts.demo.tsx
590
+ import { cx as cx2, useBreakpoint as useBreakpoint2 } from "@enact-ui/react";
591
+ import { Area, AreaChart, CartesianGrid as CartesianGrid2, Label as Label2, Legend as Legend2, ResponsiveContainer as ResponsiveContainer2, Tooltip as Tooltip2, XAxis as XAxis2, YAxis as YAxis2 } from "recharts";
592
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
593
+ var lineData = [
594
+ // collapse-start
595
+ {
596
+ date: new Date(2025, 0, 1),
597
+ A: 600,
598
+ B: 400,
599
+ C: 100
600
+ },
601
+ {
602
+ date: new Date(2025, 1, 1),
603
+ A: 620,
604
+ B: 405,
605
+ C: 160
606
+ },
607
+ {
608
+ date: new Date(2025, 2, 1),
609
+ A: 630,
610
+ B: 400,
611
+ C: 170
612
+ },
613
+ {
614
+ date: new Date(2025, 3, 1),
615
+ A: 650,
616
+ B: 410,
617
+ C: 190
618
+ },
619
+ {
620
+ date: new Date(2025, 4, 1),
621
+ A: 600,
622
+ B: 320,
623
+ C: 200
624
+ },
625
+ {
626
+ date: new Date(2025, 5, 1),
627
+ A: 650,
628
+ B: 430,
629
+ C: 230
630
+ },
631
+ {
632
+ date: new Date(2025, 6, 1),
633
+ A: 620,
634
+ B: 400,
635
+ C: 200
636
+ },
637
+ {
638
+ date: new Date(2025, 7, 1),
639
+ A: 750,
640
+ B: 540,
641
+ C: 300
642
+ },
643
+ {
644
+ date: new Date(2025, 8, 1),
645
+ A: 780,
646
+ B: 490,
647
+ C: 390
648
+ },
649
+ {
650
+ date: new Date(2025, 9, 1),
651
+ A: 750,
652
+ B: 450,
653
+ C: 300
654
+ },
655
+ {
656
+ date: new Date(2025, 10, 1),
657
+ A: 780,
658
+ B: 480,
659
+ C: 340
660
+ },
661
+ {
662
+ date: new Date(2025, 11, 1),
663
+ A: 820,
664
+ B: 500,
665
+ C: 450
666
+ }
667
+ // collapse-end
668
+ ];
669
+ var LineChart01 = () => {
670
+ const isDesktop = useBreakpoint2("lg");
671
+ const colors = {
672
+ A: "text-content-brand",
673
+ B: "text-brand-subtle",
674
+ C: "text-content-brand"
675
+ };
676
+ return /* @__PURE__ */ jsx3("div", { className: "flex h-60 flex-col gap-2", children: /* @__PURE__ */ jsx3(ResponsiveContainer2, { className: "h-full", children: /* @__PURE__ */ jsxs3(
677
+ AreaChart,
678
+ {
679
+ data: lineData,
680
+ className: "text-content-tertiary [&_.recharts-text]:text-xs",
681
+ margin: {
682
+ top: isDesktop ? 12 : 6,
683
+ bottom: isDesktop ? 16 : 0
684
+ },
685
+ children: [
686
+ /* @__PURE__ */ jsx3("defs", { children: /* @__PURE__ */ jsxs3("linearGradient", { id: "gradient", x1: "0", y1: "0", x2: "0", y2: "1", children: [
687
+ /* @__PURE__ */ jsx3("stop", { offset: "5%", stopColor: "currentColor", className: "text-content-brand", stopOpacity: "0.7" }),
688
+ /* @__PURE__ */ jsx3("stop", { offset: "95%", stopColor: "currentColor", className: "text-content-brand", stopOpacity: "0" })
689
+ ] }) }),
690
+ /* @__PURE__ */ jsx3(CartesianGrid2, { vertical: false, stroke: "currentColor", className: "text-content-tertiary" }),
691
+ /* @__PURE__ */ jsx3(
692
+ Legend2,
693
+ {
694
+ align: "right",
695
+ verticalAlign: "top",
696
+ layout: isDesktop ? "vertical" : "horizontal",
697
+ content: /* @__PURE__ */ jsx3(ChartLegendContent, { className: "-translate-y-2" })
698
+ }
699
+ ),
700
+ /* @__PURE__ */ jsx3(
701
+ XAxis2,
702
+ {
703
+ fill: "currentColor",
704
+ axisLine: false,
705
+ tickLine: false,
706
+ interval: "preserveStartEnd",
707
+ dataKey: "date",
708
+ tickFormatter: (value) => value.toLocaleDateString(void 0, { month: "short" }),
709
+ padding: { left: 10, right: 10 },
710
+ children: isDesktop && /* @__PURE__ */ jsx3(Label2, { fill: "currentColor", className: "!text-xs font-medium max-lg:hidden", position: "bottom", children: "Month" })
711
+ }
712
+ ),
713
+ /* @__PURE__ */ jsx3(
714
+ YAxis2,
715
+ {
716
+ fill: "currentColor",
717
+ axisLine: false,
718
+ tickLine: false,
719
+ interval: "preserveStartEnd",
720
+ tickFormatter: (value) => Number(value).toLocaleString(),
721
+ children: /* @__PURE__ */ jsx3(
722
+ Label2,
723
+ {
724
+ value: "Active users",
725
+ fill: "currentColor",
726
+ className: "!text-xs font-medium",
727
+ style: { textAnchor: "middle" },
728
+ angle: -90,
729
+ position: "insideLeft"
730
+ }
731
+ )
732
+ }
733
+ ),
734
+ /* @__PURE__ */ jsx3(
735
+ Tooltip2,
736
+ {
737
+ content: /* @__PURE__ */ jsx3(ChartTooltipContent, {}),
738
+ formatter: (value) => Number(value).toLocaleString(),
739
+ labelFormatter: (value) => value.toLocaleDateString(void 0, { month: "short", year: "numeric" }),
740
+ cursor: {
741
+ className: "stroke-brand-medium stroke-2"
742
+ }
743
+ }
744
+ ),
745
+ /* @__PURE__ */ jsx3(
746
+ Area,
747
+ {
748
+ isAnimationActive: false,
749
+ className: cx2(colors.A, "[&_.recharts-area-area]:translate-y-1.5 [&_.recharts-area-area]:[clip-path:inset(0_0_6px_0)]"),
750
+ dataKey: "A",
751
+ name: "Series 1",
752
+ type: "monotone",
753
+ stroke: "currentColor",
754
+ strokeWidth: 2,
755
+ fill: "url(#gradient)",
756
+ fillOpacity: 0.1,
757
+ activeDot: {
758
+ className: "fill-bg-base stroke-brand-medium stroke-2"
759
+ }
760
+ }
761
+ ),
762
+ /* @__PURE__ */ jsx3(
763
+ Area,
764
+ {
765
+ isAnimationActive: false,
766
+ className: cx2(colors.B, "[&_.recharts-area-area]:translate-y-1.5 [&_.recharts-area-area]:[clip-path:inset(0_0_6px_0)]"),
767
+ dataKey: "B",
768
+ name: "Series 2",
769
+ type: "monotone",
770
+ stroke: "currentColor",
771
+ strokeWidth: 2,
772
+ fill: "none",
773
+ activeDot: {
774
+ className: "fill-bg-base stroke-brand-medium stroke-2"
775
+ }
776
+ }
777
+ ),
778
+ /* @__PURE__ */ jsx3(
779
+ Area,
780
+ {
781
+ isAnimationActive: false,
782
+ className: cx2(colors.C, "[&_.recharts-area-area]:translate-y-1.5 [&_.recharts-area-area]:[clip-path:inset(0_0_6px_0)]"),
783
+ dataKey: "C",
784
+ name: "Series 3",
785
+ type: "monotone",
786
+ stroke: "currentColor",
787
+ strokeWidth: 2,
788
+ fill: "none",
789
+ activeDot: {
790
+ className: "fill-bg-base stroke-brand-medium stroke-2"
791
+ }
792
+ }
793
+ )
794
+ ]
795
+ }
796
+ ) }) });
797
+ };
798
+ var LineChart02 = () => {
799
+ const isDesktop = useBreakpoint2("lg");
800
+ const colors = {
801
+ A: "text-content-brand",
802
+ B: "text-brand-subtle",
803
+ C: "text-content-brand"
804
+ };
805
+ return /* @__PURE__ */ jsx3("div", { className: "flex h-60 flex-col gap-2", children: /* @__PURE__ */ jsx3(ResponsiveContainer2, { className: "h-full", children: /* @__PURE__ */ jsxs3(
806
+ AreaChart,
807
+ {
808
+ data: lineData,
809
+ className: "text-content-tertiary [&_.recharts-text]:text-xs",
810
+ margin: {
811
+ left: 5,
812
+ right: 5,
813
+ top: isDesktop ? 12 : 6,
814
+ bottom: isDesktop ? 16 : 0
815
+ },
816
+ children: [
817
+ /* @__PURE__ */ jsx3("defs", { children: /* @__PURE__ */ jsxs3("linearGradient", { id: "gradient", x1: "0", y1: "0", x2: "0", y2: "1", children: [
818
+ /* @__PURE__ */ jsx3("stop", { offset: "5%", stopColor: "currentColor", className: "text-content-brand", stopOpacity: "0.7" }),
819
+ /* @__PURE__ */ jsx3("stop", { offset: "95%", stopColor: "currentColor", className: "text-content-brand", stopOpacity: "0" })
820
+ ] }) }),
821
+ /* @__PURE__ */ jsx3(CartesianGrid2, { vertical: false, stroke: "currentColor", className: "text-content-tertiary" }),
822
+ /* @__PURE__ */ jsx3(
823
+ Legend2,
824
+ {
825
+ verticalAlign: "top",
826
+ align: "right",
827
+ layout: isDesktop ? "vertical" : "horizontal",
828
+ content: /* @__PURE__ */ jsx3(ChartLegendContent, { className: "-translate-y-2" })
829
+ }
830
+ ),
831
+ /* @__PURE__ */ jsx3(
832
+ XAxis2,
833
+ {
834
+ fill: "currentColor",
835
+ axisLine: false,
836
+ tickLine: false,
837
+ interval: "preserveStartEnd",
838
+ dataKey: "date",
839
+ tickFormatter: (value) => value.toLocaleDateString(void 0, { month: "short" }),
840
+ padding: { left: 10, right: 10 },
841
+ children: isDesktop && /* @__PURE__ */ jsx3(Label2, { fill: "currentColor", className: "!text-xs font-medium max-lg:hidden", position: "bottom", children: "Month" })
842
+ }
843
+ ),
844
+ /* @__PURE__ */ jsx3(
845
+ YAxis2,
846
+ {
847
+ fill: "currentColor",
848
+ axisLine: false,
849
+ tickLine: false,
850
+ interval: "preserveStartEnd",
851
+ tickFormatter: (value) => Number(value).toLocaleString(),
852
+ children: /* @__PURE__ */ jsx3(
853
+ Label2,
854
+ {
855
+ value: "Active users",
856
+ fill: "currentColor",
857
+ className: "!text-xs font-medium",
858
+ style: { textAnchor: "middle" },
859
+ angle: -90,
860
+ position: "insideLeft"
861
+ }
862
+ )
863
+ }
864
+ ),
865
+ /* @__PURE__ */ jsx3(
866
+ Tooltip2,
867
+ {
868
+ content: /* @__PURE__ */ jsx3(ChartTooltipContent, {}),
869
+ formatter: (value) => Number(value).toLocaleString(),
870
+ labelFormatter: (value) => value.toLocaleDateString(void 0, { month: "short", year: "numeric" }),
871
+ cursor: {
872
+ className: "stroke-brand-medium stroke-2"
873
+ }
874
+ }
875
+ ),
876
+ /* @__PURE__ */ jsx3(
877
+ Area,
878
+ {
879
+ isAnimationActive: false,
880
+ className: cx2(colors.A, "[&_.recharts-area-area]:translate-y-1.5 [&_.recharts-area-area]:[clip-path:inset(0_0_6px_0)]"),
881
+ dataKey: "A",
882
+ name: "Series 1",
883
+ type: "monotone",
884
+ stroke: "currentColor",
885
+ strokeWidth: 2,
886
+ fill: "url(#gradient)",
887
+ fillOpacity: 0.1,
888
+ activeDot: {
889
+ className: "fill-bg-base stroke-brand-medium stroke-2"
890
+ }
891
+ }
892
+ ),
893
+ /* @__PURE__ */ jsx3(
894
+ Area,
895
+ {
896
+ isAnimationActive: false,
897
+ className: cx2(colors.B, "[&_.recharts-area-area]:translate-y-1.5 [&_.recharts-area-area]:[clip-path:inset(0_0_6px_0)]"),
898
+ dataKey: "B",
899
+ name: "Series 2",
900
+ type: "monotone",
901
+ stroke: "currentColor",
902
+ strokeWidth: 2,
903
+ fill: "none",
904
+ strokeDasharray: "0.1 8",
905
+ strokeLinecap: "round",
906
+ activeDot: {
907
+ className: "fill-bg-base stroke-brand-medium stroke-2"
908
+ }
909
+ }
910
+ ),
911
+ /* @__PURE__ */ jsx3(
912
+ Area,
913
+ {
914
+ isAnimationActive: false,
915
+ className: cx2(colors.C, "[&_.recharts-area-area]:translate-y-1.5 [&_.recharts-area-area]:[clip-path:inset(0_0_6px_0)]"),
916
+ dataKey: "C",
917
+ name: "Series 3",
918
+ type: "monotone",
919
+ stroke: "currentColor",
920
+ strokeWidth: 2,
921
+ fill: "none",
922
+ strokeDasharray: "0.1 8",
923
+ strokeLinecap: "round",
924
+ activeDot: {
925
+ className: "fill-bg-base stroke-brand-medium stroke-2"
926
+ }
927
+ }
928
+ )
929
+ ]
930
+ }
931
+ ) }) });
932
+ };
933
+ var LineChart03 = () => {
934
+ const isDesktop = useBreakpoint2("lg");
935
+ const colors = {
936
+ A: "text-content-brand",
937
+ B: "text-brand-subtle",
938
+ C: "text-content-brand"
939
+ };
940
+ return /* @__PURE__ */ jsx3("div", { className: "flex h-60 flex-col gap-2", children: /* @__PURE__ */ jsx3(ResponsiveContainer2, { className: "h-full", children: /* @__PURE__ */ jsxs3(
941
+ AreaChart,
942
+ {
943
+ data: lineData,
944
+ className: "text-content-tertiary [&_.recharts-text]:text-xs",
945
+ margin: {
946
+ left: 5,
947
+ right: 5,
948
+ top: isDesktop ? 12 : 6,
949
+ bottom: isDesktop ? 16 : 0
950
+ },
951
+ children: [
952
+ /* @__PURE__ */ jsxs3("defs", { children: [
953
+ /* @__PURE__ */ jsxs3("linearGradient", { id: "gradient", x1: "0", y1: "0", x2: "0", y2: "1", children: [
954
+ /* @__PURE__ */ jsx3("stop", { offset: "0%", stopColor: "currentColor", className: "text-content-secondary", stopOpacity: "0.8" }),
955
+ /* @__PURE__ */ jsx3("stop", { offset: "80%", stopColor: "currentColor", className: "text-content-secondary", stopOpacity: "0" })
956
+ ] }),
957
+ /* @__PURE__ */ jsxs3("pattern", { id: "verticalLines", width: "8", height: "100%", fill: "url(#gradient)", patternUnits: "userSpaceOnUse", children: [
958
+ /* @__PURE__ */ jsx3("line", { x1: "0", y1: "0", x2: "0", y2: "100%", stroke: "currentColor", className: "text-content-tertiary", strokeWidth: "1.5" }),
959
+ /* @__PURE__ */ jsx3("rect", { width: "100%", height: "100%", fill: "url(#gradient)", fillOpacity: 0.15 })
960
+ ] })
961
+ ] }),
962
+ /* @__PURE__ */ jsx3(CartesianGrid2, { vertical: false, stroke: "currentColor", className: "text-content-tertiary" }),
963
+ /* @__PURE__ */ jsx3(
964
+ Legend2,
965
+ {
966
+ verticalAlign: "top",
967
+ align: "right",
968
+ layout: isDesktop ? "vertical" : "horizontal",
969
+ content: /* @__PURE__ */ jsx3(ChartLegendContent, { className: "-translate-y-2" })
970
+ }
971
+ ),
972
+ /* @__PURE__ */ jsx3(
973
+ XAxis2,
974
+ {
975
+ fill: "currentColor",
976
+ axisLine: false,
977
+ tickLine: false,
978
+ tickMargin: 10,
979
+ interval: "preserveStartEnd",
980
+ dataKey: "date",
981
+ padding: { left: 10, right: 10 },
982
+ tickFormatter: (value) => value.toLocaleDateString(void 0, { month: "short" }),
983
+ children: isDesktop && /* @__PURE__ */ jsx3(Label2, { fill: "currentColor", className: "!text-xs font-medium max-lg:hidden", position: "bottom", children: "Month" })
984
+ }
985
+ ),
986
+ /* @__PURE__ */ jsx3(
987
+ YAxis2,
988
+ {
989
+ fill: "currentColor",
990
+ axisLine: false,
991
+ tickLine: false,
992
+ interval: "preserveStartEnd",
993
+ tickFormatter: (value) => Number(value).toLocaleString(),
994
+ children: /* @__PURE__ */ jsx3(
995
+ Label2,
996
+ {
997
+ value: "Active users",
998
+ fill: "currentColor",
999
+ className: "!text-xs font-medium",
1000
+ style: { textAnchor: "middle" },
1001
+ angle: -90,
1002
+ position: "insideLeft"
1003
+ }
1004
+ )
1005
+ }
1006
+ ),
1007
+ /* @__PURE__ */ jsx3(
1008
+ Tooltip2,
1009
+ {
1010
+ content: /* @__PURE__ */ jsx3(ChartTooltipContent, {}),
1011
+ formatter: (value) => Number(value).toLocaleString(),
1012
+ labelFormatter: (value) => value.toLocaleDateString(void 0, { month: "short", year: "numeric" }),
1013
+ cursor: {
1014
+ className: "stroke-brand-medium stroke-2"
1015
+ }
1016
+ }
1017
+ ),
1018
+ /* @__PURE__ */ jsx3(
1019
+ Area,
1020
+ {
1021
+ isAnimationActive: false,
1022
+ className: cx2(colors.A, "[&_.recharts-area-area]:translate-y-1.5 [&_.recharts-area-area]:[clip-path:inset(0_0_6px_0)]"),
1023
+ dataKey: "A",
1024
+ name: "Series 1",
1025
+ type: "monotone",
1026
+ stroke: "currentColor",
1027
+ strokeWidth: 2,
1028
+ fill: "url(#verticalLines)",
1029
+ fillOpacity: 1,
1030
+ activeDot: {
1031
+ className: "fill-bg-base stroke-brand-medium stroke-2"
1032
+ }
1033
+ }
1034
+ ),
1035
+ /* @__PURE__ */ jsx3(
1036
+ Area,
1037
+ {
1038
+ isAnimationActive: false,
1039
+ className: cx2(colors.B, "[&_.recharts-area-area]:translate-y-1.5 [&_.recharts-area-area]:[clip-path:inset(0_0_6px_0)]"),
1040
+ dataKey: "B",
1041
+ name: "Series 2",
1042
+ type: "monotone",
1043
+ stroke: "currentColor",
1044
+ strokeWidth: 2,
1045
+ fill: "none",
1046
+ activeDot: {
1047
+ className: "fill-bg-base stroke-brand-medium stroke-2"
1048
+ }
1049
+ }
1050
+ ),
1051
+ /* @__PURE__ */ jsx3(
1052
+ Area,
1053
+ {
1054
+ isAnimationActive: false,
1055
+ className: cx2(colors.C, "[&_.recharts-area-area]:translate-y-1.5 [&_.recharts-area-area]:[clip-path:inset(0_0_6px_0)]"),
1056
+ dataKey: "C",
1057
+ name: "Series 3",
1058
+ type: "monotone",
1059
+ stroke: "currentColor",
1060
+ strokeWidth: 2,
1061
+ fill: "none",
1062
+ activeDot: {
1063
+ className: "fill-bg-base stroke-brand-medium stroke-2"
1064
+ }
1065
+ }
1066
+ )
1067
+ ]
1068
+ }
1069
+ ) }) });
1070
+ };
1071
+ var LineChart04 = () => {
1072
+ const isDesktop = useBreakpoint2("lg");
1073
+ const colors = {
1074
+ A: "text-content-brand",
1075
+ B: "text-content-secondary",
1076
+ C: "text-content-tertiary"
1077
+ };
1078
+ return /* @__PURE__ */ jsx3("div", { className: "flex h-60 flex-col gap-2", children: /* @__PURE__ */ jsx3(ResponsiveContainer2, { className: "h-full", children: /* @__PURE__ */ jsxs3(
1079
+ AreaChart,
1080
+ {
1081
+ data: lineData,
1082
+ className: "text-content-tertiary [&_.recharts-text]:text-xs",
1083
+ margin: {
1084
+ left: 5,
1085
+ right: 5,
1086
+ top: isDesktop ? 12 : 6,
1087
+ bottom: isDesktop ? 16 : 0
1088
+ },
1089
+ children: [
1090
+ /* @__PURE__ */ jsx3("defs", { children: /* @__PURE__ */ jsxs3("linearGradient", { id: "gradient", x1: "0", y1: "0", x2: "0", y2: "1", children: [
1091
+ /* @__PURE__ */ jsx3("stop", { offset: "5%", stopColor: "currentColor", className: "text-content-secondary", stopOpacity: "0.7" }),
1092
+ /* @__PURE__ */ jsx3("stop", { offset: "95%", stopColor: "currentColor", className: "text-content-secondary", stopOpacity: "0" })
1093
+ ] }) }),
1094
+ /* @__PURE__ */ jsx3(CartesianGrid2, { vertical: false, stroke: "currentColor", className: "text-content-tertiary" }),
1095
+ /* @__PURE__ */ jsx3(
1096
+ Legend2,
1097
+ {
1098
+ verticalAlign: "top",
1099
+ align: "right",
1100
+ layout: isDesktop ? "vertical" : "horizontal",
1101
+ content: /* @__PURE__ */ jsx3(ChartLegendContent, { className: "-translate-y-2" })
1102
+ }
1103
+ ),
1104
+ /* @__PURE__ */ jsx3(
1105
+ XAxis2,
1106
+ {
1107
+ fill: "currentColor",
1108
+ axisLine: false,
1109
+ tickLine: false,
1110
+ tickMargin: 10,
1111
+ interval: "preserveStartEnd",
1112
+ dataKey: "date",
1113
+ tickFormatter: (value) => value.toLocaleDateString(void 0, { month: "short" }),
1114
+ padding: { left: 10, right: 10 },
1115
+ children: isDesktop && /* @__PURE__ */ jsx3(Label2, { fill: "currentColor", className: "!text-xs font-medium max-lg:hidden", position: "bottom", children: "Month" })
1116
+ }
1117
+ ),
1118
+ /* @__PURE__ */ jsx3(
1119
+ YAxis2,
1120
+ {
1121
+ fill: "currentColor",
1122
+ axisLine: false,
1123
+ tickLine: false,
1124
+ interval: "preserveStartEnd",
1125
+ tickFormatter: (value) => Number(value).toLocaleString(),
1126
+ children: /* @__PURE__ */ jsx3(
1127
+ Label2,
1128
+ {
1129
+ value: "Active users",
1130
+ fill: "currentColor",
1131
+ className: "!text-xs font-medium",
1132
+ style: { textAnchor: "middle" },
1133
+ angle: -90,
1134
+ position: "insideLeft"
1135
+ }
1136
+ )
1137
+ }
1138
+ ),
1139
+ /* @__PURE__ */ jsx3(
1140
+ Tooltip2,
1141
+ {
1142
+ content: /* @__PURE__ */ jsx3(ChartTooltipContent, {}),
1143
+ formatter: (value) => Number(value).toLocaleString(),
1144
+ labelFormatter: (value) => value.toLocaleDateString(void 0, { month: "short", year: "numeric" }),
1145
+ cursor: {
1146
+ className: "stroke-brand-medium stroke-2"
1147
+ }
1148
+ }
1149
+ ),
1150
+ /* @__PURE__ */ jsx3(
1151
+ Area,
1152
+ {
1153
+ isAnimationActive: false,
1154
+ className: cx2(colors.A, "[&_.recharts-area-area]:translate-y-1.5 [&_.recharts-area-area]:[clip-path:inset(0_0_6px_0)]"),
1155
+ dataKey: "A",
1156
+ name: "Series 1",
1157
+ type: "monotone",
1158
+ stroke: "currentColor",
1159
+ strokeWidth: 2,
1160
+ fill: "url(#gradient)",
1161
+ fillOpacity: 0.1,
1162
+ activeDot: {
1163
+ className: "fill-bg-base stroke-brand-medium stroke-2"
1164
+ }
1165
+ }
1166
+ ),
1167
+ /* @__PURE__ */ jsx3(
1168
+ Area,
1169
+ {
1170
+ isAnimationActive: false,
1171
+ className: cx2(colors.B, "[&_.recharts-area-area]:translate-y-1.5 [&_.recharts-area-area]:[clip-path:inset(0_0_6px_0)]"),
1172
+ dataKey: "B",
1173
+ name: "Series 2",
1174
+ type: "monotone",
1175
+ stroke: "currentColor",
1176
+ strokeWidth: 2,
1177
+ fill: "none",
1178
+ activeDot: {
1179
+ className: "fill-bg-base stroke-brand-medium stroke-2"
1180
+ }
1181
+ }
1182
+ ),
1183
+ /* @__PURE__ */ jsx3(
1184
+ Area,
1185
+ {
1186
+ isAnimationActive: false,
1187
+ className: cx2(colors.C, "[&_.recharts-area-area]:translate-y-1.5 [&_.recharts-area-area]:[clip-path:inset(0_0_6px_0)]"),
1188
+ dataKey: "C",
1189
+ name: "Series 3",
1190
+ type: "monotone",
1191
+ stroke: "currentColor",
1192
+ strokeWidth: 2,
1193
+ fill: "none",
1194
+ activeDot: {
1195
+ className: "fill-bg-base stroke-brand-medium stroke-2"
1196
+ }
1197
+ }
1198
+ )
1199
+ ]
1200
+ }
1201
+ ) }) });
1202
+ };
1203
+
1204
+ // src/components/pie-charts.demo.tsx
1205
+ import { Legend as Legend3, Pie, PieChart as RechartsPieChart, ResponsiveContainer as ResponsiveContainer3, Tooltip as Tooltip3 } from "recharts";
1206
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1207
+ var pieChartData = [
1208
+ // collapse-start
1209
+ {
1210
+ name: "Series 1",
1211
+ value: 200,
1212
+ className: "text-content-brand"
1213
+ },
1214
+ {
1215
+ name: "Series 2",
1216
+ value: 350,
1217
+ className: "text-content-brand"
1218
+ },
1219
+ {
1220
+ name: "Series 3",
1221
+ value: 100,
1222
+ className: "text-brand-subtle"
1223
+ },
1224
+ {
1225
+ name: "Series 4",
1226
+ value: 120,
1227
+ className: "text-brand-subtle"
1228
+ },
1229
+ {
1230
+ name: "Series 5",
1231
+ value: 230,
1232
+ className: "text-content-tertiary"
1233
+ }
1234
+ // collapse-end
1235
+ ];
1236
+ var PieChartXxs = ({ data = pieChartData }) => {
1237
+ return /* @__PURE__ */ jsx4(ResponsiveContainer3, { height: 120, className: "max-w-52.5", children: /* @__PURE__ */ jsxs4(
1238
+ RechartsPieChart,
1239
+ {
1240
+ margin: {
1241
+ left: 0,
1242
+ right: 0,
1243
+ top: 0,
1244
+ bottom: 0
1245
+ },
1246
+ children: [
1247
+ /* @__PURE__ */ jsx4(Legend3, { verticalAlign: "top", align: "right", layout: "vertical", content: ChartLegendContent }),
1248
+ /* @__PURE__ */ jsx4(Tooltip3, { content: /* @__PURE__ */ jsx4(ChartTooltipContent, { isPieChart: true }) }),
1249
+ /* @__PURE__ */ jsx4(
1250
+ Pie,
1251
+ {
1252
+ isAnimationActive: false,
1253
+ startAngle: -270,
1254
+ endAngle: -630,
1255
+ stroke: "none",
1256
+ data,
1257
+ dataKey: "value",
1258
+ nameKey: "name",
1259
+ fill: "currentColor",
1260
+ innerRadius: 30,
1261
+ outerRadius: 60
1262
+ }
1263
+ )
1264
+ ]
1265
+ }
1266
+ ) });
1267
+ };
1268
+ var PieChartXs = ({ data = pieChartData }) => {
1269
+ return /* @__PURE__ */ jsx4(ResponsiveContainer3, { height: 160, className: "max-w-62.5", children: /* @__PURE__ */ jsxs4(
1270
+ RechartsPieChart,
1271
+ {
1272
+ margin: {
1273
+ left: 0,
1274
+ right: 0,
1275
+ top: 0,
1276
+ bottom: 0
1277
+ },
1278
+ children: [
1279
+ /* @__PURE__ */ jsx4(Legend3, { verticalAlign: "top", align: "right", layout: "vertical", content: ChartLegendContent }),
1280
+ /* @__PURE__ */ jsx4(Tooltip3, { content: /* @__PURE__ */ jsx4(ChartTooltipContent, { isPieChart: true }) }),
1281
+ /* @__PURE__ */ jsx4(
1282
+ Pie,
1283
+ {
1284
+ isAnimationActive: false,
1285
+ startAngle: -270,
1286
+ endAngle: -630,
1287
+ stroke: "none",
1288
+ data,
1289
+ dataKey: "value",
1290
+ nameKey: "name",
1291
+ fill: "currentColor",
1292
+ innerRadius: 40,
1293
+ outerRadius: 80
1294
+ }
1295
+ )
1296
+ ]
1297
+ }
1298
+ ) });
1299
+ };
1300
+ var PieChartSm = ({ data = pieChartData }) => {
1301
+ return /* @__PURE__ */ jsx4(ResponsiveContainer3, { height: 200, className: "max-w-72.5", children: /* @__PURE__ */ jsxs4(
1302
+ RechartsPieChart,
1303
+ {
1304
+ margin: {
1305
+ left: 0,
1306
+ right: 0,
1307
+ top: 0,
1308
+ bottom: 0
1309
+ },
1310
+ children: [
1311
+ /* @__PURE__ */ jsx4(Legend3, { verticalAlign: "top", align: "right", layout: "vertical", content: ChartLegendContent }),
1312
+ /* @__PURE__ */ jsx4(Tooltip3, { content: /* @__PURE__ */ jsx4(ChartTooltipContent, { isPieChart: true }) }),
1313
+ /* @__PURE__ */ jsx4(
1314
+ Pie,
1315
+ {
1316
+ isAnimationActive: false,
1317
+ startAngle: -270,
1318
+ endAngle: -630,
1319
+ stroke: "none",
1320
+ data,
1321
+ dataKey: "value",
1322
+ nameKey: "name",
1323
+ fill: "currentColor",
1324
+ innerRadius: 50,
1325
+ outerRadius: 100
1326
+ }
1327
+ )
1328
+ ]
1329
+ }
1330
+ ) });
1331
+ };
1332
+ var PieChartMd = ({ data = pieChartData }) => {
1333
+ return /* @__PURE__ */ jsx4(ResponsiveContainer3, { height: 240, className: "max-w-96", children: /* @__PURE__ */ jsxs4(
1334
+ RechartsPieChart,
1335
+ {
1336
+ margin: {
1337
+ left: 0,
1338
+ right: 0,
1339
+ top: 0,
1340
+ bottom: 0
1341
+ },
1342
+ children: [
1343
+ /* @__PURE__ */ jsx4(Legend3, { verticalAlign: "top", align: "right", layout: "vertical", content: ChartLegendContent }),
1344
+ /* @__PURE__ */ jsx4(Tooltip3, { content: /* @__PURE__ */ jsx4(ChartTooltipContent, { isPieChart: true }) }),
1345
+ /* @__PURE__ */ jsx4(
1346
+ Pie,
1347
+ {
1348
+ isAnimationActive: false,
1349
+ startAngle: -270,
1350
+ endAngle: -630,
1351
+ stroke: "none",
1352
+ data,
1353
+ dataKey: "value",
1354
+ nameKey: "name",
1355
+ fill: "currentColor",
1356
+ innerRadius: 60,
1357
+ outerRadius: 120
1358
+ }
1359
+ )
1360
+ ]
1361
+ }
1362
+ ) });
1363
+ };
1364
+ var PieChartLg = ({ data = pieChartData }) => {
1365
+ return /* @__PURE__ */ jsx4(ResponsiveContainer3, { height: 280, className: "max-w-96", children: /* @__PURE__ */ jsxs4(
1366
+ RechartsPieChart,
1367
+ {
1368
+ margin: {
1369
+ left: 0,
1370
+ right: 0,
1371
+ top: 0,
1372
+ bottom: 0
1373
+ },
1374
+ children: [
1375
+ /* @__PURE__ */ jsx4(Legend3, { verticalAlign: "top", align: "right", layout: "vertical", content: ChartLegendContent }),
1376
+ /* @__PURE__ */ jsx4(Tooltip3, { content: /* @__PURE__ */ jsx4(ChartTooltipContent, { isPieChart: true }) }),
1377
+ /* @__PURE__ */ jsx4(
1378
+ Pie,
1379
+ {
1380
+ isAnimationActive: false,
1381
+ startAngle: -270,
1382
+ endAngle: -630,
1383
+ stroke: "none",
1384
+ data,
1385
+ dataKey: "value",
1386
+ nameKey: "name",
1387
+ fill: "currentColor",
1388
+ innerRadius: 70,
1389
+ outerRadius: 140
1390
+ }
1391
+ )
1392
+ ]
1393
+ }
1394
+ ) });
1395
+ };
1396
+
1397
+ // src/components/relationship-graph.tsx
1398
+ import { cx as cx3 } from "@enact-ui/react";
1399
+ import { AnimatePresence, motion } from "framer-motion";
1400
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
1401
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1402
+ var DEFAULT_TYPE_COLORS = {
1403
+ product: "#0284C7",
1404
+ ingredient: "#059669",
1405
+ plant: "#65A30D",
1406
+ recipe: "#F59E0B",
1407
+ variant: "#8B5CF6",
1408
+ field: "#6366F1",
1409
+ domain: "#EC4899",
1410
+ default: "#6B7280"
1411
+ };
1412
+ var EDGE_STYLES = {
1413
+ default: {},
1414
+ dashed: { dashArray: "4,4" },
1415
+ dotted: { dashArray: "2,2" }
1416
+ };
1417
+ function useForceLayout(nodes, edges, width, height) {
1418
+ const [positionedNodes, setPositionedNodes] = useState([]);
1419
+ useEffect(() => {
1420
+ if (nodes.length === 0) return;
1421
+ const centerX = width / 2;
1422
+ const centerY = height / 2;
1423
+ const radius = Math.min(width, height) * 0.35;
1424
+ const positioned = nodes.map((node, i) => {
1425
+ const angle = 2 * Math.PI * i / nodes.length;
1426
+ return {
1427
+ ...node,
1428
+ x: node.isRoot ? centerX : centerX + radius * Math.cos(angle),
1429
+ y: node.isRoot ? centerY : centerY + radius * Math.sin(angle),
1430
+ vx: 0,
1431
+ vy: 0
1432
+ };
1433
+ });
1434
+ const iterations = 50;
1435
+ const repulsion = 5e3;
1436
+ const attraction = 0.05;
1437
+ const damping = 0.9;
1438
+ const centerForce = 0.01;
1439
+ for (let iter = 0; iter < iterations; iter++) {
1440
+ for (let i = 0; i < positioned.length; i++) {
1441
+ const node = positioned[i];
1442
+ if (!node) continue;
1443
+ for (let j = 0; j < positioned.length; j++) {
1444
+ if (i === j) continue;
1445
+ const other = positioned[j];
1446
+ if (!other) continue;
1447
+ const dx = node.x - other.x;
1448
+ const dy = node.y - other.y;
1449
+ const dist = Math.sqrt(dx * dx + dy * dy) || 1;
1450
+ const force = repulsion / (dist * dist);
1451
+ node.vx += dx / dist * force;
1452
+ node.vy += dy / dist * force;
1453
+ }
1454
+ edges.forEach((edge) => {
1455
+ if (edge.source === node.id || edge.target === node.id) {
1456
+ const otherId = edge.source === node.id ? edge.target : edge.source;
1457
+ const other = positioned.find((n) => n.id === otherId);
1458
+ if (other) {
1459
+ const dx = other.x - node.x;
1460
+ const dy = other.y - node.y;
1461
+ node.vx += dx * attraction;
1462
+ node.vy += dy * attraction;
1463
+ }
1464
+ }
1465
+ });
1466
+ node.vx += (centerX - node.x) * centerForce;
1467
+ node.vy += (centerY - node.y) * centerForce;
1468
+ if (node.isRoot) {
1469
+ node.vx = (centerX - node.x) * 0.5;
1470
+ node.vy = (centerY - node.y) * 0.5;
1471
+ }
1472
+ }
1473
+ for (const node of positioned) {
1474
+ node.x += node.vx;
1475
+ node.y += node.vy;
1476
+ node.vx *= damping;
1477
+ node.vy *= damping;
1478
+ const padding = 60;
1479
+ node.x = Math.max(padding, Math.min(width - padding, node.x));
1480
+ node.y = Math.max(padding, Math.min(height - padding, node.y));
1481
+ }
1482
+ }
1483
+ setPositionedNodes(positioned);
1484
+ }, [nodes, edges, width, height]);
1485
+ const positionedEdges = useMemo(() => {
1486
+ return edges.map((edge) => {
1487
+ const sourceNode = positionedNodes.find((n) => n.id === edge.source);
1488
+ const targetNode = positionedNodes.find((n) => n.id === edge.target);
1489
+ if (!sourceNode || !targetNode) return null;
1490
+ return { ...edge, sourceNode, targetNode };
1491
+ }).filter(Boolean);
1492
+ }, [edges, positionedNodes]);
1493
+ return { positionedNodes, positionedEdges };
1494
+ }
1495
+ function useHierarchicalLayout(nodes, edges, width, height) {
1496
+ const positionedNodes = useMemo(() => {
1497
+ if (nodes.length === 0) return [];
1498
+ const rootNode = nodes.find((n) => n.isRoot) || nodes[0];
1499
+ if (!rootNode) return [];
1500
+ const children = {};
1501
+ nodes.forEach((n) => {
1502
+ children[n.id] = [];
1503
+ });
1504
+ edges.forEach((edge) => {
1505
+ const sourceChildren = children[edge.source];
1506
+ if (sourceChildren) sourceChildren.push(edge.target);
1507
+ });
1508
+ const levels = { [rootNode.id]: 0 };
1509
+ const queue = [rootNode.id];
1510
+ const visited = /* @__PURE__ */ new Set([rootNode.id]);
1511
+ while (queue.length > 0) {
1512
+ const current = queue.shift();
1513
+ if (current === void 0) break;
1514
+ const currentLevel = levels[current];
1515
+ if (currentLevel !== void 0) {
1516
+ children[current]?.forEach((childId) => {
1517
+ if (!visited.has(childId)) {
1518
+ visited.add(childId);
1519
+ levels[childId] = currentLevel + 1;
1520
+ queue.push(childId);
1521
+ }
1522
+ });
1523
+ }
1524
+ }
1525
+ nodes.forEach((n) => {
1526
+ if (levels[n.id] === void 0) levels[n.id] = 1;
1527
+ });
1528
+ const nodesByLevel = {};
1529
+ nodes.forEach((n) => {
1530
+ const level = levels[n.id];
1531
+ if (level !== void 0) {
1532
+ if (!nodesByLevel[level]) nodesByLevel[level] = [];
1533
+ nodesByLevel[level].push(n);
1534
+ }
1535
+ });
1536
+ const maxLevel = Math.max(...Object.keys(nodesByLevel).map(Number));
1537
+ const levelHeight = height / (maxLevel + 2);
1538
+ return nodes.map((node) => {
1539
+ const level = levels[node.id];
1540
+ if (level === void 0) {
1541
+ return { ...node, x: 0, y: 0, vx: 0, vy: 0 };
1542
+ }
1543
+ const nodesAtLevel = nodesByLevel[level];
1544
+ if (!nodesAtLevel) {
1545
+ return { ...node, x: 0, y: 0, vx: 0, vy: 0 };
1546
+ }
1547
+ const indexAtLevel = nodesAtLevel.indexOf(node);
1548
+ const levelWidth = width / (nodesAtLevel.length + 1);
1549
+ return {
1550
+ ...node,
1551
+ x: levelWidth * (indexAtLevel + 1),
1552
+ y: levelHeight * (level + 1),
1553
+ vx: 0,
1554
+ vy: 0
1555
+ };
1556
+ });
1557
+ }, [nodes, edges, width, height]);
1558
+ const positionedEdges = useMemo(() => {
1559
+ return edges.map((edge) => {
1560
+ const sourceNode = positionedNodes.find((n) => n.id === edge.source);
1561
+ const targetNode = positionedNodes.find((n) => n.id === edge.target);
1562
+ if (!sourceNode || !targetNode) return null;
1563
+ return { ...edge, sourceNode, targetNode };
1564
+ }).filter(Boolean);
1565
+ }, [edges, positionedNodes]);
1566
+ return { positionedNodes, positionedEdges };
1567
+ }
1568
+ function useRadialLayout(nodes, edges, width, height) {
1569
+ const positionedNodes = useMemo(() => {
1570
+ if (nodes.length === 0) return [];
1571
+ const centerX = width / 2;
1572
+ const centerY = height / 2;
1573
+ const rootNode = nodes.find((n) => n.isRoot) || nodes[0];
1574
+ if (!rootNode) return [];
1575
+ const distances = { [rootNode.id]: 0 };
1576
+ const queue = [rootNode.id];
1577
+ const visited = /* @__PURE__ */ new Set([rootNode.id]);
1578
+ const adjacent = {};
1579
+ nodes.forEach((n) => {
1580
+ adjacent[n.id] = /* @__PURE__ */ new Set();
1581
+ });
1582
+ edges.forEach((e) => {
1583
+ adjacent[e.source]?.add(e.target);
1584
+ adjacent[e.target]?.add(e.source);
1585
+ });
1586
+ while (queue.length > 0) {
1587
+ const current = queue.shift();
1588
+ if (current === void 0) break;
1589
+ const currentDist = distances[current];
1590
+ if (currentDist !== void 0) {
1591
+ adjacent[current]?.forEach((neighborId) => {
1592
+ if (!visited.has(neighborId)) {
1593
+ visited.add(neighborId);
1594
+ distances[neighborId] = currentDist + 1;
1595
+ queue.push(neighborId);
1596
+ }
1597
+ });
1598
+ }
1599
+ }
1600
+ nodes.forEach((n) => {
1601
+ if (distances[n.id] === void 0) distances[n.id] = 1;
1602
+ });
1603
+ const nodesByDistance = {};
1604
+ nodes.forEach((n) => {
1605
+ const dist = distances[n.id];
1606
+ if (dist !== void 0) {
1607
+ if (!nodesByDistance[dist]) nodesByDistance[dist] = [];
1608
+ nodesByDistance[dist].push(n);
1609
+ }
1610
+ });
1611
+ const maxDistance = Math.max(...Object.keys(nodesByDistance).map(Number));
1612
+ const radiusStep = Math.min(width, height) * 0.35 / Math.max(maxDistance, 1);
1613
+ return nodes.map((node) => {
1614
+ const dist = distances[node.id];
1615
+ if (dist === void 0) {
1616
+ return { ...node, x: centerX, y: centerY, vx: 0, vy: 0 };
1617
+ }
1618
+ if (dist === 0) return { ...node, x: centerX, y: centerY, vx: 0, vy: 0 };
1619
+ const nodesAtDist = nodesByDistance[dist];
1620
+ if (!nodesAtDist) {
1621
+ return { ...node, x: centerX, y: centerY, vx: 0, vy: 0 };
1622
+ }
1623
+ const indexAtDist = nodesAtDist.indexOf(node);
1624
+ const angle = 2 * Math.PI * indexAtDist / nodesAtDist.length;
1625
+ const radius = radiusStep * dist;
1626
+ return {
1627
+ ...node,
1628
+ x: centerX + radius * Math.cos(angle),
1629
+ y: centerY + radius * Math.sin(angle),
1630
+ vx: 0,
1631
+ vy: 0
1632
+ };
1633
+ });
1634
+ }, [nodes, edges, width, height]);
1635
+ const positionedEdges = useMemo(() => {
1636
+ return edges.map((edge) => {
1637
+ const sourceNode = positionedNodes.find((n) => n.id === edge.source);
1638
+ const targetNode = positionedNodes.find((n) => n.id === edge.target);
1639
+ if (!sourceNode || !targetNode) return null;
1640
+ return { ...edge, sourceNode, targetNode };
1641
+ }).filter(Boolean);
1642
+ }, [edges, positionedNodes]);
1643
+ return { positionedNodes, positionedEdges };
1644
+ }
1645
+ var GraphNodeComponent = ({ node, onClick, showLabel, isHighlighted, isHovered, onHover, typeColors }) => {
1646
+ const nodeColor = node.color || typeColors[node.type] || typeColors.default || DEFAULT_TYPE_COLORS.default;
1647
+ const nodeSize = node.isRoot ? 28 : 22;
1648
+ return /* @__PURE__ */ jsxs5(
1649
+ motion.g,
1650
+ {
1651
+ initial: { scale: 0, opacity: 0 },
1652
+ animate: { scale: isHovered || isHighlighted ? 1.2 : 1, opacity: 1 },
1653
+ transition: { type: "spring", stiffness: 300, damping: 20 },
1654
+ style: { cursor: onClick ? "pointer" : "default" },
1655
+ onClick,
1656
+ onMouseEnter: () => onHover(true),
1657
+ onMouseLeave: () => onHover(false),
1658
+ role: onClick ? "button" : void 0,
1659
+ tabIndex: onClick ? 0 : void 0,
1660
+ children: [
1661
+ /* @__PURE__ */ jsx5(
1662
+ "circle",
1663
+ {
1664
+ cx: node.x,
1665
+ cy: node.y,
1666
+ r: nodeSize,
1667
+ fill: nodeColor,
1668
+ stroke: isHighlighted ? "#1F2937" : "white",
1669
+ strokeWidth: isHighlighted ? 3 : 2,
1670
+ style: { filter: isHovered ? "drop-shadow(0 4px 6px rgba(0, 0, 0, 0.3))" : void 0 }
1671
+ }
1672
+ ),
1673
+ /* @__PURE__ */ jsx5("text", { x: node.x, y: node.y, textAnchor: "middle", dominantBaseline: "central", fill: "white", fontSize: node.isRoot ? 12 : 10, fontWeight: "bold", children: node.label.charAt(0).toUpperCase() }),
1674
+ showLabel && /* @__PURE__ */ jsx5("text", { x: node.x, y: node.y + nodeSize + 14, textAnchor: "middle", fill: "#374151", fontSize: 11, fontWeight: node.isRoot ? 600 : 400, children: node.label.length > 20 ? `${node.label.substring(0, 18)}...` : node.label })
1675
+ ]
1676
+ }
1677
+ );
1678
+ };
1679
+ var GraphEdgeComponent = ({ edge, onClick, isHighlighted, showLabel }) => {
1680
+ const edgeType = edge.type || "default";
1681
+ const style = EDGE_STYLES[edgeType] ?? EDGE_STYLES.default ?? {};
1682
+ const dashArray = style.dashArray;
1683
+ const strokeWidth = (edge.strength || 0.5) * 2 + 1;
1684
+ const edgeColor = edge.color || "#6B7280";
1685
+ const dx = edge.targetNode.x - edge.sourceNode.x;
1686
+ const dy = edge.targetNode.y - edge.sourceNode.y;
1687
+ const dist = Math.sqrt(dx * dx + dy * dy) || 1;
1688
+ const sourceRadius = edge.sourceNode.isRoot ? 28 : 22;
1689
+ const targetRadius = edge.targetNode.isRoot ? 28 : 22;
1690
+ const startX = edge.sourceNode.x + dx / dist * sourceRadius;
1691
+ const startY = edge.sourceNode.y + dy / dist * sourceRadius;
1692
+ const endX = edge.targetNode.x - dx / dist * targetRadius;
1693
+ const endY = edge.targetNode.y - dy / dist * targetRadius;
1694
+ const midX = (startX + endX) / 2;
1695
+ const midY = (startY + endY) / 2;
1696
+ return (
1697
+ // biome-ignore lint/a11y/noStaticElementInteractions: SVG g element needs role="button" for accessibility when interactive
1698
+ /* @__PURE__ */ jsxs5("g", { style: { cursor: onClick ? "pointer" : "default" }, onClick, role: onClick ? "button" : void 0, tabIndex: onClick ? 0 : void 0, children: [
1699
+ /* @__PURE__ */ jsx5(
1700
+ motion.line,
1701
+ {
1702
+ x1: startX,
1703
+ y1: startY,
1704
+ x2: endX,
1705
+ y2: endY,
1706
+ stroke: isHighlighted ? "#1F2937" : edgeColor,
1707
+ strokeWidth: isHighlighted ? strokeWidth + 1 : strokeWidth,
1708
+ strokeDasharray: dashArray,
1709
+ initial: { pathLength: 0, opacity: 0 },
1710
+ animate: { pathLength: 1, opacity: 0.7 },
1711
+ transition: { duration: 0.5, delay: 0.2 },
1712
+ markerEnd: "url(#arrowhead)"
1713
+ }
1714
+ ),
1715
+ showLabel && edge.label && /* @__PURE__ */ jsxs5("g", { children: [
1716
+ /* @__PURE__ */ jsx5("rect", { x: midX - 30, y: midY - 8, width: 60, height: 16, rx: 4, fill: "white", fillOpacity: 0.9 }),
1717
+ /* @__PURE__ */ jsx5("text", { x: midX, y: midY + 4, textAnchor: "middle", fill: "#6B7280", fontSize: 9, children: edge.label })
1718
+ ] })
1719
+ ] })
1720
+ );
1721
+ };
1722
+ var NodeTooltip = ({ node, typeColors }) => {
1723
+ const nodeColor = node.color || typeColors[node.type] || typeColors.default || DEFAULT_TYPE_COLORS.default;
1724
+ return /* @__PURE__ */ jsx5(
1725
+ motion.foreignObject,
1726
+ {
1727
+ x: node.x + 30,
1728
+ y: node.y - 40,
1729
+ width: 200,
1730
+ height: 100,
1731
+ initial: { opacity: 0, scale: 0.9 },
1732
+ animate: { opacity: 1, scale: 1 },
1733
+ exit: { opacity: 0, scale: 0.9 },
1734
+ children: /* @__PURE__ */ jsxs5("div", { className: "rounded-lg border bg-white p-3 shadow-lg", children: [
1735
+ /* @__PURE__ */ jsxs5("div", { className: "mb-1 flex items-center gap-2", children: [
1736
+ /* @__PURE__ */ jsx5("span", { className: "h-2 w-2 rounded-full", style: { background: nodeColor } }),
1737
+ /* @__PURE__ */ jsx5("strong", { className: "text-sm", children: node.label })
1738
+ ] }),
1739
+ /* @__PURE__ */ jsxs5("div", { className: "text-content-tertiary text-xs", children: [
1740
+ "Type: ",
1741
+ node.type
1742
+ ] }),
1743
+ node.metadata && Object.entries(node.metadata).map(([key, value]) => /* @__PURE__ */ jsxs5("div", { className: "text-content-tertiary text-xs", children: [
1744
+ key,
1745
+ ": ",
1746
+ value
1747
+ ] }, key))
1748
+ ] })
1749
+ }
1750
+ );
1751
+ };
1752
+ var GraphLegend = ({ nodes, typeColors }) => {
1753
+ const types = useMemo(() => Array.from(new Set(nodes.map((n) => n.type))), [nodes]);
1754
+ return /* @__PURE__ */ jsxs5("div", { className: "absolute bottom-3 left-3 rounded-lg bg-white p-2 text-xs shadow-md", children: [
1755
+ /* @__PURE__ */ jsx5("div", { className: "text-content-primary mb-1.5 font-semibold", children: "Legend" }),
1756
+ types.map((type) => /* @__PURE__ */ jsxs5("div", { className: "mb-0.5 flex items-center gap-1.5", children: [
1757
+ /* @__PURE__ */ jsx5("span", { className: "h-2.5 w-2.5 rounded-full", style: { background: typeColors[type] || typeColors.default || DEFAULT_TYPE_COLORS.default } }),
1758
+ /* @__PURE__ */ jsx5("span", { className: "text-content-tertiary capitalize", children: type })
1759
+ ] }, type))
1760
+ ] });
1761
+ };
1762
+ function RelationshipGraph({
1763
+ nodes,
1764
+ edges,
1765
+ onNodeClick,
1766
+ onEdgeClick,
1767
+ width = 600,
1768
+ height = 400,
1769
+ animate: _animate = true,
1770
+ layout = "force",
1771
+ className,
1772
+ showLabels = true,
1773
+ showLegend = true,
1774
+ interactive = true,
1775
+ highlightNode,
1776
+ typeColors = DEFAULT_TYPE_COLORS
1777
+ }) {
1778
+ const [hoveredNode, setHoveredNode] = useState(null);
1779
+ const svgRef = useRef(null);
1780
+ const mergedColors = { ...DEFAULT_TYPE_COLORS, ...typeColors };
1781
+ const forceLayout = useForceLayout(layout === "force" ? nodes : [], layout === "force" ? edges : [], width, height);
1782
+ const hierarchicalLayout = useHierarchicalLayout(layout === "hierarchical" ? nodes : [], layout === "hierarchical" ? edges : [], width, height);
1783
+ const radialLayout = useRadialLayout(layout === "radial" ? nodes : [], layout === "radial" ? edges : [], width, height);
1784
+ const { positionedNodes, positionedEdges } = layout === "force" ? forceLayout : layout === "hierarchical" ? hierarchicalLayout : radialLayout;
1785
+ const handleNodeClick = useCallback(
1786
+ (node) => {
1787
+ if (onNodeClick && interactive) onNodeClick(node);
1788
+ },
1789
+ [onNodeClick, interactive]
1790
+ );
1791
+ const handleEdgeClick = useCallback(
1792
+ (edge) => {
1793
+ if (onEdgeClick && interactive) onEdgeClick(edge);
1794
+ },
1795
+ [onEdgeClick, interactive]
1796
+ );
1797
+ const hoveredNodeData = useMemo(() => positionedNodes.find((n) => n.id === hoveredNode), [positionedNodes, hoveredNode]);
1798
+ if (nodes.length === 0) {
1799
+ return /* @__PURE__ */ jsx5("div", { className: cx3("flex items-center justify-center rounded-lg border border-dashed bg-gray-50", className), style: { width, height }, children: /* @__PURE__ */ jsx5("p", { className: "text-content-tertiary text-sm", children: "No relationships to display" }) });
1800
+ }
1801
+ return /* @__PURE__ */ jsxs5("div", { className: cx3("relative", className), style: { width, height }, children: [
1802
+ /* @__PURE__ */ jsxs5("svg", { ref: svgRef, width, height, className: "rounded-lg border bg-gray-50", role: "img", "aria-label": "Relationship graph visualization", children: [
1803
+ /* @__PURE__ */ jsx5("defs", { children: /* @__PURE__ */ jsx5("marker", { id: "arrowhead", markerWidth: "10", markerHeight: "7", refX: "9", refY: "3.5", orient: "auto", children: /* @__PURE__ */ jsx5("polygon", { points: "0 0, 10 3.5, 0 7", fill: "#6B7280" }) }) }),
1804
+ /* @__PURE__ */ jsx5("g", { className: "edges", children: positionedEdges.map((edge) => /* @__PURE__ */ jsx5(
1805
+ GraphEdgeComponent,
1806
+ {
1807
+ edge,
1808
+ ...onEdgeClick ? { onClick: () => handleEdgeClick(edge) } : {},
1809
+ isHighlighted: hoveredNode === edge.source || hoveredNode === edge.target || highlightNode === edge.source || highlightNode === edge.target,
1810
+ showLabel: showLabels
1811
+ },
1812
+ edge.id
1813
+ )) }),
1814
+ /* @__PURE__ */ jsx5("g", { className: "nodes", children: positionedNodes.map((node) => /* @__PURE__ */ jsx5(
1815
+ GraphNodeComponent,
1816
+ {
1817
+ node,
1818
+ ...onNodeClick ? { onClick: () => handleNodeClick(node) } : {},
1819
+ showLabel: showLabels,
1820
+ isHighlighted: highlightNode === node.id,
1821
+ isHovered: hoveredNode === node.id,
1822
+ onHover: (hovering) => setHoveredNode(hovering ? node.id : null),
1823
+ typeColors: mergedColors
1824
+ },
1825
+ node.id
1826
+ )) }),
1827
+ /* @__PURE__ */ jsx5(AnimatePresence, { children: interactive && hoveredNodeData && /* @__PURE__ */ jsx5(NodeTooltip, { node: hoveredNodeData, typeColors: mergedColors }) })
1828
+ ] }),
1829
+ showLegend && /* @__PURE__ */ jsx5(GraphLegend, { nodes, typeColors: mergedColors })
1830
+ ] });
1831
+ }
1832
+
1833
+ // src/components/trend-indicator.tsx
1834
+ import { cx as cx4 } from "@enact-ui/react";
1835
+ import { ArrowDown, ArrowUp, Minus } from "lucide-react";
1836
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1837
+ var sizeStyles = {
1838
+ sm: {
1839
+ container: "text-xs gap-0.5",
1840
+ icon: "h-3 w-3"
1841
+ },
1842
+ md: {
1843
+ container: "text-sm gap-1",
1844
+ icon: "h-4 w-4"
1845
+ },
1846
+ lg: {
1847
+ container: "text-base gap-1",
1848
+ icon: "h-5 w-5"
1849
+ }
1850
+ };
1851
+ var TrendIndicator = ({ direction, value, inverted = false, size = "md", showPercent = true, className }) => {
1852
+ const isPositive = inverted ? direction === "down" : direction === "up";
1853
+ const isNegative = inverted ? direction === "up" : direction === "down";
1854
+ const colorClass = isPositive ? "text-content-success" : isNegative ? "text-content-error" : "text-content-tertiary";
1855
+ const Icon = direction === "up" ? ArrowUp : direction === "down" ? ArrowDown : Minus;
1856
+ const styles = sizeStyles[size];
1857
+ return /* @__PURE__ */ jsxs6("span", { className: cx4("inline-flex items-center font-medium", styles.container, colorClass, className), children: [
1858
+ /* @__PURE__ */ jsx6(Icon, { className: styles.icon }),
1859
+ /* @__PURE__ */ jsxs6("span", { children: [
1860
+ value,
1861
+ showPercent && "%"
1862
+ ] })
1863
+ ] });
1864
+ };
1865
+ var TrendBadge = ({ label, className, ...props }) => {
1866
+ const isPositive = props.inverted ? props.direction === "down" : props.direction === "up";
1867
+ const isNegative = props.inverted ? props.direction === "up" : props.direction === "down";
1868
+ const bgClass = isPositive ? "bg-surface-success-subtle" : isNegative ? "bg-surface-error-subtle" : "bg-surface-raised";
1869
+ return /* @__PURE__ */ jsxs6("span", { className: cx4("inline-flex items-center gap-1.5 rounded-full px-2 py-0.5", bgClass, className), children: [
1870
+ label && /* @__PURE__ */ jsx6("span", { className: "text-content-secondary text-xs", children: label }),
1871
+ /* @__PURE__ */ jsx6(TrendIndicator, { ...props })
1872
+ ] });
1873
+ };
61
1874
  export {
1875
+ BarChart,
1876
+ BarChart02,
1877
+ BarChart03,
62
1878
  ChartActiveDot,
63
1879
  ChartLegendContent,
64
1880
  ChartTooltipContent,
1881
+ LineChart01,
1882
+ LineChart02,
1883
+ LineChart03,
1884
+ LineChart04,
1885
+ PieChartLg,
1886
+ PieChartMd,
1887
+ PieChartSm,
1888
+ PieChartXs,
1889
+ PieChartXxs,
1890
+ RelationshipGraph,
1891
+ TrendBadge,
1892
+ TrendIndicator,
65
1893
  selectEvenlySpacedItems
66
1894
  };
67
1895
  //# sourceMappingURL=index.mjs.map