@inertiajs/core 2.2.18 → 2.2.20

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
@@ -33,6 +33,7 @@ __export(index_exports, {
33
33
  config: () => config,
34
34
  createHeadManager: () => createHeadManager,
35
35
  formDataToObject: () => formDataToObject,
36
+ getInitialPageFromDOM: () => getInitialPageFromDOM,
36
37
  getScrollableParent: () => getScrollableParent,
37
38
  hideProgress: () => hide2,
38
39
  hrefToUrl: () => hrefToUrl,
@@ -93,7 +94,8 @@ var config = new Config({
93
94
  future: {
94
95
  preserveEqualProps: false,
95
96
  useDataInertiaHeadAttribute: false,
96
- useDialogForErrorModal: false
97
+ useDialogForErrorModal: false,
98
+ useScriptElementForInitialPage: false
97
99
  },
98
100
  prefetch: {
99
101
  cacheFor: 3e4,
@@ -152,7 +154,7 @@ var firePrefetchingEvent = (visit) => {
152
154
  };
153
155
 
154
156
  // src/history.ts
155
- var import_lodash_es2 = require("lodash-es");
157
+ var import_lodash_es3 = require("lodash-es");
156
158
 
157
159
  // src/sessionStorage.ts
158
160
  var SessionStorage = class {
@@ -323,228 +325,526 @@ var getKeyFromSessionStorage = async () => {
323
325
  return key;
324
326
  };
325
327
 
326
- // src/scroll.ts
327
- var Scroll = class {
328
- static save() {
329
- history.saveScrollPositions(
330
- Array.from(this.regions()).map((region) => ({
331
- top: region.scrollTop,
332
- left: region.scrollLeft
333
- }))
334
- );
335
- }
336
- static regions() {
337
- return document.querySelectorAll("[scroll-region]");
328
+ // src/prefetched.ts
329
+ var import_lodash_es2 = require("lodash-es");
330
+
331
+ // src/objectUtils.ts
332
+ var objectsAreEqual = (obj1, obj2, excludeKeys) => {
333
+ if (obj1 === obj2) {
334
+ return true;
338
335
  }
339
- static reset() {
340
- const anchorHash = typeof window !== "undefined" ? window.location.hash : null;
341
- if (!anchorHash) {
342
- window.scrollTo(0, 0);
336
+ for (const key in obj1) {
337
+ if (excludeKeys.includes(key)) {
338
+ continue;
343
339
  }
344
- this.regions().forEach((region) => {
345
- if (typeof region.scrollTo === "function") {
346
- region.scrollTo(0, 0);
347
- } else {
348
- region.scrollTop = 0;
349
- region.scrollLeft = 0;
350
- }
351
- });
352
- this.save();
353
- if (anchorHash) {
354
- setTimeout(() => {
355
- const anchorElement = document.getElementById(anchorHash.slice(1));
356
- anchorElement ? anchorElement.scrollIntoView() : window.scrollTo(0, 0);
357
- });
340
+ if (obj1[key] === obj2[key]) {
341
+ continue;
358
342
  }
359
- }
360
- static restore(scrollRegions) {
361
- if (typeof window === "undefined") {
362
- return;
343
+ if (!compareValues(obj1[key], obj2[key])) {
344
+ return false;
363
345
  }
364
- window.requestAnimationFrame(() => {
365
- this.restoreDocument();
366
- this.restoreScrollRegions(scrollRegions);
367
- });
368
346
  }
369
- static restoreScrollRegions(scrollRegions) {
370
- if (typeof window === "undefined") {
371
- return;
347
+ for (const key in obj2) {
348
+ if (excludeKeys.includes(key)) {
349
+ continue;
372
350
  }
373
- this.regions().forEach((region, index) => {
374
- const scrollPosition = scrollRegions[index];
375
- if (!scrollPosition) {
376
- return;
377
- }
378
- if (typeof region.scrollTo === "function") {
379
- region.scrollTo(scrollPosition.left, scrollPosition.top);
380
- } else {
381
- region.scrollTop = scrollPosition.top;
382
- region.scrollLeft = scrollPosition.left;
383
- }
384
- });
385
- }
386
- static restoreDocument() {
387
- const scrollPosition = history.getDocumentScrollPosition();
388
- window.scrollTo(scrollPosition.left, scrollPosition.top);
389
- }
390
- static onScroll(event) {
391
- const target = event.target;
392
- if (typeof target.hasAttribute === "function" && target.hasAttribute("scroll-region")) {
393
- this.save();
351
+ if (!(key in obj1)) {
352
+ return false;
394
353
  }
395
354
  }
396
- static onWindowScroll() {
397
- history.saveDocumentScrollPosition({
398
- top: window.scrollY,
399
- left: window.scrollX
400
- });
401
- }
355
+ return true;
402
356
  };
403
-
404
- // src/url.ts
405
- var qs = __toESM(require("qs"), 1);
406
-
407
- // src/files.ts
408
- var isFile = (value) => typeof File !== "undefined" && value instanceof File || value instanceof Blob || typeof FileList !== "undefined" && value instanceof FileList && value.length > 0;
409
- function hasFiles(data) {
410
- return isFile(data) || data instanceof FormData && Array.from(data.values()).some((value) => hasFiles(value)) || typeof data === "object" && data !== null && Object.values(data).some((value) => hasFiles(value));
411
- }
412
-
413
- // src/formData.ts
414
- var isFormData = (value) => value instanceof FormData;
415
- function objectToFormData(source, form = new FormData(), parentKey = null, queryStringArrayFormat = "brackets") {
416
- source = source || {};
417
- for (const key in source) {
418
- if (Object.prototype.hasOwnProperty.call(source, key)) {
419
- append(form, composeKey(parentKey, key, "indices"), source[key], queryStringArrayFormat);
420
- }
421
- }
422
- return form;
423
- }
424
- function composeKey(parent, key, format) {
425
- if (!parent) {
426
- return key;
427
- }
428
- return format === "brackets" ? `${parent}[]` : `${parent}[${key}]`;
429
- }
430
- function append(form, key, value, format) {
431
- if (Array.isArray(value)) {
432
- return Array.from(value.keys()).forEach(
433
- (index) => append(form, composeKey(key, index.toString(), format), value[index], format)
434
- );
435
- } else if (value instanceof Date) {
436
- return form.append(key, value.toISOString());
437
- } else if (value instanceof File) {
438
- return form.append(key, value, value.name);
439
- } else if (value instanceof Blob) {
440
- return form.append(key, value);
441
- } else if (typeof value === "boolean") {
442
- return form.append(key, value ? "1" : "0");
443
- } else if (typeof value === "string") {
444
- return form.append(key, value);
445
- } else if (typeof value === "number") {
446
- return form.append(key, `${value}`);
447
- } else if (value === null || value === void 0) {
448
- return form.append(key, "");
357
+ var compareValues = (value1, value2) => {
358
+ switch (typeof value1) {
359
+ case "object":
360
+ return objectsAreEqual(value1, value2, []);
361
+ case "function":
362
+ return value1.toString() === value2.toString();
363
+ default:
364
+ return value1 === value2;
449
365
  }
450
- objectToFormData(value, form, key, format);
451
- }
366
+ };
452
367
 
453
- // src/url.ts
454
- function hrefToUrl(href) {
455
- return new URL(href.toString(), typeof window === "undefined" ? void 0 : window.location.toString());
456
- }
457
- var transformUrlAndData = (href, data, method, forceFormData, queryStringArrayFormat) => {
458
- let url = typeof href === "string" ? hrefToUrl(href) : href;
459
- if ((hasFiles(data) || forceFormData) && !isFormData(data)) {
460
- if (config.get("form.forceIndicesArrayFormatInFormData")) {
461
- queryStringArrayFormat = "indices";
462
- }
463
- data = objectToFormData(data, new FormData(), null, queryStringArrayFormat);
464
- }
465
- if (isFormData(data)) {
466
- return [url, data];
467
- }
468
- const [_href, _data] = mergeDataIntoQueryString(method, url, data, queryStringArrayFormat);
469
- return [hrefToUrl(_href), _data];
368
+ // src/time.ts
369
+ var conversionMap = {
370
+ ms: 1,
371
+ s: 1e3,
372
+ m: 1e3 * 60,
373
+ h: 1e3 * 60 * 60,
374
+ d: 1e3 * 60 * 60 * 24
470
375
  };
471
- function mergeDataIntoQueryString(method, href, data, qsArrayFormat = "brackets") {
472
- const hasDataForQueryString = method === "get" && !isFormData(data) && Object.keys(data).length > 0;
473
- const hasHost = urlHasProtocol(href.toString());
474
- const hasAbsolutePath = hasHost || href.toString().startsWith("/") || href.toString() === "";
475
- const hasRelativePath = !hasAbsolutePath && !href.toString().startsWith("#") && !href.toString().startsWith("?");
476
- const hasRelativePathWithDotPrefix = /^[.]{1,2}([/]|$)/.test(href.toString());
477
- const hasSearch = href.toString().includes("?") || hasDataForQueryString;
478
- const hasHash = href.toString().includes("#");
479
- const url = new URL(href.toString(), typeof window === "undefined" ? "http://localhost" : window.location.toString());
480
- if (hasDataForQueryString) {
481
- const parseOptions = { ignoreQueryPrefix: true, parseArrays: false };
482
- url.search = qs.stringify(
483
- { ...qs.parse(url.search, parseOptions), ...data },
484
- {
485
- encodeValuesOnly: true,
486
- arrayFormat: qsArrayFormat
487
- }
488
- );
376
+ var timeToMs = (time) => {
377
+ if (typeof time === "number") {
378
+ return time;
489
379
  }
490
- return [
491
- [
492
- hasHost ? `${url.protocol}//${url.host}` : "",
493
- hasAbsolutePath ? url.pathname : "",
494
- hasRelativePath ? url.pathname.substring(hasRelativePathWithDotPrefix ? 0 : 1) : "",
495
- hasSearch ? url.search : "",
496
- hasHash ? url.hash : ""
497
- ].join(""),
498
- hasDataForQueryString ? {} : data
499
- ];
500
- }
501
- function urlWithoutHash(url) {
502
- url = new URL(url.href);
503
- url.hash = "";
504
- return url;
505
- }
506
- var setHashIfSameUrl = (originUrl, destinationUrl) => {
507
- if (originUrl.hash && !destinationUrl.hash && urlWithoutHash(originUrl).href === destinationUrl.href) {
508
- destinationUrl.hash = originUrl.hash;
380
+ for (const [unit, conversion] of Object.entries(conversionMap)) {
381
+ if (time.endsWith(unit)) {
382
+ return parseFloat(time) * conversion;
383
+ }
509
384
  }
385
+ return parseInt(time);
510
386
  };
511
- var isSameUrlWithoutHash = (url1, url2) => {
512
- return urlWithoutHash(url1).href === urlWithoutHash(url2).href;
513
- };
514
- function isUrlMethodPair(href) {
515
- return href !== null && typeof href === "object" && href !== void 0 && "url" in href && "method" in href;
516
- }
517
- function urlHasProtocol(url) {
518
- return /^[a-z][a-z0-9+.-]*:\/\//i.test(url);
519
- }
520
- function urlToString(url, absolute) {
521
- const urlObj = typeof url === "string" ? hrefToUrl(url) : url;
522
- return absolute ? `${urlObj.protocol}//${urlObj.host}${urlObj.pathname}${urlObj.search}${urlObj.hash}` : `${urlObj.pathname}${urlObj.search}${urlObj.hash}`;
523
- }
524
387
 
525
- // src/page.ts
526
- var CurrentPage = class {
388
+ // src/prefetched.ts
389
+ var PrefetchedRequests = class {
527
390
  constructor() {
528
- this.componentId = {};
529
- this.listeners = [];
530
- this.isFirstPageLoad = true;
531
- this.cleared = false;
532
- this.pendingDeferredProps = null;
533
- }
534
- init({
535
- initialPage,
536
- swapComponent,
537
- resolveComponent
538
- }) {
539
- this.page = initialPage;
540
- this.swapComponent = swapComponent;
541
- this.resolveComponent = resolveComponent;
542
- return this;
391
+ this.cached = [];
392
+ this.inFlightRequests = [];
393
+ this.removalTimers = [];
394
+ this.currentUseId = null;
543
395
  }
544
- set(page2, {
545
- replace = false,
546
- preserveScroll = false,
547
- preserveState = false,
396
+ add(params, sendFunc, { cacheFor, cacheTags }) {
397
+ const inFlight = this.findInFlight(params);
398
+ if (inFlight) {
399
+ return Promise.resolve();
400
+ }
401
+ const existing = this.findCached(params);
402
+ if (!params.fresh && existing && existing.staleTimestamp > Date.now()) {
403
+ return Promise.resolve();
404
+ }
405
+ const [stale, prefetchExpiresIn] = this.extractStaleValues(cacheFor);
406
+ const promise = new Promise((resolve, reject) => {
407
+ sendFunc({
408
+ ...params,
409
+ onCancel: () => {
410
+ this.remove(params);
411
+ params.onCancel();
412
+ reject();
413
+ },
414
+ onError: (error) => {
415
+ this.remove(params);
416
+ params.onError(error);
417
+ reject();
418
+ },
419
+ onPrefetching(visitParams) {
420
+ params.onPrefetching(visitParams);
421
+ },
422
+ onPrefetched(response, visit) {
423
+ params.onPrefetched(response, visit);
424
+ },
425
+ onPrefetchResponse(response) {
426
+ resolve(response);
427
+ },
428
+ onPrefetchError(error) {
429
+ prefetchedRequests.removeFromInFlight(params);
430
+ reject(error);
431
+ }
432
+ });
433
+ }).then((response) => {
434
+ this.remove(params);
435
+ const pageResponse = response.getPageResponse();
436
+ page.mergeOncePropsIntoResponse(pageResponse);
437
+ this.cached.push({
438
+ params: { ...params },
439
+ staleTimestamp: Date.now() + stale,
440
+ expiresAt: Date.now() + prefetchExpiresIn,
441
+ response: promise,
442
+ singleUse: prefetchExpiresIn === 0,
443
+ timestamp: Date.now(),
444
+ inFlight: false,
445
+ tags: Array.isArray(cacheTags) ? cacheTags : [cacheTags]
446
+ });
447
+ const oncePropExpiresIn = this.getShortestOncePropTtl(pageResponse);
448
+ this.scheduleForRemoval(
449
+ params,
450
+ oncePropExpiresIn ? Math.min(prefetchExpiresIn, oncePropExpiresIn) : prefetchExpiresIn
451
+ );
452
+ this.removeFromInFlight(params);
453
+ response.handlePrefetch();
454
+ return response;
455
+ });
456
+ this.inFlightRequests.push({
457
+ params: { ...params },
458
+ response: promise,
459
+ staleTimestamp: null,
460
+ inFlight: true
461
+ });
462
+ return promise;
463
+ }
464
+ removeAll() {
465
+ this.cached = [];
466
+ this.removalTimers.forEach((removalTimer) => {
467
+ clearTimeout(removalTimer.timer);
468
+ });
469
+ this.removalTimers = [];
470
+ }
471
+ removeByTags(tags) {
472
+ this.cached = this.cached.filter((prefetched) => {
473
+ return !prefetched.tags.some((tag) => tags.includes(tag));
474
+ });
475
+ }
476
+ remove(params) {
477
+ this.cached = this.cached.filter((prefetched) => {
478
+ return !this.paramsAreEqual(prefetched.params, params);
479
+ });
480
+ this.clearTimer(params);
481
+ }
482
+ removeFromInFlight(params) {
483
+ this.inFlightRequests = this.inFlightRequests.filter((prefetching) => {
484
+ return !this.paramsAreEqual(prefetching.params, params);
485
+ });
486
+ }
487
+ extractStaleValues(cacheFor) {
488
+ const [stale, expires] = this.cacheForToStaleAndExpires(cacheFor);
489
+ return [timeToMs(stale), timeToMs(expires)];
490
+ }
491
+ cacheForToStaleAndExpires(cacheFor) {
492
+ if (!Array.isArray(cacheFor)) {
493
+ return [cacheFor, cacheFor];
494
+ }
495
+ switch (cacheFor.length) {
496
+ case 0:
497
+ return [0, 0];
498
+ case 1:
499
+ return [cacheFor[0], cacheFor[0]];
500
+ default:
501
+ return [cacheFor[0], cacheFor[1]];
502
+ }
503
+ }
504
+ clearTimer(params) {
505
+ const timer = this.removalTimers.find((removalTimer) => {
506
+ return this.paramsAreEqual(removalTimer.params, params);
507
+ });
508
+ if (timer) {
509
+ clearTimeout(timer.timer);
510
+ this.removalTimers = this.removalTimers.filter((removalTimer) => removalTimer !== timer);
511
+ }
512
+ }
513
+ scheduleForRemoval(params, expiresIn) {
514
+ if (typeof window === "undefined") {
515
+ return;
516
+ }
517
+ this.clearTimer(params);
518
+ if (expiresIn > 0) {
519
+ const timer = window.setTimeout(() => this.remove(params), expiresIn);
520
+ this.removalTimers.push({
521
+ params,
522
+ timer
523
+ });
524
+ }
525
+ }
526
+ get(params) {
527
+ return this.findCached(params) || this.findInFlight(params);
528
+ }
529
+ use(prefetched, params) {
530
+ const id = `${params.url.pathname}-${Date.now()}-${Math.random().toString(36).substring(7)}`;
531
+ this.currentUseId = id;
532
+ return prefetched.response.then((response) => {
533
+ if (this.currentUseId !== id) {
534
+ return;
535
+ }
536
+ response.mergeParams({ ...params, onPrefetched: () => {
537
+ } });
538
+ this.removeSingleUseItems(params);
539
+ return response.handle();
540
+ });
541
+ }
542
+ removeSingleUseItems(params) {
543
+ this.cached = this.cached.filter((prefetched) => {
544
+ if (!this.paramsAreEqual(prefetched.params, params)) {
545
+ return true;
546
+ }
547
+ return !prefetched.singleUse;
548
+ });
549
+ }
550
+ findCached(params) {
551
+ return this.cached.find((prefetched) => {
552
+ return this.paramsAreEqual(prefetched.params, params);
553
+ }) || null;
554
+ }
555
+ findInFlight(params) {
556
+ return this.inFlightRequests.find((prefetched) => {
557
+ return this.paramsAreEqual(prefetched.params, params);
558
+ }) || null;
559
+ }
560
+ withoutPurposePrefetchHeader(params) {
561
+ const newParams = (0, import_lodash_es2.cloneDeep)(params);
562
+ if (newParams.headers["Purpose"] === "prefetch") {
563
+ delete newParams.headers["Purpose"];
564
+ }
565
+ return newParams;
566
+ }
567
+ paramsAreEqual(params1, params2) {
568
+ return objectsAreEqual(
569
+ this.withoutPurposePrefetchHeader(params1),
570
+ this.withoutPurposePrefetchHeader(params2),
571
+ [
572
+ "showProgress",
573
+ "replace",
574
+ "prefetch",
575
+ "preserveScroll",
576
+ "preserveState",
577
+ "onBefore",
578
+ "onBeforeUpdate",
579
+ "onStart",
580
+ "onProgress",
581
+ "onFinish",
582
+ "onCancel",
583
+ "onSuccess",
584
+ "onError",
585
+ "onPrefetched",
586
+ "onCancelToken",
587
+ "onPrefetching",
588
+ "async",
589
+ "viewTransition"
590
+ ]
591
+ );
592
+ }
593
+ updateCachedOncePropsFromCurrentPage() {
594
+ this.cached.forEach((prefetched) => {
595
+ prefetched.response.then((response) => {
596
+ const pageResponse = response.getPageResponse();
597
+ page.mergeOncePropsIntoResponse(pageResponse, { force: true });
598
+ const oncePropExpiresIn = this.getShortestOncePropTtl(pageResponse);
599
+ if (oncePropExpiresIn === null) {
600
+ return;
601
+ }
602
+ const prefetchExpiresIn = prefetched.expiresAt - Date.now();
603
+ const expiresIn = Math.min(prefetchExpiresIn, oncePropExpiresIn);
604
+ if (expiresIn > 0) {
605
+ this.scheduleForRemoval(prefetched.params, expiresIn);
606
+ } else {
607
+ this.remove(prefetched.params);
608
+ }
609
+ });
610
+ });
611
+ }
612
+ getShortestOncePropTtl(page2) {
613
+ const expiryTimestamps = Object.values(page2.onceProps ?? {}).map((onceProp) => onceProp.expiresAt).filter((expiresAt) => !!expiresAt);
614
+ if (expiryTimestamps.length === 0) {
615
+ return null;
616
+ }
617
+ return Math.min(...expiryTimestamps) - Date.now();
618
+ }
619
+ };
620
+ var prefetchedRequests = new PrefetchedRequests();
621
+
622
+ // src/scroll.ts
623
+ var Scroll = class {
624
+ static save() {
625
+ history.saveScrollPositions(
626
+ Array.from(this.regions()).map((region) => ({
627
+ top: region.scrollTop,
628
+ left: region.scrollLeft
629
+ }))
630
+ );
631
+ }
632
+ static regions() {
633
+ return document.querySelectorAll("[scroll-region]");
634
+ }
635
+ static reset() {
636
+ const anchorHash = typeof window !== "undefined" ? window.location.hash : null;
637
+ if (!anchorHash) {
638
+ window.scrollTo(0, 0);
639
+ }
640
+ this.regions().forEach((region) => {
641
+ if (typeof region.scrollTo === "function") {
642
+ region.scrollTo(0, 0);
643
+ } else {
644
+ region.scrollTop = 0;
645
+ region.scrollLeft = 0;
646
+ }
647
+ });
648
+ this.save();
649
+ this.scrollToAnchor();
650
+ }
651
+ static scrollToAnchor() {
652
+ const anchorHash = typeof window !== "undefined" ? window.location.hash : null;
653
+ if (anchorHash) {
654
+ setTimeout(() => {
655
+ const anchorElement = document.getElementById(anchorHash.slice(1));
656
+ anchorElement ? anchorElement.scrollIntoView() : window.scrollTo(0, 0);
657
+ });
658
+ }
659
+ }
660
+ static restore(scrollRegions) {
661
+ if (typeof window === "undefined") {
662
+ return;
663
+ }
664
+ window.requestAnimationFrame(() => {
665
+ this.restoreDocument();
666
+ this.restoreScrollRegions(scrollRegions);
667
+ });
668
+ }
669
+ static restoreScrollRegions(scrollRegions) {
670
+ if (typeof window === "undefined") {
671
+ return;
672
+ }
673
+ this.regions().forEach((region, index) => {
674
+ const scrollPosition = scrollRegions[index];
675
+ if (!scrollPosition) {
676
+ return;
677
+ }
678
+ if (typeof region.scrollTo === "function") {
679
+ region.scrollTo(scrollPosition.left, scrollPosition.top);
680
+ } else {
681
+ region.scrollTop = scrollPosition.top;
682
+ region.scrollLeft = scrollPosition.left;
683
+ }
684
+ });
685
+ }
686
+ static restoreDocument() {
687
+ const scrollPosition = history.getDocumentScrollPosition();
688
+ window.scrollTo(scrollPosition.left, scrollPosition.top);
689
+ }
690
+ static onScroll(event) {
691
+ const target = event.target;
692
+ if (typeof target.hasAttribute === "function" && target.hasAttribute("scroll-region")) {
693
+ this.save();
694
+ }
695
+ }
696
+ static onWindowScroll() {
697
+ history.saveDocumentScrollPosition({
698
+ top: window.scrollY,
699
+ left: window.scrollX
700
+ });
701
+ }
702
+ };
703
+
704
+ // src/url.ts
705
+ var qs = __toESM(require("qs"), 1);
706
+
707
+ // src/files.ts
708
+ var isFile = (value) => typeof File !== "undefined" && value instanceof File || value instanceof Blob || typeof FileList !== "undefined" && value instanceof FileList && value.length > 0;
709
+ function hasFiles(data) {
710
+ return isFile(data) || data instanceof FormData && Array.from(data.values()).some((value) => hasFiles(value)) || typeof data === "object" && data !== null && Object.values(data).some((value) => hasFiles(value));
711
+ }
712
+
713
+ // src/formData.ts
714
+ var isFormData = (value) => value instanceof FormData;
715
+ function objectToFormData(source, form = new FormData(), parentKey = null, queryStringArrayFormat = "brackets") {
716
+ source = source || {};
717
+ for (const key in source) {
718
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
719
+ append(form, composeKey(parentKey, key, "indices"), source[key], queryStringArrayFormat);
720
+ }
721
+ }
722
+ return form;
723
+ }
724
+ function composeKey(parent, key, format) {
725
+ if (!parent) {
726
+ return key;
727
+ }
728
+ return format === "brackets" ? `${parent}[]` : `${parent}[${key}]`;
729
+ }
730
+ function append(form, key, value, format) {
731
+ if (Array.isArray(value)) {
732
+ return Array.from(value.keys()).forEach(
733
+ (index) => append(form, composeKey(key, index.toString(), format), value[index], format)
734
+ );
735
+ } else if (value instanceof Date) {
736
+ return form.append(key, value.toISOString());
737
+ } else if (value instanceof File) {
738
+ return form.append(key, value, value.name);
739
+ } else if (value instanceof Blob) {
740
+ return form.append(key, value);
741
+ } else if (typeof value === "boolean") {
742
+ return form.append(key, value ? "1" : "0");
743
+ } else if (typeof value === "string") {
744
+ return form.append(key, value);
745
+ } else if (typeof value === "number") {
746
+ return form.append(key, `${value}`);
747
+ } else if (value === null || value === void 0) {
748
+ return form.append(key, "");
749
+ }
750
+ objectToFormData(value, form, key, format);
751
+ }
752
+
753
+ // src/url.ts
754
+ function hrefToUrl(href) {
755
+ return new URL(href.toString(), typeof window === "undefined" ? void 0 : window.location.toString());
756
+ }
757
+ var transformUrlAndData = (href, data, method, forceFormData, queryStringArrayFormat) => {
758
+ let url = typeof href === "string" ? hrefToUrl(href) : href;
759
+ if ((hasFiles(data) || forceFormData) && !isFormData(data)) {
760
+ if (config.get("form.forceIndicesArrayFormatInFormData")) {
761
+ queryStringArrayFormat = "indices";
762
+ }
763
+ data = objectToFormData(data, new FormData(), null, queryStringArrayFormat);
764
+ }
765
+ if (isFormData(data)) {
766
+ return [url, data];
767
+ }
768
+ const [_href, _data] = mergeDataIntoQueryString(method, url, data, queryStringArrayFormat);
769
+ return [hrefToUrl(_href), _data];
770
+ };
771
+ function mergeDataIntoQueryString(method, href, data, qsArrayFormat = "brackets") {
772
+ const hasDataForQueryString = method === "get" && !isFormData(data) && Object.keys(data).length > 0;
773
+ const hasHost = urlHasProtocol(href.toString());
774
+ const hasAbsolutePath = hasHost || href.toString().startsWith("/") || href.toString() === "";
775
+ const hasRelativePath = !hasAbsolutePath && !href.toString().startsWith("#") && !href.toString().startsWith("?");
776
+ const hasRelativePathWithDotPrefix = /^[.]{1,2}([/]|$)/.test(href.toString());
777
+ const hasSearch = href.toString().includes("?") || hasDataForQueryString;
778
+ const hasHash = href.toString().includes("#");
779
+ const url = new URL(href.toString(), typeof window === "undefined" ? "http://localhost" : window.location.toString());
780
+ if (hasDataForQueryString) {
781
+ const parseOptions = { ignoreQueryPrefix: true, parseArrays: false };
782
+ url.search = qs.stringify(
783
+ { ...qs.parse(url.search, parseOptions), ...data },
784
+ {
785
+ encodeValuesOnly: true,
786
+ arrayFormat: qsArrayFormat
787
+ }
788
+ );
789
+ }
790
+ return [
791
+ [
792
+ hasHost ? `${url.protocol}//${url.host}` : "",
793
+ hasAbsolutePath ? url.pathname : "",
794
+ hasRelativePath ? url.pathname.substring(hasRelativePathWithDotPrefix ? 0 : 1) : "",
795
+ hasSearch ? url.search : "",
796
+ hasHash ? url.hash : ""
797
+ ].join(""),
798
+ hasDataForQueryString ? {} : data
799
+ ];
800
+ }
801
+ function urlWithoutHash(url) {
802
+ url = new URL(url.href);
803
+ url.hash = "";
804
+ return url;
805
+ }
806
+ var setHashIfSameUrl = (originUrl, destinationUrl) => {
807
+ if (originUrl.hash && !destinationUrl.hash && urlWithoutHash(originUrl).href === destinationUrl.href) {
808
+ destinationUrl.hash = originUrl.hash;
809
+ }
810
+ };
811
+ var isSameUrlWithoutHash = (url1, url2) => {
812
+ return urlWithoutHash(url1).href === urlWithoutHash(url2).href;
813
+ };
814
+ function isUrlMethodPair(href) {
815
+ return href !== null && typeof href === "object" && href !== void 0 && "url" in href && "method" in href;
816
+ }
817
+ function urlHasProtocol(url) {
818
+ return /^[a-z][a-z0-9+.-]*:\/\//i.test(url);
819
+ }
820
+ function urlToString(url, absolute) {
821
+ const urlObj = typeof url === "string" ? hrefToUrl(url) : url;
822
+ return absolute ? `${urlObj.protocol}//${urlObj.host}${urlObj.pathname}${urlObj.search}${urlObj.hash}` : `${urlObj.pathname}${urlObj.search}${urlObj.hash}`;
823
+ }
824
+
825
+ // src/page.ts
826
+ var CurrentPage = class {
827
+ constructor() {
828
+ this.componentId = {};
829
+ this.listeners = [];
830
+ this.isFirstPageLoad = true;
831
+ this.cleared = false;
832
+ this.pendingDeferredProps = null;
833
+ }
834
+ init({
835
+ initialPage,
836
+ swapComponent,
837
+ resolveComponent
838
+ }) {
839
+ this.page = initialPage;
840
+ this.swapComponent = swapComponent;
841
+ this.resolveComponent = resolveComponent;
842
+ return this;
843
+ }
844
+ set(page2, {
845
+ replace = false,
846
+ preserveScroll = false,
847
+ preserveState = false,
548
848
  viewTransition = false
549
849
  } = {}) {
550
850
  if (Object.keys(page2.deferredProps || {}).length) {
@@ -577,6 +877,9 @@ var CurrentPage = class {
577
877
  }
578
878
  this.page = page2;
579
879
  this.cleared = false;
880
+ if (this.hasOnceProps()) {
881
+ prefetchedRequests.updateCachedOncePropsFromCurrentPage();
882
+ }
580
883
  if (isNewComponent) {
581
884
  this.fireEventsFor("newComponent");
582
885
  }
@@ -625,6 +928,9 @@ var CurrentPage = class {
625
928
  get() {
626
929
  return this.page;
627
930
  }
931
+ hasOnceProps() {
932
+ return Object.keys(this.page.onceProps ?? {}).length > 0;
933
+ }
628
934
  merge(data) {
629
935
  this.page = { ...this.page, ...data };
630
936
  }
@@ -667,6 +973,18 @@ var CurrentPage = class {
667
973
  fireEventsFor(event) {
668
974
  this.listeners.filter((listener) => listener.event === event).forEach((listener) => listener.callback());
669
975
  }
976
+ mergeOncePropsIntoResponse(response, { force = false } = {}) {
977
+ Object.entries(response.onceProps ?? {}).forEach(([key, onceProp]) => {
978
+ const existingOnceProp = this.page.onceProps?.[key];
979
+ if (existingOnceProp === void 0) {
980
+ return;
981
+ }
982
+ if (force || response.props[onceProp.prop] === void 0) {
983
+ response.props[onceProp.prop] = this.page.props[existingOnceProp.prop];
984
+ response.onceProps[key].expiresAt = existingOnceProp.expiresAt;
985
+ }
986
+ });
987
+ }
670
988
  };
671
989
  var page = new CurrentPage();
672
990
 
@@ -750,7 +1068,7 @@ var History = class {
750
1068
  } catch {
751
1069
  return {
752
1070
  ...page2,
753
- props: (0, import_lodash_es2.cloneDeep)(page2.props)
1071
+ props: (0, import_lodash_es3.cloneDeep)(page2.props)
754
1072
  };
755
1073
  }
756
1074
  }
@@ -789,7 +1107,7 @@ var History = class {
789
1107
  if (!window.history.state?.page) {
790
1108
  return;
791
1109
  }
792
- if ((0, import_lodash_es2.isEqual)(this.getScrollRegions(), scrollRegions)) {
1110
+ if ((0, import_lodash_es3.isEqual)(this.getScrollRegions(), scrollRegions)) {
793
1111
  return;
794
1112
  }
795
1113
  return this.doReplaceState({
@@ -805,7 +1123,7 @@ var History = class {
805
1123
  if (!window.history.state?.page) {
806
1124
  return;
807
1125
  }
808
- if ((0, import_lodash_es2.isEqual)(this.getDocumentScrollPosition(), scrollRegion)) {
1126
+ if ((0, import_lodash_es3.isEqual)(this.getDocumentScrollPosition(), scrollRegion)) {
809
1127
  return;
810
1128
  }
811
1129
  return this.doReplaceState({
@@ -854,547 +1172,288 @@ var History = class {
854
1172
  "",
855
1173
  url
856
1174
  )
857
- );
858
- }
859
- doPushState(data, url) {
860
- return Promise.resolve().then(() => window.history.pushState(data, "", url));
861
- }
862
- getState(key, defaultValue) {
863
- return this.current?.[key] ?? defaultValue;
864
- }
865
- deleteState(key) {
866
- if (this.current[key] !== void 0) {
867
- delete this.current[key];
868
- this.replaceState(this.current);
869
- }
870
- }
871
- clearInitialState(key) {
872
- if (this.initialState && this.initialState[key] !== void 0) {
873
- delete this.initialState[key];
874
- }
875
- }
876
- hasAnyState() {
877
- return !!this.getAllState();
878
- }
879
- clear() {
880
- SessionStorage.remove(historySessionStorageKeys.key);
881
- SessionStorage.remove(historySessionStorageKeys.iv);
882
- }
883
- setCurrent(page2) {
884
- this.current = page2;
885
- }
886
- isValidState(state) {
887
- return !!state.page;
888
- }
889
- getAllState() {
890
- return this.current;
891
- }
892
- };
893
- if (typeof window !== "undefined" && window.history.scrollRestoration) {
894
- window.history.scrollRestoration = "manual";
895
- }
896
- var history = new History();
897
-
898
- // src/eventHandler.ts
899
- var EventHandler = class {
900
- constructor() {
901
- this.internalListeners = [];
902
- }
903
- init() {
904
- if (typeof window !== "undefined") {
905
- window.addEventListener("popstate", this.handlePopstateEvent.bind(this));
906
- window.addEventListener("scroll", debounce(Scroll.onWindowScroll.bind(Scroll), 100), true);
907
- }
908
- if (typeof document !== "undefined") {
909
- document.addEventListener("scroll", debounce(Scroll.onScroll.bind(Scroll), 100), true);
910
- }
911
- }
912
- onGlobalEvent(type, callback) {
913
- const listener = ((event) => {
914
- const response = callback(event);
915
- if (event.cancelable && !event.defaultPrevented && response === false) {
916
- event.preventDefault();
917
- }
918
- });
919
- return this.registerListener(`inertia:${type}`, listener);
920
- }
921
- on(event, callback) {
922
- this.internalListeners.push({ event, listener: callback });
923
- return () => {
924
- this.internalListeners = this.internalListeners.filter((listener) => listener.listener !== callback);
925
- };
926
- }
927
- onMissingHistoryItem() {
928
- page.clear();
929
- this.fireInternalEvent("missingHistoryItem");
930
- }
931
- fireInternalEvent(event, ...args) {
932
- this.internalListeners.filter((listener) => listener.event === event).forEach((listener) => listener.listener(...args));
933
- }
934
- registerListener(type, listener) {
935
- document.addEventListener(type, listener);
936
- return () => document.removeEventListener(type, listener);
937
- }
938
- handlePopstateEvent(event) {
939
- const state = event.state || null;
940
- if (state === null) {
941
- const url = hrefToUrl(page.get().url);
942
- url.hash = window.location.hash;
943
- history.replaceState({ ...page.get(), url: url.href });
944
- Scroll.reset();
945
- return;
946
- }
947
- if (!history.isValidState(state)) {
948
- return this.onMissingHistoryItem();
949
- }
950
- history.decrypt(state.page).then((data) => {
951
- if (page.get().version !== data.version) {
952
- this.onMissingHistoryItem();
953
- return;
954
- }
955
- router.cancelAll();
956
- page.setQuietly(data, { preserveState: false }).then(() => {
957
- Scroll.restore(history.getScrollRegions());
958
- fireNavigateEvent(page.get());
959
- });
960
- }).catch(() => {
961
- this.onMissingHistoryItem();
962
- });
963
- }
964
- };
965
- var eventHandler = new EventHandler();
966
-
967
- // src/navigationType.ts
968
- var NavigationType = class {
969
- constructor() {
970
- this.type = this.resolveType();
971
- }
972
- resolveType() {
973
- if (typeof window === "undefined") {
974
- return "navigate";
975
- }
976
- if (window.performance && window.performance.getEntriesByType && window.performance.getEntriesByType("navigation").length > 0) {
977
- return window.performance.getEntriesByType("navigation")[0].type;
978
- }
979
- return "navigate";
980
- }
981
- get() {
982
- return this.type;
983
- }
984
- isBackForward() {
985
- return this.type === "back_forward";
986
- }
987
- isReload() {
988
- return this.type === "reload";
989
- }
990
- };
991
- var navigationType = new NavigationType();
992
-
993
- // src/initialVisit.ts
994
- var InitialVisit = class {
995
- static handle() {
996
- this.clearRememberedStateOnReload();
997
- const scenarios = [this.handleBackForward, this.handleLocation, this.handleDefault];
998
- scenarios.find((handler) => handler.bind(this)());
999
- }
1000
- static clearRememberedStateOnReload() {
1001
- if (navigationType.isReload()) {
1002
- history.deleteState(history.rememberedState);
1003
- history.clearInitialState(history.rememberedState);
1004
- }
1005
- }
1006
- static handleBackForward() {
1007
- if (!navigationType.isBackForward() || !history.hasAnyState()) {
1008
- return false;
1009
- }
1010
- const scrollRegions = history.getScrollRegions();
1011
- history.decrypt().then((data) => {
1012
- page.set(data, { preserveScroll: true, preserveState: true }).then(() => {
1013
- Scroll.restore(scrollRegions);
1014
- fireNavigateEvent(page.get());
1015
- });
1016
- }).catch(() => {
1017
- eventHandler.onMissingHistoryItem();
1018
- });
1019
- return true;
1020
- }
1021
- /**
1022
- * @link https://inertiajs.com/redirects#external-redirects
1023
- */
1024
- static handleLocation() {
1025
- if (!SessionStorage.exists(SessionStorage.locationVisitKey)) {
1026
- return false;
1027
- }
1028
- const locationVisit = SessionStorage.get(SessionStorage.locationVisitKey) || {};
1029
- SessionStorage.remove(SessionStorage.locationVisitKey);
1030
- if (typeof window !== "undefined") {
1031
- page.setUrlHash(window.location.hash);
1032
- }
1033
- history.decrypt(page.get()).then(() => {
1034
- const rememberedState = history.getState(history.rememberedState, {});
1035
- const scrollRegions = history.getScrollRegions();
1036
- page.remember(rememberedState);
1037
- page.set(page.get(), {
1038
- preserveScroll: locationVisit.preserveScroll,
1039
- preserveState: true
1040
- }).then(() => {
1041
- if (locationVisit.preserveScroll) {
1042
- Scroll.restore(scrollRegions);
1043
- }
1044
- fireNavigateEvent(page.get());
1045
- });
1046
- }).catch(() => {
1047
- eventHandler.onMissingHistoryItem();
1048
- });
1049
- return true;
1050
- }
1051
- static handleDefault() {
1052
- if (typeof window !== "undefined") {
1053
- page.setUrlHash(window.location.hash);
1054
- }
1055
- page.set(page.get(), { preserveScroll: true, preserveState: true }).then(() => {
1056
- if (navigationType.isReload()) {
1057
- Scroll.restore(history.getScrollRegions());
1058
- }
1059
- fireNavigateEvent(page.get());
1060
- });
1061
- }
1062
- };
1063
-
1064
- // src/poll.ts
1065
- var Poll = class {
1066
- constructor(interval, cb, options) {
1067
- this.id = null;
1068
- this.throttle = false;
1069
- this.keepAlive = false;
1070
- this.cbCount = 0;
1071
- this.keepAlive = options.keepAlive ?? false;
1072
- this.cb = cb;
1073
- this.interval = interval;
1074
- if (options.autoStart ?? true) {
1075
- this.start();
1076
- }
1175
+ );
1077
1176
  }
1078
- stop() {
1079
- if (this.id) {
1080
- clearInterval(this.id);
1081
- }
1177
+ doPushState(data, url) {
1178
+ return Promise.resolve().then(() => window.history.pushState(data, "", url));
1082
1179
  }
1083
- start() {
1084
- if (typeof window === "undefined") {
1085
- return;
1086
- }
1087
- this.stop();
1088
- this.id = window.setInterval(() => {
1089
- if (!this.throttle || this.cbCount % 10 === 0) {
1090
- this.cb();
1091
- }
1092
- if (this.throttle) {
1093
- this.cbCount++;
1094
- }
1095
- }, this.interval);
1180
+ getState(key, defaultValue) {
1181
+ return this.current?.[key] ?? defaultValue;
1096
1182
  }
1097
- isInBackground(hidden) {
1098
- this.throttle = this.keepAlive ? false : hidden;
1099
- if (this.throttle) {
1100
- this.cbCount = 0;
1183
+ deleteState(key) {
1184
+ if (this.current[key] !== void 0) {
1185
+ delete this.current[key];
1186
+ this.replaceState(this.current);
1101
1187
  }
1102
1188
  }
1103
- };
1104
-
1105
- // src/polls.ts
1106
- var Polls = class {
1107
- constructor() {
1108
- this.polls = [];
1109
- this.setupVisibilityListener();
1189
+ clearInitialState(key) {
1190
+ if (this.initialState && this.initialState[key] !== void 0) {
1191
+ delete this.initialState[key];
1192
+ }
1110
1193
  }
1111
- add(interval, cb, options) {
1112
- const poll = new Poll(interval, cb, options);
1113
- this.polls.push(poll);
1114
- return {
1115
- stop: () => poll.stop(),
1116
- start: () => poll.start()
1117
- };
1194
+ hasAnyState() {
1195
+ return !!this.getAllState();
1118
1196
  }
1119
1197
  clear() {
1120
- this.polls.forEach((poll) => poll.stop());
1121
- this.polls = [];
1198
+ SessionStorage.remove(historySessionStorageKeys.key);
1199
+ SessionStorage.remove(historySessionStorageKeys.iv);
1122
1200
  }
1123
- setupVisibilityListener() {
1124
- if (typeof document === "undefined") {
1125
- return;
1126
- }
1127
- document.addEventListener(
1128
- "visibilitychange",
1129
- () => {
1130
- this.polls.forEach((poll) => poll.isInBackground(document.hidden));
1131
- },
1132
- false
1133
- );
1201
+ setCurrent(page2) {
1202
+ this.current = page2;
1203
+ }
1204
+ isValidState(state) {
1205
+ return !!state.page;
1206
+ }
1207
+ getAllState() {
1208
+ return this.current;
1134
1209
  }
1135
1210
  };
1136
- var polls = new Polls();
1137
-
1138
- // src/prefetched.ts
1139
- var import_lodash_es3 = require("lodash-es");
1211
+ if (typeof window !== "undefined" && window.history.scrollRestoration) {
1212
+ window.history.scrollRestoration = "manual";
1213
+ }
1214
+ var history = new History();
1140
1215
 
1141
- // src/objectUtils.ts
1142
- var objectsAreEqual = (obj1, obj2, excludeKeys) => {
1143
- if (obj1 === obj2) {
1144
- return true;
1216
+ // src/eventHandler.ts
1217
+ var EventHandler = class {
1218
+ constructor() {
1219
+ this.internalListeners = [];
1145
1220
  }
1146
- for (const key in obj1) {
1147
- if (excludeKeys.includes(key)) {
1148
- continue;
1149
- }
1150
- if (obj1[key] === obj2[key]) {
1151
- continue;
1221
+ init() {
1222
+ if (typeof window !== "undefined") {
1223
+ window.addEventListener("popstate", this.handlePopstateEvent.bind(this));
1224
+ window.addEventListener("scroll", debounce(Scroll.onWindowScroll.bind(Scroll), 100), true);
1152
1225
  }
1153
- if (!compareValues(obj1[key], obj2[key])) {
1154
- return false;
1226
+ if (typeof document !== "undefined") {
1227
+ document.addEventListener("scroll", debounce(Scroll.onScroll.bind(Scroll), 100), true);
1155
1228
  }
1156
1229
  }
1157
- for (const key in obj2) {
1158
- if (excludeKeys.includes(key)) {
1159
- continue;
1160
- }
1161
- if (!(key in obj1)) {
1162
- return false;
1163
- }
1230
+ onGlobalEvent(type, callback) {
1231
+ const listener = ((event) => {
1232
+ const response = callback(event);
1233
+ if (event.cancelable && !event.defaultPrevented && response === false) {
1234
+ event.preventDefault();
1235
+ }
1236
+ });
1237
+ return this.registerListener(`inertia:${type}`, listener);
1164
1238
  }
1165
- return true;
1166
- };
1167
- var compareValues = (value1, value2) => {
1168
- switch (typeof value1) {
1169
- case "object":
1170
- return objectsAreEqual(value1, value2, []);
1171
- case "function":
1172
- return value1.toString() === value2.toString();
1173
- default:
1174
- return value1 === value2;
1239
+ on(event, callback) {
1240
+ this.internalListeners.push({ event, listener: callback });
1241
+ return () => {
1242
+ this.internalListeners = this.internalListeners.filter((listener) => listener.listener !== callback);
1243
+ };
1175
1244
  }
1176
- };
1177
-
1178
- // src/time.ts
1179
- var conversionMap = {
1180
- ms: 1,
1181
- s: 1e3,
1182
- m: 1e3 * 60,
1183
- h: 1e3 * 60 * 60,
1184
- d: 1e3 * 60 * 60 * 24
1185
- };
1186
- var timeToMs = (time) => {
1187
- if (typeof time === "number") {
1188
- return time;
1245
+ onMissingHistoryItem() {
1246
+ page.clear();
1247
+ this.fireInternalEvent("missingHistoryItem");
1189
1248
  }
1190
- for (const [unit, conversion] of Object.entries(conversionMap)) {
1191
- if (time.endsWith(unit)) {
1192
- return parseFloat(time) * conversion;
1249
+ fireInternalEvent(event, ...args) {
1250
+ this.internalListeners.filter((listener) => listener.event === event).forEach((listener) => listener.listener(...args));
1251
+ }
1252
+ registerListener(type, listener) {
1253
+ document.addEventListener(type, listener);
1254
+ return () => document.removeEventListener(type, listener);
1255
+ }
1256
+ handlePopstateEvent(event) {
1257
+ const state = event.state || null;
1258
+ if (state === null) {
1259
+ const url = hrefToUrl(page.get().url);
1260
+ url.hash = window.location.hash;
1261
+ history.replaceState({ ...page.get(), url: url.href });
1262
+ Scroll.reset();
1263
+ return;
1264
+ }
1265
+ if (!history.isValidState(state)) {
1266
+ return this.onMissingHistoryItem();
1193
1267
  }
1268
+ history.decrypt(state.page).then((data) => {
1269
+ if (page.get().version !== data.version) {
1270
+ this.onMissingHistoryItem();
1271
+ return;
1272
+ }
1273
+ router.cancelAll();
1274
+ page.setQuietly(data, { preserveState: false }).then(() => {
1275
+ Scroll.restore(history.getScrollRegions());
1276
+ fireNavigateEvent(page.get());
1277
+ });
1278
+ }).catch(() => {
1279
+ this.onMissingHistoryItem();
1280
+ });
1194
1281
  }
1195
- return parseInt(time);
1196
1282
  };
1283
+ var eventHandler = new EventHandler();
1197
1284
 
1198
- // src/prefetched.ts
1199
- var PrefetchedRequests = class {
1285
+ // src/navigationType.ts
1286
+ var NavigationType = class {
1200
1287
  constructor() {
1201
- this.cached = [];
1202
- this.inFlightRequests = [];
1203
- this.removalTimers = [];
1204
- this.currentUseId = null;
1288
+ this.type = this.resolveType();
1205
1289
  }
1206
- add(params, sendFunc, { cacheFor, cacheTags }) {
1207
- const inFlight = this.findInFlight(params);
1208
- if (inFlight) {
1209
- return Promise.resolve();
1290
+ resolveType() {
1291
+ if (typeof window === "undefined") {
1292
+ return "navigate";
1210
1293
  }
1211
- const existing = this.findCached(params);
1212
- if (!params.fresh && existing && existing.staleTimestamp > Date.now()) {
1213
- return Promise.resolve();
1294
+ if (window.performance && window.performance.getEntriesByType && window.performance.getEntriesByType("navigation").length > 0) {
1295
+ return window.performance.getEntriesByType("navigation")[0].type;
1214
1296
  }
1215
- const [stale, expires] = this.extractStaleValues(cacheFor);
1216
- const promise = new Promise((resolve, reject) => {
1217
- sendFunc({
1218
- ...params,
1219
- onCancel: () => {
1220
- this.remove(params);
1221
- params.onCancel();
1222
- reject();
1223
- },
1224
- onError: (error) => {
1225
- this.remove(params);
1226
- params.onError(error);
1227
- reject();
1228
- },
1229
- onPrefetching(visitParams) {
1230
- params.onPrefetching(visitParams);
1231
- },
1232
- onPrefetched(response, visit) {
1233
- params.onPrefetched(response, visit);
1234
- },
1235
- onPrefetchResponse(response) {
1236
- resolve(response);
1237
- },
1238
- onPrefetchError(error) {
1239
- prefetchedRequests.removeFromInFlight(params);
1240
- reject(error);
1241
- }
1242
- });
1243
- }).then((response) => {
1244
- this.remove(params);
1245
- this.cached.push({
1246
- params: { ...params },
1247
- staleTimestamp: Date.now() + stale,
1248
- response: promise,
1249
- singleUse: expires === 0,
1250
- timestamp: Date.now(),
1251
- inFlight: false,
1252
- tags: Array.isArray(cacheTags) ? cacheTags : [cacheTags]
1253
- });
1254
- this.scheduleForRemoval(params, expires);
1255
- this.removeFromInFlight(params);
1256
- response.handlePrefetch();
1257
- return response;
1258
- });
1259
- this.inFlightRequests.push({
1260
- params: { ...params },
1261
- response: promise,
1262
- staleTimestamp: null,
1263
- inFlight: true
1264
- });
1265
- return promise;
1297
+ return "navigate";
1298
+ }
1299
+ get() {
1300
+ return this.type;
1266
1301
  }
1267
- removeAll() {
1268
- this.cached = [];
1269
- this.removalTimers.forEach((removalTimer) => {
1270
- clearTimeout(removalTimer.timer);
1271
- });
1272
- this.removalTimers = [];
1302
+ isBackForward() {
1303
+ return this.type === "back_forward";
1273
1304
  }
1274
- removeByTags(tags) {
1275
- this.cached = this.cached.filter((prefetched) => {
1276
- return !prefetched.tags.some((tag) => tags.includes(tag));
1277
- });
1305
+ isReload() {
1306
+ return this.type === "reload";
1278
1307
  }
1279
- remove(params) {
1280
- this.cached = this.cached.filter((prefetched) => {
1281
- return !this.paramsAreEqual(prefetched.params, params);
1282
- });
1283
- this.clearTimer(params);
1308
+ };
1309
+ var navigationType = new NavigationType();
1310
+
1311
+ // src/initialVisit.ts
1312
+ var InitialVisit = class {
1313
+ static handle() {
1314
+ this.clearRememberedStateOnReload();
1315
+ const scenarios = [this.handleBackForward, this.handleLocation, this.handleDefault];
1316
+ scenarios.find((handler) => handler.bind(this)());
1284
1317
  }
1285
- removeFromInFlight(params) {
1286
- this.inFlightRequests = this.inFlightRequests.filter((prefetching) => {
1287
- return !this.paramsAreEqual(prefetching.params, params);
1288
- });
1318
+ static clearRememberedStateOnReload() {
1319
+ if (navigationType.isReload()) {
1320
+ history.deleteState(history.rememberedState);
1321
+ history.clearInitialState(history.rememberedState);
1322
+ }
1289
1323
  }
1290
- extractStaleValues(cacheFor) {
1291
- const [stale, expires] = this.cacheForToStaleAndExpires(cacheFor);
1292
- return [timeToMs(stale), timeToMs(expires)];
1324
+ static handleBackForward() {
1325
+ if (!navigationType.isBackForward() || !history.hasAnyState()) {
1326
+ return false;
1327
+ }
1328
+ const scrollRegions = history.getScrollRegions();
1329
+ history.decrypt().then((data) => {
1330
+ page.set(data, { preserveScroll: true, preserveState: true }).then(() => {
1331
+ Scroll.restore(scrollRegions);
1332
+ fireNavigateEvent(page.get());
1333
+ });
1334
+ }).catch(() => {
1335
+ eventHandler.onMissingHistoryItem();
1336
+ });
1337
+ return true;
1293
1338
  }
1294
- cacheForToStaleAndExpires(cacheFor) {
1295
- if (!Array.isArray(cacheFor)) {
1296
- return [cacheFor, cacheFor];
1339
+ /**
1340
+ * @link https://inertiajs.com/redirects#external-redirects
1341
+ */
1342
+ static handleLocation() {
1343
+ if (!SessionStorage.exists(SessionStorage.locationVisitKey)) {
1344
+ return false;
1297
1345
  }
1298
- switch (cacheFor.length) {
1299
- case 0:
1300
- return [0, 0];
1301
- case 1:
1302
- return [cacheFor[0], cacheFor[0]];
1303
- default:
1304
- return [cacheFor[0], cacheFor[1]];
1346
+ const locationVisit = SessionStorage.get(SessionStorage.locationVisitKey) || {};
1347
+ SessionStorage.remove(SessionStorage.locationVisitKey);
1348
+ if (typeof window !== "undefined") {
1349
+ page.setUrlHash(window.location.hash);
1305
1350
  }
1351
+ history.decrypt(page.get()).then(() => {
1352
+ const rememberedState = history.getState(history.rememberedState, {});
1353
+ const scrollRegions = history.getScrollRegions();
1354
+ page.remember(rememberedState);
1355
+ page.set(page.get(), {
1356
+ preserveScroll: locationVisit.preserveScroll,
1357
+ preserveState: true
1358
+ }).then(() => {
1359
+ if (locationVisit.preserveScroll) {
1360
+ Scroll.restore(scrollRegions);
1361
+ }
1362
+ fireNavigateEvent(page.get());
1363
+ });
1364
+ }).catch(() => {
1365
+ eventHandler.onMissingHistoryItem();
1366
+ });
1367
+ return true;
1306
1368
  }
1307
- clearTimer(params) {
1308
- const timer = this.removalTimers.find((removalTimer) => {
1309
- return this.paramsAreEqual(removalTimer.params, params);
1369
+ static handleDefault() {
1370
+ if (typeof window !== "undefined") {
1371
+ page.setUrlHash(window.location.hash);
1372
+ }
1373
+ page.set(page.get(), { preserveScroll: true, preserveState: true }).then(() => {
1374
+ if (navigationType.isReload()) {
1375
+ Scroll.restore(history.getScrollRegions());
1376
+ } else {
1377
+ Scroll.scrollToAnchor();
1378
+ }
1379
+ fireNavigateEvent(page.get());
1310
1380
  });
1311
- if (timer) {
1312
- clearTimeout(timer.timer);
1313
- this.removalTimers = this.removalTimers.filter((removalTimer) => removalTimer !== timer);
1381
+ }
1382
+ };
1383
+
1384
+ // src/poll.ts
1385
+ var Poll = class {
1386
+ constructor(interval, cb, options) {
1387
+ this.id = null;
1388
+ this.throttle = false;
1389
+ this.keepAlive = false;
1390
+ this.cbCount = 0;
1391
+ this.keepAlive = options.keepAlive ?? false;
1392
+ this.cb = cb;
1393
+ this.interval = interval;
1394
+ if (options.autoStart ?? true) {
1395
+ this.start();
1314
1396
  }
1315
1397
  }
1316
- scheduleForRemoval(params, expiresIn) {
1398
+ stop() {
1399
+ if (this.id) {
1400
+ clearInterval(this.id);
1401
+ }
1402
+ }
1403
+ start() {
1317
1404
  if (typeof window === "undefined") {
1318
1405
  return;
1319
1406
  }
1320
- this.clearTimer(params);
1321
- if (expiresIn > 0) {
1322
- const timer = window.setTimeout(() => this.remove(params), expiresIn);
1323
- this.removalTimers.push({
1324
- params,
1325
- timer
1326
- });
1327
- }
1328
- }
1329
- get(params) {
1330
- return this.findCached(params) || this.findInFlight(params);
1331
- }
1332
- use(prefetched, params) {
1333
- const id = `${params.url.pathname}-${Date.now()}-${Math.random().toString(36).substring(7)}`;
1334
- this.currentUseId = id;
1335
- return prefetched.response.then((response) => {
1336
- if (this.currentUseId !== id) {
1337
- return;
1407
+ this.stop();
1408
+ this.id = window.setInterval(() => {
1409
+ if (!this.throttle || this.cbCount % 10 === 0) {
1410
+ this.cb();
1338
1411
  }
1339
- response.mergeParams({ ...params, onPrefetched: () => {
1340
- } });
1341
- this.removeSingleUseItems(params);
1342
- return response.handle();
1343
- });
1344
- }
1345
- removeSingleUseItems(params) {
1346
- this.cached = this.cached.filter((prefetched) => {
1347
- if (!this.paramsAreEqual(prefetched.params, params)) {
1348
- return true;
1412
+ if (this.throttle) {
1413
+ this.cbCount++;
1349
1414
  }
1350
- return !prefetched.singleUse;
1351
- });
1415
+ }, this.interval);
1352
1416
  }
1353
- findCached(params) {
1354
- return this.cached.find((prefetched) => {
1355
- return this.paramsAreEqual(prefetched.params, params);
1356
- }) || null;
1417
+ isInBackground(hidden) {
1418
+ this.throttle = this.keepAlive ? false : hidden;
1419
+ if (this.throttle) {
1420
+ this.cbCount = 0;
1421
+ }
1357
1422
  }
1358
- findInFlight(params) {
1359
- return this.inFlightRequests.find((prefetched) => {
1360
- return this.paramsAreEqual(prefetched.params, params);
1361
- }) || null;
1423
+ };
1424
+
1425
+ // src/polls.ts
1426
+ var Polls = class {
1427
+ constructor() {
1428
+ this.polls = [];
1429
+ this.setupVisibilityListener();
1362
1430
  }
1363
- withoutPurposePrefetchHeader(params) {
1364
- const newParams = (0, import_lodash_es3.cloneDeep)(params);
1365
- if (newParams.headers["Purpose"] === "prefetch") {
1366
- delete newParams.headers["Purpose"];
1367
- }
1368
- return newParams;
1431
+ add(interval, cb, options) {
1432
+ const poll = new Poll(interval, cb, options);
1433
+ this.polls.push(poll);
1434
+ return {
1435
+ stop: () => poll.stop(),
1436
+ start: () => poll.start()
1437
+ };
1369
1438
  }
1370
- paramsAreEqual(params1, params2) {
1371
- return objectsAreEqual(
1372
- this.withoutPurposePrefetchHeader(params1),
1373
- this.withoutPurposePrefetchHeader(params2),
1374
- [
1375
- "showProgress",
1376
- "replace",
1377
- "prefetch",
1378
- "preserveScroll",
1379
- "preserveState",
1380
- "onBefore",
1381
- "onBeforeUpdate",
1382
- "onStart",
1383
- "onProgress",
1384
- "onFinish",
1385
- "onCancel",
1386
- "onSuccess",
1387
- "onError",
1388
- "onPrefetched",
1389
- "onCancelToken",
1390
- "onPrefetching",
1391
- "async",
1392
- "viewTransition"
1393
- ]
1439
+ clear() {
1440
+ this.polls.forEach((poll) => poll.stop());
1441
+ this.polls = [];
1442
+ }
1443
+ setupVisibilityListener() {
1444
+ if (typeof document === "undefined") {
1445
+ return;
1446
+ }
1447
+ document.addEventListener(
1448
+ "visibilitychange",
1449
+ () => {
1450
+ this.polls.forEach((poll) => poll.isInBackground(document.hidden));
1451
+ },
1452
+ false
1394
1453
  );
1395
1454
  }
1396
1455
  };
1397
- var prefetchedRequests = new PrefetchedRequests();
1456
+ var polls = new Polls();
1398
1457
 
1399
1458
  // src/request.ts
1400
1459
  var import_axios = __toESM(require("axios"), 1);
@@ -1441,6 +1500,9 @@ var RequestParams = class _RequestParams {
1441
1500
  isPartial() {
1442
1501
  return this.params.only.length > 0 || this.params.except.length > 0 || this.params.reset.length > 0;
1443
1502
  }
1503
+ isDeferredPropsRequest() {
1504
+ return this.params.deferredProps === true;
1505
+ }
1444
1506
  onCancelToken(cb) {
1445
1507
  this.params.onCancelToken({
1446
1508
  cancel: cb
@@ -1699,6 +1761,9 @@ var Response = class _Response {
1699
1761
  mergeParams(params) {
1700
1762
  this.requestParams.merge(params);
1701
1763
  }
1764
+ getPageResponse() {
1765
+ return this.response.data = this.getDataFromResponse(this.response.data);
1766
+ }
1702
1767
  async handleNonInertiaResponse() {
1703
1768
  if (this.isLocationVisit()) {
1704
1769
  const locationUrl = hrefToUrl(this.getHeader("x-inertia-location"));
@@ -1749,11 +1814,12 @@ var Response = class _Response {
1749
1814
  }
1750
1815
  }
1751
1816
  async setPage() {
1752
- const pageResponse = this.getDataFromResponse(this.response.data);
1817
+ const pageResponse = this.getPageResponse();
1753
1818
  if (!this.shouldSetPage(pageResponse)) {
1754
1819
  return Promise.resolve();
1755
1820
  }
1756
1821
  this.mergeProps(pageResponse);
1822
+ page.mergeOncePropsIntoResponse(pageResponse);
1757
1823
  this.preserveEqualProps(pageResponse);
1758
1824
  await this.setRememberedState(pageResponse);
1759
1825
  this.requestParams.setPreserveOptions(pageResponse);
@@ -1858,6 +1924,12 @@ var Response = class _Response {
1858
1924
  pageResponse.props[prop] = deepMerge(currentProp, incomingProp, prop);
1859
1925
  });
1860
1926
  pageResponse.props = { ...page.get().props, ...pageResponse.props };
1927
+ if (this.requestParams.isDeferredPropsRequest()) {
1928
+ const currentErrors = page.get().props.errors;
1929
+ if (currentErrors && Object.keys(currentErrors).length > 0) {
1930
+ pageResponse.props.errors = currentErrors;
1931
+ }
1932
+ }
1861
1933
  if (page.get().scrollProps) {
1862
1934
  pageResponse.scrollProps = {
1863
1935
  ...page.get().scrollProps || {},
@@ -2020,8 +2092,13 @@ var Request = class _Request {
2020
2092
  "X-Requested-With": "XMLHttpRequest",
2021
2093
  "X-Inertia": true
2022
2094
  };
2023
- if (page.get().version) {
2024
- headers["X-Inertia-Version"] = page.get().version;
2095
+ const page2 = page.get();
2096
+ if (page2.version) {
2097
+ headers["X-Inertia-Version"] = page2.version;
2098
+ }
2099
+ const onceProps = Object.entries(page2.onceProps || {}).filter(([, onceProp]) => !onceProp.expiresAt || onceProp.expiresAt > Date.now()).map(([key]) => key);
2100
+ if (onceProps.length > 0) {
2101
+ headers["X-Inertia-Except-Once-Props"] = onceProps.join(",");
2025
2102
  }
2026
2103
  return headers;
2027
2104
  }
@@ -2072,6 +2149,7 @@ var Router = class {
2072
2149
  maxConcurrent: Infinity,
2073
2150
  interruptible: false
2074
2151
  });
2152
+ this.clientVisitQueue = new Queue();
2075
2153
  }
2076
2154
  init({
2077
2155
  initialPage,
@@ -2110,6 +2188,9 @@ var Router = class {
2110
2188
  return this.visit(url, { preserveState: true, ...options, method: "delete" });
2111
2189
  }
2112
2190
  reload(options = {}) {
2191
+ return this.doReload(options);
2192
+ }
2193
+ doReload(options = {}) {
2113
2194
  if (typeof window === "undefined") {
2114
2195
  return;
2115
2196
  }
@@ -2298,6 +2379,9 @@ var Router = class {
2298
2379
  this.clientVisit(params);
2299
2380
  }
2300
2381
  clientVisit(params, { replace = false } = {}) {
2382
+ this.clientVisitQueue.add(() => this.performClientVisit(params, { replace }));
2383
+ }
2384
+ performClientVisit(params, { replace = false } = {}) {
2301
2385
  const current = page.get();
2302
2386
  const props = typeof params.props === "function" ? params.props(current.props) : params.props ?? current.props;
2303
2387
  const { viewTransition, onError, onFinish, onSuccess, ...pageParams } = params;
@@ -2308,7 +2392,7 @@ var Router = class {
2308
2392
  };
2309
2393
  const preserveScroll = RequestParams.resolvePreserveOption(params.preserveScroll ?? false, page2);
2310
2394
  const preserveState = RequestParams.resolvePreserveOption(params.preserveState ?? false, page2);
2311
- page.set(page2, {
2395
+ return page.set(page2, {
2312
2396
  replace,
2313
2397
  preserveScroll,
2314
2398
  preserveState,
@@ -2316,10 +2400,11 @@ var Router = class {
2316
2400
  }).then(() => {
2317
2401
  const errors = page.get().props.errors || {};
2318
2402
  if (Object.keys(errors).length === 0) {
2319
- return onSuccess?.(page.get());
2403
+ onSuccess?.(page.get());
2404
+ return;
2320
2405
  }
2321
2406
  const scopedErrors = params.errorBag ? errors[params.errorBag || ""] || {} : errors;
2322
- return onError?.(scopedErrors);
2407
+ onError?.(scopedErrors);
2323
2408
  }).finally(() => onFinish?.(params));
2324
2409
  }
2325
2410
  getPrefetchParams(href, options) {
@@ -2415,7 +2500,7 @@ var Router = class {
2415
2500
  loadDeferredProps(deferred) {
2416
2501
  if (deferred) {
2417
2502
  Object.entries(deferred).forEach(([_, group]) => {
2418
- this.reload({ only: group });
2503
+ this.doReload({ only: group, deferredProps: true });
2419
2504
  });
2420
2505
  }
2421
2506
  }
@@ -2511,6 +2596,22 @@ var requestAnimationFrame = (cb, times = 1) => {
2511
2596
  }
2512
2597
  });
2513
2598
  };
2599
+ var getInitialPageFromDOM = (id, useScriptElement = false) => {
2600
+ if (typeof window === "undefined") {
2601
+ return null;
2602
+ }
2603
+ if (!useScriptElement) {
2604
+ const el = document.getElementById(id);
2605
+ if (el?.dataset.page) {
2606
+ return JSON.parse(el.dataset.page);
2607
+ }
2608
+ }
2609
+ const scriptEl = document.querySelector(`script[data-page="${id}"][type="application/json"]`);
2610
+ if (scriptEl?.textContent) {
2611
+ return JSON.parse(scriptEl.textContent);
2612
+ }
2613
+ return null;
2614
+ };
2514
2615
 
2515
2616
  // src/formObject.ts
2516
2617
  var import_lodash_es6 = require("lodash-es");