@inertiajs/core 3.0.0-beta.2 → 3.0.0-beta.3

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,5 +1,5 @@
1
1
  // src/router.ts
2
- import { cloneDeep as cloneDeep3, get as get7, isEqual as isEqual3, set as set5 } from "lodash-es";
2
+ import { cloneDeep as cloneDeep4, get as get7, isEqual as isEqual3, set as set5 } from "lodash-es";
3
3
 
4
4
  // src/config.ts
5
5
  import { get, has, set } from "lodash-es";
@@ -99,7 +99,7 @@ var fireFlashEvent = (flash) => {
99
99
  };
100
100
 
101
101
  // src/history.ts
102
- import { cloneDeep as cloneDeep2, isEqual } from "lodash-es";
102
+ import { cloneDeep as cloneDeep3, isEqual } from "lodash-es";
103
103
 
104
104
  // src/sessionStorage.ts
105
105
  var SessionStorage = class {
@@ -271,7 +271,7 @@ var getKeyFromSessionStorage = async () => {
271
271
  };
272
272
 
273
273
  // src/page.ts
274
- import { get as get3, set as set3 } from "lodash-es";
274
+ import { cloneDeep as cloneDeep2, get as get3, set as set3 } from "lodash-es";
275
275
 
276
276
  // src/prefetched.ts
277
277
  import { cloneDeep, get as get2 } from "lodash-es";
@@ -976,9 +976,9 @@ function resolveUrlMethodPairComponent(pair) {
976
976
  if (!pair.component) {
977
977
  return null;
978
978
  }
979
- if (Array.isArray(pair.component)) {
979
+ if (typeof pair.component !== "string") {
980
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.`
981
+ `The "component" property on the URL method pair received multiple components (${Object.keys(pair.component).join(", ")}), but only a single component string is supported for instant visits. Use the withComponent() method to specify which component to use.`
982
982
  );
983
983
  return null;
984
984
  }
@@ -1001,6 +1001,9 @@ var CurrentPage = class {
1001
1001
  this.cleared = false;
1002
1002
  this.pendingDeferredProps = null;
1003
1003
  this.historyQuotaExceeded = false;
1004
+ this.optimisticBaseline = {};
1005
+ this.pendingOptimistics = [];
1006
+ this.optimisticCounter = 0;
1004
1007
  }
1005
1008
  init({
1006
1009
  initialPage,
@@ -1048,7 +1051,6 @@ var CurrentPage = class {
1048
1051
  const scrollRegions = !isServer3 && preserveScroll ? Scroll.getScrollRegions() : [];
1049
1052
  replace = replace || isSameUrlWithoutHash(hrefToUrl(page2.url), location);
1050
1053
  const pageForHistory = { ...page2, flash: {} };
1051
- delete pageForHistory.optimisticUpdatedAt;
1052
1054
  return new Promise(
1053
1055
  (resolve) => replace ? history.replaceState(pageForHistory, resolve) : history.pushState(pageForHistory, resolve)
1054
1056
  ).then(() => {
@@ -1147,7 +1149,7 @@ var CurrentPage = class {
1147
1149
  viewTransition
1148
1150
  }) {
1149
1151
  const doSwap = () => this.swapComponent({ component, page: page2, preserveState });
1150
- if (!viewTransition || !document?.startViewTransition) {
1152
+ if (!viewTransition || !document?.startViewTransition || document.visibilityState === "hidden") {
1151
1153
  return doSwap();
1152
1154
  }
1153
1155
  const viewTransitionCallback = typeof viewTransition === "boolean" ? () => null : viewTransition;
@@ -1159,19 +1161,55 @@ var CurrentPage = class {
1159
1161
  resolve(component, page2) {
1160
1162
  return Promise.resolve(this.resolveComponent(component, page2));
1161
1163
  }
1162
- recordOptimisticUpdate(keys, updatedAt) {
1163
- if (!this.page.optimisticUpdatedAt) {
1164
- this.page.optimisticUpdatedAt = {};
1164
+ nextOptimisticId() {
1165
+ return ++this.optimisticCounter;
1166
+ }
1167
+ setBaseline(key, value) {
1168
+ if (!(key in this.optimisticBaseline)) {
1169
+ this.optimisticBaseline[key] = value;
1170
+ }
1171
+ }
1172
+ updateBaseline(key, value) {
1173
+ if (key in this.optimisticBaseline) {
1174
+ this.optimisticBaseline[key] = value;
1175
+ }
1176
+ }
1177
+ hasBaseline(key) {
1178
+ return key in this.optimisticBaseline;
1179
+ }
1180
+ registerOptimistic(id, callback) {
1181
+ this.pendingOptimistics.push({ id, callback });
1182
+ }
1183
+ unregisterOptimistic(id) {
1184
+ this.pendingOptimistics = this.pendingOptimistics.filter((entry) => entry.id !== id);
1185
+ }
1186
+ replayOptimistics() {
1187
+ const baselineKeys = Object.keys(this.optimisticBaseline);
1188
+ if (baselineKeys.length === 0) {
1189
+ return {};
1165
1190
  }
1166
- for (const key of keys) {
1167
- if (updatedAt > (this.page.optimisticUpdatedAt[key] || 0)) {
1168
- this.page.optimisticUpdatedAt[key] = updatedAt;
1191
+ const props = cloneDeep2(this.page.props);
1192
+ for (const key of baselineKeys) {
1193
+ props[key] = cloneDeep2(this.optimisticBaseline[key]);
1194
+ }
1195
+ for (const { callback } of this.pendingOptimistics) {
1196
+ const result = callback(cloneDeep2(props));
1197
+ if (result) {
1198
+ Object.assign(props, result);
1169
1199
  }
1170
1200
  }
1201
+ const replayedProps = {};
1202
+ for (const key of baselineKeys) {
1203
+ replayedProps[key] = props[key];
1204
+ }
1205
+ return replayedProps;
1171
1206
  }
1172
- shouldPreserveOptimistic(key, updatedAt) {
1173
- const lastUpdatedAt = this.page.optimisticUpdatedAt?.[key];
1174
- return lastUpdatedAt !== void 0 && updatedAt < lastUpdatedAt;
1207
+ pendingOptimisticCount() {
1208
+ return this.pendingOptimistics.length;
1209
+ }
1210
+ clearOptimisticState() {
1211
+ this.optimisticBaseline = {};
1212
+ this.pendingOptimistics = [];
1175
1213
  }
1176
1214
  isTheSame(page2) {
1177
1215
  return this.page.component === page2.component;
@@ -1280,7 +1318,7 @@ var History = class {
1280
1318
  } catch {
1281
1319
  return {
1282
1320
  ...page2,
1283
- props: cloneDeep2(page2.props)
1321
+ props: cloneDeep3(page2.props)
1284
1322
  };
1285
1323
  }
1286
1324
  }
@@ -2231,7 +2269,6 @@ var Response = class _Response {
2231
2269
  }
2232
2270
  await history.processQueue();
2233
2271
  history.preserveUrl = this.requestParams.all().preserveUrl;
2234
- const previousFlash = page.get().flash;
2235
2272
  await this.setPage();
2236
2273
  const errors = page.get().props.errors || {};
2237
2274
  if (Object.keys(errors).length > 0) {
@@ -2244,7 +2281,7 @@ var Response = class _Response {
2244
2281
  router.flush(page.get().url);
2245
2282
  }
2246
2283
  const { flash } = page.get();
2247
- if (Object.keys(flash).length > 0 && (!this.requestParams.isPartial() || !isEqual2(flash, previousFlash))) {
2284
+ if (Object.keys(flash).length > 0 && !this.requestParams.isDeferredPropsRequest()) {
2248
2285
  fireFlashEvent(flash);
2249
2286
  this.requestParams.all().onFlash(flash);
2250
2287
  }
@@ -2383,16 +2420,15 @@ var Response = class _Response {
2383
2420
  return responseUrl.pathname + responseUrl.search + responseUrl.hash;
2384
2421
  }
2385
2422
  preserveOptimisticProps(pageResponse) {
2386
- const optimisticUpdatedAt = page.get().optimisticUpdatedAt;
2387
- if (!optimisticUpdatedAt || !router.hasPendingOptimistic()) {
2423
+ if (!router.hasPendingOptimistic()) {
2388
2424
  return;
2389
2425
  }
2390
2426
  for (const key of Object.keys(pageResponse.props)) {
2391
- if (key in optimisticUpdatedAt) {
2427
+ if (page.hasBaseline(key)) {
2428
+ page.updateBaseline(key, pageResponse.props[key]);
2392
2429
  pageResponse.props[key] = page.get().props[key];
2393
2430
  }
2394
2431
  }
2395
- pageResponse.optimisticUpdatedAt = { ...optimisticUpdatedAt };
2396
2432
  }
2397
2433
  preserveEqualProps(pageResponse) {
2398
2434
  if (pageResponse.component !== page.get().component) {
@@ -2715,7 +2751,7 @@ var RequestStream = class {
2715
2751
  }
2716
2752
  send(request) {
2717
2753
  this.requests.push(request);
2718
- request.send().then(() => {
2754
+ request.send().finally(() => {
2719
2755
  this.requests = this.requests.filter((r) => r !== request);
2720
2756
  });
2721
2757
  }
@@ -3004,7 +3040,7 @@ var Router = class {
3004
3040
  preserveState: true,
3005
3041
  props(currentProps) {
3006
3042
  const newValue = typeof value === "function" ? value(get7(currentProps, name), currentProps) : value;
3007
- return set5(cloneDeep3(currentProps), name, newValue);
3043
+ return set5(cloneDeep4(currentProps), name, newValue);
3008
3044
  },
3009
3045
  ...options || {}
3010
3046
  });
@@ -3102,7 +3138,7 @@ var Router = class {
3102
3138
  const sharedProps = Object.fromEntries(
3103
3139
  (current.sharedProps ?? []).filter((key) => key in current.props).map((key) => [key, current.props[key]])
3104
3140
  );
3105
- const resolvedPageProps = typeof visit.pageProps === "function" ? visit.pageProps(cloneDeep3(current.props), cloneDeep3(sharedProps)) : visit.pageProps;
3141
+ const resolvedPageProps = typeof visit.pageProps === "function" ? visit.pageProps(cloneDeep4(current.props), cloneDeep4(sharedProps)) : visit.pageProps;
3106
3142
  const intermediateProps = resolvedPageProps !== null ? { ...resolvedPageProps } : { ...sharedProps };
3107
3143
  const intermediatePage = {
3108
3144
  component: visit.component,
@@ -3144,7 +3180,7 @@ var Router = class {
3144
3180
  options.method = options.method ?? urlMethodPair.method;
3145
3181
  }
3146
3182
  const defaultVisitOptionsCallback = config.get("visitOptions");
3147
- const configuredOptions = defaultVisitOptionsCallback ? defaultVisitOptionsCallback(href.toString(), cloneDeep3(options)) || {} : {};
3183
+ const configuredOptions = defaultVisitOptionsCallback ? defaultVisitOptionsCallback(href.toString(), cloneDeep4(options)) || {} : {};
3148
3184
  const mergedOptions = {
3149
3185
  method: "get",
3150
3186
  data: {},
@@ -3211,21 +3247,25 @@ var Router = class {
3211
3247
  }
3212
3248
  applyOptimisticUpdate(optimistic, events) {
3213
3249
  const currentProps = page.get().props;
3214
- const optimisticProps = optimistic(cloneDeep3(currentProps));
3250
+ const optimisticProps = optimistic(cloneDeep4(currentProps));
3215
3251
  if (!optimisticProps) {
3216
3252
  return;
3217
3253
  }
3218
- const propsSnapshot = {};
3254
+ const changedKeys = [];
3219
3255
  for (const key of Object.keys(optimisticProps)) {
3220
3256
  if (!isEqual3(currentProps[key], optimisticProps[key])) {
3221
- propsSnapshot[key] = cloneDeep3(currentProps[key]);
3257
+ changedKeys.push(key);
3222
3258
  }
3223
3259
  }
3224
- if (Object.keys(propsSnapshot).length === 0) {
3260
+ if (changedKeys.length === 0) {
3225
3261
  return;
3226
3262
  }
3227
- const updatedAt = Date.now();
3228
- page.recordOptimisticUpdate(Object.keys(propsSnapshot), updatedAt);
3263
+ const id = page.nextOptimisticId();
3264
+ const component = page.get().component;
3265
+ for (const key of changedKeys) {
3266
+ page.setBaseline(key, cloneDeep4(currentProps[key]));
3267
+ }
3268
+ page.registerOptimistic(id, optimistic);
3229
3269
  page.setPropsQuietly({ ...currentProps, ...optimisticProps });
3230
3270
  let shouldRestore = true;
3231
3271
  const originalOnSuccess = events.onSuccess;
@@ -3235,17 +3275,16 @@ var Router = class {
3235
3275
  };
3236
3276
  const originalOnFinish = events.onFinish;
3237
3277
  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 });
3278
+ page.unregisterOptimistic(id);
3279
+ if (shouldRestore && page.get().component === component) {
3280
+ const replayedProps = page.replayOptimistics();
3281
+ if (Object.keys(replayedProps).length > 0) {
3282
+ page.setPropsQuietly({ ...page.get().props, ...replayedProps });
3247
3283
  }
3248
3284
  }
3285
+ if (page.pendingOptimisticCount() === 0) {
3286
+ page.clearOptimisticState();
3287
+ }
3249
3288
  return originalOnFinish(visit);
3250
3289
  };
3251
3290
  }