@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.
- package/package.json +9 -31
- package/src/api/README.md +507 -0
- package/src/api/adapter.ts +106 -0
- package/src/api/client.test.ts +640 -0
- package/src/api/client.ts +385 -0
- package/src/api/default-adapter.ts +243 -0
- package/src/api/index.ts +24 -0
- package/src/components/FilterRuleEditor/ARCHITECTURE.md +354 -0
- package/src/components/FilterRuleEditor/FieldSelector.tsx +91 -0
- package/src/components/FilterRuleEditor/FilterRuleEditor.stories.tsx +462 -0
- package/src/components/FilterRuleEditor/FilterRuleEditor.test.tsx +520 -0
- package/src/components/FilterRuleEditor/FilterRuleEditor.tsx +225 -0
- package/src/components/FilterRuleEditor/LogicToggle.tsx +64 -0
- package/src/components/FilterRuleEditor/OperatorSelector.tsx +75 -0
- package/src/components/FilterRuleEditor/README.md +291 -0
- package/src/components/FilterRuleEditor/RuleRow.tsx +246 -0
- package/src/components/FilterRuleEditor/ValueInputs/BooleanValueInput.tsx +54 -0
- package/src/components/FilterRuleEditor/ValueInputs/ChoiceValueInput.tsx +83 -0
- package/src/components/FilterRuleEditor/ValueInputs/DateValueInput.tsx +70 -0
- package/src/components/FilterRuleEditor/ValueInputs/MultiChoiceValueInput.tsx +132 -0
- package/src/components/FilterRuleEditor/ValueInputs/NumberValueInput.tsx +73 -0
- package/src/components/FilterRuleEditor/ValueInputs/TextValueInput.tsx +50 -0
- package/src/components/FilterRuleEditor/ValueInputs/index.ts +12 -0
- package/src/components/FilterRuleEditor/constants.ts +64 -0
- package/src/components/FilterRuleEditor/index.ts +14 -0
- package/src/components/FunnelCard/DESIGN.md +447 -0
- package/src/components/FunnelCard/FunnelCard.stories.tsx +484 -0
- package/src/components/FunnelCard/FunnelCard.test.ts +257 -0
- package/src/components/FunnelCard/FunnelCard.test.tsx +336 -0
- package/src/components/FunnelCard/FunnelCard.tsx +204 -0
- package/src/components/FunnelCard/FunnelStats.tsx +68 -0
- package/src/components/FunnelCard/IMPLEMENTATION_SUMMARY.md +505 -0
- package/src/components/FunnelCard/INSTALLATION.md +304 -0
- package/src/components/FunnelCard/MatchBar.tsx +49 -0
- package/src/components/FunnelCard/README.md +294 -0
- package/src/components/FunnelCard/StageIndicator.tsx +62 -0
- package/src/components/FunnelCard/StatusBadge.tsx +52 -0
- package/src/components/FunnelCard/index.ts +14 -0
- package/src/components/FunnelPreview/EntityCard.tsx +72 -0
- package/src/components/FunnelPreview/FunnelPreview.stories.tsx +227 -0
- package/src/components/FunnelPreview/FunnelPreview.test.tsx +316 -0
- package/src/components/FunnelPreview/FunnelPreview.tsx +249 -0
- package/src/components/FunnelPreview/LoadingPreview.tsx +60 -0
- package/src/components/FunnelPreview/PreviewStats.tsx +78 -0
- package/src/components/FunnelPreview/README.md +337 -0
- package/src/components/FunnelPreview/StageBreakdown.tsx +94 -0
- package/src/components/FunnelPreview/example.tsx +286 -0
- package/src/components/FunnelPreview/index.ts +14 -0
- package/src/components/FunnelRunHistory/COMPONENT_SUMMARY.md +246 -0
- package/src/components/FunnelRunHistory/FunnelRunHistory.stories.tsx +272 -0
- package/src/components/FunnelRunHistory/FunnelRunHistory.test.tsx +323 -0
- package/src/components/FunnelRunHistory/FunnelRunHistory.tsx +329 -0
- package/src/components/FunnelRunHistory/README.md +325 -0
- package/src/components/FunnelRunHistory/RunActions.tsx +168 -0
- package/src/components/FunnelRunHistory/RunDetailsModal.tsx +221 -0
- package/src/components/FunnelRunHistory/RunFilters.tsx +128 -0
- package/src/components/FunnelRunHistory/RunRow.tsx +122 -0
- package/src/components/FunnelRunHistory/RunStatusBadge.tsx +75 -0
- package/src/components/FunnelRunHistory/StageBreakdownList.tsx +110 -0
- package/src/components/FunnelRunHistory/index.ts +51 -0
- package/src/components/FunnelRunHistory/types.ts +40 -0
- package/src/components/FunnelRunHistory/utils.test.ts +126 -0
- package/src/components/FunnelRunHistory/utils.ts +100 -0
- package/src/components/FunnelStageBuilder/AddStageButton.tsx +52 -0
- package/src/components/FunnelStageBuilder/FunnelStageBuilder.css +413 -0
- package/src/components/FunnelStageBuilder/FunnelStageBuilder.stories.tsx +312 -0
- package/src/components/FunnelStageBuilder/FunnelStageBuilder.test.tsx +304 -0
- package/src/components/FunnelStageBuilder/FunnelStageBuilder.tsx +321 -0
- package/src/components/FunnelStageBuilder/README.md +341 -0
- package/src/components/FunnelStageBuilder/StageActions.test.tsx +205 -0
- package/src/components/FunnelStageBuilder/StageActions.tsx +126 -0
- package/src/components/FunnelStageBuilder/StageCard.tsx +202 -0
- package/src/components/FunnelStageBuilder/StageForm.tsx +262 -0
- package/src/components/FunnelStageBuilder/TagInput.test.tsx +178 -0
- package/src/components/FunnelStageBuilder/TagInput.tsx +129 -0
- package/src/components/FunnelStageBuilder/index.ts +21 -0
- package/src/components/FunnelVisualFlow/FlowLegend.tsx +77 -0
- package/{dist/components/index.css → src/components/FunnelVisualFlow/FunnelVisualFlow.css} +89 -13
- package/src/components/FunnelVisualFlow/FunnelVisualFlow.stories.tsx +254 -0
- package/src/components/FunnelVisualFlow/FunnelVisualFlow.test.tsx +208 -0
- package/src/components/FunnelVisualFlow/FunnelVisualFlow.tsx +229 -0
- package/src/components/FunnelVisualFlow/README.md +323 -0
- package/src/components/FunnelVisualFlow/StageNode.tsx +188 -0
- package/src/components/FunnelVisualFlow/example.tsx +227 -0
- package/src/components/FunnelVisualFlow/index.ts +10 -0
- package/src/components/index.ts +102 -0
- package/src/core/README.md +307 -0
- package/src/core/engine.test.ts +1087 -0
- package/src/core/engine.ts +329 -0
- package/src/core/evaluator.example.ts +353 -0
- package/src/core/evaluator.test.ts +639 -0
- package/src/core/evaluator.ts +261 -0
- package/src/core/field-resolver.example.ts +175 -0
- package/src/core/field-resolver.test.ts +541 -0
- package/src/core/field-resolver.ts +247 -0
- package/src/core/index.ts +34 -0
- package/src/core/operators.test.ts +539 -0
- package/src/core/operators.ts +241 -0
- package/src/hooks/index.ts +5 -0
- package/src/hooks/useDebouncedValue.ts +28 -0
- package/src/index.ts +155 -0
- package/src/store/README.md +342 -0
- package/src/store/create-funnel-store.test.ts +686 -0
- package/src/store/create-funnel-store.ts +538 -0
- package/src/store/index.ts +9 -0
- package/src/store/types.ts +294 -0
- package/src/stories/CrossDomain.stories.tsx +149 -0
- package/src/stories/Welcome.stories.tsx +81 -0
- package/src/stories/demo-data/index.ts +3 -0
- package/src/stories/demo-data/investors.ts +216 -0
- package/src/stories/demo-data/leads.ts +223 -0
- package/src/stories/demo-data/recipes.ts +217 -0
- package/src/test/setup.ts +5 -0
- package/src/types/index.ts +843 -0
- package/dist/client-3ESO2NHy.d.ts +0 -310
- package/dist/client-CZu03ACp.d.cts +0 -310
- package/dist/components/index.cjs +0 -3241
- package/dist/components/index.cjs.map +0 -1
- package/dist/components/index.css.map +0 -1
- package/dist/components/index.d.cts +0 -726
- package/dist/components/index.d.ts +0 -726
- package/dist/components/index.js +0 -3194
- package/dist/components/index.js.map +0 -1
- package/dist/core/index.cjs +0 -500
- package/dist/core/index.cjs.map +0 -1
- package/dist/core/index.d.cts +0 -359
- package/dist/core/index.d.ts +0 -359
- package/dist/core/index.js +0 -486
- package/dist/core/index.js.map +0 -1
- package/dist/hooks/index.cjs +0 -20
- package/dist/hooks/index.cjs.map +0 -1
- package/dist/hooks/index.d.cts +0 -11
- package/dist/hooks/index.d.ts +0 -11
- package/dist/hooks/index.js +0 -18
- package/dist/hooks/index.js.map +0 -1
- package/dist/index-BGDEXbuz.d.cts +0 -434
- package/dist/index-BGDEXbuz.d.ts +0 -434
- package/dist/index.cjs +0 -4499
- package/dist/index.cjs.map +0 -1
- package/dist/index.css +0 -198
- package/dist/index.css.map +0 -1
- package/dist/index.d.cts +0 -99
- package/dist/index.d.ts +0 -99
- package/dist/index.js +0 -4421
- package/dist/index.js.map +0 -1
- package/dist/store/index.cjs +0 -389
- package/dist/store/index.cjs.map +0 -1
- package/dist/store/index.d.cts +0 -225
- package/dist/store/index.d.ts +0 -225
- package/dist/store/index.js +0 -386
- package/dist/store/index.js.map +0 -1
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @startsimpli/funnels - Operator Implementation
|
|
3
|
+
*
|
|
4
|
+
* BRUTALLY GENERIC operator logic that works with ANY data type.
|
|
5
|
+
*
|
|
6
|
+
* Each operator is a pure function: (actual, expected) => boolean
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { Operator } from '../types';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Apply an operator to compare actual vs expected values
|
|
13
|
+
*
|
|
14
|
+
* @param operator - The comparison operator
|
|
15
|
+
* @param actual - The actual value from entity
|
|
16
|
+
* @param expected - The expected value from rule
|
|
17
|
+
* @returns Whether the comparison passes
|
|
18
|
+
*/
|
|
19
|
+
export function applyOperator(
|
|
20
|
+
operator: Operator,
|
|
21
|
+
actual: any,
|
|
22
|
+
expected: any
|
|
23
|
+
): boolean {
|
|
24
|
+
switch (operator) {
|
|
25
|
+
// ========================================================================
|
|
26
|
+
// Equality
|
|
27
|
+
// ========================================================================
|
|
28
|
+
case 'eq':
|
|
29
|
+
return compareValues(actual, expected, (a, e) => a === e);
|
|
30
|
+
|
|
31
|
+
case 'ne':
|
|
32
|
+
return compareValues(actual, expected, (a, e) => a !== e);
|
|
33
|
+
|
|
34
|
+
// ========================================================================
|
|
35
|
+
// Comparison (numbers, dates, strings)
|
|
36
|
+
// ========================================================================
|
|
37
|
+
case 'gt':
|
|
38
|
+
return compareValues(actual, expected, (a, e) => a > e);
|
|
39
|
+
|
|
40
|
+
case 'lt':
|
|
41
|
+
return compareValues(actual, expected, (a, e) => a < e);
|
|
42
|
+
|
|
43
|
+
case 'gte':
|
|
44
|
+
return compareValues(actual, expected, (a, e) => a >= e);
|
|
45
|
+
|
|
46
|
+
case 'lte':
|
|
47
|
+
return compareValues(actual, expected, (a, e) => a <= e);
|
|
48
|
+
|
|
49
|
+
// ========================================================================
|
|
50
|
+
// String operations (case-insensitive)
|
|
51
|
+
// ========================================================================
|
|
52
|
+
case 'contains':
|
|
53
|
+
if (actual == null) return false;
|
|
54
|
+
if (expected == null) return false;
|
|
55
|
+
return String(actual).toLowerCase().includes(String(expected).toLowerCase());
|
|
56
|
+
|
|
57
|
+
case 'not_contains':
|
|
58
|
+
if (actual == null) return true; // null doesn't contain anything
|
|
59
|
+
if (expected == null) return true;
|
|
60
|
+
return !String(actual).toLowerCase().includes(String(expected).toLowerCase());
|
|
61
|
+
|
|
62
|
+
case 'startswith':
|
|
63
|
+
if (actual == null) return false;
|
|
64
|
+
if (expected == null) return false;
|
|
65
|
+
return String(actual).toLowerCase().startsWith(String(expected).toLowerCase());
|
|
66
|
+
|
|
67
|
+
case 'endswith':
|
|
68
|
+
if (actual == null) return false;
|
|
69
|
+
if (expected == null) return false;
|
|
70
|
+
return String(actual).toLowerCase().endsWith(String(expected).toLowerCase());
|
|
71
|
+
|
|
72
|
+
case 'matches':
|
|
73
|
+
if (actual == null) return false;
|
|
74
|
+
if (expected == null) return false;
|
|
75
|
+
try {
|
|
76
|
+
const regex = new RegExp(String(expected));
|
|
77
|
+
return regex.test(String(actual));
|
|
78
|
+
} catch {
|
|
79
|
+
// Invalid regex pattern
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ========================================================================
|
|
84
|
+
// Array/Set operations
|
|
85
|
+
// ========================================================================
|
|
86
|
+
case 'in':
|
|
87
|
+
// Value is in array: actual IN expected[]
|
|
88
|
+
if (!Array.isArray(expected)) return false;
|
|
89
|
+
return expected.some(item => compareValues(actual, item, (a, e) => a === e));
|
|
90
|
+
|
|
91
|
+
case 'not_in':
|
|
92
|
+
// Value is not in array: actual NOT IN expected[]
|
|
93
|
+
if (!Array.isArray(expected)) return true;
|
|
94
|
+
return !expected.some(item => compareValues(actual, item, (a, e) => a === e));
|
|
95
|
+
|
|
96
|
+
case 'has_any':
|
|
97
|
+
// Array has any of values: actual[] HAS ANY expected[]
|
|
98
|
+
if (!Array.isArray(actual)) return false;
|
|
99
|
+
if (!Array.isArray(expected)) return false;
|
|
100
|
+
return expected.some(expectedItem =>
|
|
101
|
+
actual.some(actualItem => compareValues(actualItem, expectedItem, (a, e) => a === e))
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
case 'has_all':
|
|
105
|
+
// Array has all values: actual[] HAS ALL expected[]
|
|
106
|
+
if (!Array.isArray(actual)) return false;
|
|
107
|
+
if (!Array.isArray(expected)) return false;
|
|
108
|
+
return expected.every(expectedItem =>
|
|
109
|
+
actual.some(actualItem => compareValues(actualItem, expectedItem, (a, e) => a === e))
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
// ========================================================================
|
|
113
|
+
// Null checks
|
|
114
|
+
// ========================================================================
|
|
115
|
+
case 'isnull':
|
|
116
|
+
return actual === null || actual === undefined;
|
|
117
|
+
|
|
118
|
+
case 'isnotnull':
|
|
119
|
+
return actual !== null && actual !== undefined;
|
|
120
|
+
|
|
121
|
+
// ========================================================================
|
|
122
|
+
// Tag operations (tags are arrays of strings)
|
|
123
|
+
// ========================================================================
|
|
124
|
+
case 'has_tag':
|
|
125
|
+
if (!Array.isArray(actual)) return false;
|
|
126
|
+
if (expected == null) return false;
|
|
127
|
+
// Case-insensitive tag match
|
|
128
|
+
const expectedTag = String(expected).toLowerCase();
|
|
129
|
+
return actual.some(tag => String(tag).toLowerCase() === expectedTag);
|
|
130
|
+
|
|
131
|
+
case 'not_has_tag':
|
|
132
|
+
if (!Array.isArray(actual)) return true; // No tags = doesn't have tag
|
|
133
|
+
if (expected == null) return true;
|
|
134
|
+
const expectedTagNot = String(expected).toLowerCase();
|
|
135
|
+
return !actual.some(tag => String(tag).toLowerCase() === expectedTagNot);
|
|
136
|
+
|
|
137
|
+
// ========================================================================
|
|
138
|
+
// Boolean
|
|
139
|
+
// ========================================================================
|
|
140
|
+
case 'is_true':
|
|
141
|
+
return actual === true;
|
|
142
|
+
|
|
143
|
+
case 'is_false':
|
|
144
|
+
return actual === false;
|
|
145
|
+
|
|
146
|
+
default:
|
|
147
|
+
throw new Error(`Unknown operator: ${operator}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Compare values with type normalization
|
|
153
|
+
*
|
|
154
|
+
* Handles:
|
|
155
|
+
* - Numbers: direct comparison
|
|
156
|
+
* - Dates: convert to timestamps
|
|
157
|
+
* - Strings: direct comparison (operators handle case-sensitivity)
|
|
158
|
+
* - null/undefined: handle gracefully
|
|
159
|
+
*/
|
|
160
|
+
function compareValues(
|
|
161
|
+
actual: any,
|
|
162
|
+
expected: any,
|
|
163
|
+
compare: (a: any, e: any) => boolean
|
|
164
|
+
): boolean {
|
|
165
|
+
// Handle null/undefined
|
|
166
|
+
if (actual === null || actual === undefined) {
|
|
167
|
+
return expected === null || expected === undefined;
|
|
168
|
+
}
|
|
169
|
+
if (expected === null || expected === undefined) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Both are dates - convert to timestamps
|
|
174
|
+
if (isDate(actual) && isDate(expected)) {
|
|
175
|
+
const actualTs = toTimestamp(actual);
|
|
176
|
+
const expectedTs = toTimestamp(expected);
|
|
177
|
+
if (actualTs === null || expectedTs === null) return false;
|
|
178
|
+
return compare(actualTs, expectedTs);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// One is date - try to parse the other
|
|
182
|
+
if (isDate(actual) || isDate(expected)) {
|
|
183
|
+
const actualTs = toTimestamp(actual);
|
|
184
|
+
const expectedTs = toTimestamp(expected);
|
|
185
|
+
if (actualTs === null || expectedTs === null) return false;
|
|
186
|
+
return compare(actualTs, expectedTs);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Both are numbers
|
|
190
|
+
if (typeof actual === 'number' && typeof expected === 'number') {
|
|
191
|
+
return compare(actual, expected);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Try to convert to numbers if they look numeric
|
|
195
|
+
if (isNumeric(actual) && isNumeric(expected)) {
|
|
196
|
+
return compare(Number(actual), Number(expected));
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Default: direct comparison
|
|
200
|
+
return compare(actual, expected);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Check if value is a Date object or date string
|
|
205
|
+
*/
|
|
206
|
+
function isDate(value: any): boolean {
|
|
207
|
+
if (value instanceof Date) return true;
|
|
208
|
+
if (typeof value !== 'string') return false;
|
|
209
|
+
|
|
210
|
+
// Check if string looks like a date
|
|
211
|
+
const datePattern = /^\d{4}-\d{2}-\d{2}|^\d{1,2}\/\d{1,2}\/\d{4}/;
|
|
212
|
+
return datePattern.test(value);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Convert value to timestamp (milliseconds since epoch)
|
|
217
|
+
* Returns null if conversion fails
|
|
218
|
+
*/
|
|
219
|
+
function toTimestamp(value: any): number | null {
|
|
220
|
+
if (value instanceof Date) {
|
|
221
|
+
const ts = value.getTime();
|
|
222
|
+
return isNaN(ts) ? null : ts;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (typeof value === 'string' || typeof value === 'number') {
|
|
226
|
+
const date = new Date(value);
|
|
227
|
+
const ts = date.getTime();
|
|
228
|
+
return isNaN(ts) ? null : ts;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Check if value is numeric (number or numeric string)
|
|
236
|
+
*/
|
|
237
|
+
function isNumeric(value: any): boolean {
|
|
238
|
+
if (typeof value === 'number') return !isNaN(value);
|
|
239
|
+
if (typeof value !== 'string') return false;
|
|
240
|
+
return !isNaN(Number(value)) && value.trim() !== '';
|
|
241
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useDebouncedValue Hook
|
|
3
|
+
*
|
|
4
|
+
* Returns a debounced version of the input value that only updates
|
|
5
|
+
* after the specified delay has elapsed without changes.
|
|
6
|
+
*
|
|
7
|
+
* Use for expensive computations that shouldn't run on every keystroke.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { useEffect, useState } from 'react';
|
|
11
|
+
|
|
12
|
+
export function useDebouncedValue<T>(value: T, delay: number = 300): T {
|
|
13
|
+
const [debouncedValue, setDebouncedValue] = useState<T>(value);
|
|
14
|
+
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
// Set timeout to update debounced value after delay
|
|
17
|
+
const handler = setTimeout(() => {
|
|
18
|
+
setDebouncedValue(value);
|
|
19
|
+
}, delay);
|
|
20
|
+
|
|
21
|
+
// Cleanup: cancel timeout if value changes before delay elapses
|
|
22
|
+
return () => {
|
|
23
|
+
clearTimeout(handler);
|
|
24
|
+
};
|
|
25
|
+
}, [value, delay]);
|
|
26
|
+
|
|
27
|
+
return debouncedValue;
|
|
28
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @startsimpli/funnels
|
|
3
|
+
*
|
|
4
|
+
* BRUTALLY GENERIC funnel system for filtering and processing ANY entity type.
|
|
5
|
+
*
|
|
6
|
+
* Works for:
|
|
7
|
+
* - Investors, firms, contacts, organizations
|
|
8
|
+
* - Recipes, ingredients, cooking instructions
|
|
9
|
+
* - Leads, opportunities, tasks, projects
|
|
10
|
+
* - GitHub repos, PRs, issues, users
|
|
11
|
+
* - Products, orders, customers, shipments
|
|
12
|
+
* - Literally ANY data that needs sequential filtering
|
|
13
|
+
*
|
|
14
|
+
* Core concept:
|
|
15
|
+
* 1. Start with entities (any type)
|
|
16
|
+
* 2. Apply sequential filter stages
|
|
17
|
+
* 3. Each stage: keep/exclude/tag based on rules
|
|
18
|
+
* 4. End with filtered subset + accumulated tags/context
|
|
19
|
+
*
|
|
20
|
+
* Example use cases:
|
|
21
|
+
* - Investor qualification funnel (firm stage, check size, geography, etc)
|
|
22
|
+
* - Recipe recommendation funnel (dietary restrictions, cuisine, difficulty)
|
|
23
|
+
* - Lead scoring funnel (company size, industry, engagement level)
|
|
24
|
+
* - Task prioritization funnel (urgency, importance, dependencies)
|
|
25
|
+
*
|
|
26
|
+
* @packageDocumentation
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
// Export all types
|
|
30
|
+
export * from './types';
|
|
31
|
+
|
|
32
|
+
// Export core utilities
|
|
33
|
+
export {
|
|
34
|
+
resolveField,
|
|
35
|
+
setField,
|
|
36
|
+
hasField,
|
|
37
|
+
getFields,
|
|
38
|
+
} from './core/field-resolver';
|
|
39
|
+
|
|
40
|
+
// Export rule evaluator
|
|
41
|
+
export {
|
|
42
|
+
evaluateRule,
|
|
43
|
+
evaluateRuleWithResult,
|
|
44
|
+
evaluateRules,
|
|
45
|
+
evaluateRulesAND,
|
|
46
|
+
evaluateRulesOR,
|
|
47
|
+
evaluateRulesWithResults,
|
|
48
|
+
filterEntities,
|
|
49
|
+
} from './core/evaluator';
|
|
50
|
+
|
|
51
|
+
// Export operators
|
|
52
|
+
export { applyOperator } from './core/operators';
|
|
53
|
+
|
|
54
|
+
// Export funnel engine
|
|
55
|
+
export { FunnelEngine } from './core/engine';
|
|
56
|
+
export type { ExecutionResult } from './core/engine';
|
|
57
|
+
|
|
58
|
+
// Export API client
|
|
59
|
+
export * from './api';
|
|
60
|
+
|
|
61
|
+
// Export store
|
|
62
|
+
export * from './store';
|
|
63
|
+
|
|
64
|
+
// Export hooks
|
|
65
|
+
export { useDebouncedValue } from './hooks';
|
|
66
|
+
|
|
67
|
+
// Export components
|
|
68
|
+
export {
|
|
69
|
+
FunnelPreview,
|
|
70
|
+
PreviewStats,
|
|
71
|
+
StageBreakdown,
|
|
72
|
+
EntityCard,
|
|
73
|
+
LoadingPreview,
|
|
74
|
+
} from './components/FunnelPreview';
|
|
75
|
+
export type {
|
|
76
|
+
FunnelPreviewProps,
|
|
77
|
+
PreviewResult,
|
|
78
|
+
StagePreviewStats,
|
|
79
|
+
} from './components/FunnelPreview';
|
|
80
|
+
|
|
81
|
+
export {
|
|
82
|
+
FunnelCard,
|
|
83
|
+
StatusBadge,
|
|
84
|
+
StageIndicator,
|
|
85
|
+
MatchBar,
|
|
86
|
+
FunnelStats,
|
|
87
|
+
} from './components/FunnelCard';
|
|
88
|
+
export type { FunnelCardProps } from './components/FunnelCard';
|
|
89
|
+
|
|
90
|
+
export {
|
|
91
|
+
FunnelVisualFlow,
|
|
92
|
+
StageNode,
|
|
93
|
+
FlowLegend,
|
|
94
|
+
getCircledNumber,
|
|
95
|
+
} from './components/FunnelVisualFlow';
|
|
96
|
+
export type {
|
|
97
|
+
FunnelVisualFlowProps,
|
|
98
|
+
StageNodeData,
|
|
99
|
+
} from './components/FunnelVisualFlow';
|
|
100
|
+
|
|
101
|
+
export {
|
|
102
|
+
FilterRuleEditor,
|
|
103
|
+
LogicToggle,
|
|
104
|
+
FieldSelector,
|
|
105
|
+
OperatorSelector,
|
|
106
|
+
RuleRow,
|
|
107
|
+
TextValueInput,
|
|
108
|
+
NumberValueInput,
|
|
109
|
+
DateValueInput,
|
|
110
|
+
BooleanValueInput,
|
|
111
|
+
ChoiceValueInput,
|
|
112
|
+
MultiChoiceValueInput,
|
|
113
|
+
OPERATOR_LABELS,
|
|
114
|
+
NULL_VALUE_OPERATORS,
|
|
115
|
+
MULTI_VALUE_OPERATORS,
|
|
116
|
+
} from './components/FilterRuleEditor';
|
|
117
|
+
export type { FilterRuleEditorProps } from './components/FilterRuleEditor';
|
|
118
|
+
|
|
119
|
+
export {
|
|
120
|
+
FunnelStageBuilder,
|
|
121
|
+
StageCard,
|
|
122
|
+
StageForm,
|
|
123
|
+
StageActions,
|
|
124
|
+
TagInput,
|
|
125
|
+
AddStageButton,
|
|
126
|
+
} from './components/FunnelStageBuilder';
|
|
127
|
+
export type {
|
|
128
|
+
FunnelStageBuilderProps,
|
|
129
|
+
StageCardProps,
|
|
130
|
+
StageFormProps,
|
|
131
|
+
StageActionsProps,
|
|
132
|
+
TagInputProps,
|
|
133
|
+
AddStageButtonProps,
|
|
134
|
+
} from './components/FunnelStageBuilder';
|
|
135
|
+
|
|
136
|
+
export {
|
|
137
|
+
FunnelRunHistory,
|
|
138
|
+
RunStatusBadge,
|
|
139
|
+
RunFilters,
|
|
140
|
+
RunRow,
|
|
141
|
+
RunActions,
|
|
142
|
+
RunDetailsModal,
|
|
143
|
+
StageBreakdownList,
|
|
144
|
+
formatDuration,
|
|
145
|
+
formatRelativeTime,
|
|
146
|
+
calculateMatchRate,
|
|
147
|
+
formatNumber,
|
|
148
|
+
formatFullTimestamp,
|
|
149
|
+
} from './components/FunnelRunHistory';
|
|
150
|
+
export type {
|
|
151
|
+
RunFiltersType,
|
|
152
|
+
RunSort,
|
|
153
|
+
Pagination,
|
|
154
|
+
RunAction,
|
|
155
|
+
} from './components/FunnelRunHistory';
|