@juantroconisf/lib 11.0.1 → 11.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/README.md CHANGED
@@ -343,24 +343,25 @@ return (
343
343
  );
344
344
  ```
345
345
 
346
- ### Option 3: Inline handler with full type inference
346
+ ### Option 3: External handler with `FormSubmit`
347
347
 
348
- When the schema is defined inline inside `useForm`, extract the handler type from `ControlledForm`:
348
+ When you need to define the submit handler outside the JSX, use the `FormSubmit` utility type:
349
349
 
350
350
  ```tsx
351
+ import { useForm, FormSubmit } from "@juantroconisf/lib";
352
+
351
353
  const { ControlledForm } = useForm({
352
354
  email: string().required().default(""),
353
355
  });
354
356
 
355
- const handleSubmit: React.ComponentProps<typeof ControlledForm>["onSubmit"] = (
356
- data,
357
- event,
358
- ) => {
357
+ const handleSubmit: FormSubmit<typeof ControlledForm> = (data, event) => {
359
358
  // data.email is correctly typed as string — no schema re-declaration needed
360
359
  console.log(data.email);
361
360
  };
362
361
  ```
363
362
 
363
+ `FormSubmit<typeof ControlledForm>` is a shorthand for `React.ComponentProps<typeof ControlledForm>["onSubmit"]`.
364
+
364
365
  ---
365
366
 
366
367
  ## API Reference
package/dist/index.d.mts CHANGED
@@ -66,6 +66,19 @@ type FormSubmitHandler<O extends StateType> = (data: O, e: React.FormEvent) => v
66
66
  * This saves developers from manually mapping `InferType` back to `FormSubmitHandler` when extracting sumbits.
67
67
  */
68
68
  type InferSubmitHandler<S extends Record<string, ConfigType>> = (data: InferState<S>, e: React.FormEvent) => void;
69
+ /**
70
+ * Shorthand to extract the `onSubmit` handler type from a `ControlledForm` component.
71
+ *
72
+ * @example
73
+ * ```tsx
74
+ * const { ControlledForm } = useForm({ email: string().required().default("") });
75
+ *
76
+ * const handleSubmit: FormSubmit<typeof ControlledForm> = (data, event) => {
77
+ * console.log(data.email); // fully typed
78
+ * };
79
+ * ```
80
+ */
81
+ type FormSubmit<C extends React.ComponentType<any>> = NonNullable<React.ComponentProps<C>["onSubmit"]>;
69
82
  interface FormResetOptions<O> {
70
83
  keepValues?: (keyof O)[];
71
84
  }
@@ -268,4 +281,4 @@ interface UseFormResponse<O extends StateType> {
268
281
 
269
282
  declare function useForm<S extends Record<string, ConfigType>>(schema: S, { arrayIdentifiers, onFormSubmit: onFormSubmitProp, resetOnSubmit, keepValues: keepValuesProp, }?: FormOptions<InferState<S>>): UseFormResponse<InferState<S>>;
270
283
 
271
- export { type BlurFunc, type ComponentInputProps, type ConfigType, type FieldMetadata, type FormOptions, type FormResetOptions, type FormSubmitHandler, type HelpersFunc, type InferState, type InferSubmitHandler, type ItemAutocompleteProps, type ItemInputProps, type ItemNumberInputProps, type ItemRadioGroupProps, type ItemSelectProps, type ItemToggleProps, type MetadataType, type NestedChangeProps, NextUIError, type OnMethods, type StateType, type UseFormResponse, type ValueChangeFunc, useForm };
284
+ export { type BlurFunc, type ComponentInputProps, type ConfigType, type FieldMetadata, type FormOptions, type FormResetOptions, type FormSubmit, type FormSubmitHandler, type HelpersFunc, type InferState, type InferSubmitHandler, type ItemAutocompleteProps, type ItemInputProps, type ItemNumberInputProps, type ItemRadioGroupProps, type ItemSelectProps, type ItemToggleProps, type MetadataType, type NestedChangeProps, NextUIError, type OnMethods, type StateType, type UseFormResponse, type ValueChangeFunc, useForm };
package/dist/index.d.ts CHANGED
@@ -66,6 +66,19 @@ type FormSubmitHandler<O extends StateType> = (data: O, e: React.FormEvent) => v
66
66
  * This saves developers from manually mapping `InferType` back to `FormSubmitHandler` when extracting sumbits.
67
67
  */
68
68
  type InferSubmitHandler<S extends Record<string, ConfigType>> = (data: InferState<S>, e: React.FormEvent) => void;
69
+ /**
70
+ * Shorthand to extract the `onSubmit` handler type from a `ControlledForm` component.
71
+ *
72
+ * @example
73
+ * ```tsx
74
+ * const { ControlledForm } = useForm({ email: string().required().default("") });
75
+ *
76
+ * const handleSubmit: FormSubmit<typeof ControlledForm> = (data, event) => {
77
+ * console.log(data.email); // fully typed
78
+ * };
79
+ * ```
80
+ */
81
+ type FormSubmit<C extends React.ComponentType<any>> = NonNullable<React.ComponentProps<C>["onSubmit"]>;
69
82
  interface FormResetOptions<O> {
70
83
  keepValues?: (keyof O)[];
71
84
  }
@@ -268,4 +281,4 @@ interface UseFormResponse<O extends StateType> {
268
281
 
269
282
  declare function useForm<S extends Record<string, ConfigType>>(schema: S, { arrayIdentifiers, onFormSubmit: onFormSubmitProp, resetOnSubmit, keepValues: keepValuesProp, }?: FormOptions<InferState<S>>): UseFormResponse<InferState<S>>;
270
283
 
271
- export { type BlurFunc, type ComponentInputProps, type ConfigType, type FieldMetadata, type FormOptions, type FormResetOptions, type FormSubmitHandler, type HelpersFunc, type InferState, type InferSubmitHandler, type ItemAutocompleteProps, type ItemInputProps, type ItemNumberInputProps, type ItemRadioGroupProps, type ItemSelectProps, type ItemToggleProps, type MetadataType, type NestedChangeProps, NextUIError, type OnMethods, type StateType, type UseFormResponse, type ValueChangeFunc, useForm };
284
+ export { type BlurFunc, type ComponentInputProps, type ConfigType, type FieldMetadata, type FormOptions, type FormResetOptions, type FormSubmit, type FormSubmitHandler, type HelpersFunc, type InferState, type InferSubmitHandler, type ItemAutocompleteProps, type ItemInputProps, type ItemNumberInputProps, type ItemRadioGroupProps, type ItemSelectProps, type ItemToggleProps, type MetadataType, type NestedChangeProps, NextUIError, type OnMethods, type StateType, type UseFormResponse, type ValueChangeFunc, useForm };
package/dist/index.js CHANGED
@@ -539,6 +539,30 @@ function useForm(schema, {
539
539
  finalValue = rule.cast(newValue);
540
540
  } catch {
541
541
  }
542
+ } else if (rule && rule.type === "number") {
543
+ try {
544
+ if (newValue === "") {
545
+ finalValue = null;
546
+ } else if (newValue === null || newValue === void 0) {
547
+ finalValue = newValue;
548
+ } else if (Array.isArray(newValue)) {
549
+ finalValue = newValue.map(
550
+ (v) => v === "" ? null : v === null || v === void 0 ? v : Number(v)
551
+ );
552
+ } else {
553
+ finalValue = Number(newValue);
554
+ if (isNaN(finalValue)) finalValue = newValue;
555
+ }
556
+ } catch {
557
+ }
558
+ } else if (rule && rule.type === "array" && rule.innerType && rule.innerType.type === "number") {
559
+ if (Array.isArray(newValue)) {
560
+ finalValue = newValue.map((v) => {
561
+ if (v === "" || v === null || v === void 0) return v;
562
+ const num = Number(v);
563
+ return isNaN(num) ? v : num;
564
+ });
565
+ }
542
566
  }
543
567
  let nextState = stateRef.current;
544
568
  if (type === "scalar" /* Scalar */) {
@@ -639,7 +663,7 @@ function useForm(schema, {
639
663
  if (!data) return {};
640
664
  return {
641
665
  ...createHandlers(data),
642
- value: data.value,
666
+ value: data.value === null || data.value === void 0 ? "" : typeof data.value === "boolean" ? data.value : String(data.value),
643
667
  onValueChange: (v) => handleFieldChange(data, v)
644
668
  };
645
669
  },
@@ -651,12 +675,12 @@ function useForm(schema, {
651
675
  getNestedValue
652
676
  );
653
677
  if (!data) return {};
654
- const isString = typeof data.value === "string" || data.value === null;
678
+ const isArray = Array.isArray(data.value);
655
679
  return {
656
680
  ...createHandlers(data),
657
- selectedKeys: data.value === null ? [] : isString ? [data.value] : data.value,
681
+ selectedKeys: data.value === null || data.value === void 0 ? [] : isArray ? data.value.map(String) : [String(data.value)],
658
682
  onSelectionChange: (v) => {
659
- const fixed = typeof v === "string" || v === null ? v : isString ? Array.from(v)[0] || null : Array.from(v);
683
+ const fixed = typeof v === "string" || v === null ? v : isArray ? Array.from(v) : Array.from(v)[0] ?? null;
660
684
  handleFieldChange(data, fixed);
661
685
  }
662
686
  };
@@ -671,9 +695,9 @@ function useForm(schema, {
671
695
  if (!data) return {};
672
696
  return {
673
697
  ...createHandlers(data),
674
- selectedKey: data.value,
698
+ selectedKey: data.value === null || data.value === void 0 ? null : String(data.value),
675
699
  onSelectionChange: (v) => {
676
- const fixed = typeof v === "string" || v === null ? v : String(v);
700
+ const fixed = typeof v === "string" || v === null || v === void 0 ? v : String(v);
677
701
  handleFieldChange(data, fixed);
678
702
  }
679
703
  };
@@ -688,7 +712,7 @@ function useForm(schema, {
688
712
  if (!data) return {};
689
713
  return {
690
714
  ...createHandlers(data),
691
- value: data.value ?? 0,
715
+ value: data.value === null || data.value === void 0 ? "" : String(data.value),
692
716
  onValueChange: (v) => handleFieldChange(data, v)
693
717
  };
694
718
  },
@@ -730,7 +754,7 @@ function useForm(schema, {
730
754
  if (!data) return {};
731
755
  return {
732
756
  ...createHandlers(data),
733
- value: data.value ?? "",
757
+ value: data.value === null || data.value === void 0 ? "" : String(data.value),
734
758
  onValueChange: (v) => handleFieldChange(data, v)
735
759
  };
736
760
  }
package/dist/index.mjs CHANGED
@@ -513,6 +513,30 @@ function useForm(schema, {
513
513
  finalValue = rule.cast(newValue);
514
514
  } catch {
515
515
  }
516
+ } else if (rule && rule.type === "number") {
517
+ try {
518
+ if (newValue === "") {
519
+ finalValue = null;
520
+ } else if (newValue === null || newValue === void 0) {
521
+ finalValue = newValue;
522
+ } else if (Array.isArray(newValue)) {
523
+ finalValue = newValue.map(
524
+ (v) => v === "" ? null : v === null || v === void 0 ? v : Number(v)
525
+ );
526
+ } else {
527
+ finalValue = Number(newValue);
528
+ if (isNaN(finalValue)) finalValue = newValue;
529
+ }
530
+ } catch {
531
+ }
532
+ } else if (rule && rule.type === "array" && rule.innerType && rule.innerType.type === "number") {
533
+ if (Array.isArray(newValue)) {
534
+ finalValue = newValue.map((v) => {
535
+ if (v === "" || v === null || v === void 0) return v;
536
+ const num = Number(v);
537
+ return isNaN(num) ? v : num;
538
+ });
539
+ }
516
540
  }
517
541
  let nextState = stateRef.current;
518
542
  if (type === "scalar" /* Scalar */) {
@@ -613,7 +637,7 @@ function useForm(schema, {
613
637
  if (!data) return {};
614
638
  return {
615
639
  ...createHandlers(data),
616
- value: data.value,
640
+ value: data.value === null || data.value === void 0 ? "" : typeof data.value === "boolean" ? data.value : String(data.value),
617
641
  onValueChange: (v) => handleFieldChange(data, v)
618
642
  };
619
643
  },
@@ -625,12 +649,12 @@ function useForm(schema, {
625
649
  getNestedValue
626
650
  );
627
651
  if (!data) return {};
628
- const isString = typeof data.value === "string" || data.value === null;
652
+ const isArray = Array.isArray(data.value);
629
653
  return {
630
654
  ...createHandlers(data),
631
- selectedKeys: data.value === null ? [] : isString ? [data.value] : data.value,
655
+ selectedKeys: data.value === null || data.value === void 0 ? [] : isArray ? data.value.map(String) : [String(data.value)],
632
656
  onSelectionChange: (v) => {
633
- const fixed = typeof v === "string" || v === null ? v : isString ? Array.from(v)[0] || null : Array.from(v);
657
+ const fixed = typeof v === "string" || v === null ? v : isArray ? Array.from(v) : Array.from(v)[0] ?? null;
634
658
  handleFieldChange(data, fixed);
635
659
  }
636
660
  };
@@ -645,9 +669,9 @@ function useForm(schema, {
645
669
  if (!data) return {};
646
670
  return {
647
671
  ...createHandlers(data),
648
- selectedKey: data.value,
672
+ selectedKey: data.value === null || data.value === void 0 ? null : String(data.value),
649
673
  onSelectionChange: (v) => {
650
- const fixed = typeof v === "string" || v === null ? v : String(v);
674
+ const fixed = typeof v === "string" || v === null || v === void 0 ? v : String(v);
651
675
  handleFieldChange(data, fixed);
652
676
  }
653
677
  };
@@ -662,7 +686,7 @@ function useForm(schema, {
662
686
  if (!data) return {};
663
687
  return {
664
688
  ...createHandlers(data),
665
- value: data.value ?? 0,
689
+ value: data.value === null || data.value === void 0 ? "" : String(data.value),
666
690
  onValueChange: (v) => handleFieldChange(data, v)
667
691
  };
668
692
  },
@@ -704,7 +728,7 @@ function useForm(schema, {
704
728
  if (!data) return {};
705
729
  return {
706
730
  ...createHandlers(data),
707
- value: data.value ?? "",
731
+ value: data.value === null || data.value === void 0 ? "" : String(data.value),
708
732
  onValueChange: (v) => handleFieldChange(data, v)
709
733
  };
710
734
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juantroconisf/lib",
3
- "version": "11.0.1",
3
+ "version": "11.2.0",
4
4
  "description": "A form validation library for HeroUI.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",