@salesmind-ai/design-system 0.3.3 → 0.3.4

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 (215) hide show
  1. package/dist/{SectionShell-BfBw5q0Y.d.cts → SectionShell-GlglHCzz.d.cts} +1 -0
  2. package/dist/{SectionShell-BfBw5q0Y.d.ts → SectionShell-GlglHCzz.d.ts} +1 -0
  3. package/dist/StatsSection-B8iD9L-o.d.ts +68 -0
  4. package/dist/StatsSection-wgd8Vge1.d.cts +68 -0
  5. package/dist/admin/index.cjs +2928 -68
  6. package/dist/admin/index.cjs.map +1 -1
  7. package/dist/admin/index.js +2915 -5
  8. package/dist/admin/index.js.map +1 -1
  9. package/dist/blog/index.cjs +1064 -53
  10. package/dist/blog/index.cjs.map +1 -1
  11. package/dist/blog/index.d.cts +1 -1
  12. package/dist/blog/index.d.ts +1 -1
  13. package/dist/blog/index.js +1054 -8
  14. package/dist/blog/index.js.map +1 -1
  15. package/dist/charts/index.cjs +2694 -46
  16. package/dist/charts/index.cjs.map +1 -1
  17. package/dist/charts/index.js +2680 -3
  18. package/dist/charts/index.js.map +1 -1
  19. package/dist/core/index.cjs +4333 -807
  20. package/dist/core/index.cjs.map +1 -1
  21. package/dist/core/index.js +4130 -14
  22. package/dist/core/index.js.map +1 -1
  23. package/dist/i18n/index.cjs +558 -86
  24. package/dist/i18n/index.cjs.map +1 -1
  25. package/dist/i18n/index.js +544 -1
  26. package/dist/i18n/index.js.map +1 -1
  27. package/dist/index.cjs +17140 -1432
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.css +24 -13
  30. package/dist/index.css.map +1 -1
  31. package/dist/index.d.cts +2 -2
  32. package/dist/index.d.ts +2 -2
  33. package/dist/index.js +16785 -31
  34. package/dist/index.js.map +1 -1
  35. package/dist/marketing/index.cjs +3072 -142
  36. package/dist/marketing/index.cjs.map +1 -1
  37. package/dist/marketing/index.d.cts +1 -1
  38. package/dist/marketing/index.d.ts +1 -1
  39. package/dist/marketing/index.js +3042 -11
  40. package/dist/marketing/index.js.map +1 -1
  41. package/dist/motion/index.cjs +1222 -26
  42. package/dist/motion/index.cjs.map +1 -1
  43. package/dist/motion/index.js +1215 -2
  44. package/dist/motion/index.js.map +1 -1
  45. package/dist/nav/index.cjs +1518 -101
  46. package/dist/nav/index.cjs.map +1 -1
  47. package/dist/nav/index.css +24 -13
  48. package/dist/nav/index.css.map +1 -1
  49. package/dist/nav/index.js +1498 -4
  50. package/dist/nav/index.js.map +1 -1
  51. package/dist/report/index.cjs +2403 -171
  52. package/dist/report/index.cjs.map +1 -1
  53. package/dist/report/index.js +2363 -3
  54. package/dist/report/index.js.map +1 -1
  55. package/dist/sections/index.cjs +382 -28
  56. package/dist/sections/index.cjs.map +1 -1
  57. package/dist/sections/index.d.cts +15 -69
  58. package/dist/sections/index.d.ts +15 -69
  59. package/dist/sections/index.js +376 -4
  60. package/dist/sections/index.js.map +1 -1
  61. package/dist/social-proof/index.cjs +1250 -53
  62. package/dist/social-proof/index.cjs.map +1 -1
  63. package/dist/social-proof/index.d.cts +1 -1
  64. package/dist/social-proof/index.d.ts +1 -1
  65. package/dist/social-proof/index.js +1235 -6
  66. package/dist/social-proof/index.js.map +1 -1
  67. package/dist/theme/index.cjs +565 -38
  68. package/dist/theme/index.cjs.map +1 -1
  69. package/dist/theme/index.js +555 -2
  70. package/dist/theme/index.js.map +1 -1
  71. package/dist/web/client/index.cjs +491 -38
  72. package/dist/web/client/index.cjs.map +1 -1
  73. package/dist/web/client/index.js +483 -4
  74. package/dist/web/client/index.js.map +1 -1
  75. package/dist/web/index.cjs +1346 -158
  76. package/dist/web/index.cjs.map +1 -1
  77. package/dist/web/index.js +1305 -9
  78. package/dist/web/index.js.map +1 -1
  79. package/dist/web/server/index.cjs +563 -26
  80. package/dist/web/server/index.cjs.map +1 -1
  81. package/dist/web/server/index.js +560 -1
  82. package/dist/web/server/index.js.map +1 -1
  83. package/package.json +1 -1
  84. package/dist/chunk-2GARWEJK.js +0 -17
  85. package/dist/chunk-2GARWEJK.js.map +0 -1
  86. package/dist/chunk-3NKRFUAR.js +0 -37
  87. package/dist/chunk-3NKRFUAR.js.map +0 -1
  88. package/dist/chunk-3TGSIILM.cjs +0 -201
  89. package/dist/chunk-3TGSIILM.cjs.map +0 -1
  90. package/dist/chunk-4GM5BGBN.cjs +0 -801
  91. package/dist/chunk-4GM5BGBN.cjs.map +0 -1
  92. package/dist/chunk-5LGDEZWY.cjs +0 -2434
  93. package/dist/chunk-5LGDEZWY.cjs.map +0 -1
  94. package/dist/chunk-6H4DSTXR.js +0 -786
  95. package/dist/chunk-6H4DSTXR.js.map +0 -1
  96. package/dist/chunk-6UNG76Y2.js +0 -153
  97. package/dist/chunk-6UNG76Y2.js.map +0 -1
  98. package/dist/chunk-7PX2AZ6Y.js +0 -39
  99. package/dist/chunk-7PX2AZ6Y.js.map +0 -1
  100. package/dist/chunk-B6AVAX4F.js +0 -1415
  101. package/dist/chunk-B6AVAX4F.js.map +0 -1
  102. package/dist/chunk-BILT5KD3.js +0 -264
  103. package/dist/chunk-BILT5KD3.js.map +0 -1
  104. package/dist/chunk-C2BCDNAV.js +0 -24
  105. package/dist/chunk-C2BCDNAV.js.map +0 -1
  106. package/dist/chunk-CH42VPWE.cjs +0 -421
  107. package/dist/chunk-CH42VPWE.cjs.map +0 -1
  108. package/dist/chunk-CJ2MKVAF.cjs +0 -46
  109. package/dist/chunk-CJ2MKVAF.cjs.map +0 -1
  110. package/dist/chunk-DP74LUXG.cjs +0 -98
  111. package/dist/chunk-DP74LUXG.cjs.map +0 -1
  112. package/dist/chunk-E7D6EKJ4.cjs +0 -44
  113. package/dist/chunk-E7D6EKJ4.cjs.map +0 -1
  114. package/dist/chunk-ECXBTUH6.cjs +0 -584
  115. package/dist/chunk-ECXBTUH6.cjs.map +0 -1
  116. package/dist/chunk-EFRAP5ES.js +0 -157
  117. package/dist/chunk-EFRAP5ES.js.map +0 -1
  118. package/dist/chunk-F6YYWMME.js +0 -485
  119. package/dist/chunk-F6YYWMME.js.map +0 -1
  120. package/dist/chunk-FAFAP4L5.js +0 -183
  121. package/dist/chunk-FAFAP4L5.js.map +0 -1
  122. package/dist/chunk-GUZIMHWS.js +0 -1608
  123. package/dist/chunk-GUZIMHWS.js.map +0 -1
  124. package/dist/chunk-H2Y6BSTL.cjs +0 -69
  125. package/dist/chunk-H2Y6BSTL.cjs.map +0 -1
  126. package/dist/chunk-HN4PHABT.js +0 -126
  127. package/dist/chunk-HN4PHABT.js.map +0 -1
  128. package/dist/chunk-HRENHNDJ.js +0 -211
  129. package/dist/chunk-HRENHNDJ.js.map +0 -1
  130. package/dist/chunk-I75BFEYT.cjs +0 -2561
  131. package/dist/chunk-I75BFEYT.cjs.map +0 -1
  132. package/dist/chunk-IFRATNLU.js +0 -562
  133. package/dist/chunk-IFRATNLU.js.map +0 -1
  134. package/dist/chunk-IYPXJ6YC.cjs +0 -69
  135. package/dist/chunk-IYPXJ6YC.cjs.map +0 -1
  136. package/dist/chunk-JPJN4YBC.js +0 -409
  137. package/dist/chunk-JPJN4YBC.js.map +0 -1
  138. package/dist/chunk-KBA2LFBG.js +0 -62
  139. package/dist/chunk-KBA2LFBG.js.map +0 -1
  140. package/dist/chunk-KCKUSU2M.cjs +0 -166
  141. package/dist/chunk-KCKUSU2M.cjs.map +0 -1
  142. package/dist/chunk-KJ2OXQF4.js +0 -287
  143. package/dist/chunk-KJ2OXQF4.js.map +0 -1
  144. package/dist/chunk-KNQEIU7O.cjs +0 -1202
  145. package/dist/chunk-KNQEIU7O.cjs.map +0 -1
  146. package/dist/chunk-KVGSVGRK.cjs +0 -569
  147. package/dist/chunk-KVGSVGRK.cjs.map +0 -1
  148. package/dist/chunk-L352JRV6.cjs +0 -105
  149. package/dist/chunk-L352JRV6.cjs.map +0 -1
  150. package/dist/chunk-LJADZITX.cjs +0 -298
  151. package/dist/chunk-LJADZITX.cjs.map +0 -1
  152. package/dist/chunk-LMJPWXTZ.cjs +0 -194
  153. package/dist/chunk-LMJPWXTZ.cjs.map +0 -1
  154. package/dist/chunk-LOWEAQST.js +0 -701
  155. package/dist/chunk-LOWEAQST.js.map +0 -1
  156. package/dist/chunk-MDB2WCRQ.cjs +0 -137
  157. package/dist/chunk-MDB2WCRQ.cjs.map +0 -1
  158. package/dist/chunk-MQDEE7HC.cjs +0 -283
  159. package/dist/chunk-MQDEE7HC.cjs.map +0 -1
  160. package/dist/chunk-MQRB634A.cjs +0 -34
  161. package/dist/chunk-MQRB634A.cjs.map +0 -1
  162. package/dist/chunk-MTI27RDV.js +0 -185
  163. package/dist/chunk-MTI27RDV.js.map +0 -1
  164. package/dist/chunk-MU6GW5ZV.js +0 -2317
  165. package/dist/chunk-MU6GW5ZV.js.map +0 -1
  166. package/dist/chunk-NN3TUHIH.js +0 -28
  167. package/dist/chunk-NN3TUHIH.js.map +0 -1
  168. package/dist/chunk-NT4LBP7D.cjs +0 -111
  169. package/dist/chunk-NT4LBP7D.cjs.map +0 -1
  170. package/dist/chunk-OLV7OD3X.cjs +0 -502
  171. package/dist/chunk-OLV7OD3X.cjs.map +0 -1
  172. package/dist/chunk-OXNXEQY7.js +0 -2538
  173. package/dist/chunk-OXNXEQY7.js.map +0 -1
  174. package/dist/chunk-P5BOFE5A.js +0 -546
  175. package/dist/chunk-P5BOFE5A.js.map +0 -1
  176. package/dist/chunk-Q2MFGYTE.cjs +0 -1449
  177. package/dist/chunk-Q2MFGYTE.cjs.map +0 -1
  178. package/dist/chunk-Q75DBVDY.cjs +0 -68
  179. package/dist/chunk-Q75DBVDY.cjs.map +0 -1
  180. package/dist/chunk-REQ5Q6ZI.js +0 -1022
  181. package/dist/chunk-REQ5Q6ZI.js.map +0 -1
  182. package/dist/chunk-SICKWUWB.js +0 -62
  183. package/dist/chunk-SICKWUWB.js.map +0 -1
  184. package/dist/chunk-T343CCH5.js +0 -1190
  185. package/dist/chunk-T343CCH5.js.map +0 -1
  186. package/dist/chunk-TEC62D4A.cjs +0 -1624
  187. package/dist/chunk-TEC62D4A.cjs.map +0 -1
  188. package/dist/chunk-TW5JB35D.js +0 -2122
  189. package/dist/chunk-TW5JB35D.js.map +0 -1
  190. package/dist/chunk-VC5LMUVQ.cjs +0 -20
  191. package/dist/chunk-VC5LMUVQ.cjs.map +0 -1
  192. package/dist/chunk-VM7WFMKI.cjs +0 -76
  193. package/dist/chunk-VM7WFMKI.cjs.map +0 -1
  194. package/dist/chunk-W2WTP6HS.cjs +0 -233
  195. package/dist/chunk-W2WTP6HS.cjs.map +0 -1
  196. package/dist/chunk-WH7PYHZY.cjs +0 -35
  197. package/dist/chunk-WH7PYHZY.cjs.map +0 -1
  198. package/dist/chunk-XQZVY7JJ.cjs +0 -717
  199. package/dist/chunk-XQZVY7JJ.cjs.map +0 -1
  200. package/dist/chunk-XU3OMQ7V.js +0 -98
  201. package/dist/chunk-XU3OMQ7V.js.map +0 -1
  202. package/dist/chunk-XWPDRMZG.js +0 -62
  203. package/dist/chunk-XWPDRMZG.js.map +0 -1
  204. package/dist/chunk-Y3CPKNB7.js +0 -67
  205. package/dist/chunk-Y3CPKNB7.js.map +0 -1
  206. package/dist/chunk-YNVRDD2P.js +0 -98
  207. package/dist/chunk-YNVRDD2P.js.map +0 -1
  208. package/dist/chunk-YSYR54XR.js +0 -92
  209. package/dist/chunk-YSYR54XR.js.map +0 -1
  210. package/dist/chunk-YTYDQBVY.cjs +0 -162
  211. package/dist/chunk-YTYDQBVY.cjs.map +0 -1
  212. package/dist/chunk-ZDLOA2UT.cjs +0 -1042
  213. package/dist/chunk-ZDLOA2UT.cjs.map +0 -1
  214. package/dist/chunk-ZWUKRCOJ.cjs +0 -2162
  215. package/dist/chunk-ZWUKRCOJ.cjs.map +0 -1
@@ -1,5 +1,2365 @@
1
- export { CaveatBlock, EvidenceGroup, ExecutiveThesis, ExportMenu, InsightBlock, KeyMetric, MethodologyNote, ReportShell, TrendIndicator } from '../chunk-6H4DSTXR.js';
2
- export { ANALYST_MODE, ANALYTICAL_STATE_CONFIG, CHART_REGISTRY, CONFIDENCE_THRESHOLDS, ConfidenceIndicator, DataCoverageBadge, DataStateIndicator, EXECUTIVE_MODE, INSIGHT_TYPE_CONTRACTS, INTENT_CHART_FAMILIES, MINIMUM_SAMPLE_SIZES, ReportModeProvider, calculateCompleteness, calculateConfidence, calculateNormalizedVariance, calculateRecency, canSwitchChart, getAllowedSwitchTargets, getConfidenceLevel, getConfidenceThreshold, getDefaultChartForIntent, getMVPChartsForIntent, suggestChartType, useChartData, useDataState, useReportMode, validateChartData, validateReportStructure } from '../chunk-B6AVAX4F.js';
3
- export { Select, SelectContent, SelectGroup, SelectItem, SelectSeparator, SelectTrigger } from '../chunk-FAFAP4L5.js';
1
+ import React2, { createContext, useMemo, useContext } from 'react';
2
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
+ import clsx12 from 'clsx';
4
+ import { Select as Select$1 } from '@base-ui/react/select';
5
+ import { Menu } from '@base-ui/react/menu';
6
+
7
+ // src/report-engine/constants.ts
8
+ var EXECUTIVE_MODE = {
9
+ mode: "executive",
10
+ features: {
11
+ showMethodology: false,
12
+ showConfidenceScores: false,
13
+ showRawData: false,
14
+ showStatisticalTests: false,
15
+ chartDetailLevel: "summary",
16
+ maxInsightsShown: 5,
17
+ allowDrilldown: false
18
+ }
19
+ };
20
+ var ANALYST_MODE = {
21
+ mode: "analyst",
22
+ features: {
23
+ showMethodology: true,
24
+ showConfidenceScores: true,
25
+ showRawData: true,
26
+ showStatisticalTests: true,
27
+ chartDetailLevel: "detailed",
28
+ maxInsightsShown: 20,
29
+ allowDrilldown: true
30
+ }
31
+ };
32
+ var CONFIDENCE_THRESHOLDS = [
33
+ { level: "high", min: 90, max: 100, label: "High Confidence", color: "var(--status-success)" },
34
+ {
35
+ level: "moderate",
36
+ min: 70,
37
+ max: 89,
38
+ label: "Moderate Confidence",
39
+ color: "var(--status-info)"
40
+ },
41
+ { level: "low", min: 50, max: 69, label: "Low Confidence", color: "var(--status-warning)" },
42
+ {
43
+ level: "insufficient",
44
+ min: 0,
45
+ max: 49,
46
+ label: "Insufficient Data",
47
+ color: "var(--status-error)"
48
+ }
49
+ ];
50
+ var MINIMUM_SAMPLE_SIZES = {
51
+ overall: 30,
52
+ segment: 30,
53
+ mbtiType: 50,
54
+ correlation: 100,
55
+ timeSeries: 7
56
+ };
57
+ var INSIGHT_TYPE_CONTRACTS = {
58
+ "performance-delta": {
59
+ type: "performance-delta",
60
+ allowedCharts: ["BarChart", "LineChart", "KeyMetric"],
61
+ requiredFields: ["metric_name", "current_value", "previous_value", "time_period"],
62
+ minSampleSize: 30,
63
+ headlinePattern: "{metric} {direction} by {delta}% {timeframe}",
64
+ recommendationFormats: ["maintain-strategy", "investigate-decline", "scale-success"]
65
+ },
66
+ "behavioral-correlation": {
67
+ type: "behavioral-correlation",
68
+ allowedCharts: ["HeatmapChart", "BarChart"],
69
+ requiredFields: ["variable_a", "variable_b", "correlation_coefficient"],
70
+ minSampleSize: 100,
71
+ headlinePattern: "{variable_a} correlates with {variable_b}",
72
+ recommendationFormats: ["leverage-correlation", "investigate-causation"]
73
+ },
74
+ "funnel-leakage": {
75
+ type: "funnel-leakage",
76
+ allowedCharts: ["FunnelChart", "BarChart"],
77
+ requiredFields: ["stages", "stage_counts", "drop_rates"],
78
+ minSampleSize: 50,
79
+ headlinePattern: "{drop_rate}% drop-off at {stage}",
80
+ recommendationFormats: ["optimize-stage", "remove-friction"]
81
+ },
82
+ "audience-mismatch": {
83
+ type: "audience-mismatch",
84
+ allowedCharts: ["BarChart", "PieChart"],
85
+ requiredFields: ["target_audience", "actual_audience", "overlap_percentage"],
86
+ minSampleSize: 50,
87
+ headlinePattern: "Target audience differs by {mismatch}%",
88
+ recommendationFormats: ["refine-targeting", "expand-audience"]
89
+ },
90
+ "message-fatigue": {
91
+ type: "message-fatigue",
92
+ allowedCharts: ["LineChart", "BarChart"],
93
+ requiredFields: ["message_sequence", "engagement_rates", "fatigue_point"],
94
+ minSampleSize: 100,
95
+ headlinePattern: "Engagement drops {drop}% after message {n}",
96
+ recommendationFormats: ["reduce-frequency", "vary-content"]
97
+ },
98
+ "psychological-resonance": {
99
+ type: "psychological-resonance",
100
+ allowedCharts: ["MBTIRadar", "MBTITypeGrid", "BarChart"],
101
+ requiredFields: ["mbti_types", "response_rates", "message_type"],
102
+ minSampleSize: 50,
103
+ headlinePattern: "{mbti_type} responds {rate}% better to {message_type}",
104
+ recommendationFormats: ["personalize-messaging", "segment-by-type"]
105
+ },
106
+ "timing-pattern": {
107
+ type: "timing-pattern",
108
+ allowedCharts: ["HeatmapChart", "LineChart"],
109
+ requiredFields: ["time_slots", "engagement_rates"],
110
+ minSampleSize: 100,
111
+ headlinePattern: "Best engagement on {day} at {time}",
112
+ recommendationFormats: ["optimize-timing", "schedule-sends"]
113
+ },
114
+ "segment-outperformance": {
115
+ type: "segment-outperformance",
116
+ allowedCharts: ["BarChart", "KeyMetric"],
117
+ requiredFields: ["segments", "performance_metrics", "baseline"],
118
+ minSampleSize: 30,
119
+ headlinePattern: "{segment} outperforms by {delta}%",
120
+ recommendationFormats: ["double-down", "investigate-success"]
121
+ },
122
+ "anomaly-detection": {
123
+ type: "anomaly-detection",
124
+ allowedCharts: ["LineChart", "BarChart"],
125
+ requiredFields: ["metric", "expected_value", "actual_value", "deviation"],
126
+ minSampleSize: 30,
127
+ headlinePattern: "Unusual {direction} in {metric}",
128
+ recommendationFormats: ["investigate", "monitor"]
129
+ },
130
+ "competitive-benchmark": {
131
+ type: "competitive-benchmark",
132
+ allowedCharts: ["BarChart", "KeyMetric"],
133
+ requiredFields: ["metric", "our_value", "benchmark_value"],
134
+ minSampleSize: 30,
135
+ headlinePattern: "{position} industry benchmark by {delta}%",
136
+ recommendationFormats: ["maintain-lead", "close-gap"]
137
+ }
138
+ };
139
+ var ANALYTICAL_STATE_CONFIG = {
140
+ VALID: {
141
+ label: "Valid",
142
+ icon: "check",
143
+ color: "var(--status-success)",
144
+ action: null
145
+ },
146
+ INSUFFICIENT_SAMPLE: {
147
+ label: "Insufficient Sample",
148
+ icon: "alert-triangle",
149
+ color: "var(--status-warning)",
150
+ action: "Add more data"
151
+ },
152
+ LOW_CONFIDENCE: {
153
+ label: "Low Confidence",
154
+ icon: "alert-circle",
155
+ color: "var(--status-warning)",
156
+ action: "Interpret with caution"
157
+ },
158
+ PARTIAL_TIME_WINDOW: {
159
+ label: "Partial Data",
160
+ icon: "clock",
161
+ color: "var(--status-info)",
162
+ action: "Expand date range"
163
+ },
164
+ DATA_SKEW_DETECTED: {
165
+ label: "Data Skew",
166
+ icon: "bar-chart-2",
167
+ color: "var(--status-warning)",
168
+ action: "Review methodology"
169
+ },
170
+ CONFLICTING_SIGNALS: {
171
+ label: "Conflicting Signals",
172
+ icon: "git-merge",
173
+ color: "var(--status-error)",
174
+ action: "Manual review needed"
175
+ },
176
+ INFERRED_NOT_OBSERVED: {
177
+ label: "AI Generated",
178
+ icon: "cpu",
179
+ color: "var(--status-info)",
180
+ action: "Verify with data"
181
+ },
182
+ STALE_DATA: {
183
+ label: "Stale Data",
184
+ icon: "clock",
185
+ color: "var(--status-warning)",
186
+ action: "Refresh data"
187
+ },
188
+ FIELD_MISSING: {
189
+ label: "Missing Field",
190
+ icon: "file-x",
191
+ color: "var(--status-error)",
192
+ action: "Upload complete data"
193
+ },
194
+ CALCULATION_ERROR: {
195
+ label: "Calculation Error",
196
+ icon: "x-circle",
197
+ color: "var(--status-error)",
198
+ action: "Contact support"
199
+ }
200
+ };
201
+
202
+ // src/report-engine/confidence.ts
203
+ function calculateConfidence(params) {
204
+ const { sampleSize, requiredSize, completeness, recency, variance, aiInference } = params;
205
+ const sampleScore = Math.min(40, sampleSize / requiredSize * 40);
206
+ const completenessScore = completeness * 20;
207
+ const recencyScore = recency * 20;
208
+ const variancePenalty = variance * 10;
209
+ const aiPenalty = aiInference ? 10 : 0;
210
+ const rawScore = sampleScore + completenessScore + recencyScore - variancePenalty - aiPenalty;
211
+ return Math.max(0, Math.min(100, Math.round(rawScore)));
212
+ }
213
+ function getConfidenceLevel(score) {
214
+ const threshold = CONFIDENCE_THRESHOLDS.find((t) => score >= t.min && score <= t.max);
215
+ return threshold?.level ?? "insufficient";
216
+ }
217
+ function getConfidenceThreshold(score) {
218
+ return CONFIDENCE_THRESHOLDS.find((t) => score >= t.min && score <= t.max) ?? CONFIDENCE_THRESHOLDS[CONFIDENCE_THRESHOLDS.length - 1];
219
+ }
220
+ function calculateRecency(dataDate, maxAgeDays = 30) {
221
+ const now = /* @__PURE__ */ new Date();
222
+ const ageInDays = (now.getTime() - dataDate.getTime()) / (1e3 * 60 * 60 * 24);
223
+ if (ageInDays <= 0) return 1;
224
+ if (ageInDays >= maxAgeDays) return 0;
225
+ return 1 - ageInDays / maxAgeDays;
226
+ }
227
+ function calculateCompleteness(data, requiredFields) {
228
+ if (data.length === 0 || requiredFields.length === 0) return 0;
229
+ let totalFields = 0;
230
+ let filledFields = 0;
231
+ for (const record of data) {
232
+ for (const field of requiredFields) {
233
+ totalFields++;
234
+ const value = record[field];
235
+ if (value !== null && value !== void 0 && value !== "") {
236
+ filledFields++;
237
+ }
238
+ }
239
+ }
240
+ return totalFields > 0 ? filledFields / totalFields : 0;
241
+ }
242
+ function calculateNormalizedVariance(values) {
243
+ if (values.length < 2) return 0;
244
+ const mean = values.reduce((a, b) => a + b, 0) / values.length;
245
+ const squaredDiffs = values.map((v) => Math.pow(v - mean, 2));
246
+ const variance = squaredDiffs.reduce((a, b) => a + b, 0) / values.length;
247
+ const stdDev = Math.sqrt(variance);
248
+ const cv = mean !== 0 ? stdDev / Math.abs(mean) : 0;
249
+ return Math.min(1, cv);
250
+ }
251
+ var ReportModeContext = createContext(null);
252
+ function ReportModeProvider({
253
+ mode = "executive",
254
+ children,
255
+ onModeChange
256
+ }) {
257
+ const config = mode === "executive" ? EXECUTIVE_MODE : ANALYST_MODE;
258
+ const value = useMemo(
259
+ () => ({
260
+ ...config,
261
+ setMode: onModeChange
262
+ }),
263
+ [config, onModeChange]
264
+ );
265
+ return /* @__PURE__ */ jsx(ReportModeContext.Provider, { value, children });
266
+ }
267
+ function useReportMode() {
268
+ const context = useContext(ReportModeContext);
269
+ if (!context) {
270
+ return EXECUTIVE_MODE;
271
+ }
272
+ return context;
273
+ }
274
+ function useDataState(params) {
275
+ const {
276
+ sampleSize,
277
+ requiredSize = MINIMUM_SAMPLE_SIZES.overall,
278
+ completeness = 1,
279
+ recency = 1,
280
+ variance = 0,
281
+ aiInferred = false,
282
+ missingFields = [],
283
+ staleDays
284
+ } = params;
285
+ return useMemo(() => {
286
+ const confidenceParams = {
287
+ sampleSize,
288
+ requiredSize,
289
+ completeness,
290
+ recency,
291
+ variance,
292
+ aiInference: aiInferred
293
+ };
294
+ const confidence = calculateConfidence(confidenceParams);
295
+ const confidenceLevel = getConfidenceLevel(confidence);
296
+ let state = "VALID";
297
+ if (missingFields.length > 0) {
298
+ state = "FIELD_MISSING";
299
+ } else if (sampleSize < requiredSize) {
300
+ state = "INSUFFICIENT_SAMPLE";
301
+ } else if (staleDays && staleDays > 30) {
302
+ state = "STALE_DATA";
303
+ } else if (aiInferred) {
304
+ state = "INFERRED_NOT_OBSERVED";
305
+ } else if (confidence < 50) {
306
+ state = "LOW_CONFIDENCE";
307
+ } else if (variance > 0.7) {
308
+ state = "DATA_SKEW_DETECTED";
309
+ } else if (recency < 0.3) {
310
+ state = "PARTIAL_TIME_WINDOW";
311
+ }
312
+ const details = {
313
+ sampleSize,
314
+ requiredSize,
315
+ confidence,
316
+ missingFields: missingFields.length > 0 ? missingFields : void 0,
317
+ staleDays
318
+ };
319
+ return {
320
+ state,
321
+ confidence,
322
+ confidenceLevel,
323
+ details,
324
+ isValid: state === "VALID"
325
+ };
326
+ }, [
327
+ sampleSize,
328
+ requiredSize,
329
+ completeness,
330
+ recency,
331
+ variance,
332
+ aiInferred,
333
+ missingFields,
334
+ staleDays
335
+ ]);
336
+ }
337
+ function useChartData({
338
+ data,
339
+ requiredFields,
340
+ minSampleSize = MINIMUM_SAMPLE_SIZES.overall
341
+ }) {
342
+ return useMemo(() => {
343
+ const missingFields = [];
344
+ if (data.length > 0) {
345
+ const firstRecord = data[0];
346
+ for (const field of requiredFields) {
347
+ if (!(field in firstRecord)) {
348
+ missingFields.push(field);
349
+ }
350
+ }
351
+ }
352
+ let completeness = 1;
353
+ if (data.length > 0 && requiredFields.length > 0) {
354
+ let filled = 0;
355
+ let total = 0;
356
+ for (const record of data) {
357
+ for (const field of requiredFields) {
358
+ total++;
359
+ const value = record[field];
360
+ if (value !== null && value !== void 0 && value !== "") {
361
+ filled++;
362
+ }
363
+ }
364
+ }
365
+ completeness = total > 0 ? filled / total : 0;
366
+ }
367
+ let state = "VALID";
368
+ let message;
369
+ if (missingFields.length > 0) {
370
+ state = "FIELD_MISSING";
371
+ message = `Missing fields: ${missingFields.join(", ")}`;
372
+ } else if (data.length === 0) {
373
+ state = "INSUFFICIENT_SAMPLE";
374
+ message = "No data available";
375
+ } else if (data.length < minSampleSize) {
376
+ state = "INSUFFICIENT_SAMPLE";
377
+ message = `Sample size ${data.length} is below minimum ${minSampleSize}`;
378
+ } else if (completeness < 0.7) {
379
+ state = "LOW_CONFIDENCE";
380
+ message = `Data completeness is ${Math.round(completeness * 100)}%`;
381
+ }
382
+ const confidence = calculateConfidence({
383
+ sampleSize: data.length,
384
+ requiredSize: minSampleSize,
385
+ completeness,
386
+ recency: 1,
387
+ // Assume fresh data if not specified
388
+ variance: 0,
389
+ aiInference: false
390
+ });
391
+ const isRenderable = state === "VALID" || state === "LOW_CONFIDENCE";
392
+ return {
393
+ data,
394
+ state,
395
+ confidence,
396
+ isRenderable,
397
+ message
398
+ };
399
+ }, [data, requiredFields, minSampleSize]);
400
+ }
401
+
402
+ // src/report-engine/chart-types.ts
403
+ var CHART_REGISTRY = {
404
+ // ══════════════════════════════════════════════════════════════════════════
405
+ // TREND CHARTS (MVP)
406
+ // ══════════════════════════════════════════════════════════════════════════
407
+ line: {
408
+ id: "line",
409
+ name: "Line Chart",
410
+ description: "Shows trends over time with connected data points",
411
+ intent: "trend",
412
+ phase: "mvp",
413
+ contract: {
414
+ requiredDimensions: 1,
415
+ requiredMeasures: 1,
416
+ minDataPoints: 3,
417
+ idealDataPoints: 7,
418
+ allowNegativeValues: true,
419
+ requireNonZeroTotal: false,
420
+ warningThresholds: { sparseData: 3 },
421
+ fallback: { type: "show_kpi", message: "Insufficient data for trend visualization" }
422
+ },
423
+ switchableTo: ["smooth_line", "area", "stacked_area"],
424
+ supportsStacking: false,
425
+ supportsMultipleSeries: true,
426
+ requiresTimeAxis: true
427
+ },
428
+ smooth_line: {
429
+ id: "smooth_line",
430
+ name: "Smooth Line Chart",
431
+ description: "Curved line chart for smoother trend visualization",
432
+ intent: "trend",
433
+ phase: "mvp",
434
+ contract: {
435
+ requiredDimensions: 1,
436
+ requiredMeasures: 1,
437
+ minDataPoints: 3,
438
+ idealDataPoints: 7,
439
+ allowNegativeValues: true,
440
+ requireNonZeroTotal: false,
441
+ warningThresholds: { sparseData: 3 },
442
+ fallback: { type: "show_kpi", message: "Insufficient data for trend visualization" }
443
+ },
444
+ switchableTo: ["line", "area", "stacked_area"],
445
+ supportsStacking: false,
446
+ supportsMultipleSeries: true,
447
+ requiresTimeAxis: true
448
+ },
449
+ area: {
450
+ id: "area",
451
+ name: "Area Chart",
452
+ description: "Filled area under line, emphasizes volume over time",
453
+ intent: "trend",
454
+ phase: "mvp",
455
+ contract: {
456
+ requiredDimensions: 1,
457
+ requiredMeasures: 1,
458
+ minDataPoints: 3,
459
+ idealDataPoints: 7,
460
+ allowNegativeValues: false,
461
+ requireNonZeroTotal: false,
462
+ warningThresholds: { sparseData: 3 },
463
+ fallback: { type: "show_kpi", message: "Insufficient data for area visualization" }
464
+ },
465
+ switchableTo: ["line", "smooth_line", "stacked_area", "area_100pct"],
466
+ supportsStacking: true,
467
+ supportsMultipleSeries: true,
468
+ requiresTimeAxis: true
469
+ },
470
+ stacked_area: {
471
+ id: "stacked_area",
472
+ name: "Stacked Area Chart",
473
+ description: "Multiple series stacked to show cumulative trends",
474
+ intent: "trend",
475
+ phase: "mvp",
476
+ contract: {
477
+ requiredDimensions: 1,
478
+ requiredMeasures: 2,
479
+ minDataPoints: 3,
480
+ idealDataPoints: 7,
481
+ allowNegativeValues: false,
482
+ requireNonZeroTotal: true,
483
+ warningThresholds: { sparseData: 3 },
484
+ fallback: { type: "warn", message: "Stacked area requires non-negative values" }
485
+ },
486
+ switchableTo: ["line", "area", "area_100pct"],
487
+ supportsStacking: true,
488
+ supportsMultipleSeries: true,
489
+ requiresTimeAxis: true
490
+ },
491
+ area_100pct: {
492
+ id: "area_100pct",
493
+ name: "100% Stacked Area",
494
+ description: "Shows proportional contribution over time",
495
+ intent: "trend",
496
+ phase: "mvp",
497
+ contract: {
498
+ requiredDimensions: 1,
499
+ requiredMeasures: 2,
500
+ minDataPoints: 3,
501
+ idealDataPoints: 7,
502
+ allowNegativeValues: false,
503
+ requireNonZeroTotal: true,
504
+ warningThresholds: { sparseData: 3 },
505
+ fallback: { type: "warn", message: "100% stacked requires positive totals" }
506
+ },
507
+ switchableTo: ["stacked_area", "area"],
508
+ supportsStacking: true,
509
+ supportsMultipleSeries: true,
510
+ requiresTimeAxis: true
511
+ },
512
+ // ══════════════════════════════════════════════════════════════════════════
513
+ // COMPARISON CHARTS (MVP)
514
+ // ══════════════════════════════════════════════════════════════════════════
515
+ bar: {
516
+ id: "bar",
517
+ name: "Horizontal Bar Chart",
518
+ description: "Horizontal bars for comparing categories",
519
+ intent: "comparison",
520
+ phase: "mvp",
521
+ contract: {
522
+ requiredDimensions: 1,
523
+ requiredMeasures: 1,
524
+ minDataPoints: 2,
525
+ idealDataPoints: 5,
526
+ maxDataPoints: 15,
527
+ allowNegativeValues: true,
528
+ requireNonZeroTotal: false,
529
+ warningThresholds: { tooManyCategories: 12 },
530
+ fallback: { type: "aggregate", strategy: "top_n" }
531
+ },
532
+ switchableTo: ["column", "stacked_bar", "stacked_column"],
533
+ supportsStacking: true,
534
+ supportsMultipleSeries: true,
535
+ requiresTimeAxis: false
536
+ },
537
+ column: {
538
+ id: "column",
539
+ name: "Vertical Column Chart",
540
+ description: "Vertical bars for comparing categories",
541
+ intent: "comparison",
542
+ phase: "mvp",
543
+ contract: {
544
+ requiredDimensions: 1,
545
+ requiredMeasures: 1,
546
+ minDataPoints: 2,
547
+ idealDataPoints: 5,
548
+ maxDataPoints: 12,
549
+ allowNegativeValues: true,
550
+ requireNonZeroTotal: false,
551
+ warningThresholds: { tooManyCategories: 10 },
552
+ fallback: { type: "aggregate", strategy: "top_n" }
553
+ },
554
+ switchableTo: ["bar", "stacked_column", "stacked_bar"],
555
+ supportsStacking: true,
556
+ supportsMultipleSeries: true,
557
+ requiresTimeAxis: false
558
+ },
559
+ stacked_bar: {
560
+ id: "stacked_bar",
561
+ name: "Stacked Horizontal Bar",
562
+ description: "Horizontal stacked bars showing composition per category",
563
+ intent: "comparison",
564
+ phase: "mvp",
565
+ contract: {
566
+ requiredDimensions: 1,
567
+ requiredMeasures: 2,
568
+ minDataPoints: 2,
569
+ idealDataPoints: 5,
570
+ maxDataPoints: 10,
571
+ allowNegativeValues: false,
572
+ requireNonZeroTotal: true,
573
+ warningThresholds: { tooManyCategories: 8, imbalancedRatio: 0.9 },
574
+ fallback: { type: "aggregate", strategy: "other_bucket" }
575
+ },
576
+ switchableTo: ["bar", "stacked_column", "column_100pct"],
577
+ supportsStacking: true,
578
+ supportsMultipleSeries: true,
579
+ requiresTimeAxis: false
580
+ },
581
+ stacked_column: {
582
+ id: "stacked_column",
583
+ name: "Stacked Vertical Column",
584
+ description: "Vertical stacked columns showing composition per category",
585
+ intent: "comparison",
586
+ phase: "mvp",
587
+ contract: {
588
+ requiredDimensions: 1,
589
+ requiredMeasures: 2,
590
+ minDataPoints: 2,
591
+ idealDataPoints: 5,
592
+ maxDataPoints: 10,
593
+ allowNegativeValues: false,
594
+ requireNonZeroTotal: true,
595
+ warningThresholds: { tooManyCategories: 8, imbalancedRatio: 0.9 },
596
+ fallback: { type: "aggregate", strategy: "other_bucket" }
597
+ },
598
+ switchableTo: ["column", "stacked_bar", "column_100pct"],
599
+ supportsStacking: true,
600
+ supportsMultipleSeries: true,
601
+ requiresTimeAxis: false
602
+ },
603
+ column_100pct: {
604
+ id: "column_100pct",
605
+ name: "100% Stacked Column",
606
+ description: "Shows proportional composition per category",
607
+ intent: "comparison",
608
+ phase: "mvp",
609
+ contract: {
610
+ requiredDimensions: 1,
611
+ requiredMeasures: 2,
612
+ minDataPoints: 2,
613
+ idealDataPoints: 5,
614
+ maxDataPoints: 10,
615
+ allowNegativeValues: false,
616
+ requireNonZeroTotal: true,
617
+ warningThresholds: { tooManyCategories: 8 },
618
+ fallback: { type: "warn", message: "100% stacked requires positive totals" }
619
+ },
620
+ switchableTo: ["stacked_column", "stacked_bar"],
621
+ supportsStacking: true,
622
+ supportsMultipleSeries: true,
623
+ requiresTimeAxis: false
624
+ },
625
+ combo: {
626
+ id: "combo",
627
+ name: "Combo Chart",
628
+ description: "Combines bars with line overlay (Phase 2)",
629
+ intent: "comparison",
630
+ phase: "phase2",
631
+ contract: {
632
+ requiredDimensions: 1,
633
+ requiredMeasures: 2,
634
+ minDataPoints: 3,
635
+ idealDataPoints: 6,
636
+ allowNegativeValues: true,
637
+ requireNonZeroTotal: false,
638
+ warningThresholds: { tooManyCategories: 10 },
639
+ fallback: { type: "warn", message: "Combo chart requires dual measures" }
640
+ },
641
+ switchableTo: ["column", "line"],
642
+ supportsStacking: false,
643
+ supportsMultipleSeries: true,
644
+ requiresTimeAxis: false
645
+ },
646
+ // ══════════════════════════════════════════════════════════════════════════
647
+ // COMPOSITION CHARTS (MVP)
648
+ // ══════════════════════════════════════════════════════════════════════════
649
+ pie: {
650
+ id: "pie",
651
+ name: "Pie Chart",
652
+ description: "Shows proportional composition of a whole",
653
+ intent: "composition",
654
+ phase: "mvp",
655
+ contract: {
656
+ requiredDimensions: 1,
657
+ requiredMeasures: 1,
658
+ minDataPoints: 2,
659
+ idealDataPoints: 4,
660
+ maxDataPoints: 6,
661
+ allowNegativeValues: false,
662
+ requireNonZeroTotal: true,
663
+ warningThresholds: { tooManyCategories: 6, imbalancedRatio: 0.95 },
664
+ fallback: { type: "aggregate", strategy: "other_bucket" }
665
+ },
666
+ switchableTo: ["donut", "column_100pct"],
667
+ supportsStacking: false,
668
+ supportsMultipleSeries: false,
669
+ requiresTimeAxis: false,
670
+ maxSlices: 6
671
+ },
672
+ donut: {
673
+ id: "donut",
674
+ name: "Donut Chart",
675
+ description: "Pie chart with center cutout, can display total",
676
+ intent: "composition",
677
+ phase: "mvp",
678
+ contract: {
679
+ requiredDimensions: 1,
680
+ requiredMeasures: 1,
681
+ minDataPoints: 2,
682
+ idealDataPoints: 4,
683
+ maxDataPoints: 6,
684
+ allowNegativeValues: false,
685
+ requireNonZeroTotal: true,
686
+ warningThresholds: { tooManyCategories: 6, imbalancedRatio: 0.95 },
687
+ fallback: { type: "aggregate", strategy: "other_bucket" }
688
+ },
689
+ switchableTo: ["pie", "column_100pct"],
690
+ supportsStacking: false,
691
+ supportsMultipleSeries: false,
692
+ requiresTimeAxis: false,
693
+ maxSlices: 6
694
+ },
695
+ treemap: {
696
+ id: "treemap",
697
+ name: "Treemap",
698
+ description: "Nested rectangles showing hierarchical composition (Phase 2)",
699
+ intent: "composition",
700
+ phase: "phase2",
701
+ contract: {
702
+ requiredDimensions: 1,
703
+ requiredMeasures: 1,
704
+ minDataPoints: 3,
705
+ idealDataPoints: 10,
706
+ maxDataPoints: 50,
707
+ allowNegativeValues: false,
708
+ requireNonZeroTotal: true,
709
+ warningThresholds: { tooManyCategories: 30 },
710
+ fallback: { type: "aggregate", strategy: "top_n" }
711
+ },
712
+ switchableTo: ["pie", "donut"],
713
+ supportsStacking: false,
714
+ supportsMultipleSeries: false,
715
+ requiresTimeAxis: false
716
+ },
717
+ // ══════════════════════════════════════════════════════════════════════════
718
+ // DISTRIBUTION CHARTS (MVP)
719
+ // ══════════════════════════════════════════════════════════════════════════
720
+ histogram: {
721
+ id: "histogram",
722
+ name: "Histogram",
723
+ description: "Shows distribution of values across bins",
724
+ intent: "distribution",
725
+ phase: "mvp",
726
+ contract: {
727
+ requiredDimensions: 0,
728
+ requiredMeasures: 1,
729
+ minDataPoints: 10,
730
+ idealDataPoints: 50,
731
+ allowNegativeValues: true,
732
+ requireNonZeroTotal: false,
733
+ warningThresholds: { sparseData: 10 },
734
+ fallback: { type: "show_kpi", message: "Insufficient data for distribution" }
735
+ },
736
+ switchableTo: ["radar"],
737
+ supportsStacking: false,
738
+ supportsMultipleSeries: false,
739
+ requiresTimeAxis: false
740
+ },
741
+ radar: {
742
+ id: "radar",
743
+ name: "Radar Chart",
744
+ description: "Multi-dimensional comparison in radial layout (Phase 2)",
745
+ intent: "distribution",
746
+ phase: "phase2",
747
+ contract: {
748
+ requiredDimensions: 1,
749
+ requiredMeasures: 3,
750
+ minDataPoints: 3,
751
+ idealDataPoints: 6,
752
+ maxDataPoints: 8,
753
+ allowNegativeValues: false,
754
+ requireNonZeroTotal: false,
755
+ warningThresholds: { tooManyCategories: 8 },
756
+ fallback: { type: "warn", message: "Radar works best with 3-8 dimensions" }
757
+ },
758
+ switchableTo: ["histogram"],
759
+ supportsStacking: false,
760
+ supportsMultipleSeries: true,
761
+ requiresTimeAxis: false
762
+ },
763
+ // ══════════════════════════════════════════════════════════════════════════
764
+ // RELATIONSHIP CHARTS
765
+ // ══════════════════════════════════════════════════════════════════════════
766
+ heatmap: {
767
+ id: "heatmap",
768
+ name: "Heatmap",
769
+ description: "Color-coded matrix showing intensity",
770
+ intent: "relationship",
771
+ phase: "mvp",
772
+ contract: {
773
+ requiredDimensions: 2,
774
+ requiredMeasures: 1,
775
+ minDataPoints: 9,
776
+ idealDataPoints: 25,
777
+ allowNegativeValues: true,
778
+ requireNonZeroTotal: false,
779
+ warningThresholds: { sparseData: 9 },
780
+ fallback: { type: "warn", message: "Heatmap requires grid data" }
781
+ },
782
+ switchableTo: ["scatter"],
783
+ supportsStacking: false,
784
+ supportsMultipleSeries: false,
785
+ requiresTimeAxis: false
786
+ },
787
+ scatter: {
788
+ id: "scatter",
789
+ name: "Scatter Plot",
790
+ description: "Shows correlation between two variables (Phase 2)",
791
+ intent: "relationship",
792
+ phase: "phase2",
793
+ contract: {
794
+ requiredDimensions: 0,
795
+ requiredMeasures: 2,
796
+ minDataPoints: 20,
797
+ idealDataPoints: 100,
798
+ allowNegativeValues: true,
799
+ requireNonZeroTotal: false,
800
+ warningThresholds: { sparseData: 20 },
801
+ fallback: { type: "show_kpi", message: "Scatter requires 20+ points" }
802
+ },
803
+ switchableTo: ["bubble", "heatmap"],
804
+ supportsStacking: false,
805
+ supportsMultipleSeries: true,
806
+ requiresTimeAxis: false
807
+ },
808
+ bubble: {
809
+ id: "bubble",
810
+ name: "Bubble Chart",
811
+ description: "Scatter with sized points for third dimension (Phase 2)",
812
+ intent: "relationship",
813
+ phase: "phase2",
814
+ contract: {
815
+ requiredDimensions: 0,
816
+ requiredMeasures: 3,
817
+ minDataPoints: 10,
818
+ idealDataPoints: 50,
819
+ allowNegativeValues: true,
820
+ requireNonZeroTotal: false,
821
+ warningThresholds: { sparseData: 10 },
822
+ fallback: { type: "show_kpi", message: "Bubble requires 3 measures" }
823
+ },
824
+ switchableTo: ["scatter"],
825
+ supportsStacking: false,
826
+ supportsMultipleSeries: true,
827
+ requiresTimeAxis: false
828
+ },
829
+ // ══════════════════════════════════════════════════════════════════════════
830
+ // GEOGRAPHIC CHARTS (Phase 2)
831
+ // ══════════════════════════════════════════════════════════════════════════
832
+ geo: {
833
+ id: "geo",
834
+ name: "Geographic Map",
835
+ description: "Map with regional data markers (Phase 2)",
836
+ intent: "geo",
837
+ phase: "phase2",
838
+ contract: {
839
+ requiredDimensions: 1,
840
+ // geo dimension (country/region)
841
+ requiredMeasures: 1,
842
+ minDataPoints: 1,
843
+ idealDataPoints: 10,
844
+ allowNegativeValues: true,
845
+ requireNonZeroTotal: false,
846
+ warningThresholds: {},
847
+ fallback: { type: "hide" }
848
+ },
849
+ switchableTo: ["choropleth"],
850
+ supportsStacking: false,
851
+ supportsMultipleSeries: false,
852
+ requiresTimeAxis: false
853
+ },
854
+ choropleth: {
855
+ id: "choropleth",
856
+ name: "Choropleth Map",
857
+ description: "Color-shaded regions by value (Phase 2)",
858
+ intent: "geo",
859
+ phase: "phase2",
860
+ contract: {
861
+ requiredDimensions: 1,
862
+ requiredMeasures: 1,
863
+ minDataPoints: 3,
864
+ idealDataPoints: 20,
865
+ allowNegativeValues: false,
866
+ requireNonZeroTotal: false,
867
+ warningThresholds: {},
868
+ fallback: { type: "hide" }
869
+ },
870
+ switchableTo: ["geo"],
871
+ supportsStacking: false,
872
+ supportsMultipleSeries: false,
873
+ requiresTimeAxis: false
874
+ },
875
+ // ══════════════════════════════════════════════════════════════════════════
876
+ // SPECIAL CHARTS
877
+ // ══════════════════════════════════════════════════════════════════════════
878
+ funnel: {
879
+ id: "funnel",
880
+ name: "Funnel Chart",
881
+ description: "Shows conversion through sequential stages",
882
+ intent: "comparison",
883
+ phase: "mvp",
884
+ contract: {
885
+ requiredDimensions: 1,
886
+ requiredMeasures: 1,
887
+ minDataPoints: 3,
888
+ idealDataPoints: 5,
889
+ maxDataPoints: 7,
890
+ allowNegativeValues: false,
891
+ requireNonZeroTotal: true,
892
+ warningThresholds: { tooManyCategories: 7 },
893
+ fallback: { type: "warn", message: "Funnel requires sequential stages" }
894
+ },
895
+ switchableTo: ["bar"],
896
+ supportsStacking: false,
897
+ supportsMultipleSeries: false,
898
+ requiresTimeAxis: false
899
+ },
900
+ waterfall: {
901
+ id: "waterfall",
902
+ name: "Waterfall Chart",
903
+ description: "Shows cumulative effect of sequential changes (Phase 2)",
904
+ intent: "comparison",
905
+ phase: "phase2",
906
+ contract: {
907
+ requiredDimensions: 1,
908
+ requiredMeasures: 1,
909
+ minDataPoints: 3,
910
+ idealDataPoints: 6,
911
+ maxDataPoints: 12,
912
+ allowNegativeValues: true,
913
+ requireNonZeroTotal: false,
914
+ warningThresholds: { tooManyCategories: 10 },
915
+ fallback: { type: "warn", message: "Waterfall requires sequential data" }
916
+ },
917
+ switchableTo: ["bar", "column"],
918
+ supportsStacking: false,
919
+ supportsMultipleSeries: false,
920
+ requiresTimeAxis: false
921
+ },
922
+ timeline: {
923
+ id: "timeline",
924
+ name: "Timeline",
925
+ description: "Shows events along time axis (Phase 2)",
926
+ intent: "trend",
927
+ phase: "phase2",
928
+ contract: {
929
+ requiredDimensions: 1,
930
+ requiredMeasures: 0,
931
+ minDataPoints: 2,
932
+ idealDataPoints: 10,
933
+ allowNegativeValues: false,
934
+ requireNonZeroTotal: false,
935
+ warningThresholds: {},
936
+ fallback: { type: "hide" }
937
+ },
938
+ switchableTo: ["line"],
939
+ supportsStacking: false,
940
+ supportsMultipleSeries: false,
941
+ requiresTimeAxis: true
942
+ }
943
+ };
944
+ var INTENT_CHART_FAMILIES = {
945
+ trend: ["line", "smooth_line", "area", "stacked_area", "area_100pct"],
946
+ comparison: ["bar", "column", "stacked_bar", "stacked_column", "column_100pct", "funnel"],
947
+ composition: ["pie", "donut"],
948
+ distribution: ["histogram"],
949
+ relationship: ["heatmap"],
950
+ geo: []
951
+ };
952
+ function getAllowedSwitchTargets(currentType) {
953
+ const metadata = CHART_REGISTRY[currentType];
954
+ if (!metadata) return [];
955
+ return metadata.switchableTo.filter((type) => {
956
+ const targetMeta = CHART_REGISTRY[type];
957
+ return targetMeta && targetMeta.phase === "mvp";
958
+ });
959
+ }
960
+ function canSwitchChart(from, to) {
961
+ const fromMeta = CHART_REGISTRY[from];
962
+ const toMeta = CHART_REGISTRY[to];
963
+ if (!fromMeta || !toMeta) return false;
964
+ if (fromMeta.intent !== toMeta.intent) return false;
965
+ return fromMeta.switchableTo.includes(to);
966
+ }
967
+ function validateChartData(chartType, data, dimensions, measures) {
968
+ const metadata = CHART_REGISTRY[chartType];
969
+ if (!metadata) {
970
+ return {
971
+ isValid: false,
972
+ warnings: [],
973
+ errors: [`Unknown chart type: ${chartType}`]
974
+ };
975
+ }
976
+ const contract = metadata.contract;
977
+ const warnings = [];
978
+ const errors = [];
979
+ if (data.length < contract.minDataPoints) {
980
+ errors.push(`Requires at least ${contract.minDataPoints} data points, got ${data.length}`);
981
+ }
982
+ if (contract.maxDataPoints && data.length > contract.maxDataPoints) {
983
+ warnings.push(`Chart works best with \u2264${contract.maxDataPoints} items. Consider aggregating.`);
984
+ }
985
+ if (dimensions.length < contract.requiredDimensions) {
986
+ errors.push(`Requires ${contract.requiredDimensions} dimension(s), got ${dimensions.length}`);
987
+ }
988
+ if (measures.length < contract.requiredMeasures) {
989
+ errors.push(`Requires ${contract.requiredMeasures} measure(s), got ${measures.length}`);
990
+ }
991
+ if (!contract.allowNegativeValues && data.length > 0) {
992
+ const hasNegative = data.some((row) => {
993
+ if (typeof row !== "object" || row === null) return false;
994
+ return measures.some((m) => {
995
+ const val = row[m];
996
+ return typeof val === "number" && val < 0;
997
+ });
998
+ });
999
+ if (hasNegative) {
1000
+ errors.push("This chart type does not support negative values");
1001
+ }
1002
+ }
1003
+ if (contract.warningThresholds.tooManyCategories && data.length > contract.warningThresholds.tooManyCategories) {
1004
+ warnings.push(`Too many categories (${data.length}). Consider grouping smaller values.`);
1005
+ }
1006
+ return {
1007
+ isValid: errors.length === 0,
1008
+ warnings,
1009
+ errors,
1010
+ fallbackAction: errors.length > 0 ? contract.fallback : void 0
1011
+ };
1012
+ }
1013
+ function getMVPChartsForIntent(intent) {
1014
+ return Object.values(CHART_REGISTRY).filter(
1015
+ (meta) => meta.intent === intent && meta.phase === "mvp"
1016
+ );
1017
+ }
1018
+ function getDefaultChartForIntent(intent) {
1019
+ const defaults = {
1020
+ trend: "line",
1021
+ comparison: "column",
1022
+ composition: "donut",
1023
+ distribution: "histogram",
1024
+ relationship: "heatmap",
1025
+ geo: "geo"
1026
+ };
1027
+ return defaults[intent];
1028
+ }
1029
+ function suggestChartType(params) {
1030
+ const {
1031
+ hasTimeAxis,
1032
+ dimensionCount,
1033
+ measureCount,
1034
+ dataPointCount,
1035
+ hasNegativeValues,
1036
+ isSequential
1037
+ } = params;
1038
+ if (hasTimeAxis && measureCount >= 1) {
1039
+ if (measureCount > 1 && !hasNegativeValues) return "stacked_area";
1040
+ return "line";
1041
+ }
1042
+ if (isSequential && !hasNegativeValues && dataPointCount <= 7) {
1043
+ return "funnel";
1044
+ }
1045
+ if (measureCount === 1 && dataPointCount <= 6 && !hasNegativeValues) {
1046
+ return "donut";
1047
+ }
1048
+ if (dimensionCount === 2 && measureCount === 1) {
1049
+ return "heatmap";
1050
+ }
1051
+ return "column";
1052
+ }
1053
+ function validateReportStructure(children) {
1054
+ const issues = [];
1055
+ const childArray = React2.Children.toArray(children);
1056
+ let hasThesis = false;
1057
+ let thesisIndex = -1;
1058
+ const getComponentName2 = (child) => {
1059
+ if (!React2.isValidElement(child)) return void 0;
1060
+ const type = child.type;
1061
+ return type.displayName || type.name;
1062
+ };
1063
+ const isChart2 = (name) => {
1064
+ return name && (name.endsWith("Chart") || name === "MBTIRadar" || name === "MBTITypeGrid" || name === "KeyMetric");
1065
+ };
1066
+ childArray.forEach((child, index) => {
1067
+ const name = getComponentName2(child);
1068
+ if (name === "ExecutiveThesis") {
1069
+ if (hasThesis) {
1070
+ issues.push({
1071
+ ruleId: "R1",
1072
+ severity: "error",
1073
+ message: "Only one ExecutiveThesis is allowed per report.",
1074
+ component: "ExecutiveThesis"
1075
+ });
1076
+ }
1077
+ hasThesis = true;
1078
+ thesisIndex = index;
1079
+ }
1080
+ if (isChart2(name)) {
1081
+ issues.push({
1082
+ ruleId: "R3",
1083
+ severity: "error",
1084
+ message: `Orphan chart detected: <${name} />. Charts must be placed inside an InsightBlock or EvidenceGroup.`,
1085
+ component: name
1086
+ });
1087
+ }
1088
+ if (name === "InsightBlock" && React2.isValidElement(child)) {
1089
+ validateInsightBlock(child, issues);
1090
+ }
1091
+ });
1092
+ if (!hasThesis) {
1093
+ issues.push({
1094
+ ruleId: "R1",
1095
+ severity: "error",
1096
+ message: "Report must contain an ExecutiveThesis."
1097
+ });
1098
+ } else if (thesisIndex > 2) {
1099
+ issues.push({
1100
+ ruleId: "R1",
1101
+ severity: "warning",
1102
+ message: "ExecutiveThesis should be the first major component in the report."
1103
+ });
1104
+ }
1105
+ return {
1106
+ isValid: issues.filter((i) => i.severity === "error").length === 0,
1107
+ issues
1108
+ };
1109
+ }
1110
+ function validateInsightBlock(node, issues) {
1111
+ const children = node.props.children;
1112
+ const childArray = React2.Children.toArray(children);
1113
+ let chartsInBlock = 0;
1114
+ const countCharts = (nodes) => {
1115
+ nodes.forEach((n) => {
1116
+ const name = getComponentName(n);
1117
+ if (isChart(name)) {
1118
+ chartsInBlock++;
1119
+ }
1120
+ if (name === "EvidenceGroup" && React2.isValidElement(n)) {
1121
+ countCharts(React2.Children.toArray(n.props.children));
1122
+ }
1123
+ });
1124
+ };
1125
+ countCharts(childArray);
1126
+ if (chartsInBlock > 3) {
1127
+ issues.push({
1128
+ ruleId: "R6",
1129
+ severity: "warning",
1130
+ message: `InsightBlock contains ${chartsInBlock} charts. Recommended maximum is 3 to prevent data dumping.`,
1131
+ component: "InsightBlock"
1132
+ });
1133
+ }
1134
+ }
1135
+ var getComponentName = (child) => {
1136
+ if (!React2.isValidElement(child)) return void 0;
1137
+ const type = child.type;
1138
+ return type.displayName || type.name;
1139
+ };
1140
+ var isChart = (name) => {
1141
+ return name && (name.endsWith("Chart") || name === "MBTIRadar" || name === "MBTITypeGrid" || name === "KeyMetric");
1142
+ };
1143
+ var ReportShell = React2.forwardRef(
1144
+ ({
1145
+ title,
1146
+ subtitle,
1147
+ mode = "executive",
1148
+ brand,
1149
+ onModeChange,
1150
+ children,
1151
+ actions,
1152
+ className,
1153
+ ...props
1154
+ }, ref) => {
1155
+ return /* @__PURE__ */ jsx(ReportModeProvider, { mode, onModeChange, children: /* @__PURE__ */ jsxs(
1156
+ "div",
1157
+ {
1158
+ ref,
1159
+ className: clsx12("ds-report-shell", className),
1160
+ "data-mode": mode,
1161
+ "data-brand": brand,
1162
+ ...props,
1163
+ children: [
1164
+ (title || subtitle || actions) && /* @__PURE__ */ jsxs("header", { className: "ds-report-shell__header", children: [
1165
+ /* @__PURE__ */ jsxs("div", { className: "ds-report-shell__header-content", children: [
1166
+ title && /* @__PURE__ */ jsx("h1", { className: "ds-report-shell__title", children: title }),
1167
+ subtitle && /* @__PURE__ */ jsx("p", { className: "ds-report-shell__subtitle", children: subtitle })
1168
+ ] }),
1169
+ actions && /* @__PURE__ */ jsx("div", { className: "ds-report-shell__actions", children: actions })
1170
+ ] }),
1171
+ /* @__PURE__ */ jsx("main", { className: "ds-report-shell__content", children })
1172
+ ]
1173
+ }
1174
+ ) });
1175
+ }
1176
+ );
1177
+ ReportShell.displayName = "ReportShell";
1178
+ var ExecutiveThesis = React2.forwardRef(
1179
+ ({ thesis, context, metric, aiGenerated, className, ...props }, ref) => {
1180
+ const { features } = useReportMode();
1181
+ return /* @__PURE__ */ jsxs(
1182
+ "section",
1183
+ {
1184
+ ref,
1185
+ className: clsx12("ds-executive-thesis", className),
1186
+ "aria-labelledby": "executive-thesis-title",
1187
+ ...props,
1188
+ children: [
1189
+ /* @__PURE__ */ jsxs("div", { className: "ds-executive-thesis__content", children: [
1190
+ /* @__PURE__ */ jsxs("h2", { id: "executive-thesis-title", className: "ds-executive-thesis__title", children: [
1191
+ "Key Finding",
1192
+ aiGenerated && features.showConfidenceScores && /* @__PURE__ */ jsx("span", { className: "ds-executive-thesis__ai-badge", children: "AI Generated" })
1193
+ ] }),
1194
+ /* @__PURE__ */ jsx("p", { className: "ds-executive-thesis__thesis", children: thesis }),
1195
+ context && /* @__PURE__ */ jsx("p", { className: "ds-executive-thesis__context", children: context })
1196
+ ] }),
1197
+ metric && /* @__PURE__ */ jsxs("div", { className: "ds-executive-thesis__metric", children: [
1198
+ /* @__PURE__ */ jsx("span", { className: "ds-executive-thesis__metric-label", children: metric.label }),
1199
+ /* @__PURE__ */ jsxs(
1200
+ "span",
1201
+ {
1202
+ className: clsx12(
1203
+ "ds-executive-thesis__metric-value",
1204
+ metric.trend && `ds-executive-thesis__metric-value--${metric.trend}`
1205
+ ),
1206
+ children: [
1207
+ metric.trend === "up" && "\u2191 ",
1208
+ metric.trend === "down" && "\u2193 ",
1209
+ metric.value
1210
+ ]
1211
+ }
1212
+ )
1213
+ ] })
1214
+ ]
1215
+ }
1216
+ );
1217
+ }
1218
+ );
1219
+ ExecutiveThesis.displayName = "ExecutiveThesis";
1220
+ var InsightBlock = React2.forwardRef(
1221
+ ({ type, headline, description, confidence, methodology, children, className, ...props }, ref) => {
1222
+ const { features } = useReportMode();
1223
+ const contract = INSIGHT_TYPE_CONTRACTS[type];
1224
+ const getConfidenceClass = () => {
1225
+ if (confidence === void 0) return "";
1226
+ if (confidence >= 90) return "ds-insight-block--confidence-high";
1227
+ if (confidence >= 70) return "ds-insight-block--confidence-moderate";
1228
+ if (confidence >= 50) return "ds-insight-block--confidence-low";
1229
+ return "ds-insight-block--confidence-insufficient";
1230
+ };
1231
+ return /* @__PURE__ */ jsxs(
1232
+ "section",
1233
+ {
1234
+ ref,
1235
+ className: clsx12("ds-insight-block", getConfidenceClass(), className),
1236
+ "data-insight-type": type,
1237
+ "aria-labelledby": `insight-${type}-title`,
1238
+ ...props,
1239
+ children: [
1240
+ /* @__PURE__ */ jsxs("header", { className: "ds-insight-block__header", children: [
1241
+ /* @__PURE__ */ jsxs("div", { className: "ds-insight-block__meta", children: [
1242
+ /* @__PURE__ */ jsx("span", { className: "ds-insight-block__type", children: type.replace(/-/g, " ") }),
1243
+ features.showConfidenceScores && confidence !== void 0 && /* @__PURE__ */ jsxs("span", { className: "ds-insight-block__confidence", children: [
1244
+ confidence,
1245
+ "% confidence"
1246
+ ] })
1247
+ ] }),
1248
+ /* @__PURE__ */ jsx("h3", { id: `insight-${type}-title`, className: "ds-insight-block__headline", children: headline }),
1249
+ description && /* @__PURE__ */ jsx("p", { className: "ds-insight-block__description", children: description })
1250
+ ] }),
1251
+ /* @__PURE__ */ jsx("div", { className: "ds-insight-block__evidence", children }),
1252
+ features.showMethodology && methodology && /* @__PURE__ */ jsxs("footer", { className: "ds-insight-block__methodology", children: [
1253
+ /* @__PURE__ */ jsx("h4", { className: "ds-insight-block__methodology-title", children: "Methodology" }),
1254
+ /* @__PURE__ */ jsx("p", { className: "ds-insight-block__methodology-text", children: methodology }),
1255
+ contract && /* @__PURE__ */ jsxs("p", { className: "ds-insight-block__methodology-contract", children: [
1256
+ "Min sample: ",
1257
+ contract.minSampleSize,
1258
+ " | Allowed charts:",
1259
+ " ",
1260
+ contract.allowedCharts.join(", ")
1261
+ ] })
1262
+ ] })
1263
+ ]
1264
+ }
1265
+ );
1266
+ }
1267
+ );
1268
+ InsightBlock.displayName = "InsightBlock";
1269
+ var EvidenceGroup = React2.forwardRef(
1270
+ ({ title, layout = "row", columns = 2, children, className, ...props }, ref) => {
1271
+ const childCount = React2.Children.count(children);
1272
+ if (childCount > 3) {
1273
+ console.warn(
1274
+ `EvidenceGroup: Maximum 3 charts allowed per insight block (received ${childCount}). This violates composition rule R6.`
1275
+ );
1276
+ }
1277
+ return /* @__PURE__ */ jsxs(
1278
+ "div",
1279
+ {
1280
+ ref,
1281
+ className: clsx12(
1282
+ "ds-evidence-group",
1283
+ `ds-evidence-group--${layout}`,
1284
+ layout === "grid" && `ds-evidence-group--cols-${columns}`,
1285
+ className
1286
+ ),
1287
+ role: "group",
1288
+ "aria-label": title || "Evidence charts",
1289
+ ...props,
1290
+ children: [
1291
+ title && /* @__PURE__ */ jsx("h4", { className: "ds-evidence-group__title", children: title }),
1292
+ /* @__PURE__ */ jsx("div", { className: "ds-evidence-group__content", children })
1293
+ ]
1294
+ }
1295
+ );
1296
+ }
1297
+ );
1298
+ EvidenceGroup.displayName = "EvidenceGroup";
1299
+ var ConfidenceIndicator = React2.forwardRef(
1300
+ ({ score, showScore = true, showLabel = true, size = "md", className, ...props }, ref) => {
1301
+ const threshold = getConfidenceThreshold(score);
1302
+ const normalizedScore = Math.max(0, Math.min(100, score));
1303
+ return /* @__PURE__ */ jsxs(
1304
+ "div",
1305
+ {
1306
+ ref,
1307
+ className: clsx12(
1308
+ "ds-confidence-indicator",
1309
+ `ds-confidence-indicator--${size}`,
1310
+ `ds-confidence-indicator--${threshold.level}`,
1311
+ className
1312
+ ),
1313
+ role: "meter",
1314
+ "aria-valuenow": normalizedScore,
1315
+ "aria-valuemin": 0,
1316
+ "aria-valuemax": 100,
1317
+ "aria-label": `Confidence: ${threshold.label} (${normalizedScore}%)`,
1318
+ ...props,
1319
+ children: [
1320
+ /* @__PURE__ */ jsx("div", { className: "ds-confidence-indicator__bar", children: /* @__PURE__ */ jsx("div", { className: "ds-confidence-indicator__fill", style: { width: `${normalizedScore}%` } }) }),
1321
+ /* @__PURE__ */ jsxs("div", { className: "ds-confidence-indicator__text", children: [
1322
+ showScore && /* @__PURE__ */ jsxs("span", { className: "ds-confidence-indicator__score", children: [
1323
+ normalizedScore,
1324
+ "%"
1325
+ ] }),
1326
+ showLabel && /* @__PURE__ */ jsx("span", { className: "ds-confidence-indicator__label", children: threshold.label })
1327
+ ] })
1328
+ ]
1329
+ }
1330
+ );
1331
+ }
1332
+ );
1333
+ ConfidenceIndicator.displayName = "ConfidenceIndicator";
1334
+ var DataCoverageBadge = React2.forwardRef(
1335
+ ({ sampleSize, requiredSize, dateRange, showDateRange = true, size = "md", className, ...props }, ref) => {
1336
+ const isSufficient = !requiredSize || sampleSize >= requiredSize;
1337
+ const percentage = requiredSize ? Math.min(100, Math.round(sampleSize / requiredSize * 100)) : 100;
1338
+ return /* @__PURE__ */ jsxs(
1339
+ "div",
1340
+ {
1341
+ ref,
1342
+ className: clsx12(
1343
+ "ds-data-coverage-badge",
1344
+ `ds-data-coverage-badge--${size}`,
1345
+ !isSufficient && "ds-data-coverage-badge--insufficient",
1346
+ className
1347
+ ),
1348
+ ...props,
1349
+ children: [
1350
+ /* @__PURE__ */ jsxs("div", { className: "ds-data-coverage-badge__sample", children: [
1351
+ /* @__PURE__ */ jsx("span", { className: "ds-data-coverage-badge__icon", children: /* @__PURE__ */ jsxs(
1352
+ "svg",
1353
+ {
1354
+ width: "14",
1355
+ height: "14",
1356
+ viewBox: "0 0 24 24",
1357
+ fill: "none",
1358
+ stroke: "currentColor",
1359
+ strokeWidth: "2",
1360
+ children: [
1361
+ /* @__PURE__ */ jsx("path", { d: "M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" }),
1362
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "7", r: "4" }),
1363
+ /* @__PURE__ */ jsx("path", { d: "M23 21v-2a4 4 0 0 0-3-3.87" }),
1364
+ /* @__PURE__ */ jsx("path", { d: "M16 3.13a4 4 0 0 1 0 7.75" })
1365
+ ]
1366
+ }
1367
+ ) }),
1368
+ /* @__PURE__ */ jsxs("span", { className: "ds-data-coverage-badge__count", children: [
1369
+ "n=",
1370
+ sampleSize.toLocaleString()
1371
+ ] }),
1372
+ requiredSize && /* @__PURE__ */ jsxs("span", { className: "ds-data-coverage-badge__required", children: [
1373
+ "(",
1374
+ percentage,
1375
+ "% of min ",
1376
+ requiredSize,
1377
+ ")"
1378
+ ] })
1379
+ ] }),
1380
+ showDateRange && dateRange && /* @__PURE__ */ jsxs("div", { className: "ds-data-coverage-badge__date", children: [
1381
+ /* @__PURE__ */ jsx("span", { className: "ds-data-coverage-badge__icon", children: /* @__PURE__ */ jsxs(
1382
+ "svg",
1383
+ {
1384
+ width: "14",
1385
+ height: "14",
1386
+ viewBox: "0 0 24 24",
1387
+ fill: "none",
1388
+ stroke: "currentColor",
1389
+ strokeWidth: "2",
1390
+ children: [
1391
+ /* @__PURE__ */ jsx("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2", ry: "2" }),
1392
+ /* @__PURE__ */ jsx("line", { x1: "16", y1: "2", x2: "16", y2: "6" }),
1393
+ /* @__PURE__ */ jsx("line", { x1: "8", y1: "2", x2: "8", y2: "6" }),
1394
+ /* @__PURE__ */ jsx("line", { x1: "3", y1: "10", x2: "21", y2: "10" })
1395
+ ]
1396
+ }
1397
+ ) }),
1398
+ /* @__PURE__ */ jsxs("span", { children: [
1399
+ dateRange.start,
1400
+ " \u2013 ",
1401
+ dateRange.end
1402
+ ] })
1403
+ ] })
1404
+ ]
1405
+ }
1406
+ );
1407
+ }
1408
+ );
1409
+ DataCoverageBadge.displayName = "DataCoverageBadge";
1410
+ var DataStateIndicator = React2.forwardRef(
1411
+ ({ state, details, variant = "compact", onAction, className, ...props }, ref) => {
1412
+ const config = ANALYTICAL_STATE_CONFIG[state];
1413
+ if (state === "VALID" && variant === "compact") {
1414
+ return null;
1415
+ }
1416
+ const renderIcon = () => {
1417
+ switch (config.icon) {
1418
+ case "check":
1419
+ return /* @__PURE__ */ jsx(
1420
+ "svg",
1421
+ {
1422
+ width: "16",
1423
+ height: "16",
1424
+ viewBox: "0 0 24 24",
1425
+ fill: "none",
1426
+ stroke: "currentColor",
1427
+ strokeWidth: "2",
1428
+ children: /* @__PURE__ */ jsx("polyline", { points: "20,6 9,17 4,12" })
1429
+ }
1430
+ );
1431
+ case "alert-triangle":
1432
+ return /* @__PURE__ */ jsxs(
1433
+ "svg",
1434
+ {
1435
+ width: "16",
1436
+ height: "16",
1437
+ viewBox: "0 0 24 24",
1438
+ fill: "none",
1439
+ stroke: "currentColor",
1440
+ strokeWidth: "2",
1441
+ children: [
1442
+ /* @__PURE__ */ 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" }),
1443
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "9", x2: "12", y2: "13" }),
1444
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
1445
+ ]
1446
+ }
1447
+ );
1448
+ case "alert-circle":
1449
+ return /* @__PURE__ */ jsxs(
1450
+ "svg",
1451
+ {
1452
+ width: "16",
1453
+ height: "16",
1454
+ viewBox: "0 0 24 24",
1455
+ fill: "none",
1456
+ stroke: "currentColor",
1457
+ strokeWidth: "2",
1458
+ children: [
1459
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
1460
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
1461
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
1462
+ ]
1463
+ }
1464
+ );
1465
+ case "x-circle":
1466
+ return /* @__PURE__ */ jsxs(
1467
+ "svg",
1468
+ {
1469
+ width: "16",
1470
+ height: "16",
1471
+ viewBox: "0 0 24 24",
1472
+ fill: "none",
1473
+ stroke: "currentColor",
1474
+ strokeWidth: "2",
1475
+ children: [
1476
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
1477
+ /* @__PURE__ */ jsx("line", { x1: "15", y1: "9", x2: "9", y2: "15" }),
1478
+ /* @__PURE__ */ jsx("line", { x1: "9", y1: "9", x2: "15", y2: "15" })
1479
+ ]
1480
+ }
1481
+ );
1482
+ case "cpu":
1483
+ return /* @__PURE__ */ jsxs(
1484
+ "svg",
1485
+ {
1486
+ width: "16",
1487
+ height: "16",
1488
+ viewBox: "0 0 24 24",
1489
+ fill: "none",
1490
+ stroke: "currentColor",
1491
+ strokeWidth: "2",
1492
+ children: [
1493
+ /* @__PURE__ */ jsx("rect", { x: "4", y: "4", width: "16", height: "16", rx: "2", ry: "2" }),
1494
+ /* @__PURE__ */ jsx("rect", { x: "9", y: "9", width: "6", height: "6" }),
1495
+ /* @__PURE__ */ jsx("line", { x1: "9", y1: "1", x2: "9", y2: "4" }),
1496
+ /* @__PURE__ */ jsx("line", { x1: "15", y1: "1", x2: "15", y2: "4" }),
1497
+ /* @__PURE__ */ jsx("line", { x1: "9", y1: "20", x2: "9", y2: "23" }),
1498
+ /* @__PURE__ */ jsx("line", { x1: "15", y1: "20", x2: "15", y2: "23" }),
1499
+ /* @__PURE__ */ jsx("line", { x1: "20", y1: "9", x2: "23", y2: "9" }),
1500
+ /* @__PURE__ */ jsx("line", { x1: "20", y1: "14", x2: "23", y2: "14" }),
1501
+ /* @__PURE__ */ jsx("line", { x1: "1", y1: "9", x2: "4", y2: "9" }),
1502
+ /* @__PURE__ */ jsx("line", { x1: "1", y1: "14", x2: "4", y2: "14" })
1503
+ ]
1504
+ }
1505
+ );
1506
+ default:
1507
+ return /* @__PURE__ */ jsxs(
1508
+ "svg",
1509
+ {
1510
+ width: "16",
1511
+ height: "16",
1512
+ viewBox: "0 0 24 24",
1513
+ fill: "none",
1514
+ stroke: "currentColor",
1515
+ strokeWidth: "2",
1516
+ children: [
1517
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
1518
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "16", x2: "12", y2: "12" }),
1519
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "8", x2: "12.01", y2: "8" })
1520
+ ]
1521
+ }
1522
+ );
1523
+ }
1524
+ };
1525
+ return /* @__PURE__ */ jsxs(
1526
+ "div",
1527
+ {
1528
+ ref,
1529
+ className: clsx12(
1530
+ "ds-data-state-indicator",
1531
+ `ds-data-state-indicator--${variant}`,
1532
+ `ds-data-state-indicator--${state.toLowerCase().replace(/_/g, "-")}`,
1533
+ className
1534
+ ),
1535
+ role: "status",
1536
+ "aria-live": "polite",
1537
+ ...props,
1538
+ children: [
1539
+ /* @__PURE__ */ jsx("span", { className: "ds-data-state-indicator__icon", style: { color: config.color }, children: renderIcon() }),
1540
+ /* @__PURE__ */ jsxs("div", { className: "ds-data-state-indicator__content", children: [
1541
+ /* @__PURE__ */ jsx("span", { className: "ds-data-state-indicator__label", children: config.label }),
1542
+ variant === "full" && details && /* @__PURE__ */ jsxs("span", { className: "ds-data-state-indicator__details", children: [
1543
+ details.message,
1544
+ details.sampleSize !== void 0 && details.requiredSize !== void 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
1545
+ " ",
1546
+ "(n=",
1547
+ details.sampleSize,
1548
+ "/",
1549
+ details.requiredSize,
1550
+ ")"
1551
+ ] }),
1552
+ details.confidence !== void 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
1553
+ " \u2022 ",
1554
+ details.confidence,
1555
+ "% confidence"
1556
+ ] }),
1557
+ details.missingFields && details.missingFields.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
1558
+ " \u2022 Missing: ",
1559
+ details.missingFields.join(", ")
1560
+ ] })
1561
+ ] })
1562
+ ] }),
1563
+ config.action && onAction && /* @__PURE__ */ jsx("button", { type: "button", className: "ds-data-state-indicator__action", onClick: onAction, children: config.action })
1564
+ ]
1565
+ }
1566
+ );
1567
+ }
1568
+ );
1569
+ DataStateIndicator.displayName = "DataStateIndicator";
1570
+ var MethodologyNote = React2.forwardRef(
1571
+ ({ children, sampleSize, sources, calculation, forceShow = false, className, labels, ...props }, ref) => {
1572
+ const titleText = labels?.title ?? "Methodology";
1573
+ const sampleSizeLabel = labels?.sampleSize ?? "Sample Size";
1574
+ const dataSourcesLabel = labels?.dataSources ?? "Data Sources";
1575
+ const calculationLabel = labels?.calculation ?? "Calculation";
1576
+ const { features } = useReportMode();
1577
+ const shouldShow = forceShow || features.showMethodology || sampleSize !== void 0 && sampleSize < 100;
1578
+ if (!shouldShow) {
1579
+ return null;
1580
+ }
1581
+ return /* @__PURE__ */ jsxs(
1582
+ "aside",
1583
+ {
1584
+ ref,
1585
+ className: clsx12("ds-methodology-note", className),
1586
+ "aria-label": titleText,
1587
+ ...props,
1588
+ children: [
1589
+ /* @__PURE__ */ jsxs("div", { className: "ds-methodology-note__header", children: [
1590
+ /* @__PURE__ */ jsxs(
1591
+ "svg",
1592
+ {
1593
+ className: "ds-methodology-note__icon",
1594
+ width: "16",
1595
+ height: "16",
1596
+ viewBox: "0 0 24 24",
1597
+ fill: "none",
1598
+ stroke: "currentColor",
1599
+ strokeWidth: "2",
1600
+ children: [
1601
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
1602
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "16", x2: "12", y2: "12" }),
1603
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "8", x2: "12.01", y2: "8" })
1604
+ ]
1605
+ }
1606
+ ),
1607
+ /* @__PURE__ */ jsx("span", { className: "ds-methodology-note__title", children: titleText })
1608
+ ] }),
1609
+ /* @__PURE__ */ jsx("div", { className: "ds-methodology-note__content", children }),
1610
+ (sources || calculation || sampleSize !== void 0) && /* @__PURE__ */ jsxs("dl", { className: "ds-methodology-note__details", children: [
1611
+ sampleSize !== void 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
1612
+ /* @__PURE__ */ jsx("dt", { children: sampleSizeLabel }),
1613
+ /* @__PURE__ */ jsxs("dd", { children: [
1614
+ "n=",
1615
+ sampleSize.toLocaleString()
1616
+ ] })
1617
+ ] }),
1618
+ sources && sources.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
1619
+ /* @__PURE__ */ jsx("dt", { children: dataSourcesLabel }),
1620
+ /* @__PURE__ */ jsx("dd", { children: sources.join(", ") })
1621
+ ] }),
1622
+ calculation && /* @__PURE__ */ jsxs(Fragment, { children: [
1623
+ /* @__PURE__ */ jsx("dt", { children: calculationLabel }),
1624
+ /* @__PURE__ */ jsx("dd", { children: calculation })
1625
+ ] })
1626
+ ] })
1627
+ ]
1628
+ }
1629
+ );
1630
+ }
1631
+ );
1632
+ MethodologyNote.displayName = "MethodologyNote";
1633
+ var CaveatBlock = React2.forwardRef(
1634
+ ({
1635
+ title = "Important Caveat",
1636
+ children,
1637
+ severity = "warning",
1638
+ confidence,
1639
+ forceShow = false,
1640
+ className,
1641
+ ...props
1642
+ }, ref) => {
1643
+ const { features } = useReportMode();
1644
+ const shouldShow = forceShow || features.showMethodology || confidence !== void 0 && confidence < 70;
1645
+ if (!shouldShow) {
1646
+ return null;
1647
+ }
1648
+ const renderIcon = () => {
1649
+ if (severity === "critical") {
1650
+ return /* @__PURE__ */ jsxs(
1651
+ "svg",
1652
+ {
1653
+ width: "18",
1654
+ height: "18",
1655
+ viewBox: "0 0 24 24",
1656
+ fill: "none",
1657
+ stroke: "currentColor",
1658
+ strokeWidth: "2",
1659
+ children: [
1660
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
1661
+ /* @__PURE__ */ jsx("line", { x1: "15", y1: "9", x2: "9", y2: "15" }),
1662
+ /* @__PURE__ */ jsx("line", { x1: "9", y1: "9", x2: "15", y2: "15" })
1663
+ ]
1664
+ }
1665
+ );
1666
+ }
1667
+ if (severity === "info") {
1668
+ return /* @__PURE__ */ jsxs(
1669
+ "svg",
1670
+ {
1671
+ width: "18",
1672
+ height: "18",
1673
+ viewBox: "0 0 24 24",
1674
+ fill: "none",
1675
+ stroke: "currentColor",
1676
+ strokeWidth: "2",
1677
+ children: [
1678
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
1679
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "16", x2: "12", y2: "12" }),
1680
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "8", x2: "12.01", y2: "8" })
1681
+ ]
1682
+ }
1683
+ );
1684
+ }
1685
+ return /* @__PURE__ */ jsxs(
1686
+ "svg",
1687
+ {
1688
+ width: "18",
1689
+ height: "18",
1690
+ viewBox: "0 0 24 24",
1691
+ fill: "none",
1692
+ stroke: "currentColor",
1693
+ strokeWidth: "2",
1694
+ children: [
1695
+ /* @__PURE__ */ 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" }),
1696
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "9", x2: "12", y2: "13" }),
1697
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
1698
+ ]
1699
+ }
1700
+ );
1701
+ };
1702
+ return /* @__PURE__ */ jsxs(
1703
+ "aside",
1704
+ {
1705
+ ref,
1706
+ className: clsx12("ds-caveat-block", `ds-caveat-block--${severity}`, className),
1707
+ role: "note",
1708
+ "aria-label": title,
1709
+ ...props,
1710
+ children: [
1711
+ /* @__PURE__ */ jsxs("div", { className: "ds-caveat-block__header", children: [
1712
+ /* @__PURE__ */ jsx("span", { className: "ds-caveat-block__icon", children: renderIcon() }),
1713
+ /* @__PURE__ */ jsx("span", { className: "ds-caveat-block__title", children: title }),
1714
+ confidence !== void 0 && /* @__PURE__ */ jsxs("span", { className: "ds-caveat-block__confidence", children: [
1715
+ confidence,
1716
+ "% confidence"
1717
+ ] })
1718
+ ] }),
1719
+ /* @__PURE__ */ jsx("div", { className: "ds-caveat-block__content", children })
1720
+ ]
1721
+ }
1722
+ );
1723
+ }
1724
+ );
1725
+ CaveatBlock.displayName = "CaveatBlock";
1726
+ var KeyMetric = React2.forwardRef(
1727
+ ({
1728
+ title,
1729
+ value,
1730
+ prefix,
1731
+ suffix,
1732
+ trend,
1733
+ secondary,
1734
+ sampleSize,
1735
+ confidence,
1736
+ onClick,
1737
+ loading,
1738
+ size = "md",
1739
+ className,
1740
+ ...props
1741
+ }, ref) => {
1742
+ const { features } = useReportMode();
1743
+ const { isValid } = useDataState({
1744
+ sampleSize: sampleSize ?? 100,
1745
+ requiredSize: 30
1746
+ });
1747
+ const isClickable = onClick && !loading;
1748
+ const formatValue = (val) => {
1749
+ if (typeof val === "number") {
1750
+ return val.toLocaleString();
1751
+ }
1752
+ return val;
1753
+ };
1754
+ const getTrendIcon = (direction) => {
1755
+ switch (direction) {
1756
+ case "up":
1757
+ return "\u2191";
1758
+ case "down":
1759
+ return "\u2193";
1760
+ default:
1761
+ return "\u2192";
1762
+ }
1763
+ };
1764
+ const Component = isClickable ? "button" : "div";
1765
+ return /* @__PURE__ */ jsxs(
1766
+ Component,
1767
+ {
1768
+ ref,
1769
+ className: clsx12(
1770
+ "ds-key-metric",
1771
+ `ds-key-metric--${size}`,
1772
+ loading && "ds-key-metric--loading",
1773
+ isClickable && "ds-key-metric--clickable",
1774
+ !isValid && "ds-key-metric--invalid",
1775
+ className
1776
+ ),
1777
+ onClick: isClickable ? onClick : void 0,
1778
+ type: isClickable ? "button" : void 0,
1779
+ ...props,
1780
+ children: [
1781
+ /* @__PURE__ */ jsxs("div", { className: "ds-key-metric__header", children: [
1782
+ /* @__PURE__ */ jsx("span", { className: "ds-key-metric__title", children: title }),
1783
+ features.showConfidenceScores && confidence !== void 0 && /* @__PURE__ */ jsxs("span", { className: "ds-key-metric__confidence", children: [
1784
+ confidence,
1785
+ "%"
1786
+ ] })
1787
+ ] }),
1788
+ /* @__PURE__ */ jsxs("div", { className: "ds-key-metric__value-row", children: [
1789
+ /* @__PURE__ */ jsxs("span", { className: "ds-key-metric__value", children: [
1790
+ prefix && /* @__PURE__ */ jsx("span", { className: "ds-key-metric__prefix", children: prefix }),
1791
+ loading ? "\u2014" : formatValue(value),
1792
+ suffix && /* @__PURE__ */ jsx("span", { className: "ds-key-metric__suffix", children: suffix })
1793
+ ] }),
1794
+ trend && /* @__PURE__ */ jsxs(
1795
+ "span",
1796
+ {
1797
+ className: clsx12("ds-key-metric__trend", `ds-key-metric__trend--${trend.direction}`),
1798
+ children: [
1799
+ /* @__PURE__ */ jsx("span", { className: "ds-key-metric__trend-icon", children: getTrendIcon(trend.direction) }),
1800
+ /* @__PURE__ */ jsxs("span", { className: "ds-key-metric__trend-value", children: [
1801
+ Math.abs(trend.value),
1802
+ "%"
1803
+ ] }),
1804
+ trend.label && /* @__PURE__ */ jsx("span", { className: "ds-key-metric__trend-label", children: trend.label })
1805
+ ]
1806
+ }
1807
+ )
1808
+ ] }),
1809
+ secondary && /* @__PURE__ */ jsxs("div", { className: "ds-key-metric__secondary", children: [
1810
+ /* @__PURE__ */ jsxs("span", { className: "ds-key-metric__secondary-label", children: [
1811
+ secondary.label,
1812
+ ":"
1813
+ ] }),
1814
+ /* @__PURE__ */ jsx("span", { className: "ds-key-metric__secondary-value", children: formatValue(secondary.value) })
1815
+ ] }),
1816
+ features.showMethodology && sampleSize !== void 0 && /* @__PURE__ */ jsxs("div", { className: "ds-key-metric__sample", children: [
1817
+ "n=",
1818
+ sampleSize.toLocaleString()
1819
+ ] })
1820
+ ]
1821
+ }
1822
+ );
1823
+ }
1824
+ );
1825
+ KeyMetric.displayName = "KeyMetric";
1826
+ var TrendIndicator = React2.forwardRef(
1827
+ ({
1828
+ value,
1829
+ direction: directionOverride,
1830
+ positiveIsGood = true,
1831
+ showIcon = true,
1832
+ showPercent = true,
1833
+ size = "md",
1834
+ className,
1835
+ ...props
1836
+ }, ref) => {
1837
+ const direction = directionOverride ?? (value > 0 ? "up" : value < 0 ? "down" : "neutral");
1838
+ const isGood = positiveIsGood ? direction === "up" : direction === "down";
1839
+ const isBad = positiveIsGood ? direction === "down" : direction === "up";
1840
+ const getIcon = () => {
1841
+ switch (direction) {
1842
+ case "up":
1843
+ return /* @__PURE__ */ jsx(
1844
+ "svg",
1845
+ {
1846
+ width: "12",
1847
+ height: "12",
1848
+ viewBox: "0 0 24 24",
1849
+ fill: "none",
1850
+ stroke: "currentColor",
1851
+ strokeWidth: "3",
1852
+ children: /* @__PURE__ */ jsx("polyline", { points: "18,15 12,9 6,15" })
1853
+ }
1854
+ );
1855
+ case "down":
1856
+ return /* @__PURE__ */ jsx(
1857
+ "svg",
1858
+ {
1859
+ width: "12",
1860
+ height: "12",
1861
+ viewBox: "0 0 24 24",
1862
+ fill: "none",
1863
+ stroke: "currentColor",
1864
+ strokeWidth: "3",
1865
+ children: /* @__PURE__ */ jsx("polyline", { points: "6,9 12,15 18,9" })
1866
+ }
1867
+ );
1868
+ default:
1869
+ return /* @__PURE__ */ jsx(
1870
+ "svg",
1871
+ {
1872
+ width: "12",
1873
+ height: "12",
1874
+ viewBox: "0 0 24 24",
1875
+ fill: "none",
1876
+ stroke: "currentColor",
1877
+ strokeWidth: "3",
1878
+ children: /* @__PURE__ */ jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
1879
+ }
1880
+ );
1881
+ }
1882
+ };
1883
+ return /* @__PURE__ */ jsxs(
1884
+ "span",
1885
+ {
1886
+ ref,
1887
+ className: clsx12(
1888
+ "ds-trend-indicator",
1889
+ `ds-trend-indicator--${size}`,
1890
+ `ds-trend-indicator--${direction}`,
1891
+ isGood && "ds-trend-indicator--good",
1892
+ isBad && "ds-trend-indicator--bad",
1893
+ className
1894
+ ),
1895
+ "aria-label": `${direction === "up" ? "Increased" : direction === "down" ? "Decreased" : "No change"} by ${Math.abs(value)}%`,
1896
+ ...props,
1897
+ children: [
1898
+ showIcon && /* @__PURE__ */ jsx("span", { className: "ds-trend-indicator__icon", children: getIcon() }),
1899
+ /* @__PURE__ */ jsxs("span", { className: "ds-trend-indicator__value", children: [
1900
+ value > 0 && "+",
1901
+ value.toFixed(1),
1902
+ showPercent && "%"
1903
+ ] })
1904
+ ]
1905
+ }
1906
+ );
1907
+ }
1908
+ );
1909
+ TrendIndicator.displayName = "TrendIndicator";
1910
+ function Select({
1911
+ value,
1912
+ defaultValue,
1913
+ onValueChange,
1914
+ disabled,
1915
+ required,
1916
+ name,
1917
+ items,
1918
+ children
1919
+ }) {
1920
+ return /* @__PURE__ */ jsx(
1921
+ Select$1.Root,
1922
+ {
1923
+ value,
1924
+ defaultValue,
1925
+ onValueChange: onValueChange ? (val) => onValueChange(val) : void 0,
1926
+ disabled,
1927
+ required,
1928
+ name,
1929
+ items,
1930
+ children
1931
+ }
1932
+ );
1933
+ }
1934
+ Select.displayName = "Select";
1935
+ var SelectTrigger = React2.forwardRef(
1936
+ ({ className, placeholder = "Select...", size = "md", ...props }, ref) => {
1937
+ return /* @__PURE__ */ jsx("div", { className: "ds-select__trigger-wrapper", children: /* @__PURE__ */ jsxs(
1938
+ Select$1.Trigger,
1939
+ {
1940
+ ref,
1941
+ className: clsx12("ds-select__trigger", `ds-select__trigger--${size}`, className),
1942
+ "aria-label": props["aria-label"] || (typeof placeholder === "string" ? placeholder : "Select"),
1943
+ ...props,
1944
+ children: [
1945
+ /* @__PURE__ */ jsx(Select$1.Value, { className: "ds-select__value", placeholder }),
1946
+ /* @__PURE__ */ jsx(Select$1.Icon, { className: "ds-select__icon", "aria-hidden": true, children: /* @__PURE__ */ jsx(ChevronDownIcon, {}) })
1947
+ ]
1948
+ }
1949
+ ) });
1950
+ }
1951
+ );
1952
+ SelectTrigger.displayName = "SelectTrigger";
1953
+ var SelectContent = React2.forwardRef(
1954
+ ({ className, side = "bottom", sideOffset = 4, align = "start", children, ...props }, ref) => {
1955
+ return /* @__PURE__ */ jsx(Select$1.Portal, { children: /* @__PURE__ */ jsx(
1956
+ Select$1.Positioner,
1957
+ {
1958
+ side,
1959
+ sideOffset,
1960
+ align,
1961
+ alignItemWithTrigger: false,
1962
+ children: /* @__PURE__ */ jsx(Select$1.Popup, { ref, className: clsx12("ds-select__content", className), ...props, children: /* @__PURE__ */ jsx(Select$1.List, { className: "ds-select__list", children }) })
1963
+ }
1964
+ ) });
1965
+ }
1966
+ );
1967
+ SelectContent.displayName = "SelectContent";
1968
+ var SelectItem = React2.forwardRef(
1969
+ ({ className, value, children, disabled, ...props }, ref) => {
1970
+ return /* @__PURE__ */ jsxs(
1971
+ Select$1.Item,
1972
+ {
1973
+ ref,
1974
+ value,
1975
+ disabled,
1976
+ className: clsx12("ds-select__item", className),
1977
+ ...props,
1978
+ children: [
1979
+ /* @__PURE__ */ jsx(Select$1.ItemIndicator, { className: "ds-select__item-indicator", children: /* @__PURE__ */ jsx(CheckIcon, {}) }),
1980
+ /* @__PURE__ */ jsx(Select$1.ItemText, { children })
1981
+ ]
1982
+ }
1983
+ );
1984
+ }
1985
+ );
1986
+ SelectItem.displayName = "SelectItem";
1987
+ var SelectGroup = React2.forwardRef(
1988
+ ({ className, label, children, ...props }, ref) => {
1989
+ return /* @__PURE__ */ jsxs(Select$1.Group, { ref, className: clsx12("ds-select__group", className), ...props, children: [
1990
+ label && /* @__PURE__ */ jsx(Select$1.GroupLabel, { className: "ds-select__group-label", children: label }),
1991
+ children
1992
+ ] });
1993
+ }
1994
+ );
1995
+ SelectGroup.displayName = "SelectGroup";
1996
+ var SelectSeparator = React2.forwardRef(({ className, ...props }, ref) => {
1997
+ return /* @__PURE__ */ jsx("div", { ref, className: clsx12("ds-select__separator", className), ...props });
1998
+ });
1999
+ SelectSeparator.displayName = "SelectSeparator";
2000
+ function ChevronDownIcon() {
2001
+ return /* @__PURE__ */ jsx(
2002
+ "svg",
2003
+ {
2004
+ xmlns: "http://www.w3.org/2000/svg",
2005
+ width: "16",
2006
+ height: "16",
2007
+ viewBox: "0 0 24 24",
2008
+ fill: "none",
2009
+ stroke: "currentColor",
2010
+ strokeWidth: "2",
2011
+ strokeLinecap: "round",
2012
+ strokeLinejoin: "round",
2013
+ children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })
2014
+ }
2015
+ );
2016
+ }
2017
+ function CheckIcon() {
2018
+ return /* @__PURE__ */ jsx(
2019
+ "svg",
2020
+ {
2021
+ xmlns: "http://www.w3.org/2000/svg",
2022
+ width: "14",
2023
+ height: "14",
2024
+ viewBox: "0 0 24 24",
2025
+ fill: "none",
2026
+ stroke: "currentColor",
2027
+ strokeWidth: "2",
2028
+ strokeLinecap: "round",
2029
+ strokeLinejoin: "round",
2030
+ children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" })
2031
+ }
2032
+ );
2033
+ }
2034
+ var DropdownMenu = Menu.Root;
2035
+ var DropdownMenuTrigger = React2.forwardRef(({ className, ...props }, ref) => {
2036
+ return /* @__PURE__ */ jsx(
2037
+ Menu.Trigger,
2038
+ {
2039
+ ref,
2040
+ className: clsx12("ds-dropdown-menu__trigger", className),
2041
+ ...props
2042
+ }
2043
+ );
2044
+ });
2045
+ DropdownMenuTrigger.displayName = "DropdownMenuTrigger";
2046
+ var DropdownMenuContent = React2.forwardRef(
2047
+ ({ className, side = "bottom", align = "start", sideOffset = 4, alignOffset = 0, ...props }, ref) => {
2048
+ return /* @__PURE__ */ jsx(Menu.Portal, { children: /* @__PURE__ */ jsx(
2049
+ Menu.Positioner,
2050
+ {
2051
+ side,
2052
+ align,
2053
+ sideOffset,
2054
+ alignOffset,
2055
+ children: /* @__PURE__ */ jsx(
2056
+ Menu.Popup,
2057
+ {
2058
+ ref,
2059
+ className: clsx12("ds-dropdown-menu__content", className),
2060
+ ...props
2061
+ }
2062
+ )
2063
+ }
2064
+ ) });
2065
+ }
2066
+ );
2067
+ DropdownMenuContent.displayName = "DropdownMenuContent";
2068
+ var DropdownMenuItem = React2.forwardRef(
2069
+ ({ className, ...props }, ref) => {
2070
+ return /* @__PURE__ */ jsx(Menu.Item, { ref, className: clsx12("ds-dropdown-menu__item", className), ...props });
2071
+ }
2072
+ );
2073
+ DropdownMenuItem.displayName = "DropdownMenuItem";
2074
+ var DropdownMenuSeparator = React2.forwardRef(({ className, ...props }, ref) => {
2075
+ return /* @__PURE__ */ jsx("div", { ref, className: clsx12("ds-dropdown-menu__separator", className), ...props });
2076
+ });
2077
+ DropdownMenuSeparator.displayName = "DropdownMenuSeparator";
2078
+ var DropdownMenuLabel = React2.forwardRef(({ className, ...props }, ref) => {
2079
+ return /* @__PURE__ */ jsx("div", { ref, className: clsx12("ds-dropdown-menu__label", className), ...props });
2080
+ });
2081
+ DropdownMenuLabel.displayName = "DropdownMenuLabel";
2082
+ var DEFAULT_OPTIONS = [
2083
+ { format: "pdf", label: "PDF Document", description: "Best for sharing reports" },
2084
+ { format: "pptx", label: "PowerPoint", description: "Editable presentation" },
2085
+ { format: "xlsx", label: "Excel Spreadsheet", description: "Data with charts" },
2086
+ { format: "csv", label: "CSV Data", description: "Raw data only" },
2087
+ { format: "png", label: "PNG Image", description: "Chart screenshot" },
2088
+ { format: "json", label: "JSON", description: "Developer format" }
2089
+ ];
2090
+ var FORMAT_ICONS = {
2091
+ pdf: /* @__PURE__ */ jsx(PdfIcon, {}),
2092
+ csv: /* @__PURE__ */ jsx(CsvIcon, {}),
2093
+ xlsx: /* @__PURE__ */ jsx(ExcelIcon, {}),
2094
+ pptx: /* @__PURE__ */ jsx(PptIcon, {}),
2095
+ png: /* @__PURE__ */ jsx(ImageIcon, {}),
2096
+ json: /* @__PURE__ */ jsx(JsonIcon, {})
2097
+ };
2098
+ function ExportMenu({
2099
+ options = DEFAULT_OPTIONS,
2100
+ onExport,
2101
+ isExporting = false,
2102
+ label = "Export",
2103
+ size = "md",
2104
+ variant = "secondary",
2105
+ className,
2106
+ disabled
2107
+ }) {
2108
+ const documentOptions = options.filter((o) => ["pdf", "pptx"].includes(o.format));
2109
+ const dataOptions = options.filter((o) => ["xlsx", "csv", "json"].includes(o.format));
2110
+ const imageOptions = options.filter((o) => ["png"].includes(o.format));
2111
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
2112
+ /* @__PURE__ */ jsx(
2113
+ DropdownMenuTrigger,
2114
+ {
2115
+ className: clsx12(
2116
+ "ds-export-menu__trigger",
2117
+ "ds-button",
2118
+ `ds-button--${variant}`,
2119
+ `ds-button--${size}`,
2120
+ className
2121
+ ),
2122
+ disabled: disabled || isExporting,
2123
+ children: isExporting ? /* @__PURE__ */ jsxs(Fragment, { children: [
2124
+ /* @__PURE__ */ jsx(LoadingIcon, {}),
2125
+ "Exporting..."
2126
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
2127
+ /* @__PURE__ */ jsx(ExportIcon, {}),
2128
+ label
2129
+ ] })
2130
+ }
2131
+ ),
2132
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { side: "bottom", align: "end", sideOffset: 4, children: [
2133
+ documentOptions.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
2134
+ /* @__PURE__ */ jsx(DropdownMenuLabel, { children: "Documents" }),
2135
+ documentOptions.map((option) => /* @__PURE__ */ jsxs(
2136
+ DropdownMenuItem,
2137
+ {
2138
+ disabled: option.disabled,
2139
+ onClick: () => onExport(option.format),
2140
+ children: [
2141
+ /* @__PURE__ */ jsx("span", { className: "ds-export-menu__item-icon", children: FORMAT_ICONS[option.format] }),
2142
+ /* @__PURE__ */ jsxs("span", { className: "ds-export-menu__item-content", children: [
2143
+ /* @__PURE__ */ jsx("span", { className: "ds-export-menu__item-label", children: option.label }),
2144
+ option.description && /* @__PURE__ */ jsx("span", { className: "ds-export-menu__item-description", children: option.description })
2145
+ ] })
2146
+ ]
2147
+ },
2148
+ option.format
2149
+ ))
2150
+ ] }),
2151
+ documentOptions.length > 0 && dataOptions.length > 0 && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
2152
+ dataOptions.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
2153
+ /* @__PURE__ */ jsx(DropdownMenuLabel, { children: "Data" }),
2154
+ dataOptions.map((option) => /* @__PURE__ */ jsxs(
2155
+ DropdownMenuItem,
2156
+ {
2157
+ disabled: option.disabled,
2158
+ onClick: () => onExport(option.format),
2159
+ children: [
2160
+ /* @__PURE__ */ jsx("span", { className: "ds-export-menu__item-icon", children: FORMAT_ICONS[option.format] }),
2161
+ /* @__PURE__ */ jsxs("span", { className: "ds-export-menu__item-content", children: [
2162
+ /* @__PURE__ */ jsx("span", { className: "ds-export-menu__item-label", children: option.label }),
2163
+ option.description && /* @__PURE__ */ jsx("span", { className: "ds-export-menu__item-description", children: option.description })
2164
+ ] })
2165
+ ]
2166
+ },
2167
+ option.format
2168
+ ))
2169
+ ] }),
2170
+ imageOptions.length > 0 && (dataOptions.length > 0 || documentOptions.length > 0) && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
2171
+ imageOptions.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
2172
+ /* @__PURE__ */ jsx(DropdownMenuLabel, { children: "Image" }),
2173
+ imageOptions.map((option) => /* @__PURE__ */ jsxs(
2174
+ DropdownMenuItem,
2175
+ {
2176
+ disabled: option.disabled,
2177
+ onClick: () => onExport(option.format),
2178
+ children: [
2179
+ /* @__PURE__ */ jsx("span", { className: "ds-export-menu__item-icon", children: FORMAT_ICONS[option.format] }),
2180
+ /* @__PURE__ */ jsxs("span", { className: "ds-export-menu__item-content", children: [
2181
+ /* @__PURE__ */ jsx("span", { className: "ds-export-menu__item-label", children: option.label }),
2182
+ option.description && /* @__PURE__ */ jsx("span", { className: "ds-export-menu__item-description", children: option.description })
2183
+ ] })
2184
+ ]
2185
+ },
2186
+ option.format
2187
+ ))
2188
+ ] })
2189
+ ] })
2190
+ ] });
2191
+ }
2192
+ ExportMenu.displayName = "ExportMenu";
2193
+ function ExportIcon() {
2194
+ return /* @__PURE__ */ jsxs(
2195
+ "svg",
2196
+ {
2197
+ xmlns: "http://www.w3.org/2000/svg",
2198
+ width: "16",
2199
+ height: "16",
2200
+ viewBox: "0 0 24 24",
2201
+ fill: "none",
2202
+ stroke: "currentColor",
2203
+ strokeWidth: "2",
2204
+ strokeLinecap: "round",
2205
+ strokeLinejoin: "round",
2206
+ children: [
2207
+ /* @__PURE__ */ jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
2208
+ /* @__PURE__ */ jsx("polyline", { points: "17 8 12 3 7 8" }),
2209
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
2210
+ ]
2211
+ }
2212
+ );
2213
+ }
2214
+ function LoadingIcon() {
2215
+ return /* @__PURE__ */ jsx(
2216
+ "svg",
2217
+ {
2218
+ className: "ds-export-menu__loading-icon",
2219
+ xmlns: "http://www.w3.org/2000/svg",
2220
+ width: "16",
2221
+ height: "16",
2222
+ viewBox: "0 0 24 24",
2223
+ fill: "none",
2224
+ stroke: "currentColor",
2225
+ strokeWidth: "2",
2226
+ strokeLinecap: "round",
2227
+ strokeLinejoin: "round",
2228
+ children: /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" })
2229
+ }
2230
+ );
2231
+ }
2232
+ function PdfIcon() {
2233
+ return /* @__PURE__ */ jsxs(
2234
+ "svg",
2235
+ {
2236
+ xmlns: "http://www.w3.org/2000/svg",
2237
+ width: "16",
2238
+ height: "16",
2239
+ viewBox: "0 0 24 24",
2240
+ fill: "none",
2241
+ stroke: "currentColor",
2242
+ strokeWidth: "2",
2243
+ strokeLinecap: "round",
2244
+ strokeLinejoin: "round",
2245
+ children: [
2246
+ /* @__PURE__ */ jsx("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
2247
+ /* @__PURE__ */ jsx("polyline", { points: "14 2 14 8 20 8" }),
2248
+ /* @__PURE__ */ jsx("line", { x1: "16", y1: "13", x2: "8", y2: "13" }),
2249
+ /* @__PURE__ */ jsx("line", { x1: "16", y1: "17", x2: "8", y2: "17" }),
2250
+ /* @__PURE__ */ jsx("polyline", { points: "10 9 9 9 8 9" })
2251
+ ]
2252
+ }
2253
+ );
2254
+ }
2255
+ function CsvIcon() {
2256
+ return /* @__PURE__ */ jsxs(
2257
+ "svg",
2258
+ {
2259
+ xmlns: "http://www.w3.org/2000/svg",
2260
+ width: "16",
2261
+ height: "16",
2262
+ viewBox: "0 0 24 24",
2263
+ fill: "none",
2264
+ stroke: "currentColor",
2265
+ strokeWidth: "2",
2266
+ strokeLinecap: "round",
2267
+ strokeLinejoin: "round",
2268
+ children: [
2269
+ /* @__PURE__ */ jsx("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
2270
+ /* @__PURE__ */ jsx("polyline", { points: "14 2 14 8 20 8" }),
2271
+ /* @__PURE__ */ jsx("line", { x1: "8", y1: "13", x2: "16", y2: "13" }),
2272
+ /* @__PURE__ */ jsx("line", { x1: "8", y1: "17", x2: "16", y2: "17" })
2273
+ ]
2274
+ }
2275
+ );
2276
+ }
2277
+ function ExcelIcon() {
2278
+ return /* @__PURE__ */ jsxs(
2279
+ "svg",
2280
+ {
2281
+ xmlns: "http://www.w3.org/2000/svg",
2282
+ width: "16",
2283
+ height: "16",
2284
+ viewBox: "0 0 24 24",
2285
+ fill: "none",
2286
+ stroke: "currentColor",
2287
+ strokeWidth: "2",
2288
+ strokeLinecap: "round",
2289
+ strokeLinejoin: "round",
2290
+ children: [
2291
+ /* @__PURE__ */ jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
2292
+ /* @__PURE__ */ jsx("path", { d: "M3 9h18" }),
2293
+ /* @__PURE__ */ jsx("path", { d: "M3 15h18" }),
2294
+ /* @__PURE__ */ jsx("path", { d: "M9 3v18" }),
2295
+ /* @__PURE__ */ jsx("path", { d: "M15 3v18" })
2296
+ ]
2297
+ }
2298
+ );
2299
+ }
2300
+ function PptIcon() {
2301
+ return /* @__PURE__ */ jsxs(
2302
+ "svg",
2303
+ {
2304
+ xmlns: "http://www.w3.org/2000/svg",
2305
+ width: "16",
2306
+ height: "16",
2307
+ viewBox: "0 0 24 24",
2308
+ fill: "none",
2309
+ stroke: "currentColor",
2310
+ strokeWidth: "2",
2311
+ strokeLinecap: "round",
2312
+ strokeLinejoin: "round",
2313
+ children: [
2314
+ /* @__PURE__ */ jsx("rect", { x: "2", y: "3", width: "20", height: "14", rx: "2" }),
2315
+ /* @__PURE__ */ jsx("line", { x1: "8", y1: "21", x2: "16", y2: "21" }),
2316
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "17", x2: "12", y2: "21" })
2317
+ ]
2318
+ }
2319
+ );
2320
+ }
2321
+ function ImageIcon() {
2322
+ return /* @__PURE__ */ jsxs(
2323
+ "svg",
2324
+ {
2325
+ xmlns: "http://www.w3.org/2000/svg",
2326
+ width: "16",
2327
+ height: "16",
2328
+ viewBox: "0 0 24 24",
2329
+ fill: "none",
2330
+ stroke: "currentColor",
2331
+ strokeWidth: "2",
2332
+ strokeLinecap: "round",
2333
+ strokeLinejoin: "round",
2334
+ children: [
2335
+ /* @__PURE__ */ jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
2336
+ /* @__PURE__ */ jsx("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
2337
+ /* @__PURE__ */ jsx("path", { d: "m21 15-5-5L5 21" })
2338
+ ]
2339
+ }
2340
+ );
2341
+ }
2342
+ function JsonIcon() {
2343
+ return /* @__PURE__ */ jsxs(
2344
+ "svg",
2345
+ {
2346
+ xmlns: "http://www.w3.org/2000/svg",
2347
+ width: "16",
2348
+ height: "16",
2349
+ viewBox: "0 0 24 24",
2350
+ fill: "none",
2351
+ stroke: "currentColor",
2352
+ strokeWidth: "2",
2353
+ strokeLinecap: "round",
2354
+ strokeLinejoin: "round",
2355
+ children: [
2356
+ /* @__PURE__ */ jsx("path", { d: "M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5a2 2 0 0 0 2 2h1" }),
2357
+ /* @__PURE__ */ jsx("path", { d: "M16 21h1a2 2 0 0 0 2-2v-5a2 2 0 0 1 2-2 2 2 0 0 1-2-2V5a2 2 0 0 0-2-2h-1" })
2358
+ ]
2359
+ }
2360
+ );
2361
+ }
2362
+
2363
+ export { ANALYST_MODE, ANALYTICAL_STATE_CONFIG, CHART_REGISTRY, CONFIDENCE_THRESHOLDS, CaveatBlock, ConfidenceIndicator, DataCoverageBadge, DataStateIndicator, EXECUTIVE_MODE, EvidenceGroup, ExecutiveThesis, ExportMenu, INSIGHT_TYPE_CONTRACTS, INTENT_CHART_FAMILIES, InsightBlock, KeyMetric, MINIMUM_SAMPLE_SIZES, MethodologyNote, ReportModeProvider, ReportShell, Select, SelectContent, SelectGroup, SelectItem, SelectSeparator, SelectTrigger, TrendIndicator, calculateCompleteness, calculateConfidence, calculateNormalizedVariance, calculateRecency, canSwitchChart, getAllowedSwitchTargets, getConfidenceLevel, getConfidenceThreshold, getDefaultChartForIntent, getMVPChartsForIntent, suggestChartType, useChartData, useDataState, useReportMode, validateChartData, validateReportStructure };
4
2364
  //# sourceMappingURL=out.js.map
5
2365
  //# sourceMappingURL=index.js.map