@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,1449 +0,0 @@
1
- 'use strict';
2
-
3
- var React2 = require('react');
4
- var jsxRuntime = require('react/jsx-runtime');
5
- var clsx = require('clsx');
6
-
7
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
-
9
- var React2__default = /*#__PURE__*/_interopDefault(React2);
10
- var clsx__default = /*#__PURE__*/_interopDefault(clsx);
11
-
12
- // src/report-engine/constants.ts
13
- var EXECUTIVE_MODE = {
14
- mode: "executive",
15
- features: {
16
- showMethodology: false,
17
- showConfidenceScores: false,
18
- showRawData: false,
19
- showStatisticalTests: false,
20
- chartDetailLevel: "summary",
21
- maxInsightsShown: 5,
22
- allowDrilldown: false
23
- }
24
- };
25
- var ANALYST_MODE = {
26
- mode: "analyst",
27
- features: {
28
- showMethodology: true,
29
- showConfidenceScores: true,
30
- showRawData: true,
31
- showStatisticalTests: true,
32
- chartDetailLevel: "detailed",
33
- maxInsightsShown: 20,
34
- allowDrilldown: true
35
- }
36
- };
37
- var CONFIDENCE_THRESHOLDS = [
38
- { level: "high", min: 90, max: 100, label: "High Confidence", color: "var(--status-success)" },
39
- {
40
- level: "moderate",
41
- min: 70,
42
- max: 89,
43
- label: "Moderate Confidence",
44
- color: "var(--status-info)"
45
- },
46
- { level: "low", min: 50, max: 69, label: "Low Confidence", color: "var(--status-warning)" },
47
- {
48
- level: "insufficient",
49
- min: 0,
50
- max: 49,
51
- label: "Insufficient Data",
52
- color: "var(--status-error)"
53
- }
54
- ];
55
- var MINIMUM_SAMPLE_SIZES = {
56
- overall: 30,
57
- segment: 30,
58
- mbtiType: 50,
59
- correlation: 100,
60
- timeSeries: 7
61
- };
62
- var INSIGHT_TYPE_CONTRACTS = {
63
- "performance-delta": {
64
- type: "performance-delta",
65
- allowedCharts: ["BarChart", "LineChart", "KeyMetric"],
66
- requiredFields: ["metric_name", "current_value", "previous_value", "time_period"],
67
- minSampleSize: 30,
68
- headlinePattern: "{metric} {direction} by {delta}% {timeframe}",
69
- recommendationFormats: ["maintain-strategy", "investigate-decline", "scale-success"]
70
- },
71
- "behavioral-correlation": {
72
- type: "behavioral-correlation",
73
- allowedCharts: ["HeatmapChart", "BarChart"],
74
- requiredFields: ["variable_a", "variable_b", "correlation_coefficient"],
75
- minSampleSize: 100,
76
- headlinePattern: "{variable_a} correlates with {variable_b}",
77
- recommendationFormats: ["leverage-correlation", "investigate-causation"]
78
- },
79
- "funnel-leakage": {
80
- type: "funnel-leakage",
81
- allowedCharts: ["FunnelChart", "BarChart"],
82
- requiredFields: ["stages", "stage_counts", "drop_rates"],
83
- minSampleSize: 50,
84
- headlinePattern: "{drop_rate}% drop-off at {stage}",
85
- recommendationFormats: ["optimize-stage", "remove-friction"]
86
- },
87
- "audience-mismatch": {
88
- type: "audience-mismatch",
89
- allowedCharts: ["BarChart", "PieChart"],
90
- requiredFields: ["target_audience", "actual_audience", "overlap_percentage"],
91
- minSampleSize: 50,
92
- headlinePattern: "Target audience differs by {mismatch}%",
93
- recommendationFormats: ["refine-targeting", "expand-audience"]
94
- },
95
- "message-fatigue": {
96
- type: "message-fatigue",
97
- allowedCharts: ["LineChart", "BarChart"],
98
- requiredFields: ["message_sequence", "engagement_rates", "fatigue_point"],
99
- minSampleSize: 100,
100
- headlinePattern: "Engagement drops {drop}% after message {n}",
101
- recommendationFormats: ["reduce-frequency", "vary-content"]
102
- },
103
- "psychological-resonance": {
104
- type: "psychological-resonance",
105
- allowedCharts: ["MBTIRadar", "MBTITypeGrid", "BarChart"],
106
- requiredFields: ["mbti_types", "response_rates", "message_type"],
107
- minSampleSize: 50,
108
- headlinePattern: "{mbti_type} responds {rate}% better to {message_type}",
109
- recommendationFormats: ["personalize-messaging", "segment-by-type"]
110
- },
111
- "timing-pattern": {
112
- type: "timing-pattern",
113
- allowedCharts: ["HeatmapChart", "LineChart"],
114
- requiredFields: ["time_slots", "engagement_rates"],
115
- minSampleSize: 100,
116
- headlinePattern: "Best engagement on {day} at {time}",
117
- recommendationFormats: ["optimize-timing", "schedule-sends"]
118
- },
119
- "segment-outperformance": {
120
- type: "segment-outperformance",
121
- allowedCharts: ["BarChart", "KeyMetric"],
122
- requiredFields: ["segments", "performance_metrics", "baseline"],
123
- minSampleSize: 30,
124
- headlinePattern: "{segment} outperforms by {delta}%",
125
- recommendationFormats: ["double-down", "investigate-success"]
126
- },
127
- "anomaly-detection": {
128
- type: "anomaly-detection",
129
- allowedCharts: ["LineChart", "BarChart"],
130
- requiredFields: ["metric", "expected_value", "actual_value", "deviation"],
131
- minSampleSize: 30,
132
- headlinePattern: "Unusual {direction} in {metric}",
133
- recommendationFormats: ["investigate", "monitor"]
134
- },
135
- "competitive-benchmark": {
136
- type: "competitive-benchmark",
137
- allowedCharts: ["BarChart", "KeyMetric"],
138
- requiredFields: ["metric", "our_value", "benchmark_value"],
139
- minSampleSize: 30,
140
- headlinePattern: "{position} industry benchmark by {delta}%",
141
- recommendationFormats: ["maintain-lead", "close-gap"]
142
- }
143
- };
144
- var ANALYTICAL_STATE_CONFIG = {
145
- VALID: {
146
- label: "Valid",
147
- icon: "check",
148
- color: "var(--status-success)",
149
- action: null
150
- },
151
- INSUFFICIENT_SAMPLE: {
152
- label: "Insufficient Sample",
153
- icon: "alert-triangle",
154
- color: "var(--status-warning)",
155
- action: "Add more data"
156
- },
157
- LOW_CONFIDENCE: {
158
- label: "Low Confidence",
159
- icon: "alert-circle",
160
- color: "var(--status-warning)",
161
- action: "Interpret with caution"
162
- },
163
- PARTIAL_TIME_WINDOW: {
164
- label: "Partial Data",
165
- icon: "clock",
166
- color: "var(--status-info)",
167
- action: "Expand date range"
168
- },
169
- DATA_SKEW_DETECTED: {
170
- label: "Data Skew",
171
- icon: "bar-chart-2",
172
- color: "var(--status-warning)",
173
- action: "Review methodology"
174
- },
175
- CONFLICTING_SIGNALS: {
176
- label: "Conflicting Signals",
177
- icon: "git-merge",
178
- color: "var(--status-error)",
179
- action: "Manual review needed"
180
- },
181
- INFERRED_NOT_OBSERVED: {
182
- label: "AI Generated",
183
- icon: "cpu",
184
- color: "var(--status-info)",
185
- action: "Verify with data"
186
- },
187
- STALE_DATA: {
188
- label: "Stale Data",
189
- icon: "clock",
190
- color: "var(--status-warning)",
191
- action: "Refresh data"
192
- },
193
- FIELD_MISSING: {
194
- label: "Missing Field",
195
- icon: "file-x",
196
- color: "var(--status-error)",
197
- action: "Upload complete data"
198
- },
199
- CALCULATION_ERROR: {
200
- label: "Calculation Error",
201
- icon: "x-circle",
202
- color: "var(--status-error)",
203
- action: "Contact support"
204
- }
205
- };
206
-
207
- // src/report-engine/confidence.ts
208
- function calculateConfidence(params) {
209
- const { sampleSize, requiredSize, completeness, recency, variance, aiInference } = params;
210
- const sampleScore = Math.min(40, sampleSize / requiredSize * 40);
211
- const completenessScore = completeness * 20;
212
- const recencyScore = recency * 20;
213
- const variancePenalty = variance * 10;
214
- const aiPenalty = aiInference ? 10 : 0;
215
- const rawScore = sampleScore + completenessScore + recencyScore - variancePenalty - aiPenalty;
216
- return Math.max(0, Math.min(100, Math.round(rawScore)));
217
- }
218
- function getConfidenceLevel(score) {
219
- const threshold = CONFIDENCE_THRESHOLDS.find((t) => score >= t.min && score <= t.max);
220
- return threshold?.level ?? "insufficient";
221
- }
222
- function getConfidenceThreshold(score) {
223
- return CONFIDENCE_THRESHOLDS.find((t) => score >= t.min && score <= t.max) ?? CONFIDENCE_THRESHOLDS[CONFIDENCE_THRESHOLDS.length - 1];
224
- }
225
- function calculateRecency(dataDate, maxAgeDays = 30) {
226
- const now = /* @__PURE__ */ new Date();
227
- const ageInDays = (now.getTime() - dataDate.getTime()) / (1e3 * 60 * 60 * 24);
228
- if (ageInDays <= 0) return 1;
229
- if (ageInDays >= maxAgeDays) return 0;
230
- return 1 - ageInDays / maxAgeDays;
231
- }
232
- function calculateCompleteness(data, requiredFields) {
233
- if (data.length === 0 || requiredFields.length === 0) return 0;
234
- let totalFields = 0;
235
- let filledFields = 0;
236
- for (const record of data) {
237
- for (const field of requiredFields) {
238
- totalFields++;
239
- const value = record[field];
240
- if (value !== null && value !== void 0 && value !== "") {
241
- filledFields++;
242
- }
243
- }
244
- }
245
- return totalFields > 0 ? filledFields / totalFields : 0;
246
- }
247
- function calculateNormalizedVariance(values) {
248
- if (values.length < 2) return 0;
249
- const mean = values.reduce((a, b) => a + b, 0) / values.length;
250
- const squaredDiffs = values.map((v) => Math.pow(v - mean, 2));
251
- const variance = squaredDiffs.reduce((a, b) => a + b, 0) / values.length;
252
- const stdDev = Math.sqrt(variance);
253
- const cv = mean !== 0 ? stdDev / Math.abs(mean) : 0;
254
- return Math.min(1, cv);
255
- }
256
- var ReportModeContext = React2.createContext(null);
257
- function ReportModeProvider({
258
- mode = "executive",
259
- children,
260
- onModeChange
261
- }) {
262
- const config = mode === "executive" ? EXECUTIVE_MODE : ANALYST_MODE;
263
- const value = React2.useMemo(
264
- () => ({
265
- ...config,
266
- setMode: onModeChange
267
- }),
268
- [config, onModeChange]
269
- );
270
- return /* @__PURE__ */ jsxRuntime.jsx(ReportModeContext.Provider, { value, children });
271
- }
272
- function useReportMode() {
273
- const context = React2.useContext(ReportModeContext);
274
- if (!context) {
275
- return EXECUTIVE_MODE;
276
- }
277
- return context;
278
- }
279
- function useDataState(params) {
280
- const {
281
- sampleSize,
282
- requiredSize = MINIMUM_SAMPLE_SIZES.overall,
283
- completeness = 1,
284
- recency = 1,
285
- variance = 0,
286
- aiInferred = false,
287
- missingFields = [],
288
- staleDays
289
- } = params;
290
- return React2.useMemo(() => {
291
- const confidenceParams = {
292
- sampleSize,
293
- requiredSize,
294
- completeness,
295
- recency,
296
- variance,
297
- aiInference: aiInferred
298
- };
299
- const confidence = calculateConfidence(confidenceParams);
300
- const confidenceLevel = getConfidenceLevel(confidence);
301
- let state = "VALID";
302
- if (missingFields.length > 0) {
303
- state = "FIELD_MISSING";
304
- } else if (sampleSize < requiredSize) {
305
- state = "INSUFFICIENT_SAMPLE";
306
- } else if (staleDays && staleDays > 30) {
307
- state = "STALE_DATA";
308
- } else if (aiInferred) {
309
- state = "INFERRED_NOT_OBSERVED";
310
- } else if (confidence < 50) {
311
- state = "LOW_CONFIDENCE";
312
- } else if (variance > 0.7) {
313
- state = "DATA_SKEW_DETECTED";
314
- } else if (recency < 0.3) {
315
- state = "PARTIAL_TIME_WINDOW";
316
- }
317
- const details = {
318
- sampleSize,
319
- requiredSize,
320
- confidence,
321
- missingFields: missingFields.length > 0 ? missingFields : void 0,
322
- staleDays
323
- };
324
- return {
325
- state,
326
- confidence,
327
- confidenceLevel,
328
- details,
329
- isValid: state === "VALID"
330
- };
331
- }, [
332
- sampleSize,
333
- requiredSize,
334
- completeness,
335
- recency,
336
- variance,
337
- aiInferred,
338
- missingFields,
339
- staleDays
340
- ]);
341
- }
342
- function useChartData({
343
- data,
344
- requiredFields,
345
- minSampleSize = MINIMUM_SAMPLE_SIZES.overall
346
- }) {
347
- return React2.useMemo(() => {
348
- const missingFields = [];
349
- if (data.length > 0) {
350
- const firstRecord = data[0];
351
- for (const field of requiredFields) {
352
- if (!(field in firstRecord)) {
353
- missingFields.push(field);
354
- }
355
- }
356
- }
357
- let completeness = 1;
358
- if (data.length > 0 && requiredFields.length > 0) {
359
- let filled = 0;
360
- let total = 0;
361
- for (const record of data) {
362
- for (const field of requiredFields) {
363
- total++;
364
- const value = record[field];
365
- if (value !== null && value !== void 0 && value !== "") {
366
- filled++;
367
- }
368
- }
369
- }
370
- completeness = total > 0 ? filled / total : 0;
371
- }
372
- let state = "VALID";
373
- let message;
374
- if (missingFields.length > 0) {
375
- state = "FIELD_MISSING";
376
- message = `Missing fields: ${missingFields.join(", ")}`;
377
- } else if (data.length === 0) {
378
- state = "INSUFFICIENT_SAMPLE";
379
- message = "No data available";
380
- } else if (data.length < minSampleSize) {
381
- state = "INSUFFICIENT_SAMPLE";
382
- message = `Sample size ${data.length} is below minimum ${minSampleSize}`;
383
- } else if (completeness < 0.7) {
384
- state = "LOW_CONFIDENCE";
385
- message = `Data completeness is ${Math.round(completeness * 100)}%`;
386
- }
387
- const confidence = calculateConfidence({
388
- sampleSize: data.length,
389
- requiredSize: minSampleSize,
390
- completeness,
391
- recency: 1,
392
- // Assume fresh data if not specified
393
- variance: 0,
394
- aiInference: false
395
- });
396
- const isRenderable = state === "VALID" || state === "LOW_CONFIDENCE";
397
- return {
398
- data,
399
- state,
400
- confidence,
401
- isRenderable,
402
- message
403
- };
404
- }, [data, requiredFields, minSampleSize]);
405
- }
406
-
407
- // src/report-engine/chart-types.ts
408
- var CHART_REGISTRY = {
409
- // ══════════════════════════════════════════════════════════════════════════
410
- // TREND CHARTS (MVP)
411
- // ══════════════════════════════════════════════════════════════════════════
412
- line: {
413
- id: "line",
414
- name: "Line Chart",
415
- description: "Shows trends over time with connected data points",
416
- intent: "trend",
417
- phase: "mvp",
418
- contract: {
419
- requiredDimensions: 1,
420
- requiredMeasures: 1,
421
- minDataPoints: 3,
422
- idealDataPoints: 7,
423
- allowNegativeValues: true,
424
- requireNonZeroTotal: false,
425
- warningThresholds: { sparseData: 3 },
426
- fallback: { type: "show_kpi", message: "Insufficient data for trend visualization" }
427
- },
428
- switchableTo: ["smooth_line", "area", "stacked_area"],
429
- supportsStacking: false,
430
- supportsMultipleSeries: true,
431
- requiresTimeAxis: true
432
- },
433
- smooth_line: {
434
- id: "smooth_line",
435
- name: "Smooth Line Chart",
436
- description: "Curved line chart for smoother trend visualization",
437
- intent: "trend",
438
- phase: "mvp",
439
- contract: {
440
- requiredDimensions: 1,
441
- requiredMeasures: 1,
442
- minDataPoints: 3,
443
- idealDataPoints: 7,
444
- allowNegativeValues: true,
445
- requireNonZeroTotal: false,
446
- warningThresholds: { sparseData: 3 },
447
- fallback: { type: "show_kpi", message: "Insufficient data for trend visualization" }
448
- },
449
- switchableTo: ["line", "area", "stacked_area"],
450
- supportsStacking: false,
451
- supportsMultipleSeries: true,
452
- requiresTimeAxis: true
453
- },
454
- area: {
455
- id: "area",
456
- name: "Area Chart",
457
- description: "Filled area under line, emphasizes volume over time",
458
- intent: "trend",
459
- phase: "mvp",
460
- contract: {
461
- requiredDimensions: 1,
462
- requiredMeasures: 1,
463
- minDataPoints: 3,
464
- idealDataPoints: 7,
465
- allowNegativeValues: false,
466
- requireNonZeroTotal: false,
467
- warningThresholds: { sparseData: 3 },
468
- fallback: { type: "show_kpi", message: "Insufficient data for area visualization" }
469
- },
470
- switchableTo: ["line", "smooth_line", "stacked_area", "area_100pct"],
471
- supportsStacking: true,
472
- supportsMultipleSeries: true,
473
- requiresTimeAxis: true
474
- },
475
- stacked_area: {
476
- id: "stacked_area",
477
- name: "Stacked Area Chart",
478
- description: "Multiple series stacked to show cumulative trends",
479
- intent: "trend",
480
- phase: "mvp",
481
- contract: {
482
- requiredDimensions: 1,
483
- requiredMeasures: 2,
484
- minDataPoints: 3,
485
- idealDataPoints: 7,
486
- allowNegativeValues: false,
487
- requireNonZeroTotal: true,
488
- warningThresholds: { sparseData: 3 },
489
- fallback: { type: "warn", message: "Stacked area requires non-negative values" }
490
- },
491
- switchableTo: ["line", "area", "area_100pct"],
492
- supportsStacking: true,
493
- supportsMultipleSeries: true,
494
- requiresTimeAxis: true
495
- },
496
- area_100pct: {
497
- id: "area_100pct",
498
- name: "100% Stacked Area",
499
- description: "Shows proportional contribution over time",
500
- intent: "trend",
501
- phase: "mvp",
502
- contract: {
503
- requiredDimensions: 1,
504
- requiredMeasures: 2,
505
- minDataPoints: 3,
506
- idealDataPoints: 7,
507
- allowNegativeValues: false,
508
- requireNonZeroTotal: true,
509
- warningThresholds: { sparseData: 3 },
510
- fallback: { type: "warn", message: "100% stacked requires positive totals" }
511
- },
512
- switchableTo: ["stacked_area", "area"],
513
- supportsStacking: true,
514
- supportsMultipleSeries: true,
515
- requiresTimeAxis: true
516
- },
517
- // ══════════════════════════════════════════════════════════════════════════
518
- // COMPARISON CHARTS (MVP)
519
- // ══════════════════════════════════════════════════════════════════════════
520
- bar: {
521
- id: "bar",
522
- name: "Horizontal Bar Chart",
523
- description: "Horizontal bars for comparing categories",
524
- intent: "comparison",
525
- phase: "mvp",
526
- contract: {
527
- requiredDimensions: 1,
528
- requiredMeasures: 1,
529
- minDataPoints: 2,
530
- idealDataPoints: 5,
531
- maxDataPoints: 15,
532
- allowNegativeValues: true,
533
- requireNonZeroTotal: false,
534
- warningThresholds: { tooManyCategories: 12 },
535
- fallback: { type: "aggregate", strategy: "top_n" }
536
- },
537
- switchableTo: ["column", "stacked_bar", "stacked_column"],
538
- supportsStacking: true,
539
- supportsMultipleSeries: true,
540
- requiresTimeAxis: false
541
- },
542
- column: {
543
- id: "column",
544
- name: "Vertical Column Chart",
545
- description: "Vertical bars for comparing categories",
546
- intent: "comparison",
547
- phase: "mvp",
548
- contract: {
549
- requiredDimensions: 1,
550
- requiredMeasures: 1,
551
- minDataPoints: 2,
552
- idealDataPoints: 5,
553
- maxDataPoints: 12,
554
- allowNegativeValues: true,
555
- requireNonZeroTotal: false,
556
- warningThresholds: { tooManyCategories: 10 },
557
- fallback: { type: "aggregate", strategy: "top_n" }
558
- },
559
- switchableTo: ["bar", "stacked_column", "stacked_bar"],
560
- supportsStacking: true,
561
- supportsMultipleSeries: true,
562
- requiresTimeAxis: false
563
- },
564
- stacked_bar: {
565
- id: "stacked_bar",
566
- name: "Stacked Horizontal Bar",
567
- description: "Horizontal stacked bars showing composition per category",
568
- intent: "comparison",
569
- phase: "mvp",
570
- contract: {
571
- requiredDimensions: 1,
572
- requiredMeasures: 2,
573
- minDataPoints: 2,
574
- idealDataPoints: 5,
575
- maxDataPoints: 10,
576
- allowNegativeValues: false,
577
- requireNonZeroTotal: true,
578
- warningThresholds: { tooManyCategories: 8, imbalancedRatio: 0.9 },
579
- fallback: { type: "aggregate", strategy: "other_bucket" }
580
- },
581
- switchableTo: ["bar", "stacked_column", "column_100pct"],
582
- supportsStacking: true,
583
- supportsMultipleSeries: true,
584
- requiresTimeAxis: false
585
- },
586
- stacked_column: {
587
- id: "stacked_column",
588
- name: "Stacked Vertical Column",
589
- description: "Vertical stacked columns showing composition per category",
590
- intent: "comparison",
591
- phase: "mvp",
592
- contract: {
593
- requiredDimensions: 1,
594
- requiredMeasures: 2,
595
- minDataPoints: 2,
596
- idealDataPoints: 5,
597
- maxDataPoints: 10,
598
- allowNegativeValues: false,
599
- requireNonZeroTotal: true,
600
- warningThresholds: { tooManyCategories: 8, imbalancedRatio: 0.9 },
601
- fallback: { type: "aggregate", strategy: "other_bucket" }
602
- },
603
- switchableTo: ["column", "stacked_bar", "column_100pct"],
604
- supportsStacking: true,
605
- supportsMultipleSeries: true,
606
- requiresTimeAxis: false
607
- },
608
- column_100pct: {
609
- id: "column_100pct",
610
- name: "100% Stacked Column",
611
- description: "Shows proportional composition per category",
612
- intent: "comparison",
613
- phase: "mvp",
614
- contract: {
615
- requiredDimensions: 1,
616
- requiredMeasures: 2,
617
- minDataPoints: 2,
618
- idealDataPoints: 5,
619
- maxDataPoints: 10,
620
- allowNegativeValues: false,
621
- requireNonZeroTotal: true,
622
- warningThresholds: { tooManyCategories: 8 },
623
- fallback: { type: "warn", message: "100% stacked requires positive totals" }
624
- },
625
- switchableTo: ["stacked_column", "stacked_bar"],
626
- supportsStacking: true,
627
- supportsMultipleSeries: true,
628
- requiresTimeAxis: false
629
- },
630
- combo: {
631
- id: "combo",
632
- name: "Combo Chart",
633
- description: "Combines bars with line overlay (Phase 2)",
634
- intent: "comparison",
635
- phase: "phase2",
636
- contract: {
637
- requiredDimensions: 1,
638
- requiredMeasures: 2,
639
- minDataPoints: 3,
640
- idealDataPoints: 6,
641
- allowNegativeValues: true,
642
- requireNonZeroTotal: false,
643
- warningThresholds: { tooManyCategories: 10 },
644
- fallback: { type: "warn", message: "Combo chart requires dual measures" }
645
- },
646
- switchableTo: ["column", "line"],
647
- supportsStacking: false,
648
- supportsMultipleSeries: true,
649
- requiresTimeAxis: false
650
- },
651
- // ══════════════════════════════════════════════════════════════════════════
652
- // COMPOSITION CHARTS (MVP)
653
- // ══════════════════════════════════════════════════════════════════════════
654
- pie: {
655
- id: "pie",
656
- name: "Pie Chart",
657
- description: "Shows proportional composition of a whole",
658
- intent: "composition",
659
- phase: "mvp",
660
- contract: {
661
- requiredDimensions: 1,
662
- requiredMeasures: 1,
663
- minDataPoints: 2,
664
- idealDataPoints: 4,
665
- maxDataPoints: 6,
666
- allowNegativeValues: false,
667
- requireNonZeroTotal: true,
668
- warningThresholds: { tooManyCategories: 6, imbalancedRatio: 0.95 },
669
- fallback: { type: "aggregate", strategy: "other_bucket" }
670
- },
671
- switchableTo: ["donut", "column_100pct"],
672
- supportsStacking: false,
673
- supportsMultipleSeries: false,
674
- requiresTimeAxis: false,
675
- maxSlices: 6
676
- },
677
- donut: {
678
- id: "donut",
679
- name: "Donut Chart",
680
- description: "Pie chart with center cutout, can display total",
681
- intent: "composition",
682
- phase: "mvp",
683
- contract: {
684
- requiredDimensions: 1,
685
- requiredMeasures: 1,
686
- minDataPoints: 2,
687
- idealDataPoints: 4,
688
- maxDataPoints: 6,
689
- allowNegativeValues: false,
690
- requireNonZeroTotal: true,
691
- warningThresholds: { tooManyCategories: 6, imbalancedRatio: 0.95 },
692
- fallback: { type: "aggregate", strategy: "other_bucket" }
693
- },
694
- switchableTo: ["pie", "column_100pct"],
695
- supportsStacking: false,
696
- supportsMultipleSeries: false,
697
- requiresTimeAxis: false,
698
- maxSlices: 6
699
- },
700
- treemap: {
701
- id: "treemap",
702
- name: "Treemap",
703
- description: "Nested rectangles showing hierarchical composition (Phase 2)",
704
- intent: "composition",
705
- phase: "phase2",
706
- contract: {
707
- requiredDimensions: 1,
708
- requiredMeasures: 1,
709
- minDataPoints: 3,
710
- idealDataPoints: 10,
711
- maxDataPoints: 50,
712
- allowNegativeValues: false,
713
- requireNonZeroTotal: true,
714
- warningThresholds: { tooManyCategories: 30 },
715
- fallback: { type: "aggregate", strategy: "top_n" }
716
- },
717
- switchableTo: ["pie", "donut"],
718
- supportsStacking: false,
719
- supportsMultipleSeries: false,
720
- requiresTimeAxis: false
721
- },
722
- // ══════════════════════════════════════════════════════════════════════════
723
- // DISTRIBUTION CHARTS (MVP)
724
- // ══════════════════════════════════════════════════════════════════════════
725
- histogram: {
726
- id: "histogram",
727
- name: "Histogram",
728
- description: "Shows distribution of values across bins",
729
- intent: "distribution",
730
- phase: "mvp",
731
- contract: {
732
- requiredDimensions: 0,
733
- requiredMeasures: 1,
734
- minDataPoints: 10,
735
- idealDataPoints: 50,
736
- allowNegativeValues: true,
737
- requireNonZeroTotal: false,
738
- warningThresholds: { sparseData: 10 },
739
- fallback: { type: "show_kpi", message: "Insufficient data for distribution" }
740
- },
741
- switchableTo: ["radar"],
742
- supportsStacking: false,
743
- supportsMultipleSeries: false,
744
- requiresTimeAxis: false
745
- },
746
- radar: {
747
- id: "radar",
748
- name: "Radar Chart",
749
- description: "Multi-dimensional comparison in radial layout (Phase 2)",
750
- intent: "distribution",
751
- phase: "phase2",
752
- contract: {
753
- requiredDimensions: 1,
754
- requiredMeasures: 3,
755
- minDataPoints: 3,
756
- idealDataPoints: 6,
757
- maxDataPoints: 8,
758
- allowNegativeValues: false,
759
- requireNonZeroTotal: false,
760
- warningThresholds: { tooManyCategories: 8 },
761
- fallback: { type: "warn", message: "Radar works best with 3-8 dimensions" }
762
- },
763
- switchableTo: ["histogram"],
764
- supportsStacking: false,
765
- supportsMultipleSeries: true,
766
- requiresTimeAxis: false
767
- },
768
- // ══════════════════════════════════════════════════════════════════════════
769
- // RELATIONSHIP CHARTS
770
- // ══════════════════════════════════════════════════════════════════════════
771
- heatmap: {
772
- id: "heatmap",
773
- name: "Heatmap",
774
- description: "Color-coded matrix showing intensity",
775
- intent: "relationship",
776
- phase: "mvp",
777
- contract: {
778
- requiredDimensions: 2,
779
- requiredMeasures: 1,
780
- minDataPoints: 9,
781
- idealDataPoints: 25,
782
- allowNegativeValues: true,
783
- requireNonZeroTotal: false,
784
- warningThresholds: { sparseData: 9 },
785
- fallback: { type: "warn", message: "Heatmap requires grid data" }
786
- },
787
- switchableTo: ["scatter"],
788
- supportsStacking: false,
789
- supportsMultipleSeries: false,
790
- requiresTimeAxis: false
791
- },
792
- scatter: {
793
- id: "scatter",
794
- name: "Scatter Plot",
795
- description: "Shows correlation between two variables (Phase 2)",
796
- intent: "relationship",
797
- phase: "phase2",
798
- contract: {
799
- requiredDimensions: 0,
800
- requiredMeasures: 2,
801
- minDataPoints: 20,
802
- idealDataPoints: 100,
803
- allowNegativeValues: true,
804
- requireNonZeroTotal: false,
805
- warningThresholds: { sparseData: 20 },
806
- fallback: { type: "show_kpi", message: "Scatter requires 20+ points" }
807
- },
808
- switchableTo: ["bubble", "heatmap"],
809
- supportsStacking: false,
810
- supportsMultipleSeries: true,
811
- requiresTimeAxis: false
812
- },
813
- bubble: {
814
- id: "bubble",
815
- name: "Bubble Chart",
816
- description: "Scatter with sized points for third dimension (Phase 2)",
817
- intent: "relationship",
818
- phase: "phase2",
819
- contract: {
820
- requiredDimensions: 0,
821
- requiredMeasures: 3,
822
- minDataPoints: 10,
823
- idealDataPoints: 50,
824
- allowNegativeValues: true,
825
- requireNonZeroTotal: false,
826
- warningThresholds: { sparseData: 10 },
827
- fallback: { type: "show_kpi", message: "Bubble requires 3 measures" }
828
- },
829
- switchableTo: ["scatter"],
830
- supportsStacking: false,
831
- supportsMultipleSeries: true,
832
- requiresTimeAxis: false
833
- },
834
- // ══════════════════════════════════════════════════════════════════════════
835
- // GEOGRAPHIC CHARTS (Phase 2)
836
- // ══════════════════════════════════════════════════════════════════════════
837
- geo: {
838
- id: "geo",
839
- name: "Geographic Map",
840
- description: "Map with regional data markers (Phase 2)",
841
- intent: "geo",
842
- phase: "phase2",
843
- contract: {
844
- requiredDimensions: 1,
845
- // geo dimension (country/region)
846
- requiredMeasures: 1,
847
- minDataPoints: 1,
848
- idealDataPoints: 10,
849
- allowNegativeValues: true,
850
- requireNonZeroTotal: false,
851
- warningThresholds: {},
852
- fallback: { type: "hide" }
853
- },
854
- switchableTo: ["choropleth"],
855
- supportsStacking: false,
856
- supportsMultipleSeries: false,
857
- requiresTimeAxis: false
858
- },
859
- choropleth: {
860
- id: "choropleth",
861
- name: "Choropleth Map",
862
- description: "Color-shaded regions by value (Phase 2)",
863
- intent: "geo",
864
- phase: "phase2",
865
- contract: {
866
- requiredDimensions: 1,
867
- requiredMeasures: 1,
868
- minDataPoints: 3,
869
- idealDataPoints: 20,
870
- allowNegativeValues: false,
871
- requireNonZeroTotal: false,
872
- warningThresholds: {},
873
- fallback: { type: "hide" }
874
- },
875
- switchableTo: ["geo"],
876
- supportsStacking: false,
877
- supportsMultipleSeries: false,
878
- requiresTimeAxis: false
879
- },
880
- // ══════════════════════════════════════════════════════════════════════════
881
- // SPECIAL CHARTS
882
- // ══════════════════════════════════════════════════════════════════════════
883
- funnel: {
884
- id: "funnel",
885
- name: "Funnel Chart",
886
- description: "Shows conversion through sequential stages",
887
- intent: "comparison",
888
- phase: "mvp",
889
- contract: {
890
- requiredDimensions: 1,
891
- requiredMeasures: 1,
892
- minDataPoints: 3,
893
- idealDataPoints: 5,
894
- maxDataPoints: 7,
895
- allowNegativeValues: false,
896
- requireNonZeroTotal: true,
897
- warningThresholds: { tooManyCategories: 7 },
898
- fallback: { type: "warn", message: "Funnel requires sequential stages" }
899
- },
900
- switchableTo: ["bar"],
901
- supportsStacking: false,
902
- supportsMultipleSeries: false,
903
- requiresTimeAxis: false
904
- },
905
- waterfall: {
906
- id: "waterfall",
907
- name: "Waterfall Chart",
908
- description: "Shows cumulative effect of sequential changes (Phase 2)",
909
- intent: "comparison",
910
- phase: "phase2",
911
- contract: {
912
- requiredDimensions: 1,
913
- requiredMeasures: 1,
914
- minDataPoints: 3,
915
- idealDataPoints: 6,
916
- maxDataPoints: 12,
917
- allowNegativeValues: true,
918
- requireNonZeroTotal: false,
919
- warningThresholds: { tooManyCategories: 10 },
920
- fallback: { type: "warn", message: "Waterfall requires sequential data" }
921
- },
922
- switchableTo: ["bar", "column"],
923
- supportsStacking: false,
924
- supportsMultipleSeries: false,
925
- requiresTimeAxis: false
926
- },
927
- timeline: {
928
- id: "timeline",
929
- name: "Timeline",
930
- description: "Shows events along time axis (Phase 2)",
931
- intent: "trend",
932
- phase: "phase2",
933
- contract: {
934
- requiredDimensions: 1,
935
- requiredMeasures: 0,
936
- minDataPoints: 2,
937
- idealDataPoints: 10,
938
- allowNegativeValues: false,
939
- requireNonZeroTotal: false,
940
- warningThresholds: {},
941
- fallback: { type: "hide" }
942
- },
943
- switchableTo: ["line"],
944
- supportsStacking: false,
945
- supportsMultipleSeries: false,
946
- requiresTimeAxis: true
947
- }
948
- };
949
- var INTENT_CHART_FAMILIES = {
950
- trend: ["line", "smooth_line", "area", "stacked_area", "area_100pct"],
951
- comparison: ["bar", "column", "stacked_bar", "stacked_column", "column_100pct", "funnel"],
952
- composition: ["pie", "donut"],
953
- distribution: ["histogram"],
954
- relationship: ["heatmap"],
955
- geo: []
956
- };
957
- function getAllowedSwitchTargets(currentType) {
958
- const metadata = CHART_REGISTRY[currentType];
959
- if (!metadata) return [];
960
- return metadata.switchableTo.filter((type) => {
961
- const targetMeta = CHART_REGISTRY[type];
962
- return targetMeta && targetMeta.phase === "mvp";
963
- });
964
- }
965
- function canSwitchChart(from, to) {
966
- const fromMeta = CHART_REGISTRY[from];
967
- const toMeta = CHART_REGISTRY[to];
968
- if (!fromMeta || !toMeta) return false;
969
- if (fromMeta.intent !== toMeta.intent) return false;
970
- return fromMeta.switchableTo.includes(to);
971
- }
972
- function validateChartData(chartType, data, dimensions, measures) {
973
- const metadata = CHART_REGISTRY[chartType];
974
- if (!metadata) {
975
- return {
976
- isValid: false,
977
- warnings: [],
978
- errors: [`Unknown chart type: ${chartType}`]
979
- };
980
- }
981
- const contract = metadata.contract;
982
- const warnings = [];
983
- const errors = [];
984
- if (data.length < contract.minDataPoints) {
985
- errors.push(`Requires at least ${contract.minDataPoints} data points, got ${data.length}`);
986
- }
987
- if (contract.maxDataPoints && data.length > contract.maxDataPoints) {
988
- warnings.push(`Chart works best with \u2264${contract.maxDataPoints} items. Consider aggregating.`);
989
- }
990
- if (dimensions.length < contract.requiredDimensions) {
991
- errors.push(`Requires ${contract.requiredDimensions} dimension(s), got ${dimensions.length}`);
992
- }
993
- if (measures.length < contract.requiredMeasures) {
994
- errors.push(`Requires ${contract.requiredMeasures} measure(s), got ${measures.length}`);
995
- }
996
- if (!contract.allowNegativeValues && data.length > 0) {
997
- const hasNegative = data.some((row) => {
998
- if (typeof row !== "object" || row === null) return false;
999
- return measures.some((m) => {
1000
- const val = row[m];
1001
- return typeof val === "number" && val < 0;
1002
- });
1003
- });
1004
- if (hasNegative) {
1005
- errors.push("This chart type does not support negative values");
1006
- }
1007
- }
1008
- if (contract.warningThresholds.tooManyCategories && data.length > contract.warningThresholds.tooManyCategories) {
1009
- warnings.push(`Too many categories (${data.length}). Consider grouping smaller values.`);
1010
- }
1011
- return {
1012
- isValid: errors.length === 0,
1013
- warnings,
1014
- errors,
1015
- fallbackAction: errors.length > 0 ? contract.fallback : void 0
1016
- };
1017
- }
1018
- function getMVPChartsForIntent(intent) {
1019
- return Object.values(CHART_REGISTRY).filter(
1020
- (meta) => meta.intent === intent && meta.phase === "mvp"
1021
- );
1022
- }
1023
- function getDefaultChartForIntent(intent) {
1024
- const defaults = {
1025
- trend: "line",
1026
- comparison: "column",
1027
- composition: "donut",
1028
- distribution: "histogram",
1029
- relationship: "heatmap",
1030
- geo: "geo"
1031
- };
1032
- return defaults[intent];
1033
- }
1034
- function suggestChartType(params) {
1035
- const {
1036
- hasTimeAxis,
1037
- dimensionCount,
1038
- measureCount,
1039
- dataPointCount,
1040
- hasNegativeValues,
1041
- isSequential
1042
- } = params;
1043
- if (hasTimeAxis && measureCount >= 1) {
1044
- if (measureCount > 1 && !hasNegativeValues) return "stacked_area";
1045
- return "line";
1046
- }
1047
- if (isSequential && !hasNegativeValues && dataPointCount <= 7) {
1048
- return "funnel";
1049
- }
1050
- if (measureCount === 1 && dataPointCount <= 6 && !hasNegativeValues) {
1051
- return "donut";
1052
- }
1053
- if (dimensionCount === 2 && measureCount === 1) {
1054
- return "heatmap";
1055
- }
1056
- return "column";
1057
- }
1058
- function validateReportStructure(children) {
1059
- const issues = [];
1060
- const childArray = React2__default.default.Children.toArray(children);
1061
- let hasThesis = false;
1062
- let thesisIndex = -1;
1063
- const getComponentName2 = (child) => {
1064
- if (!React2__default.default.isValidElement(child)) return void 0;
1065
- const type = child.type;
1066
- return type.displayName || type.name;
1067
- };
1068
- const isChart2 = (name) => {
1069
- return name && (name.endsWith("Chart") || name === "MBTIRadar" || name === "MBTITypeGrid" || name === "KeyMetric");
1070
- };
1071
- childArray.forEach((child, index) => {
1072
- const name = getComponentName2(child);
1073
- if (name === "ExecutiveThesis") {
1074
- if (hasThesis) {
1075
- issues.push({
1076
- ruleId: "R1",
1077
- severity: "error",
1078
- message: "Only one ExecutiveThesis is allowed per report.",
1079
- component: "ExecutiveThesis"
1080
- });
1081
- }
1082
- hasThesis = true;
1083
- thesisIndex = index;
1084
- }
1085
- if (isChart2(name)) {
1086
- issues.push({
1087
- ruleId: "R3",
1088
- severity: "error",
1089
- message: `Orphan chart detected: <${name} />. Charts must be placed inside an InsightBlock or EvidenceGroup.`,
1090
- component: name
1091
- });
1092
- }
1093
- if (name === "InsightBlock" && React2__default.default.isValidElement(child)) {
1094
- validateInsightBlock(child, issues);
1095
- }
1096
- });
1097
- if (!hasThesis) {
1098
- issues.push({
1099
- ruleId: "R1",
1100
- severity: "error",
1101
- message: "Report must contain an ExecutiveThesis."
1102
- });
1103
- } else if (thesisIndex > 2) {
1104
- issues.push({
1105
- ruleId: "R1",
1106
- severity: "warning",
1107
- message: "ExecutiveThesis should be the first major component in the report."
1108
- });
1109
- }
1110
- return {
1111
- isValid: issues.filter((i) => i.severity === "error").length === 0,
1112
- issues
1113
- };
1114
- }
1115
- function validateInsightBlock(node, issues) {
1116
- const children = node.props.children;
1117
- const childArray = React2__default.default.Children.toArray(children);
1118
- let chartsInBlock = 0;
1119
- const countCharts = (nodes) => {
1120
- nodes.forEach((n) => {
1121
- const name = getComponentName(n);
1122
- if (isChart(name)) {
1123
- chartsInBlock++;
1124
- }
1125
- if (name === "EvidenceGroup" && React2__default.default.isValidElement(n)) {
1126
- countCharts(React2__default.default.Children.toArray(n.props.children));
1127
- }
1128
- });
1129
- };
1130
- countCharts(childArray);
1131
- if (chartsInBlock > 3) {
1132
- issues.push({
1133
- ruleId: "R6",
1134
- severity: "warning",
1135
- message: `InsightBlock contains ${chartsInBlock} charts. Recommended maximum is 3 to prevent data dumping.`,
1136
- component: "InsightBlock"
1137
- });
1138
- }
1139
- }
1140
- var getComponentName = (child) => {
1141
- if (!React2__default.default.isValidElement(child)) return void 0;
1142
- const type = child.type;
1143
- return type.displayName || type.name;
1144
- };
1145
- var isChart = (name) => {
1146
- return name && (name.endsWith("Chart") || name === "MBTIRadar" || name === "MBTITypeGrid" || name === "KeyMetric");
1147
- };
1148
- var ConfidenceIndicator = React2__default.default.forwardRef(
1149
- ({ score, showScore = true, showLabel = true, size = "md", className, ...props }, ref) => {
1150
- const threshold = getConfidenceThreshold(score);
1151
- const normalizedScore = Math.max(0, Math.min(100, score));
1152
- return /* @__PURE__ */ jsxRuntime.jsxs(
1153
- "div",
1154
- {
1155
- ref,
1156
- className: clsx__default.default(
1157
- "ds-confidence-indicator",
1158
- `ds-confidence-indicator--${size}`,
1159
- `ds-confidence-indicator--${threshold.level}`,
1160
- className
1161
- ),
1162
- role: "meter",
1163
- "aria-valuenow": normalizedScore,
1164
- "aria-valuemin": 0,
1165
- "aria-valuemax": 100,
1166
- "aria-label": `Confidence: ${threshold.label} (${normalizedScore}%)`,
1167
- ...props,
1168
- children: [
1169
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-confidence-indicator__bar", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-confidence-indicator__fill", style: { width: `${normalizedScore}%` } }) }),
1170
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-confidence-indicator__text", children: [
1171
- showScore && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ds-confidence-indicator__score", children: [
1172
- normalizedScore,
1173
- "%"
1174
- ] }),
1175
- showLabel && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-confidence-indicator__label", children: threshold.label })
1176
- ] })
1177
- ]
1178
- }
1179
- );
1180
- }
1181
- );
1182
- ConfidenceIndicator.displayName = "ConfidenceIndicator";
1183
- var DataCoverageBadge = React2__default.default.forwardRef(
1184
- ({ sampleSize, requiredSize, dateRange, showDateRange = true, size = "md", className, ...props }, ref) => {
1185
- const isSufficient = !requiredSize || sampleSize >= requiredSize;
1186
- const percentage = requiredSize ? Math.min(100, Math.round(sampleSize / requiredSize * 100)) : 100;
1187
- return /* @__PURE__ */ jsxRuntime.jsxs(
1188
- "div",
1189
- {
1190
- ref,
1191
- className: clsx__default.default(
1192
- "ds-data-coverage-badge",
1193
- `ds-data-coverage-badge--${size}`,
1194
- !isSufficient && "ds-data-coverage-badge--insufficient",
1195
- className
1196
- ),
1197
- ...props,
1198
- children: [
1199
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-data-coverage-badge__sample", children: [
1200
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-data-coverage-badge__icon", children: /* @__PURE__ */ jsxRuntime.jsxs(
1201
- "svg",
1202
- {
1203
- width: "14",
1204
- height: "14",
1205
- viewBox: "0 0 24 24",
1206
- fill: "none",
1207
- stroke: "currentColor",
1208
- strokeWidth: "2",
1209
- children: [
1210
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" }),
1211
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "9", cy: "7", r: "4" }),
1212
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M23 21v-2a4 4 0 0 0-3-3.87" }),
1213
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16 3.13a4 4 0 0 1 0 7.75" })
1214
- ]
1215
- }
1216
- ) }),
1217
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ds-data-coverage-badge__count", children: [
1218
- "n=",
1219
- sampleSize.toLocaleString()
1220
- ] }),
1221
- requiredSize && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ds-data-coverage-badge__required", children: [
1222
- "(",
1223
- percentage,
1224
- "% of min ",
1225
- requiredSize,
1226
- ")"
1227
- ] })
1228
- ] }),
1229
- showDateRange && dateRange && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-data-coverage-badge__date", children: [
1230
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-data-coverage-badge__icon", children: /* @__PURE__ */ jsxRuntime.jsxs(
1231
- "svg",
1232
- {
1233
- width: "14",
1234
- height: "14",
1235
- viewBox: "0 0 24 24",
1236
- fill: "none",
1237
- stroke: "currentColor",
1238
- strokeWidth: "2",
1239
- children: [
1240
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2", ry: "2" }),
1241
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "16", y1: "2", x2: "16", y2: "6" }),
1242
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "8", y1: "2", x2: "8", y2: "6" }),
1243
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "10", x2: "21", y2: "10" })
1244
- ]
1245
- }
1246
- ) }),
1247
- /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
1248
- dateRange.start,
1249
- " \u2013 ",
1250
- dateRange.end
1251
- ] })
1252
- ] })
1253
- ]
1254
- }
1255
- );
1256
- }
1257
- );
1258
- DataCoverageBadge.displayName = "DataCoverageBadge";
1259
- var DataStateIndicator = React2__default.default.forwardRef(
1260
- ({ state, details, variant = "compact", onAction, className, ...props }, ref) => {
1261
- const config = ANALYTICAL_STATE_CONFIG[state];
1262
- if (state === "VALID" && variant === "compact") {
1263
- return null;
1264
- }
1265
- const renderIcon = () => {
1266
- switch (config.icon) {
1267
- case "check":
1268
- return /* @__PURE__ */ jsxRuntime.jsx(
1269
- "svg",
1270
- {
1271
- width: "16",
1272
- height: "16",
1273
- viewBox: "0 0 24 24",
1274
- fill: "none",
1275
- stroke: "currentColor",
1276
- strokeWidth: "2",
1277
- children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "20,6 9,17 4,12" })
1278
- }
1279
- );
1280
- case "alert-triangle":
1281
- return /* @__PURE__ */ jsxRuntime.jsxs(
1282
- "svg",
1283
- {
1284
- width: "16",
1285
- height: "16",
1286
- viewBox: "0 0 24 24",
1287
- fill: "none",
1288
- stroke: "currentColor",
1289
- strokeWidth: "2",
1290
- children: [
1291
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" }),
1292
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "9", x2: "12", y2: "13" }),
1293
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
1294
- ]
1295
- }
1296
- );
1297
- case "alert-circle":
1298
- return /* @__PURE__ */ jsxRuntime.jsxs(
1299
- "svg",
1300
- {
1301
- width: "16",
1302
- height: "16",
1303
- viewBox: "0 0 24 24",
1304
- fill: "none",
1305
- stroke: "currentColor",
1306
- strokeWidth: "2",
1307
- children: [
1308
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }),
1309
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
1310
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
1311
- ]
1312
- }
1313
- );
1314
- case "x-circle":
1315
- return /* @__PURE__ */ jsxRuntime.jsxs(
1316
- "svg",
1317
- {
1318
- width: "16",
1319
- height: "16",
1320
- viewBox: "0 0 24 24",
1321
- fill: "none",
1322
- stroke: "currentColor",
1323
- strokeWidth: "2",
1324
- children: [
1325
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }),
1326
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "15", y1: "9", x2: "9", y2: "15" }),
1327
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "9", y1: "9", x2: "15", y2: "15" })
1328
- ]
1329
- }
1330
- );
1331
- case "cpu":
1332
- return /* @__PURE__ */ jsxRuntime.jsxs(
1333
- "svg",
1334
- {
1335
- width: "16",
1336
- height: "16",
1337
- viewBox: "0 0 24 24",
1338
- fill: "none",
1339
- stroke: "currentColor",
1340
- strokeWidth: "2",
1341
- children: [
1342
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "4", y: "4", width: "16", height: "16", rx: "2", ry: "2" }),
1343
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "9", y: "9", width: "6", height: "6" }),
1344
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "9", y1: "1", x2: "9", y2: "4" }),
1345
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "15", y1: "1", x2: "15", y2: "4" }),
1346
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "9", y1: "20", x2: "9", y2: "23" }),
1347
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "15", y1: "20", x2: "15", y2: "23" }),
1348
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "20", y1: "9", x2: "23", y2: "9" }),
1349
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "20", y1: "14", x2: "23", y2: "14" }),
1350
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "1", y1: "9", x2: "4", y2: "9" }),
1351
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "1", y1: "14", x2: "4", y2: "14" })
1352
- ]
1353
- }
1354
- );
1355
- default:
1356
- return /* @__PURE__ */ jsxRuntime.jsxs(
1357
- "svg",
1358
- {
1359
- width: "16",
1360
- height: "16",
1361
- viewBox: "0 0 24 24",
1362
- fill: "none",
1363
- stroke: "currentColor",
1364
- strokeWidth: "2",
1365
- children: [
1366
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }),
1367
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "16", x2: "12", y2: "12" }),
1368
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "8", x2: "12.01", y2: "8" })
1369
- ]
1370
- }
1371
- );
1372
- }
1373
- };
1374
- return /* @__PURE__ */ jsxRuntime.jsxs(
1375
- "div",
1376
- {
1377
- ref,
1378
- className: clsx__default.default(
1379
- "ds-data-state-indicator",
1380
- `ds-data-state-indicator--${variant}`,
1381
- `ds-data-state-indicator--${state.toLowerCase().replace(/_/g, "-")}`,
1382
- className
1383
- ),
1384
- role: "status",
1385
- "aria-live": "polite",
1386
- ...props,
1387
- children: [
1388
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-data-state-indicator__icon", style: { color: config.color }, children: renderIcon() }),
1389
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-data-state-indicator__content", children: [
1390
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-data-state-indicator__label", children: config.label }),
1391
- variant === "full" && details && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ds-data-state-indicator__details", children: [
1392
- details.message,
1393
- details.sampleSize !== void 0 && details.requiredSize !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1394
- " ",
1395
- "(n=",
1396
- details.sampleSize,
1397
- "/",
1398
- details.requiredSize,
1399
- ")"
1400
- ] }),
1401
- details.confidence !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1402
- " \u2022 ",
1403
- details.confidence,
1404
- "% confidence"
1405
- ] }),
1406
- details.missingFields && details.missingFields.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1407
- " \u2022 Missing: ",
1408
- details.missingFields.join(", ")
1409
- ] })
1410
- ] })
1411
- ] }),
1412
- config.action && onAction && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "ds-data-state-indicator__action", onClick: onAction, children: config.action })
1413
- ]
1414
- }
1415
- );
1416
- }
1417
- );
1418
- DataStateIndicator.displayName = "DataStateIndicator";
1419
-
1420
- exports.ANALYST_MODE = ANALYST_MODE;
1421
- exports.ANALYTICAL_STATE_CONFIG = ANALYTICAL_STATE_CONFIG;
1422
- exports.CHART_REGISTRY = CHART_REGISTRY;
1423
- exports.CONFIDENCE_THRESHOLDS = CONFIDENCE_THRESHOLDS;
1424
- exports.ConfidenceIndicator = ConfidenceIndicator;
1425
- exports.DataCoverageBadge = DataCoverageBadge;
1426
- exports.DataStateIndicator = DataStateIndicator;
1427
- exports.EXECUTIVE_MODE = EXECUTIVE_MODE;
1428
- exports.INSIGHT_TYPE_CONTRACTS = INSIGHT_TYPE_CONTRACTS;
1429
- exports.INTENT_CHART_FAMILIES = INTENT_CHART_FAMILIES;
1430
- exports.MINIMUM_SAMPLE_SIZES = MINIMUM_SAMPLE_SIZES;
1431
- exports.ReportModeProvider = ReportModeProvider;
1432
- exports.calculateCompleteness = calculateCompleteness;
1433
- exports.calculateConfidence = calculateConfidence;
1434
- exports.calculateNormalizedVariance = calculateNormalizedVariance;
1435
- exports.calculateRecency = calculateRecency;
1436
- exports.canSwitchChart = canSwitchChart;
1437
- exports.getAllowedSwitchTargets = getAllowedSwitchTargets;
1438
- exports.getConfidenceLevel = getConfidenceLevel;
1439
- exports.getConfidenceThreshold = getConfidenceThreshold;
1440
- exports.getDefaultChartForIntent = getDefaultChartForIntent;
1441
- exports.getMVPChartsForIntent = getMVPChartsForIntent;
1442
- exports.suggestChartType = suggestChartType;
1443
- exports.useChartData = useChartData;
1444
- exports.useDataState = useDataState;
1445
- exports.useReportMode = useReportMode;
1446
- exports.validateChartData = validateChartData;
1447
- exports.validateReportStructure = validateReportStructure;
1448
- //# sourceMappingURL=out.js.map
1449
- //# sourceMappingURL=chunk-Q2MFGYTE.cjs.map