@ktnpm_devops/react-component 0.2.1 → 0.4.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 (285) hide show
  1. package/dist/index.cjs +38 -33
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.ts +5 -0
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +38 -33
  6. package/dist/index.js.map +1 -1
  7. package/dist/index10.cjs +15 -4
  8. package/dist/index10.cjs.map +1 -1
  9. package/dist/index10.js +15 -4
  10. package/dist/index10.js.map +1 -1
  11. package/dist/index11.cjs +4 -16
  12. package/dist/index11.cjs.map +1 -1
  13. package/dist/index11.js +4 -16
  14. package/dist/index11.js.map +1 -1
  15. package/dist/index12.cjs +16 -10
  16. package/dist/index12.cjs.map +1 -1
  17. package/dist/index12.js +16 -10
  18. package/dist/index12.js.map +1 -1
  19. package/dist/index13.cjs +10 -100
  20. package/dist/index13.cjs.map +1 -1
  21. package/dist/index13.js +11 -101
  22. package/dist/index13.js.map +1 -1
  23. package/dist/index14.cjs +100 -20
  24. package/dist/index14.cjs.map +1 -1
  25. package/dist/index14.js +101 -21
  26. package/dist/index14.js.map +1 -1
  27. package/dist/index15.cjs +20 -90
  28. package/dist/index15.cjs.map +1 -1
  29. package/dist/index15.js +21 -91
  30. package/dist/index15.js.map +1 -1
  31. package/dist/index16.cjs +40 -155
  32. package/dist/index16.cjs.map +1 -1
  33. package/dist/index16.js +42 -157
  34. package/dist/index16.js.map +1 -1
  35. package/dist/index17.cjs +86 -132
  36. package/dist/index17.cjs.map +1 -1
  37. package/dist/index17.js +88 -134
  38. package/dist/index17.js.map +1 -1
  39. package/dist/index18.cjs +150 -113
  40. package/dist/index18.cjs.map +1 -1
  41. package/dist/index18.js +151 -114
  42. package/dist/index18.js.map +1 -1
  43. package/dist/index19.cjs +136 -17
  44. package/dist/index19.cjs.map +1 -1
  45. package/dist/index19.js +136 -17
  46. package/dist/index19.js.map +1 -1
  47. package/dist/index20.cjs +120 -7
  48. package/dist/index20.cjs.map +1 -1
  49. package/dist/index20.js +122 -9
  50. package/dist/index20.js.map +1 -1
  51. package/dist/index21.cjs +16 -130
  52. package/dist/index21.cjs.map +1 -1
  53. package/dist/index21.js +16 -130
  54. package/dist/index21.js.map +1 -1
  55. package/dist/index22.cjs +8 -38
  56. package/dist/index22.cjs.map +1 -1
  57. package/dist/index22.js +9 -39
  58. package/dist/index22.js.map +1 -1
  59. package/dist/index23.cjs +118 -211
  60. package/dist/index23.cjs.map +1 -1
  61. package/dist/index23.js +119 -212
  62. package/dist/index23.js.map +1 -1
  63. package/dist/index24.cjs +38 -34
  64. package/dist/index24.cjs.map +1 -1
  65. package/dist/index24.js +39 -35
  66. package/dist/index24.js.map +1 -1
  67. package/dist/index25.cjs +211 -65
  68. package/dist/index25.cjs.map +1 -1
  69. package/dist/index25.js +211 -65
  70. package/dist/index25.js.map +1 -1
  71. package/dist/index26.cjs +29 -148
  72. package/dist/index26.cjs.map +1 -1
  73. package/dist/index26.js +31 -150
  74. package/dist/index26.js.map +1 -1
  75. package/dist/index27.cjs +77 -7
  76. package/dist/index27.cjs.map +1 -1
  77. package/dist/index27.js +79 -9
  78. package/dist/index27.js.map +1 -1
  79. package/dist/index28.cjs +59 -17
  80. package/dist/index28.cjs.map +1 -1
  81. package/dist/index28.js +60 -18
  82. package/dist/index28.js.map +1 -1
  83. package/dist/index29.cjs +146 -70
  84. package/dist/index29.cjs.map +1 -1
  85. package/dist/index29.js +148 -72
  86. package/dist/index29.js.map +1 -1
  87. package/dist/index3.cjs +76 -16
  88. package/dist/index3.cjs.map +1 -1
  89. package/dist/index3.js +76 -16
  90. package/dist/index3.js.map +1 -1
  91. package/dist/index30.cjs +7 -142
  92. package/dist/index30.cjs.map +1 -1
  93. package/dist/index30.js +9 -144
  94. package/dist/index30.js.map +1 -1
  95. package/dist/index31.cjs +15 -103
  96. package/dist/index31.cjs.map +1 -1
  97. package/dist/index31.js +14 -102
  98. package/dist/index31.js.map +1 -1
  99. package/dist/index32.cjs +77 -6
  100. package/dist/index32.cjs.map +1 -1
  101. package/dist/index32.js +78 -7
  102. package/dist/index32.js.map +1 -1
  103. package/dist/index33.cjs +133 -206
  104. package/dist/index33.cjs.map +1 -1
  105. package/dist/index33.js +134 -207
  106. package/dist/index33.js.map +1 -1
  107. package/dist/index34.cjs +104 -7
  108. package/dist/index34.cjs.map +1 -1
  109. package/dist/index34.js +106 -9
  110. package/dist/index34.js.map +1 -1
  111. package/dist/index35.cjs +8 -16
  112. package/dist/index35.cjs.map +1 -1
  113. package/dist/index35.js +7 -15
  114. package/dist/index35.js.map +1 -1
  115. package/dist/index36.cjs +218 -7
  116. package/dist/index36.cjs.map +1 -1
  117. package/dist/index36.js +217 -6
  118. package/dist/index36.js.map +1 -1
  119. package/dist/index37.cjs +10 -7
  120. package/dist/index37.cjs.map +1 -1
  121. package/dist/index37.js +9 -6
  122. package/dist/index37.js.map +1 -1
  123. package/dist/index38.cjs +15 -6
  124. package/dist/index38.cjs.map +1 -1
  125. package/dist/index38.js +15 -6
  126. package/dist/index38.js.map +1 -1
  127. package/dist/index39.cjs +9 -15
  128. package/dist/index39.cjs.map +1 -1
  129. package/dist/index39.js +10 -16
  130. package/dist/index39.js.map +1 -1
  131. package/dist/index4.cjs +12 -8
  132. package/dist/index4.cjs.map +1 -1
  133. package/dist/index4.js +12 -8
  134. package/dist/index4.js.map +1 -1
  135. package/dist/index40.cjs +24 -67
  136. package/dist/index40.cjs.map +1 -1
  137. package/dist/index40.js +23 -66
  138. package/dist/index40.js.map +1 -1
  139. package/dist/index41.cjs +10 -37
  140. package/dist/index41.cjs.map +1 -1
  141. package/dist/index41.js +10 -37
  142. package/dist/index41.js.map +1 -1
  143. package/dist/index42.cjs +2 -17
  144. package/dist/index42.cjs.map +1 -1
  145. package/dist/index42.js +3 -18
  146. package/dist/index42.js.map +1 -1
  147. package/dist/index43.cjs +2 -11
  148. package/dist/index43.cjs.map +1 -1
  149. package/dist/index43.js +2 -11
  150. package/dist/index43.js.map +1 -1
  151. package/dist/index44.cjs +22 -16
  152. package/dist/index44.cjs.map +1 -1
  153. package/dist/index44.js +22 -16
  154. package/dist/index44.js.map +1 -1
  155. package/dist/index45.cjs +16 -134
  156. package/dist/index45.cjs.map +1 -1
  157. package/dist/index45.js +15 -133
  158. package/dist/index45.js.map +1 -1
  159. package/dist/index46.cjs +15 -39
  160. package/dist/index46.cjs.map +1 -1
  161. package/dist/index46.js +16 -40
  162. package/dist/index46.js.map +1 -1
  163. package/dist/index47.cjs +16 -28
  164. package/dist/index47.cjs.map +1 -1
  165. package/dist/index47.js +16 -28
  166. package/dist/index47.js.map +1 -1
  167. package/dist/index48.cjs +67 -57
  168. package/dist/index48.cjs.map +1 -1
  169. package/dist/index48.js +66 -56
  170. package/dist/index48.js.map +1 -1
  171. package/dist/index49.cjs +77 -26
  172. package/dist/index49.cjs.map +1 -1
  173. package/dist/index49.js +77 -26
  174. package/dist/index49.js.map +1 -1
  175. package/dist/index5.cjs +9 -16
  176. package/dist/index5.cjs.map +1 -1
  177. package/dist/index5.js +10 -17
  178. package/dist/index5.js.map +1 -1
  179. package/dist/index51.cjs +30 -21
  180. package/dist/index51.cjs.map +1 -1
  181. package/dist/index51.js +30 -21
  182. package/dist/index51.js.map +1 -1
  183. package/dist/index52.cjs +13 -13
  184. package/dist/index52.js +14 -14
  185. package/dist/index54.cjs +1 -4
  186. package/dist/index54.cjs.map +1 -1
  187. package/dist/index54.js +1 -4
  188. package/dist/index54.js.map +1 -1
  189. package/dist/index55.cjs +5 -14
  190. package/dist/index55.cjs.map +1 -1
  191. package/dist/index55.js +5 -14
  192. package/dist/index55.js.map +1 -1
  193. package/dist/index56.cjs +37 -10
  194. package/dist/index56.cjs.map +1 -1
  195. package/dist/index56.js +37 -10
  196. package/dist/index56.js.map +1 -1
  197. package/dist/index57.cjs +2 -11
  198. package/dist/index57.cjs.map +1 -1
  199. package/dist/index57.js +2 -11
  200. package/dist/index57.js.map +1 -1
  201. package/dist/index58.cjs +13 -19
  202. package/dist/index58.cjs.map +1 -1
  203. package/dist/index58.js +13 -19
  204. package/dist/index58.js.map +1 -1
  205. package/dist/index59.cjs +27 -54
  206. package/dist/index59.cjs.map +1 -1
  207. package/dist/index59.js +28 -55
  208. package/dist/index59.js.map +1 -1
  209. package/dist/index6.cjs +19 -65
  210. package/dist/index6.cjs.map +1 -1
  211. package/dist/index6.js +19 -65
  212. package/dist/index6.js.map +1 -1
  213. package/dist/index60.cjs +64 -22
  214. package/dist/index60.cjs.map +1 -1
  215. package/dist/index60.js +64 -22
  216. package/dist/index60.js.map +1 -1
  217. package/dist/index61.cjs +15 -48
  218. package/dist/index61.cjs.map +1 -1
  219. package/dist/index61.js +16 -49
  220. package/dist/index61.js.map +1 -1
  221. package/dist/index62.cjs +16 -13
  222. package/dist/index62.cjs.map +1 -1
  223. package/dist/index62.js +17 -14
  224. package/dist/index62.js.map +1 -1
  225. package/dist/index63.cjs +27 -48
  226. package/dist/index63.cjs.map +1 -1
  227. package/dist/index63.js +27 -48
  228. package/dist/index63.js.map +1 -1
  229. package/dist/index64.cjs +13 -37
  230. package/dist/index64.cjs.map +1 -1
  231. package/dist/index64.js +14 -38
  232. package/dist/index64.js.map +1 -1
  233. package/dist/index65.cjs +45 -0
  234. package/dist/index65.cjs.map +1 -0
  235. package/dist/index65.js +45 -0
  236. package/dist/index65.js.map +1 -0
  237. package/dist/index66.cjs +136 -0
  238. package/dist/index66.cjs.map +1 -0
  239. package/dist/index66.js +136 -0
  240. package/dist/index66.js.map +1 -0
  241. package/dist/index67.cjs +48 -0
  242. package/dist/index67.cjs.map +1 -0
  243. package/dist/index67.js +48 -0
  244. package/dist/index67.js.map +1 -0
  245. package/dist/index68.cjs +60 -0
  246. package/dist/index68.cjs.map +1 -0
  247. package/dist/index68.js +60 -0
  248. package/dist/index68.js.map +1 -0
  249. package/dist/index69.cjs +57 -0
  250. package/dist/index69.cjs.map +1 -0
  251. package/dist/index69.js +57 -0
  252. package/dist/index69.js.map +1 -0
  253. package/dist/index7.cjs +58 -75
  254. package/dist/index7.cjs.map +1 -1
  255. package/dist/index7.js +58 -75
  256. package/dist/index7.js.map +1 -1
  257. package/dist/index8.cjs +82 -15
  258. package/dist/index8.cjs.map +1 -1
  259. package/dist/index8.js +82 -15
  260. package/dist/index8.js.map +1 -1
  261. package/dist/index9.cjs +14 -15
  262. package/dist/index9.cjs.map +1 -1
  263. package/dist/index9.js +15 -16
  264. package/dist/index9.js.map +1 -1
  265. package/dist/primitives/Col/Col.d.ts +4 -0
  266. package/dist/primitives/Col/Col.d.ts.map +1 -0
  267. package/dist/primitives/Col/Col.types.d.ts +13 -0
  268. package/dist/primitives/Col/Col.types.d.ts.map +1 -0
  269. package/dist/primitives/Col/index.d.ts +3 -0
  270. package/dist/primitives/Col/index.d.ts.map +1 -0
  271. package/dist/primitives/Row/Row.d.ts +4 -0
  272. package/dist/primitives/Row/Row.d.ts.map +1 -0
  273. package/dist/primitives/Row/Row.types.d.ts +16 -0
  274. package/dist/primitives/Row/Row.types.d.ts.map +1 -0
  275. package/dist/primitives/Row/index.d.ts +3 -0
  276. package/dist/primitives/Row/index.d.ts.map +1 -0
  277. package/dist/style.css +312 -0
  278. package/dist/tokens/semantic-tokens.css +21 -0
  279. package/dist/tokens/tokens.d.ts +35 -0
  280. package/dist/tokens/tokens.d.ts.map +1 -1
  281. package/package.json +3 -2
  282. package/dist/index2.cjs +0 -44
  283. package/dist/index2.cjs.map +0 -1
  284. package/dist/index2.js +0 -44
  285. package/dist/index2.js.map +0 -1
package/dist/index33.js CHANGED
@@ -1,220 +1,147 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
- import { useMemo, useCallback } from "react";
3
- import { clsx } from "./index35.js";
4
- import ReactECharts from "echarts-for-react";
5
- import { MAX_SERIES, CHART_COLORS } from "./index40.js";
6
- import styles from "./index64.js";
7
- function groupByCategory(data, limit) {
8
- const grouped = /* @__PURE__ */ new Map();
9
- for (const point of data) {
10
- const key = point.category ?? "Unknown";
11
- if (!grouped.has(key)) {
12
- grouped.set(key, []);
13
- }
14
- grouped.get(key).push({
15
- ts: point.ts ?? "",
16
- value: point.value
2
+ import { useState, useRef, useCallback, useMemo } from "react";
3
+ import { clsx } from "./index38.js";
4
+ import { useClickOutside } from "./index4.js";
5
+ import { useEscapeKey } from "./index5.js";
6
+ import { SVG_STROKE_WIDTH, SVG_VIEWBOX, ICON_SIZE } from "./index48.js";
7
+ import styles from "./index59.js";
8
+ const SingleSelectDropdown = ({
9
+ label,
10
+ options,
11
+ selected,
12
+ onSelect,
13
+ customTriggerLabel,
14
+ onClear,
15
+ showClearButton = false
16
+ }) => {
17
+ const [isOpen, setIsOpen] = useState(false);
18
+ const [searchTerm, setSearchTerm] = useState("");
19
+ const [focusedIndex, setFocusedIndex] = useState(-1);
20
+ const containerRef = useRef(null);
21
+ const listRef = useRef(null);
22
+ const close = useCallback(() => {
23
+ setIsOpen(false);
24
+ setSearchTerm("");
25
+ setFocusedIndex(-1);
26
+ }, []);
27
+ useClickOutside(containerRef, close);
28
+ useEscapeKey(close, isOpen);
29
+ const filteredOptions = useMemo(() => {
30
+ if (!searchTerm.trim()) return options;
31
+ const term = searchTerm.trim().toLowerCase();
32
+ return options.filter((opt) => {
33
+ const lbl = opt.label ?? opt.value;
34
+ return lbl.toLowerCase().includes(term) || opt.value.toLowerCase().includes(term);
17
35
  });
18
- }
19
- const entries = [...grouped.entries()].sort(
20
- (a, b) => b[1].reduce((sum, p) => sum + p.value, 0) - a[1].reduce((sum, p) => sum + p.value, 0)
21
- );
22
- if (entries.length <= limit) {
23
- return entries;
24
- }
25
- const top = entries.slice(0, limit - 1);
26
- const rest = entries.slice(limit - 1);
27
- const otherMap = /* @__PURE__ */ new Map();
28
- for (const [, points] of rest) {
29
- for (const p of points) {
30
- otherMap.set(p.ts, (otherMap.get(p.ts) ?? 0) + p.value);
31
- }
32
- }
33
- const otherPoints = [...otherMap.entries()].map(([ts, value]) => ({
34
- ts,
35
- value
36
- }));
37
- return [...top, ["Other", otherPoints]];
38
- }
39
- function buildMarkAreas(annotations) {
40
- return annotations.filter((a) => a.end).map((a) => [
41
- {
42
- name: a.label,
43
- xAxis: a.start,
44
- itemStyle: { color: a.color ?? "rgba(255,107,90,0.1)" }
45
- },
46
- { xAxis: a.end }
47
- ]);
48
- }
49
- function buildMarkLines(annotations) {
50
- return annotations.filter((a) => !a.end).map((a) => ({
51
- name: a.label,
52
- xAxis: a.start,
53
- lineStyle: { color: a.color ?? CHART_COLORS[0], type: "dashed" },
54
- label: { formatter: a.label, position: "end" }
55
- }));
56
- }
57
- function TemporalTrendChartCard({
58
- title,
59
- data,
60
- isLoading = false,
61
- error,
62
- onRetry,
63
- onChartReady,
64
- actions,
65
- className,
66
- groupBy,
67
- groupOptions,
68
- onGroupChange,
69
- granularity,
70
- granularityOptions,
71
- onGranularityChange,
72
- annotations = [],
73
- showLegend = true,
74
- onToggleLegend,
75
- onSeriesSelect,
76
- onBucketSelect,
77
- maxSeries = MAX_SERIES
78
- }) {
79
- const seriesGroups = useMemo(
80
- () => groupByCategory(data, maxSeries),
81
- [data, maxSeries]
82
- );
83
- const option = useMemo(() => {
84
- const markAreas = buildMarkAreas(annotations);
85
- const markLines = buildMarkLines(annotations);
86
- const series = seriesGroups.map(([name, points], idx) => ({
87
- name,
88
- type: "line",
89
- stack: "total",
90
- areaStyle: {},
91
- emphasis: { focus: "series" },
92
- color: CHART_COLORS[idx % CHART_COLORS.length],
93
- data: points.sort((a, b) => a.ts < b.ts ? -1 : 1).map((p) => [p.ts, p.value]),
94
- ...idx === 0 && (markAreas.length > 0 || markLines.length > 0) ? {
95
- markArea: markAreas.length > 0 ? { silent: true, data: markAreas } : void 0,
96
- markLine: markLines.length > 0 ? { silent: true, symbol: "none", data: markLines } : void 0
97
- } : {}
98
- }));
99
- return {
100
- tooltip: {
101
- trigger: "axis",
102
- axisPointer: { type: "cross" }
103
- },
104
- legend: {
105
- show: showLegend,
106
- type: "scroll",
107
- bottom: 0
108
- },
109
- grid: {
110
- left: "3%",
111
- right: "4%",
112
- bottom: showLegend ? "15%" : "3%",
113
- containLabel: true
114
- },
115
- xAxis: { type: "time" },
116
- yAxis: { type: "value" },
117
- series
118
- };
119
- }, [seriesGroups, annotations, showLegend]);
120
- const handleChartReady = useCallback(
121
- (instance) => {
122
- onChartReady == null ? void 0 : onChartReady(instance);
123
- },
124
- [onChartReady]
125
- );
126
- const handleEvents = useMemo(() => {
127
- const events = {};
128
- if (onSeriesSelect) {
129
- events["legendselectchanged"] = (params) => {
130
- const p = params;
131
- onSeriesSelect(p.name);
132
- };
36
+ }, [options, searchTerm]);
37
+ const handleSelect = (value) => {
38
+ onSelect(value);
39
+ close();
40
+ };
41
+ const handleClear = (e) => {
42
+ e.stopPropagation();
43
+ onClear == null ? void 0 : onClear();
44
+ close();
45
+ };
46
+ const handleKeyDown = (e) => {
47
+ if (!isOpen) return;
48
+ if (e.key === "ArrowDown") {
49
+ e.preventDefault();
50
+ setFocusedIndex((prev) => Math.min(prev + 1, filteredOptions.length - 1));
51
+ } else if (e.key === "ArrowUp") {
52
+ e.preventDefault();
53
+ setFocusedIndex((prev) => Math.max(prev - 1, 0));
54
+ } else if (e.key === "Enter" && focusedIndex >= 0 && focusedIndex < filteredOptions.length) {
55
+ e.preventDefault();
56
+ handleSelect(filteredOptions[focusedIndex].value);
133
57
  }
134
- if (onBucketSelect) {
135
- events["brushSelected"] = (params) => {
136
- var _a, _b, _c;
137
- const p = params;
138
- const area = (_c = (_b = (_a = p.batch) == null ? void 0 : _a[0]) == null ? void 0 : _b.areas) == null ? void 0 : _c[0];
139
- if (area) {
140
- onBucketSelect({ start: area.coordRange[0], end: area.coordRange[1] });
141
- }
142
- };
143
- }
144
- return events;
145
- }, [onSeriesSelect, onBucketSelect]);
146
- const hasToolbar = groupOptions || granularityOptions || onToggleLegend;
147
- const hasData = data.length > 0;
148
- return /* @__PURE__ */ jsxs("div", { className: clsx(styles.root, className), children: [
149
- /* @__PURE__ */ jsxs("div", { className: styles.header, children: [
150
- /* @__PURE__ */ jsx("span", { className: styles.title, children: title }),
151
- /* @__PURE__ */ jsxs("div", { className: styles.headerRight, children: [
152
- hasToolbar && /* @__PURE__ */ jsxs("div", { className: styles.toolbar, children: [
153
- groupOptions && groupOptions.length > 0 && /* @__PURE__ */ jsx(
154
- "select",
155
- {
156
- className: styles.select,
157
- value: groupBy ?? "",
158
- onChange: (e) => onGroupChange == null ? void 0 : onGroupChange(e.target.value),
159
- "aria-label": "Group by",
160
- children: groupOptions.map((opt) => /* @__PURE__ */ jsx("option", { value: opt.value, children: opt.label }, opt.value))
161
- }
162
- ),
163
- granularityOptions && granularityOptions.length > 0 && /* @__PURE__ */ jsx(
164
- "select",
58
+ };
59
+ const selectedOption = options.find((o) => o.value === selected);
60
+ const displayLabel = customTriggerLabel || (selectedOption == null ? void 0 : selectedOption.label) || (selectedOption == null ? void 0 : selectedOption.value) || "Select";
61
+ const showClear = showClearButton && selected !== null;
62
+ return /* @__PURE__ */ jsxs("div", { className: styles.root, ref: containerRef, onKeyDown: handleKeyDown, children: [
63
+ /* @__PURE__ */ jsx(
64
+ "button",
65
+ {
66
+ type: "button",
67
+ className: clsx(styles.trigger, { [styles.active]: isOpen }),
68
+ onClick: () => {
69
+ setIsOpen((prev) => !prev);
70
+ setFocusedIndex(-1);
71
+ },
72
+ "aria-expanded": isOpen,
73
+ "aria-haspopup": "listbox",
74
+ children: /* @__PURE__ */ jsxs("div", { className: styles.triggerContent, children: [
75
+ /* @__PURE__ */ jsx("svg", { className: styles.chevron, width: ICON_SIZE.MD, height: ICON_SIZE.MD, viewBox: SVG_VIEWBOX, fill: "none", stroke: "currentColor", strokeWidth: SVG_STROKE_WIDTH, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("polyline", { points: "6 9 12 15 18 9" }) }),
76
+ /* @__PURE__ */ jsx("span", { className: styles.label, children: label }),
77
+ /* @__PURE__ */ jsx("span", { className: styles.value, children: displayLabel }),
78
+ showClear && /* @__PURE__ */ jsx(
79
+ "span",
165
80
  {
166
- className: styles.select,
167
- value: granularity ?? "",
168
- onChange: (e) => onGranularityChange == null ? void 0 : onGranularityChange(e.target.value || null),
169
- "aria-label": "Granularity",
170
- children: granularityOptions.map((opt) => /* @__PURE__ */ jsx("option", { value: opt.value, children: opt.label }, opt.value))
81
+ className: styles.clear,
82
+ onClick: handleClear,
83
+ role: "button",
84
+ tabIndex: 0,
85
+ "aria-label": `Clear ${label}`,
86
+ onKeyDown: (e) => {
87
+ if (e.key === "Enter" || e.key === " ") {
88
+ e.preventDefault();
89
+ handleClear(e);
90
+ }
91
+ },
92
+ children: /* @__PURE__ */ jsxs("svg", { width: ICON_SIZE.SM, height: ICON_SIZE.SM, viewBox: SVG_VIEWBOX, fill: "none", stroke: "currentColor", strokeWidth: SVG_STROKE_WIDTH, strokeLinecap: "round", strokeLinejoin: "round", children: [
93
+ /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
94
+ /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
95
+ ] })
171
96
  }
172
- ),
173
- onToggleLegend && /* @__PURE__ */ jsx(
97
+ )
98
+ ] })
99
+ }
100
+ ),
101
+ isOpen && /* @__PURE__ */ jsxs("div", { className: styles.panel, role: "listbox", ref: listRef, children: [
102
+ /* @__PURE__ */ jsx("div", { className: styles.searchContainer, children: /* @__PURE__ */ jsx(
103
+ "input",
104
+ {
105
+ type: "search",
106
+ className: styles.search,
107
+ placeholder: `Search ${label.toLowerCase()}`,
108
+ value: searchTerm,
109
+ onChange: (e) => {
110
+ setSearchTerm(e.target.value);
111
+ setFocusedIndex(-1);
112
+ },
113
+ onClick: (e) => e.stopPropagation()
114
+ }
115
+ ) }),
116
+ /* @__PURE__ */ jsxs("div", { className: styles.list, children: [
117
+ filteredOptions.length === 0 && /* @__PURE__ */ jsx("div", { className: styles.noResults, children: "No matches found" }),
118
+ filteredOptions.map((opt, i) => {
119
+ const isSelected = opt.value === selected;
120
+ const isFocused = i === focusedIndex;
121
+ return /* @__PURE__ */ jsx(
174
122
  "button",
175
123
  {
176
124
  type: "button",
177
- className: clsx(
178
- styles.legendToggle,
179
- showLegend && styles.legendToggleActive
180
- ),
181
- onClick: onToggleLegend,
182
- "aria-label": "Toggle legend",
183
- children: "Legend"
184
- }
185
- )
186
- ] }),
187
- actions
125
+ className: clsx(styles.option, {
126
+ [styles.selected]: isSelected,
127
+ [styles.focused]: isFocused
128
+ }),
129
+ onClick: () => handleSelect(opt.value),
130
+ role: "option",
131
+ "aria-selected": isSelected,
132
+ children: /* @__PURE__ */ jsxs("span", { className: styles.optionLabel, children: [
133
+ opt.label ?? opt.value,
134
+ opt.count !== void 0 && /* @__PURE__ */ jsx("span", { className: styles.optionCount, children: opt.count })
135
+ ] })
136
+ },
137
+ opt.value
138
+ );
139
+ })
188
140
  ] })
189
- ] }),
190
- isLoading && /* @__PURE__ */ jsx("div", { className: styles.loading, children: "Loading chart data..." }),
191
- !isLoading && error && /* @__PURE__ */ jsxs("div", { className: styles.error, children: [
192
- /* @__PURE__ */ jsx("span", { children: error }),
193
- onRetry && /* @__PURE__ */ jsx(
194
- "button",
195
- {
196
- type: "button",
197
- className: styles.retryButton,
198
- onClick: onRetry,
199
- children: "Retry"
200
- }
201
- )
202
- ] }),
203
- !isLoading && !error && !hasData && /* @__PURE__ */ jsx("div", { className: styles.empty, children: "No data available" }),
204
- !isLoading && !error && hasData && /* @__PURE__ */ jsx("div", { className: styles.chartContainer, children: /* @__PURE__ */ jsx(
205
- ReactECharts,
206
- {
207
- option,
208
- style: { height: "100%", minHeight: "18.75rem" },
209
- onChartReady: handleChartReady,
210
- onEvents: handleEvents,
211
- notMerge: true
212
- }
213
- ) })
141
+ ] })
214
142
  ] });
215
- }
216
- TemporalTrendChartCard.displayName = "TemporalTrendChartCard";
143
+ };
217
144
  export {
218
- TemporalTrendChartCard
145
+ SingleSelectDropdown
219
146
  };
220
147
  //# sourceMappingURL=index33.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index33.js","sources":["../src/charts/TemporalTrendChartCard/TemporalTrendChartCard.tsx"],"sourcesContent":["import { useMemo, useCallback } from 'react';\nimport clsx from 'clsx';\nimport ReactECharts from 'echarts-for-react';\nimport type { TemporalTrendChartCardProps } from './TemporalTrendChartCard.types';\nimport type { EChartsInstance, ChartAnnotation } from '../../types/chart.types';\nimport { MAX_SERIES, CHART_COLORS } from '../../constants';\nimport styles from './TemporalTrendChartCard.module.css';\n\n/** Group data points by category, returning sorted series keyed by category name. */\nfunction groupByCategory(\n data: TemporalTrendChartCardProps['data'],\n limit: number,\n) {\n const grouped = new Map<string, { ts: string; value: number }[]>();\n\n for (const point of data) {\n const key = point.category ?? 'Unknown';\n if (!grouped.has(key)) {\n grouped.set(key, []);\n }\n grouped.get(key)!.push({\n ts: point.ts ?? '',\n value: point.value,\n });\n }\n\n const entries = [...grouped.entries()].sort(\n (a, b) =>\n b[1].reduce((sum, p) => sum + p.value, 0) -\n a[1].reduce((sum, p) => sum + p.value, 0),\n );\n\n if (entries.length <= limit) {\n return entries;\n }\n\n const top = entries.slice(0, limit - 1);\n const rest = entries.slice(limit - 1);\n\n const otherMap = new Map<string, number>();\n for (const [, points] of rest) {\n for (const p of points) {\n otherMap.set(p.ts, (otherMap.get(p.ts) ?? 0) + p.value);\n }\n }\n\n const otherPoints = [...otherMap.entries()].map(([ts, value]) => ({\n ts,\n value,\n }));\n\n return [...top, ['Other', otherPoints] as const] as Array<\n [string, { ts: string; value: number }[]]\n >;\n}\n\n/** Build markArea items from range annotations. */\nfunction buildMarkAreas(annotations: ChartAnnotation[]) {\n return annotations\n .filter((a) => a.end)\n .map((a) => [\n {\n name: a.label,\n xAxis: a.start,\n itemStyle: { color: a.color ?? 'rgba(255,107,90,0.1)' },\n },\n { xAxis: a.end },\n ]);\n}\n\n/** Build markLine items from point annotations. */\nfunction buildMarkLines(annotations: ChartAnnotation[]) {\n return annotations\n .filter((a) => !a.end)\n .map((a) => ({\n name: a.label,\n xAxis: a.start,\n lineStyle: { color: a.color ?? CHART_COLORS[0], type: 'dashed' as const },\n label: { formatter: a.label, position: 'end' as const },\n }));\n}\n\nexport function TemporalTrendChartCard({\n title,\n data,\n isLoading = false,\n error,\n onRetry,\n onChartReady,\n actions,\n className,\n groupBy,\n groupOptions,\n onGroupChange,\n granularity,\n granularityOptions,\n onGranularityChange,\n annotations = [],\n showLegend = true,\n onToggleLegend,\n onSeriesSelect,\n onBucketSelect,\n maxSeries = MAX_SERIES,\n}: TemporalTrendChartCardProps) {\n const seriesGroups = useMemo(\n () => groupByCategory(data, maxSeries),\n [data, maxSeries],\n );\n\n const option = useMemo(() => {\n const markAreas = buildMarkAreas(annotations);\n const markLines = buildMarkLines(annotations);\n\n const series = seriesGroups.map(([name, points], idx) => ({\n name,\n type: 'line' as const,\n stack: 'total',\n areaStyle: {},\n emphasis: { focus: 'series' as const },\n color: CHART_COLORS[idx % CHART_COLORS.length],\n data: points\n .sort((a, b) => (a.ts < b.ts ? -1 : 1))\n .map((p) => [p.ts, p.value]),\n ...(idx === 0 && (markAreas.length > 0 || markLines.length > 0)\n ? {\n markArea:\n markAreas.length > 0 ? { silent: true, data: markAreas } : undefined,\n markLine:\n markLines.length > 0\n ? { silent: true, symbol: 'none', data: markLines }\n : undefined,\n }\n : {}),\n }));\n\n return {\n tooltip: {\n trigger: 'axis' as const,\n axisPointer: { type: 'cross' as const },\n },\n legend: {\n show: showLegend,\n type: 'scroll' as const,\n bottom: 0,\n },\n grid: {\n left: '3%',\n right: '4%',\n bottom: showLegend ? '15%' : '3%',\n containLabel: true,\n },\n xAxis: { type: 'time' as const },\n yAxis: { type: 'value' as const },\n series,\n };\n }, [seriesGroups, annotations, showLegend]);\n\n const handleChartReady = useCallback(\n (instance: EChartsInstance) => {\n onChartReady?.(instance);\n },\n [onChartReady],\n );\n\n const handleEvents = useMemo(() => {\n const events: Record<string, (...args: unknown[]) => void> = {};\n\n if (onSeriesSelect) {\n events['legendselectchanged'] = (params: unknown) => {\n const p = params as { name: string };\n onSeriesSelect(p.name);\n };\n }\n\n if (onBucketSelect) {\n events['brushSelected'] = (params: unknown) => {\n const p = params as {\n batch: { areas: { coordRange: [string, string] }[] }[];\n };\n const area = p.batch?.[0]?.areas?.[0];\n if (area) {\n onBucketSelect({ start: area.coordRange[0], end: area.coordRange[1] });\n }\n };\n }\n\n return events;\n }, [onSeriesSelect, onBucketSelect]);\n\n const hasToolbar = groupOptions || granularityOptions || onToggleLegend;\n const hasData = data.length > 0;\n\n return (\n <div className={clsx(styles.root, className)}>\n <div className={styles.header}>\n <span className={styles.title}>{title}</span>\n <div className={styles.headerRight}>\n {hasToolbar && (\n <div className={styles.toolbar}>\n {groupOptions && groupOptions.length > 0 && (\n <select\n className={styles.select}\n value={groupBy ?? ''}\n onChange={(e) => onGroupChange?.(e.target.value)}\n aria-label=\"Group by\"\n >\n {groupOptions.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n )}\n {granularityOptions && granularityOptions.length > 0 && (\n <select\n className={styles.select}\n value={granularity ?? ''}\n onChange={(e) =>\n onGranularityChange?.(e.target.value || null)\n }\n aria-label=\"Granularity\"\n >\n {granularityOptions.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n )}\n {onToggleLegend && (\n <button\n type=\"button\"\n className={clsx(\n styles.legendToggle,\n showLegend && styles.legendToggleActive,\n )}\n onClick={onToggleLegend}\n aria-label=\"Toggle legend\"\n >\n Legend\n </button>\n )}\n </div>\n )}\n {actions}\n </div>\n </div>\n\n {isLoading && <div className={styles.loading}>Loading chart data...</div>}\n\n {!isLoading && error && (\n <div className={styles.error}>\n <span>{error}</span>\n {onRetry && (\n <button\n type=\"button\"\n className={styles.retryButton}\n onClick={onRetry}\n >\n Retry\n </button>\n )}\n </div>\n )}\n\n {!isLoading && !error && !hasData && (\n <div className={styles.empty}>No data available</div>\n )}\n\n {!isLoading && !error && hasData && (\n <div className={styles.chartContainer}>\n <ReactECharts\n option={option}\n style={{ height: '100%', minHeight: '18.75rem' }}\n onChartReady={handleChartReady}\n onEvents={handleEvents}\n notMerge\n />\n </div>\n )}\n </div>\n );\n}\n\nTemporalTrendChartCard.displayName = 'TemporalTrendChartCard';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index33.js","sources":["../src/composites/SingleSelectDropdown/SingleSelectDropdown.tsx"],"sourcesContent":["import { useState, useRef, useMemo, useCallback } from 'react';\nimport clsx from 'clsx';\nimport { useClickOutside } from '../../hooks/useClickOutside';\nimport { useEscapeKey } from '../../hooks/useEscapeKey';\nimport { ICON_SIZE, SVG_VIEWBOX, SVG_STROKE_WIDTH } from '../../constants';\nimport styles from './SingleSelectDropdown.module.css';\n\nexport interface SingleSelectOption {\n value: string;\n label?: string;\n count?: number;\n}\n\nexport interface SingleSelectDropdownProps {\n /** Label displayed on the trigger. */\n label: string;\n /** Available options. */\n options: SingleSelectOption[];\n /** Currently selected value (controlled). `null` means no selection. */\n selected: string | null;\n /** Called when the user selects an option. */\n onSelect: (value: string) => void;\n /** Override the trigger value label. */\n customTriggerLabel?: string;\n /** Called when the user clears the selection. */\n onClear?: () => void;\n /** Show clear button when a value is selected. */\n showClearButton?: boolean;\n}\n\nexport const SingleSelectDropdown = ({\n label,\n options,\n selected,\n onSelect,\n customTriggerLabel,\n onClear,\n showClearButton = false,\n}: SingleSelectDropdownProps) => {\n const [isOpen, setIsOpen] = useState(false);\n const [searchTerm, setSearchTerm] = useState('');\n const [focusedIndex, setFocusedIndex] = useState(-1);\n const containerRef = useRef<HTMLDivElement>(null);\n const listRef = useRef<HTMLDivElement>(null);\n\n const close = useCallback(() => {\n setIsOpen(false);\n setSearchTerm('');\n setFocusedIndex(-1);\n }, []);\n\n useClickOutside(containerRef, close);\n useEscapeKey(close, isOpen);\n\n const filteredOptions = useMemo(() => {\n if (!searchTerm.trim()) return options;\n const term = searchTerm.trim().toLowerCase();\n return options.filter((opt) => {\n const lbl = opt.label ?? opt.value;\n return lbl.toLowerCase().includes(term) || opt.value.toLowerCase().includes(term);\n });\n }, [options, searchTerm]);\n\n const handleSelect = (value: string) => {\n onSelect(value);\n close();\n };\n\n const handleClear = (e: React.MouseEvent) => {\n e.stopPropagation();\n onClear?.();\n close();\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (!isOpen) return;\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setFocusedIndex((prev) => Math.min(prev + 1, filteredOptions.length - 1));\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n setFocusedIndex((prev) => Math.max(prev - 1, 0));\n } else if (e.key === 'Enter' && focusedIndex >= 0 && focusedIndex < filteredOptions.length) {\n e.preventDefault();\n handleSelect(filteredOptions[focusedIndex].value);\n }\n };\n\n const selectedOption = options.find((o) => o.value === selected);\n const displayLabel = customTriggerLabel || selectedOption?.label || selectedOption?.value || 'Select';\n const showClear = showClearButton && selected !== null;\n\n return (\n <div className={styles.root} ref={containerRef} onKeyDown={handleKeyDown}>\n <button\n type=\"button\"\n className={clsx(styles.trigger, { [styles.active]: isOpen })}\n onClick={() => {\n setIsOpen((prev) => !prev);\n setFocusedIndex(-1);\n }}\n aria-expanded={isOpen}\n aria-haspopup=\"listbox\"\n >\n <div className={styles.triggerContent}>\n <svg className={styles.chevron} width={ICON_SIZE.MD} height={ICON_SIZE.MD} viewBox={SVG_VIEWBOX} fill=\"none\" stroke=\"currentColor\" strokeWidth={SVG_STROKE_WIDTH} strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n <span className={styles.label}>{label}</span>\n <span className={styles.value}>{displayLabel}</span>\n {showClear && (\n <span\n className={styles.clear}\n onClick={handleClear}\n role=\"button\"\n tabIndex={0}\n aria-label={`Clear ${label}`}\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); handleClear(e as unknown as React.MouseEvent); } }}\n >\n <svg width={ICON_SIZE.SM} height={ICON_SIZE.SM} viewBox={SVG_VIEWBOX} fill=\"none\" stroke=\"currentColor\" strokeWidth={SVG_STROKE_WIDTH} strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </span>\n )}\n </div>\n </button>\n\n {isOpen && (\n <div className={styles.panel} role=\"listbox\" ref={listRef}>\n <div className={styles.searchContainer}>\n <input\n type=\"search\"\n className={styles.search}\n placeholder={`Search ${label.toLowerCase()}`}\n value={searchTerm}\n onChange={(e) => {\n setSearchTerm(e.target.value);\n setFocusedIndex(-1);\n }}\n onClick={(e) => e.stopPropagation()}\n />\n </div>\n <div className={styles.list}>\n {filteredOptions.length === 0 && (\n <div className={styles.noResults}>No matches found</div>\n )}\n {filteredOptions.map((opt, i) => {\n const isSelected = opt.value === selected;\n const isFocused = i === focusedIndex;\n return (\n <button\n key={opt.value}\n type=\"button\"\n className={clsx(styles.option, {\n [styles.selected]: isSelected,\n [styles.focused]: isFocused,\n })}\n onClick={() => handleSelect(opt.value)}\n role=\"option\"\n aria-selected={isSelected}\n >\n <span className={styles.optionLabel}>\n {opt.label ?? opt.value}\n {opt.count !== undefined && (\n <span className={styles.optionCount}>{opt.count}</span>\n )}\n </span>\n </button>\n );\n })}\n </div>\n </div>\n )}\n </div>\n );\n};\n"],"names":[],"mappings":"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"}
package/dist/index34.cjs CHANGED
@@ -2,11 +2,108 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const react = require("react");
5
- const clsx = require("./index35.cjs");
6
- const Textarea_module = require("./index36.cjs");
7
- const Textarea = react.forwardRef(
8
- ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("textarea", { ref, className: clsx.clsx(Textarea_module.default.root, className), ...props })
9
- );
10
- Textarea.displayName = "Textarea";
11
- exports.Textarea = Textarea;
5
+ const ReactECharts = require("echarts-for-react");
6
+ const clsx = require("./index38.cjs");
7
+ const constants = require("./index48.cjs");
8
+ const buildChartOptions = require("./index66.cjs");
9
+ const StackedBarChartCard_module = require("./index67.cjs");
10
+ const CHART_TYPE_LABELS = {
11
+ bar: "Bar",
12
+ pie: "Pie",
13
+ sunburst: "Sunburst"
14
+ };
15
+ const CHART_TYPES = ["bar", "pie", "sunburst"];
16
+ const StackedBarChartCard = ({
17
+ title,
18
+ data,
19
+ subtitle,
20
+ chartType = "bar",
21
+ isLoading = false,
22
+ error,
23
+ onRetry,
24
+ onChartReady,
25
+ onSelectCategory,
26
+ // onAnalyzeRootCause — reserved for context menu integration
27
+ maxCategories = constants.MAX_CATEGORIES,
28
+ maxSubcategories = constants.MAX_SUBCATEGORIES,
29
+ showOthersBucket = true,
30
+ invertAxis = false,
31
+ hideLegend = false,
32
+ enableScroll = false,
33
+ toolbar,
34
+ actions,
35
+ className
36
+ }) => {
37
+ const { categories, series } = react.useMemo(
38
+ () => buildChartOptions.aggregateData(data, maxCategories, maxSubcategories, showOthersBucket),
39
+ [data, maxCategories, maxSubcategories, showOthersBucket]
40
+ );
41
+ const option = react.useMemo(() => {
42
+ switch (chartType) {
43
+ case "pie":
44
+ return buildChartOptions.buildPieOption(categories, series, hideLegend);
45
+ case "sunburst":
46
+ return buildChartOptions.buildSunburstOption(categories, series);
47
+ default:
48
+ return buildChartOptions.buildBarOption(categories, series, invertAxis, hideLegend, enableScroll);
49
+ }
50
+ }, [chartType, categories, series, invertAxis, hideLegend, enableScroll]);
51
+ const handleChartReady = react.useCallback(
52
+ (instance) => {
53
+ onChartReady == null ? void 0 : onChartReady(instance);
54
+ },
55
+ [onChartReady]
56
+ );
57
+ const handleChartClick = react.useCallback(
58
+ (params) => {
59
+ if (!onSelectCategory || !params.name) return;
60
+ onSelectCategory({
61
+ category: params.name,
62
+ subCategory: params.seriesName ?? null
63
+ });
64
+ },
65
+ [onSelectCategory]
66
+ );
67
+ const hasData = data.length > 0;
68
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx.clsx(StackedBarChartCard_module.default.root, className), children: [
69
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: StackedBarChartCard_module.default.header, children: [
70
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: StackedBarChartCard_module.default.headerLeft, children: [
71
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: StackedBarChartCard_module.default.title, children: title }),
72
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx("div", { className: StackedBarChartCard_module.default.subtitle, children: subtitle })
73
+ ] }),
74
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: StackedBarChartCard_module.default.headerRight, children: [
75
+ toolbar && /* @__PURE__ */ jsxRuntime.jsx("div", { className: StackedBarChartCard_module.default.toolbar, children: toolbar }),
76
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: StackedBarChartCard_module.default.chartTypeToggle, children: CHART_TYPES.map((type) => /* @__PURE__ */ jsxRuntime.jsx(
77
+ "button",
78
+ {
79
+ type: "button",
80
+ className: chartType === type ? StackedBarChartCard_module.default.active : void 0,
81
+ "aria-pressed": chartType === type,
82
+ disabled: true,
83
+ children: CHART_TYPE_LABELS[type]
84
+ },
85
+ type
86
+ )) }),
87
+ actions
88
+ ] })
89
+ ] }),
90
+ isLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: StackedBarChartCard_module.default.loading, children: "Loading chart data..." }),
91
+ !isLoading && error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: StackedBarChartCard_module.default.error, children: [
92
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: error }),
93
+ onRetry && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: StackedBarChartCard_module.default.retryButton, onClick: onRetry, children: "Retry" })
94
+ ] }),
95
+ !isLoading && !error && !hasData && /* @__PURE__ */ jsxRuntime.jsx("div", { className: StackedBarChartCard_module.default.empty, children: "No data available" }),
96
+ !isLoading && !error && hasData && /* @__PURE__ */ jsxRuntime.jsx("div", { className: StackedBarChartCard_module.default.chartContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
97
+ ReactECharts,
98
+ {
99
+ option,
100
+ style: { height: "100%", width: "100%" },
101
+ onChartReady: handleChartReady,
102
+ onEvents: { click: handleChartClick },
103
+ notMerge: true
104
+ }
105
+ ) })
106
+ ] });
107
+ };
108
+ exports.StackedBarChartCard = StackedBarChartCard;
12
109
  //# sourceMappingURL=index34.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index34.cjs","sources":["../src/primitives/Textarea/Textarea.tsx"],"sourcesContent":["import { forwardRef } from 'react';\nimport clsx from 'clsx';\nimport styles from './Textarea.module.css';\n\nexport interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}\n\nexport const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, ...props }, ref) => (\n <textarea ref={ref} className={clsx(styles.root, className)} {...props} />\n ),\n);\n\nTextarea.displayName = 'Textarea';\n"],"names":["forwardRef","jsx","clsx","styles"],"mappings":";;;;;;AAMO,MAAM,WAAWA,MAAAA;AAAAA,EACtB,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QACxBC,2BAAAA,IAAC,YAAA,EAAS,KAAU,WAAWC,KAAAA,KAAKC,gBAAAA,QAAO,MAAM,SAAS,GAAI,GAAG,MAAA,CAAO;AAE5E;AAEA,SAAS,cAAc;;"}
1
+ {"version":3,"file":"index34.cjs","sources":["../src/charts/StackedBarChartCard/StackedBarChartCard.tsx"],"sourcesContent":["import { useMemo, useCallback } from 'react';\nimport ReactECharts from 'echarts-for-react';\nimport clsx from 'clsx';\nimport type { EChartsInstance } from '../../types/chart.types';\nimport { MAX_CATEGORIES, MAX_SUBCATEGORIES } from '../../constants';\nimport type { StackedBarChartCardProps, StackedBarChartType } from './StackedBarChartCard.types';\nimport { aggregateData, buildBarOption, buildPieOption, buildSunburstOption } from './buildChartOptions';\nimport styles from './StackedBarChartCard.module.css';\n\n/** Label map for chart type toggle buttons. */\nconst CHART_TYPE_LABELS: Record<StackedBarChartType, string> = {\n bar: 'Bar',\n pie: 'Pie',\n sunburst: 'Sunburst',\n};\n\n/** All available chart types for the toggle group. */\nconst CHART_TYPES: StackedBarChartType[] = ['bar', 'pie', 'sunburst'];\n\nexport const StackedBarChartCard = ({\n title,\n data,\n subtitle,\n chartType = 'bar',\n isLoading = false,\n error,\n onRetry,\n onChartReady,\n onSelectCategory,\n // onAnalyzeRootCause — reserved for context menu integration\n maxCategories = MAX_CATEGORIES,\n maxSubcategories = MAX_SUBCATEGORIES,\n showOthersBucket = true,\n invertAxis = false,\n hideLegend = false,\n enableScroll = false,\n toolbar,\n actions,\n className,\n}: StackedBarChartCardProps) => {\n const { categories, series } = useMemo(\n () => aggregateData(data, maxCategories, maxSubcategories, showOthersBucket),\n [data, maxCategories, maxSubcategories, showOthersBucket],\n );\n\n const option = useMemo(() => {\n switch (chartType) {\n case 'pie':\n return buildPieOption(categories, series, hideLegend);\n case 'sunburst':\n return buildSunburstOption(categories, series);\n default:\n return buildBarOption(categories, series, invertAxis, hideLegend, enableScroll);\n }\n }, [chartType, categories, series, invertAxis, hideLegend, enableScroll]);\n\n const handleChartReady = useCallback(\n (instance: EChartsInstance) => {\n onChartReady?.(instance);\n },\n [onChartReady],\n );\n\n const handleChartClick = useCallback(\n (params: { name?: string; seriesName?: string }) => {\n if (!onSelectCategory || !params.name) return;\n onSelectCategory({\n category: params.name,\n subCategory: params.seriesName ?? null,\n });\n },\n [onSelectCategory],\n );\n\n const hasData = data.length > 0;\n\n return (\n <div className={clsx(styles.root, className)}>\n <div className={styles.header}>\n <div className={styles.headerLeft}>\n <h3 className={styles.title}>{title}</h3>\n {subtitle && <div className={styles.subtitle}>{subtitle}</div>}\n </div>\n <div className={styles.headerRight}>\n {toolbar && <div className={styles.toolbar}>{toolbar}</div>}\n <div className={styles.chartTypeToggle}>\n {CHART_TYPES.map((type) => (\n <button\n key={type}\n type=\"button\"\n className={chartType === type ? styles.active : undefined}\n aria-pressed={chartType === type}\n disabled\n >\n {CHART_TYPE_LABELS[type]}\n </button>\n ))}\n </div>\n {actions}\n </div>\n </div>\n\n {isLoading && <div className={styles.loading}>Loading chart data...</div>}\n\n {!isLoading && error && (\n <div className={styles.error}>\n <span>{error}</span>\n {onRetry && (\n <button type=\"button\" className={styles.retryButton} onClick={onRetry}>\n Retry\n </button>\n )}\n </div>\n )}\n\n {!isLoading && !error && !hasData && (\n <div className={styles.empty}>No data available</div>\n )}\n\n {!isLoading && !error && hasData && (\n <div className={styles.chartContainer}>\n <ReactECharts\n option={option}\n style={{ height: '100%', width: '100%' }}\n onChartReady={handleChartReady}\n onEvents={{ click: handleChartClick }}\n notMerge\n />\n </div>\n )}\n </div>\n );\n};\n"],"names":["MAX_CATEGORIES","MAX_SUBCATEGORIES","useMemo","aggregateData","buildPieOption","buildSunburstOption","buildBarOption","useCallback","clsx","styles","jsxs","jsx"],"mappings":"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"}