@formality-ui/react 0.0.0 → 0.2.0

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/dist/index.js CHANGED
@@ -23,7 +23,9 @@ function useConfigContext() {
23
23
  var FormContext = createContext(null);
24
24
  FormContext.displayName = "FormalityFormContext";
25
25
  function useFormContext() {
26
- const context = useContext(FormContext);
26
+ const context = useContext(
27
+ FormContext
28
+ );
27
29
  if (!context) {
28
30
  throw new Error(
29
31
  "useFormContext must be used within a Form component. Make sure your component is wrapped in a <Form> component."
@@ -109,7 +111,6 @@ function makeDeepProxyState(source) {
109
111
  const result = {};
110
112
  for (const key in source) {
111
113
  if (Object.prototype.hasOwnProperty.call(source, key)) {
112
- source[key];
113
114
  Object.defineProperty(result, key, {
114
115
  get: () => {
115
116
  const currentValue = source[key];
@@ -191,6 +192,11 @@ function Form({
191
192
  invertedSubscriptions.current.set(target, /* @__PURE__ */ new Set());
192
193
  }
193
194
  invertedSubscriptions.current.get(target).add(subscriber);
195
+ if (process.env.NODE_ENV !== "production") {
196
+ console.warn(
197
+ `[Formality Subscription] "${subscriber}" added to watch "${target}"`
198
+ );
199
+ }
194
200
  const setter = watcherSetters.current.get(target);
195
201
  if (setter) {
196
202
  setter((prev) => ({ ...prev, [subscriber]: true }));
@@ -203,7 +209,20 @@ function Form({
203
209
  }, []);
204
210
  const removeSubscription = useCallback(
205
211
  (target, subscriber) => {
212
+ const subscribers = invertedSubscriptions.current.get(target);
213
+ const subscriptionExists = subscribers?.has(subscriber) ?? false;
206
214
  invertedSubscriptions.current.get(target)?.delete(subscriber);
215
+ if (process.env.NODE_ENV !== "production") {
216
+ if (subscriptionExists) {
217
+ console.warn(
218
+ `[Formality Subscription] "${subscriber}" removed from watching "${target}"`
219
+ );
220
+ } else {
221
+ console.warn(
222
+ `[Formality Subscription] WARNING: Double-cleanup attempt - "${subscriber}" was not watching "${target}"`
223
+ );
224
+ }
225
+ }
207
226
  const setter = watcherSetters.current.get(target);
208
227
  if (setter) {
209
228
  setter((prev) => {
@@ -253,14 +272,18 @@ function Form({
253
272
  return affected;
254
273
  }, []);
255
274
  const changeField = useCallback(
256
- (name, value) => {
275
+ (name, value, inputConfig) => {
257
276
  if (autoSave) {
258
277
  pendingChangedFields.current.add(name);
259
278
  const affected = getAffectedFields(name);
260
279
  for (const field of affected) {
261
280
  pendingAffectedFields.current.add(field);
262
281
  }
263
- debouncedSubmit();
282
+ if (inputConfig?.debounce === false) {
283
+ executeAutoSaveRef.current?.();
284
+ } else {
285
+ debouncedSubmitRef.current?.();
286
+ }
264
287
  }
265
288
  },
266
289
  [autoSave, getAffectedFields]
@@ -303,7 +326,7 @@ function Form({
303
326
  };
304
327
  }, [methods, config, record, defaultValues]);
305
328
  const handleSubmit = useCallback(
306
- async (values) => {
329
+ async (values, overrideOnSubmit) => {
307
330
  for (const [, isValidating] of validatingFields.current) {
308
331
  if (isValidating) return;
309
332
  }
@@ -316,12 +339,26 @@ function Form({
316
339
  return;
317
340
  }
318
341
  }
319
- const submitValues = transformValuesForSubmit(values, config, mergedInputs);
320
- await onSubmit?.(submitValues);
342
+ const submitValues = transformValuesForSubmit(
343
+ values,
344
+ config,
345
+ mergedInputs
346
+ );
347
+ const sink = overrideOnSubmit ?? onSubmit;
348
+ await sink?.(submitValues);
321
349
  },
322
350
  [validate, methods, onSubmit, config, mergedInputs]
323
351
  );
352
+ const handleRenderSubmit = useCallback(
353
+ (userOnSubmit) => {
354
+ return methods.handleSubmit(async (values) => {
355
+ await handleSubmit(values, userOnSubmit);
356
+ });
357
+ },
358
+ [methods, handleSubmit]
359
+ );
324
360
  const debouncedSubmitRef = useRef();
361
+ const executeAutoSaveRef = useRef();
325
362
  const waitForFieldValidation = useCallback(
326
363
  async (fields, version) => {
327
364
  const maxWaitMs = 1e4;
@@ -353,29 +390,36 @@ function Form({
353
390
  if (changedFields.size === 0) {
354
391
  return;
355
392
  }
356
- const fieldsToValidate = [...changedFields, ...affectedFields];
393
+ const fieldsToWaitFor = [...changedFields, ...affectedFields];
394
+ const fieldsToTrigger = [...affectedFields];
357
395
  const validationsComplete = await waitForFieldValidation(
358
- fieldsToValidate,
396
+ fieldsToWaitFor,
359
397
  executionVersion
360
398
  );
361
399
  if (!validationsComplete || executionVersionRef.current !== executionVersion) {
362
400
  return;
363
401
  }
364
- if (fieldsToValidate.length > 0) {
365
- const isValid = await methods.trigger(fieldsToValidate);
402
+ for (const fieldName of changedFields) {
403
+ const fieldState = methods.getFieldState(fieldName);
404
+ if (fieldState.error) {
405
+ return;
406
+ }
407
+ }
408
+ if (fieldsToTrigger.length > 0) {
409
+ const isValid = await methods.trigger(fieldsToTrigger);
366
410
  if (executionVersionRef.current !== executionVersion) {
367
411
  return;
368
412
  }
369
413
  if (!isValid) {
370
414
  return;
371
415
  }
372
- }
373
- const postTriggerComplete = await waitForFieldValidation(
374
- fieldsToValidate,
375
- executionVersion
376
- );
377
- if (!postTriggerComplete || executionVersionRef.current !== executionVersion) {
378
- return;
416
+ const postTriggerComplete = await waitForFieldValidation(
417
+ fieldsToTrigger,
418
+ executionVersion
419
+ );
420
+ if (!postTriggerComplete || executionVersionRef.current !== executionVersion) {
421
+ return;
422
+ }
379
423
  }
380
424
  const formState = methods.formState;
381
425
  if (Object.keys(formState.errors).length > 0) {
@@ -384,7 +428,27 @@ function Form({
384
428
  const values = methods.getValues();
385
429
  await handleSubmit(values);
386
430
  }, [methods, handleSubmit, waitForFieldValidation]);
431
+ executeAutoSaveRef.current = executeAutoSave;
387
432
  useEffect(() => {
433
+ if (debounceMs === false) {
434
+ const immediateFn = Object.assign(
435
+ () => {
436
+ executeAutoSave();
437
+ },
438
+ {
439
+ cancel: () => {
440
+ },
441
+ // No-op for immediate function
442
+ flush: () => executeAutoSave(),
443
+ // Execute immediately on flush
444
+ pending: () => false
445
+ // Never pending when immediate
446
+ }
447
+ );
448
+ debouncedSubmitRef.current = immediateFn;
449
+ return () => {
450
+ };
451
+ }
388
452
  const debouncedFn = debounce(() => {
389
453
  executeAutoSave();
390
454
  }, debounceMs);
@@ -397,12 +461,13 @@ function Form({
397
461
  debouncedFn.cancel();
398
462
  };
399
463
  }, [executeAutoSave, debounceMs]);
400
- const debouncedSubmit = useCallback(() => {
401
- debouncedSubmitRef.current?.();
402
- }, []);
403
464
  const submitImmediate = useCallback(() => {
404
- debouncedSubmitRef.current?.flush();
405
- }, []);
465
+ if (debouncedSubmitRef.current?.flush) {
466
+ debouncedSubmitRef.current.flush();
467
+ } else {
468
+ executeAutoSave();
469
+ }
470
+ }, [executeAutoSave]);
406
471
  const unusedFields = useMemo(() => {
407
472
  const allFields = Object.keys(config);
408
473
  return allFields.filter((name) => !registeredFields.has(name));
@@ -470,6 +535,7 @@ function Form({
470
535
  unusedFields,
471
536
  formState: methods.formState,
472
537
  methods,
538
+ handleSubmit: handleRenderSubmit,
473
539
  resolvedTitle
474
540
  }) : children }) }) });
475
541
  }
@@ -490,9 +556,21 @@ function transformValuesForSubmit(values, config, inputs) {
490
556
  return result;
491
557
  }
492
558
  function useInferredInputs(options) {
493
- const { selectProps, conditions = [], subscribesTo = [] } = options;
559
+ const {
560
+ selectProps,
561
+ formDefaultFieldProps,
562
+ providerDefaultFieldProps,
563
+ conditions = [],
564
+ subscribesTo = []
565
+ } = options;
494
566
  return useMemo(() => {
495
567
  const inferred = [...subscribesTo];
568
+ if (providerDefaultFieldProps) {
569
+ inferred.push(...inferFieldsFromDescriptor(providerDefaultFieldProps));
570
+ }
571
+ if (formDefaultFieldProps) {
572
+ inferred.push(...inferFieldsFromDescriptor(formDefaultFieldProps));
573
+ }
496
574
  if (selectProps) {
497
575
  inferred.push(...inferFieldsFromDescriptor(selectProps));
498
576
  }
@@ -500,12 +578,18 @@ function useInferredInputs(options) {
500
578
  inferred.push(...inferFieldsFromConditions(conditions));
501
579
  }
502
580
  return [...new Set(inferred)];
503
- }, [selectProps, conditions, subscribesTo]);
581
+ }, [
582
+ providerDefaultFieldProps,
583
+ formDefaultFieldProps,
584
+ selectProps,
585
+ conditions,
586
+ subscribesTo
587
+ ]);
504
588
  }
505
589
 
506
590
  // src/hooks/useConditions.ts
507
591
  function useConditions(options) {
508
- const { conditions, subscribesTo, props } = options;
592
+ const { conditions, subscribesTo, props, allFieldsConfig } = options;
509
593
  const { record, methods } = useFormContext();
510
594
  const watchFields = useInferredInputs({
511
595
  conditions,
@@ -529,12 +613,14 @@ function useConditions(options) {
529
613
  }
530
614
  return values;
531
615
  }, [watchFields, watchedValues]);
532
- const fieldStates = useMemo(() => {
616
+ const baseFieldStates = useMemo(() => {
533
617
  const states = {};
534
- if (watchFields.length === 0) {
618
+ const currentFieldName = props?.name;
619
+ const allFieldsForPass1 = currentFieldName ? [.../* @__PURE__ */ new Set([...watchFields, currentFieldName])] : watchFields;
620
+ if (allFieldsForPass1.length === 0) {
535
621
  return states;
536
622
  }
537
- watchFields.forEach((fieldName) => {
623
+ allFieldsForPass1.forEach((fieldName) => {
538
624
  const fieldState = methods.getFieldState(fieldName);
539
625
  states[fieldName] = {
540
626
  value: fieldValues[fieldName],
@@ -544,10 +630,112 @@ function useConditions(options) {
544
630
  invalid: fieldState.invalid,
545
631
  isValidating: false
546
632
  // Not easily available per-field
633
+ // ❌ NO disabled property - this is critical for Pass 1 to prevent circular dependency
547
634
  };
548
635
  });
549
636
  return states;
550
- }, [watchFields, fieldValues, methods]);
637
+ }, [watchFields, fieldValues, methods, props]);
638
+ const disabledStates = useMemo(() => {
639
+ const disabled = {};
640
+ const currentFieldName = props?.name;
641
+ const configFields = allFieldsConfig ? Object.keys(allFieldsConfig) : [];
642
+ const allFieldsForPass2 = [.../* @__PURE__ */ new Set([...watchFields, ...configFields])];
643
+ if (currentFieldName && !allFieldsForPass2.includes(currentFieldName)) {
644
+ allFieldsForPass2.push(currentFieldName);
645
+ }
646
+ if (allFieldsForPass2.length === 0) {
647
+ return disabled;
648
+ }
649
+ const allBaseStates = {};
650
+ for (const fieldName of allFieldsForPass2) {
651
+ if (baseFieldStates[fieldName]) {
652
+ allBaseStates[fieldName] = baseFieldStates[fieldName];
653
+ } else {
654
+ const fieldState = methods.getFieldState(fieldName);
655
+ allBaseStates[fieldName] = {
656
+ value: fieldValues[fieldName],
657
+ isTouched: fieldState.isTouched,
658
+ isDirty: fieldState.isDirty,
659
+ error: fieldState.error,
660
+ invalid: fieldState.invalid,
661
+ isValidating: false
662
+ };
663
+ }
664
+ }
665
+ let currentStates = allBaseStates;
666
+ let hasChanged = true;
667
+ let iteration = 0;
668
+ const maxIterations = 10;
669
+ while (hasChanged && iteration < maxIterations) {
670
+ hasChanged = false;
671
+ iteration++;
672
+ const newDisabled = {};
673
+ for (const fieldName of allFieldsForPass2) {
674
+ const fieldConfig = allFieldsConfig?.[fieldName];
675
+ const fieldConditions = fieldConfig?.conditions ?? [];
676
+ const configDisabled = fieldConfig?.disabled;
677
+ const result = evaluateConditions({
678
+ conditions: fieldConditions,
679
+ fieldValues,
680
+ fieldStates: currentStates,
681
+ record,
682
+ props: { name: fieldName }
683
+ });
684
+ newDisabled[fieldName] = configDisabled ?? result.disabled ?? false;
685
+ }
686
+ const newStates = {};
687
+ for (const fieldName of allFieldsForPass2) {
688
+ const baseState = allBaseStates[fieldName];
689
+ if (baseState) {
690
+ newStates[fieldName] = {
691
+ ...baseState,
692
+ disabled: newDisabled[fieldName]
693
+ };
694
+ }
695
+ }
696
+ for (const fieldName of allFieldsForPass2) {
697
+ const oldDisabled = disabled[fieldName];
698
+ const newDisabledValue = newDisabled[fieldName];
699
+ if (oldDisabled !== newDisabledValue) {
700
+ hasChanged = true;
701
+ disabled[fieldName] = newDisabledValue;
702
+ }
703
+ }
704
+ currentStates = newStates;
705
+ }
706
+ return disabled;
707
+ }, [
708
+ watchFields,
709
+ allFieldsConfig,
710
+ fieldValues,
711
+ baseFieldStates,
712
+ record,
713
+ props,
714
+ methods
715
+ ]);
716
+ const fieldStates = useMemo(() => {
717
+ const states = { ...baseFieldStates };
718
+ Object.entries(disabledStates).forEach(([fieldName, disabled]) => {
719
+ if (states[fieldName]) {
720
+ states[fieldName] = {
721
+ ...states[fieldName],
722
+ disabled
723
+ };
724
+ } else {
725
+ const fieldState = methods.getFieldState(fieldName);
726
+ states[fieldName] = {
727
+ value: fieldValues[fieldName],
728
+ isTouched: fieldState.isTouched,
729
+ isDirty: fieldState.isDirty,
730
+ error: fieldState.error,
731
+ invalid: fieldState.invalid,
732
+ isValidating: false,
733
+ disabled
734
+ };
735
+ }
736
+ });
737
+ return states;
738
+ }, [baseFieldStates, disabledStates, fieldValues, methods]);
551
739
  return useMemo(() => {
552
740
  if (conditions.length === 0) {
553
741
  return {
@@ -569,9 +757,17 @@ function useConditions(options) {
569
757
  }, [conditions, fieldValues, fieldStates, record, props]);
570
758
  }
571
759
  function usePropsEvaluation(options) {
572
- const { selectProps, subscribesTo, fieldName } = options;
760
+ const {
761
+ selectProps,
762
+ formDefaultFieldProps,
763
+ providerDefaultFieldProps,
764
+ subscribesTo,
765
+ fieldName
766
+ } = options;
573
767
  const { record, methods } = useFormContext();
574
768
  const watchFields = useInferredInputs({
769
+ providerDefaultFieldProps,
770
+ formDefaultFieldProps,
575
771
  selectProps,
576
772
  subscribesTo
577
773
  });
@@ -582,10 +778,13 @@ function usePropsEvaluation(options) {
582
778
  const formState = useMemo(() => {
583
779
  const fields = {};
584
780
  if (watchFields.length > 0) {
585
- const values = watchFields.length === 1 ? { [watchFields[0]]: watchedValues } : watchFields.reduce((acc, field, i) => {
586
- acc[field] = watchedValues[i];
587
- return acc;
588
- }, {});
781
+ const values = Array.isArray(watchedValues) ? watchFields.reduce(
782
+ (acc, field, i) => {
783
+ acc[field] = watchedValues[i];
784
+ return acc;
785
+ },
786
+ {}
787
+ ) : watchedValues;
589
788
  watchFields.forEach((name) => {
590
789
  fields[name] = makeProxyState({
591
790
  value: values[name],
@@ -611,40 +810,75 @@ function usePropsEvaluation(options) {
611
810
  };
612
811
  }, [watchFields, watchedValues, record]);
613
812
  return useMemo(() => {
614
- if (!selectProps) {
615
- return {};
813
+ let providerResult = {};
814
+ if (providerDefaultFieldProps) {
815
+ if (typeof providerDefaultFieldProps === "function") {
816
+ providerResult = providerDefaultFieldProps(formState, methods) ?? {};
817
+ } else {
818
+ const context = buildFieldContext(formState, fieldName);
819
+ providerResult = evaluateDescriptor(providerDefaultFieldProps, context) ?? {};
820
+ }
821
+ }
822
+ let formResult = {};
823
+ if (formDefaultFieldProps) {
824
+ if (typeof formDefaultFieldProps === "function") {
825
+ formResult = formDefaultFieldProps(formState, methods) ?? {};
826
+ } else {
827
+ const context = buildFieldContext(formState, fieldName);
828
+ formResult = evaluateDescriptor(formDefaultFieldProps, context) ?? {};
829
+ }
616
830
  }
617
- if (typeof selectProps === "function") {
618
- const result2 = selectProps(formState, methods);
619
- return result2 ?? {};
831
+ let fieldResult = {};
832
+ if (selectProps) {
833
+ if (typeof selectProps === "function") {
834
+ fieldResult = selectProps(formState, methods) ?? {};
835
+ } else {
836
+ const context = buildFieldContext(formState, fieldName);
837
+ fieldResult = evaluateDescriptor(selectProps, context) ?? {};
838
+ }
620
839
  }
621
- const context = buildFieldContext(formState, fieldName);
622
- const result = evaluateDescriptor(selectProps, context);
623
- return result ?? {};
624
- }, [selectProps, formState, methods, fieldName]);
840
+ return {
841
+ providerSelectProps: providerResult,
842
+ formSelectProps: formResult,
843
+ fieldSelectProps: fieldResult
844
+ };
845
+ }, [
846
+ providerDefaultFieldProps,
847
+ formDefaultFieldProps,
848
+ selectProps,
849
+ formState,
850
+ methods,
851
+ fieldName
852
+ ]);
625
853
  }
626
854
  function useSubscriptions(fieldName, subscriptions) {
627
855
  const { addSubscription, removeSubscription } = useFormContext();
628
- const prevSubscriptionsRef = useRef([]);
856
+ const runIdRef = useRef(0);
857
+ const runSubscriptionsRef = useRef(/* @__PURE__ */ new Map());
629
858
  useEffect(() => {
630
- const prevSubscriptions = prevSubscriptionsRef.current;
631
- const toRemove = prevSubscriptions.filter(
632
- (target) => !subscriptions.includes(target)
633
- );
634
- const toAdd = subscriptions.filter(
635
- (target) => !prevSubscriptions.includes(target)
636
- );
637
- toRemove.forEach((target) => {
638
- removeSubscription(target, fieldName);
639
- });
640
- toAdd.forEach((target) => {
859
+ const currentRunId = ++runIdRef.current;
860
+ runSubscriptionsRef.current.set(currentRunId, [...subscriptions]);
861
+ subscriptions.forEach((target) => {
641
862
  addSubscription(target, fieldName);
863
+ if (process.env.NODE_ENV !== "production") {
864
+ console.warn(
865
+ `[Formality Subscription] Run ${currentRunId}: "${fieldName}" subscribing to "${target}"`
866
+ );
867
+ }
642
868
  });
643
- prevSubscriptionsRef.current = subscriptions;
644
869
  return () => {
645
- subscriptions.forEach((target) => {
646
- removeSubscription(target, fieldName);
647
- });
870
+ const thisRunSubscriptions = runSubscriptionsRef.current.get(currentRunId);
871
+ if (thisRunSubscriptions) {
872
+ if (process.env.NODE_ENV !== "production") {
873
+ console.warn(
874
+ `[Formality Subscription] Run ${currentRunId}: "${fieldName}" cleaning up [${thisRunSubscriptions.join(", ")}]`
875
+ );
876
+ }
877
+ [...thisRunSubscriptions].reverse().forEach((target) => {
878
+ removeSubscription(target, fieldName);
879
+ });
880
+ runSubscriptionsRef.current.delete(currentRunId);
881
+ }
648
882
  };
649
883
  }, [fieldName, subscriptions, addSubscription, removeSubscription]);
650
884
  }
@@ -655,6 +889,7 @@ function Field({
655
889
  hidden: hiddenProp,
656
890
  children,
657
891
  shouldRegister = true,
892
+ inputConfig: inputConfigProp,
658
893
  ...restProps
659
894
  }) {
660
895
  const {
@@ -674,14 +909,23 @@ function Field({
674
909
  const type = typeProp ?? fieldConfig.type ?? "textField";
675
910
  const inputConfig = useMemo(() => {
676
911
  const formInputs = typeof formConfig.inputs === "function" ? formConfig.inputs(providerConfig.inputs) : formConfig.inputs ?? {};
677
- const mergedInputs = { ...providerConfig.inputs };
912
+ const mergedInputs = {
913
+ ...providerConfig.inputs
914
+ };
678
915
  for (const [key, override] of Object.entries(formInputs)) {
679
916
  if (mergedInputs[key]) {
680
- mergedInputs[key] = { ...mergedInputs[key], ...override };
917
+ mergedInputs[key] = {
918
+ ...mergedInputs[key],
919
+ ...override
920
+ };
681
921
  }
682
922
  }
683
- return resolveInputConfig(type, mergedInputs) ?? { component: "input", defaultValue: "" };
684
- }, [type, providerConfig.inputs, formConfig.inputs]);
923
+ const baseInputConfig = resolveInputConfig(type, mergedInputs) ?? {
924
+ component: "input",
925
+ defaultValue: ""
926
+ };
927
+ return inputConfigProp ? { ...baseInputConfig, ...inputConfigProp } : baseInputConfig;
928
+ }, [type, providerConfig.inputs, formConfig.inputs, inputConfigProp]);
685
929
  useEffect(() => {
686
930
  if (shouldRegister) {
687
931
  registerField(name);
@@ -699,13 +943,17 @@ function Field({
699
943
  subscribesTo: fieldConfig.subscribesTo
700
944
  });
701
945
  const allSubscriptions = useMemo(() => {
702
- return [.../* @__PURE__ */ new Set([...inferredSubscriptions, ...groupContext.subscriptions])];
946
+ return [
947
+ .../* @__PURE__ */ new Set([...inferredSubscriptions, ...groupContext.subscriptions])
948
+ ];
703
949
  }, [inferredSubscriptions, groupContext.subscriptions]);
704
950
  useSubscriptions(name, allSubscriptions);
705
951
  const conditionResult = useConditions({
706
952
  conditions: fieldConfig.conditions ?? [],
707
953
  subscribesTo: fieldConfig.subscribesTo,
708
- props: { name }
954
+ props: { name },
955
+ allFieldsConfig: config
956
+ // Pass all field configs for two-pass evaluation of disabled states
709
957
  });
710
958
  const setValueRef = useRef(methods.setValue);
711
959
  setValueRef.current = methods.setValue;
@@ -757,15 +1005,22 @@ function Field({
757
1005
  return conditionResult.visible ?? true;
758
1006
  if (!groupContext.state.isVisible) return false;
759
1007
  return true;
760
- }, [hiddenProp, fieldConfig.hidden, conditionResult, groupContext.state.isVisible]);
761
- const evaluatedSelectProps = usePropsEvaluation({
1008
+ }, [
1009
+ hiddenProp,
1010
+ fieldConfig.hidden,
1011
+ conditionResult,
1012
+ groupContext.state.isVisible
1013
+ ]);
1014
+ const { providerSelectProps, formSelectProps, fieldSelectProps } = usePropsEvaluation({
762
1015
  selectProps: fieldConfig.selectProps,
1016
+ formDefaultFieldProps: formConfig.selectDefaultFieldProps,
1017
+ providerDefaultFieldProps: providerConfig.selectDefaultFieldProps,
763
1018
  subscribesTo: fieldConfig.subscribesTo,
764
1019
  fieldName: name
765
1020
  });
766
1021
  const label = useMemo(() => {
767
- return resolveLabel(name, fieldConfig, evaluatedSelectProps, restProps);
768
- }, [name, fieldConfig, evaluatedSelectProps, restProps]);
1022
+ return resolveLabel(name, fieldConfig, fieldSelectProps, restProps);
1023
+ }, [name, fieldConfig, fieldSelectProps, restProps]);
769
1024
  const validationRules = useMemo(() => {
770
1025
  return {
771
1026
  ...fieldConfig.rules,
@@ -818,9 +1073,15 @@ function Field({
818
1073
  providerConfig.parsers
819
1074
  );
820
1075
  onChange(parsedValue);
821
- changeField(name, parsedValue);
1076
+ changeField(name, parsedValue, inputConfig);
822
1077
  },
823
- [inputConfig.parser, providerConfig.parsers, changeField, name]
1078
+ [
1079
+ inputConfig.parser,
1080
+ providerConfig.parsers,
1081
+ changeField,
1082
+ name,
1083
+ inputConfig
1084
+ ]
824
1085
  );
825
1086
  if (!isVisible) {
826
1087
  return null;
@@ -839,14 +1100,12 @@ function Field({
839
1100
  );
840
1101
  const finalProps = mergeFieldProps({
841
1102
  providerDefaultFieldProps: providerConfig.defaultFieldProps,
842
- providerSelectDefaultFieldProps: {},
843
- // Evaluated at provider level if needed
1103
+ providerSelectDefaultFieldProps: providerSelectProps,
844
1104
  formDefaultFieldProps: formConfig.defaultFieldProps,
845
- formSelectDefaultFieldProps: {},
846
- // Evaluated at form level if needed
1105
+ formSelectDefaultFieldProps: formSelectProps,
847
1106
  inputProps: inputConfig.props,
848
1107
  fieldConfigProps: fieldConfig.props,
849
- selectProps: evaluatedSelectProps,
1108
+ selectProps: fieldSelectProps,
850
1109
  componentProps: restProps,
851
1110
  coreProps: {
852
1111
  name,
@@ -856,7 +1115,7 @@ function Field({
856
1115
  [inputConfig.inputFieldProp ?? "value"]: formattedValue,
857
1116
  onChange: handleChange(field.onChange),
858
1117
  onBlur: field.onBlur,
859
- ref: field.ref
1118
+ forwardRef: field.ref
860
1119
  }
861
1120
  });
862
1121
  const Component = inputConfig.component;
@@ -1023,6 +1282,11 @@ function useFormState(options) {
1023
1282
  return result;
1024
1283
  }
1025
1284
 
1026
- export { ConfigContext, Field, FieldGroup, Form, FormContext, FormalityProvider, GroupContext, UnusedFields, makeDeepProxyState, makeProxyState, useConditions, useConfigContext, useFormContext, useFormState, useGroupContext, useInferredInputs, usePropsEvaluation, useSubscriptions };
1285
+ // src/overlays.ts
1286
+ function defineInputs(inputs) {
1287
+ return inputs;
1288
+ }
1289
+
1290
+ export { ConfigContext, Field, FieldGroup, Form, FormContext, FormalityProvider, GroupContext, UnusedFields, defineInputs, makeDeepProxyState, makeProxyState, useConditions, useConfigContext, useFormContext, useFormState, useGroupContext, useInferredInputs, usePropsEvaluation, useSubscriptions };
1027
1291
  //# sourceMappingURL=index.js.map
1028
1292
  //# sourceMappingURL=index.js.map