@k3-universe/react-kit 0.0.4 → 0.0.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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormBuilder.d.ts","sourceRoot":"","sources":["../../../../../src/kit/builder/form/components/FormBuilder.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"FormBuilder.d.ts","sourceRoot":"","sources":["../../../../../src/kit/builder/form/components/FormBuilder.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React, { useCallback, useMemo } from 'react';
|
|
2
|
-
import { useForm, type Control, type FieldValues } from 'react-hook-form';
|
|
1
|
+
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
|
|
2
|
+
import { useForm, useWatch, type Control, type FieldValues } from 'react-hook-form';
|
|
3
3
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import { cn } from '../../../../shadcn/lib/utils';
|
|
@@ -337,21 +337,36 @@ export function FormBuilder({
|
|
|
337
337
|
defaultValues: generatedDefaultValues,
|
|
338
338
|
});
|
|
339
339
|
|
|
340
|
-
const { control, handleSubmit, reset, setValue, getValues
|
|
340
|
+
const { control, handleSubmit, reset, setValue, getValues } = form;
|
|
341
341
|
|
|
342
|
-
// Determine
|
|
343
|
-
const
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
342
|
+
// Determine dependency fields to watch
|
|
343
|
+
const dependencyFields = useMemo(() => {
|
|
344
|
+
const set = new Set<string>();
|
|
345
|
+
sections.forEach((section) => {
|
|
346
|
+
section.fields?.forEach((f) => {
|
|
347
|
+
f.dependencies?.forEach((d) => set.add(d.field));
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
return Array.from(set);
|
|
347
351
|
}, [sections]);
|
|
348
352
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
+
const hasDependencies = dependencyFields.length > 0;
|
|
354
|
+
|
|
355
|
+
// Watch only dependency fields via useWatch; create a stable object map
|
|
356
|
+
// Always call useWatch to satisfy hooks rules. Passing an empty array is safe and returns an empty array.
|
|
357
|
+
const depValuesArr = useWatch({ control, name: dependencyFields });
|
|
358
|
+
const watchedValues = useMemo(() => {
|
|
359
|
+
if (!hasDependencies) return {} as Record<string, any>;
|
|
360
|
+
const obj: Record<string, any> = {};
|
|
361
|
+
dependencyFields.forEach((n, i) => { obj[n] = (depValuesArr as any[])[i]; });
|
|
362
|
+
return obj;
|
|
363
|
+
// dependencyFields is stable from sections; depValuesArr changes only when values change
|
|
364
|
+
}, [hasDependencies, dependencyFields, depValuesArr]);
|
|
353
365
|
|
|
354
366
|
// Handle field dependencies
|
|
367
|
+
// Queue dependency-driven value updates to avoid calling setValue during render
|
|
368
|
+
const pendingValueUpdatesRef = useRef<Array<{ name: string; value: any }>>([]);
|
|
369
|
+
|
|
355
370
|
const handleFieldDependencies = useCallback(
|
|
356
371
|
(field: FormBuilderFieldConfig) => {
|
|
357
372
|
if (!hasDependencies || !field.dependencies) return {};
|
|
@@ -359,7 +374,7 @@ export function FormBuilder({
|
|
|
359
374
|
const result: { disabled?: boolean; hidden?: boolean } = {};
|
|
360
375
|
|
|
361
376
|
field.dependencies.forEach((dep) => {
|
|
362
|
-
const dependentValue =
|
|
377
|
+
const dependentValue = watchedValues[dep.field];
|
|
363
378
|
const conditionMet = dep.condition(dependentValue);
|
|
364
379
|
|
|
365
380
|
switch (dep.action) {
|
|
@@ -378,9 +393,9 @@ export function FormBuilder({
|
|
|
378
393
|
case 'setValue':
|
|
379
394
|
if (conditionMet && dep.value !== undefined) {
|
|
380
395
|
const currentValue = getValues(field.name);
|
|
381
|
-
// Only setValue if the value is actually different to prevent infinite loops
|
|
382
396
|
if (currentValue !== dep.value) {
|
|
383
|
-
|
|
397
|
+
// Defer the update to an effect to prevent state changes during render
|
|
398
|
+
pendingValueUpdatesRef.current.push({ name: field.name, value: dep.value });
|
|
384
399
|
}
|
|
385
400
|
}
|
|
386
401
|
break;
|
|
@@ -389,9 +404,24 @@ export function FormBuilder({
|
|
|
389
404
|
|
|
390
405
|
return result;
|
|
391
406
|
},
|
|
392
|
-
[hasDependencies, watchedValues,
|
|
407
|
+
[hasDependencies, watchedValues, getValues],
|
|
393
408
|
);
|
|
394
409
|
|
|
410
|
+
// Flush any pending setValue updates after watchedValues change
|
|
411
|
+
useEffect(() => {
|
|
412
|
+
if (pendingValueUpdatesRef.current.length === 0) return;
|
|
413
|
+
const updatesMap = new Map<string, any>();
|
|
414
|
+
// last write wins per field
|
|
415
|
+
pendingValueUpdatesRef.current.forEach(({ name, value }) => updatesMap.set(name, value));
|
|
416
|
+
pendingValueUpdatesRef.current = [];
|
|
417
|
+
updatesMap.forEach((value, name) => {
|
|
418
|
+
const current = getValues(name);
|
|
419
|
+
if (current !== value) {
|
|
420
|
+
setValue(name, value, { shouldDirty: false, shouldTouch: false, shouldValidate: false });
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
}, [watchedValues, setValue, getValues]);
|
|
424
|
+
|
|
395
425
|
// Handle field change with custom onChange
|
|
396
426
|
const handleFieldChange = useCallback(
|
|
397
427
|
(field: FormBuilderFieldConfig, value: any) => {
|
|
@@ -228,7 +228,7 @@ export function FormBuilderField({ field, control, onChange, parentPath }: FormB
|
|
|
228
228
|
);
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
if (placement === 'inline'
|
|
231
|
+
if (placement === 'inline') {
|
|
232
232
|
return (
|
|
233
233
|
<div className={cn('space-y-1', field.gridCols && `md:col-span-${field.gridCols}`)}>
|
|
234
234
|
<div className="flex items-center gap-2">
|