@inertiajs/core 2.3.17 → 3.0.0-beta.2

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
@@ -1,66 +1,8 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/index.ts
31
- var index_exports = {};
32
- __export(index_exports, {
33
- FormComponentResetSymbol: () => FormComponentResetSymbol,
34
- UseFormUtils: () => UseFormUtils,
35
- config: () => config,
36
- createHeadManager: () => createHeadManager,
37
- formDataToObject: () => formDataToObject,
38
- getInitialPageFromDOM: () => getInitialPageFromDOM,
39
- getScrollableParent: () => getScrollableParent,
40
- hideProgress: () => hide2,
41
- hrefToUrl: () => hrefToUrl,
42
- isUrlMethodPair: () => isUrlMethodPair,
43
- mergeDataIntoQueryString: () => mergeDataIntoQueryString,
44
- objectToFormData: () => objectToFormData,
45
- progress: () => progress,
46
- resetFormFields: () => resetFormFields,
47
- revealProgress: () => reveal,
48
- router: () => router,
49
- setupProgress: () => setupProgress,
50
- shouldIntercept: () => shouldIntercept,
51
- shouldNavigate: () => shouldNavigate,
52
- urlHasProtocol: () => urlHasProtocol,
53
- urlToString: () => urlToString,
54
- urlWithoutHash: () => urlWithoutHash,
55
- useInfiniteScroll: () => useInfiniteScroll
56
- });
57
- module.exports = __toCommonJS(index_exports);
58
-
59
1
  // src/router.ts
60
- var import_lodash_es5 = require("lodash-es");
2
+ import { cloneDeep as cloneDeep3, get as get7, isEqual as isEqual3, set as set5 } from "lodash-es";
61
3
 
62
4
  // src/config.ts
63
- var import_lodash_es = require("lodash-es");
5
+ import { get, has, set } from "lodash-es";
64
6
  var Config = class {
65
7
  constructor(defaults) {
66
8
  this.config = {};
@@ -76,14 +18,14 @@ var Config = class {
76
18
  this.config = newConfig;
77
19
  }
78
20
  get(key) {
79
- return (0, import_lodash_es.has)(this.config, key) ? (0, import_lodash_es.get)(this.config, key) : (0, import_lodash_es.get)(this.defaults, key);
21
+ return has(this.config, key) ? get(this.config, key) : get(this.defaults, key);
80
22
  }
81
23
  set(keyOrValues, value) {
82
24
  if (typeof keyOrValues === "string") {
83
- (0, import_lodash_es.set)(this.config, keyOrValues, value);
25
+ set(this.config, keyOrValues, value);
84
26
  } else {
85
27
  Object.entries(keyOrValues).forEach(([key, val]) => {
86
- (0, import_lodash_es.set)(this.config, key, val);
28
+ set(this.config, key, val);
87
29
  });
88
30
  }
89
31
  }
@@ -94,18 +36,15 @@ var config = new Config({
94
36
  forceIndicesArrayFormatInFormData: true,
95
37
  withAllErrors: false
96
38
  },
97
- future: {
98
- preserveEqualProps: false,
99
- useDataInertiaHeadAttribute: false,
100
- useDialogForErrorModal: false,
101
- useScriptElementForInitialPage: false
102
- },
103
39
  prefetch: {
104
40
  cacheFor: 3e4,
105
41
  hoverDelay: 75
106
42
  }
107
43
  });
108
44
 
45
+ // src/eventHandler.ts
46
+ import { get as get4 } from "lodash-es";
47
+
109
48
  // src/debounce.ts
110
49
  function debounce(fn, delay) {
111
50
  let timeoutID;
@@ -125,14 +64,14 @@ var fireBeforeEvent = (visit) => {
125
64
  var fireErrorEvent = (errors) => {
126
65
  return fireEvent("error", { detail: { errors } });
127
66
  };
128
- var fireExceptionEvent = (exception) => {
129
- return fireEvent("exception", { cancelable: true, detail: { exception } });
67
+ var fireNetworkErrorEvent = (exception) => {
68
+ return fireEvent("networkError", { cancelable: true, detail: { exception } });
130
69
  };
131
70
  var fireFinishEvent = (visit) => {
132
71
  return fireEvent("finish", { detail: { visit } });
133
72
  };
134
- var fireInvalidEvent = (response) => {
135
- return fireEvent("invalid", { cancelable: true, detail: { response } });
73
+ var fireHttpExceptionEvent = (response) => {
74
+ return fireEvent("httpException", { cancelable: true, detail: { response } });
136
75
  };
137
76
  var fireBeforeUpdateEvent = (page2) => {
138
77
  return fireEvent("beforeUpdate", { detail: { page: page2 } });
@@ -150,7 +89,7 @@ var fireSuccessEvent = (page2) => {
150
89
  return fireEvent("success", { detail: { page: page2 } });
151
90
  };
152
91
  var firePrefetchedEvent = (response, visit) => {
153
- return fireEvent("prefetched", { detail: { fetchedAt: Date.now(), response: response.data, visit } });
92
+ return fireEvent("prefetched", { detail: { fetchedAt: Date.now(), response, visit } });
154
93
  };
155
94
  var firePrefetchingEvent = (visit) => {
156
95
  return fireEvent("prefetching", { detail: { visit } });
@@ -160,7 +99,7 @@ var fireFlashEvent = (flash) => {
160
99
  };
161
100
 
162
101
  // src/history.ts
163
- var import_lodash_es3 = require("lodash-es");
102
+ import { cloneDeep as cloneDeep2, isEqual } from "lodash-es";
164
103
 
165
104
  // src/sessionStorage.ts
166
105
  var SessionStorage = class {
@@ -331,8 +270,11 @@ var getKeyFromSessionStorage = async () => {
331
270
  return key;
332
271
  };
333
272
 
273
+ // src/page.ts
274
+ import { get as get3, set as set3 } from "lodash-es";
275
+
334
276
  // src/prefetched.ts
335
- var import_lodash_es2 = require("lodash-es");
277
+ import { cloneDeep, get as get2 } from "lodash-es";
336
278
 
337
279
  // src/objectUtils.ts
338
280
  var objectsAreEqual = (obj1, obj2, excludeKeys) => {
@@ -564,7 +506,7 @@ var PrefetchedRequests = class {
564
506
  }) || null;
565
507
  }
566
508
  withoutPurposePrefetchHeader(params) {
567
- const newParams = (0, import_lodash_es2.cloneDeep)(params);
509
+ const newParams = cloneDeep(params);
568
510
  if (newParams.headers["Purpose"] === "prefetch") {
569
511
  delete newParams.headers["Purpose"];
570
512
  }
@@ -593,7 +535,10 @@ var PrefetchedRequests = class {
593
535
  "onCancelToken",
594
536
  "onPrefetching",
595
537
  "async",
596
- "viewTransition"
538
+ "viewTransition",
539
+ "optimistic",
540
+ "component",
541
+ "pageProps"
597
542
  ]
598
543
  );
599
544
  }
@@ -603,7 +548,7 @@ var PrefetchedRequests = class {
603
548
  const pageResponse = response.getPageResponse();
604
549
  page.mergeOncePropsIntoResponse(pageResponse, { force: true });
605
550
  for (const [group, deferredProps] of Object.entries(pageResponse.deferredProps ?? {})) {
606
- const remaining = deferredProps.filter((prop) => pageResponse.props[prop] === void 0);
551
+ const remaining = deferredProps.filter((prop) => get2(pageResponse.props, prop) === void 0);
607
552
  if (remaining.length > 0) {
608
553
  pageResponse.deferredProps[group] = remaining;
609
554
  } else {
@@ -647,7 +592,7 @@ var elementInViewport = (el) => {
647
592
  var getScrollableParent = (element) => {
648
593
  const allowsVerticalScroll = (el) => {
649
594
  const computedStyle = window.getComputedStyle(el);
650
- if (["scroll", "overlay"].includes(computedStyle.overflowY)) {
595
+ if (computedStyle.overflowY === "scroll") {
651
596
  return true;
652
597
  }
653
598
  if (computedStyle.overflowY !== "auto") {
@@ -660,7 +605,7 @@ var getScrollableParent = (element) => {
660
605
  };
661
606
  const allowsHorizontalScroll = (el) => {
662
607
  const computedStyle = window.getComputedStyle(el);
663
- if (["scroll", "overlay"].includes(computedStyle.overflowX)) {
608
+ if (computedStyle.overflowX === "scroll") {
664
609
  return true;
665
610
  }
666
611
  if (computedStyle.overflowX !== "auto") {
@@ -736,16 +681,10 @@ var requestAnimationFrame = (cb, times = 1) => {
736
681
  }
737
682
  });
738
683
  };
739
- var getInitialPageFromDOM = (id, useScriptElement = false) => {
684
+ var getInitialPageFromDOM = (id) => {
740
685
  if (typeof window === "undefined") {
741
686
  return null;
742
687
  }
743
- if (!useScriptElement) {
744
- const el = document.getElementById(id);
745
- if (el?.dataset.page) {
746
- return JSON.parse(el.dataset.page);
747
- }
748
- }
749
688
  const scriptEl = document.querySelector(`script[data-page="${id}"][type="application/json"]`);
750
689
  if (scriptEl?.textContent) {
751
690
  return JSON.parse(scriptEl.textContent);
@@ -844,9 +783,6 @@ var Scroll = class {
844
783
  }
845
784
  };
846
785
 
847
- // src/url.ts
848
- var qs = __toESM(require("qs"), 1);
849
-
850
786
  // src/files.ts
851
787
  var isFile = (value) => typeof File !== "undefined" && value instanceof File || value instanceof Blob || typeof FileList !== "undefined" && value instanceof FileList && value.length > 0;
852
788
  function hasFiles(data) {
@@ -893,6 +829,88 @@ function append(form, key, value, format) {
893
829
  objectToFormData(value, form, key, format);
894
830
  }
895
831
 
832
+ // src/queryString.ts
833
+ function hasIndices(url) {
834
+ return /\[\d+\]/.test(decodeURIComponent(url.search));
835
+ }
836
+ function parse(query) {
837
+ if (!query || query === "?") {
838
+ return {};
839
+ }
840
+ const result = {};
841
+ query.replace(/^\?/, "").split("&").filter(Boolean).forEach((segment) => {
842
+ const [rawKey, rawValue] = splitPair(segment);
843
+ set2(result, decode(rawKey), decode(rawValue));
844
+ });
845
+ return result;
846
+ }
847
+ function stringify(data, arrayFormat) {
848
+ const pairs = [];
849
+ build(data, "", pairs, arrayFormat);
850
+ return pairs.length ? "?" + pairs.join("&") : "";
851
+ }
852
+ function splitPair(pair) {
853
+ const index = pair.indexOf("=");
854
+ return index === -1 ? [pair, ""] : [pair.substring(0, index), pair.substring(index + 1)];
855
+ }
856
+ function decode(value) {
857
+ return decodeURIComponent(value.replace(/\+/g, " "));
858
+ }
859
+ function set2(target, key, value) {
860
+ const keys = parseKey(key);
861
+ let current = target;
862
+ while (keys.length > 1) {
863
+ const segment = keys.shift();
864
+ const nextIsArrayPush = keys[0] === "";
865
+ if (typeof current[segment] !== "object" || current[segment] === null) {
866
+ current[segment] = nextIsArrayPush ? [] : {};
867
+ }
868
+ current = current[segment];
869
+ }
870
+ const final = keys.shift();
871
+ if (final === "" && Array.isArray(current)) {
872
+ current.push(value);
873
+ } else {
874
+ current[final] = value;
875
+ }
876
+ }
877
+ function parseKey(key) {
878
+ const segments = [];
879
+ const base = key.split("[")[0];
880
+ if (base) {
881
+ segments.push(base);
882
+ }
883
+ let match;
884
+ const pattern = /\[([^\]]*)\]/g;
885
+ while ((match = pattern.exec(key)) !== null) {
886
+ segments.push(match[1]);
887
+ }
888
+ return segments;
889
+ }
890
+ function build(value, prefix, pairs, arrayFormat) {
891
+ if (value === void 0) {
892
+ return;
893
+ }
894
+ if (value === null) {
895
+ pairs.push(`${prefix}=`);
896
+ return;
897
+ }
898
+ if (Array.isArray(value)) {
899
+ value.forEach((item, index) => {
900
+ const key = arrayFormat === "indices" ? `${prefix}[${index}]` : `${prefix}[]`;
901
+ build(item, key, pairs, arrayFormat);
902
+ });
903
+ return;
904
+ }
905
+ if (typeof value === "object") {
906
+ Object.keys(value).forEach((key) => {
907
+ build(value[key], prefix ? `${prefix}[${key}]` : key, pairs, arrayFormat);
908
+ });
909
+ return;
910
+ }
911
+ pairs.push(`${prefix}=${encodeURIComponent(String(value))}`);
912
+ }
913
+
896
914
  // src/url.ts
897
915
  function hrefToUrl(href) {
898
916
  return new URL(href.toString(), typeof window === "undefined" ? void 0 : window.location.toString());
@@ -921,15 +939,8 @@ function mergeDataIntoQueryString(method, href, data, qsArrayFormat = "brackets"
921
939
  const hasHash = href.toString().includes("#");
922
940
  const url = new URL(href.toString(), typeof window === "undefined" ? "http://localhost" : window.location.toString());
923
941
  if (hasDataForQueryString) {
924
- const hasIndices = /\[\d+\]/.test(decodeURIComponent(url.search));
925
- const parseOptions = { ignoreQueryPrefix: true, allowSparse: true };
926
- url.search = qs.stringify(
927
- { ...qs.parse(url.search, parseOptions), ...data },
928
- {
929
- encodeValuesOnly: true,
930
- arrayFormat: hasIndices ? "indices" : qsArrayFormat
931
- }
932
- );
942
+ const arrayFormat = hasIndices(url) ? "indices" : qsArrayFormat;
943
+ url.search = stringify({ ...parse(url.search), ...data }, arrayFormat);
933
944
  }
934
945
  return [
935
946
  [
@@ -961,6 +972,18 @@ var isSameUrlWithoutQueryOrHash = (url1, url2) => {
961
972
  function isUrlMethodPair(href) {
962
973
  return href !== null && typeof href === "object" && href !== void 0 && "url" in href && "method" in href;
963
974
  }
975
+ function resolveUrlMethodPairComponent(pair) {
976
+ if (!pair.component) {
977
+ return null;
978
+ }
979
+ if (Array.isArray(pair.component)) {
980
+ console.error(
981
+ `The "component" property on the URL method pair received an array of components (${pair.component.join(", ")}), but only a single component string is supported for instant visits. Pass an explicit component name instead.`
982
+ );
983
+ return null;
984
+ }
985
+ return pair.component;
986
+ }
964
987
  function urlHasProtocol(url) {
965
988
  return /^([a-z][a-z0-9+.-]*:)?\/\/[^/]/i.test(url);
966
989
  }
@@ -1015,7 +1038,7 @@ var CurrentPage = class {
1015
1038
  if (page2.clearHistory) {
1016
1039
  history.clear();
1017
1040
  }
1018
- return this.resolve(page2.component).then((component) => {
1041
+ return this.resolve(page2.component, page2).then((component) => {
1019
1042
  if (componentId !== this.componentId) {
1020
1043
  return;
1021
1044
  }
@@ -1025,6 +1048,7 @@ var CurrentPage = class {
1025
1048
  const scrollRegions = !isServer3 && preserveScroll ? Scroll.getScrollRegions() : [];
1026
1049
  replace = replace || isSameUrlWithoutHash(hrefToUrl(page2.url), location);
1027
1050
  const pageForHistory = { ...page2, flash: {} };
1051
+ delete pageForHistory.optimisticUpdatedAt;
1028
1052
  return new Promise(
1029
1053
  (resolve) => replace ? history.replaceState(pageForHistory, resolve) : history.pushState(pageForHistory, resolve)
1030
1054
  ).then(() => {
@@ -1073,7 +1097,7 @@ var CurrentPage = class {
1073
1097
  setQuietly(page2, {
1074
1098
  preserveState = false
1075
1099
  } = {}) {
1076
- return this.resolve(page2.component).then((component) => {
1100
+ return this.resolve(page2.component, page2).then((component) => {
1077
1101
  this.page = page2;
1078
1102
  this.cleared = false;
1079
1103
  history.setCurrent(page2);
@@ -1098,6 +1122,12 @@ var CurrentPage = class {
1098
1122
  merge(data) {
1099
1123
  this.page = { ...this.page, ...data };
1100
1124
  }
1125
+ setPropsQuietly(props) {
1126
+ this.page = { ...this.page, props };
1127
+ return this.resolve(this.page.component, this.page).then((component) => {
1128
+ return this.swap({ component, page: this.page, preserveState: true, viewTransition: false });
1129
+ });
1130
+ }
1101
1131
  setFlash(flash) {
1102
1132
  this.page = { ...this.page, flash };
1103
1133
  this.onFlashCallback?.(flash);
@@ -1126,8 +1156,22 @@ var CurrentPage = class {
1126
1156
  viewTransitionCallback(transitionResult);
1127
1157
  });
1128
1158
  }
1129
- resolve(component) {
1130
- return Promise.resolve(this.resolveComponent(component));
1159
+ resolve(component, page2) {
1160
+ return Promise.resolve(this.resolveComponent(component, page2));
1161
+ }
1162
+ recordOptimisticUpdate(keys, updatedAt) {
1163
+ if (!this.page.optimisticUpdatedAt) {
1164
+ this.page.optimisticUpdatedAt = {};
1165
+ }
1166
+ for (const key of keys) {
1167
+ if (updatedAt > (this.page.optimisticUpdatedAt[key] || 0)) {
1168
+ this.page.optimisticUpdatedAt[key] = updatedAt;
1169
+ }
1170
+ }
1171
+ }
1172
+ shouldPreserveOptimistic(key, updatedAt) {
1173
+ const lastUpdatedAt = this.page.optimisticUpdatedAt?.[key];
1174
+ return lastUpdatedAt !== void 0 && updatedAt < lastUpdatedAt;
1131
1175
  }
1132
1176
  isTheSame(page2) {
1133
1177
  return this.page.component === page2.component;
@@ -1147,8 +1191,8 @@ var CurrentPage = class {
1147
1191
  if (existingOnceProp === void 0) {
1148
1192
  return;
1149
1193
  }
1150
- if (force || response.props[onceProp.prop] === void 0) {
1151
- response.props[onceProp.prop] = this.page.props[existingOnceProp.prop];
1194
+ if (force || get3(response.props, onceProp.prop) === void 0) {
1195
+ set3(response.props, onceProp.prop, get3(this.page.props, existingOnceProp.prop));
1152
1196
  response.onceProps[key].expiresAt = existingOnceProp.expiresAt;
1153
1197
  }
1154
1198
  });
@@ -1236,7 +1280,7 @@ var History = class {
1236
1280
  } catch {
1237
1281
  return {
1238
1282
  ...page2,
1239
- props: (0, import_lodash_es3.cloneDeep)(page2.props)
1283
+ props: cloneDeep2(page2.props)
1240
1284
  };
1241
1285
  }
1242
1286
  }
@@ -1275,7 +1319,7 @@ var History = class {
1275
1319
  if (!window.history.state?.page) {
1276
1320
  return;
1277
1321
  }
1278
- if ((0, import_lodash_es3.isEqual)(this.getScrollRegions(), scrollRegions)) {
1322
+ if (isEqual(this.getScrollRegions(), scrollRegions)) {
1279
1323
  return;
1280
1324
  }
1281
1325
  return this.doReplaceState({
@@ -1291,7 +1335,7 @@ var History = class {
1291
1335
  if (!window.history.state?.page) {
1292
1336
  return;
1293
1337
  }
1294
- if ((0, import_lodash_es3.isEqual)(this.getDocumentScrollPosition(), scrollRegion)) {
1338
+ if (isEqual(this.getDocumentScrollPosition(), scrollRegion)) {
1295
1339
  return;
1296
1340
  }
1297
1341
  return this.doReplaceState({
@@ -1308,7 +1352,7 @@ var History = class {
1308
1352
  return window.history.state?.documentScrollPosition || { top: 0, left: 0 };
1309
1353
  }
1310
1354
  replaceState(page2, cb = null) {
1311
- if ((0, import_lodash_es3.isEqual)(this.current, page2)) {
1355
+ if (isEqual(this.current, page2)) {
1312
1356
  cb && cb();
1313
1357
  return;
1314
1358
  }
@@ -1486,7 +1530,7 @@ var EventHandler = class {
1486
1530
  const pendingDeferred = {};
1487
1531
  const pageProps = page.get().props;
1488
1532
  for (const [group, props] of Object.entries(data.initialDeferredProps ?? data.deferredProps ?? {})) {
1489
- const missing = props.filter((prop) => pageProps[prop] === void 0);
1533
+ const missing = props.filter((prop) => get4(pageProps, prop) === void 0);
1490
1534
  if (missing.length > 0) {
1491
1535
  pendingDeferred[group] = missing;
1492
1536
  }
@@ -1511,10 +1555,8 @@ var NavigationType = class {
1511
1555
  if (typeof window === "undefined") {
1512
1556
  return "navigate";
1513
1557
  }
1514
- if (window.performance && window.performance.getEntriesByType && window.performance.getEntriesByType("navigation").length > 0) {
1515
- return window.performance.getEntriesByType("navigation")[0].type;
1516
- }
1517
- return "navigate";
1558
+ const entry = window.performance?.getEntriesByType("navigation")[0];
1559
+ return entry?.type ?? "navigate";
1518
1560
  }
1519
1561
  get() {
1520
1562
  return this.type;
@@ -1639,8 +1681,8 @@ var Poll = class {
1639
1681
  }
1640
1682
  }, this.interval);
1641
1683
  }
1642
- isInBackground(hidden) {
1643
- this.throttle = this.keepAlive ? false : hidden;
1684
+ isInBackground(hidden2) {
1685
+ this.throttle = this.keepAlive ? false : hidden2;
1644
1686
  if (this.throttle) {
1645
1687
  this.cbCount = 0;
1646
1688
  }
@@ -1681,7 +1723,245 @@ var Polls = class {
1681
1723
  var polls = new Polls();
1682
1724
 
1683
1725
  // src/request.ts
1684
- var import_axios = __toESM(require("axios"), 1);
1726
+ import { get as get6 } from "lodash-es";
1727
+
1728
+ // src/http.ts
1729
+ import { client as precognitionClient } from "laravel-precognition";
1730
+
1731
+ // src/httpHandlers.ts
1732
+ var HttpHandlers = class {
1733
+ constructor() {
1734
+ this.requestHandlers = [];
1735
+ this.responseHandlers = [];
1736
+ this.errorHandlers = [];
1737
+ }
1738
+ onRequest(handler) {
1739
+ this.requestHandlers.push(handler);
1740
+ return () => {
1741
+ this.requestHandlers = this.requestHandlers.filter((h) => h !== handler);
1742
+ };
1743
+ }
1744
+ onResponse(handler) {
1745
+ this.responseHandlers.push(handler);
1746
+ return () => {
1747
+ this.responseHandlers = this.responseHandlers.filter((h) => h !== handler);
1748
+ };
1749
+ }
1750
+ onError(handler) {
1751
+ this.errorHandlers.push(handler);
1752
+ return () => {
1753
+ this.errorHandlers = this.errorHandlers.filter((h) => h !== handler);
1754
+ };
1755
+ }
1756
+ async processRequest(config2) {
1757
+ let result = config2;
1758
+ for (const handler of this.requestHandlers) {
1759
+ result = await handler(result);
1760
+ }
1761
+ return result;
1762
+ }
1763
+ async processResponse(response) {
1764
+ let result = response;
1765
+ for (const handler of this.responseHandlers) {
1766
+ result = await handler(result);
1767
+ }
1768
+ return result;
1769
+ }
1770
+ async processError(error) {
1771
+ for (const handler of this.errorHandlers) {
1772
+ await handler(error);
1773
+ }
1774
+ }
1775
+ };
1776
+ var httpHandlers = new HttpHandlers();
1777
+
1778
+ // src/httpErrors.ts
1779
+ var HttpResponseError = class extends Error {
1780
+ constructor(message, response, url) {
1781
+ super(url ? `${message} (${url})` : message);
1782
+ this.name = "HttpResponseError";
1783
+ this.response = response;
1784
+ this.url = url;
1785
+ }
1786
+ };
1787
+ var HttpCancelledError = class extends Error {
1788
+ constructor(message = "Request was cancelled", url) {
1789
+ super(url ? `${message} (${url})` : message);
1790
+ this.name = "HttpCancelledError";
1791
+ this.url = url;
1792
+ }
1793
+ };
1794
+ var HttpNetworkError = class extends Error {
1795
+ constructor(message, url, cause) {
1796
+ super(url ? `${message} (${url})` : message);
1797
+ this.code = "ERR_NETWORK";
1798
+ this.name = "HttpNetworkError";
1799
+ this.url = url;
1800
+ this.cause = cause;
1801
+ }
1802
+ };
1803
+
1804
+ // src/xhrHttpClient.ts
1805
+ function getCookie(name) {
1806
+ const match = document.cookie.match(new RegExp("(^|;\\s*)(" + name + ")=([^;]*)"));
1807
+ return match ? decodeURIComponent(match[3]) : null;
1808
+ }
1809
+ function parseHeaders(xhr) {
1810
+ const headers = {};
1811
+ xhr.getAllResponseHeaders().split("\r\n").forEach((line) => {
1812
+ const index = line.indexOf(":");
1813
+ if (index > 0) {
1814
+ headers[line.slice(0, index).toLowerCase().trim()] = line.slice(index + 1).trim();
1815
+ }
1816
+ });
1817
+ return headers;
1818
+ }
1819
+ function setHeaders(xhr, config2) {
1820
+ if (!config2.headers) {
1821
+ return;
1822
+ }
1823
+ const isFormData2 = config2.data instanceof FormData;
1824
+ Object.entries(config2.headers).forEach(([key, value]) => {
1825
+ if (key.toLowerCase() !== "content-type" || !isFormData2) {
1826
+ xhr.setRequestHeader(key, String(value));
1827
+ }
1828
+ });
1829
+ }
1830
+ function buildUrlWithParams(url, params) {
1831
+ if (!params || Object.keys(params).length === 0) {
1832
+ return url;
1833
+ }
1834
+ const [urlWithParams] = mergeDataIntoQueryString("get", url, params);
1835
+ return urlWithParams;
1836
+ }
1837
+ var XhrHttpClient = class {
1838
+ constructor(options = {}) {
1839
+ this.xsrfCookieName = options.xsrfCookieName ?? "XSRF-TOKEN";
1840
+ this.xsrfHeaderName = options.xsrfHeaderName ?? "X-XSRF-TOKEN";
1841
+ }
1842
+ async request(config2) {
1843
+ const processedConfig = await httpHandlers.processRequest(config2);
1844
+ try {
1845
+ const response = await this.doRequest(processedConfig);
1846
+ return await httpHandlers.processResponse(response);
1847
+ } catch (error) {
1848
+ if (error instanceof HttpResponseError || error instanceof HttpNetworkError || error instanceof HttpCancelledError) {
1849
+ await httpHandlers.processError(error);
1850
+ }
1851
+ throw error;
1852
+ }
1853
+ }
1854
+ doRequest(config2) {
1855
+ return new Promise((resolve, reject) => {
1856
+ const xhr = new XMLHttpRequest();
1857
+ const url = buildUrlWithParams(config2.url, config2.params);
1858
+ xhr.open(config2.method.toUpperCase(), url, true);
1859
+ const xsrfToken = getCookie(this.xsrfCookieName);
1860
+ if (xsrfToken) {
1861
+ xhr.setRequestHeader(this.xsrfHeaderName, xsrfToken);
1862
+ }
1863
+ let body = null;
1864
+ if (config2.data !== null && config2.data !== void 0) {
1865
+ if (config2.data instanceof FormData) {
1866
+ body = config2.data;
1867
+ } else if (typeof config2.data === "object") {
1868
+ body = JSON.stringify(config2.data);
1869
+ if (!config2.headers?.["Content-Type"] && !config2.headers?.["content-type"]) {
1870
+ xhr.setRequestHeader("Content-Type", "application/json");
1871
+ }
1872
+ } else {
1873
+ body = String(config2.data);
1874
+ }
1875
+ }
1876
+ setHeaders(xhr, config2);
1877
+ if (config2.onUploadProgress) {
1878
+ xhr.upload.onprogress = (event) => {
1879
+ config2.onUploadProgress({
1880
+ progress: event.lengthComputable ? event.loaded / event.total : void 0,
1881
+ loaded: event.loaded,
1882
+ total: event.lengthComputable ? event.total : void 0
1883
+ });
1884
+ };
1885
+ }
1886
+ if (config2.signal) {
1887
+ config2.signal.addEventListener("abort", () => xhr.abort());
1888
+ }
1889
+ xhr.onabort = () => reject(new HttpCancelledError("Request was cancelled", config2.url));
1890
+ xhr.onerror = () => reject(new HttpNetworkError("Network error", config2.url));
1891
+ xhr.onload = () => {
1892
+ const response = {
1893
+ status: xhr.status,
1894
+ data: xhr.responseText,
1895
+ headers: parseHeaders(xhr)
1896
+ };
1897
+ if (xhr.status >= 400) {
1898
+ reject(new HttpResponseError(`Request failed with status ${xhr.status}`, response, config2.url));
1899
+ } else {
1900
+ resolve(response);
1901
+ }
1902
+ };
1903
+ xhr.send(body);
1904
+ });
1905
+ }
1906
+ };
1907
+ var xhrHttpClient = new XhrHttpClient();
1908
+
1909
+ // src/http.ts
1910
+ var httpClient = xhrHttpClient;
1911
+ function isHttpClientOptions(client) {
1912
+ return !("request" in client);
1913
+ }
1914
+ var http = {
1915
+ /**
1916
+ * Get the current HTTP client
1917
+ */
1918
+ getClient() {
1919
+ return httpClient;
1920
+ },
1921
+ /**
1922
+ * Set the HTTP client to use for all Inertia requests
1923
+ */
1924
+ setClient(clientOrOptions) {
1925
+ if (!isHttpClientOptions(clientOrOptions)) {
1926
+ httpClient = clientOrOptions;
1927
+ return;
1928
+ }
1929
+ httpClient = new XhrHttpClient(clientOrOptions);
1930
+ if (clientOrOptions.xsrfCookieName) {
1931
+ precognitionClient.withXsrfCookieName(clientOrOptions.xsrfCookieName);
1932
+ }
1933
+ if (clientOrOptions.xsrfHeaderName) {
1934
+ precognitionClient.withXsrfHeaderName(clientOrOptions.xsrfHeaderName);
1935
+ }
1936
+ },
1937
+ /**
1938
+ * Register a request handler that runs before each request
1939
+ */
1940
+ onRequest: httpHandlers.onRequest.bind(httpHandlers),
1941
+ /**
1942
+ * Register a response handler that runs after each successful response
1943
+ */
1944
+ onResponse: httpHandlers.onResponse.bind(httpHandlers),
1945
+ /**
1946
+ * Register an error handler that runs when a request fails
1947
+ */
1948
+ onError: httpHandlers.onError.bind(httpHandlers),
1949
+ /**
1950
+ * Process a request config through all registered request handlers.
1951
+ * For use by custom HttpClient implementations.
1952
+ */
1953
+ processRequest: httpHandlers.processRequest.bind(httpHandlers),
1954
+ /**
1955
+ * Process a response through all registered response handlers.
1956
+ * For use by custom HttpClient implementations.
1957
+ */
1958
+ processResponse: httpHandlers.processResponse.bind(httpHandlers),
1959
+ /**
1960
+ * Process an error through all registered error handlers.
1961
+ * For use by custom HttpClient implementations.
1962
+ */
1963
+ processError: httpHandlers.processError.bind(httpHandlers)
1964
+ };
1685
1965
 
1686
1966
  // src/requestParams.ts
1687
1967
  var RequestParams = class _RequestParams {
@@ -1699,6 +1979,8 @@ var RequestParams = class _RequestParams {
1699
1979
  onCancel: this.wrapCallback(params, "onCancel"),
1700
1980
  onSuccess: this.wrapCallback(params, "onSuccess"),
1701
1981
  onError: this.wrapCallback(params, "onError"),
1982
+ onHttpException: this.wrapCallback(params, "onHttpException"),
1983
+ onNetworkError: this.wrapCallback(params, "onNetworkError"),
1702
1984
  onFlash: this.wrapCallback(params, "onFlash"),
1703
1985
  onCancelToken: this.wrapCallback(params, "onCancelToken"),
1704
1986
  onPrefetched: this.wrapCallback(params, "onPrefetched"),
@@ -1831,12 +2113,10 @@ var RequestParams = class _RequestParams {
1831
2113
  };
1832
2114
 
1833
2115
  // src/response.ts
1834
- var import_lodash_es4 = require("lodash-es");
2116
+ import { get as get5, isEqual as isEqual2, set as set4 } from "lodash-es";
1835
2117
 
1836
- // src/modal.ts
1837
- var modal_default = {
1838
- modal: null,
1839
- listener: null,
2118
+ // src/dialog.ts
2119
+ var dialog_default = {
1840
2120
  createIframeAndPage(html) {
1841
2121
  if (typeof html === "object") {
1842
2122
  html = `All Inertia requests must receive a valid Inertia response, however a plain JSON response was received.<hr>${JSON.stringify(
@@ -1855,44 +2135,6 @@ var modal_default = {
1855
2135
  },
1856
2136
  show(html) {
1857
2137
  const { iframe, page: page2 } = this.createIframeAndPage(html);
1858
- this.modal = document.createElement("div");
1859
- this.modal.style.position = "fixed";
1860
- this.modal.style.width = "100vw";
1861
- this.modal.style.height = "100vh";
1862
- this.modal.style.padding = "50px";
1863
- this.modal.style.boxSizing = "border-box";
1864
- this.modal.style.backgroundColor = "rgba(0, 0, 0, .6)";
1865
- this.modal.style.zIndex = 2e5;
1866
- this.modal.addEventListener("click", () => this.hide());
1867
- this.modal.appendChild(iframe);
1868
- document.body.prepend(this.modal);
1869
- document.body.style.overflow = "hidden";
1870
- if (!iframe.contentWindow) {
1871
- throw new Error("iframe not yet ready.");
1872
- }
1873
- iframe.contentWindow.document.open();
1874
- iframe.contentWindow.document.write(page2.outerHTML);
1875
- iframe.contentWindow.document.close();
1876
- this.listener = this.hideOnEscape.bind(this);
1877
- document.addEventListener("keydown", this.listener);
1878
- },
1879
- hide() {
1880
- this.modal.outerHTML = "";
1881
- this.modal = null;
1882
- document.body.style.overflow = "visible";
1883
- document.removeEventListener("keydown", this.listener);
1884
- },
1885
- hideOnEscape(event) {
1886
- if (event.keyCode === 27) {
1887
- this.hide();
1888
- }
1889
- }
1890
- };
1891
-
1892
- // src/dialog.ts
1893
- var dialog_default = {
1894
- show(html) {
1895
- const { iframe, page: page2 } = modal_default.createIframeAndPage(html);
1896
2138
  iframe.style.boxSizing = "border-box";
1897
2139
  iframe.style.display = "block";
1898
2140
  const dialog = document.createElement("dialog");
@@ -1946,10 +2188,14 @@ var Response = class _Response {
1946
2188
  this.response = response;
1947
2189
  this.originatingPage = originatingPage;
1948
2190
  this.wasPrefetched = false;
2191
+ this.processed = false;
1949
2192
  }
1950
2193
  static create(params, response, originatingPage) {
1951
2194
  return new _Response(params, response, originatingPage);
1952
2195
  }
2196
+ isProcessed() {
2197
+ return this.processed;
2198
+ }
1953
2199
  async handlePrefetch() {
1954
2200
  if (isSameUrlWithoutHash(this.requestParams.all().url, window.location)) {
1955
2201
  this.handle();
@@ -1967,9 +2213,22 @@ var Response = class _Response {
1967
2213
  return Promise.resolve();
1968
2214
  }
1969
2215
  this.requestParams.runCallbacks();
2216
+ this.processed = true;
1970
2217
  if (!this.isInertiaResponse()) {
1971
2218
  return this.handleNonInertiaResponse();
1972
2219
  }
2220
+ if (this.isHttpException()) {
2221
+ const response = {
2222
+ ...this.response,
2223
+ data: this.getDataFromResponse(this.response.data)
2224
+ };
2225
+ if (this.requestParams.all().onHttpException(response) === false) {
2226
+ return;
2227
+ }
2228
+ if (!fireHttpExceptionEvent(response)) {
2229
+ return;
2230
+ }
2231
+ }
1973
2232
  await history.processQueue();
1974
2233
  history.preserveUrl = this.requestParams.all().preserveUrl;
1975
2234
  const previousFlash = page.get().flash;
@@ -1985,7 +2244,7 @@ var Response = class _Response {
1985
2244
  router.flush(page.get().url);
1986
2245
  }
1987
2246
  const { flash } = page.get();
1988
- if (Object.keys(flash).length > 0 && (!this.requestParams.isPartial() || !(0, import_lodash_es4.isEqual)(flash, previousFlash))) {
2247
+ if (Object.keys(flash).length > 0 && (!this.requestParams.isPartial() || !isEqual2(flash, previousFlash))) {
1989
2248
  fireFlashEvent(flash);
1990
2249
  this.requestParams.all().onFlash(flash);
1991
2250
  }
@@ -2004,6 +2263,14 @@ var Response = class _Response {
2004
2263
  return this.response.data = data;
2005
2264
  }
2006
2265
  async handleNonInertiaResponse() {
2266
+ if (this.isInertiaRedirect()) {
2267
+ router.visit(this.getHeader("x-inertia-redirect"), {
2268
+ ...this.requestParams.all(),
2269
+ method: "get",
2270
+ data: {}
2271
+ });
2272
+ return;
2273
+ }
2007
2274
  if (this.isLocationVisit()) {
2008
2275
  const locationUrl = hrefToUrl(this.getHeader("x-inertia-location"));
2009
2276
  setHashIfSameUrl(this.requestParams.all().url, locationUrl);
@@ -2013,13 +2280,19 @@ var Response = class _Response {
2013
2280
  ...this.response,
2014
2281
  data: this.getDataFromResponse(this.response.data)
2015
2282
  };
2016
- if (fireInvalidEvent(response)) {
2017
- return config.get("future.useDialogForErrorModal") ? dialog_default.show(response.data) : modal_default.show(response.data);
2283
+ if (this.requestParams.all().onHttpException(response) === false) {
2284
+ return;
2285
+ }
2286
+ if (fireHttpExceptionEvent(response)) {
2287
+ return dialog_default.show(response.data);
2018
2288
  }
2019
2289
  }
2020
2290
  isInertiaResponse() {
2021
2291
  return this.hasHeader("x-inertia");
2022
2292
  }
2293
+ isHttpException() {
2294
+ return this.response.status >= 400;
2295
+ }
2023
2296
  hasStatus(status2) {
2024
2297
  return this.response.status === status2;
2025
2298
  }
@@ -2029,6 +2302,9 @@ var Response = class _Response {
2029
2302
  hasHeader(header) {
2030
2303
  return this.getHeader(header) !== void 0;
2031
2304
  }
2305
+ isInertiaRedirect() {
2306
+ return this.hasStatus(409) && this.hasHeader("x-inertia-redirect");
2307
+ }
2032
2308
  isLocationVisit() {
2033
2309
  return this.hasStatus(409) && this.hasHeader("x-inertia-location");
2034
2310
  }
@@ -2059,6 +2335,7 @@ var Response = class _Response {
2059
2335
  }
2060
2336
  this.mergeProps(pageResponse);
2061
2337
  page.mergeOncePropsIntoResponse(pageResponse);
2338
+ this.preserveOptimisticProps(pageResponse);
2062
2339
  this.preserveEqualProps(pageResponse);
2063
2340
  await this.setRememberedState(pageResponse);
2064
2341
  this.requestParams.setPreserveOptions(pageResponse);
@@ -2098,16 +2375,32 @@ var Response = class _Response {
2098
2375
  }
2099
2376
  pageUrl(pageResponse) {
2100
2377
  const responseUrl = hrefToUrl(pageResponse.url);
2101
- setHashIfSameUrl(this.requestParams.all().url, responseUrl);
2378
+ if (pageResponse.preserveFragment) {
2379
+ responseUrl.hash = this.requestParams.all().url.hash;
2380
+ } else {
2381
+ setHashIfSameUrl(this.requestParams.all().url, responseUrl);
2382
+ }
2102
2383
  return responseUrl.pathname + responseUrl.search + responseUrl.hash;
2103
2384
  }
2385
+ preserveOptimisticProps(pageResponse) {
2386
+ const optimisticUpdatedAt = page.get().optimisticUpdatedAt;
2387
+ if (!optimisticUpdatedAt || !router.hasPendingOptimistic()) {
2388
+ return;
2389
+ }
2390
+ for (const key of Object.keys(pageResponse.props)) {
2391
+ if (key in optimisticUpdatedAt) {
2392
+ pageResponse.props[key] = page.get().props[key];
2393
+ }
2394
+ }
2395
+ pageResponse.optimisticUpdatedAt = { ...optimisticUpdatedAt };
2396
+ }
2104
2397
  preserveEqualProps(pageResponse) {
2105
- if (pageResponse.component !== page.get().component || config.get("future.preserveEqualProps") !== true) {
2398
+ if (pageResponse.component !== page.get().component) {
2106
2399
  return;
2107
2400
  }
2108
2401
  const currentPageProps = page.get().props;
2109
2402
  Object.entries(pageResponse.props).forEach(([key, value]) => {
2110
- if ((0, import_lodash_es4.isEqual)(value, currentPageProps[key])) {
2403
+ if (isEqual2(value, currentPageProps[key])) {
2111
2404
  pageResponse.props[key] = currentPageProps[key];
2112
2405
  }
2113
2406
  });
@@ -2121,8 +2414,8 @@ var Response = class _Response {
2121
2414
  const propsToDeepMerge = pageResponse.deepMergeProps || [];
2122
2415
  const matchPropsOn = pageResponse.matchPropsOn || [];
2123
2416
  const mergeProp = (prop, shouldAppend) => {
2124
- const currentProp = (0, import_lodash_es4.get)(page.get().props, prop);
2125
- const incomingProp = (0, import_lodash_es4.get)(pageResponse.props, prop);
2417
+ const currentProp = get5(page.get().props, prop);
2418
+ const incomingProp = get5(pageResponse.props, prop);
2126
2419
  if (Array.isArray(incomingProp)) {
2127
2420
  const newArray = this.mergeOrMatchItems(
2128
2421
  currentProp || [],
@@ -2131,20 +2424,20 @@ var Response = class _Response {
2131
2424
  matchPropsOn,
2132
2425
  shouldAppend
2133
2426
  );
2134
- (0, import_lodash_es4.set)(pageResponse.props, prop, newArray);
2427
+ set4(pageResponse.props, prop, newArray);
2135
2428
  } else if (typeof incomingProp === "object" && incomingProp !== null) {
2136
2429
  const newObject = {
2137
2430
  ...currentProp || {},
2138
2431
  ...incomingProp
2139
2432
  };
2140
- (0, import_lodash_es4.set)(pageResponse.props, prop, newObject);
2433
+ set4(pageResponse.props, prop, newObject);
2141
2434
  }
2142
2435
  };
2143
2436
  propsToAppend.forEach((prop) => mergeProp(prop, true));
2144
2437
  propsToPrepend.forEach((prop) => mergeProp(prop, false));
2145
2438
  propsToDeepMerge.forEach((prop) => {
2146
- const currentProp = page.get().props[prop];
2147
- const incomingProp = pageResponse.props[prop];
2439
+ const currentProp = get5(page.get().props, prop);
2440
+ const incomingProp = get5(pageResponse.props, prop);
2148
2441
  const deepMerge = (target, source, matchProp) => {
2149
2442
  if (Array.isArray(source)) {
2150
2443
  return this.mergeOrMatchItems(target, source, matchProp, matchPropsOn);
@@ -2160,15 +2453,21 @@ var Response = class _Response {
2160
2453
  }
2161
2454
  return source;
2162
2455
  };
2163
- pageResponse.props[prop] = deepMerge(currentProp, incomingProp, prop);
2456
+ set4(pageResponse.props, prop, deepMerge(currentProp, incomingProp, prop));
2164
2457
  });
2165
- pageResponse.props = { ...page.get().props, ...pageResponse.props };
2166
- if (this.requestParams.isDeferredPropsRequest()) {
2167
- const currentErrors = page.get().props.errors;
2168
- if (currentErrors && Object.keys(currentErrors).length > 0) {
2169
- pageResponse.props.errors = currentErrors;
2458
+ const nestedTopKeys = new Set(
2459
+ [...this.requestParams.all().only, ...this.requestParams.all().except].filter((prop) => prop.includes(".")).map((prop) => prop.split(".")[0])
2460
+ );
2461
+ for (const key of nestedTopKeys) {
2462
+ const currentValue = page.get().props[key];
2463
+ if (this.isObject(currentValue) && this.isObject(pageResponse.props[key])) {
2464
+ pageResponse.props[key] = this.deepMergeObjects(currentValue, pageResponse.props[key]);
2170
2465
  }
2171
2466
  }
2467
+ pageResponse.props = { ...page.get().props, ...pageResponse.props };
2468
+ if (this.shouldPreserveErrors(pageResponse)) {
2469
+ pageResponse.props.errors = page.get().props.errors;
2470
+ }
2172
2471
  if (page.get().scrollProps) {
2173
2472
  pageResponse.scrollProps = {
2174
2473
  ...page.get().scrollProps || {},
@@ -2190,6 +2489,42 @@ var Response = class _Response {
2190
2489
  pageResponse.initialDeferredProps = currentOriginalDeferred;
2191
2490
  }
2192
2491
  }
2492
+ /**
2493
+ * By default, the Laravel adapter shares validation errors via Inertia::always(),
2494
+ * so responses always include errors, even when empty. Components like
2495
+ * InfiniteScroll and WhenVisible, as well as loading deferred props,
2496
+ * perform async requests that should practically never reset errors.
2497
+ */
2498
+ shouldPreserveErrors(pageResponse) {
2499
+ if (!this.requestParams.all().preserveErrors) {
2500
+ return false;
2501
+ }
2502
+ const currentErrors = page.get().props.errors;
2503
+ if (!currentErrors || Object.keys(currentErrors).length === 0) {
2504
+ return false;
2505
+ }
2506
+ const responseErrors = pageResponse.props.errors;
2507
+ if (responseErrors && Object.keys(responseErrors).length > 0) {
2508
+ return false;
2509
+ }
2510
+ return true;
2511
+ }
2512
+ isObject(item) {
2513
+ return item && typeof item === "object" && !Array.isArray(item);
2514
+ }
2515
+ deepMergeObjects(target, source) {
2516
+ const result = { ...target };
2517
+ for (const key of Object.keys(source)) {
2518
+ const targetValue = target[key];
2519
+ const sourceValue = source[key];
2520
+ if (this.isObject(targetValue) && this.isObject(sourceValue)) {
2521
+ result[key] = this.deepMergeObjects(targetValue, sourceValue);
2522
+ } else {
2523
+ result[key] = sourceValue;
2524
+ }
2525
+ }
2526
+ return result;
2527
+ }
2193
2528
  mergeOrMatchItems(existingItems, newItems, matchProp, matchPropsOn, shouldAppend = true) {
2194
2529
  const items = Array.isArray(existingItems) ? existingItems : [];
2195
2530
  const matchingKey = matchPropsOn.find((key) => {
@@ -2253,18 +2588,25 @@ var Response = class _Response {
2253
2588
 
2254
2589
  // src/request.ts
2255
2590
  var Request = class _Request {
2256
- constructor(params, page2) {
2591
+ constructor(params, page2, { optimistic = false } = {}) {
2257
2592
  this.page = page2;
2258
2593
  this.requestHasFinished = false;
2259
2594
  this.requestParams = RequestParams.create(params);
2260
2595
  this.cancelToken = new AbortController();
2596
+ this.optimistic = optimistic;
2261
2597
  }
2262
- static create(params, page2) {
2263
- return new _Request(params, page2);
2598
+ static create(params, page2, options) {
2599
+ return new _Request(params, page2, options);
2264
2600
  }
2265
2601
  isPrefetch() {
2266
2602
  return this.requestParams.isPrefetch();
2267
2603
  }
2604
+ isOptimistic() {
2605
+ return this.optimistic;
2606
+ }
2607
+ isPendingOptimistic() {
2608
+ return this.isOptimistic() && (!this.response || !this.response.isProcessed());
2609
+ }
2268
2610
  async send() {
2269
2611
  this.requestParams.onCancelToken(() => this.cancel({ cancelled: true }));
2270
2612
  fireStartEvent(this.requestParams.all());
@@ -2274,31 +2616,30 @@ var Request = class _Request {
2274
2616
  firePrefetchingEvent(this.requestParams.all());
2275
2617
  }
2276
2618
  const originallyPrefetch = this.requestParams.all().prefetch;
2277
- return (0, import_axios.default)({
2619
+ return http.getClient().request({
2278
2620
  method: this.requestParams.all().method,
2279
2621
  url: urlWithoutHash(this.requestParams.all().url).href,
2280
2622
  data: this.requestParams.data(),
2281
- params: this.requestParams.queryParams(),
2282
2623
  signal: this.cancelToken.signal,
2283
2624
  headers: this.getHeaders(),
2284
- onUploadProgress: this.onProgress.bind(this),
2285
- // Why text? This allows us to delay JSON.parse until we're ready to use the response,
2286
- // helps with performance particularly on large responses + history encryption
2287
- responseType: "text"
2625
+ onUploadProgress: this.onProgress.bind(this)
2288
2626
  }).then((response) => {
2289
2627
  this.response = Response.create(this.requestParams, response, this.page);
2290
2628
  return this.response.handle();
2291
2629
  }).catch((error) => {
2292
- if (error?.response) {
2630
+ if (error instanceof HttpResponseError) {
2293
2631
  this.response = Response.create(this.requestParams, error.response, this.page);
2294
2632
  return this.response.handle();
2295
2633
  }
2296
2634
  return Promise.reject(error);
2297
2635
  }).catch((error) => {
2298
- if (import_axios.default.isCancel(error)) {
2636
+ if (error instanceof HttpCancelledError) {
2637
+ return;
2638
+ }
2639
+ if (this.requestParams.all().onNetworkError(error) === false) {
2299
2640
  return;
2300
2641
  }
2301
- if (fireExceptionEvent(error)) {
2642
+ if (fireNetworkErrorEvent(error)) {
2302
2643
  if (originallyPrefetch) {
2303
2644
  this.requestParams.onPrefetchError(error);
2304
2645
  }
@@ -2353,7 +2694,7 @@ var Request = class _Request {
2353
2694
  headers["X-Inertia-Version"] = page2.version;
2354
2695
  }
2355
2696
  const onceProps = Object.entries(page2.onceProps || {}).filter(([, onceProp]) => {
2356
- if (page2.props[onceProp.prop] === void 0) {
2697
+ if (get6(page2.props, onceProp.prop) === void 0) {
2357
2698
  return false;
2358
2699
  }
2359
2700
  return !onceProp.expiresAt || onceProp.expiresAt > Date.now();
@@ -2381,8 +2722,8 @@ var RequestStream = class {
2381
2722
  interruptInFlight() {
2382
2723
  this.cancel({ interrupted: true }, false);
2383
2724
  }
2384
- cancelInFlight({ prefetch = true } = {}) {
2385
- this.requests.filter((request) => prefetch || !request.isPrefetch()).forEach((request) => request.cancel({ cancelled: true }));
2725
+ cancelInFlight({ prefetch = true, optimistic = true } = {}) {
2726
+ this.requests.filter((request) => prefetch || !request.isPrefetch()).filter((request) => optimistic || !request.isOptimistic()).forEach((request) => request.cancel({ cancelled: true }));
2386
2727
  }
2387
2728
  cancel({ cancelled = false, interrupted = false } = {}, force = false) {
2388
2729
  if (!force && !this.shouldCancel()) {
@@ -2394,9 +2735,14 @@ var RequestStream = class {
2394
2735
  shouldCancel() {
2395
2736
  return this.interruptible && this.requests.length >= this.maxConcurrent;
2396
2737
  }
2738
+ hasPendingOptimistic() {
2739
+ return this.requests.some((request) => request.isPendingOptimistic());
2740
+ }
2397
2741
  };
2398
2742
 
2399
2743
  // src/router.ts
2744
+ var noop = () => {
2745
+ };
2400
2746
  var Router = class {
2401
2747
  constructor() {
2402
2748
  this.syncRequestStream = new RequestStream({
@@ -2408,6 +2754,7 @@ var Router = class {
2408
2754
  interruptible: false
2409
2755
  });
2410
2756
  this.clientVisitQueue = new Queue();
2757
+ this.pendingOptimisticCallback = void 0;
2411
2758
  }
2412
2759
  init({
2413
2760
  initialPage,
@@ -2435,6 +2782,10 @@ var Router = class {
2435
2782
  window.location.href = url;
2436
2783
  });
2437
2784
  }
2785
+ optimistic(callback) {
2786
+ this.pendingOptimisticCallback = callback;
2787
+ return this;
2788
+ }
2438
2789
  get(url, data = {}, options = {}) {
2439
2790
  return this.visit(url, { ...options, method: "get", data });
2440
2791
  }
@@ -2487,6 +2838,9 @@ var Router = class {
2487
2838
  cancel() {
2488
2839
  this.syncRequestStream.cancelInFlight();
2489
2840
  }
2841
+ hasPendingOptimistic() {
2842
+ return this.asyncRequestStream.hasPendingOptimistic();
2843
+ }
2490
2844
  cancelAll({ async = true, prefetch = true, sync = true } = {}) {
2491
2845
  if (async) {
2492
2846
  this.asyncRequestStream.cancelInFlight({ prefetch });
@@ -2496,15 +2850,20 @@ var Router = class {
2496
2850
  }
2497
2851
  }
2498
2852
  poll(interval, requestOptions = {}, options = {}) {
2499
- return polls.add(interval, () => this.reload(requestOptions), {
2853
+ return polls.add(interval, () => this.reload({ preserveErrors: true, ...requestOptions }), {
2500
2854
  autoStart: options.autoStart ?? true,
2501
2855
  keepAlive: options.keepAlive ?? false
2502
2856
  });
2503
2857
  }
2504
2858
  visit(href, options = {}) {
2859
+ options.optimistic = options.optimistic ?? this.pendingOptimisticCallback;
2860
+ this.pendingOptimisticCallback = void 0;
2861
+ if (options.optimistic) {
2862
+ options.async = options.async ?? true;
2863
+ }
2505
2864
  const visit = this.getPendingVisit(href, {
2506
2865
  ...options,
2507
- showProgress: options.showProgress ?? !options.async
2866
+ showProgress: options.showProgress ?? (!options.async || !!options.optimistic)
2508
2867
  });
2509
2868
  const events = this.getVisitEvents(options);
2510
2869
  if (events.onBefore(visit) === false || !fireBeforeEvent(visit)) {
@@ -2514,11 +2873,14 @@ var Router = class {
2514
2873
  const isPartialReload = visit.only.length > 0 || visit.except.length > 0 || visit.reset.length > 0;
2515
2874
  const isSamePage = isPartialReload ? isSameUrlWithoutQueryOrHash(visit.url, currentPageUrl) : isSameUrlWithoutHash(visit.url, currentPageUrl);
2516
2875
  if (!isSamePage) {
2517
- this.asyncRequestStream.cancelInFlight({ prefetch: false });
2876
+ this.asyncRequestStream.cancelInFlight({ prefetch: false, optimistic: false });
2518
2877
  }
2519
2878
  if (!visit.async) {
2520
2879
  this.syncRequestStream.interruptInFlight();
2521
2880
  }
2881
+ if (options.optimistic) {
2882
+ this.applyOptimisticUpdate(options.optimistic, events);
2883
+ }
2522
2884
  if (!page.isCleared() && !visit.preserveUrl) {
2523
2885
  Scroll.save();
2524
2886
  }
@@ -2526,14 +2888,34 @@ var Router = class {
2526
2888
  ...visit,
2527
2889
  ...events
2528
2890
  };
2529
- const prefetched = prefetchedRequests.get(requestParams);
2530
- if (prefetched) {
2531
- progress.reveal(prefetched.inFlight);
2532
- prefetchedRequests.use(prefetched, requestParams);
2891
+ const sendRequest = () => {
2892
+ const prefetched = prefetchedRequests.get(requestParams);
2893
+ if (prefetched) {
2894
+ progress.reveal(prefetched.inFlight);
2895
+ prefetchedRequests.use(prefetched, requestParams);
2896
+ } else {
2897
+ progress.reveal(true);
2898
+ const requestStream = visit.async ? this.asyncRequestStream : this.syncRequestStream;
2899
+ requestStream.send(Request.create(requestParams, page.get(), { optimistic: !!options.optimistic }));
2900
+ }
2901
+ };
2902
+ if (Array.isArray(visit.component)) {
2903
+ console.error(
2904
+ `The "component" prop received an array of components (${visit.component.join(", ")}), but only a single component string is supported for instant visits. Pass an explicit component name instead.`
2905
+ );
2906
+ visit.component = null;
2907
+ }
2908
+ if (visit.component) {
2909
+ history.processQueue().then(() => {
2910
+ this.performInstantSwap(visit).then(() => {
2911
+ requestParams.preserveState = true;
2912
+ requestParams.replace = true;
2913
+ requestParams.viewTransition = false;
2914
+ sendRequest();
2915
+ });
2916
+ });
2533
2917
  } else {
2534
- progress.reveal(true);
2535
- const requestStream = visit.async ? this.asyncRequestStream : this.syncRequestStream;
2536
- requestStream.send(Request.create(requestParams, page.get()));
2918
+ sendRequest();
2537
2919
  }
2538
2920
  }
2539
2921
  getCached(href, options = {}) {
@@ -2610,8 +2992,8 @@ var Router = class {
2610
2992
  decryptHistory() {
2611
2993
  return history.decrypt();
2612
2994
  }
2613
- resolveComponent(component) {
2614
- return page.resolve(component);
2995
+ resolveComponent(component, page2) {
2996
+ return page.resolve(component, page2);
2615
2997
  }
2616
2998
  replace(params) {
2617
2999
  this.clientVisit(params, { replace: true });
@@ -2621,8 +3003,8 @@ var Router = class {
2621
3003
  preserveScroll: true,
2622
3004
  preserveState: true,
2623
3005
  props(currentProps) {
2624
- const newValue = typeof value === "function" ? value((0, import_lodash_es5.get)(currentProps, name), currentProps) : value;
2625
- return (0, import_lodash_es5.set)((0, import_lodash_es5.cloneDeep)(currentProps), name, newValue);
3006
+ const newValue = typeof value === "function" ? value(get7(currentProps, name), currentProps) : value;
3007
+ return set5(cloneDeep3(currentProps), name, newValue);
2626
3008
  },
2627
3009
  ...options || {}
2628
3010
  });
@@ -2679,7 +3061,10 @@ var Router = class {
2679
3061
  performClientVisit(params, { replace = false } = {}) {
2680
3062
  const current = page.get();
2681
3063
  const onceProps = typeof params.props === "function" ? Object.fromEntries(
2682
- Object.values(current.onceProps ?? {}).map((onceProp) => [onceProp.prop, current.props[onceProp.prop]])
3064
+ Object.values(current.onceProps ?? {}).map((onceProp) => [
3065
+ onceProp.prop,
3066
+ get7(current.props, onceProp.prop)
3067
+ ])
2683
3068
  ) : {};
2684
3069
  const props = typeof params.props === "function" ? params.props(current.props, onceProps) : params.props ?? current.props;
2685
3070
  const flash = typeof params.flash === "function" ? params.flash(current.flash) : params.flash;
@@ -2712,6 +3097,34 @@ var Router = class {
2712
3097
  onError?.(scopedErrors);
2713
3098
  }).finally(() => onFinish?.(params));
2714
3099
  }
3100
+ performInstantSwap(visit) {
3101
+ const current = page.get();
3102
+ const sharedProps = Object.fromEntries(
3103
+ (current.sharedProps ?? []).filter((key) => key in current.props).map((key) => [key, current.props[key]])
3104
+ );
3105
+ const resolvedPageProps = typeof visit.pageProps === "function" ? visit.pageProps(cloneDeep3(current.props), cloneDeep3(sharedProps)) : visit.pageProps;
3106
+ const intermediateProps = resolvedPageProps !== null ? { ...resolvedPageProps } : { ...sharedProps };
3107
+ const intermediatePage = {
3108
+ component: visit.component,
3109
+ url: visit.url.pathname + visit.url.search + visit.url.hash,
3110
+ version: current.version,
3111
+ props: {
3112
+ ...intermediateProps,
3113
+ errors: {}
3114
+ },
3115
+ flash: {},
3116
+ clearHistory: false,
3117
+ encryptHistory: current.encryptHistory,
3118
+ sharedProps: current.sharedProps,
3119
+ rememberedState: {}
3120
+ };
3121
+ return page.set(intermediatePage, {
3122
+ replace: visit.replace,
3123
+ preserveScroll: RequestParams.resolvePreserveOption(visit.preserveScroll, intermediatePage),
3124
+ preserveState: false,
3125
+ viewTransition: visit.viewTransition
3126
+ });
3127
+ }
2715
3128
  getPrefetchParams(href, options) {
2716
3129
  return {
2717
3130
  ...this.getPendingVisit(href, {
@@ -2724,14 +3137,14 @@ var Router = class {
2724
3137
  ...this.getVisitEvents(options)
2725
3138
  };
2726
3139
  }
2727
- getPendingVisit(href, options, pendingVisitOptions = {}) {
3140
+ getPendingVisit(href, options) {
2728
3141
  if (isUrlMethodPair(href)) {
2729
3142
  const urlMethodPair = href;
2730
3143
  href = urlMethodPair.url;
2731
3144
  options.method = options.method ?? urlMethodPair.method;
2732
3145
  }
2733
3146
  const defaultVisitOptionsCallback = config.get("visitOptions");
2734
- const configuredOptions = defaultVisitOptionsCallback ? defaultVisitOptionsCallback(href.toString(), (0, import_lodash_es5.cloneDeep)(options)) || {} : {};
3147
+ const configuredOptions = defaultVisitOptionsCallback ? defaultVisitOptionsCallback(href.toString(), cloneDeep3(options)) || {} : {};
2735
3148
  const mergedOptions = {
2736
3149
  method: "get",
2737
3150
  data: {},
@@ -2749,9 +3162,12 @@ var Router = class {
2749
3162
  fresh: false,
2750
3163
  reset: [],
2751
3164
  preserveUrl: false,
3165
+ preserveErrors: false,
2752
3166
  prefetch: false,
2753
3167
  invalidateCacheTags: [],
2754
3168
  viewTransition: false,
3169
+ component: null,
3170
+ pageProps: null,
2755
3171
  ...options,
2756
3172
  ...configuredOptions
2757
3173
  };
@@ -2767,7 +3183,6 @@ var Router = class {
2767
3183
  completed: false,
2768
3184
  interrupted: false,
2769
3185
  ...mergedOptions,
2770
- ...pendingVisitOptions,
2771
3186
  url,
2772
3187
  data: _data
2773
3188
  };
@@ -2778,36 +3193,66 @@ var Router = class {
2778
3193
  }
2779
3194
  getVisitEvents(options) {
2780
3195
  return {
2781
- onCancelToken: options.onCancelToken || (() => {
2782
- }),
2783
- onBefore: options.onBefore || (() => {
2784
- }),
2785
- onBeforeUpdate: options.onBeforeUpdate || (() => {
2786
- }),
2787
- onStart: options.onStart || (() => {
2788
- }),
2789
- onProgress: options.onProgress || (() => {
2790
- }),
2791
- onFinish: options.onFinish || (() => {
2792
- }),
2793
- onCancel: options.onCancel || (() => {
2794
- }),
2795
- onSuccess: options.onSuccess || (() => {
2796
- }),
2797
- onError: options.onError || (() => {
2798
- }),
2799
- onFlash: options.onFlash || (() => {
2800
- }),
2801
- onPrefetched: options.onPrefetched || (() => {
2802
- }),
2803
- onPrefetching: options.onPrefetching || (() => {
2804
- })
3196
+ onCancelToken: options.onCancelToken || noop,
3197
+ onBefore: options.onBefore || noop,
3198
+ onBeforeUpdate: options.onBeforeUpdate || noop,
3199
+ onStart: options.onStart || noop,
3200
+ onProgress: options.onProgress || noop,
3201
+ onFinish: options.onFinish || noop,
3202
+ onCancel: options.onCancel || noop,
3203
+ onSuccess: options.onSuccess || noop,
3204
+ onError: options.onError || noop,
3205
+ onHttpException: options.onHttpException || noop,
3206
+ onNetworkError: options.onNetworkError || noop,
3207
+ onFlash: options.onFlash || noop,
3208
+ onPrefetched: options.onPrefetched || noop,
3209
+ onPrefetching: options.onPrefetching || noop
3210
+ };
3211
+ }
3212
+ applyOptimisticUpdate(optimistic, events) {
3213
+ const currentProps = page.get().props;
3214
+ const optimisticProps = optimistic(cloneDeep3(currentProps));
3215
+ if (!optimisticProps) {
3216
+ return;
3217
+ }
3218
+ const propsSnapshot = {};
3219
+ for (const key of Object.keys(optimisticProps)) {
3220
+ if (!isEqual3(currentProps[key], optimisticProps[key])) {
3221
+ propsSnapshot[key] = cloneDeep3(currentProps[key]);
3222
+ }
3223
+ }
3224
+ if (Object.keys(propsSnapshot).length === 0) {
3225
+ return;
3226
+ }
3227
+ const updatedAt = Date.now();
3228
+ page.recordOptimisticUpdate(Object.keys(propsSnapshot), updatedAt);
3229
+ page.setPropsQuietly({ ...currentProps, ...optimisticProps });
3230
+ let shouldRestore = true;
3231
+ const originalOnSuccess = events.onSuccess;
3232
+ events.onSuccess = (page2) => {
3233
+ shouldRestore = false;
3234
+ return originalOnSuccess(page2);
3235
+ };
3236
+ const originalOnFinish = events.onFinish;
3237
+ events.onFinish = (visit) => {
3238
+ if (shouldRestore) {
3239
+ const propsToRestore = {};
3240
+ for (const [key, value] of Object.entries(propsSnapshot)) {
3241
+ if (!page.shouldPreserveOptimistic(key, updatedAt)) {
3242
+ propsToRestore[key] = value;
3243
+ }
3244
+ }
3245
+ if (Object.keys(propsToRestore).length > 0) {
3246
+ page.setPropsQuietly({ ...page.get().props, ...propsToRestore });
3247
+ }
3248
+ }
3249
+ return originalOnFinish(visit);
2805
3250
  };
2806
3251
  }
2807
3252
  loadDeferredProps(deferred) {
2808
3253
  if (deferred) {
2809
- Object.entries(deferred).forEach(([_, group]) => {
2810
- this.doReload({ only: group, deferredProps: true });
3254
+ Object.values(deferred).forEach((props) => {
3255
+ this.doReload({ only: props, deferredProps: true, preserveErrors: true });
2811
3256
  });
2812
3257
  }
2813
3258
  }
@@ -2923,8 +3368,108 @@ var UseFormUtils = class {
2923
3368
  }
2924
3369
  };
2925
3370
 
3371
+ // src/axiosHttpClient.ts
3372
+ function normalizeHeaders(headers) {
3373
+ if (!headers || typeof headers !== "object") {
3374
+ return {};
3375
+ }
3376
+ const normalized = {};
3377
+ const entries = typeof headers.entries === "function" ? Array.from(headers.entries()) : Object.entries(headers);
3378
+ for (const [key, value] of entries) {
3379
+ if (typeof value === "string") {
3380
+ normalized[key.toLowerCase()] = value;
3381
+ } else if (Array.isArray(value)) {
3382
+ normalized[key.toLowerCase()] = value.join(", ");
3383
+ }
3384
+ }
3385
+ return normalized;
3386
+ }
3387
+ function toHttpProgressEvent(axiosEvent) {
3388
+ return {
3389
+ progress: axiosEvent.progress,
3390
+ loaded: axiosEvent.loaded,
3391
+ total: axiosEvent.total
3392
+ };
3393
+ }
3394
+ var axiosModulePromise;
3395
+ function loadAxiosModule() {
3396
+ if (!axiosModulePromise) {
3397
+ axiosModulePromise = import("axios").catch((error) => {
3398
+ axiosModulePromise = void 0;
3399
+ throw error;
3400
+ });
3401
+ }
3402
+ return axiosModulePromise;
3403
+ }
3404
+ var AxiosHttpClient = class {
3405
+ constructor(instance) {
3406
+ this.axiosInstance = instance ? Promise.resolve(instance) : loadAxiosModule().then((module) => module.default);
3407
+ }
3408
+ async getAxios() {
3409
+ return this.axiosInstance;
3410
+ }
3411
+ async request(config2) {
3412
+ const processedConfig = await httpHandlers.processRequest(config2);
3413
+ try {
3414
+ const response = await this.doRequest(processedConfig);
3415
+ return await httpHandlers.processResponse(response);
3416
+ } catch (error) {
3417
+ if (error instanceof HttpResponseError || error instanceof HttpNetworkError || error instanceof HttpCancelledError) {
3418
+ await httpHandlers.processError(error);
3419
+ }
3420
+ throw error;
3421
+ }
3422
+ }
3423
+ async doRequest(config2) {
3424
+ const axios = await this.getAxios();
3425
+ try {
3426
+ const response = await axios({
3427
+ method: config2.method,
3428
+ url: config2.url,
3429
+ data: config2.data,
3430
+ params: config2.params,
3431
+ headers: config2.headers,
3432
+ signal: config2.signal,
3433
+ responseType: "text",
3434
+ onUploadProgress: config2.onUploadProgress ? (event) => config2.onUploadProgress(toHttpProgressEvent(event)) : void 0
3435
+ });
3436
+ return {
3437
+ status: response.status,
3438
+ data: response.data,
3439
+ headers: normalizeHeaders(response.headers)
3440
+ };
3441
+ } catch (error) {
3442
+ const axiosModule = await loadAxiosModule();
3443
+ if (axiosModule.default.isCancel(error)) {
3444
+ throw new HttpCancelledError("Request was cancelled", config2.url);
3445
+ }
3446
+ if (error && typeof error === "object" && "response" in error) {
3447
+ const axiosError = error;
3448
+ const httpResponse = {
3449
+ status: axiosError.response.status,
3450
+ data: axiosError.response.data,
3451
+ headers: normalizeHeaders(axiosError.response.headers)
3452
+ };
3453
+ throw new HttpResponseError(
3454
+ `Request failed with status ${axiosError.response.status}`,
3455
+ httpResponse,
3456
+ config2.url
3457
+ );
3458
+ }
3459
+ throw new HttpNetworkError(
3460
+ error instanceof Error ? error.message : "Network error",
3461
+ config2.url,
3462
+ error instanceof Error ? error : void 0
3463
+ );
3464
+ }
3465
+ }
3466
+ };
3467
+ function axiosAdapter(instance) {
3468
+ return new AxiosHttpClient(instance);
3469
+ }
3470
+
2926
3471
  // src/formObject.ts
2927
- var import_lodash_es6 = require("lodash-es");
3472
+ import { get as get8, set as set6 } from "lodash-es";
2928
3473
  function undotKey(key) {
2929
3474
  if (!key.includes(".")) {
2930
3475
  return key;
@@ -2937,7 +3482,7 @@ function undotKey(key) {
2937
3482
  };
2938
3483
  return key.replace(/\\\./g, "__ESCAPED_DOT__").split(/(\[[^\]]*\])/).filter(Boolean).map(transformSegment).join("").replace(/__ESCAPED_DOT__/g, ".");
2939
3484
  }
2940
- function parseKey(key) {
3485
+ function parseKey2(key) {
2941
3486
  const path = [];
2942
3487
  const pattern = /([^\[\]]+)|\[(\d*)\]/g;
2943
3488
  let match;
@@ -2991,17 +3536,17 @@ function formDataToObject(source) {
2991
3536
  if (value instanceof File && value.size === 0 && value.name === "") {
2992
3537
  continue;
2993
3538
  }
2994
- const path = parseKey(undotKey(key));
3539
+ const path = parseKey2(undotKey(key));
2995
3540
  if (path[path.length - 1] === "") {
2996
3541
  const arrayPath = path.slice(0, -1);
2997
- const existing = (0, import_lodash_es6.get)(form, arrayPath);
3542
+ const existing = get8(form, arrayPath);
2998
3543
  if (Array.isArray(existing)) {
2999
3544
  existing.push(value);
3000
3545
  } else if (existing && typeof existing === "object" && !isFile(existing)) {
3001
3546
  const numericKeys = Object.keys(existing).filter((k) => /^\d+$/.test(k)).map(Number).sort((a, b) => a - b);
3002
- (0, import_lodash_es6.set)(form, arrayPath, numericKeys.length > 0 ? [...numericKeys.map((k) => existing[k]), value] : [value]);
3547
+ set6(form, arrayPath, numericKeys.length > 0 ? [...numericKeys.map((k) => existing[k]), value] : [value]);
3003
3548
  } else {
3004
- (0, import_lodash_es6.set)(form, arrayPath, [value]);
3549
+ set6(form, arrayPath, [value]);
3005
3550
  }
3006
3551
  continue;
3007
3552
  }
@@ -3012,9 +3557,6 @@ function formDataToObject(source) {
3012
3557
 
3013
3558
  // src/head.ts
3014
3559
  var Renderer = {
3015
- preferredAttribute() {
3016
- return config.get("future.useDataInertiaHeadAttribute") ? "data-inertia" : "inertia";
3017
- },
3018
3560
  buildDOMElement(tag) {
3019
3561
  const template = document.createElement("template");
3020
3562
  template.innerHTML = tag;
@@ -3030,13 +3572,12 @@ var Renderer = {
3030
3572
  return script;
3031
3573
  },
3032
3574
  isInertiaManagedElement(element) {
3033
- return element.nodeType === Node.ELEMENT_NODE && element.getAttribute(this.preferredAttribute()) !== null;
3575
+ return element.nodeType === Node.ELEMENT_NODE && element.getAttribute("data-inertia") !== null;
3034
3576
  },
3035
3577
  findMatchingElementIndex(element, elements) {
3036
- const attribute = this.preferredAttribute();
3037
- const key = element.getAttribute(attribute);
3578
+ const key = element.getAttribute("data-inertia");
3038
3579
  if (key !== null) {
3039
- return elements.findIndex((element2) => element2.getAttribute(attribute) === key);
3580
+ return elements.findIndex((element2) => element2.getAttribute("data-inertia") === key);
3040
3581
  }
3041
3582
  return -1;
3042
3583
  },
@@ -3048,12 +3589,12 @@ var Renderer = {
3048
3589
  targetElements.forEach((targetElement) => {
3049
3590
  const index = this.findMatchingElementIndex(targetElement, sourceElements);
3050
3591
  if (index === -1) {
3051
- targetElement?.parentNode?.removeChild(targetElement);
3592
+ targetElement.remove();
3052
3593
  return;
3053
3594
  }
3054
3595
  const sourceElement = sourceElements.splice(index, 1)[0];
3055
3596
  if (sourceElement && !targetElement.isEqualNode(sourceElement)) {
3056
- targetElement?.parentNode?.replaceChild(sourceElement, targetElement);
3597
+ targetElement.replaceWith(sourceElement);
3057
3598
  }
3058
3599
  });
3059
3600
  sourceElements.forEach((element) => document.head.appendChild(element));
@@ -3087,9 +3628,8 @@ function createHeadManager(isServer3, titleCallback, onUpdate) {
3087
3628
  }
3088
3629
  function collect() {
3089
3630
  const title = titleCallback("");
3090
- const attribute = Renderer.preferredAttribute();
3091
3631
  const defaults = {
3092
- ...title ? { title: `<title ${attribute}="">${title}</title>` } : {}
3632
+ ...title ? { title: `<title data-inertia="">${title}</title>` } : {}
3093
3633
  };
3094
3634
  const elements = Object.values(states).reduce((carry, elements2) => carry.concat(elements2), []).reduce((carry, element) => {
3095
3635
  if (element.indexOf("<") === -1) {
@@ -3100,7 +3640,7 @@ function createHeadManager(isServer3, titleCallback, onUpdate) {
3100
3640
  carry.title = title2 ? `${title2[1]}${titleCallback(title2[2])}${title2[3]}` : element;
3101
3641
  return carry;
3102
3642
  }
3103
- const match = element.match(attribute === "inertia" ? / inertia="[^"]+"/ : / data-inertia="[^"]+"/);
3643
+ const match = element.match(/ data-inertia="[^"]+"/);
3104
3644
  if (match) {
3105
3645
  carry[match[0]] = element;
3106
3646
  } else {
@@ -3119,7 +3659,6 @@ function createHeadManager(isServer3, titleCallback, onUpdate) {
3119
3659
  createProvider: function() {
3120
3660
  const id = connect();
3121
3661
  return {
3122
- preferredAttribute: Renderer.preferredAttribute,
3123
3662
  reconnect: () => reconnect(id),
3124
3663
  update: (elements) => update(id, elements),
3125
3664
  disconnect: () => disconnect(id)
@@ -3204,9 +3743,10 @@ var useInfiniteScrollData = (options) => {
3204
3743
  }
3205
3744
  state.loading = true;
3206
3745
  router.reload({
3746
+ preserveErrors: true,
3207
3747
  ...reloadOptions,
3208
- data: { [getPageName()]: page2 },
3209
- only: [options.getPropName()],
3748
+ data: { ...reloadOptions.data || {}, [getPageName()]: page2 },
3749
+ only: [...reloadOptions.only || [], options.getPropName()],
3210
3750
  preserveUrl: true,
3211
3751
  // we handle URL updates manually via useInfiniteScrollQueryString()
3212
3752
  headers: {
@@ -3607,6 +4147,7 @@ function useInfiniteScroll(options) {
3607
4147
  };
3608
4148
  const originalFetchNext = dataManager.fetchNext;
3609
4149
  dataManager.fetchNext = (reloadOptions = {}) => {
4150
+ reloadOptions = { ...options.getReloadOptions?.(), ...reloadOptions };
3610
4151
  if (options.inReverseMode()) {
3611
4152
  reloadOptions = addScrollPreservationCallbacks(reloadOptions);
3612
4153
  }
@@ -3614,6 +4155,7 @@ function useInfiniteScroll(options) {
3614
4155
  };
3615
4156
  const originalFetchPrevious = dataManager.fetchPrevious;
3616
4157
  dataManager.fetchPrevious = (reloadOptions = {}) => {
4158
+ reloadOptions = { ...options.getReloadOptions?.(), ...reloadOptions };
3617
4159
  if (!options.inReverseMode()) {
3618
4160
  reloadOptions = addScrollPreservationCallbacks(reloadOptions);
3619
4161
  }
@@ -3632,6 +4174,121 @@ function useInfiniteScroll(options) {
3632
4174
  };
3633
4175
  }
3634
4176
 
4177
+ // src/layout.ts
4178
+ import { isEqual as isEqual4 } from "lodash-es";
4179
+ function createLayoutPropsStore() {
4180
+ let shared = {};
4181
+ let named = {};
4182
+ let snapshot = { shared, named };
4183
+ const listeners = /* @__PURE__ */ new Set();
4184
+ let pendingNotify = false;
4185
+ const updateSnapshot = () => {
4186
+ snapshot = { shared, named };
4187
+ };
4188
+ const notify = () => {
4189
+ if (pendingNotify) {
4190
+ return;
4191
+ }
4192
+ pendingNotify = true;
4193
+ queueMicrotask(() => {
4194
+ pendingNotify = false;
4195
+ listeners.forEach((fn) => fn());
4196
+ });
4197
+ };
4198
+ return {
4199
+ set(props) {
4200
+ const merged = { ...shared, ...props };
4201
+ if (isEqual4(shared, merged)) {
4202
+ return;
4203
+ }
4204
+ shared = merged;
4205
+ updateSnapshot();
4206
+ notify();
4207
+ },
4208
+ setFor(name, props) {
4209
+ const current = named[name] || {};
4210
+ const merged = { ...current, ...props };
4211
+ if (isEqual4(current, merged)) {
4212
+ return;
4213
+ }
4214
+ named = { ...named, [name]: merged };
4215
+ updateSnapshot();
4216
+ notify();
4217
+ },
4218
+ reset() {
4219
+ shared = {};
4220
+ named = {};
4221
+ updateSnapshot();
4222
+ notify();
4223
+ },
4224
+ subscribe(callback) {
4225
+ listeners.add(callback);
4226
+ return () => listeners.delete(callback);
4227
+ },
4228
+ get: () => snapshot
4229
+ };
4230
+ }
4231
+ function mergeLayoutProps(defaults, staticProps, dynamicProps) {
4232
+ const result = { ...defaults };
4233
+ for (const key of Object.keys(defaults)) {
4234
+ if (key in staticProps && staticProps[key] !== void 0) {
4235
+ result[key] = staticProps[key];
4236
+ }
4237
+ if (key in dynamicProps && dynamicProps[key] !== void 0) {
4238
+ result[key] = dynamicProps[key];
4239
+ }
4240
+ }
4241
+ return result;
4242
+ }
4243
+ function isPlainObject(value) {
4244
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4245
+ }
4246
+ function hasComponentKey(value) {
4247
+ return isPlainObject(value) && "component" in value;
4248
+ }
4249
+ function isNamedLayouts(value, isComponent) {
4250
+ if (!isPlainObject(value) || isComponent(value) || "component" in value) {
4251
+ return false;
4252
+ }
4253
+ return Object.values(value).some((v) => isComponent(v) || Array.isArray(v) && isComponent(v[0]));
4254
+ }
4255
+ function isTuple(value, isComponent) {
4256
+ return Array.isArray(value) && value.length === 2 && isComponent(value[0]) && isPlainObject(value[1]) && !isComponent(value[1]);
4257
+ }
4258
+ function extract(item, isComponent) {
4259
+ if (Array.isArray(item) && isComponent(item[0])) {
4260
+ return { component: item[0], props: item[1] ?? {} };
4261
+ }
4262
+ if (hasComponentKey(item) && isComponent(item.component)) {
4263
+ return { component: item.component, props: item.props ?? {} };
4264
+ }
4265
+ if (isComponent(item)) {
4266
+ return { component: item, props: {} };
4267
+ }
4268
+ throw new Error(`Invalid layout definition: received ${typeof item}`);
4269
+ }
4270
+ function normalizeLayouts(layout, isComponent, isRenderFunction) {
4271
+ if (!layout || isRenderFunction && isRenderFunction(layout)) {
4272
+ return [];
4273
+ }
4274
+ if (isNamedLayouts(layout, isComponent)) {
4275
+ return Object.entries(layout).map(([name, value]) => ({ ...extract(value, isComponent), name }));
4276
+ }
4277
+ if (isTuple(layout, isComponent)) {
4278
+ return [{ component: layout[0], props: layout[1] ?? {} }];
4279
+ }
4280
+ if (Array.isArray(layout)) {
4281
+ return layout.map((item) => extract(item, isComponent));
4282
+ }
4283
+ if (hasComponentKey(layout) && isComponent(layout.component)) {
4284
+ return [{ component: layout.component, props: layout.props ?? {} }];
4285
+ }
4286
+ if (isComponent(layout)) {
4287
+ return [{ component: layout, props: {} }];
4288
+ }
4289
+ return [];
4290
+ }
4291
+
3635
4292
  // src/navigationEvents.ts
3636
4293
  function isContentEditableOrPrevented(event) {
3637
4294
  return event.target instanceof HTMLElement && event.target.isContentEditable || event.defaultPrevented;
@@ -3647,11 +4304,11 @@ function shouldNavigate(event) {
3647
4304
 
3648
4305
  // src/progress-component.ts
3649
4306
  var baseComponentSelector = "nprogress";
4307
+ var usePopover;
3650
4308
  var progress2;
3651
4309
  var settings = {
3652
4310
  minimum: 0.08,
3653
4311
  easing: "linear",
3654
- positionUsing: "translate3d",
3655
4312
  speed: 200,
3656
4313
  trickle: true,
3657
4314
  trickleSpeed: 200,
@@ -3661,6 +4318,7 @@ var settings = {
3661
4318
  parent: "body",
3662
4319
  color: "#29d",
3663
4320
  includeCSS: true,
4321
+ popover: null,
3664
4322
  template: [
3665
4323
  '<div class="bar" role="bar">',
3666
4324
  '<div class="peg"></div>',
@@ -3671,16 +4329,21 @@ var settings = {
3671
4329
  ].join("")
3672
4330
  };
3673
4331
  var status = null;
4332
+ var hidden = false;
3674
4333
  var configure = (options) => {
3675
4334
  Object.assign(settings, options);
4335
+ usePopover = settings.popover ?? "popover" in HTMLElement.prototype;
3676
4336
  if (settings.includeCSS) {
3677
4337
  injectCSS(settings.color);
3678
4338
  }
3679
4339
  progress2 = document.createElement("div");
3680
4340
  progress2.id = baseComponentSelector;
3681
4341
  progress2.innerHTML = settings.template;
4342
+ if (usePopover) {
4343
+ progress2.popover = "manual";
4344
+ }
3682
4345
  };
3683
- var set5 = (n) => {
4346
+ var set7 = (n) => {
3684
4347
  const started = isStarted();
3685
4348
  n = clamp(n, settings.minimum, 1);
3686
4349
  status = n === 1 ? null : n;
@@ -3690,21 +4353,10 @@ var set5 = (n) => {
3690
4353
  const ease = settings.easing;
3691
4354
  progress3.offsetWidth;
3692
4355
  queue4((next) => {
3693
- const barStyles = (() => {
3694
- if (settings.positionUsing === "translate3d") {
3695
- return {
3696
- transition: `all ${speed}ms ${ease}`,
3697
- transform: `translate3d(${toBarPercentage(n)}%,0,0)`
3698
- };
3699
- }
3700
- if (settings.positionUsing === "translate") {
3701
- return {
3702
- transition: `all ${speed}ms ${ease}`,
3703
- transform: `translate(${toBarPercentage(n)}%,0)`
3704
- };
3705
- }
3706
- return { marginLeft: `${toBarPercentage(n)}%` };
3707
- })();
4356
+ const barStyles = {
4357
+ transition: `all ${speed}ms ${ease}`,
4358
+ transform: `translate3d(${toBarPercentage(n)}%,0,0)`
4359
+ };
3708
4360
  for (const key in barStyles) {
3709
4361
  bar.style[key] = barStyles[key];
3710
4362
  }
@@ -3729,7 +4381,7 @@ var set5 = (n) => {
3729
4381
  var isStarted = () => typeof status === "number";
3730
4382
  var start = () => {
3731
4383
  if (!status) {
3732
- set5(0);
4384
+ set7(0);
3733
4385
  }
3734
4386
  const work = function() {
3735
4387
  setTimeout(function() {
@@ -3749,7 +4401,7 @@ var done = (force) => {
3749
4401
  return;
3750
4402
  }
3751
4403
  increaseByRandom(0.3 + 0.5 * Math.random());
3752
- set5(1);
4404
+ set7(1);
3753
4405
  };
3754
4406
  var increaseByRandom = (amount) => {
3755
4407
  const n = status;
@@ -3773,7 +4425,7 @@ var increaseByRandom = (amount) => {
3773
4425
  }
3774
4426
  return 0;
3775
4427
  })();
3776
- return set5(clamp(n + amount, 0, 0.994));
4428
+ return set7(clamp(n + amount, 0, 0.994));
3777
4429
  };
3778
4430
  var render = (fromStart) => {
3779
4431
  if (isRendered()) {
@@ -3782,35 +4434,47 @@ var render = (fromStart) => {
3782
4434
  document.documentElement.classList.add(`${baseComponentSelector}-busy`);
3783
4435
  const bar = progress2.querySelector(settings.barSelector);
3784
4436
  const perc = fromStart ? "-100" : toBarPercentage(status || 0);
3785
- const parent = getParent();
3786
4437
  bar.style.transition = "all 0 linear";
3787
4438
  bar.style.transform = `translate3d(${perc}%,0,0)`;
3788
4439
  if (!settings.showSpinner) {
3789
4440
  progress2.querySelector(settings.spinnerSelector)?.remove();
3790
4441
  }
3791
- if (parent !== document.body) {
3792
- parent.classList.add(`${baseComponentSelector}-custom-parent`);
4442
+ if (usePopover) {
4443
+ document.body.appendChild(progress2);
4444
+ if (!hidden) {
4445
+ progress2.showPopover();
4446
+ }
4447
+ } else {
4448
+ const parent = getParent();
4449
+ if (parent !== document.body) {
4450
+ parent.classList.add(`${baseComponentSelector}-custom-parent`);
4451
+ }
4452
+ parent.appendChild(progress2);
4453
+ if (hidden) {
4454
+ progress2.style.display = "none";
4455
+ }
3793
4456
  }
3794
- parent.appendChild(progress2);
3795
4457
  return progress2;
3796
4458
  };
3797
4459
  var getParent = () => {
3798
- return isDOM(settings.parent) ? settings.parent : document.querySelector(settings.parent);
4460
+ return document.querySelector(settings.parent);
3799
4461
  };
3800
4462
  var remove = () => {
3801
4463
  document.documentElement.classList.remove(`${baseComponentSelector}-busy`);
3802
- getParent().classList.remove(`${baseComponentSelector}-custom-parent`);
4464
+ if (usePopover && progress2?.isConnected) {
4465
+ try {
4466
+ progress2.hidePopover();
4467
+ } catch {
4468
+ }
4469
+ }
4470
+ if (!usePopover) {
4471
+ getParent().classList.remove(`${baseComponentSelector}-custom-parent`);
4472
+ }
3803
4473
  progress2?.remove();
3804
4474
  };
3805
4475
  var isRendered = () => {
3806
4476
  return document.getElementById(baseComponentSelector) !== null;
3807
4477
  };
3808
- var isDOM = (obj) => {
3809
- if (typeof HTMLElement === "object") {
3810
- return obj instanceof HTMLElement;
3811
- }
3812
- return obj && typeof obj === "object" && obj.nodeType === 1 && typeof obj.nodeName === "string";
3813
- };
3814
4478
  function clamp(n, min, max) {
3815
4479
  if (n < min) {
3816
4480
  return min;
@@ -3841,6 +4505,21 @@ var injectCSS = (color) => {
3841
4505
  element.textContent = `
3842
4506
  #${baseComponentSelector} {
3843
4507
  pointer-events: none;
4508
+ background: none;
4509
+ border: none;
4510
+ margin: 0;
4511
+ padding: 0;
4512
+ overflow: visible;
4513
+ inset: unset;
4514
+ width: 100%;
4515
+ height: 0;
4516
+ position: fixed;
4517
+ top: 0;
4518
+ left: 0;
4519
+ }
4520
+
4521
+ #${baseComponentSelector}::backdrop {
4522
+ display: none;
3844
4523
  }
3845
4524
 
3846
4525
  #${baseComponentSelector} .bar {
@@ -3906,12 +4585,30 @@ var injectCSS = (color) => {
3906
4585
  document.head.appendChild(element);
3907
4586
  };
3908
4587
  var show = () => {
3909
- if (progress2) {
4588
+ hidden = false;
4589
+ if (!progress2?.isConnected) {
4590
+ return;
4591
+ }
4592
+ if (usePopover) {
4593
+ try {
4594
+ progress2.showPopover();
4595
+ } catch {
4596
+ }
4597
+ } else {
3910
4598
  progress2.style.display = "";
3911
4599
  }
3912
4600
  };
3913
4601
  var hide = () => {
3914
- if (progress2) {
4602
+ hidden = true;
4603
+ if (!progress2?.isConnected) {
4604
+ return;
4605
+ }
4606
+ if (usePopover) {
4607
+ try {
4608
+ progress2.hidePopover();
4609
+ } catch {
4610
+ }
4611
+ } else {
3915
4612
  progress2.style.display = "none";
3916
4613
  }
3917
4614
  };
@@ -3919,7 +4616,7 @@ var progress_component_default = {
3919
4616
  configure,
3920
4617
  isStarted,
3921
4618
  done,
3922
- set: set5,
4619
+ set: set7,
3923
4620
  remove,
3924
4621
  start,
3925
4622
  status,
@@ -3966,8 +4663,6 @@ var Progress = class {
3966
4663
  }
3967
4664
  };
3968
4665
  var progress = new Progress();
3969
- var reveal = progress.reveal;
3970
- var hide2 = progress.hide;
3971
4666
  function addEventListeners(delay) {
3972
4667
  document.addEventListener("inertia:start", (e) => handleStartEvent(e, delay));
3973
4668
  document.addEventListener("inertia:progress", handleProgressEvent);
@@ -4001,10 +4696,11 @@ function setupProgress({
4001
4696
  delay = 250,
4002
4697
  color = "#29d",
4003
4698
  includeCSS = true,
4004
- showSpinner = false
4699
+ showSpinner = false,
4700
+ popover = null
4005
4701
  } = {}) {
4006
4702
  addEventListeners(delay);
4007
- progress_component_default.configure({ showSpinner, includeCSS, color });
4703
+ progress_component_default.configure({ showSpinner, includeCSS, color, popover });
4008
4704
  }
4009
4705
 
4010
4706
  // src/resetFormFields.ts
@@ -4145,8 +4841,51 @@ function resetFormFields(formElement, defaults, fieldNames) {
4145
4841
  }
4146
4842
  }
4147
4843
 
4844
+ // src/ssrUtils.ts
4845
+ function buildSSRBody(id, page2, html) {
4846
+ const json = JSON.stringify(page2).replace(/\//g, "\\/");
4847
+ return `<script data-page="${id}" type="application/json">${json}<\/script><div data-server-rendered="true" id="${id}">${html}</div>`;
4848
+ }
4849
+
4148
4850
  // src/index.ts
4149
4851
  var router = new Router();
4852
+ export {
4853
+ FormComponentResetSymbol,
4854
+ HttpCancelledError,
4855
+ HttpNetworkError,
4856
+ HttpResponseError,
4857
+ UseFormUtils,
4858
+ XhrHttpClient,
4859
+ axiosAdapter,
4860
+ buildSSRBody,
4861
+ config,
4862
+ createHeadManager,
4863
+ createLayoutPropsStore,
4864
+ formDataToObject,
4865
+ getInitialPageFromDOM,
4866
+ getScrollableParent,
4867
+ hasFiles,
4868
+ hrefToUrl,
4869
+ http,
4870
+ isSameUrlWithoutQueryOrHash,
4871
+ isUrlMethodPair,
4872
+ mergeDataIntoQueryString,
4873
+ mergeLayoutProps,
4874
+ normalizeLayouts,
4875
+ objectToFormData,
4876
+ progress,
4877
+ resetFormFields,
4878
+ resolveUrlMethodPairComponent,
4879
+ router,
4880
+ setupProgress,
4881
+ shouldIntercept,
4882
+ shouldNavigate,
4883
+ urlHasProtocol,
4884
+ urlToString,
4885
+ urlWithoutHash,
4886
+ useInfiniteScroll,
4887
+ xhrHttpClient
4888
+ };
4150
4889
  /* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress
4151
4890
  * @license MIT */
4152
4891
  //# sourceMappingURL=index.js.map