@inertiajs/react 2.2.21 → 2.3.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
@@ -286,6 +286,7 @@ var import_react11 = __toESM(require("react"), 1);
286
286
 
287
287
  // src/useForm.ts
288
288
  var import_core4 = require("@inertiajs/core");
289
+ var import_laravel_precognition = require("laravel-precognition");
289
290
  var import_lodash_es = require("lodash-es");
290
291
  var import_react9 = require("react");
291
292
 
@@ -310,11 +311,13 @@ function useRemember(initialState, key) {
310
311
  }
311
312
 
312
313
  // src/useForm.ts
313
- function useForm(rememberKeyOrInitialValues, maybeInitialValues) {
314
+ function useForm(...args) {
314
315
  const isMounted = (0, import_react9.useRef)(false);
315
- const rememberKey = typeof rememberKeyOrInitialValues === "string" ? rememberKeyOrInitialValues : null;
316
+ const parsedArgs = import_core4.UseFormUtils.parseUseFormArguments(...args);
317
+ const { rememberKey, data: initialData } = parsedArgs;
318
+ const precognitionEndpoint = (0, import_react9.useRef)(parsedArgs.precognitionEndpoint);
316
319
  const [defaults, setDefaults] = (0, import_react9.useState)(
317
- (typeof rememberKeyOrInitialValues === "string" ? maybeInitialValues : rememberKeyOrInitialValues) || {}
320
+ typeof initialData === "function" ? (0, import_lodash_es.cloneDeep)(initialData()) : (0, import_lodash_es.cloneDeep)(initialData)
318
321
  );
319
322
  const cancelToken = (0, import_react9.useRef)(null);
320
323
  const recentlySuccessfulTimeoutId = (0, import_react9.useRef)(void 0);
@@ -327,6 +330,11 @@ function useForm(rememberKeyOrInitialValues, maybeInitialValues) {
327
330
  const [recentlySuccessful, setRecentlySuccessful] = (0, import_react9.useState)(false);
328
331
  const transform = (0, import_react9.useRef)((data2) => data2);
329
332
  const isDirty = (0, import_react9.useMemo)(() => !(0, import_lodash_es.isEqual)(data, defaults), [data, defaults]);
333
+ const validatorRef = (0, import_react9.useRef)(null);
334
+ const [validating, setValidating] = (0, import_react9.useState)(false);
335
+ const [touchedFields, setTouchedFields] = (0, import_react9.useState)([]);
336
+ const [validFields, setValidFields] = (0, import_react9.useState)([]);
337
+ const withAllErrors = (0, import_react9.useRef)(false);
330
338
  (0, import_react9.useEffect)(() => {
331
339
  isMounted.current = true;
332
340
  return () => {
@@ -335,11 +343,8 @@ function useForm(rememberKeyOrInitialValues, maybeInitialValues) {
335
343
  }, []);
336
344
  const setDefaultsCalledInOnSuccess = (0, import_react9.useRef)(false);
337
345
  const submit = (0, import_react9.useCallback)(
338
- (...args) => {
339
- const objectPassed = args[0] !== null && typeof args[0] === "object";
340
- const method = objectPassed ? args[0].method : args[0];
341
- const url = objectPassed ? args[0].url : args[1];
342
- const options = (objectPassed ? args[1] : args[2]) ?? {};
346
+ (...args2) => {
347
+ const { method, url, options } = import_core4.UseFormUtils.parseSubmitArguments(args2, precognitionEndpoint.current);
343
348
  setDefaultsCalledInOnSuccess.current = false;
344
349
  const _options = {
345
350
  ...options,
@@ -452,14 +457,18 @@ function useForm(rememberKeyOrInitialValues, maybeInitialValues) {
452
457
  const setDefaultsFunction = (0, import_react9.useCallback)(
453
458
  (fieldOrFields, maybeValue) => {
454
459
  setDefaultsCalledInOnSuccess.current = true;
460
+ let newDefaults = {};
455
461
  if (typeof fieldOrFields === "undefined") {
462
+ newDefaults = { ...dataRef.current };
456
463
  setDefaults(dataRef.current);
457
464
  setDataAsDefaults(true);
458
465
  } else {
459
466
  setDefaults((defaults2) => {
460
- return typeof fieldOrFields === "string" ? (0, import_lodash_es.set)((0, import_lodash_es.cloneDeep)(defaults2), fieldOrFields, maybeValue) : Object.assign((0, import_lodash_es.cloneDeep)(defaults2), fieldOrFields);
467
+ newDefaults = typeof fieldOrFields === "string" ? (0, import_lodash_es.set)((0, import_lodash_es.cloneDeep)(defaults2), fieldOrFields, maybeValue) : Object.assign((0, import_lodash_es.cloneDeep)(defaults2), fieldOrFields);
468
+ return newDefaults;
461
469
  });
462
470
  }
471
+ validatorRef.current?.defaults(newDefaults);
463
472
  },
464
473
  [setDefaults]
465
474
  );
@@ -486,6 +495,7 @@ function useForm(rememberKeyOrInitialValues, maybeInitialValues) {
486
495
  )
487
496
  );
488
497
  }
498
+ validatorRef.current?.reset(...fields);
489
499
  },
490
500
  [setData, defaults]
491
501
  );
@@ -497,6 +507,7 @@ function useForm(rememberKeyOrInitialValues, maybeInitialValues) {
497
507
  ...typeof fieldOrFields === "string" ? { [fieldOrFields]: maybeValue } : fieldOrFields
498
508
  };
499
509
  setHasErrors(Object.keys(newErrors).length > 0);
510
+ validatorRef.current?.setErrors(newErrors);
500
511
  return newErrors;
501
512
  });
502
513
  },
@@ -513,6 +524,13 @@ function useForm(rememberKeyOrInitialValues, maybeInitialValues) {
513
524
  {}
514
525
  );
515
526
  setHasErrors(Object.keys(newErrors).length > 0);
527
+ if (validatorRef.current) {
528
+ if (fields.length === 0) {
529
+ validatorRef.current.setErrors({});
530
+ } else {
531
+ fields.forEach(validatorRef.current.forgetError);
532
+ }
533
+ }
516
534
  return newErrors;
517
535
  });
518
536
  },
@@ -541,7 +559,7 @@ function useForm(rememberKeyOrInitialValues, maybeInitialValues) {
541
559
  const transformFunction = (0, import_react9.useCallback)((callback) => {
542
560
  transform.current = callback;
543
561
  }, []);
544
- return {
562
+ const form = {
545
563
  data,
546
564
  setData: setDataFunction,
547
565
  isDirty,
@@ -565,6 +583,88 @@ function useForm(rememberKeyOrInitialValues, maybeInitialValues) {
565
583
  delete: deleteMethod,
566
584
  cancel
567
585
  };
586
+ const tap = (value, callback) => {
587
+ callback(value);
588
+ return value;
589
+ };
590
+ const valid = (0, import_react9.useCallback)(
591
+ (field) => validFields.includes(field),
592
+ [validFields]
593
+ );
594
+ const invalid = (0, import_react9.useCallback)((field) => field in errors, [errors]);
595
+ const touched = (0, import_react9.useCallback)(
596
+ (field) => typeof field === "string" ? touchedFields.includes(field) : touchedFields.length > 0,
597
+ [touchedFields]
598
+ );
599
+ const validate = (field, config2) => {
600
+ if (typeof field === "object" && !("target" in field)) {
601
+ config2 = field;
602
+ field = void 0;
603
+ }
604
+ if (field === void 0) {
605
+ validatorRef.current.validate(config2);
606
+ } else {
607
+ const fieldName = (0, import_laravel_precognition.resolveName)(field);
608
+ const currentData = dataRef.current;
609
+ const transformedData = transform.current(currentData);
610
+ validatorRef.current.validate(fieldName, (0, import_lodash_es.get)(transformedData, fieldName), config2);
611
+ }
612
+ return form;
613
+ };
614
+ const withPrecognition = (...args2) => {
615
+ precognitionEndpoint.current = import_core4.UseFormUtils.createWayfinderCallback(...args2);
616
+ if (!validatorRef.current) {
617
+ const validator = (0, import_laravel_precognition.createValidator)((client) => {
618
+ const { method, url } = precognitionEndpoint.current();
619
+ const currentData = dataRef.current;
620
+ const transformedData = transform.current(currentData);
621
+ return client[method](url, transformedData);
622
+ }, (0, import_lodash_es.cloneDeep)(defaults));
623
+ validatorRef.current = validator;
624
+ validator.on("validatingChanged", () => {
625
+ setValidating(validator.validating());
626
+ }).on("validatedChanged", () => {
627
+ setValidFields(validator.valid());
628
+ }).on("touchedChanged", () => {
629
+ setTouchedFields(validator.touched());
630
+ }).on("errorsChanged", () => {
631
+ const validationErrors = withAllErrors.current ? validator.errors() : (0, import_laravel_precognition.toSimpleValidationErrors)(validator.errors());
632
+ setErrors(validationErrors);
633
+ setHasErrors(Object.keys(validationErrors).length > 0);
634
+ setValidFields(validator.valid());
635
+ });
636
+ }
637
+ const precognitiveForm = Object.assign(form, {
638
+ validating,
639
+ validator: () => validatorRef.current,
640
+ valid,
641
+ invalid,
642
+ touched,
643
+ withoutFileValidation: () => tap(precognitiveForm, () => validatorRef.current?.withoutFileValidation()),
644
+ touch: (field, ...fields) => {
645
+ if (Array.isArray(field)) {
646
+ validatorRef.current?.touch(field);
647
+ } else if (typeof field === "string") {
648
+ validatorRef.current?.touch([field, ...fields]);
649
+ } else {
650
+ validatorRef.current?.touch(field);
651
+ }
652
+ return precognitiveForm;
653
+ },
654
+ withAllErrors: () => tap(precognitiveForm, () => withAllErrors.current = true),
655
+ setValidationTimeout: (duration) => tap(precognitiveForm, () => validatorRef.current?.setTimeout(duration)),
656
+ validateFiles: () => tap(precognitiveForm, () => validatorRef.current?.validateFiles()),
657
+ validate,
658
+ setErrors: (errors2) => tap(precognitiveForm, () => form.setError(errors2)),
659
+ forgetError: (field) => tap(
660
+ precognitiveForm,
661
+ () => form.clearErrors((0, import_laravel_precognition.resolveName)(field))
662
+ )
663
+ });
664
+ return precognitiveForm;
665
+ };
666
+ form.withPrecognition = withPrecognition;
667
+ return precognitionEndpoint.current ? form.withPrecognition(precognitionEndpoint.current) : form;
568
668
  }
569
669
 
570
670
  // src/Form.ts
@@ -596,10 +696,27 @@ var Form = (0, import_react11.forwardRef)(
596
696
  resetOnSuccess = false,
597
697
  setDefaultsOnSuccess = false,
598
698
  invalidateCacheTags = [],
699
+ validateFiles = false,
700
+ validationTimeout = 1500,
701
+ withAllErrors = false,
599
702
  children,
600
703
  ...props
601
704
  }, ref) => {
602
- const form = useForm({});
705
+ const getTransformedData = () => {
706
+ const [_url, data] = getUrlAndData();
707
+ return transform(data);
708
+ };
709
+ const form = useForm({}).withPrecognition(
710
+ () => resolvedMethod,
711
+ () => getUrlAndData()[0]
712
+ ).setValidationTimeout(validationTimeout);
713
+ if (validateFiles) {
714
+ form.validateFiles();
715
+ }
716
+ if (withAllErrors) {
717
+ form.withAllErrors();
718
+ }
719
+ form.transform(getTransformedData);
603
720
  const formElement = (0, import_react11.useRef)(void 0);
604
721
  const resolvedMethod = (0, import_react11.useMemo)(() => {
605
722
  return (0, import_core5.isUrlMethodPair)(action) ? action.method : method.toLowerCase();
@@ -608,22 +725,48 @@ var Form = (0, import_react11.forwardRef)(
608
725
  const defaultData = (0, import_react11.useRef)(new FormData());
609
726
  const getFormData = () => new FormData(formElement.current);
610
727
  const getData = () => (0, import_core5.formDataToObject)(getFormData());
728
+ const getUrlAndData = () => {
729
+ return (0, import_core5.mergeDataIntoQueryString)(
730
+ resolvedMethod,
731
+ (0, import_core5.isUrlMethodPair)(action) ? action.url : action,
732
+ getData(),
733
+ queryStringArrayFormat
734
+ );
735
+ };
611
736
  const updateDirtyState = (event) => deferStateUpdate(
612
737
  () => setIsDirty(event.type === "reset" ? false : !(0, import_lodash_es2.isEqual)(getData(), (0, import_core5.formDataToObject)(defaultData.current)))
613
738
  );
739
+ const clearErrors = (...names) => {
740
+ form.clearErrors(...names);
741
+ return form;
742
+ };
614
743
  (0, import_react11.useEffect)(() => {
615
744
  defaultData.current = getFormData();
745
+ form.setDefaults(getData());
616
746
  const formEvents = ["input", "change", "reset"];
617
747
  formEvents.forEach((e) => formElement.current.addEventListener(e, updateDirtyState));
618
- return () => formEvents.forEach((e) => formElement.current?.removeEventListener(e, updateDirtyState));
748
+ return () => {
749
+ formEvents.forEach((e) => formElement.current?.removeEventListener(e, updateDirtyState));
750
+ };
619
751
  }, []);
752
+ (0, import_react11.useEffect)(() => {
753
+ form.setValidationTimeout(validationTimeout);
754
+ }, [validationTimeout]);
755
+ (0, import_react11.useEffect)(() => {
756
+ if (validateFiles) {
757
+ form.validateFiles();
758
+ } else {
759
+ form.withoutFileValidation();
760
+ }
761
+ }, [validateFiles]);
620
762
  const reset = (...fields) => {
621
763
  if (formElement.current) {
622
764
  (0, import_core5.resetFormFields)(formElement.current, defaultData.current, fields);
623
765
  }
766
+ form.reset(...fields);
624
767
  };
625
768
  const resetAndClearErrors = (...fields) => {
626
- form.clearErrors(...fields);
769
+ clearErrors(...fields);
627
770
  reset(...fields);
628
771
  };
629
772
  const maybeReset = (resetOption) => {
@@ -637,12 +780,7 @@ var Form = (0, import_react11.forwardRef)(
637
780
  }
638
781
  };
639
782
  const submit = () => {
640
- const [url, _data] = (0, import_core5.mergeDataIntoQueryString)(
641
- resolvedMethod,
642
- (0, import_core5.isUrlMethodPair)(action) ? action.url : action,
643
- getData(),
644
- queryStringArrayFormat
645
- );
783
+ const [url, _data] = getUrlAndData();
646
784
  const submitOptions = {
647
785
  headers,
648
786
  queryStringArrayFormat,
@@ -672,7 +810,6 @@ var Form = (0, import_react11.forwardRef)(
672
810
  },
673
811
  ...options
674
812
  };
675
- form.transform(() => transform(_data));
676
813
  form.submit(resolvedMethod, url, submitOptions);
677
814
  };
678
815
  const defaults = () => {
@@ -687,14 +824,22 @@ var Form = (0, import_react11.forwardRef)(
687
824
  wasSuccessful: form.wasSuccessful,
688
825
  recentlySuccessful: form.recentlySuccessful,
689
826
  isDirty,
690
- clearErrors: form.clearErrors,
827
+ clearErrors,
691
828
  resetAndClearErrors,
692
829
  setError: form.setError,
693
830
  reset,
694
831
  submit,
695
832
  defaults,
696
833
  getData,
697
- getFormData
834
+ getFormData,
835
+ // Precognition
836
+ validator: () => form.validator(),
837
+ validating: form.validating,
838
+ valid: form.valid,
839
+ invalid: form.invalid,
840
+ validate: (field, config2) => form.validate(...import_core5.UseFormUtils.mergeHeadersForValidation(field, config2, headers)),
841
+ touch: form.touch,
842
+ touched: form.touched
698
843
  });
699
844
  (0, import_react11.useImperativeHandle)(ref, exposed, [form, isDirty, submit]);
700
845
  return (0, import_react11.createElement)(
@@ -1342,22 +1487,17 @@ var WhenVisible = ({ children, data, params, buffer, as, always, fallback }) =>
1342
1487
  always = always ?? false;
1343
1488
  as = as ?? "div";
1344
1489
  fallback = fallback ?? null;
1345
- const [loaded, setLoaded] = (0, import_react17.useState)(false);
1490
+ const pageProps = usePage().props;
1491
+ const keys = (0, import_react17.useMemo)(() => data ? Array.isArray(data) ? data : [data] : [], [data]);
1492
+ const [loaded, setLoaded] = (0, import_react17.useState)(() => keys.length > 0 && keys.every((key) => pageProps[key] !== void 0));
1346
1493
  const fetching = (0, import_react17.useRef)(false);
1347
1494
  const ref = (0, import_react17.useRef)(null);
1348
1495
  const observer = (0, import_react17.useRef)(null);
1349
- const page = usePage();
1350
1496
  (0, import_react17.useEffect)(() => {
1351
- if (Array.isArray(data)) {
1352
- if (data.some((key) => page.props[key] === void 0)) {
1353
- setLoaded(false);
1354
- }
1355
- } else if (data) {
1356
- if (page.props[data] === void 0) {
1357
- setLoaded(false);
1358
- }
1497
+ if (keys.length > 0) {
1498
+ setLoaded(keys.every((key) => pageProps[key] !== void 0));
1359
1499
  }
1360
- }, [data, ...Array.isArray(data) ? data.map((key) => page.props[key]) : [page.props[data]]]);
1500
+ }, [pageProps, keys]);
1361
1501
  const getReloadParams = (0, import_react17.useCallback)(() => {
1362
1502
  if (data) {
1363
1503
  return {
@@ -1410,11 +1550,14 @@ var WhenVisible = ({ children, data, params, buffer, as, always, fallback }) =>
1410
1550
  if (!ref.current) {
1411
1551
  return;
1412
1552
  }
1553
+ if (loaded && !always) {
1554
+ return;
1555
+ }
1413
1556
  registerObserver();
1414
1557
  return () => {
1415
1558
  observer.current?.disconnect();
1416
1559
  };
1417
- }, [loaded, ref, getReloadParams, buffer]);
1560
+ }, [always, loaded, ref, getReloadParams, buffer]);
1418
1561
  const resolveChildren = () => typeof children === "function" ? children() : children;
1419
1562
  const resolveFallback = () => typeof fallback === "function" ? fallback() : fallback;
1420
1563
  if (always || !loaded) {