@salesmind-ai/design-system 0.3.1 → 0.3.2

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 (197) hide show
  1. package/dist/admin/index.cjs +68 -2928
  2. package/dist/admin/index.cjs.map +1 -1
  3. package/dist/admin/index.js +5 -2915
  4. package/dist/admin/index.js.map +1 -1
  5. package/dist/blog/index.cjs +53 -1064
  6. package/dist/blog/index.cjs.map +1 -1
  7. package/dist/blog/index.js +8 -1054
  8. package/dist/blog/index.js.map +1 -1
  9. package/dist/charts/index.cjs +46 -2694
  10. package/dist/charts/index.cjs.map +1 -1
  11. package/dist/charts/index.js +3 -2680
  12. package/dist/charts/index.js.map +1 -1
  13. package/dist/chunk-2GARWEJK.js +17 -0
  14. package/dist/chunk-2GARWEJK.js.map +1 -0
  15. package/dist/chunk-3NKRFUAR.js +37 -0
  16. package/dist/chunk-3NKRFUAR.js.map +1 -0
  17. package/dist/chunk-3TGSIILM.cjs +201 -0
  18. package/dist/chunk-3TGSIILM.cjs.map +1 -0
  19. package/dist/chunk-4GM5BGBN.cjs +801 -0
  20. package/dist/chunk-4GM5BGBN.cjs.map +1 -0
  21. package/dist/chunk-5LGDEZWY.cjs +2434 -0
  22. package/dist/chunk-5LGDEZWY.cjs.map +1 -0
  23. package/dist/chunk-6H4DSTXR.js +786 -0
  24. package/dist/chunk-6H4DSTXR.js.map +1 -0
  25. package/dist/chunk-6UNG76Y2.js +153 -0
  26. package/dist/chunk-6UNG76Y2.js.map +1 -0
  27. package/dist/chunk-7PX2AZ6Y.js +39 -0
  28. package/dist/chunk-7PX2AZ6Y.js.map +1 -0
  29. package/dist/chunk-B6AVAX4F.js +1415 -0
  30. package/dist/chunk-B6AVAX4F.js.map +1 -0
  31. package/dist/chunk-BILT5KD3.js +264 -0
  32. package/dist/chunk-BILT5KD3.js.map +1 -0
  33. package/dist/chunk-C2BCDNAV.js +24 -0
  34. package/dist/chunk-C2BCDNAV.js.map +1 -0
  35. package/dist/chunk-CH42VPWE.cjs +421 -0
  36. package/dist/chunk-CH42VPWE.cjs.map +1 -0
  37. package/dist/chunk-CJ2MKVAF.cjs +46 -0
  38. package/dist/chunk-CJ2MKVAF.cjs.map +1 -0
  39. package/dist/chunk-DP74LUXG.cjs +98 -0
  40. package/dist/chunk-DP74LUXG.cjs.map +1 -0
  41. package/dist/chunk-E7D6EKJ4.cjs +44 -0
  42. package/dist/chunk-E7D6EKJ4.cjs.map +1 -0
  43. package/dist/chunk-ECXBTUH6.cjs +584 -0
  44. package/dist/chunk-ECXBTUH6.cjs.map +1 -0
  45. package/dist/chunk-EFRAP5ES.js +157 -0
  46. package/dist/chunk-EFRAP5ES.js.map +1 -0
  47. package/dist/chunk-F6YYWMME.js +485 -0
  48. package/dist/chunk-F6YYWMME.js.map +1 -0
  49. package/dist/chunk-FAFAP4L5.js +183 -0
  50. package/dist/chunk-FAFAP4L5.js.map +1 -0
  51. package/dist/chunk-GUZIMHWS.js +1608 -0
  52. package/dist/chunk-GUZIMHWS.js.map +1 -0
  53. package/dist/chunk-H2Y6BSTL.cjs +69 -0
  54. package/dist/chunk-H2Y6BSTL.cjs.map +1 -0
  55. package/dist/chunk-HN4PHABT.js +126 -0
  56. package/dist/chunk-HN4PHABT.js.map +1 -0
  57. package/dist/chunk-HRENHNDJ.js +211 -0
  58. package/dist/chunk-HRENHNDJ.js.map +1 -0
  59. package/dist/chunk-I75BFEYT.cjs +2561 -0
  60. package/dist/chunk-I75BFEYT.cjs.map +1 -0
  61. package/dist/chunk-IFRATNLU.js +562 -0
  62. package/dist/chunk-IFRATNLU.js.map +1 -0
  63. package/dist/chunk-IYPXJ6YC.cjs +69 -0
  64. package/dist/chunk-IYPXJ6YC.cjs.map +1 -0
  65. package/dist/chunk-JPJN4YBC.js +409 -0
  66. package/dist/chunk-JPJN4YBC.js.map +1 -0
  67. package/dist/chunk-KBA2LFBG.js +62 -0
  68. package/dist/chunk-KBA2LFBG.js.map +1 -0
  69. package/dist/chunk-KCKUSU2M.cjs +166 -0
  70. package/dist/chunk-KCKUSU2M.cjs.map +1 -0
  71. package/dist/chunk-KJ2OXQF4.js +287 -0
  72. package/dist/chunk-KJ2OXQF4.js.map +1 -0
  73. package/dist/chunk-KNQEIU7O.cjs +1202 -0
  74. package/dist/chunk-KNQEIU7O.cjs.map +1 -0
  75. package/dist/chunk-KVGSVGRK.cjs +569 -0
  76. package/dist/chunk-KVGSVGRK.cjs.map +1 -0
  77. package/dist/chunk-L352JRV6.cjs +105 -0
  78. package/dist/chunk-L352JRV6.cjs.map +1 -0
  79. package/dist/chunk-LJADZITX.cjs +298 -0
  80. package/dist/chunk-LJADZITX.cjs.map +1 -0
  81. package/dist/chunk-LMJPWXTZ.cjs +194 -0
  82. package/dist/chunk-LMJPWXTZ.cjs.map +1 -0
  83. package/dist/chunk-LOWEAQST.js +701 -0
  84. package/dist/chunk-LOWEAQST.js.map +1 -0
  85. package/dist/chunk-MDB2WCRQ.cjs +137 -0
  86. package/dist/chunk-MDB2WCRQ.cjs.map +1 -0
  87. package/dist/chunk-MQDEE7HC.cjs +283 -0
  88. package/dist/chunk-MQDEE7HC.cjs.map +1 -0
  89. package/dist/chunk-MQRB634A.cjs +34 -0
  90. package/dist/chunk-MQRB634A.cjs.map +1 -0
  91. package/dist/chunk-MTI27RDV.js +185 -0
  92. package/dist/chunk-MTI27RDV.js.map +1 -0
  93. package/dist/chunk-MU6GW5ZV.js +2317 -0
  94. package/dist/chunk-MU6GW5ZV.js.map +1 -0
  95. package/dist/chunk-NN3TUHIH.js +28 -0
  96. package/dist/chunk-NN3TUHIH.js.map +1 -0
  97. package/dist/chunk-NT4LBP7D.cjs +111 -0
  98. package/dist/chunk-NT4LBP7D.cjs.map +1 -0
  99. package/dist/chunk-OLV7OD3X.cjs +502 -0
  100. package/dist/chunk-OLV7OD3X.cjs.map +1 -0
  101. package/dist/chunk-OXNXEQY7.js +2538 -0
  102. package/dist/chunk-OXNXEQY7.js.map +1 -0
  103. package/dist/chunk-P5BOFE5A.js +546 -0
  104. package/dist/chunk-P5BOFE5A.js.map +1 -0
  105. package/dist/chunk-Q2MFGYTE.cjs +1449 -0
  106. package/dist/chunk-Q2MFGYTE.cjs.map +1 -0
  107. package/dist/chunk-Q75DBVDY.cjs +68 -0
  108. package/dist/chunk-Q75DBVDY.cjs.map +1 -0
  109. package/dist/chunk-REQ5Q6ZI.js +1022 -0
  110. package/dist/chunk-REQ5Q6ZI.js.map +1 -0
  111. package/dist/chunk-SICKWUWB.js +62 -0
  112. package/dist/chunk-SICKWUWB.js.map +1 -0
  113. package/dist/chunk-T343CCH5.js +1190 -0
  114. package/dist/chunk-T343CCH5.js.map +1 -0
  115. package/dist/chunk-TEC62D4A.cjs +1624 -0
  116. package/dist/chunk-TEC62D4A.cjs.map +1 -0
  117. package/dist/chunk-TW5JB35D.js +2122 -0
  118. package/dist/chunk-TW5JB35D.js.map +1 -0
  119. package/dist/chunk-VC5LMUVQ.cjs +20 -0
  120. package/dist/chunk-VC5LMUVQ.cjs.map +1 -0
  121. package/dist/chunk-VM7WFMKI.cjs +76 -0
  122. package/dist/chunk-VM7WFMKI.cjs.map +1 -0
  123. package/dist/chunk-W2WTP6HS.cjs +233 -0
  124. package/dist/chunk-W2WTP6HS.cjs.map +1 -0
  125. package/dist/chunk-WH7PYHZY.cjs +35 -0
  126. package/dist/chunk-WH7PYHZY.cjs.map +1 -0
  127. package/dist/chunk-XQZVY7JJ.cjs +717 -0
  128. package/dist/chunk-XQZVY7JJ.cjs.map +1 -0
  129. package/dist/chunk-XU3OMQ7V.js +98 -0
  130. package/dist/chunk-XU3OMQ7V.js.map +1 -0
  131. package/dist/chunk-XWPDRMZG.js +62 -0
  132. package/dist/chunk-XWPDRMZG.js.map +1 -0
  133. package/dist/chunk-Y3CPKNB7.js +67 -0
  134. package/dist/chunk-Y3CPKNB7.js.map +1 -0
  135. package/dist/chunk-YNVRDD2P.js +98 -0
  136. package/dist/chunk-YNVRDD2P.js.map +1 -0
  137. package/dist/chunk-YSYR54XR.js +92 -0
  138. package/dist/chunk-YSYR54XR.js.map +1 -0
  139. package/dist/chunk-YTYDQBVY.cjs +162 -0
  140. package/dist/chunk-YTYDQBVY.cjs.map +1 -0
  141. package/dist/chunk-ZDLOA2UT.cjs +1042 -0
  142. package/dist/chunk-ZDLOA2UT.cjs.map +1 -0
  143. package/dist/chunk-ZWUKRCOJ.cjs +2162 -0
  144. package/dist/chunk-ZWUKRCOJ.cjs.map +1 -0
  145. package/dist/core/index.cjs +807 -4333
  146. package/dist/core/index.cjs.map +1 -1
  147. package/dist/core/index.js +14 -4130
  148. package/dist/core/index.js.map +1 -1
  149. package/dist/i18n/index.cjs +86 -558
  150. package/dist/i18n/index.cjs.map +1 -1
  151. package/dist/i18n/index.js +1 -544
  152. package/dist/i18n/index.js.map +1 -1
  153. package/dist/index.cjs +1432 -17140
  154. package/dist/index.cjs.map +1 -1
  155. package/dist/index.js +31 -16785
  156. package/dist/index.js.map +1 -1
  157. package/dist/marketing/index.cjs +142 -3072
  158. package/dist/marketing/index.cjs.map +1 -1
  159. package/dist/marketing/index.js +11 -3042
  160. package/dist/marketing/index.js.map +1 -1
  161. package/dist/motion/index.cjs +26 -1222
  162. package/dist/motion/index.cjs.map +1 -1
  163. package/dist/motion/index.js +2 -1215
  164. package/dist/motion/index.js.map +1 -1
  165. package/dist/nav/index.cjs +101 -1518
  166. package/dist/nav/index.cjs.map +1 -1
  167. package/dist/nav/index.js +4 -1498
  168. package/dist/nav/index.js.map +1 -1
  169. package/dist/report/index.cjs +171 -2403
  170. package/dist/report/index.cjs.map +1 -1
  171. package/dist/report/index.js +3 -2363
  172. package/dist/report/index.js.map +1 -1
  173. package/dist/sections/index.cjs +28 -378
  174. package/dist/sections/index.cjs.map +1 -1
  175. package/dist/sections/index.js +4 -372
  176. package/dist/sections/index.js.map +1 -1
  177. package/dist/social-proof/index.cjs +53 -1250
  178. package/dist/social-proof/index.cjs.map +1 -1
  179. package/dist/social-proof/index.js +6 -1235
  180. package/dist/social-proof/index.js.map +1 -1
  181. package/dist/theme/index.cjs +38 -565
  182. package/dist/theme/index.cjs.map +1 -1
  183. package/dist/theme/index.js +2 -555
  184. package/dist/theme/index.js.map +1 -1
  185. package/dist/web/client/index.cjs +38 -491
  186. package/dist/web/client/index.cjs.map +1 -1
  187. package/dist/web/client/index.js +4 -483
  188. package/dist/web/client/index.js.map +1 -1
  189. package/dist/web/index.cjs +158 -1346
  190. package/dist/web/index.cjs.map +1 -1
  191. package/dist/web/index.js +9 -1305
  192. package/dist/web/index.js.map +1 -1
  193. package/dist/web/server/index.cjs +26 -563
  194. package/dist/web/server/index.cjs.map +1 -1
  195. package/dist/web/server/index.js +1 -560
  196. package/dist/web/server/index.js.map +1 -1
  197. package/package.json +1 -1
@@ -1,2698 +1,50 @@
1
1
  'use strict';
2
2
 
3
- var clsx11 = require('clsx');
4
- var recharts = require('recharts');
5
- var React2 = require('react');
6
- var jsxRuntime = require('react/jsx-runtime');
7
- var tooltip = require('@base-ui/react/tooltip');
8
-
9
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
-
11
- var clsx11__default = /*#__PURE__*/_interopDefault(clsx11);
12
- var React2__default = /*#__PURE__*/_interopDefault(React2);
13
-
14
- // src/components/ChartContainer/ChartContainer.tsx
15
-
16
- // src/report-engine/constants.ts
17
- var EXECUTIVE_MODE = {
18
- mode: "executive",
19
- features: {
20
- showMethodology: false,
21
- showConfidenceScores: false,
22
- showRawData: false,
23
- showStatisticalTests: false,
24
- chartDetailLevel: "summary",
25
- maxInsightsShown: 5,
26
- allowDrilldown: false
27
- }
28
- };
29
- var CONFIDENCE_THRESHOLDS = [
30
- { level: "high", min: 90, max: 100, label: "High Confidence", color: "var(--status-success)" },
31
- {
32
- level: "moderate",
33
- min: 70,
34
- max: 89,
35
- label: "Moderate Confidence",
36
- color: "var(--status-info)"
37
- },
38
- { level: "low", min: 50, max: 69, label: "Low Confidence", color: "var(--status-warning)" },
39
- {
40
- level: "insufficient",
41
- min: 0,
42
- max: 49,
43
- label: "Insufficient Data",
44
- color: "var(--status-error)"
45
- }
46
- ];
47
- var MINIMUM_SAMPLE_SIZES = {
48
- overall: 30};
49
- var ANALYTICAL_STATE_CONFIG = {
50
- VALID: {
51
- label: "Valid",
52
- icon: "check",
53
- color: "var(--status-success)",
54
- action: null
55
- },
56
- INSUFFICIENT_SAMPLE: {
57
- label: "Insufficient Sample",
58
- icon: "alert-triangle",
59
- color: "var(--status-warning)",
60
- action: "Add more data"
61
- },
62
- LOW_CONFIDENCE: {
63
- label: "Low Confidence",
64
- icon: "alert-circle",
65
- color: "var(--status-warning)",
66
- action: "Interpret with caution"
67
- },
68
- PARTIAL_TIME_WINDOW: {
69
- label: "Partial Data",
70
- icon: "clock",
71
- color: "var(--status-info)",
72
- action: "Expand date range"
73
- },
74
- DATA_SKEW_DETECTED: {
75
- label: "Data Skew",
76
- icon: "bar-chart-2",
77
- color: "var(--status-warning)",
78
- action: "Review methodology"
79
- },
80
- CONFLICTING_SIGNALS: {
81
- label: "Conflicting Signals",
82
- icon: "git-merge",
83
- color: "var(--status-error)",
84
- action: "Manual review needed"
85
- },
86
- INFERRED_NOT_OBSERVED: {
87
- label: "AI Generated",
88
- icon: "cpu",
89
- color: "var(--status-info)",
90
- action: "Verify with data"
91
- },
92
- STALE_DATA: {
93
- label: "Stale Data",
94
- icon: "clock",
95
- color: "var(--status-warning)",
96
- action: "Refresh data"
97
- },
98
- FIELD_MISSING: {
99
- label: "Missing Field",
100
- icon: "file-x",
101
- color: "var(--status-error)",
102
- action: "Upload complete data"
103
- },
104
- CALCULATION_ERROR: {
105
- label: "Calculation Error",
106
- icon: "x-circle",
107
- color: "var(--status-error)",
108
- action: "Contact support"
109
- }
110
- };
111
-
112
- // src/report-engine/confidence.ts
113
- function calculateConfidence(params) {
114
- const { sampleSize, requiredSize, completeness, recency, variance} = params;
115
- const sampleScore = Math.min(40, sampleSize / requiredSize * 40);
116
- const completenessScore = completeness * 20;
117
- const recencyScore = recency * 20;
118
- const variancePenalty = variance * 10;
119
- const aiPenalty = 0;
120
- const rawScore = sampleScore + completenessScore + recencyScore - variancePenalty - aiPenalty;
121
- return Math.max(0, Math.min(100, Math.round(rawScore)));
122
- }
123
- function getConfidenceThreshold(score) {
124
- return CONFIDENCE_THRESHOLDS.find((t) => score >= t.min && score <= t.max) ?? CONFIDENCE_THRESHOLDS[CONFIDENCE_THRESHOLDS.length - 1];
125
- }
126
- var ReportModeContext = React2.createContext(null);
127
- function useReportMode() {
128
- const context = React2.useContext(ReportModeContext);
129
- if (!context) {
130
- return EXECUTIVE_MODE;
131
- }
132
- return context;
133
- }
134
- function useChartData({
135
- data,
136
- requiredFields,
137
- minSampleSize = MINIMUM_SAMPLE_SIZES.overall
138
- }) {
139
- return React2.useMemo(() => {
140
- const missingFields = [];
141
- if (data.length > 0) {
142
- const firstRecord = data[0];
143
- for (const field of requiredFields) {
144
- if (!(field in firstRecord)) {
145
- missingFields.push(field);
146
- }
147
- }
148
- }
149
- let completeness = 1;
150
- if (data.length > 0 && requiredFields.length > 0) {
151
- let filled = 0;
152
- let total = 0;
153
- for (const record of data) {
154
- for (const field of requiredFields) {
155
- total++;
156
- const value = record[field];
157
- if (value !== null && value !== void 0 && value !== "") {
158
- filled++;
159
- }
160
- }
161
- }
162
- completeness = total > 0 ? filled / total : 0;
163
- }
164
- let state = "VALID";
165
- let message;
166
- if (missingFields.length > 0) {
167
- state = "FIELD_MISSING";
168
- message = `Missing fields: ${missingFields.join(", ")}`;
169
- } else if (data.length === 0) {
170
- state = "INSUFFICIENT_SAMPLE";
171
- message = "No data available";
172
- } else if (data.length < minSampleSize) {
173
- state = "INSUFFICIENT_SAMPLE";
174
- message = `Sample size ${data.length} is below minimum ${minSampleSize}`;
175
- } else if (completeness < 0.7) {
176
- state = "LOW_CONFIDENCE";
177
- message = `Data completeness is ${Math.round(completeness * 100)}%`;
178
- }
179
- const confidence = calculateConfidence({
180
- sampleSize: data.length,
181
- requiredSize: minSampleSize,
182
- completeness,
183
- recency: 1,
184
- // Assume fresh data if not specified
185
- variance: 0});
186
- const isRenderable = state === "VALID" || state === "LOW_CONFIDENCE";
187
- return {
188
- data,
189
- state,
190
- confidence,
191
- isRenderable,
192
- message
193
- };
194
- }, [data, requiredFields, minSampleSize]);
195
- }
196
-
197
- // src/report-engine/chart-types.ts
198
- var CHART_REGISTRY = {
199
- // ══════════════════════════════════════════════════════════════════════════
200
- // TREND CHARTS (MVP)
201
- // ══════════════════════════════════════════════════════════════════════════
202
- line: {
203
- id: "line",
204
- name: "Line Chart",
205
- description: "Shows trends over time with connected data points",
206
- intent: "trend",
207
- phase: "mvp",
208
- contract: {
209
- requiredDimensions: 1,
210
- requiredMeasures: 1,
211
- minDataPoints: 3,
212
- idealDataPoints: 7,
213
- allowNegativeValues: true,
214
- requireNonZeroTotal: false,
215
- warningThresholds: { sparseData: 3 },
216
- fallback: { type: "show_kpi", message: "Insufficient data for trend visualization" }
217
- },
218
- switchableTo: ["smooth_line", "area", "stacked_area"],
219
- supportsStacking: false,
220
- supportsMultipleSeries: true,
221
- requiresTimeAxis: true
222
- },
223
- smooth_line: {
224
- id: "smooth_line",
225
- name: "Smooth Line Chart",
226
- description: "Curved line chart for smoother trend visualization",
227
- intent: "trend",
228
- phase: "mvp",
229
- contract: {
230
- requiredDimensions: 1,
231
- requiredMeasures: 1,
232
- minDataPoints: 3,
233
- idealDataPoints: 7,
234
- allowNegativeValues: true,
235
- requireNonZeroTotal: false,
236
- warningThresholds: { sparseData: 3 },
237
- fallback: { type: "show_kpi", message: "Insufficient data for trend visualization" }
238
- },
239
- switchableTo: ["line", "area", "stacked_area"],
240
- supportsStacking: false,
241
- supportsMultipleSeries: true,
242
- requiresTimeAxis: true
243
- },
244
- area: {
245
- id: "area",
246
- name: "Area Chart",
247
- description: "Filled area under line, emphasizes volume over time",
248
- intent: "trend",
249
- phase: "mvp",
250
- contract: {
251
- requiredDimensions: 1,
252
- requiredMeasures: 1,
253
- minDataPoints: 3,
254
- idealDataPoints: 7,
255
- allowNegativeValues: false,
256
- requireNonZeroTotal: false,
257
- warningThresholds: { sparseData: 3 },
258
- fallback: { type: "show_kpi", message: "Insufficient data for area visualization" }
259
- },
260
- switchableTo: ["line", "smooth_line", "stacked_area", "area_100pct"],
261
- supportsStacking: true,
262
- supportsMultipleSeries: true,
263
- requiresTimeAxis: true
264
- },
265
- stacked_area: {
266
- id: "stacked_area",
267
- name: "Stacked Area Chart",
268
- description: "Multiple series stacked to show cumulative trends",
269
- intent: "trend",
270
- phase: "mvp",
271
- contract: {
272
- requiredDimensions: 1,
273
- requiredMeasures: 2,
274
- minDataPoints: 3,
275
- idealDataPoints: 7,
276
- allowNegativeValues: false,
277
- requireNonZeroTotal: true,
278
- warningThresholds: { sparseData: 3 },
279
- fallback: { type: "warn", message: "Stacked area requires non-negative values" }
280
- },
281
- switchableTo: ["line", "area", "area_100pct"],
282
- supportsStacking: true,
283
- supportsMultipleSeries: true,
284
- requiresTimeAxis: true
285
- },
286
- area_100pct: {
287
- id: "area_100pct",
288
- name: "100% Stacked Area",
289
- description: "Shows proportional contribution over time",
290
- intent: "trend",
291
- phase: "mvp",
292
- contract: {
293
- requiredDimensions: 1,
294
- requiredMeasures: 2,
295
- minDataPoints: 3,
296
- idealDataPoints: 7,
297
- allowNegativeValues: false,
298
- requireNonZeroTotal: true,
299
- warningThresholds: { sparseData: 3 },
300
- fallback: { type: "warn", message: "100% stacked requires positive totals" }
301
- },
302
- switchableTo: ["stacked_area", "area"],
303
- supportsStacking: true,
304
- supportsMultipleSeries: true,
305
- requiresTimeAxis: true
306
- },
307
- // ══════════════════════════════════════════════════════════════════════════
308
- // COMPARISON CHARTS (MVP)
309
- // ══════════════════════════════════════════════════════════════════════════
310
- bar: {
311
- id: "bar",
312
- name: "Horizontal Bar Chart",
313
- description: "Horizontal bars for comparing categories",
314
- intent: "comparison",
315
- phase: "mvp",
316
- contract: {
317
- requiredDimensions: 1,
318
- requiredMeasures: 1,
319
- minDataPoints: 2,
320
- idealDataPoints: 5,
321
- maxDataPoints: 15,
322
- allowNegativeValues: true,
323
- requireNonZeroTotal: false,
324
- warningThresholds: { tooManyCategories: 12 },
325
- fallback: { type: "aggregate", strategy: "top_n" }
326
- },
327
- switchableTo: ["column", "stacked_bar", "stacked_column"],
328
- supportsStacking: true,
329
- supportsMultipleSeries: true,
330
- requiresTimeAxis: false
331
- },
332
- column: {
333
- id: "column",
334
- name: "Vertical Column Chart",
335
- description: "Vertical bars for comparing categories",
336
- intent: "comparison",
337
- phase: "mvp",
338
- contract: {
339
- requiredDimensions: 1,
340
- requiredMeasures: 1,
341
- minDataPoints: 2,
342
- idealDataPoints: 5,
343
- maxDataPoints: 12,
344
- allowNegativeValues: true,
345
- requireNonZeroTotal: false,
346
- warningThresholds: { tooManyCategories: 10 },
347
- fallback: { type: "aggregate", strategy: "top_n" }
348
- },
349
- switchableTo: ["bar", "stacked_column", "stacked_bar"],
350
- supportsStacking: true,
351
- supportsMultipleSeries: true,
352
- requiresTimeAxis: false
353
- },
354
- stacked_bar: {
355
- id: "stacked_bar",
356
- name: "Stacked Horizontal Bar",
357
- description: "Horizontal stacked bars showing composition per category",
358
- intent: "comparison",
359
- phase: "mvp",
360
- contract: {
361
- requiredDimensions: 1,
362
- requiredMeasures: 2,
363
- minDataPoints: 2,
364
- idealDataPoints: 5,
365
- maxDataPoints: 10,
366
- allowNegativeValues: false,
367
- requireNonZeroTotal: true,
368
- warningThresholds: { tooManyCategories: 8, imbalancedRatio: 0.9 },
369
- fallback: { type: "aggregate", strategy: "other_bucket" }
370
- },
371
- switchableTo: ["bar", "stacked_column", "column_100pct"],
372
- supportsStacking: true,
373
- supportsMultipleSeries: true,
374
- requiresTimeAxis: false
375
- },
376
- stacked_column: {
377
- id: "stacked_column",
378
- name: "Stacked Vertical Column",
379
- description: "Vertical stacked columns showing composition per category",
380
- intent: "comparison",
381
- phase: "mvp",
382
- contract: {
383
- requiredDimensions: 1,
384
- requiredMeasures: 2,
385
- minDataPoints: 2,
386
- idealDataPoints: 5,
387
- maxDataPoints: 10,
388
- allowNegativeValues: false,
389
- requireNonZeroTotal: true,
390
- warningThresholds: { tooManyCategories: 8, imbalancedRatio: 0.9 },
391
- fallback: { type: "aggregate", strategy: "other_bucket" }
392
- },
393
- switchableTo: ["column", "stacked_bar", "column_100pct"],
394
- supportsStacking: true,
395
- supportsMultipleSeries: true,
396
- requiresTimeAxis: false
397
- },
398
- column_100pct: {
399
- id: "column_100pct",
400
- name: "100% Stacked Column",
401
- description: "Shows proportional composition per category",
402
- intent: "comparison",
403
- phase: "mvp",
404
- contract: {
405
- requiredDimensions: 1,
406
- requiredMeasures: 2,
407
- minDataPoints: 2,
408
- idealDataPoints: 5,
409
- maxDataPoints: 10,
410
- allowNegativeValues: false,
411
- requireNonZeroTotal: true,
412
- warningThresholds: { tooManyCategories: 8 },
413
- fallback: { type: "warn", message: "100% stacked requires positive totals" }
414
- },
415
- switchableTo: ["stacked_column", "stacked_bar"],
416
- supportsStacking: true,
417
- supportsMultipleSeries: true,
418
- requiresTimeAxis: false
419
- },
420
- combo: {
421
- id: "combo",
422
- name: "Combo Chart",
423
- description: "Combines bars with line overlay (Phase 2)",
424
- intent: "comparison",
425
- phase: "phase2",
426
- contract: {
427
- requiredDimensions: 1,
428
- requiredMeasures: 2,
429
- minDataPoints: 3,
430
- idealDataPoints: 6,
431
- allowNegativeValues: true,
432
- requireNonZeroTotal: false,
433
- warningThresholds: { tooManyCategories: 10 },
434
- fallback: { type: "warn", message: "Combo chart requires dual measures" }
435
- },
436
- switchableTo: ["column", "line"],
437
- supportsStacking: false,
438
- supportsMultipleSeries: true,
439
- requiresTimeAxis: false
440
- },
441
- // ══════════════════════════════════════════════════════════════════════════
442
- // COMPOSITION CHARTS (MVP)
443
- // ══════════════════════════════════════════════════════════════════════════
444
- pie: {
445
- id: "pie",
446
- name: "Pie Chart",
447
- description: "Shows proportional composition of a whole",
448
- intent: "composition",
449
- phase: "mvp",
450
- contract: {
451
- requiredDimensions: 1,
452
- requiredMeasures: 1,
453
- minDataPoints: 2,
454
- idealDataPoints: 4,
455
- maxDataPoints: 6,
456
- allowNegativeValues: false,
457
- requireNonZeroTotal: true,
458
- warningThresholds: { tooManyCategories: 6, imbalancedRatio: 0.95 },
459
- fallback: { type: "aggregate", strategy: "other_bucket" }
460
- },
461
- switchableTo: ["donut", "column_100pct"],
462
- supportsStacking: false,
463
- supportsMultipleSeries: false,
464
- requiresTimeAxis: false,
465
- maxSlices: 6
466
- },
467
- donut: {
468
- id: "donut",
469
- name: "Donut Chart",
470
- description: "Pie chart with center cutout, can display total",
471
- intent: "composition",
472
- phase: "mvp",
473
- contract: {
474
- requiredDimensions: 1,
475
- requiredMeasures: 1,
476
- minDataPoints: 2,
477
- idealDataPoints: 4,
478
- maxDataPoints: 6,
479
- allowNegativeValues: false,
480
- requireNonZeroTotal: true,
481
- warningThresholds: { tooManyCategories: 6, imbalancedRatio: 0.95 },
482
- fallback: { type: "aggregate", strategy: "other_bucket" }
483
- },
484
- switchableTo: ["pie", "column_100pct"],
485
- supportsStacking: false,
486
- supportsMultipleSeries: false,
487
- requiresTimeAxis: false,
488
- maxSlices: 6
489
- },
490
- treemap: {
491
- id: "treemap",
492
- name: "Treemap",
493
- description: "Nested rectangles showing hierarchical composition (Phase 2)",
494
- intent: "composition",
495
- phase: "phase2",
496
- contract: {
497
- requiredDimensions: 1,
498
- requiredMeasures: 1,
499
- minDataPoints: 3,
500
- idealDataPoints: 10,
501
- maxDataPoints: 50,
502
- allowNegativeValues: false,
503
- requireNonZeroTotal: true,
504
- warningThresholds: { tooManyCategories: 30 },
505
- fallback: { type: "aggregate", strategy: "top_n" }
506
- },
507
- switchableTo: ["pie", "donut"],
508
- supportsStacking: false,
509
- supportsMultipleSeries: false,
510
- requiresTimeAxis: false
511
- },
512
- // ══════════════════════════════════════════════════════════════════════════
513
- // DISTRIBUTION CHARTS (MVP)
514
- // ══════════════════════════════════════════════════════════════════════════
515
- histogram: {
516
- id: "histogram",
517
- name: "Histogram",
518
- description: "Shows distribution of values across bins",
519
- intent: "distribution",
520
- phase: "mvp",
521
- contract: {
522
- requiredDimensions: 0,
523
- requiredMeasures: 1,
524
- minDataPoints: 10,
525
- idealDataPoints: 50,
526
- allowNegativeValues: true,
527
- requireNonZeroTotal: false,
528
- warningThresholds: { sparseData: 10 },
529
- fallback: { type: "show_kpi", message: "Insufficient data for distribution" }
530
- },
531
- switchableTo: ["radar"],
532
- supportsStacking: false,
533
- supportsMultipleSeries: false,
534
- requiresTimeAxis: false
535
- },
536
- radar: {
537
- id: "radar",
538
- name: "Radar Chart",
539
- description: "Multi-dimensional comparison in radial layout (Phase 2)",
540
- intent: "distribution",
541
- phase: "phase2",
542
- contract: {
543
- requiredDimensions: 1,
544
- requiredMeasures: 3,
545
- minDataPoints: 3,
546
- idealDataPoints: 6,
547
- maxDataPoints: 8,
548
- allowNegativeValues: false,
549
- requireNonZeroTotal: false,
550
- warningThresholds: { tooManyCategories: 8 },
551
- fallback: { type: "warn", message: "Radar works best with 3-8 dimensions" }
552
- },
553
- switchableTo: ["histogram"],
554
- supportsStacking: false,
555
- supportsMultipleSeries: true,
556
- requiresTimeAxis: false
557
- },
558
- // ══════════════════════════════════════════════════════════════════════════
559
- // RELATIONSHIP CHARTS
560
- // ══════════════════════════════════════════════════════════════════════════
561
- heatmap: {
562
- id: "heatmap",
563
- name: "Heatmap",
564
- description: "Color-coded matrix showing intensity",
565
- intent: "relationship",
566
- phase: "mvp",
567
- contract: {
568
- requiredDimensions: 2,
569
- requiredMeasures: 1,
570
- minDataPoints: 9,
571
- idealDataPoints: 25,
572
- allowNegativeValues: true,
573
- requireNonZeroTotal: false,
574
- warningThresholds: { sparseData: 9 },
575
- fallback: { type: "warn", message: "Heatmap requires grid data" }
576
- },
577
- switchableTo: ["scatter"],
578
- supportsStacking: false,
579
- supportsMultipleSeries: false,
580
- requiresTimeAxis: false
581
- },
582
- scatter: {
583
- id: "scatter",
584
- name: "Scatter Plot",
585
- description: "Shows correlation between two variables (Phase 2)",
586
- intent: "relationship",
587
- phase: "phase2",
588
- contract: {
589
- requiredDimensions: 0,
590
- requiredMeasures: 2,
591
- minDataPoints: 20,
592
- idealDataPoints: 100,
593
- allowNegativeValues: true,
594
- requireNonZeroTotal: false,
595
- warningThresholds: { sparseData: 20 },
596
- fallback: { type: "show_kpi", message: "Scatter requires 20+ points" }
597
- },
598
- switchableTo: ["bubble", "heatmap"],
599
- supportsStacking: false,
600
- supportsMultipleSeries: true,
601
- requiresTimeAxis: false
602
- },
603
- bubble: {
604
- id: "bubble",
605
- name: "Bubble Chart",
606
- description: "Scatter with sized points for third dimension (Phase 2)",
607
- intent: "relationship",
608
- phase: "phase2",
609
- contract: {
610
- requiredDimensions: 0,
611
- requiredMeasures: 3,
612
- minDataPoints: 10,
613
- idealDataPoints: 50,
614
- allowNegativeValues: true,
615
- requireNonZeroTotal: false,
616
- warningThresholds: { sparseData: 10 },
617
- fallback: { type: "show_kpi", message: "Bubble requires 3 measures" }
618
- },
619
- switchableTo: ["scatter"],
620
- supportsStacking: false,
621
- supportsMultipleSeries: true,
622
- requiresTimeAxis: false
623
- },
624
- // ══════════════════════════════════════════════════════════════════════════
625
- // GEOGRAPHIC CHARTS (Phase 2)
626
- // ══════════════════════════════════════════════════════════════════════════
627
- geo: {
628
- id: "geo",
629
- name: "Geographic Map",
630
- description: "Map with regional data markers (Phase 2)",
631
- intent: "geo",
632
- phase: "phase2",
633
- contract: {
634
- requiredDimensions: 1,
635
- // geo dimension (country/region)
636
- requiredMeasures: 1,
637
- minDataPoints: 1,
638
- idealDataPoints: 10,
639
- allowNegativeValues: true,
640
- requireNonZeroTotal: false,
641
- warningThresholds: {},
642
- fallback: { type: "hide" }
643
- },
644
- switchableTo: ["choropleth"],
645
- supportsStacking: false,
646
- supportsMultipleSeries: false,
647
- requiresTimeAxis: false
648
- },
649
- choropleth: {
650
- id: "choropleth",
651
- name: "Choropleth Map",
652
- description: "Color-shaded regions by value (Phase 2)",
653
- intent: "geo",
654
- phase: "phase2",
655
- contract: {
656
- requiredDimensions: 1,
657
- requiredMeasures: 1,
658
- minDataPoints: 3,
659
- idealDataPoints: 20,
660
- allowNegativeValues: false,
661
- requireNonZeroTotal: false,
662
- warningThresholds: {},
663
- fallback: { type: "hide" }
664
- },
665
- switchableTo: ["geo"],
666
- supportsStacking: false,
667
- supportsMultipleSeries: false,
668
- requiresTimeAxis: false
669
- },
670
- // ══════════════════════════════════════════════════════════════════════════
671
- // SPECIAL CHARTS
672
- // ══════════════════════════════════════════════════════════════════════════
673
- funnel: {
674
- id: "funnel",
675
- name: "Funnel Chart",
676
- description: "Shows conversion through sequential stages",
677
- intent: "comparison",
678
- phase: "mvp",
679
- contract: {
680
- requiredDimensions: 1,
681
- requiredMeasures: 1,
682
- minDataPoints: 3,
683
- idealDataPoints: 5,
684
- maxDataPoints: 7,
685
- allowNegativeValues: false,
686
- requireNonZeroTotal: true,
687
- warningThresholds: { tooManyCategories: 7 },
688
- fallback: { type: "warn", message: "Funnel requires sequential stages" }
689
- },
690
- switchableTo: ["bar"],
691
- supportsStacking: false,
692
- supportsMultipleSeries: false,
693
- requiresTimeAxis: false
694
- },
695
- waterfall: {
696
- id: "waterfall",
697
- name: "Waterfall Chart",
698
- description: "Shows cumulative effect of sequential changes (Phase 2)",
699
- intent: "comparison",
700
- phase: "phase2",
701
- contract: {
702
- requiredDimensions: 1,
703
- requiredMeasures: 1,
704
- minDataPoints: 3,
705
- idealDataPoints: 6,
706
- maxDataPoints: 12,
707
- allowNegativeValues: true,
708
- requireNonZeroTotal: false,
709
- warningThresholds: { tooManyCategories: 10 },
710
- fallback: { type: "warn", message: "Waterfall requires sequential data" }
711
- },
712
- switchableTo: ["bar", "column"],
713
- supportsStacking: false,
714
- supportsMultipleSeries: false,
715
- requiresTimeAxis: false
716
- },
717
- timeline: {
718
- id: "timeline",
719
- name: "Timeline",
720
- description: "Shows events along time axis (Phase 2)",
721
- intent: "trend",
722
- phase: "phase2",
723
- contract: {
724
- requiredDimensions: 1,
725
- requiredMeasures: 0,
726
- minDataPoints: 2,
727
- idealDataPoints: 10,
728
- allowNegativeValues: false,
729
- requireNonZeroTotal: false,
730
- warningThresholds: {},
731
- fallback: { type: "hide" }
732
- },
733
- switchableTo: ["line"],
734
- supportsStacking: false,
735
- supportsMultipleSeries: false,
736
- requiresTimeAxis: true
737
- }
738
- };
739
- function getAllowedSwitchTargets(currentType) {
740
- const metadata = CHART_REGISTRY[currentType];
741
- if (!metadata) return [];
742
- return metadata.switchableTo.filter((type) => {
743
- const targetMeta = CHART_REGISTRY[type];
744
- return targetMeta && targetMeta.phase === "mvp";
745
- });
746
- }
747
- function validateChartData(chartType, data, dimensions, measures) {
748
- const metadata = CHART_REGISTRY[chartType];
749
- if (!metadata) {
750
- return {
751
- isValid: false,
752
- warnings: [],
753
- errors: [`Unknown chart type: ${chartType}`]
754
- };
755
- }
756
- const contract = metadata.contract;
757
- const warnings = [];
758
- const errors = [];
759
- if (data.length < contract.minDataPoints) {
760
- errors.push(`Requires at least ${contract.minDataPoints} data points, got ${data.length}`);
761
- }
762
- if (contract.maxDataPoints && data.length > contract.maxDataPoints) {
763
- warnings.push(`Chart works best with \u2264${contract.maxDataPoints} items. Consider aggregating.`);
764
- }
765
- if (dimensions.length < contract.requiredDimensions) {
766
- errors.push(`Requires ${contract.requiredDimensions} dimension(s), got ${dimensions.length}`);
767
- }
768
- if (measures.length < contract.requiredMeasures) {
769
- errors.push(`Requires ${contract.requiredMeasures} measure(s), got ${measures.length}`);
770
- }
771
- if (!contract.allowNegativeValues && data.length > 0) {
772
- const hasNegative = data.some((row) => {
773
- if (typeof row !== "object" || row === null) return false;
774
- return measures.some((m) => {
775
- const val = row[m];
776
- return typeof val === "number" && val < 0;
777
- });
778
- });
779
- if (hasNegative) {
780
- errors.push("This chart type does not support negative values");
781
- }
782
- }
783
- if (contract.warningThresholds.tooManyCategories && data.length > contract.warningThresholds.tooManyCategories) {
784
- warnings.push(`Too many categories (${data.length}). Consider grouping smaller values.`);
785
- }
786
- return {
787
- isValid: errors.length === 0,
788
- warnings,
789
- errors,
790
- fallbackAction: errors.length > 0 ? contract.fallback : void 0
791
- };
792
- }
793
- function getDefaultChartForIntent(intent) {
794
- const defaults = {
795
- trend: "line",
796
- comparison: "column",
797
- composition: "donut",
798
- distribution: "histogram",
799
- relationship: "heatmap",
800
- geo: "geo"
801
- };
802
- return defaults[intent];
803
- }
804
- var DataStateIndicator = React2__default.default.forwardRef(
805
- ({ state, details, variant = "compact", onAction, className, ...props }, ref) => {
806
- const config = ANALYTICAL_STATE_CONFIG[state];
807
- if (state === "VALID" && variant === "compact") {
808
- return null;
809
- }
810
- const renderIcon = () => {
811
- switch (config.icon) {
812
- case "check":
813
- return /* @__PURE__ */ jsxRuntime.jsx(
814
- "svg",
815
- {
816
- width: "16",
817
- height: "16",
818
- viewBox: "0 0 24 24",
819
- fill: "none",
820
- stroke: "currentColor",
821
- strokeWidth: "2",
822
- children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "20,6 9,17 4,12" })
823
- }
824
- );
825
- case "alert-triangle":
826
- return /* @__PURE__ */ jsxRuntime.jsxs(
827
- "svg",
828
- {
829
- width: "16",
830
- height: "16",
831
- viewBox: "0 0 24 24",
832
- fill: "none",
833
- stroke: "currentColor",
834
- strokeWidth: "2",
835
- children: [
836
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" }),
837
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "9", x2: "12", y2: "13" }),
838
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
839
- ]
840
- }
841
- );
842
- case "alert-circle":
843
- return /* @__PURE__ */ jsxRuntime.jsxs(
844
- "svg",
845
- {
846
- width: "16",
847
- height: "16",
848
- viewBox: "0 0 24 24",
849
- fill: "none",
850
- stroke: "currentColor",
851
- strokeWidth: "2",
852
- children: [
853
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }),
854
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
855
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
856
- ]
857
- }
858
- );
859
- case "x-circle":
860
- return /* @__PURE__ */ jsxRuntime.jsxs(
861
- "svg",
862
- {
863
- width: "16",
864
- height: "16",
865
- viewBox: "0 0 24 24",
866
- fill: "none",
867
- stroke: "currentColor",
868
- strokeWidth: "2",
869
- children: [
870
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }),
871
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "15", y1: "9", x2: "9", y2: "15" }),
872
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "9", y1: "9", x2: "15", y2: "15" })
873
- ]
874
- }
875
- );
876
- case "cpu":
877
- return /* @__PURE__ */ jsxRuntime.jsxs(
878
- "svg",
879
- {
880
- width: "16",
881
- height: "16",
882
- viewBox: "0 0 24 24",
883
- fill: "none",
884
- stroke: "currentColor",
885
- strokeWidth: "2",
886
- children: [
887
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "4", y: "4", width: "16", height: "16", rx: "2", ry: "2" }),
888
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "9", y: "9", width: "6", height: "6" }),
889
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "9", y1: "1", x2: "9", y2: "4" }),
890
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "15", y1: "1", x2: "15", y2: "4" }),
891
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "9", y1: "20", x2: "9", y2: "23" }),
892
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "15", y1: "20", x2: "15", y2: "23" }),
893
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "20", y1: "9", x2: "23", y2: "9" }),
894
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "20", y1: "14", x2: "23", y2: "14" }),
895
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "1", y1: "9", x2: "4", y2: "9" }),
896
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "1", y1: "14", x2: "4", y2: "14" })
897
- ]
898
- }
899
- );
900
- default:
901
- return /* @__PURE__ */ jsxRuntime.jsxs(
902
- "svg",
903
- {
904
- width: "16",
905
- height: "16",
906
- viewBox: "0 0 24 24",
907
- fill: "none",
908
- stroke: "currentColor",
909
- strokeWidth: "2",
910
- children: [
911
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }),
912
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "16", x2: "12", y2: "12" }),
913
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "8", x2: "12.01", y2: "8" })
914
- ]
915
- }
916
- );
917
- }
918
- };
919
- return /* @__PURE__ */ jsxRuntime.jsxs(
920
- "div",
921
- {
922
- ref,
923
- className: clsx11__default.default(
924
- "ds-data-state-indicator",
925
- `ds-data-state-indicator--${variant}`,
926
- `ds-data-state-indicator--${state.toLowerCase().replace(/_/g, "-")}`,
927
- className
928
- ),
929
- role: "status",
930
- "aria-live": "polite",
931
- ...props,
932
- children: [
933
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-data-state-indicator__icon", style: { color: config.color }, children: renderIcon() }),
934
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-data-state-indicator__content", children: [
935
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-data-state-indicator__label", children: config.label }),
936
- variant === "full" && details && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ds-data-state-indicator__details", children: [
937
- details.message,
938
- details.sampleSize !== void 0 && details.requiredSize !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
939
- " ",
940
- "(n=",
941
- details.sampleSize,
942
- "/",
943
- details.requiredSize,
944
- ")"
945
- ] }),
946
- details.confidence !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
947
- " \u2022 ",
948
- details.confidence,
949
- "% confidence"
950
- ] }),
951
- details.missingFields && details.missingFields.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
952
- " \u2022 Missing: ",
953
- details.missingFields.join(", ")
954
- ] })
955
- ] })
956
- ] }),
957
- config.action && onAction && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "ds-data-state-indicator__action", onClick: onAction, children: config.action })
958
- ]
959
- }
960
- );
961
- }
962
- );
963
- DataStateIndicator.displayName = "DataStateIndicator";
964
- var DataCoverageBadge = React2__default.default.forwardRef(
965
- ({ sampleSize, requiredSize, dateRange, showDateRange = true, size = "md", className, ...props }, ref) => {
966
- const isSufficient = !requiredSize || sampleSize >= requiredSize;
967
- const percentage = requiredSize ? Math.min(100, Math.round(sampleSize / requiredSize * 100)) : 100;
968
- return /* @__PURE__ */ jsxRuntime.jsxs(
969
- "div",
970
- {
971
- ref,
972
- className: clsx11__default.default(
973
- "ds-data-coverage-badge",
974
- `ds-data-coverage-badge--${size}`,
975
- !isSufficient && "ds-data-coverage-badge--insufficient",
976
- className
977
- ),
978
- ...props,
979
- children: [
980
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-data-coverage-badge__sample", children: [
981
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-data-coverage-badge__icon", children: /* @__PURE__ */ jsxRuntime.jsxs(
982
- "svg",
983
- {
984
- width: "14",
985
- height: "14",
986
- viewBox: "0 0 24 24",
987
- fill: "none",
988
- stroke: "currentColor",
989
- strokeWidth: "2",
990
- children: [
991
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" }),
992
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "9", cy: "7", r: "4" }),
993
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M23 21v-2a4 4 0 0 0-3-3.87" }),
994
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16 3.13a4 4 0 0 1 0 7.75" })
995
- ]
996
- }
997
- ) }),
998
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ds-data-coverage-badge__count", children: [
999
- "n=",
1000
- sampleSize.toLocaleString()
1001
- ] }),
1002
- requiredSize && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ds-data-coverage-badge__required", children: [
1003
- "(",
1004
- percentage,
1005
- "% of min ",
1006
- requiredSize,
1007
- ")"
1008
- ] })
1009
- ] }),
1010
- showDateRange && dateRange && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-data-coverage-badge__date", children: [
1011
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-data-coverage-badge__icon", children: /* @__PURE__ */ jsxRuntime.jsxs(
1012
- "svg",
1013
- {
1014
- width: "14",
1015
- height: "14",
1016
- viewBox: "0 0 24 24",
1017
- fill: "none",
1018
- stroke: "currentColor",
1019
- strokeWidth: "2",
1020
- children: [
1021
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2", ry: "2" }),
1022
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "16", y1: "2", x2: "16", y2: "6" }),
1023
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "8", y1: "2", x2: "8", y2: "6" }),
1024
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "10", x2: "21", y2: "10" })
1025
- ]
1026
- }
1027
- ) }),
1028
- /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
1029
- dateRange.start,
1030
- " \u2013 ",
1031
- dateRange.end
1032
- ] })
1033
- ] })
1034
- ]
1035
- }
1036
- );
1037
- }
1038
- );
1039
- DataCoverageBadge.displayName = "DataCoverageBadge";
1040
- function ChartContainer({
1041
- title,
1042
- subtitle,
1043
- height = 300,
1044
- data = [],
1045
- requiredFields = [],
1046
- minSampleSize = 30,
1047
- showCoverage = true,
1048
- dateRange,
1049
- loading,
1050
- emptyMessage = "No data available",
1051
- children,
1052
- className,
1053
- ...props
1054
- }) {
1055
- const { features } = useReportMode();
1056
- const { state, isRenderable, message } = useChartData({
1057
- data,
1058
- requiredFields,
1059
- minSampleSize
1060
- });
1061
- const renderContent = () => {
1062
- if (loading) {
1063
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-chart-container__loading", children: [
1064
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-chart-container__spinner" }),
1065
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Loading chart..." })
1066
- ] });
1067
- }
1068
- if (!isRenderable && state !== "VALID") {
1069
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-chart-container__empty", children: [
1070
- /* @__PURE__ */ jsxRuntime.jsx(
1071
- DataStateIndicator,
1072
- {
1073
- state,
1074
- variant: "full",
1075
- details: { message, sampleSize: data.length, requiredSize: minSampleSize }
1076
- }
1077
- ),
1078
- state === "INSUFFICIENT_SAMPLE" && data.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ds-chart-container__empty-message", children: emptyMessage })
1079
- ] });
1080
- }
1081
- return /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height, children });
1082
- };
1083
- return /* @__PURE__ */ jsxRuntime.jsxs(
1084
- "div",
1085
- {
1086
- className: clsx11__default.default(
1087
- "ds-chart-container",
1088
- loading && "ds-chart-container--loading",
1089
- !isRenderable && "ds-chart-container--invalid",
1090
- className
1091
- ),
1092
- ...props,
1093
- children: [
1094
- (title || subtitle || showCoverage && features.showMethodology) && /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "ds-chart-container__header", children: [
1095
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-chart-container__header-content", children: [
1096
- title && /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "ds-chart-container__title", children: title }),
1097
- subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ds-chart-container__subtitle", children: subtitle })
1098
- ] }),
1099
- showCoverage && features.showMethodology && data.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
1100
- DataCoverageBadge,
1101
- {
1102
- sampleSize: data.length,
1103
- requiredSize: minSampleSize,
1104
- dateRange,
1105
- size: "sm"
1106
- }
1107
- )
1108
- ] }),
1109
- /* @__PURE__ */ jsxRuntime.jsx(
1110
- "div",
1111
- {
1112
- className: "ds-chart-container__chart",
1113
- style: { height: typeof height === "number" ? height : void 0 },
1114
- children: renderContent()
1115
- }
1116
- ),
1117
- isRenderable && state !== "VALID" && /* @__PURE__ */ jsxRuntime.jsx("footer", { className: "ds-chart-container__footer", children: /* @__PURE__ */ jsxRuntime.jsx(DataStateIndicator, { state, variant: "compact" }) })
1118
- ]
1119
- }
1120
- );
1121
- }
1122
- ChartContainer.displayName = "ChartContainer";
1123
- var DEFAULT_COLORS = [
1124
- "var(--brand-pink)",
1125
- "var(--brand-yellow)",
1126
- "var(--status-info)",
1127
- "var(--status-success)",
1128
- "var(--status-warning)"
1129
- ];
1130
- function LineChart({
1131
- data,
1132
- xKey,
1133
- lines,
1134
- title,
1135
- subtitle,
1136
- height = 300,
1137
- grid = true,
1138
- legend: showLegend = true,
1139
- curve = "monotone",
1140
- minSampleSize = 7,
1141
- dateRange,
1142
- className
1143
- }) {
1144
- const requiredFields = [xKey, ...lines.map((l) => l.key)];
1145
- const chartData = React2__default.default.useMemo(() => data.map((item) => ({ ...item })), [data]);
1146
- return /* @__PURE__ */ jsxRuntime.jsx(
1147
- ChartContainer,
1148
- {
1149
- title,
1150
- subtitle,
1151
- height,
1152
- data,
1153
- requiredFields,
1154
- minSampleSize,
1155
- dateRange,
1156
- className,
1157
- children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.LineChart, { data: chartData, margin: { top: 5, right: 20, left: 0, bottom: 5 }, children: [
1158
- grid && /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false }),
1159
- /* @__PURE__ */ jsxRuntime.jsx(
1160
- recharts.XAxis,
1161
- {
1162
- dataKey: xKey,
1163
- tick: { fontSize: 12 },
1164
- tickLine: false,
1165
- axisLine: { strokeWidth: 1 }
1166
- }
1167
- ),
1168
- /* @__PURE__ */ jsxRuntime.jsx(recharts.YAxis, { tick: { fontSize: 12 }, tickLine: false, axisLine: false, width: 40 }),
1169
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, {}),
1170
- showLegend && /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, {}),
1171
- lines.map((line, index) => /* @__PURE__ */ jsxRuntime.jsx(
1172
- recharts.Line,
1173
- {
1174
- type: curve,
1175
- dataKey: line.key,
1176
- name: line.name || line.key,
1177
- stroke: line.color || DEFAULT_COLORS[index % DEFAULT_COLORS.length],
1178
- strokeWidth: 2,
1179
- strokeDasharray: line.dashed ? "5 5" : void 0,
1180
- dot: line.dot !== false,
1181
- activeDot: { r: 6 }
1182
- },
1183
- line.key
1184
- ))
1185
- ] })
1186
- }
1187
- );
1188
- }
1189
- LineChart.displayName = "LineChart";
1190
- var DEFAULT_COLORS2 = [
1191
- "var(--brand-pink)",
1192
- "var(--brand-yellow)",
1193
- "var(--status-info)",
1194
- "var(--status-success)",
1195
- "var(--status-warning)"
1196
- ];
1197
- function BarChart({
1198
- data,
1199
- xKey,
1200
- bars,
1201
- title,
1202
- subtitle,
1203
- height = 300,
1204
- layout = "horizontal",
1205
- grid = true,
1206
- legend: showLegend = true,
1207
- radius = 4,
1208
- showLabels = false,
1209
- minSampleSize = 5,
1210
- categoryColors,
1211
- className
1212
- }) {
1213
- const requiredFields = [xKey, ...bars.map((b) => b.key)];
1214
- const isVertical = layout === "vertical";
1215
- const chartData = React2.useMemo(() => data.map((item) => ({ ...item })), [data]);
1216
- return /* @__PURE__ */ jsxRuntime.jsx(
1217
- ChartContainer,
1218
- {
1219
- title,
1220
- subtitle,
1221
- height,
1222
- data: chartData,
1223
- requiredFields,
1224
- minSampleSize,
1225
- className,
1226
- children: /* @__PURE__ */ jsxRuntime.jsxs(
1227
- recharts.BarChart,
1228
- {
1229
- data: chartData,
1230
- layout: isVertical ? "vertical" : "horizontal",
1231
- margin: { top: 5, right: 20, left: isVertical ? 80 : 0, bottom: 5 },
1232
- children: [
1233
- grid && /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", horizontal: !isVertical, vertical: isVertical }),
1234
- isVertical ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1235
- /* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { type: "number", tick: { fontSize: 12 }, tickLine: false, axisLine: false }),
1236
- /* @__PURE__ */ jsxRuntime.jsx(
1237
- recharts.YAxis,
1238
- {
1239
- type: "category",
1240
- dataKey: xKey,
1241
- tick: { fontSize: 12 },
1242
- tickLine: false,
1243
- axisLine: false,
1244
- width: 80
1245
- }
1246
- )
1247
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1248
- /* @__PURE__ */ jsxRuntime.jsx(
1249
- recharts.XAxis,
1250
- {
1251
- dataKey: xKey,
1252
- tick: { fontSize: 12 },
1253
- tickLine: false,
1254
- axisLine: { strokeWidth: 1 }
1255
- }
1256
- ),
1257
- /* @__PURE__ */ jsxRuntime.jsx(recharts.YAxis, { tick: { fontSize: 12 }, tickLine: false, axisLine: false, width: 40 })
1258
- ] }),
1259
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, {}),
1260
- showLegend && bars.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, {}),
1261
- bars.map((bar, barIndex) => /* @__PURE__ */ jsxRuntime.jsx(
1262
- recharts.Bar,
1263
- {
1264
- dataKey: bar.key,
1265
- name: bar.name || bar.key,
1266
- fill: bar.color || DEFAULT_COLORS2[barIndex % DEFAULT_COLORS2.length],
1267
- stackId: bar.stackId,
1268
- radius: [radius, radius, 0, 0],
1269
- label: showLabels ? { position: "top", fontSize: 10 } : false,
1270
- children: categoryColors && chartData.map((_, index) => /* @__PURE__ */ jsxRuntime.jsx(recharts.Cell, { fill: categoryColors[index % categoryColors.length] }, `cell-${index}`))
1271
- },
1272
- bar.key
1273
- ))
1274
- ]
1275
- }
1276
- )
1277
- }
1278
- );
1279
- }
1280
- BarChart.displayName = "BarChart";
1281
- var DEFAULT_COLORS3 = [
1282
- "var(--brand-pink)",
1283
- "var(--brand-yellow)",
1284
- "var(--status-info)",
1285
- "var(--status-success)",
1286
- "var(--status-warning)",
1287
- "var(--status-error)",
1288
- "#8884d8",
1289
- "#82ca9d"
1290
- ];
1291
- function PieChart({
1292
- data,
1293
- title,
1294
- subtitle,
1295
- height = 300,
1296
- innerRadius = 0,
1297
- outerRadius = 80,
1298
- showLabels = true,
1299
- labelType = "percent",
1300
- legend: showLegend = true,
1301
- minSampleSize = 30,
1302
- className
1303
- }) {
1304
- const safeData = React2.useMemo(() => data.map((item) => ({ ...item })), [data]);
1305
- const renderLabel = (props) => {
1306
- const { name, value, percent } = props;
1307
- switch (labelType) {
1308
- case "percent":
1309
- return `${((percent ?? 0) * 100).toFixed(0)}%`;
1310
- case "value":
1311
- return (value ?? 0).toLocaleString();
1312
- case "name":
1313
- return name ?? "";
1314
- default:
1315
- return "";
1316
- }
1317
- };
1318
- return /* @__PURE__ */ jsxRuntime.jsx(
1319
- ChartContainer,
1320
- {
1321
- title,
1322
- subtitle,
1323
- height,
1324
- data: safeData,
1325
- requiredFields: ["name", "value"],
1326
- minSampleSize,
1327
- className,
1328
- children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.PieChart, { children: [
1329
- /* @__PURE__ */ jsxRuntime.jsx(
1330
- recharts.Pie,
1331
- {
1332
- data: safeData,
1333
- cx: "50%",
1334
- cy: "50%",
1335
- innerRadius,
1336
- outerRadius,
1337
- paddingAngle: 2,
1338
- dataKey: "value",
1339
- label: showLabels ? renderLabel : void 0,
1340
- labelLine: showLabels,
1341
- children: safeData.map((entry, index) => /* @__PURE__ */ jsxRuntime.jsx(
1342
- recharts.Cell,
1343
- {
1344
- fill: entry.color || DEFAULT_COLORS3[index % DEFAULT_COLORS3.length]
1345
- },
1346
- `cell-${index}`
1347
- ))
1348
- }
1349
- ),
1350
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, {}),
1351
- showLegend && /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, {})
1352
- ] })
1353
- }
1354
- );
1355
- }
1356
- PieChart.displayName = "PieChart";
1357
- var DEFAULT_COLORS4 = [
1358
- "var(--brand-pink)",
1359
- "var(--brand-yellow)",
1360
- "var(--status-info)",
1361
- "var(--status-success)",
1362
- "var(--status-warning)"
1363
- ];
1364
- function FunnelChart({
1365
- stages,
1366
- title,
1367
- subtitle,
1368
- showConversionRates = true,
1369
- showDropOff = true,
1370
- showValues = true,
1371
- height = 300,
1372
- className
1373
- }) {
1374
- const { features } = useReportMode();
1375
- const isValid = stages.length >= 3;
1376
- const maxValue = stages.length > 0 ? Math.max(...stages.map((s) => s.value)) : 0;
1377
- const stagesWithMetrics = React2.useMemo(() => {
1378
- return stages.map((stage, index) => {
1379
- const prevStage = index > 0 ? stages[index - 1] : null;
1380
- const conversionRate = prevStage ? stage.value / prevStage.value * 100 : 100;
1381
- const dropOff = prevStage ? (prevStage.value - stage.value) / prevStage.value * 100 : 0;
1382
- const widthPercent = maxValue > 0 ? stage.value / maxValue * 100 : 0;
1383
- return {
1384
- ...stage,
1385
- conversionRate,
1386
- dropOff,
1387
- widthPercent,
1388
- color: stage.color || DEFAULT_COLORS4[index % DEFAULT_COLORS4.length]
1389
- };
1390
- });
1391
- }, [stages, maxValue]);
1392
- if (!isValid) {
1393
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx11__default.default("ds-funnel-chart", "ds-funnel-chart--invalid", className), children: [
1394
- title && /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "ds-funnel-chart__title", children: title }),
1395
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-funnel-chart__empty", children: /* @__PURE__ */ jsxRuntime.jsx(
1396
- DataStateIndicator,
1397
- {
1398
- state: "INSUFFICIENT_SAMPLE",
1399
- variant: "full",
1400
- details: {
1401
- message: "Funnel requires at least 3 stages",
1402
- sampleSize: stages.length,
1403
- requiredSize: 3
1404
- }
1405
- }
1406
- ) })
1407
- ] });
1408
- }
1409
- const totalConversion = stages.length > 1 ? (stages[stages.length - 1].value / stages[0].value * 100).toFixed(1) : "100";
1410
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx11__default.default("ds-funnel-chart", className), style: { minHeight: height }, children: [
1411
- (title || subtitle) && /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "ds-funnel-chart__header", children: [
1412
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1413
- title && /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "ds-funnel-chart__title", children: title }),
1414
- subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ds-funnel-chart__subtitle", children: subtitle })
1415
- ] }),
1416
- features.showMethodology && /* @__PURE__ */ jsxRuntime.jsx(DataCoverageBadge, { sampleSize: stages[0].value, size: "sm" })
1417
- ] }),
1418
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-funnel-chart__stages", children: stagesWithMetrics.map((stage, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-funnel-chart__stage", children: [
1419
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-funnel-chart__bar-container", children: /* @__PURE__ */ jsxRuntime.jsx(
1420
- "div",
1421
- {
1422
- className: "ds-funnel-chart__bar",
1423
- style: {
1424
- width: `${stage.widthPercent}%`,
1425
- backgroundColor: stage.color
1426
- },
1427
- children: showValues && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-funnel-chart__value", children: stage.value.toLocaleString() })
1428
- }
1429
- ) }),
1430
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-funnel-chart__label", children: [
1431
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-funnel-chart__stage-name", children: stage.name }),
1432
- showConversionRates && index > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ds-funnel-chart__conversion", children: [
1433
- stage.conversionRate.toFixed(1),
1434
- "% converted"
1435
- ] })
1436
- ] }),
1437
- showDropOff && index > 0 && stage.dropOff > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-funnel-chart__dropoff", children: [
1438
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-funnel-chart__dropoff-arrow", children: "\u2193" }),
1439
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ds-funnel-chart__dropoff-value", children: [
1440
- "-",
1441
- stage.dropOff.toFixed(1),
1442
- "%"
1443
- ] })
1444
- ] })
1445
- ] }, stage.name)) }),
1446
- /* @__PURE__ */ jsxRuntime.jsx("footer", { className: "ds-funnel-chart__footer", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ds-funnel-chart__total", children: [
1447
- "Overall Conversion: ",
1448
- /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
1449
- totalConversion,
1450
- "%"
1451
- ] })
1452
- ] }) })
1453
- ] });
1454
- }
1455
- FunnelChart.displayName = "FunnelChart";
1456
- tooltip.Tooltip.Provider;
1457
- tooltip.Tooltip.Root;
1458
- tooltip.Tooltip.Trigger;
1459
- var TooltipContent = React2__default.default.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(tooltip.Tooltip.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(tooltip.Tooltip.Positioner, { sideOffset: 5, children: /* @__PURE__ */ jsxRuntime.jsxs(tooltip.Tooltip.Popup, { ref, className: clsx11__default.default("ds-tooltip__content", className), ...props, children: [
1460
- children,
1461
- /* @__PURE__ */ jsxRuntime.jsx(tooltip.Tooltip.Arrow, { className: "ds-tooltip__arrow" })
1462
- ] }) }) }));
1463
- TooltipContent.displayName = "TooltipContent";
1464
- var Tooltip4 = ({ content, children, delay = 200 }) => {
1465
- return /* @__PURE__ */ jsxRuntime.jsx(tooltip.Tooltip.Provider, { delay, children: /* @__PURE__ */ jsxRuntime.jsxs(tooltip.Tooltip.Root, { children: [
1466
- /* @__PURE__ */ jsxRuntime.jsx(tooltip.Tooltip.Trigger, { render: children }),
1467
- /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: content })
1468
- ] }) });
1469
- };
1470
- function HeatmapChart({
1471
- data,
1472
- title,
1473
- subtitle,
1474
- xLabel,
1475
- yLabel,
1476
- colorScale = ["var(--glass-elevated)", "var(--brand-pink)"],
1477
- showValues = true,
1478
- valueFormatter = (v) => v.toFixed(0),
1479
- minCells = 25,
1480
- className
1481
- }) {
1482
- const { features } = useReportMode();
1483
- const { xValues, yValues, cellMap, minValue, maxValue } = React2.useMemo(() => {
1484
- const xSet = /* @__PURE__ */ new Set();
1485
- const ySet = /* @__PURE__ */ new Set();
1486
- const map = /* @__PURE__ */ new Map();
1487
- let min = Infinity;
1488
- let max = -Infinity;
1489
- for (const cell of data) {
1490
- xSet.add(cell.x);
1491
- ySet.add(cell.y);
1492
- map.set(`${cell.x}-${cell.y}`, cell.value);
1493
- min = Math.min(min, cell.value);
1494
- max = Math.max(max, cell.value);
1495
- }
1496
- return {
1497
- xValues: Array.from(xSet),
1498
- yValues: Array.from(ySet),
1499
- cellMap: map,
1500
- minValue: min === Infinity ? 0 : min,
1501
- maxValue: max === -Infinity ? 0 : max
1502
- };
1503
- }, [data]);
1504
- const isValid = data.length >= minCells;
1505
- const getCellColor = (value) => {
1506
- if (maxValue === minValue) return colorScale[0];
1507
- const ratio = (value - minValue) / (maxValue - minValue);
1508
- return `color-mix(in srgb, ${colorScale[1]} ${ratio * 100}%, ${colorScale[0]})`;
1509
- };
1510
- const getTextColor = (value) => {
1511
- const ratio = (value - minValue) / (maxValue - minValue);
1512
- return ratio > 0.5 ? "white" : "var(--text-primary)";
1513
- };
1514
- if (!isValid) {
1515
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx11__default.default("ds-heatmap-chart", "ds-heatmap-chart--invalid", className), children: [
1516
- title && /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "ds-heatmap-chart__title", children: title }),
1517
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-heatmap-chart__empty", children: [
1518
- /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Insufficient data for heatmap visualization" }),
1519
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "ds-heatmap-chart__empty-detail", children: [
1520
- data.length,
1521
- " cells provided, ",
1522
- minCells,
1523
- " required"
1524
- ] })
1525
- ] })
1526
- ] });
1527
- }
1528
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx11__default.default("ds-heatmap-chart", className), children: [
1529
- (title || subtitle) && /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "ds-heatmap-chart__header", children: [
1530
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1531
- title && /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "ds-heatmap-chart__title", children: title }),
1532
- subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ds-heatmap-chart__subtitle", children: subtitle })
1533
- ] }),
1534
- features.showMethodology && /* @__PURE__ */ jsxRuntime.jsx(DataCoverageBadge, { sampleSize: data.length, requiredSize: minCells, size: "sm" })
1535
- ] }),
1536
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-heatmap-chart__container", children: [
1537
- yLabel && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-heatmap-chart__y-label", children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: yLabel }) }),
1538
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-heatmap-chart__grid-wrapper", children: [
1539
- /* @__PURE__ */ jsxRuntime.jsx(
1540
- "div",
1541
- {
1542
- className: "ds-heatmap-chart__grid",
1543
- style: {
1544
- gridTemplateColumns: `repeat(${xValues.length}, 1fr)`,
1545
- gridTemplateRows: `repeat(${yValues.length}, 1fr)`
1546
- },
1547
- children: yValues.map(
1548
- (y) => xValues.map((x) => {
1549
- const value = cellMap.get(`${x}-${y}`) ?? 0;
1550
- const cellContent = /* @__PURE__ */ jsxRuntime.jsx(
1551
- "div",
1552
- {
1553
- className: "ds-heatmap-chart__cell",
1554
- style: {
1555
- backgroundColor: getCellColor(value),
1556
- color: getTextColor(value)
1557
- },
1558
- children: showValues && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-heatmap-chart__cell-value", children: valueFormatter(value) })
1559
- },
1560
- `${x}-${y}`
1561
- );
1562
- return /* @__PURE__ */ jsxRuntime.jsx(Tooltip4, { content: `${x}, ${y}: ${valueFormatter(value)}`, children: cellContent }, `${x}-${y}`);
1563
- })
1564
- )
1565
- }
1566
- ),
1567
- /* @__PURE__ */ jsxRuntime.jsx(
1568
- "div",
1569
- {
1570
- className: "ds-heatmap-chart__x-labels",
1571
- style: { gridTemplateColumns: `repeat(${xValues.length}, 1fr)` },
1572
- children: xValues.map((x) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-heatmap-chart__x-label", children: x }, x))
1573
- }
1574
- )
1575
- ] }),
1576
- /* @__PURE__ */ jsxRuntime.jsx(
1577
- "div",
1578
- {
1579
- className: "ds-heatmap-chart__y-labels",
1580
- style: { gridTemplateRows: `repeat(${yValues.length}, 1fr)` },
1581
- children: yValues.map((y) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-heatmap-chart__y-label-item", children: y }, y))
1582
- }
1583
- )
1584
- ] }),
1585
- xLabel && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-heatmap-chart__x-axis-label", children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: xLabel }) }),
1586
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-heatmap-chart__legend", children: [
1587
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-heatmap-chart__legend-label", children: "Low" }),
1588
- /* @__PURE__ */ jsxRuntime.jsx(
1589
- "div",
1590
- {
1591
- className: "ds-heatmap-chart__legend-bar",
1592
- style: {
1593
- background: `linear-gradient(to right, ${colorScale[0]}, ${colorScale[1]})`
1594
- }
1595
- }
1596
- ),
1597
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-heatmap-chart__legend-label", children: "High" })
1598
- ] })
1599
- ] });
1600
- }
1601
- HeatmapChart.displayName = "HeatmapChart";
1602
- function ChartSwitchControl({
1603
- currentType,
1604
- allowedTypes,
1605
- onTypeChange,
1606
- size = "sm",
1607
- className
1608
- }) {
1609
- if (allowedTypes.length <= 1) {
1610
- return null;
1611
- }
1612
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx11__default.default("ds-chart-switch", `ds-chart-switch--${size}`, className), children: allowedTypes.map((type) => {
1613
- const meta = CHART_REGISTRY[type];
1614
- if (!meta) return null;
1615
- const isActive = type === currentType;
1616
- const Icon = getChartIcon(type);
1617
- return /* @__PURE__ */ jsxRuntime.jsxs(
1618
- "button",
1619
- {
1620
- type: "button",
1621
- className: clsx11__default.default(
1622
- "ds-chart-switch__option",
1623
- isActive && "ds-chart-switch__option--active"
1624
- ),
1625
- onClick: () => onTypeChange(type),
1626
- title: meta.name,
1627
- "aria-pressed": isActive,
1628
- children: [
1629
- /* @__PURE__ */ jsxRuntime.jsx(Icon, {}),
1630
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-chart-switch__label", children: getShortLabel(type) })
1631
- ]
1632
- },
1633
- type
1634
- );
1635
- }) });
1636
- }
1637
- ChartSwitchControl.displayName = "ChartSwitchControl";
1638
- function getChartIcon(type) {
1639
- const icons = {
1640
- line: LineIcon,
1641
- smooth_line: SmoothLineIcon,
1642
- area: AreaIcon,
1643
- stacked_area: StackedAreaIcon,
1644
- area_100pct: StackedAreaIcon,
1645
- bar: BarIcon,
1646
- column: ColumnIcon,
1647
- stacked_bar: StackedBarIcon,
1648
- stacked_column: StackedColumnIcon,
1649
- column_100pct: StackedColumnIcon,
1650
- pie: PieIcon,
1651
- donut: DonutIcon,
1652
- histogram: HistogramIcon,
1653
- funnel: FunnelIcon,
1654
- heatmap: HeatmapIcon
1655
- };
1656
- return icons[type] || DefaultChartIcon;
1657
- }
1658
- function getShortLabel(type) {
1659
- const labels = {
1660
- line: "Line",
1661
- smooth_line: "Smooth",
1662
- area: "Area",
1663
- stacked_area: "Stacked",
1664
- area_100pct: "100%",
1665
- bar: "Bar",
1666
- column: "Column",
1667
- stacked_bar: "Stacked",
1668
- stacked_column: "Stacked",
1669
- column_100pct: "100%",
1670
- pie: "Pie",
1671
- donut: "Donut",
1672
- histogram: "Histogram",
1673
- funnel: "Funnel",
1674
- heatmap: "Heatmap"
1675
- };
1676
- return labels[type] || type;
1677
- }
1678
- function LineIcon() {
1679
- return /* @__PURE__ */ jsxRuntime.jsx(
1680
- "svg",
1681
- {
1682
- width: "16",
1683
- height: "16",
1684
- viewBox: "0 0 24 24",
1685
- fill: "none",
1686
- stroke: "currentColor",
1687
- strokeWidth: "2",
1688
- children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "22 12 18 8 13 13 9 9 2 16" })
1689
- }
1690
- );
1691
- }
1692
- function SmoothLineIcon() {
1693
- return /* @__PURE__ */ jsxRuntime.jsx(
1694
- "svg",
1695
- {
1696
- width: "16",
1697
- height: "16",
1698
- viewBox: "0 0 24 24",
1699
- fill: "none",
1700
- stroke: "currentColor",
1701
- strokeWidth: "2",
1702
- children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 16 C6 16, 8 8, 12 12 S18 6, 22 10" })
1703
- }
1704
- );
1705
- }
1706
- function AreaIcon() {
1707
- return /* @__PURE__ */ jsxRuntime.jsxs(
1708
- "svg",
1709
- {
1710
- width: "16",
1711
- height: "16",
1712
- viewBox: "0 0 24 24",
1713
- fill: "none",
1714
- stroke: "currentColor",
1715
- strokeWidth: "2",
1716
- children: [
1717
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 20 L2 16 L8 10 L14 14 L22 6 L22 20 Z", fill: "currentColor", fillOpacity: "0.2" }),
1718
- /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "2 16 8 10 14 14 22 6" })
1719
- ]
1720
- }
1721
- );
1722
- }
1723
- function StackedAreaIcon() {
1724
- return /* @__PURE__ */ jsxRuntime.jsxs(
1725
- "svg",
1726
- {
1727
- width: "16",
1728
- height: "16",
1729
- viewBox: "0 0 24 24",
1730
- fill: "none",
1731
- stroke: "currentColor",
1732
- strokeWidth: "2",
1733
- children: [
1734
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 20 L2 14 L8 10 L14 12 L22 8 L22 20 Z", fill: "currentColor", fillOpacity: "0.3" }),
1735
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 20 L2 16 L8 14 L14 15 L22 12 L22 20 Z", fill: "currentColor", fillOpacity: "0.2" })
1736
- ]
1737
- }
1738
- );
1739
- }
1740
- function BarIcon() {
1741
- return /* @__PURE__ */ jsxRuntime.jsxs(
1742
- "svg",
1743
- {
1744
- width: "16",
1745
- height: "16",
1746
- viewBox: "0 0 24 24",
1747
- fill: "none",
1748
- stroke: "currentColor",
1749
- strokeWidth: "2",
1750
- children: [
1751
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2", y: "4", width: "14", height: "4", rx: "1", fill: "currentColor", fillOpacity: "0.2" }),
1752
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2", y: "10", width: "18", height: "4", rx: "1", fill: "currentColor", fillOpacity: "0.2" }),
1753
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2", y: "16", width: "10", height: "4", rx: "1", fill: "currentColor", fillOpacity: "0.2" })
1754
- ]
1755
- }
1756
- );
1757
- }
1758
- function ColumnIcon() {
1759
- return /* @__PURE__ */ jsxRuntime.jsxs(
1760
- "svg",
1761
- {
1762
- width: "16",
1763
- height: "16",
1764
- viewBox: "0 0 24 24",
1765
- fill: "none",
1766
- stroke: "currentColor",
1767
- strokeWidth: "2",
1768
- children: [
1769
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "4", y: "8", width: "4", height: "14", rx: "1", fill: "currentColor", fillOpacity: "0.2" }),
1770
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "10", y: "4", width: "4", height: "18", rx: "1", fill: "currentColor", fillOpacity: "0.2" }),
1771
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "16", y: "12", width: "4", height: "10", rx: "1", fill: "currentColor", fillOpacity: "0.2" })
1772
- ]
1773
- }
1774
- );
1775
- }
1776
- function StackedBarIcon() {
1777
- return /* @__PURE__ */ jsxRuntime.jsxs(
1778
- "svg",
1779
- {
1780
- width: "16",
1781
- height: "16",
1782
- viewBox: "0 0 24 24",
1783
- fill: "none",
1784
- stroke: "currentColor",
1785
- strokeWidth: "2",
1786
- children: [
1787
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2", y: "4", width: "8", height: "4", rx: "1", fill: "currentColor", fillOpacity: "0.3" }),
1788
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "10", y: "4", width: "6", height: "4", rx: "1", fill: "currentColor", fillOpacity: "0.15" }),
1789
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2", y: "10", width: "12", height: "4", rx: "1", fill: "currentColor", fillOpacity: "0.3" }),
1790
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "14", y: "10", width: "6", height: "4", rx: "1", fill: "currentColor", fillOpacity: "0.15" }),
1791
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2", y: "16", width: "6", height: "4", rx: "1", fill: "currentColor", fillOpacity: "0.3" }),
1792
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "8", y: "16", width: "4", height: "4", rx: "1", fill: "currentColor", fillOpacity: "0.15" })
1793
- ]
1794
- }
1795
- );
1796
- }
1797
- function StackedColumnIcon() {
1798
- return /* @__PURE__ */ jsxRuntime.jsxs(
1799
- "svg",
1800
- {
1801
- width: "16",
1802
- height: "16",
1803
- viewBox: "0 0 24 24",
1804
- fill: "none",
1805
- stroke: "currentColor",
1806
- strokeWidth: "2",
1807
- children: [
1808
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "4", y: "14", width: "4", height: "8", rx: "1", fill: "currentColor", fillOpacity: "0.3" }),
1809
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "4", y: "8", width: "4", height: "6", rx: "1", fill: "currentColor", fillOpacity: "0.15" }),
1810
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "10", y: "10", width: "4", height: "12", rx: "1", fill: "currentColor", fillOpacity: "0.3" }),
1811
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "10", y: "4", width: "4", height: "6", rx: "1", fill: "currentColor", fillOpacity: "0.15" }),
1812
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "16", y: "16", width: "4", height: "6", rx: "1", fill: "currentColor", fillOpacity: "0.3" }),
1813
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "16", y: "12", width: "4", height: "4", rx: "1", fill: "currentColor", fillOpacity: "0.15" })
1814
- ]
1815
- }
1816
- );
1817
- }
1818
- function PieIcon() {
1819
- return /* @__PURE__ */ jsxRuntime.jsxs(
1820
- "svg",
1821
- {
1822
- width: "16",
1823
- height: "16",
1824
- viewBox: "0 0 24 24",
1825
- fill: "none",
1826
- stroke: "currentColor",
1827
- strokeWidth: "2",
1828
- children: [
1829
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", fill: "currentColor", fillOpacity: "0.2" }),
1830
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 2 A10 10 0 0 1 22 12 L12 12 Z", fill: "currentColor", fillOpacity: "0.3" })
1831
- ]
1832
- }
1833
- );
1834
- }
1835
- function DonutIcon() {
1836
- return /* @__PURE__ */ jsxRuntime.jsxs(
1837
- "svg",
1838
- {
1839
- width: "16",
1840
- height: "16",
1841
- viewBox: "0 0 24 24",
1842
- fill: "none",
1843
- stroke: "currentColor",
1844
- strokeWidth: "2",
1845
- children: [
1846
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", fill: "currentColor", fillOpacity: "0.2" }),
1847
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "5", fill: "var(--glass-elevated)", stroke: "none" }),
1848
- /* @__PURE__ */ jsxRuntime.jsx(
1849
- "path",
1850
- {
1851
- d: "M12 2 A10 10 0 0 1 22 12 L17 12 A5 5 0 0 0 12 7 Z",
1852
- fill: "currentColor",
1853
- fillOpacity: "0.3"
1854
- }
1855
- )
1856
- ]
1857
- }
1858
- );
1859
- }
1860
- function HistogramIcon() {
1861
- return /* @__PURE__ */ jsxRuntime.jsxs(
1862
- "svg",
1863
- {
1864
- width: "16",
1865
- height: "16",
1866
- viewBox: "0 0 24 24",
1867
- fill: "none",
1868
- stroke: "currentColor",
1869
- strokeWidth: "2",
1870
- children: [
1871
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2", y: "14", width: "4", height: "8", rx: "0", fill: "currentColor", fillOpacity: "0.2" }),
1872
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "6", y: "10", width: "4", height: "12", rx: "0", fill: "currentColor", fillOpacity: "0.2" }),
1873
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "10", y: "4", width: "4", height: "18", rx: "0", fill: "currentColor", fillOpacity: "0.2" }),
1874
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "14", y: "8", width: "4", height: "14", rx: "0", fill: "currentColor", fillOpacity: "0.2" }),
1875
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "18", y: "12", width: "4", height: "10", rx: "0", fill: "currentColor", fillOpacity: "0.2" })
1876
- ]
1877
- }
1878
- );
1879
- }
1880
- function FunnelIcon() {
1881
- return /* @__PURE__ */ jsxRuntime.jsxs(
1882
- "svg",
1883
- {
1884
- width: "16",
1885
- height: "16",
1886
- viewBox: "0 0 24 24",
1887
- fill: "none",
1888
- stroke: "currentColor",
1889
- strokeWidth: "2",
1890
- children: [
1891
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 4 H22 L18 10 H6 Z", fill: "currentColor", fillOpacity: "0.3" }),
1892
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 10 H18 L15 16 H9 Z", fill: "currentColor", fillOpacity: "0.25" }),
1893
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 16 H15 L13 22 H11 Z", fill: "currentColor", fillOpacity: "0.2" })
1894
- ]
1895
- }
1896
- );
1897
- }
1898
- function HeatmapIcon() {
1899
- return /* @__PURE__ */ jsxRuntime.jsxs(
1900
- "svg",
1901
- {
1902
- width: "16",
1903
- height: "16",
1904
- viewBox: "0 0 24 24",
1905
- fill: "none",
1906
- stroke: "currentColor",
1907
- strokeWidth: "1",
1908
- children: [
1909
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2", y: "2", width: "6", height: "6", fill: "currentColor", fillOpacity: "0.1" }),
1910
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "9", y: "2", width: "6", height: "6", fill: "currentColor", fillOpacity: "0.3" }),
1911
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "16", y: "2", width: "6", height: "6", fill: "currentColor", fillOpacity: "0.2" }),
1912
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2", y: "9", width: "6", height: "6", fill: "currentColor", fillOpacity: "0.4" }),
1913
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "9", y: "9", width: "6", height: "6", fill: "currentColor", fillOpacity: "0.6" }),
1914
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "16", y: "9", width: "6", height: "6", fill: "currentColor", fillOpacity: "0.3" }),
1915
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2", y: "16", width: "6", height: "6", fill: "currentColor", fillOpacity: "0.2" }),
1916
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "9", y: "16", width: "6", height: "6", fill: "currentColor", fillOpacity: "0.5" }),
1917
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "16", y: "16", width: "6", height: "6", fill: "currentColor", fillOpacity: "0.4" })
1918
- ]
1919
- }
1920
- );
1921
- }
1922
- function DefaultChartIcon() {
1923
- return /* @__PURE__ */ jsxRuntime.jsxs(
1924
- "svg",
1925
- {
1926
- width: "16",
1927
- height: "16",
1928
- viewBox: "0 0 24 24",
1929
- fill: "none",
1930
- stroke: "currentColor",
1931
- strokeWidth: "2",
1932
- children: [
1933
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
1934
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 15 L9 9 L13 13 L21 5" })
1935
- ]
1936
- }
1937
- );
1938
- }
1939
- var CHART_COLORS = [
1940
- "var(--brand-pink)",
1941
- "var(--brand-yellow)",
1942
- "var(--status-info)",
1943
- "var(--status-success)",
1944
- "var(--status-warning)",
1945
- "var(--status-error)"
1946
- ];
1947
- function getColor(index, customColor) {
1948
- return customColor || CHART_COLORS[index % CHART_COLORS.length];
1949
- }
1950
- function Chart({
1951
- intent,
1952
- data,
1953
- dimensions,
1954
- measures,
1955
- defaultType,
1956
- allowedTypes,
1957
- chartType: controlledType,
1958
- onChartTypeChange,
1959
- allowSwitching = false,
1960
- title,
1961
- subtitle,
1962
- height = 300,
1963
- legend: showLegend = true,
1964
- grid = true,
1965
- className
1966
- }) {
1967
- const { features } = useReportMode();
1968
- const resolvedDefault = defaultType || getDefaultChartForIntent(intent);
1969
- const [internalType, setInternalType] = React2.useState(resolvedDefault);
1970
- const activeType = controlledType ?? internalType;
1971
- const resolvedAllowedTypes = React2.useMemo(() => {
1972
- if (allowedTypes) return allowedTypes;
1973
- return getAllowedSwitchTargets(activeType);
1974
- }, [allowedTypes, activeType]);
1975
- const validation = React2.useMemo(() => {
1976
- return validateChartData(
1977
- activeType,
1978
- data,
1979
- dimensions.map((d) => d.key),
1980
- measures.map((m) => m.key)
1981
- );
1982
- }, [activeType, data, dimensions, measures]);
1983
- const handleTypeChange = (newType) => {
1984
- if (onChartTypeChange) {
1985
- onChartTypeChange(newType);
1986
- } else {
1987
- setInternalType(newType);
1988
- }
1989
- };
1990
- const chartMeta = CHART_REGISTRY[activeType];
1991
- const renderChart = () => {
1992
- if (!validation.isValid) {
1993
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-chart__invalid", children: /* @__PURE__ */ jsxRuntime.jsx(
1994
- DataStateIndicator,
1995
- {
1996
- state: "INSUFFICIENT_SAMPLE",
1997
- variant: "full",
1998
- details: {
1999
- message: validation.errors[0],
2000
- sampleSize: data.length,
2001
- requiredSize: chartMeta?.contract.minDataPoints || 0
2002
- }
2003
- }
2004
- ) });
2005
- }
2006
- const xKey = dimensions[0]?.key || "x";
2007
- switch (activeType) {
2008
- case "line":
2009
- case "smooth_line":
2010
- return renderLineChart(xKey, activeType === "smooth_line");
2011
- case "area":
2012
- case "stacked_area":
2013
- case "area_100pct":
2014
- return renderAreaChart(xKey, activeType);
2015
- case "bar":
2016
- case "stacked_bar":
2017
- return renderBarChart(xKey, activeType, "horizontal");
2018
- case "column":
2019
- case "stacked_column":
2020
- case "column_100pct":
2021
- return renderBarChart(xKey, activeType, "vertical");
2022
- case "pie":
2023
- case "donut":
2024
- return renderPieChart(xKey, activeType === "donut");
2025
- case "histogram":
2026
- return renderHistogram();
2027
- default:
2028
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-chart__unsupported", children: [
2029
- 'Chart type "',
2030
- activeType,
2031
- '" is not yet implemented'
2032
- ] });
2033
- }
2034
- };
2035
- const renderLineChart = (xKey, smooth) => /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height, children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.LineChart, { data, margin: { top: 5, right: 20, left: 0, bottom: 5 }, children: [
2036
- grid && /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false }),
2037
- /* @__PURE__ */ jsxRuntime.jsx(
2038
- recharts.XAxis,
2039
- {
2040
- dataKey: xKey,
2041
- tick: { fontSize: 12 },
2042
- tickLine: false,
2043
- axisLine: { strokeWidth: 1 }
2044
- }
2045
- ),
2046
- /* @__PURE__ */ jsxRuntime.jsx(recharts.YAxis, { tick: { fontSize: 12 }, tickLine: false, axisLine: false, width: 40 }),
2047
- /* @__PURE__ */ jsxRuntime.jsx(
2048
- recharts.Tooltip,
2049
- {
2050
- contentStyle: {
2051
- background: "var(--glass-elevated)",
2052
- border: "1px solid var(--glass-border)"
2053
- }
2054
- }
2055
- ),
2056
- showLegend && measures.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, {}),
2057
- measures.map((measure, idx) => /* @__PURE__ */ jsxRuntime.jsx(
2058
- recharts.Line,
2059
- {
2060
- type: smooth ? "monotone" : "linear",
2061
- dataKey: measure.key,
2062
- name: measure.label || measure.key,
2063
- stroke: getColor(idx, measure.color),
2064
- strokeWidth: 2,
2065
- dot: true,
2066
- activeDot: { r: 6 }
2067
- },
2068
- measure.key
2069
- ))
2070
- ] }) });
2071
- const renderAreaChart = (xKey, type) => {
2072
- const isStacked = type === "stacked_area" || type === "area_100pct";
2073
- const is100Pct = type === "area_100pct";
2074
- const chartData = is100Pct ? normalizeData(data, measures) : data;
2075
- return /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height, children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.AreaChart, { data: chartData, margin: { top: 5, right: 20, left: 0, bottom: 5 }, children: [
2076
- grid && /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false }),
2077
- /* @__PURE__ */ jsxRuntime.jsx(
2078
- recharts.XAxis,
2079
- {
2080
- dataKey: xKey,
2081
- tick: { fontSize: 12 },
2082
- tickLine: false,
2083
- axisLine: { strokeWidth: 1 }
2084
- }
2085
- ),
2086
- /* @__PURE__ */ jsxRuntime.jsx(
2087
- recharts.YAxis,
2088
- {
2089
- tick: { fontSize: 12 },
2090
- tickLine: false,
2091
- axisLine: false,
2092
- width: 40,
2093
- domain: is100Pct ? [0, 100] : void 0,
2094
- tickFormatter: is100Pct ? (v) => `${v}%` : void 0
2095
- }
2096
- ),
2097
- /* @__PURE__ */ jsxRuntime.jsx(
2098
- recharts.Tooltip,
2099
- {
2100
- contentStyle: {
2101
- background: "var(--glass-elevated)",
2102
- border: "1px solid var(--glass-border)"
2103
- }
2104
- }
2105
- ),
2106
- showLegend && /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, {}),
2107
- measures.map((measure, idx) => /* @__PURE__ */ jsxRuntime.jsx(
2108
- recharts.Area,
2109
- {
2110
- type: "monotone",
2111
- dataKey: measure.key,
2112
- name: measure.label || measure.key,
2113
- stroke: getColor(idx, measure.color),
2114
- fill: getColor(idx, measure.color),
2115
- fillOpacity: 0.3,
2116
- stackId: isStacked ? "stack" : void 0
2117
- },
2118
- measure.key
2119
- ))
2120
- ] }) });
2121
- };
2122
- const renderBarChart = (xKey, type, layout) => {
2123
- const isStacked = type.includes("stacked") || type.includes("100pct");
2124
- const is100Pct = type.includes("100pct");
2125
- const isHorizontal = layout === "horizontal";
2126
- const chartData = is100Pct ? normalizeData(data, measures) : data;
2127
- return /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height, children: /* @__PURE__ */ jsxRuntime.jsxs(
2128
- recharts.BarChart,
2129
- {
2130
- data: chartData,
2131
- layout: isHorizontal ? "vertical" : "horizontal",
2132
- margin: { top: 5, right: 20, left: isHorizontal ? 80 : 0, bottom: 5 },
2133
- children: [
2134
- grid && /* @__PURE__ */ jsxRuntime.jsx(
2135
- recharts.CartesianGrid,
2136
- {
2137
- strokeDasharray: "3 3",
2138
- horizontal: !isHorizontal,
2139
- vertical: isHorizontal
2140
- }
2141
- ),
2142
- isHorizontal ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2143
- /* @__PURE__ */ jsxRuntime.jsx(
2144
- recharts.XAxis,
2145
- {
2146
- type: "number",
2147
- tick: { fontSize: 12 },
2148
- tickLine: false,
2149
- axisLine: false,
2150
- domain: is100Pct ? [0, 100] : void 0,
2151
- tickFormatter: is100Pct ? (v) => `${v}%` : void 0
2152
- }
2153
- ),
2154
- /* @__PURE__ */ jsxRuntime.jsx(
2155
- recharts.YAxis,
2156
- {
2157
- type: "category",
2158
- dataKey: xKey,
2159
- tick: { fontSize: 12 },
2160
- tickLine: false,
2161
- axisLine: false,
2162
- width: 80
2163
- }
2164
- )
2165
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2166
- /* @__PURE__ */ jsxRuntime.jsx(
2167
- recharts.XAxis,
2168
- {
2169
- dataKey: xKey,
2170
- tick: { fontSize: 12 },
2171
- tickLine: false,
2172
- axisLine: { strokeWidth: 1 }
2173
- }
2174
- ),
2175
- /* @__PURE__ */ jsxRuntime.jsx(
2176
- recharts.YAxis,
2177
- {
2178
- tick: { fontSize: 12 },
2179
- tickLine: false,
2180
- axisLine: false,
2181
- width: 40,
2182
- domain: is100Pct ? [0, 100] : void 0,
2183
- tickFormatter: is100Pct ? (v) => `${v}%` : void 0
2184
- }
2185
- )
2186
- ] }),
2187
- /* @__PURE__ */ jsxRuntime.jsx(
2188
- recharts.Tooltip,
2189
- {
2190
- contentStyle: {
2191
- background: "var(--glass-elevated)",
2192
- border: "1px solid var(--glass-border)"
2193
- }
2194
- }
2195
- ),
2196
- showLegend && measures.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, {}),
2197
- measures.map((measure, idx) => /* @__PURE__ */ jsxRuntime.jsx(
2198
- recharts.Bar,
2199
- {
2200
- dataKey: measure.key,
2201
- name: measure.label || measure.key,
2202
- fill: getColor(idx, measure.color),
2203
- stackId: isStacked ? "stack" : void 0,
2204
- radius: isStacked ? void 0 : [4, 4, 0, 0]
2205
- },
2206
- measure.key
2207
- ))
2208
- ]
2209
- }
2210
- ) });
2211
- };
2212
- const renderPieChart = (nameKey, isDonut) => {
2213
- const valueKey = measures[0]?.key || "value";
2214
- return /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height, children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.PieChart, { children: [
2215
- /* @__PURE__ */ jsxRuntime.jsx(
2216
- recharts.Pie,
2217
- {
2218
- data,
2219
- dataKey: valueKey,
2220
- nameKey,
2221
- cx: "50%",
2222
- cy: "50%",
2223
- innerRadius: isDonut ? "50%" : 0,
2224
- outerRadius: "80%",
2225
- label: ({ name, percent }) => `${name}: ${((percent ?? 0) * 100).toFixed(0)}%`,
2226
- labelLine: false,
2227
- children: data.map((_, idx) => /* @__PURE__ */ jsxRuntime.jsx(recharts.Cell, { fill: getColor(idx) }, `cell-${idx}`))
2228
- }
2229
- ),
2230
- /* @__PURE__ */ jsxRuntime.jsx(
2231
- recharts.Tooltip,
2232
- {
2233
- contentStyle: {
2234
- background: "var(--glass-elevated)",
2235
- border: "1px solid var(--glass-border)"
2236
- }
2237
- }
2238
- ),
2239
- showLegend && /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, {})
2240
- ] }) });
2241
- };
2242
- const renderHistogram = () => {
2243
- const valueKey = measures[0]?.key || "value";
2244
- const binKey = dimensions[0]?.key || "bin";
2245
- return /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height, children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.BarChart, { data, margin: { top: 5, right: 20, left: 0, bottom: 5 }, children: [
2246
- grid && /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false }),
2247
- /* @__PURE__ */ jsxRuntime.jsx(
2248
- recharts.XAxis,
2249
- {
2250
- dataKey: binKey,
2251
- tick: { fontSize: 12 },
2252
- tickLine: false,
2253
- axisLine: { strokeWidth: 1 }
2254
- }
2255
- ),
2256
- /* @__PURE__ */ jsxRuntime.jsx(recharts.YAxis, { tick: { fontSize: 12 }, tickLine: false, axisLine: false, width: 40 }),
2257
- /* @__PURE__ */ jsxRuntime.jsx(
2258
- recharts.Tooltip,
2259
- {
2260
- contentStyle: {
2261
- background: "var(--glass-elevated)",
2262
- border: "1px solid var(--glass-border)"
2263
- }
2264
- }
2265
- ),
2266
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Bar, { dataKey: valueKey, fill: getColor(0), radius: [4, 4, 0, 0] })
2267
- ] }) });
2268
- };
2269
- const normalizeData = (sourceData, sourceMeasures) => {
2270
- return sourceData.map((row) => {
2271
- const total = sourceMeasures.reduce((sum, m) => {
2272
- const val = row[m.key];
2273
- return sum + (typeof val === "number" ? val : 0);
2274
- }, 0);
2275
- if (total === 0) return row;
2276
- const normalized = { ...row };
2277
- sourceMeasures.forEach((m) => {
2278
- const val = row[m.key];
2279
- if (typeof val === "number") {
2280
- normalized[m.key] = val / total * 100;
2281
- }
2282
- });
2283
- return normalized;
2284
- });
2285
- };
2286
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx11__default.default("ds-chart", className), children: [
2287
- (title || subtitle || allowSwitching) && /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "ds-chart__header", children: [
2288
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-chart__header-text", children: [
2289
- title && /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "ds-chart__title", children: title }),
2290
- subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ds-chart__subtitle", children: subtitle })
2291
- ] }),
2292
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-chart__header-actions", children: [
2293
- features.showMethodology && data.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
2294
- DataCoverageBadge,
2295
- {
2296
- sampleSize: data.length,
2297
- requiredSize: chartMeta?.contract.minDataPoints || 0,
2298
- size: "sm"
2299
- }
2300
- ),
2301
- allowSwitching && resolvedAllowedTypes.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
2302
- ChartSwitchControl,
2303
- {
2304
- currentType: activeType,
2305
- allowedTypes: [activeType, ...resolvedAllowedTypes],
2306
- onTypeChange: handleTypeChange
2307
- }
2308
- )
2309
- ] })
2310
- ] }),
2311
- validation.warnings.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-chart__warnings", children: validation.warnings.map((warning, idx) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-chart__warning", children: warning }, idx)) }),
2312
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-chart__body", style: { height }, children: renderChart() })
2313
- ] });
2314
- }
2315
- Chart.displayName = "Chart";
2316
- var ConfidenceIndicator = React2__default.default.forwardRef(
2317
- ({ score, showScore = true, showLabel = true, size = "md", className, ...props }, ref) => {
2318
- const threshold = getConfidenceThreshold(score);
2319
- const normalizedScore = Math.max(0, Math.min(100, score));
2320
- return /* @__PURE__ */ jsxRuntime.jsxs(
2321
- "div",
2322
- {
2323
- ref,
2324
- className: clsx11__default.default(
2325
- "ds-confidence-indicator",
2326
- `ds-confidence-indicator--${size}`,
2327
- `ds-confidence-indicator--${threshold.level}`,
2328
- className
2329
- ),
2330
- role: "meter",
2331
- "aria-valuenow": normalizedScore,
2332
- "aria-valuemin": 0,
2333
- "aria-valuemax": 100,
2334
- "aria-label": `Confidence: ${threshold.label} (${normalizedScore}%)`,
2335
- ...props,
2336
- children: [
2337
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-confidence-indicator__bar", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-confidence-indicator__fill", style: { width: `${normalizedScore}%` } }) }),
2338
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-confidence-indicator__text", children: [
2339
- showScore && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ds-confidence-indicator__score", children: [
2340
- normalizedScore,
2341
- "%"
2342
- ] }),
2343
- showLabel && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-confidence-indicator__label", children: threshold.label })
2344
- ] })
2345
- ]
2346
- }
2347
- );
2348
- }
2349
- );
2350
- ConfidenceIndicator.displayName = "ConfidenceIndicator";
2351
- var DIMENSION_LABELS = {
2352
- EI: { left: "Extraversion", right: "Introversion", full: "E/I" },
2353
- SN: { left: "Sensing", right: "Intuition", full: "S/N" },
2354
- TF: { left: "Thinking", right: "Feeling", full: "T/F" },
2355
- JP: { left: "Judging", right: "Perceiving", full: "J/P" }
2356
- };
2357
- function MBTIRadar({
2358
- dimensions,
2359
- sampleSize,
2360
- comparison,
2361
- title,
2362
- subtitle,
2363
- size = 300,
2364
- showLabels = true,
2365
- showValues = true,
2366
- minSampleSize = 20,
2367
- confidence,
2368
- className
2369
- }) {
2370
- const { features } = useReportMode();
2371
- const isValid = sampleSize >= minSampleSize;
2372
- const radarData = React2.useMemo(() => {
2373
- return Object.keys(dimensions).map((key) => ({
2374
- dimension: DIMENSION_LABELS[key].full,
2375
- fullName: `${DIMENSION_LABELS[key].left} vs ${DIMENSION_LABELS[key].right}`,
2376
- value: dimensions[key],
2377
- comparison: comparison?.[key],
2378
- leftLabel: DIMENSION_LABELS[key].left,
2379
- rightLabel: DIMENSION_LABELS[key].right
2380
- }));
2381
- }, [dimensions, comparison]);
2382
- const derivedType = React2.useMemo(() => {
2383
- const e = dimensions.EI < 50 ? "E" : "I";
2384
- const s = dimensions.SN < 50 ? "S" : "N";
2385
- const t = dimensions.TF < 50 ? "T" : "F";
2386
- const j = dimensions.JP < 50 ? "J" : "P";
2387
- return `${e}${s}${t}${j}`;
2388
- }, [dimensions]);
2389
- if (!isValid) {
2390
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx11__default.default("ds-mbti-radar", "ds-mbti-radar--invalid", className), children: [
2391
- title && /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "ds-mbti-radar__title", children: title }),
2392
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-mbti-radar__empty", children: /* @__PURE__ */ jsxRuntime.jsx(
2393
- DataStateIndicator,
2394
- {
2395
- state: "INSUFFICIENT_SAMPLE",
2396
- variant: "full",
2397
- details: {
2398
- message: "MBTI analysis requires sufficient sample size",
2399
- sampleSize,
2400
- requiredSize: minSampleSize
2401
- }
2402
- }
2403
- ) })
2404
- ] });
2405
- }
2406
- const CustomTooltip = ({
2407
- active,
2408
- payload
2409
- }) => {
2410
- if (!active || !payload?.length) return null;
2411
- const data = payload[0].payload;
2412
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-mbti-radar__tooltip", children: [
2413
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ds-mbti-radar__tooltip-title", children: data.fullName }),
2414
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "ds-mbti-radar__tooltip-value", children: [
2415
- data.leftLabel,
2416
- ": ",
2417
- 100 - data.value,
2418
- "%"
2419
- ] }),
2420
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "ds-mbti-radar__tooltip-value", children: [
2421
- data.rightLabel,
2422
- ": ",
2423
- data.value,
2424
- "%"
2425
- ] }),
2426
- data.comparison !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "ds-mbti-radar__tooltip-comparison", children: [
2427
- "Benchmark: ",
2428
- data.comparison,
2429
- "%"
2430
- ] })
2431
- ] });
2432
- };
2433
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx11__default.default("ds-mbti-radar", className), children: [
2434
- (title || subtitle) && /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "ds-mbti-radar__header", children: [
2435
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-mbti-radar__header-text", children: [
2436
- title && /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "ds-mbti-radar__title", children: title }),
2437
- subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ds-mbti-radar__subtitle", children: subtitle })
2438
- ] }),
2439
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-mbti-radar__header-badges", children: [
2440
- features.showConfidenceScores && confidence !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(ConfidenceIndicator, { score: confidence, size: "sm" }),
2441
- features.showMethodology && /* @__PURE__ */ jsxRuntime.jsx(DataCoverageBadge, { sampleSize, requiredSize: minSampleSize, size: "sm" })
2442
- ] })
2443
- ] }),
2444
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-mbti-radar__type-badge", children: [
2445
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-mbti-radar__type-label", children: "Derived Type" }),
2446
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-mbti-radar__type-value", children: derivedType })
2447
- ] }),
2448
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-mbti-radar__chart", style: { width: size, height: size }, children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.RadarChart, { cx: "50%", cy: "50%", outerRadius: "70%", width: size, height: size, data: radarData, children: [
2449
- /* @__PURE__ */ jsxRuntime.jsx(recharts.PolarGrid, { stroke: "var(--glass-border)" }),
2450
- /* @__PURE__ */ jsxRuntime.jsx(
2451
- recharts.PolarAngleAxis,
2452
- {
2453
- dataKey: "dimension",
2454
- tick: { fill: "var(--text-secondary)", fontSize: 12 }
2455
- }
2456
- ),
2457
- /* @__PURE__ */ jsxRuntime.jsx(
2458
- recharts.PolarRadiusAxis,
2459
- {
2460
- angle: 45,
2461
- domain: [0, 100],
2462
- tick: { fill: "var(--text-tertiary)", fontSize: 10 },
2463
- tickCount: 5
2464
- }
2465
- ),
2466
- /* @__PURE__ */ jsxRuntime.jsx(
2467
- recharts.Radar,
2468
- {
2469
- name: "Profile",
2470
- dataKey: "value",
2471
- stroke: "var(--brand-pink)",
2472
- fill: "var(--brand-pink)",
2473
- fillOpacity: 0.3,
2474
- strokeWidth: 2
2475
- }
2476
- ),
2477
- comparison && /* @__PURE__ */ jsxRuntime.jsx(
2478
- recharts.Radar,
2479
- {
2480
- name: "Benchmark",
2481
- dataKey: "comparison",
2482
- stroke: "var(--brand-yellow)",
2483
- fill: "var(--brand-yellow)",
2484
- fillOpacity: 0.1,
2485
- strokeWidth: 2,
2486
- strokeDasharray: "5 5"
2487
- }
2488
- ),
2489
- showValues && /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(CustomTooltip, {}) }),
2490
- comparison && /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, {})
2491
- ] }) }),
2492
- showLabels && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-mbti-radar__dimensions", children: radarData.map((d) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-mbti-radar__dimension", children: [
2493
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-mbti-radar__dimension-left", children: d.leftLabel }),
2494
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-mbti-radar__dimension-bar", children: [
2495
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-mbti-radar__dimension-fill", style: { width: `${d.value}%` } }),
2496
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-mbti-radar__dimension-marker", style: { left: `${d.value}%` } })
2497
- ] }),
2498
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-mbti-radar__dimension-right", children: d.rightLabel })
2499
- ] }, d.dimension)) })
2500
- ] });
2501
- }
2502
- MBTIRadar.displayName = "MBTIRadar";
2503
- var MBTI_GRID = [
2504
- ["ISTJ", "ISFJ", "INFJ", "INTJ"],
2505
- ["ISTP", "ISFP", "INFP", "INTP"],
2506
- ["ESTP", "ESFP", "ENFP", "ENTP"],
2507
- ["ESTJ", "ESFJ", "ENFJ", "ENTJ"]
2508
- ];
2509
- var TYPE_DESCRIPTIONS = {
2510
- ISTJ: "The Inspector - Practical, reliable, systematic",
2511
- ISFJ: "The Protector - Caring, supportive, traditional",
2512
- INFJ: "The Advocate - Insightful, principled, compassionate",
2513
- INTJ: "The Architect - Strategic, independent, determined",
2514
- ISTP: "The Virtuoso - Observant, practical, analytical",
2515
- ISFP: "The Adventurer - Artistic, sensitive, exploratory",
2516
- INFP: "The Mediator - Idealistic, empathetic, creative",
2517
- INTP: "The Logician - Inventive, logical, objective",
2518
- ESTP: "The Entrepreneur - Energetic, pragmatic, observant",
2519
- ESFP: "The Entertainer - Spontaneous, energetic, friendly",
2520
- ENFP: "The Campaigner - Enthusiastic, creative, sociable",
2521
- ENTP: "The Debater - Clever, curious, innovative",
2522
- ESTJ: "The Executive - Organized, logical, assertive",
2523
- ESFJ: "The Consul - Caring, sociable, traditional",
2524
- ENFJ: "The Protagonist - Charismatic, empathetic, organized",
2525
- ENTJ: "The Commander - Strategic, efficient, energetic"
2526
- };
2527
- var COLUMN_LABELS = ["ST", "SF", "NF", "NT"];
2528
- var ROW_LABELS = ["I-J", "I-P", "E-P", "E-J"];
2529
- function MBTITypeGrid({
2530
- data,
2531
- sampleSize: propSampleSize,
2532
- title,
2533
- subtitle,
2534
- showPercentages = true,
2535
- showCounts = true,
2536
- highlightThreshold,
2537
- minSampleSize = 50,
2538
- confidence,
2539
- onTypeClick,
2540
- selectedType,
2541
- className
2542
- }) {
2543
- const { features } = useReportMode();
2544
- const typeMap = React2.useMemo(() => {
2545
- const map = /* @__PURE__ */ new Map();
2546
- for (const item of data) {
2547
- map.set(item.type, item);
2548
- }
2549
- return map;
2550
- }, [data]);
2551
- const totalSampleSize = propSampleSize ?? data.reduce((sum, d) => sum + d.count, 0);
2552
- const isValid = totalSampleSize >= minSampleSize;
2553
- const maxCount = React2.useMemo(() => Math.max(...data.map((d) => d.count), 1), [data]);
2554
- const getPercentage = (count) => {
2555
- return totalSampleSize > 0 ? (count / totalSampleSize * 100).toFixed(1) : "0.0";
2556
- };
2557
- const getIntensity = (count) => {
2558
- if (maxCount === 0) return 0;
2559
- return count / maxCount * 100;
2560
- };
2561
- const isHighlighted = (type) => {
2562
- if (!highlightThreshold) return false;
2563
- const item = typeMap.get(type);
2564
- if (!item) return false;
2565
- const percentage = item.count / totalSampleSize * 100;
2566
- return percentage >= highlightThreshold;
2567
- };
2568
- if (!isValid) {
2569
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx11__default.default("ds-mbti-type-grid", "ds-mbti-type-grid--invalid", className), children: [
2570
- title && /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "ds-mbti-type-grid__title", children: title }),
2571
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-mbti-type-grid__empty", children: /* @__PURE__ */ jsxRuntime.jsx(
2572
- DataStateIndicator,
2573
- {
2574
- state: "INSUFFICIENT_SAMPLE",
2575
- variant: "full",
2576
- details: {
2577
- message: "MBTI distribution analysis requires sufficient sample size",
2578
- sampleSize: totalSampleSize,
2579
- requiredSize: minSampleSize
2580
- }
2581
- }
2582
- ) })
2583
- ] });
2584
- }
2585
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx11__default.default("ds-mbti-type-grid", className), children: [
2586
- (title || subtitle) && /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "ds-mbti-type-grid__header", children: [
2587
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-mbti-type-grid__header-text", children: [
2588
- title && /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "ds-mbti-type-grid__title", children: title }),
2589
- subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ds-mbti-type-grid__subtitle", children: subtitle })
2590
- ] }),
2591
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-mbti-type-grid__header-badges", children: [
2592
- features.showConfidenceScores && confidence !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(ConfidenceIndicator, { score: confidence, size: "sm" }),
2593
- features.showMethodology && /* @__PURE__ */ jsxRuntime.jsx(
2594
- DataCoverageBadge,
2595
- {
2596
- sampleSize: totalSampleSize,
2597
- requiredSize: minSampleSize,
2598
- size: "sm"
2599
- }
2600
- )
2601
- ] })
2602
- ] }),
2603
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-mbti-type-grid__container", children: [
2604
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-mbti-type-grid__column-headers", children: [
2605
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-mbti-type-grid__corner" }),
2606
- COLUMN_LABELS.map((label) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-mbti-type-grid__column-header", children: label }, label))
2607
- ] }),
2608
- MBTI_GRID.map((row, rowIndex) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-mbti-type-grid__row", children: [
2609
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-mbti-type-grid__row-header", children: ROW_LABELS[rowIndex] }),
2610
- row.map((type) => {
2611
- const typeData = typeMap.get(type);
2612
- const count = typeData?.count ?? 0;
2613
- const percentage = getPercentage(count);
2614
- const intensity = getIntensity(count);
2615
- const highlighted = isHighlighted(type);
2616
- const selected = selectedType === type;
2617
- return /* @__PURE__ */ jsxRuntime.jsx(
2618
- Tooltip4,
2619
- {
2620
- content: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-mbti-type-grid__tooltip-content", children: [
2621
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: type }),
2622
- /* @__PURE__ */ jsxRuntime.jsx("p", { children: TYPE_DESCRIPTIONS[type] }),
2623
- /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
2624
- "Count: ",
2625
- count.toLocaleString()
2626
- ] }),
2627
- /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
2628
- "Percentage: ",
2629
- percentage,
2630
- "%"
2631
- ] }),
2632
- typeData?.responseRate !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
2633
- "Response Rate: ",
2634
- typeData.responseRate.toFixed(1),
2635
- "%"
2636
- ] })
2637
- ] }),
2638
- children: /* @__PURE__ */ jsxRuntime.jsxs(
2639
- "button",
2640
- {
2641
- type: "button",
2642
- className: clsx11__default.default(
2643
- "ds-mbti-type-grid__cell",
2644
- highlighted && "ds-mbti-type-grid__cell--highlighted",
2645
- selected && "ds-mbti-type-grid__cell--selected",
2646
- onTypeClick && "ds-mbti-type-grid__cell--clickable"
2647
- ),
2648
- onClick: () => onTypeClick?.(type),
2649
- disabled: !onTypeClick,
2650
- style: {
2651
- "--cell-intensity": `${intensity}%`
2652
- },
2653
- children: [
2654
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-mbti-type-grid__cell-type", children: type }),
2655
- showCounts && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-mbti-type-grid__cell-count", children: count.toLocaleString() }),
2656
- showPercentages && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ds-mbti-type-grid__cell-percentage", children: [
2657
- percentage,
2658
- "%"
2659
- ] })
2660
- ]
2661
- }
2662
- )
2663
- },
2664
- type
2665
- );
2666
- })
2667
- ] }, rowIndex))
2668
- ] }),
2669
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-mbti-type-grid__legend", children: [
2670
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-mbti-type-grid__legend-item", children: [
2671
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-mbti-type-grid__legend-bar ds-mbti-type-grid__legend-bar--gradient" }),
2672
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-mbti-type-grid__legend-label", children: "Distribution density" })
2673
- ] }),
2674
- highlightThreshold && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-mbti-type-grid__legend-item", children: [
2675
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-mbti-type-grid__legend-bar ds-mbti-type-grid__legend-bar--highlight" }),
2676
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ds-mbti-type-grid__legend-label", children: [
2677
- ">=",
2678
- highlightThreshold,
2679
- "% of sample"
2680
- ] })
2681
- ] })
2682
- ] })
2683
- ] });
2684
- }
2685
- MBTITypeGrid.displayName = "MBTITypeGrid";
2686
-
2687
- exports.BarChart = BarChart;
2688
- exports.Chart = Chart;
2689
- exports.ChartContainer = ChartContainer;
2690
- exports.ChartSwitchControl = ChartSwitchControl;
2691
- exports.FunnelChart = FunnelChart;
2692
- exports.HeatmapChart = HeatmapChart;
2693
- exports.LineChart = LineChart;
2694
- exports.MBTIRadar = MBTIRadar;
2695
- exports.MBTITypeGrid = MBTITypeGrid;
2696
- exports.PieChart = PieChart;
3
+ var chunkTEC62D4A_cjs = require('../chunk-TEC62D4A.cjs');
4
+ require('../chunk-Q2MFGYTE.cjs');
5
+ require('../chunk-WH7PYHZY.cjs');
6
+
7
+
8
+
9
+ Object.defineProperty(exports, "BarChart", {
10
+ enumerable: true,
11
+ get: function () { return chunkTEC62D4A_cjs.BarChart; }
12
+ });
13
+ Object.defineProperty(exports, "Chart", {
14
+ enumerable: true,
15
+ get: function () { return chunkTEC62D4A_cjs.Chart; }
16
+ });
17
+ Object.defineProperty(exports, "ChartContainer", {
18
+ enumerable: true,
19
+ get: function () { return chunkTEC62D4A_cjs.ChartContainer; }
20
+ });
21
+ Object.defineProperty(exports, "ChartSwitchControl", {
22
+ enumerable: true,
23
+ get: function () { return chunkTEC62D4A_cjs.ChartSwitchControl; }
24
+ });
25
+ Object.defineProperty(exports, "FunnelChart", {
26
+ enumerable: true,
27
+ get: function () { return chunkTEC62D4A_cjs.FunnelChart; }
28
+ });
29
+ Object.defineProperty(exports, "HeatmapChart", {
30
+ enumerable: true,
31
+ get: function () { return chunkTEC62D4A_cjs.HeatmapChart; }
32
+ });
33
+ Object.defineProperty(exports, "LineChart", {
34
+ enumerable: true,
35
+ get: function () { return chunkTEC62D4A_cjs.LineChart; }
36
+ });
37
+ Object.defineProperty(exports, "MBTIRadar", {
38
+ enumerable: true,
39
+ get: function () { return chunkTEC62D4A_cjs.MBTIRadar; }
40
+ });
41
+ Object.defineProperty(exports, "MBTITypeGrid", {
42
+ enumerable: true,
43
+ get: function () { return chunkTEC62D4A_cjs.MBTITypeGrid; }
44
+ });
45
+ Object.defineProperty(exports, "PieChart", {
46
+ enumerable: true,
47
+ get: function () { return chunkTEC62D4A_cjs.PieChart; }
48
+ });
2697
49
  //# sourceMappingURL=out.js.map
2698
50
  //# sourceMappingURL=index.cjs.map