@startsimpli/funnels 0.1.4 → 0.1.5

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 (151) hide show
  1. package/package.json +9 -31
  2. package/src/api/README.md +507 -0
  3. package/src/api/adapter.ts +106 -0
  4. package/src/api/client.test.ts +640 -0
  5. package/src/api/client.ts +385 -0
  6. package/src/api/default-adapter.ts +243 -0
  7. package/src/api/index.ts +24 -0
  8. package/src/components/FilterRuleEditor/ARCHITECTURE.md +354 -0
  9. package/src/components/FilterRuleEditor/FieldSelector.tsx +91 -0
  10. package/src/components/FilterRuleEditor/FilterRuleEditor.stories.tsx +462 -0
  11. package/src/components/FilterRuleEditor/FilterRuleEditor.test.tsx +520 -0
  12. package/src/components/FilterRuleEditor/FilterRuleEditor.tsx +225 -0
  13. package/src/components/FilterRuleEditor/LogicToggle.tsx +64 -0
  14. package/src/components/FilterRuleEditor/OperatorSelector.tsx +75 -0
  15. package/src/components/FilterRuleEditor/README.md +291 -0
  16. package/src/components/FilterRuleEditor/RuleRow.tsx +246 -0
  17. package/src/components/FilterRuleEditor/ValueInputs/BooleanValueInput.tsx +54 -0
  18. package/src/components/FilterRuleEditor/ValueInputs/ChoiceValueInput.tsx +83 -0
  19. package/src/components/FilterRuleEditor/ValueInputs/DateValueInput.tsx +70 -0
  20. package/src/components/FilterRuleEditor/ValueInputs/MultiChoiceValueInput.tsx +132 -0
  21. package/src/components/FilterRuleEditor/ValueInputs/NumberValueInput.tsx +73 -0
  22. package/src/components/FilterRuleEditor/ValueInputs/TextValueInput.tsx +50 -0
  23. package/src/components/FilterRuleEditor/ValueInputs/index.ts +12 -0
  24. package/src/components/FilterRuleEditor/constants.ts +64 -0
  25. package/src/components/FilterRuleEditor/index.ts +14 -0
  26. package/src/components/FunnelCard/DESIGN.md +447 -0
  27. package/src/components/FunnelCard/FunnelCard.stories.tsx +484 -0
  28. package/src/components/FunnelCard/FunnelCard.test.ts +257 -0
  29. package/src/components/FunnelCard/FunnelCard.test.tsx +336 -0
  30. package/src/components/FunnelCard/FunnelCard.tsx +204 -0
  31. package/src/components/FunnelCard/FunnelStats.tsx +68 -0
  32. package/src/components/FunnelCard/IMPLEMENTATION_SUMMARY.md +505 -0
  33. package/src/components/FunnelCard/INSTALLATION.md +304 -0
  34. package/src/components/FunnelCard/MatchBar.tsx +49 -0
  35. package/src/components/FunnelCard/README.md +294 -0
  36. package/src/components/FunnelCard/StageIndicator.tsx +62 -0
  37. package/src/components/FunnelCard/StatusBadge.tsx +52 -0
  38. package/src/components/FunnelCard/index.ts +14 -0
  39. package/src/components/FunnelPreview/EntityCard.tsx +72 -0
  40. package/src/components/FunnelPreview/FunnelPreview.stories.tsx +227 -0
  41. package/src/components/FunnelPreview/FunnelPreview.test.tsx +316 -0
  42. package/src/components/FunnelPreview/FunnelPreview.tsx +249 -0
  43. package/src/components/FunnelPreview/LoadingPreview.tsx +60 -0
  44. package/src/components/FunnelPreview/PreviewStats.tsx +78 -0
  45. package/src/components/FunnelPreview/README.md +337 -0
  46. package/src/components/FunnelPreview/StageBreakdown.tsx +94 -0
  47. package/src/components/FunnelPreview/example.tsx +286 -0
  48. package/src/components/FunnelPreview/index.ts +14 -0
  49. package/src/components/FunnelRunHistory/COMPONENT_SUMMARY.md +246 -0
  50. package/src/components/FunnelRunHistory/FunnelRunHistory.stories.tsx +272 -0
  51. package/src/components/FunnelRunHistory/FunnelRunHistory.test.tsx +323 -0
  52. package/src/components/FunnelRunHistory/FunnelRunHistory.tsx +329 -0
  53. package/src/components/FunnelRunHistory/README.md +325 -0
  54. package/src/components/FunnelRunHistory/RunActions.tsx +168 -0
  55. package/src/components/FunnelRunHistory/RunDetailsModal.tsx +221 -0
  56. package/src/components/FunnelRunHistory/RunFilters.tsx +128 -0
  57. package/src/components/FunnelRunHistory/RunRow.tsx +122 -0
  58. package/src/components/FunnelRunHistory/RunStatusBadge.tsx +75 -0
  59. package/src/components/FunnelRunHistory/StageBreakdownList.tsx +110 -0
  60. package/src/components/FunnelRunHistory/index.ts +51 -0
  61. package/src/components/FunnelRunHistory/types.ts +40 -0
  62. package/src/components/FunnelRunHistory/utils.test.ts +126 -0
  63. package/src/components/FunnelRunHistory/utils.ts +100 -0
  64. package/src/components/FunnelStageBuilder/AddStageButton.tsx +52 -0
  65. package/src/components/FunnelStageBuilder/FunnelStageBuilder.css +413 -0
  66. package/src/components/FunnelStageBuilder/FunnelStageBuilder.stories.tsx +312 -0
  67. package/src/components/FunnelStageBuilder/FunnelStageBuilder.test.tsx +304 -0
  68. package/src/components/FunnelStageBuilder/FunnelStageBuilder.tsx +321 -0
  69. package/src/components/FunnelStageBuilder/README.md +341 -0
  70. package/src/components/FunnelStageBuilder/StageActions.test.tsx +205 -0
  71. package/src/components/FunnelStageBuilder/StageActions.tsx +126 -0
  72. package/src/components/FunnelStageBuilder/StageCard.tsx +202 -0
  73. package/src/components/FunnelStageBuilder/StageForm.tsx +262 -0
  74. package/src/components/FunnelStageBuilder/TagInput.test.tsx +178 -0
  75. package/src/components/FunnelStageBuilder/TagInput.tsx +129 -0
  76. package/src/components/FunnelStageBuilder/index.ts +21 -0
  77. package/src/components/FunnelVisualFlow/FlowLegend.tsx +77 -0
  78. package/{dist/components/index.css → src/components/FunnelVisualFlow/FunnelVisualFlow.css} +89 -13
  79. package/src/components/FunnelVisualFlow/FunnelVisualFlow.stories.tsx +254 -0
  80. package/src/components/FunnelVisualFlow/FunnelVisualFlow.test.tsx +208 -0
  81. package/src/components/FunnelVisualFlow/FunnelVisualFlow.tsx +229 -0
  82. package/src/components/FunnelVisualFlow/README.md +323 -0
  83. package/src/components/FunnelVisualFlow/StageNode.tsx +188 -0
  84. package/src/components/FunnelVisualFlow/example.tsx +227 -0
  85. package/src/components/FunnelVisualFlow/index.ts +10 -0
  86. package/src/components/index.ts +102 -0
  87. package/src/core/README.md +307 -0
  88. package/src/core/engine.test.ts +1087 -0
  89. package/src/core/engine.ts +329 -0
  90. package/src/core/evaluator.example.ts +353 -0
  91. package/src/core/evaluator.test.ts +639 -0
  92. package/src/core/evaluator.ts +261 -0
  93. package/src/core/field-resolver.example.ts +175 -0
  94. package/src/core/field-resolver.test.ts +541 -0
  95. package/src/core/field-resolver.ts +247 -0
  96. package/src/core/index.ts +34 -0
  97. package/src/core/operators.test.ts +539 -0
  98. package/src/core/operators.ts +241 -0
  99. package/src/hooks/index.ts +5 -0
  100. package/src/hooks/useDebouncedValue.ts +28 -0
  101. package/src/index.ts +155 -0
  102. package/src/store/README.md +342 -0
  103. package/src/store/create-funnel-store.test.ts +686 -0
  104. package/src/store/create-funnel-store.ts +538 -0
  105. package/src/store/index.ts +9 -0
  106. package/src/store/types.ts +294 -0
  107. package/src/stories/CrossDomain.stories.tsx +149 -0
  108. package/src/stories/Welcome.stories.tsx +81 -0
  109. package/src/stories/demo-data/index.ts +3 -0
  110. package/src/stories/demo-data/investors.ts +216 -0
  111. package/src/stories/demo-data/leads.ts +223 -0
  112. package/src/stories/demo-data/recipes.ts +217 -0
  113. package/src/test/setup.ts +5 -0
  114. package/src/types/index.ts +843 -0
  115. package/dist/client-3ESO2NHy.d.ts +0 -310
  116. package/dist/client-CZu03ACp.d.cts +0 -310
  117. package/dist/components/index.cjs +0 -3241
  118. package/dist/components/index.cjs.map +0 -1
  119. package/dist/components/index.css.map +0 -1
  120. package/dist/components/index.d.cts +0 -726
  121. package/dist/components/index.d.ts +0 -726
  122. package/dist/components/index.js +0 -3194
  123. package/dist/components/index.js.map +0 -1
  124. package/dist/core/index.cjs +0 -500
  125. package/dist/core/index.cjs.map +0 -1
  126. package/dist/core/index.d.cts +0 -359
  127. package/dist/core/index.d.ts +0 -359
  128. package/dist/core/index.js +0 -486
  129. package/dist/core/index.js.map +0 -1
  130. package/dist/hooks/index.cjs +0 -20
  131. package/dist/hooks/index.cjs.map +0 -1
  132. package/dist/hooks/index.d.cts +0 -11
  133. package/dist/hooks/index.d.ts +0 -11
  134. package/dist/hooks/index.js +0 -18
  135. package/dist/hooks/index.js.map +0 -1
  136. package/dist/index-BGDEXbuz.d.cts +0 -434
  137. package/dist/index-BGDEXbuz.d.ts +0 -434
  138. package/dist/index.cjs +0 -4499
  139. package/dist/index.cjs.map +0 -1
  140. package/dist/index.css +0 -198
  141. package/dist/index.css.map +0 -1
  142. package/dist/index.d.cts +0 -99
  143. package/dist/index.d.ts +0 -99
  144. package/dist/index.js +0 -4421
  145. package/dist/index.js.map +0 -1
  146. package/dist/store/index.cjs +0 -389
  147. package/dist/store/index.cjs.map +0 -1
  148. package/dist/store/index.d.cts +0 -225
  149. package/dist/store/index.d.ts +0 -225
  150. package/dist/store/index.js +0 -386
  151. package/dist/store/index.js.map +0 -1
@@ -1,23 +1,43 @@
1
- /* src/components/FunnelVisualFlow/FunnelVisualFlow.css */
1
+ /**
2
+ * FunnelVisualFlow Styles
3
+ *
4
+ * Design System:
5
+ * - Uses Tailwind-like utility values
6
+ * - Consistent spacing (4px grid)
7
+ * - Clean, minimal aesthetic
8
+ * - Smooth transitions
9
+ */
10
+
11
+ /* =============================================================================
12
+ * Flow Container
13
+ * ============================================================================= */
14
+
2
15
  .funnel-visual-flow {
3
16
  position: relative;
4
17
  width: 100%;
5
- background: #f9fafb;
18
+ background: #f9fafb; /* gray-50 */
6
19
  border-radius: 8px;
7
20
  overflow: hidden;
8
21
  }
22
+
9
23
  .funnel-visual-flow-empty {
10
24
  display: flex;
11
25
  align-items: center;
12
26
  justify-content: center;
13
27
  background: #f9fafb;
14
- border: 2px dashed #d1d5db;
28
+ border: 2px dashed #d1d5db; /* gray-300 */
15
29
  border-radius: 8px;
16
30
  }
31
+
17
32
  .empty-state {
18
33
  text-align: center;
19
34
  padding: 32px;
20
35
  }
36
+
37
+ /* =============================================================================
38
+ * Stage Node
39
+ * ============================================================================= */
40
+
21
41
  .stage-node {
22
42
  padding: 16px;
23
43
  border-radius: 8px;
@@ -29,34 +49,44 @@
29
49
  cursor: pointer;
30
50
  transition: all 0.2s ease;
31
51
  }
52
+
32
53
  .stage-node:hover {
33
54
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
34
55
  transform: translateY(-2px);
35
56
  }
57
+
36
58
  .stage-node:focus {
37
59
  outline: none;
38
60
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.3);
39
61
  }
62
+
63
+ /* Stage number (circled number) */
40
64
  .stage-number {
41
65
  font-size: 28px;
42
66
  font-weight: 700;
43
67
  line-height: 1;
44
68
  margin-bottom: 8px;
45
69
  }
70
+
71
+ /* Stage name */
46
72
  .stage-name {
47
73
  font-size: 16px;
48
74
  font-weight: 600;
49
- color: #111827;
75
+ color: #111827; /* gray-900 */
50
76
  margin-bottom: 4px;
51
77
  overflow: hidden;
52
78
  text-overflow: ellipsis;
53
79
  white-space: nowrap;
54
80
  }
81
+
82
+ /* Rule count */
55
83
  .stage-rules {
56
84
  font-size: 13px;
57
- color: #6b7280;
85
+ color: #6b7280; /* gray-500 */
58
86
  margin-bottom: 6px;
59
87
  }
88
+
89
+ /* Action label */
60
90
  .stage-action {
61
91
  font-size: 12px;
62
92
  font-weight: 600;
@@ -64,38 +94,51 @@
64
94
  letter-spacing: 0.5px;
65
95
  margin-bottom: 8px;
66
96
  }
97
+
98
+ /* Stats section */
67
99
  .stage-stats {
68
100
  margin-top: 12px;
69
101
  padding-top: 12px;
70
- border-top: 1px solid #e5e7eb;
102
+ border-top: 1px solid #e5e7eb; /* gray-200 */
71
103
  }
104
+
72
105
  .stat-row {
73
106
  display: flex;
74
107
  justify-content: space-between;
75
108
  font-size: 13px;
76
109
  margin-bottom: 4px;
77
110
  }
111
+
78
112
  .stat-label {
79
- color: #6b7280;
113
+ color: #6b7280; /* gray-500 */
80
114
  font-weight: 500;
81
115
  }
116
+
82
117
  .stat-value {
83
118
  font-weight: 600;
84
- color: #111827;
119
+ color: #111827; /* gray-900 */
85
120
  }
121
+
122
+ /* Description (if shown) */
86
123
  .stage-description {
87
124
  margin-top: 8px;
88
125
  font-size: 12px;
89
- color: #9ca3af;
126
+ color: #9ca3af; /* gray-400 */
90
127
  font-style: italic;
91
128
  overflow: hidden;
92
129
  text-overflow: ellipsis;
93
130
  white-space: nowrap;
94
131
  }
132
+
133
+ /* =============================================================================
134
+ * Flow Legend
135
+ * ============================================================================= */
136
+
95
137
  .flow-legend-panel {
96
138
  background: transparent;
97
139
  border: none;
98
140
  }
141
+
99
142
  .flow-legend {
100
143
  background: white;
101
144
  border-radius: 8px;
@@ -103,6 +146,7 @@
103
146
  padding: 12px;
104
147
  min-width: 140px;
105
148
  }
149
+
106
150
  .legend-toggle {
107
151
  width: 100%;
108
152
  display: flex;
@@ -114,85 +158,117 @@
114
158
  padding: 0;
115
159
  margin-bottom: 8px;
116
160
  }
161
+
117
162
  .legend-toggle:hover {
118
163
  opacity: 0.8;
119
164
  }
165
+
120
166
  .legend-toggle:focus {
121
167
  outline: 2px solid #3b82f6;
122
168
  outline-offset: 2px;
123
169
  border-radius: 4px;
124
170
  }
171
+
125
172
  .legend-title {
126
173
  font-size: 13px;
127
174
  font-weight: 600;
128
- color: #374151;
175
+ color: #374151; /* gray-700 */
129
176
  }
177
+
130
178
  .legend-chevron {
131
179
  transition: transform 0.2s ease;
132
- color: #6b7280;
180
+ color: #6b7280; /* gray-500 */
133
181
  }
182
+
134
183
  .legend-chevron.expanded {
135
184
  transform: rotate(180deg);
136
185
  }
186
+
137
187
  .legend-items {
138
188
  display: flex;
139
189
  flex-direction: column;
140
190
  gap: 8px;
141
191
  }
192
+
142
193
  .legend-item {
143
194
  display: flex;
144
195
  align-items: center;
145
196
  gap: 8px;
146
197
  }
198
+
147
199
  .legend-color {
148
200
  width: 16px;
149
201
  height: 16px;
150
202
  border-radius: 4px;
151
203
  flex-shrink: 0;
152
204
  }
205
+
153
206
  .legend-label {
154
207
  font-size: 12px;
155
- color: #4b5563;
208
+ color: #4b5563; /* gray-600 */
156
209
  font-weight: 500;
157
210
  }
211
+
212
+ /* =============================================================================
213
+ * React Flow Overrides
214
+ * ============================================================================= */
215
+
216
+ /* Make edges more visible */
158
217
  .react-flow__edge-path {
159
218
  stroke-width: 2;
160
219
  }
220
+
221
+ /* Edge labels */
161
222
  .react-flow__edge-text {
162
223
  font-size: 12px;
163
224
  font-weight: 600;
164
225
  }
226
+
227
+ /* Controls */
165
228
  .react-flow__controls {
166
229
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
167
230
  }
231
+
168
232
  .react-flow__controls-button {
169
233
  border-bottom: 1px solid #e5e7eb;
170
234
  }
235
+
171
236
  .react-flow__controls-button:hover {
172
237
  background: #f3f4f6;
173
238
  }
239
+
240
+ /* Background */
174
241
  .react-flow__background {
175
242
  background-color: #f9fafb;
176
243
  }
244
+
245
+ /* Attribution */
177
246
  .react-flow__attribution {
178
247
  opacity: 0.5;
179
248
  font-size: 10px;
180
249
  }
250
+
251
+ /* =============================================================================
252
+ * Responsive Design
253
+ * ============================================================================= */
254
+
181
255
  @media (max-width: 640px) {
182
256
  .stage-node {
183
257
  min-width: 180px;
184
258
  max-width: 220px;
185
259
  padding: 12px;
186
260
  }
261
+
187
262
  .stage-number {
188
263
  font-size: 24px;
189
264
  }
265
+
190
266
  .stage-name {
191
267
  font-size: 14px;
192
268
  }
269
+
193
270
  .flow-legend {
194
271
  min-width: 120px;
195
272
  padding: 8px;
196
273
  }
197
274
  }
198
- /*# sourceMappingURL=index.css.map */
@@ -0,0 +1,254 @@
1
+ /**
2
+ * FunnelVisualFlow Storybook Stories
3
+ *
4
+ * Visual testing and documentation for the FunnelVisualFlow component.
5
+ *
6
+ * Stories:
7
+ * 1. Empty (no stages)
8
+ * 2. Single stage
9
+ * 3. Simple funnel (3 stages)
10
+ * 4. Complex funnel (5+ stages)
11
+ * 5. With run data (shows stats)
12
+ * 6. Different action types (color coding)
13
+ * 7. Interactive (click callbacks)
14
+ */
15
+
16
+ import type { Meta, StoryObj } from '@storybook/react';
17
+ import { FunnelVisualFlow } from './FunnelVisualFlow';
18
+ import { Funnel, FunnelStage, FunnelRun } from '../../types';
19
+
20
+ const meta: Meta<typeof FunnelVisualFlow> = {
21
+ title: 'Components/FunnelVisualFlow',
22
+ component: FunnelVisualFlow,
23
+ parameters: {
24
+ layout: 'fullscreen',
25
+ },
26
+ tags: ['autodocs'],
27
+ };
28
+
29
+ export default meta;
30
+ type Story = StoryObj<typeof FunnelVisualFlow>;
31
+
32
+ // Helper to create stages
33
+ const createStage = (
34
+ id: string,
35
+ name: string,
36
+ order: number,
37
+ matchAction: any = 'continue',
38
+ noMatchAction: any = 'exclude'
39
+ ): FunnelStage => ({
40
+ id,
41
+ order,
42
+ name,
43
+ description: `${name} stage filters entities`,
44
+ filter_logic: 'AND',
45
+ rules: [
46
+ {
47
+ field_path: 'score',
48
+ operator: 'gte',
49
+ value: 50,
50
+ },
51
+ {
52
+ field_path: 'status',
53
+ operator: 'eq',
54
+ value: 'active',
55
+ },
56
+ ],
57
+ match_action: matchAction,
58
+ no_match_action: noMatchAction,
59
+ });
60
+
61
+ // Helper to create funnel
62
+ const createFunnel = (
63
+ stages: FunnelStage[],
64
+ name: string = 'Sample Funnel'
65
+ ): Funnel => ({
66
+ id: 'funnel-1',
67
+ name,
68
+ description: 'A sample funnel for visualization',
69
+ status: 'active',
70
+ input_type: 'contacts',
71
+ stages,
72
+ created_at: new Date().toISOString(),
73
+ updated_at: new Date().toISOString(),
74
+ });
75
+
76
+ // Empty state
77
+ export const Empty: Story = {
78
+ args: {
79
+ funnel: createFunnel([]),
80
+ height: 400,
81
+ },
82
+ };
83
+
84
+ // Single stage
85
+ export const SingleStage: Story = {
86
+ args: {
87
+ funnel: createFunnel([createStage('stage-1', 'High ICP Score', 0)]),
88
+ height: 400,
89
+ },
90
+ };
91
+
92
+ // Simple funnel (3 stages)
93
+ export const SimpleFunnel: Story = {
94
+ args: {
95
+ funnel: createFunnel(
96
+ [
97
+ createStage('stage-1', 'High ICP Score', 0),
98
+ createStage('stage-2', 'Frontend Stack', 1),
99
+ createStage('stage-3', 'Testing Tools', 2, 'output', 'exclude'),
100
+ ],
101
+ 'Frontend Developer Funnel'
102
+ ),
103
+ height: 600,
104
+ },
105
+ };
106
+
107
+ // Complex funnel (5 stages)
108
+ export const ComplexFunnel: Story = {
109
+ args: {
110
+ funnel: createFunnel(
111
+ [
112
+ createStage('stage-1', 'High ICP Score', 0),
113
+ createStage('stage-2', 'Frontend Stack', 1),
114
+ createStage('stage-3', 'Testing Tools', 2),
115
+ createStage('stage-4', 'Likely SMB', 3),
116
+ createStage('stage-5', 'Not Enterprise', 4, 'output', 'exclude'),
117
+ ],
118
+ 'SMB Frontend Developer Funnel'
119
+ ),
120
+ height: 800,
121
+ },
122
+ };
123
+
124
+ // With run data (shows stats)
125
+ export const WithRunData: Story = {
126
+ args: {
127
+ funnel: createFunnel(
128
+ [
129
+ createStage('stage-1', 'High ICP Score', 0),
130
+ createStage('stage-2', 'Frontend Stack', 1),
131
+ createStage('stage-3', 'Testing Tools', 2, 'output', 'exclude'),
132
+ ],
133
+ 'Frontend Developer Funnel'
134
+ ),
135
+ runData: {
136
+ id: 'run-1',
137
+ funnel_id: 'funnel-1',
138
+ status: 'completed',
139
+ trigger_type: 'manual',
140
+ started_at: new Date().toISOString(),
141
+ completed_at: new Date().toISOString(),
142
+ duration_ms: 1234,
143
+ total_input: 1000,
144
+ total_matched: 235,
145
+ total_excluded: 765,
146
+ total_tagged: 0,
147
+ stage_stats: {
148
+ 'stage-1': {
149
+ stage_id: 'stage-1',
150
+ stage_name: 'High ICP Score',
151
+ input_count: 1000,
152
+ matched_count: 500,
153
+ not_matched_count: 500,
154
+ excluded_count: 500,
155
+ tagged_count: 0,
156
+ continued_count: 500,
157
+ },
158
+ 'stage-2': {
159
+ stage_id: 'stage-2',
160
+ stage_name: 'Frontend Stack',
161
+ input_count: 500,
162
+ matched_count: 350,
163
+ not_matched_count: 150,
164
+ excluded_count: 150,
165
+ tagged_count: 0,
166
+ continued_count: 350,
167
+ },
168
+ 'stage-3': {
169
+ stage_id: 'stage-3',
170
+ stage_name: 'Testing Tools',
171
+ input_count: 350,
172
+ matched_count: 235,
173
+ not_matched_count: 115,
174
+ excluded_count: 115,
175
+ tagged_count: 0,
176
+ continued_count: 235,
177
+ },
178
+ },
179
+ } as FunnelRun,
180
+ height: 600,
181
+ },
182
+ };
183
+
184
+ // Different action types (color coding)
185
+ export const ActionTypes: Story = {
186
+ args: {
187
+ funnel: createFunnel(
188
+ [
189
+ createStage('stage-1', 'Continue Action', 0, 'continue', 'continue'),
190
+ createStage('stage-2', 'Tag Action', 1, 'tag', 'continue'),
191
+ createStage('stage-3', 'Tag & Continue', 2, 'tag_continue', 'exclude'),
192
+ createStage('stage-4', 'Exclude Action', 3, 'continue', 'exclude'),
193
+ createStage('stage-5', 'Output Action', 4, 'output', 'exclude'),
194
+ ],
195
+ 'Action Types Demo'
196
+ ),
197
+ height: 800,
198
+ },
199
+ };
200
+
201
+ // Interactive (with callbacks)
202
+ export const Interactive: Story = {
203
+ args: {
204
+ funnel: createFunnel(
205
+ [
206
+ createStage('stage-1', 'High ICP Score', 0),
207
+ createStage('stage-2', 'Frontend Stack', 1),
208
+ createStage('stage-3', 'Testing Tools', 2, 'output', 'exclude'),
209
+ ],
210
+ 'Interactive Funnel'
211
+ ),
212
+ onStageClick: (stage: FunnelStage) => {
213
+ alert(`Clicked stage: ${stage.name}`);
214
+ },
215
+ onEdgeClick: (fromStage: string, toStage: string) => {
216
+ alert(`Clicked edge from ${fromStage} to ${toStage}`);
217
+ },
218
+ height: 600,
219
+ },
220
+ };
221
+
222
+ // Custom height
223
+ export const CustomHeight: Story = {
224
+ args: {
225
+ funnel: createFunnel(
226
+ [
227
+ createStage('stage-1', 'High ICP Score', 0),
228
+ createStage('stage-2', 'Frontend Stack', 1),
229
+ createStage('stage-3', 'Testing Tools', 2, 'output', 'exclude'),
230
+ ],
231
+ 'Custom Height Funnel'
232
+ ),
233
+ height: 400,
234
+ },
235
+ };
236
+
237
+ // Large funnel (10 stages)
238
+ export const LargeFunnel: Story = {
239
+ args: {
240
+ funnel: createFunnel(
241
+ Array.from({ length: 10 }, (_, i) =>
242
+ createStage(
243
+ `stage-${i + 1}`,
244
+ `Stage ${i + 1}`,
245
+ i,
246
+ i === 9 ? 'output' : 'continue',
247
+ 'exclude'
248
+ )
249
+ ),
250
+ 'Large Funnel (10 Stages)'
251
+ ),
252
+ height: 1000,
253
+ },
254
+ };