@ram_28/kf-ai-sdk 1.0.7 → 1.0.8

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 (35) hide show
  1. package/dist/api/index.d.ts +1 -1
  2. package/dist/api/index.d.ts.map +1 -1
  3. package/dist/components/hooks/useFilter/index.d.ts +3 -3
  4. package/dist/components/hooks/useFilter/index.d.ts.map +1 -1
  5. package/dist/components/hooks/useFilter/types.d.ts +83 -109
  6. package/dist/components/hooks/useFilter/types.d.ts.map +1 -1
  7. package/dist/components/hooks/useFilter/useFilter.d.ts +1 -1
  8. package/dist/components/hooks/useFilter/useFilter.d.ts.map +1 -1
  9. package/dist/components/hooks/useKanban/index.d.ts +1 -1
  10. package/dist/components/hooks/useKanban/index.d.ts.map +1 -1
  11. package/dist/components/hooks/useKanban/types.d.ts +6 -46
  12. package/dist/components/hooks/useKanban/types.d.ts.map +1 -1
  13. package/dist/components/hooks/useKanban/useKanban.d.ts.map +1 -1
  14. package/dist/components/hooks/useTable/types.d.ts +5 -33
  15. package/dist/components/hooks/useTable/types.d.ts.map +1 -1
  16. package/dist/components/hooks/useTable/useTable.d.ts +0 -5
  17. package/dist/components/hooks/useTable/useTable.d.ts.map +1 -1
  18. package/dist/index.cjs +12 -12
  19. package/dist/index.mjs +2130 -2368
  20. package/dist/types/common.d.ts +35 -26
  21. package/dist/types/common.d.ts.map +1 -1
  22. package/package.json +1 -1
  23. package/sdk/api/index.ts +7 -3
  24. package/sdk/components/hooks/useFilter/index.ts +19 -18
  25. package/sdk/components/hooks/useFilter/types.ts +157 -123
  26. package/sdk/components/hooks/useFilter/useFilter.ts +259 -393
  27. package/sdk/components/hooks/useKanban/index.ts +0 -1
  28. package/sdk/components/hooks/useKanban/types.ts +8 -66
  29. package/sdk/components/hooks/useKanban/useKanban.ts +14 -75
  30. package/sdk/components/hooks/useTable/types.ts +7 -60
  31. package/sdk/components/hooks/useTable/useTable.ts +13 -121
  32. package/sdk/types/common.ts +42 -26
  33. package/dist/components/hooks/useFilter/payloadBuilder.utils.d.ts +0 -33
  34. package/dist/components/hooks/useFilter/payloadBuilder.utils.d.ts.map +0 -1
  35. package/sdk/components/hooks/useFilter/payloadBuilder.utils.ts +0 -298
@@ -1,473 +1,339 @@
1
- import { useState, useCallback, useMemo, useEffect } from "react";
2
- import type { Filter, LogicalOperator } from "../../../types/common";
1
+ import { useState, useCallback, useMemo } from "react";
3
2
  import type {
4
- FilterConditionWithId,
5
- TypedFilterConditionInput,
6
- ValidationResult,
7
- ValidationError,
8
- FilterState,
9
- UseFilterOptions,
10
- UseFilterReturn,
11
- } from "./types";
3
+ Condition,
4
+ ConditionGroup,
5
+ ConditionGroupOperator,
6
+ Filter,
7
+ } from "../../../types/common";
8
+ import type { UseFilterOptions, UseFilterReturn } from "./types";
9
+ import { isConditionGroup } from "./types";
12
10
 
13
11
  // ============================================================
14
- // VALIDATION HELPERS
12
+ // HELPER FUNCTIONS
15
13
  // ============================================================
16
14
 
15
+ let idCounter = 0;
16
+
17
17
  /**
18
- * Generate a unique ID for conditions
18
+ * Generate a unique ID for conditions and groups
19
19
  */
20
20
  const generateId = (): string => {
21
- return crypto.randomUUID();
21
+ return `filter_${Date.now()}_${++idCounter}`;
22
22
  };
23
23
 
24
24
  /**
25
- * Helper to check if operator is a logical operator
25
+ * Ensure an item has an id
26
26
  */
27
- const isLogicalOperator = (operator: string): operator is LogicalOperator => {
28
- return operator === 'And' || operator === 'Or' || operator === 'Not';
27
+ const ensureId = <T extends Condition | ConditionGroup>(item: T): T => {
28
+ if (!item.id) {
29
+ return { ...item, id: generateId() };
30
+ }
31
+ return item;
29
32
  };
30
33
 
31
34
  /**
32
- * Validate a filter condition (supports both simple conditions and nested logical groups)
35
+ * Deep clone and ensure all items have ids
33
36
  */
34
- const validateFilterCondition = (
35
- condition: Partial<FilterConditionWithId>
36
- ): ValidationResult => {
37
- const errors: string[] = [];
38
-
39
- // Check required fields
40
- if (!condition.operator) {
41
- errors.push('Operator is required');
42
- }
43
-
44
- // Check if this is a logical operator (nested group)
45
- if (condition.operator && isLogicalOperator(condition.operator)) {
46
- // Validate logical group
47
- if (!condition.children || !Array.isArray(condition.children)) {
48
- errors.push('Logical operators require a children array');
49
- } else if (condition.children.length === 0) {
50
- errors.push('Logical operators require at least one child condition');
51
- } else if (condition.operator === 'Not' && condition.children.length > 1) {
52
- errors.push('Not operator can only have one child condition');
37
+ const cloneWithIds = (
38
+ items: Array<Condition | ConditionGroup>
39
+ ): Array<Condition | ConditionGroup> => {
40
+ return items.map((item) => {
41
+ const withId = ensureId(item);
42
+ if (isConditionGroup(withId)) {
43
+ return {
44
+ ...withId,
45
+ Condition: cloneWithIds(withId.Condition),
46
+ };
53
47
  }
48
+ return withId;
49
+ });
50
+ };
54
51
 
55
- // Recursively validate children
56
- if (condition.children && Array.isArray(condition.children)) {
57
- condition.children.forEach((child, index) => {
58
- const childValidation = validateFilterCondition(child);
59
- if (!childValidation.isValid) {
60
- errors.push(...childValidation.errors.map(err => `Child ${index + 1}: ${err}`));
61
- }
62
- });
52
+ /**
53
+ * Strip id fields from items for API payload
54
+ */
55
+ const stripIds = (
56
+ items: Array<Condition | ConditionGroup>
57
+ ): Array<Condition | ConditionGroup> => {
58
+ return items.map((item) => {
59
+ if (isConditionGroup(item)) {
60
+ const { id, ...rest } = item;
61
+ return {
62
+ ...rest,
63
+ Condition: stripIds(item.Condition),
64
+ } as ConditionGroup;
63
65
  }
66
+ const { id, ...rest } = item;
67
+ return rest as Condition;
68
+ });
69
+ };
64
70
 
65
- // Logical operators should not have lhsField or rhsValue
66
- if (condition.lhsField) {
67
- errors.push('Logical operators should not have lhsField');
68
- }
69
- if (condition.rhsValue !== undefined) {
70
- errors.push('Logical operators should not have rhsValue');
71
+ /**
72
+ * Find an item by id in a tree structure
73
+ */
74
+ const findById = (
75
+ items: Array<Condition | ConditionGroup>,
76
+ id: string
77
+ ): Condition | ConditionGroup | undefined => {
78
+ for (const item of items) {
79
+ if (item.id === id) {
80
+ return item;
71
81
  }
72
- } else {
73
- // Validate simple condition
74
- if (!condition.lhsField) {
75
- errors.push('Field is required for condition operators');
82
+ if (isConditionGroup(item)) {
83
+ const found = findById(item.Condition, id);
84
+ if (found) return found;
76
85
  }
86
+ }
87
+ return undefined;
88
+ };
77
89
 
78
- // Validate operator-specific requirements
79
- if (condition.operator && condition.rhsValue !== undefined) {
80
- switch (condition.operator) {
81
- case 'Between':
82
- case 'NotBetween':
83
- if (!Array.isArray(condition.rhsValue) || condition.rhsValue.length !== 2) {
84
- errors.push('Between operators require an array of two values');
85
- }
86
- break;
87
- case 'IN':
88
- case 'NIN':
89
- if (!Array.isArray(condition.rhsValue) || condition.rhsValue.length === 0) {
90
- errors.push('IN/NIN operators require a non-empty array');
91
- }
92
- break;
93
- case 'Empty':
94
- case 'NotEmpty':
95
- // These operators don't need RHS values
96
- break;
97
- default:
98
- if (condition.rhsValue === null || condition.rhsValue === undefined || condition.rhsValue === '') {
99
- errors.push('Value is required for this operator');
100
- }
101
- break;
102
- }
90
+ /**
91
+ * Find a parent group by child id
92
+ */
93
+ const findParentById = (
94
+ items: Array<Condition | ConditionGroup>,
95
+ childId: string,
96
+ parent: ConditionGroup | null = null
97
+ ): ConditionGroup | null => {
98
+ for (const item of items) {
99
+ if (item.id === childId) {
100
+ return parent;
103
101
  }
104
-
105
- // Simple conditions should not have children
106
- if (condition.children && condition.children.length > 0) {
107
- errors.push('Condition operators should not have children');
102
+ if (isConditionGroup(item)) {
103
+ const found = findParentById(item.Condition, childId, item);
104
+ if (found !== null) return found;
108
105
  }
109
106
  }
110
-
111
- return {
112
- isValid: errors.length === 0,
113
- errors
114
- };
107
+ return null;
115
108
  };
116
109
 
117
110
  /**
118
- * Convert a single FilterConditionWithId to API format (FilterCondition or FilterLogical)
111
+ * Update an item in the tree by id
119
112
  */
120
- const convertConditionToAPI = (condition: FilterConditionWithId): any => {
121
- // Check if this is a logical operator (nested group)
122
- if (isLogicalOperator(condition.operator)) {
123
- // Build nested logical filter
124
- return {
125
- Operator: condition.operator,
126
- Condition: (condition.children || [])
127
- .filter(child => child.isValid)
128
- .map(child => convertConditionToAPI(child))
129
- };
130
- } else {
131
- // Build simple condition
132
- return {
133
- Operator: condition.operator,
134
- LHSField: condition.lhsField,
135
- RHSValue: condition.rhsValue,
136
- RHSType: condition.rhsType || "Constant"
137
- };
138
- }
113
+ const updateInTree = (
114
+ items: Array<Condition | ConditionGroup>,
115
+ id: string,
116
+ updater: (item: Condition | ConditionGroup) => Condition | ConditionGroup
117
+ ): Array<Condition | ConditionGroup> => {
118
+ return items.map((item) => {
119
+ if (item.id === id) {
120
+ return updater(item);
121
+ }
122
+ if (isConditionGroup(item)) {
123
+ return {
124
+ ...item,
125
+ Condition: updateInTree(item.Condition, id, updater),
126
+ };
127
+ }
128
+ return item;
129
+ });
139
130
  };
140
131
 
141
132
  /**
142
- * Convert filter state to SDK Filter format
143
- * Supports both flat and nested filter structures
133
+ * Remove an item from the tree by id
144
134
  */
145
- const buildFilterPayload = (
146
- conditions: FilterConditionWithId[],
147
- logicalOperator: LogicalOperator
148
- ): Filter | undefined => {
149
- if (conditions.length === 0) {
150
- return undefined;
151
- }
152
-
153
- const validConditions = conditions.filter(c => c.isValid);
154
- if (validConditions.length === 0) {
155
- return undefined;
156
- }
135
+ const removeFromTree = (
136
+ items: Array<Condition | ConditionGroup>,
137
+ id: string
138
+ ): Array<Condition | ConditionGroup> => {
139
+ return items
140
+ .filter((item) => item.id !== id)
141
+ .map((item) => {
142
+ if (isConditionGroup(item)) {
143
+ return {
144
+ ...item,
145
+ Condition: removeFromTree(item.Condition, id),
146
+ };
147
+ }
148
+ return item;
149
+ });
150
+ };
157
151
 
158
- return {
159
- Operator: logicalOperator,
160
- Condition: validConditions.map(c => convertConditionToAPI(c))
161
- };
152
+ /**
153
+ * Add an item to a specific parent in the tree
154
+ */
155
+ const addToParent = (
156
+ items: Array<Condition | ConditionGroup>,
157
+ parentId: string,
158
+ newItem: Condition | ConditionGroup
159
+ ): Array<Condition | ConditionGroup> => {
160
+ return items.map((item) => {
161
+ if (item.id === parentId && isConditionGroup(item)) {
162
+ return {
163
+ ...item,
164
+ Condition: [...item.Condition, newItem],
165
+ };
166
+ }
167
+ if (isConditionGroup(item)) {
168
+ return {
169
+ ...item,
170
+ Condition: addToParent(item.Condition, parentId, newItem),
171
+ };
172
+ }
173
+ return item;
174
+ });
162
175
  };
163
176
 
164
177
  // ============================================================
165
- // MAIN HOOK
178
+ // USE FILTER HOOK - Nested Filter Support
166
179
  // ============================================================
167
180
 
168
- export function useFilter<T = any>(
169
- options: UseFilterOptions = {}
170
- ): UseFilterReturn<T> {
171
- // ============================================================
172
- // STATE MANAGEMENT
173
- // ============================================================
174
-
175
- const [filterState, setFilterState] = useState<FilterState>({
176
- logicalOperator: options.initialLogicalOperator || "And",
177
- conditions: options.initialConditions || []
178
- });
179
-
180
- // Store initial state for reset functionality
181
- const [initialState] = useState<FilterState>({
182
- logicalOperator: options.initialLogicalOperator || "And",
183
- conditions: options.initialConditions || []
184
- });
185
-
186
- // ============================================================
187
- // VALIDATION
188
- // ============================================================
189
-
190
- const validateCondition = useCallback((condition: Partial<FilterConditionWithId>): ValidationResult => {
191
- return validateFilterCondition(condition);
192
- }, []);
193
-
194
- const validateAllConditions = useCallback((): ValidationResult => {
195
- const allErrors: string[] = [];
181
+ export function useFilter(options: UseFilterOptions = {}): UseFilterReturn {
182
+ // Initialize items with ids
183
+ const [items, setItems] = useState<Array<Condition | ConditionGroup>>(() =>
184
+ cloneWithIds(options.initialConditions || [])
185
+ );
196
186
 
197
- filterState.conditions.forEach(condition => {
198
- const validation = validateCondition(condition);
199
- if (!validation.isValid) {
200
- allErrors.push(...validation.errors.map(err => `Condition ${condition.id}: ${err}`));
201
- }
202
- });
187
+ const [operator, setOperatorState] = useState<ConditionGroupOperator>(
188
+ options.initialOperator || "And"
189
+ );
203
190
 
191
+ // Build payload for API (strip ids)
192
+ const payload = useMemo((): Filter | undefined => {
193
+ if (items.length === 0) return undefined;
204
194
  return {
205
- isValid: allErrors.length === 0,
206
- errors: allErrors
195
+ Operator: operator,
196
+ Condition: stripIds(items),
207
197
  };
208
- }, [filterState.conditions, validateCondition]);
198
+ }, [items, operator]);
199
+
200
+ const hasConditions = items.length > 0;
209
201
 
210
202
  // ============================================================
211
- // CONDITION MANAGEMENT
203
+ // ADD OPERATIONS
212
204
  // ============================================================
213
205
 
214
- const addCondition = useCallback((condition: TypedFilterConditionInput<T>): string => {
206
+ const add = useCallback((condition: Omit<Condition, "id">): string => {
215
207
  const id = generateId();
216
- // Convert typed input to internal format (using unknown for type narrowing)
217
- const internalCondition = condition as unknown as Omit<FilterConditionWithId, 'id' | 'isValid'>;
218
- const validation = validateCondition(internalCondition);
208
+ const newCondition: Condition = { ...condition, id };
209
+ setItems((prev) => [...prev, newCondition]);
210
+ return id;
211
+ }, []);
219
212
 
220
- const newCondition: FilterConditionWithId = {
221
- ...internalCondition,
213
+ const addGroup = useCallback((groupOperator: ConditionGroupOperator): string => {
214
+ const id = generateId();
215
+ const newGroup: ConditionGroup = {
222
216
  id,
223
- isValid: validation.isValid,
224
- validationErrors: validation.errors
217
+ Operator: groupOperator,
218
+ Condition: [],
225
219
  };
226
-
227
- setFilterState(prev => ({
228
- ...prev,
229
- conditions: [...prev.conditions, newCondition]
230
- }));
231
-
232
- if (options.onConditionAdd) {
233
- options.onConditionAdd(newCondition);
234
- }
235
-
220
+ setItems((prev) => [...prev, newGroup]);
236
221
  return id;
237
- }, [validateCondition, options]);
238
-
239
- const updateCondition = useCallback((id: string, updates: Partial<TypedFilterConditionInput<T>>): boolean => {
240
- let found = false;
241
- // Convert typed input to internal format (using unknown for type narrowing)
242
- const internalUpdates = updates as unknown as Partial<FilterConditionWithId>;
243
-
244
- setFilterState(prev => ({
245
- ...prev,
246
- conditions: prev.conditions.map(condition => {
247
- if (condition.id === id) {
248
- found = true;
249
- const updatedCondition = { ...condition, ...internalUpdates };
250
- const validation = validateCondition(updatedCondition);
251
-
252
- const finalCondition = {
253
- ...updatedCondition,
254
- isValid: validation.isValid,
255
- validationErrors: validation.errors
256
- };
257
-
258
- if (options.onConditionUpdate) {
259
- options.onConditionUpdate(finalCondition);
260
- }
261
-
262
- return finalCondition;
263
- }
264
- return condition;
265
- })
266
- }));
267
-
268
- return found;
269
- }, [validateCondition, options]);
270
-
271
- const removeCondition = useCallback((id: string): boolean => {
272
- let found = false;
273
-
274
- setFilterState(prev => ({
275
- ...prev,
276
- conditions: prev.conditions.filter(condition => {
277
- if (condition.id === id) {
278
- found = true;
279
- if (options.onConditionRemove) {
280
- options.onConditionRemove(id);
281
- }
282
- return false;
283
- }
284
- return true;
285
- })
286
- }));
287
-
288
- return found;
289
- }, [options]);
290
-
291
- const clearConditions = useCallback(() => {
292
- setFilterState(prev => ({
293
- ...prev,
294
- conditions: []
295
- }));
296
222
  }, []);
297
223
 
298
- const getCondition = useCallback((id: string): FilterConditionWithId | undefined => {
299
- return filterState.conditions.find(condition => condition.id === id);
300
- }, [filterState.conditions]);
301
-
302
- // ============================================================
303
- // LOGICAL OPERATOR MANAGEMENT
304
- // ============================================================
305
-
306
- const setLogicalOperator = useCallback((operator: LogicalOperator) => {
307
- setFilterState(prev => ({
308
- ...prev,
309
- logicalOperator: operator
310
- }));
311
- }, []);
312
-
313
- // ============================================================
314
- // BULK OPERATIONS
315
- // ============================================================
224
+ const addTo = useCallback(
225
+ (parentId: string, condition: Omit<Condition, "id">): string => {
226
+ const id = generateId();
227
+ const newCondition: Condition = { ...condition, id };
228
+ setItems((prev) => addToParent(prev, parentId, newCondition));
229
+ return id;
230
+ },
231
+ []
232
+ );
316
233
 
317
- const setConditions = useCallback((conditions: FilterConditionWithId[]) => {
318
- const validatedConditions = conditions.map(condition => {
319
- const validation = validateCondition(condition);
320
- return {
321
- ...condition,
322
- isValid: validation.isValid,
323
- validationErrors: validation.errors
234
+ const addGroupTo = useCallback(
235
+ (parentId: string, groupOperator: ConditionGroupOperator): string => {
236
+ const id = generateId();
237
+ const newGroup: ConditionGroup = {
238
+ id,
239
+ Operator: groupOperator,
240
+ Condition: [],
324
241
  };
325
- });
326
-
327
- setFilterState(prev => ({
328
- ...prev,
329
- conditions: validatedConditions
330
- }));
331
- }, [validateCondition]);
332
-
333
- const replaceCondition = useCallback((id: string, newCondition: TypedFilterConditionInput<T>): boolean => {
334
- let found = false;
335
- // Convert typed input to internal format (using unknown for type narrowing)
336
- const internalCondition = newCondition as unknown as Omit<FilterConditionWithId, 'id' | 'isValid'>;
337
-
338
- setFilterState(prev => ({
339
- ...prev,
340
- conditions: prev.conditions.map(condition => {
341
- if (condition.id === id) {
342
- found = true;
343
- const validation = validateCondition(internalCondition);
344
- return {
345
- ...internalCondition,
346
- id,
347
- isValid: validation.isValid,
348
- validationErrors: validation.errors
349
- };
350
- }
351
- return condition;
352
- })
353
- }));
354
-
355
- return found;
356
- }, [validateCondition]);
242
+ setItems((prev) => addToParent(prev, parentId, newGroup));
243
+ return id;
244
+ },
245
+ []
246
+ );
357
247
 
358
248
  // ============================================================
359
- // STATE MANAGEMENT
249
+ // UPDATE OPERATIONS
360
250
  // ============================================================
361
251
 
362
- const exportState = useCallback((): FilterState => ({
363
- logicalOperator: filterState.logicalOperator,
364
- conditions: filterState.conditions.map(condition => ({ ...condition })) // Deep copy
365
- }), [filterState]);
366
-
367
- const importState = useCallback((state: FilterState) => {
368
- const validatedConditions = state.conditions.map(condition => {
369
- const validation = validateCondition(condition);
370
- return {
371
- ...condition,
372
- isValid: validation.isValid,
373
- validationErrors: validation.errors
374
- };
375
- });
376
-
377
- setFilterState({
378
- logicalOperator: state.logicalOperator,
379
- conditions: validatedConditions
380
- });
381
- }, [validateCondition]);
252
+ const update = useCallback(
253
+ (id: string, updates: Partial<Omit<Condition, "id">>): void => {
254
+ setItems((prev) =>
255
+ updateInTree(prev, id, (item) => {
256
+ if (!isConditionGroup(item)) {
257
+ return { ...item, ...updates };
258
+ }
259
+ return item;
260
+ })
261
+ );
262
+ },
263
+ []
264
+ );
382
265
 
383
- const resetToInitial = useCallback(() => {
384
- setFilterState({ ...initialState });
385
- }, [initialState]);
266
+ const updateOperator = useCallback(
267
+ (id: string, newOperator: ConditionGroupOperator): void => {
268
+ setItems((prev) =>
269
+ updateInTree(prev, id, (item) => {
270
+ if (isConditionGroup(item)) {
271
+ return { ...item, Operator: newOperator };
272
+ }
273
+ return item;
274
+ })
275
+ );
276
+ },
277
+ []
278
+ );
386
279
 
387
280
  // ============================================================
388
- // COMPUTED VALUES
281
+ // REMOVE & ACCESS
389
282
  // ============================================================
390
283
 
391
- const filterPayload = useMemo(() =>
392
- buildFilterPayload(filterState.conditions, filterState.logicalOperator),
393
- [filterState.conditions, filterState.logicalOperator]
394
- );
395
-
396
- const validationErrors = useMemo((): ValidationError[] => {
397
- const errors: ValidationError[] = [];
398
-
399
- filterState.conditions.forEach(condition => {
400
- if (!condition.isValid && condition.validationErrors) {
401
- condition.validationErrors.forEach(error => {
402
- errors.push({
403
- conditionId: condition.id,
404
- field: condition.lhsField || '', // Empty string for logical operators
405
- message: error
406
- });
407
- });
408
- }
409
- });
410
-
411
- return errors;
412
- }, [filterState.conditions]);
284
+ const remove = useCallback((id: string): void => {
285
+ setItems((prev) => removeFromTree(prev, id));
286
+ }, []);
413
287
 
414
- const isValid = useMemo(() =>
415
- filterState.conditions.every(condition => condition.isValid),
416
- [filterState.conditions]
288
+ const get = useCallback(
289
+ (id: string): Condition | ConditionGroup | undefined => {
290
+ return findById(items, id);
291
+ },
292
+ [items]
417
293
  );
418
294
 
419
- const getConditionCount = useCallback(() => filterState.conditions.length, [filterState.conditions]);
420
- const hasConditions = useMemo(() => filterState.conditions.length > 0, [filterState.conditions]);
421
- const canAddCondition = useMemo(() => true, []); // Can always add more conditions
422
-
423
295
  // ============================================================
424
- // VALIDATION ERROR CALLBACK
296
+ // UTILITY
425
297
  // ============================================================
426
298
 
427
- useEffect(() => {
428
- if (options.onValidationError && validationErrors.length > 0) {
429
- options.onValidationError(validationErrors);
430
- }
431
- }, [validationErrors, options]);
299
+ const clear = useCallback((): void => {
300
+ setItems([]);
301
+ }, []);
302
+
303
+ const setOperator = useCallback((op: ConditionGroupOperator): void => {
304
+ setOperatorState(op);
305
+ }, []);
432
306
 
433
307
  // ============================================================
434
- // RETURN OBJECT
308
+ // RETURN
435
309
  // ============================================================
436
310
 
437
311
  return {
438
- // Current state
439
- conditions: filterState.conditions,
440
- logicalOperator: filterState.logicalOperator,
441
- filterPayload,
442
- isValid,
443
- validationErrors,
444
-
445
- // Condition management
446
- addCondition,
447
- updateCondition,
448
- removeCondition,
449
- clearConditions,
450
- getCondition,
451
-
452
- // Logical operator management
453
- setLogicalOperator,
454
-
455
- // Bulk operations
456
- setConditions,
457
- replaceCondition,
458
-
459
- // Validation
460
- validateCondition,
461
- validateAllConditions,
462
-
463
- // State management
464
- exportState,
465
- importState,
466
- resetToInitial,
467
-
468
- // Utilities
469
- getConditionCount,
312
+ // State
313
+ operator,
314
+ items,
315
+ payload,
470
316
  hasConditions,
471
- canAddCondition
317
+
318
+ // Add operations
319
+ add,
320
+ addGroup,
321
+ addTo,
322
+ addGroupTo,
323
+
324
+ // Update operations
325
+ update,
326
+ updateOperator,
327
+
328
+ // Remove & access
329
+ remove,
330
+ get,
331
+
332
+ // Utility
333
+ clear,
334
+ setOperator,
335
+
336
+ // Legacy API
337
+ conditions: items,
472
338
  };
473
339
  }