@inertiajs/vue3 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.esm.js CHANGED
@@ -69,18 +69,24 @@ var remember_default = remember;
69
69
 
70
70
  // src/useForm.ts
71
71
  import {
72
- router as router2
72
+ router as router2,
73
+ UseFormUtils
73
74
  } from "@inertiajs/core";
75
+ import {
76
+ createValidator,
77
+ resolveName,
78
+ toSimpleValidationErrors
79
+ } from "laravel-precognition";
74
80
  import { cloneDeep as cloneDeep2, get, has, isEqual, set } from "lodash-es";
75
81
  import { reactive, watch } from "vue";
76
- function useForm(rememberKeyOrData, maybeData) {
77
- const rememberKey = typeof rememberKeyOrData === "string" ? rememberKeyOrData : null;
78
- const data = (typeof rememberKeyOrData === "string" ? maybeData : rememberKeyOrData) ?? {};
82
+ function useForm(...args) {
83
+ let { rememberKey, data, precognitionEndpoint } = UseFormUtils.parseUseFormArguments(...args);
79
84
  const restored = rememberKey ? router2.restore(rememberKey) : null;
80
85
  let defaults = typeof data === "function" ? cloneDeep2(data()) : cloneDeep2(data);
81
86
  let cancelToken = null;
82
87
  let recentlySuccessfulTimeoutId;
83
88
  let transform = (data2) => data2;
89
+ let validatorRef = null;
84
90
  let defaultsCalledInOnSuccess = false;
85
91
  const form = reactive({
86
92
  ...restored ? restored.data : cloneDeep2(defaults),
@@ -91,6 +97,76 @@ function useForm(rememberKeyOrData, maybeData) {
91
97
  progress: null,
92
98
  wasSuccessful: false,
93
99
  recentlySuccessful: false,
100
+ withPrecognition(...args2) {
101
+ precognitionEndpoint = UseFormUtils.createWayfinderCallback(...args2);
102
+ const formWithPrecognition = this;
103
+ let withAllErrors = false;
104
+ const validator = createValidator((client) => {
105
+ const { method, url } = precognitionEndpoint();
106
+ const transformedData = transform(this.data());
107
+ return client[method](url, transformedData);
108
+ }, cloneDeep2(defaults));
109
+ validatorRef = validator;
110
+ validator.on("validatingChanged", () => {
111
+ formWithPrecognition.validating = validator.validating();
112
+ }).on("validatedChanged", () => {
113
+ formWithPrecognition.__valid = validator.valid();
114
+ }).on("touchedChanged", () => {
115
+ formWithPrecognition.__touched = validator.touched();
116
+ }).on("errorsChanged", () => {
117
+ const validationErrors = withAllErrors ? validator.errors() : toSimpleValidationErrors(validator.errors());
118
+ this.errors = {};
119
+ this.setError(validationErrors);
120
+ formWithPrecognition.__valid = validator.valid();
121
+ });
122
+ const tap = (value, callback) => {
123
+ callback(value);
124
+ return value;
125
+ };
126
+ Object.assign(formWithPrecognition, {
127
+ __touched: [],
128
+ __valid: [],
129
+ validating: false,
130
+ validator: () => validator,
131
+ withAllErrors: () => tap(formWithPrecognition, () => withAllErrors = true),
132
+ valid: (field) => formWithPrecognition.__valid.includes(field),
133
+ invalid: (field) => field in this.errors,
134
+ setValidationTimeout: (duration) => tap(formWithPrecognition, () => validator.setTimeout(duration)),
135
+ validateFiles: () => tap(formWithPrecognition, () => validator.validateFiles()),
136
+ withoutFileValidation: () => tap(formWithPrecognition, () => validator.withoutFileValidation()),
137
+ touch: (field, ...fields) => {
138
+ if (Array.isArray(field)) {
139
+ validator.touch(field);
140
+ } else if (typeof field === "string") {
141
+ validator.touch([field, ...fields]);
142
+ } else {
143
+ validator.touch(field);
144
+ }
145
+ return formWithPrecognition;
146
+ },
147
+ touched: (field) => typeof field === "string" ? formWithPrecognition.__touched.includes(field) : formWithPrecognition.__touched.length > 0,
148
+ validate: (field, config2) => {
149
+ if (typeof field === "object" && !("target" in field)) {
150
+ config2 = field;
151
+ field = void 0;
152
+ }
153
+ if (field === void 0) {
154
+ validator.validate(config2);
155
+ } else {
156
+ const fieldName = resolveName(field);
157
+ const transformedData = transform(this.data());
158
+ validator.validate(fieldName, get(transformedData, fieldName), config2);
159
+ }
160
+ return formWithPrecognition;
161
+ },
162
+ setErrors: (errors) => tap(formWithPrecognition, () => this.setError(errors)),
163
+ forgetError: (field) => tap(
164
+ formWithPrecognition,
165
+ () => this.clearErrors(resolveName(field))
166
+ )
167
+ });
168
+ return formWithPrecognition;
169
+ },
94
170
  data() {
95
171
  return Object.keys(defaults).reduce((carry, key2) => {
96
172
  return set(carry, key2, get(this, key2));
@@ -111,6 +187,7 @@ function useForm(rememberKeyOrData, maybeData) {
111
187
  } else {
112
188
  defaults = typeof fieldOrFields === "string" ? set(cloneDeep2(defaults), fieldOrFields, maybeValue) : Object.assign({}, cloneDeep2(defaults), fieldOrFields);
113
189
  }
190
+ validatorRef?.defaults(defaults);
114
191
  return this;
115
192
  },
116
193
  reset(...fields) {
@@ -126,11 +203,14 @@ function useForm(rememberKeyOrData, maybeData) {
126
203
  set(this, key2, get(resolvedData, key2));
127
204
  });
128
205
  }
206
+ validatorRef?.reset(...fields);
129
207
  return this;
130
208
  },
131
209
  setError(fieldOrFields, maybeValue) {
132
- Object.assign(this.errors, typeof fieldOrFields === "string" ? { [fieldOrFields]: maybeValue } : fieldOrFields);
210
+ const errors = typeof fieldOrFields === "string" ? { [fieldOrFields]: maybeValue } : fieldOrFields;
211
+ Object.assign(this.errors, errors);
133
212
  this.hasErrors = Object.keys(this.errors).length > 0;
213
+ validatorRef?.setErrors(errors);
134
214
  return this;
135
215
  },
136
216
  clearErrors(...fields) {
@@ -142,6 +222,13 @@ function useForm(rememberKeyOrData, maybeData) {
142
222
  {}
143
223
  );
144
224
  this.hasErrors = Object.keys(this.errors).length > 0;
225
+ if (validatorRef) {
226
+ if (fields.length === 0) {
227
+ validatorRef.setErrors({});
228
+ } else {
229
+ fields.forEach(validatorRef.forgetError);
230
+ }
231
+ }
145
232
  return this;
146
233
  },
147
234
  resetAndClearErrors(...fields) {
@@ -149,11 +236,8 @@ function useForm(rememberKeyOrData, maybeData) {
149
236
  this.clearErrors(...fields);
150
237
  return this;
151
238
  },
152
- submit(...args) {
153
- const objectPassed = args[0] !== null && typeof args[0] === "object";
154
- const method = objectPassed ? args[0].method : args[0];
155
- const url = objectPassed ? args[0].url : args[1];
156
- const options = (objectPassed ? args[1] : args[2]) ?? {};
239
+ submit(...args2) {
240
+ const { method, url, options } = UseFormUtils.parseSubmitArguments(args2, precognitionEndpoint);
157
241
  defaultsCalledInOnSuccess = false;
158
242
  const _options = {
159
243
  ...options,
@@ -178,7 +262,7 @@ function useForm(rememberKeyOrData, maybeData) {
178
262
  }
179
263
  },
180
264
  onProgress: (event) => {
181
- this.progress = event;
265
+ this.progress = event ?? null;
182
266
  if (options.onProgress) {
183
267
  return options.onProgress(event);
184
268
  }
@@ -260,17 +344,18 @@ function useForm(rememberKeyOrData, maybeData) {
260
344
  this.setError(restored2.errors);
261
345
  }
262
346
  });
347
+ const typedForm = form;
263
348
  watch(
264
- form,
349
+ typedForm,
265
350
  (newValue) => {
266
- form.isDirty = !isEqual(form.data(), defaults);
351
+ typedForm.isDirty = !isEqual(typedForm.data(), defaults);
267
352
  if (rememberKey) {
268
353
  router2.remember(cloneDeep2(newValue.__remember()), rememberKey);
269
354
  }
270
355
  },
271
356
  { immediate: true, deep: true }
272
357
  );
273
- return form;
358
+ return precognitionEndpoint ? typedForm.withPrecognition(precognitionEndpoint) : typedForm;
274
359
  }
275
360
 
276
361
  // src/app.ts
@@ -485,10 +570,11 @@ import {
485
570
  formDataToObject,
486
571
  isUrlMethodPair,
487
572
  mergeDataIntoQueryString,
488
- resetFormFields
573
+ resetFormFields,
574
+ UseFormUtils as UseFormUtils2
489
575
  } from "@inertiajs/core";
490
576
  import { isEqual as isEqual2 } from "lodash-es";
491
- import { computed as computed2, defineComponent as defineComponent3, h as h3, onBeforeUnmount, onMounted, ref as ref2 } from "vue";
577
+ import { computed as computed2, defineComponent as defineComponent3, h as h3, onBeforeUnmount, onMounted, ref as ref2, watch as watch2 } from "vue";
492
578
  var noop = () => void 0;
493
579
  var Form = defineComponent3({
494
580
  name: "Form",
@@ -581,10 +667,35 @@ var Form = defineComponent3({
581
667
  invalidateCacheTags: {
582
668
  type: [String, Array],
583
669
  default: () => []
670
+ },
671
+ validateFiles: {
672
+ type: Boolean,
673
+ default: false
674
+ },
675
+ validationTimeout: {
676
+ type: Number,
677
+ default: 1500
678
+ },
679
+ withAllErrors: {
680
+ type: Boolean,
681
+ default: false
584
682
  }
585
683
  },
586
684
  setup(props, { slots, attrs, expose }) {
587
- const form = useForm({});
685
+ const getTransformedData = () => {
686
+ const [_url, data] = getUrlAndData();
687
+ return props.transform(data);
688
+ };
689
+ const form = useForm({}).withPrecognition(
690
+ () => method.value,
691
+ () => getUrlAndData()[0]
692
+ ).transform(getTransformedData).setValidationTimeout(props.validationTimeout);
693
+ if (props.validateFiles) {
694
+ form.validateFiles();
695
+ }
696
+ if (props.withAllErrors) {
697
+ form.withAllErrors();
698
+ }
588
699
  const formElement = ref2();
589
700
  const method = computed2(
590
701
  () => isUrlMethodPair(props.action) ? props.action.method : props.method.toLowerCase()
@@ -597,18 +708,29 @@ var Form = defineComponent3({
597
708
  const formEvents = ["input", "change", "reset"];
598
709
  onMounted(() => {
599
710
  defaultData.value = getFormData();
711
+ form.defaults(getData());
600
712
  formEvents.forEach((e) => formElement.value.addEventListener(e, onFormUpdate));
601
713
  });
714
+ watch2(
715
+ () => props.validateFiles,
716
+ (value) => value ? form.validateFiles() : form.withoutFileValidation()
717
+ );
718
+ watch2(
719
+ () => props.validationTimeout,
720
+ (value) => form.setValidationTimeout(value)
721
+ );
602
722
  onBeforeUnmount(() => formEvents.forEach((e) => formElement.value?.removeEventListener(e, onFormUpdate)));
603
723
  const getFormData = () => new FormData(formElement.value);
604
724
  const getData = () => formDataToObject(getFormData());
605
- const submit = () => {
606
- const [action, data] = mergeDataIntoQueryString(
725
+ const getUrlAndData = () => {
726
+ return mergeDataIntoQueryString(
607
727
  method.value,
608
728
  isUrlMethodPair(props.action) ? props.action.url : props.action,
609
729
  getData(),
610
730
  props.queryStringArrayFormat
611
731
  );
732
+ };
733
+ const submit = () => {
612
734
  const maybeReset = (resetOption) => {
613
735
  if (!resetOption) {
614
736
  return;
@@ -645,13 +767,18 @@ var Form = defineComponent3({
645
767
  },
646
768
  ...props.options
647
769
  };
648
- form.transform(() => props.transform(data)).submit(method.value, action, submitOptions);
770
+ const [url, data] = getUrlAndData();
771
+ form.transform(() => props.transform(data)).submit(method.value, url, submitOptions);
649
772
  };
650
773
  const reset = (...fields) => {
651
774
  resetFormFields(formElement.value, defaultData.value, fields);
775
+ form.reset(...fields);
652
776
  };
653
- const resetAndClearErrors = (...fields) => {
777
+ const clearErrors = (...fields) => {
654
778
  form.clearErrors(...fields);
779
+ };
780
+ const resetAndClearErrors = (...fields) => {
781
+ clearErrors(...fields);
655
782
  reset(...fields);
656
783
  };
657
784
  const defaults = () => {
@@ -677,7 +804,10 @@ var Form = defineComponent3({
677
804
  get recentlySuccessful() {
678
805
  return form.recentlySuccessful;
679
806
  },
680
- clearErrors: (...fields) => form.clearErrors(...fields),
807
+ get validating() {
808
+ return form.validating;
809
+ },
810
+ clearErrors,
681
811
  resetAndClearErrors,
682
812
  setError: (fieldOrFields, maybeValue) => form.setError(typeof fieldOrFields === "string" ? { [fieldOrFields]: maybeValue } : fieldOrFields),
683
813
  get isDirty() {
@@ -687,7 +817,14 @@ var Form = defineComponent3({
687
817
  submit,
688
818
  defaults,
689
819
  getData,
690
- getFormData
820
+ getFormData,
821
+ // Precognition
822
+ touch: form.touch,
823
+ valid: form.valid,
824
+ invalid: form.invalid,
825
+ touched: form.touched,
826
+ validate: (field, config2) => form.validate(...UseFormUtils2.mergeHeadersForValidation(field, config2, props.headers)),
827
+ validator: () => form.validator()
691
828
  };
692
829
  expose(exposed);
693
830
  return () => {
@@ -846,7 +983,7 @@ import {
846
983
  getScrollableParent,
847
984
  useInfiniteScroll
848
985
  } from "@inertiajs/core";
849
- import { computed as computed3, defineComponent as defineComponent5, Fragment, h as h4, onMounted as onMounted2, onUnmounted, ref as ref3, watch as watch2 } from "vue";
986
+ import { computed as computed3, defineComponent as defineComponent5, Fragment, h as h4, onMounted as onMounted2, onUnmounted, ref as ref3, watch as watch3 } from "vue";
850
987
  var resolveHTMLElement = (value, fallback) => {
851
988
  if (!value) {
852
989
  return fallback;
@@ -991,7 +1128,7 @@ var InfiniteScroll = defineComponent5({
991
1128
  }
992
1129
  });
993
1130
  onUnmounted(flushInfiniteScroll);
994
- watch2(
1131
+ watch3(
995
1132
  () => [autoLoad.value, props.onlyNext, props.onlyPrevious],
996
1133
  ([enabled]) => {
997
1134
  enabled ? elementManager.enableTriggers() : elementManager.disableTriggers();
@@ -1432,7 +1569,7 @@ function usePrefetch(options = {}) {
1432
1569
  // src/useRemember.ts
1433
1570
  import { router as router8 } from "@inertiajs/core";
1434
1571
  import { cloneDeep as cloneDeep3 } from "lodash-es";
1435
- import { isReactive, reactive as reactive3, ref as ref6, watch as watch3 } from "vue";
1572
+ import { isReactive, reactive as reactive3, ref as ref6, watch as watch4 } from "vue";
1436
1573
  function useRemember(data, key2) {
1437
1574
  if (typeof data === "object" && data !== null && data.__rememberable === false) {
1438
1575
  return data;
@@ -1441,7 +1578,7 @@ function useRemember(data, key2) {
1441
1578
  const type = isReactive(data) ? reactive3 : ref6;
1442
1579
  const hasCallbacks = typeof data.__remember === "function" && typeof data.__restore === "function";
1443
1580
  const remembered = type(restored === void 0 ? data : hasCallbacks ? data.__restore(restored) : restored);
1444
- watch3(
1581
+ watch4(
1445
1582
  remembered,
1446
1583
  (newValue) => {
1447
1584
  router8.remember(cloneDeep3(hasCallbacks ? data.__remember() : newValue), key2);
@@ -1486,21 +1623,21 @@ var whenVisible_default = defineComponent7({
1486
1623
  unmounted() {
1487
1624
  this.observer?.disconnect();
1488
1625
  },
1626
+ computed: {
1627
+ keys() {
1628
+ return this.data ? Array.isArray(this.data) ? this.data : [this.data] : [];
1629
+ }
1630
+ },
1489
1631
  created() {
1490
1632
  const page2 = usePage();
1491
1633
  this.$watch(
1634
+ () => this.keys.map((key2) => page2.props[key2]),
1492
1635
  () => {
1493
- return Array.isArray(this.data) ? this.data.map((data) => page2.props[data]) : page2.props[this.data];
1494
- },
1495
- (value) => {
1496
- if (Array.isArray(this.data)) {
1497
- if (this.data.every((data) => page2.props[data] !== void 0)) {
1498
- return;
1499
- }
1500
- } else if (value !== void 0) {
1636
+ const exists = this.keys.length > 0 && this.keys.every((key2) => page2.props[key2] !== void 0);
1637
+ this.loaded = exists;
1638
+ if (exists && !this.always) {
1501
1639
  return;
1502
1640
  }
1503
- this.loaded = false;
1504
1641
  this.$nextTick(this.registerObserver);
1505
1642
  },
1506
1643
  { immediate: true }