@inertiajs/core 2.3.8 → 2.3.10

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
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ FormComponentResetSymbol: () => FormComponentResetSymbol,
33
34
  UseFormUtils: () => UseFormUtils,
34
35
  config: () => config,
35
36
  createHeadManager: () => createHeadManager,
@@ -632,7 +633,116 @@ var PrefetchedRequests = class {
632
633
  };
633
634
  var prefetchedRequests = new PrefetchedRequests();
634
635
 
636
+ // src/domUtils.ts
637
+ var elementInViewport = (el) => {
638
+ if (el.offsetParent === null) {
639
+ return false;
640
+ }
641
+ const rect = el.getBoundingClientRect();
642
+ const verticallyVisible = rect.top < window.innerHeight && rect.bottom >= 0;
643
+ const horizontallyVisible = rect.left < window.innerWidth && rect.right >= 0;
644
+ return verticallyVisible && horizontallyVisible;
645
+ };
646
+ var getScrollableParent = (element) => {
647
+ const allowsVerticalScroll = (el) => {
648
+ const computedStyle = window.getComputedStyle(el);
649
+ if (["scroll", "overlay"].includes(computedStyle.overflowY)) {
650
+ return true;
651
+ }
652
+ if (computedStyle.overflowY !== "auto") {
653
+ return false;
654
+ }
655
+ if (["visible", "clip"].includes(computedStyle.overflowX)) {
656
+ return true;
657
+ }
658
+ return hasDimensionConstraint(computedStyle.maxHeight, el.style.height);
659
+ };
660
+ const allowsHorizontalScroll = (el) => {
661
+ const computedStyle = window.getComputedStyle(el);
662
+ if (["scroll", "overlay"].includes(computedStyle.overflowX)) {
663
+ return true;
664
+ }
665
+ if (computedStyle.overflowX !== "auto") {
666
+ return false;
667
+ }
668
+ if (["visible", "clip"].includes(computedStyle.overflowY)) {
669
+ return true;
670
+ }
671
+ return hasDimensionConstraint(computedStyle.maxWidth, el.style.width);
672
+ };
673
+ const hasDimensionConstraint = (computedMaxDimension, inlineStyleDimension) => {
674
+ if (computedMaxDimension && computedMaxDimension !== "none" && computedMaxDimension !== "0px") {
675
+ return true;
676
+ }
677
+ if (inlineStyleDimension && inlineStyleDimension !== "auto" && inlineStyleDimension !== "0") {
678
+ return true;
679
+ }
680
+ return false;
681
+ };
682
+ let parent = element?.parentElement;
683
+ while (parent) {
684
+ const allowsScroll = allowsVerticalScroll(parent) || allowsHorizontalScroll(parent);
685
+ if (window.getComputedStyle(parent).display !== "contents" && allowsScroll) {
686
+ return parent;
687
+ }
688
+ parent = parent.parentElement;
689
+ }
690
+ return null;
691
+ };
692
+ var getElementsInViewportFromCollection = (elements, referenceElement) => {
693
+ if (!referenceElement) {
694
+ return elements.filter((element) => elementInViewport(element));
695
+ }
696
+ const referenceIndex = elements.indexOf(referenceElement);
697
+ const upwardElements = [];
698
+ const downwardElements = [];
699
+ for (let i = referenceIndex; i >= 0; i--) {
700
+ const element = elements[i];
701
+ if (elementInViewport(element)) {
702
+ upwardElements.push(element);
703
+ } else {
704
+ break;
705
+ }
706
+ }
707
+ for (let i = referenceIndex + 1; i < elements.length; i++) {
708
+ const element = elements[i];
709
+ if (elementInViewport(element)) {
710
+ downwardElements.push(element);
711
+ } else {
712
+ break;
713
+ }
714
+ }
715
+ return [...upwardElements.reverse(), ...downwardElements];
716
+ };
717
+ var requestAnimationFrame = (cb, times = 1) => {
718
+ window.requestAnimationFrame(() => {
719
+ if (times > 1) {
720
+ requestAnimationFrame(cb, times - 1);
721
+ } else {
722
+ cb();
723
+ }
724
+ });
725
+ };
726
+ var getInitialPageFromDOM = (id, useScriptElement = false) => {
727
+ if (typeof window === "undefined") {
728
+ return null;
729
+ }
730
+ if (!useScriptElement) {
731
+ const el = document.getElementById(id);
732
+ if (el?.dataset.page) {
733
+ return JSON.parse(el.dataset.page);
734
+ }
735
+ }
736
+ const scriptEl = document.querySelector(`script[data-page="${id}"][type="application/json"]`);
737
+ if (scriptEl?.textContent) {
738
+ return JSON.parse(scriptEl.textContent);
739
+ }
740
+ return null;
741
+ };
742
+
635
743
  // src/scroll.ts
744
+ var isServer = typeof window === "undefined";
745
+ var isFirefox = !isServer && /Firefox/i.test(window.navigator.userAgent);
636
746
  var Scroll = class {
637
747
  static save() {
638
748
  history.saveScrollPositions(this.getScrollRegions());
@@ -646,10 +756,16 @@ var Scroll = class {
646
756
  static regions() {
647
757
  return document.querySelectorAll("[scroll-region]");
648
758
  }
759
+ static scrollToTop() {
760
+ if (isFirefox && getComputedStyle(document.documentElement).scrollBehavior === "smooth") {
761
+ return requestAnimationFrame(() => window.scrollTo(0, 0), 2);
762
+ }
763
+ window.scrollTo(0, 0);
764
+ }
649
765
  static reset() {
650
- const anchorHash = typeof window !== "undefined" ? window.location.hash : null;
766
+ const anchorHash = isServer ? null : window.location.hash;
651
767
  if (!anchorHash) {
652
- window.scrollTo(0, 0);
768
+ this.scrollToTop();
653
769
  }
654
770
  this.regions().forEach((region) => {
655
771
  if (typeof region.scrollTo === "function") {
@@ -663,16 +779,16 @@ var Scroll = class {
663
779
  this.scrollToAnchor();
664
780
  }
665
781
  static scrollToAnchor() {
666
- const anchorHash = typeof window !== "undefined" ? window.location.hash : null;
782
+ const anchorHash = isServer ? null : window.location.hash;
667
783
  if (anchorHash) {
668
784
  setTimeout(() => {
669
785
  const anchorElement = document.getElementById(anchorHash.slice(1));
670
- anchorElement ? anchorElement.scrollIntoView() : window.scrollTo(0, 0);
786
+ anchorElement ? anchorElement.scrollIntoView() : this.scrollToTop();
671
787
  });
672
788
  }
673
789
  }
674
790
  static restore(scrollRegions) {
675
- if (typeof window === "undefined") {
791
+ if (isServer) {
676
792
  return;
677
793
  }
678
794
  window.requestAnimationFrame(() => {
@@ -681,7 +797,7 @@ var Scroll = class {
681
797
  });
682
798
  }
683
799
  static restoreScrollRegions(scrollRegions) {
684
- if (typeof window === "undefined") {
800
+ if (isServer) {
685
801
  return;
686
802
  }
687
803
  this.regions().forEach((region, index) => {
@@ -874,6 +990,9 @@ var CurrentPage = class {
874
990
  component: page2.component,
875
991
  url: page2.url
876
992
  };
993
+ if (page2.initialDeferredProps === void 0) {
994
+ page2.initialDeferredProps = page2.deferredProps;
995
+ }
877
996
  }
878
997
  this.componentId = {};
879
998
  const componentId = this.componentId;
@@ -885,9 +1004,9 @@ var CurrentPage = class {
885
1004
  return;
886
1005
  }
887
1006
  page2.rememberedState ?? (page2.rememberedState = {});
888
- const isServer2 = typeof window === "undefined";
889
- const location = !isServer2 ? window.location : new URL(page2.url);
890
- const scrollRegions = !isServer2 && preserveScroll ? Scroll.getScrollRegions() : [];
1007
+ const isServer3 = typeof window === "undefined";
1008
+ const location = !isServer3 ? window.location : new URL(page2.url);
1009
+ const scrollRegions = !isServer3 && preserveScroll ? Scroll.getScrollRegions() : [];
891
1010
  replace = replace || isSameUrlWithoutHash(hrefToUrl(page2.url), location);
892
1011
  const pageForHistory = { ...page2, flash: {} };
893
1012
  return new Promise(
@@ -1047,9 +1166,9 @@ var Queue = class {
1047
1166
  };
1048
1167
 
1049
1168
  // src/history.ts
1050
- var isServer = typeof window === "undefined";
1169
+ var isServer2 = typeof window === "undefined";
1051
1170
  var queue = new Queue();
1052
- var isChromeIOS = !isServer && /CriOS/.test(window.navigator.userAgent);
1171
+ var isChromeIOS = !isServer2 && /CriOS/.test(window.navigator.userAgent);
1053
1172
  var History = class {
1054
1173
  constructor() {
1055
1174
  this.rememberedState = "rememberedState";
@@ -1069,12 +1188,12 @@ var History = class {
1069
1188
  });
1070
1189
  }
1071
1190
  restore(key) {
1072
- if (!isServer) {
1191
+ if (!isServer2) {
1073
1192
  return this.current[this.rememberedState]?.[key] !== void 0 ? this.current[this.rememberedState]?.[key] : this.initialState?.[this.rememberedState]?.[key];
1074
1193
  }
1075
1194
  }
1076
1195
  pushState(page2, cb = null) {
1077
- if (isServer) {
1196
+ if (isServer2) {
1078
1197
  return;
1079
1198
  }
1080
1199
  if (this.preserveUrl) {
@@ -1115,7 +1234,7 @@ var History = class {
1115
1234
  return queue.process();
1116
1235
  }
1117
1236
  decrypt(page2 = null) {
1118
- if (isServer) {
1237
+ if (isServer2) {
1119
1238
  return Promise.resolve(page2 ?? page.get());
1120
1239
  }
1121
1240
  const pageData = page2 ?? window.history.state?.page;
@@ -1178,7 +1297,7 @@ var History = class {
1178
1297
  return;
1179
1298
  }
1180
1299
  page.merge(page2);
1181
- if (isServer) {
1300
+ if (isServer2) {
1182
1301
  return;
1183
1302
  }
1184
1303
  if (this.preserveUrl) {
@@ -1256,7 +1375,7 @@ var History = class {
1256
1375
  }
1257
1376
  }
1258
1377
  browserHasHistoryEntry() {
1259
- return !isServer && !!window.history.state?.page;
1378
+ return !isServer2 && !!window.history.state?.page;
1260
1379
  }
1261
1380
  clear() {
1262
1381
  SessionStorage.remove(historySessionStorageKeys.key);
@@ -1334,10 +1453,21 @@ var EventHandler = class {
1334
1453
  this.onMissingHistoryItem();
1335
1454
  return;
1336
1455
  }
1337
- router.cancelAll();
1456
+ router.cancelAll({ prefetch: false });
1338
1457
  page.setQuietly(data, { preserveState: false }).then(() => {
1339
1458
  Scroll.restore(history.getScrollRegions());
1340
1459
  fireNavigateEvent(page.get());
1460
+ const pendingDeferred = {};
1461
+ const pageProps = page.get().props;
1462
+ for (const [group, props] of Object.entries(data.initialDeferredProps ?? data.deferredProps ?? {})) {
1463
+ const missing = props.filter((prop) => pageProps[prop] === void 0);
1464
+ if (missing.length > 0) {
1465
+ pendingDeferred[group] = missing;
1466
+ }
1467
+ }
1468
+ if (Object.keys(pendingDeferred).length > 0) {
1469
+ this.fireInternalEvent("loadDeferredProps", pendingDeferred);
1470
+ }
1341
1471
  });
1342
1472
  }).catch(() => {
1343
1473
  this.onMissingHistoryItem();
@@ -1570,6 +1700,9 @@ var RequestParams = class _RequestParams {
1570
1700
  isPartial() {
1571
1701
  return this.params.only.length > 0 || this.params.except.length > 0 || this.params.reset.length > 0;
1572
1702
  }
1703
+ isPrefetch() {
1704
+ return this.params.prefetch === true;
1705
+ }
1573
1706
  isDeferredPropsRequest() {
1574
1707
  return this.params.deferredProps === true;
1575
1708
  }
@@ -1839,7 +1972,10 @@ var Response = class _Response {
1839
1972
  }
1840
1973
  getPageResponse() {
1841
1974
  const data = this.getDataFromResponse(this.response.data);
1842
- return this.response.data = { ...data, flash: data.flash ?? {} };
1975
+ if (typeof data === "object") {
1976
+ return this.response.data = { ...data, flash: data.flash ?? {} };
1977
+ }
1978
+ return this.response.data = data;
1843
1979
  }
1844
1980
  async handleNonInertiaResponse() {
1845
1981
  if (this.isLocationVisit()) {
@@ -2023,6 +2159,10 @@ var Response = class _Response {
2023
2159
  ...page.get().flash,
2024
2160
  ...this.requestParams.isDeferredPropsRequest() ? {} : pageResponse.flash
2025
2161
  };
2162
+ const currentOriginalDeferred = page.get().initialDeferredProps;
2163
+ if (currentOriginalDeferred && Object.keys(currentOriginalDeferred).length > 0) {
2164
+ pageResponse.initialDeferredProps = currentOriginalDeferred;
2165
+ }
2026
2166
  }
2027
2167
  mergeOrMatchItems(existingItems, newItems, matchProp, matchPropsOn, shouldAppend = true) {
2028
2168
  const items = Array.isArray(existingItems) ? existingItems : [];
@@ -2096,6 +2236,9 @@ var Request = class _Request {
2096
2236
  static create(params, page2) {
2097
2237
  return new _Request(params, page2);
2098
2238
  }
2239
+ isPrefetch() {
2240
+ return this.requestParams.isPrefetch();
2241
+ }
2099
2242
  async send() {
2100
2243
  this.requestParams.onCancelToken(() => this.cancel({ cancelled: true }));
2101
2244
  fireStartEvent(this.requestParams.all());
@@ -2212,20 +2355,17 @@ var RequestStream = class {
2212
2355
  interruptInFlight() {
2213
2356
  this.cancel({ interrupted: true }, false);
2214
2357
  }
2215
- cancelInFlight() {
2216
- this.cancel({ cancelled: true }, true);
2358
+ cancelInFlight({ prefetch = true } = {}) {
2359
+ this.requests.filter((request) => prefetch || !request.isPrefetch()).forEach((request) => request.cancel({ cancelled: true }));
2217
2360
  }
2218
- cancel({ cancelled = false, interrupted = false } = {}, force) {
2219
- if (!this.shouldCancel(force)) {
2361
+ cancel({ cancelled = false, interrupted = false } = {}, force = false) {
2362
+ if (!force && !this.shouldCancel()) {
2220
2363
  return;
2221
2364
  }
2222
2365
  const request = this.requests.shift();
2223
- request?.cancel({ interrupted, cancelled });
2366
+ request?.cancel({ cancelled, interrupted });
2224
2367
  }
2225
- shouldCancel(force) {
2226
- if (force) {
2227
- return true;
2228
- }
2368
+ shouldCancel() {
2229
2369
  return this.interruptible && this.requests.length >= this.maxConcurrent;
2230
2370
  }
2231
2371
  };
@@ -2315,12 +2455,19 @@ var Router = class {
2315
2455
  }
2316
2456
  return eventHandler.onGlobalEvent(type, callback);
2317
2457
  }
2458
+ /**
2459
+ * @deprecated Use cancelAll() instead.
2460
+ */
2318
2461
  cancel() {
2319
2462
  this.syncRequestStream.cancelInFlight();
2320
2463
  }
2321
- cancelAll() {
2322
- this.asyncRequestStream.cancelInFlight();
2323
- this.syncRequestStream.cancelInFlight();
2464
+ cancelAll({ async = true, prefetch = true, sync = true } = {}) {
2465
+ if (async) {
2466
+ this.asyncRequestStream.cancelInFlight({ prefetch });
2467
+ }
2468
+ if (sync) {
2469
+ this.syncRequestStream.cancelInFlight();
2470
+ }
2324
2471
  }
2325
2472
  poll(interval, requestOptions = {}, options = {}) {
2326
2473
  return polls.add(interval, () => this.reload(requestOptions), {
@@ -2337,8 +2484,12 @@ var Router = class {
2337
2484
  if (events.onBefore(visit) === false || !fireBeforeEvent(visit)) {
2338
2485
  return;
2339
2486
  }
2340
- const requestStream = visit.async ? this.asyncRequestStream : this.syncRequestStream;
2341
- requestStream.interruptInFlight();
2487
+ if (!isSameUrlWithoutHash(visit.url, hrefToUrl(page.get().url))) {
2488
+ this.asyncRequestStream.cancelInFlight({ prefetch: false });
2489
+ }
2490
+ if (!visit.async) {
2491
+ this.syncRequestStream.interruptInFlight();
2492
+ }
2342
2493
  if (!page.isCleared() && !visit.preserveUrl) {
2343
2494
  Scroll.save();
2344
2495
  }
@@ -2352,6 +2503,7 @@ var Router = class {
2352
2503
  prefetchedRequests.use(prefetched, requestParams);
2353
2504
  } else {
2354
2505
  progress.reveal(true);
2506
+ const requestStream = visit.async ? this.asyncRequestStream : this.syncRequestStream;
2355
2507
  requestStream.send(Request.create(requestParams, page.get()));
2356
2508
  }
2357
2509
  }
@@ -2497,7 +2649,10 @@ var Router = class {
2497
2649
  }
2498
2650
  performClientVisit(params, { replace = false } = {}) {
2499
2651
  const current = page.get();
2500
- const props = typeof params.props === "function" ? params.props(current.props) : params.props ?? current.props;
2652
+ const onceProps = typeof params.props === "function" ? Object.fromEntries(
2653
+ Object.values(current.onceProps ?? {}).map((onceProp) => [onceProp.prop, current.props[onceProp.prop]])
2654
+ ) : {};
2655
+ const props = typeof params.props === "function" ? params.props(current.props, onceProps) : params.props ?? current.props;
2501
2656
  const flash = typeof params.flash === "function" ? params.flash(current.flash) : params.flash;
2502
2657
  const { viewTransition, onError, onFinish, onFlash, onSuccess, ...pageParams } = params;
2503
2658
  const page2 = {
@@ -2731,113 +2886,6 @@ var UseFormUtils = class {
2731
2886
  }
2732
2887
  };
2733
2888
 
2734
- // src/domUtils.ts
2735
- var elementInViewport = (el) => {
2736
- if (el.offsetParent === null) {
2737
- return false;
2738
- }
2739
- const rect = el.getBoundingClientRect();
2740
- const verticallyVisible = rect.top < window.innerHeight && rect.bottom >= 0;
2741
- const horizontallyVisible = rect.left < window.innerWidth && rect.right >= 0;
2742
- return verticallyVisible && horizontallyVisible;
2743
- };
2744
- var getScrollableParent = (element) => {
2745
- const allowsVerticalScroll = (el) => {
2746
- const computedStyle = window.getComputedStyle(el);
2747
- if (["scroll", "overlay"].includes(computedStyle.overflowY)) {
2748
- return true;
2749
- }
2750
- if (computedStyle.overflowY !== "auto") {
2751
- return false;
2752
- }
2753
- if (["visible", "clip"].includes(computedStyle.overflowX)) {
2754
- return true;
2755
- }
2756
- return hasDimensionConstraint(computedStyle.maxHeight, el.style.height);
2757
- };
2758
- const allowsHorizontalScroll = (el) => {
2759
- const computedStyle = window.getComputedStyle(el);
2760
- if (["scroll", "overlay"].includes(computedStyle.overflowX)) {
2761
- return true;
2762
- }
2763
- if (computedStyle.overflowX !== "auto") {
2764
- return false;
2765
- }
2766
- if (["visible", "clip"].includes(computedStyle.overflowY)) {
2767
- return true;
2768
- }
2769
- return hasDimensionConstraint(computedStyle.maxWidth, el.style.width);
2770
- };
2771
- const hasDimensionConstraint = (computedMaxDimension, inlineStyleDimension) => {
2772
- if (computedMaxDimension && computedMaxDimension !== "none" && computedMaxDimension !== "0px") {
2773
- return true;
2774
- }
2775
- if (inlineStyleDimension && inlineStyleDimension !== "auto" && inlineStyleDimension !== "0") {
2776
- return true;
2777
- }
2778
- return false;
2779
- };
2780
- let parent = element?.parentElement;
2781
- while (parent) {
2782
- const allowsScroll = allowsVerticalScroll(parent) || allowsHorizontalScroll(parent);
2783
- if (window.getComputedStyle(parent).display !== "contents" && allowsScroll) {
2784
- return parent;
2785
- }
2786
- parent = parent.parentElement;
2787
- }
2788
- return null;
2789
- };
2790
- var getElementsInViewportFromCollection = (elements, referenceElement) => {
2791
- if (!referenceElement) {
2792
- return elements.filter((element) => elementInViewport(element));
2793
- }
2794
- const referenceIndex = elements.indexOf(referenceElement);
2795
- const upwardElements = [];
2796
- const downwardElements = [];
2797
- for (let i = referenceIndex; i >= 0; i--) {
2798
- const element = elements[i];
2799
- if (elementInViewport(element)) {
2800
- upwardElements.push(element);
2801
- } else {
2802
- break;
2803
- }
2804
- }
2805
- for (let i = referenceIndex + 1; i < elements.length; i++) {
2806
- const element = elements[i];
2807
- if (elementInViewport(element)) {
2808
- downwardElements.push(element);
2809
- } else {
2810
- break;
2811
- }
2812
- }
2813
- return [...upwardElements.reverse(), ...downwardElements];
2814
- };
2815
- var requestAnimationFrame = (cb, times = 1) => {
2816
- window.requestAnimationFrame(() => {
2817
- if (times > 1) {
2818
- requestAnimationFrame(cb, times - 1);
2819
- } else {
2820
- cb();
2821
- }
2822
- });
2823
- };
2824
- var getInitialPageFromDOM = (id, useScriptElement = false) => {
2825
- if (typeof window === "undefined") {
2826
- return null;
2827
- }
2828
- if (!useScriptElement) {
2829
- const el = document.getElementById(id);
2830
- if (el?.dataset.page) {
2831
- return JSON.parse(el.dataset.page);
2832
- }
2833
- }
2834
- const scriptEl = document.querySelector(`script[data-page="${id}"][type="application/json"]`);
2835
- if (scriptEl?.textContent) {
2836
- return JSON.parse(scriptEl.textContent);
2837
- }
2838
- return null;
2839
- };
2840
-
2841
2889
  // src/formObject.ts
2842
2890
  var import_lodash_es6 = require("lodash-es");
2843
2891
  function undotKey(key) {
@@ -2974,7 +3022,7 @@ var Renderer = {
2974
3022
  sourceElements.forEach((element) => document.head.appendChild(element));
2975
3023
  }, 1)
2976
3024
  };
2977
- function createHeadManager(isServer2, titleCallback, onUpdate) {
3025
+ function createHeadManager(isServer3, titleCallback, onUpdate) {
2978
3026
  const states = {};
2979
3027
  let lastProviderId = 0;
2980
3028
  function connect() {
@@ -3026,7 +3074,7 @@ function createHeadManager(isServer2, titleCallback, onUpdate) {
3026
3074
  return Object.values(elements);
3027
3075
  }
3028
3076
  function commit() {
3029
- isServer2 ? onUpdate(collect()) : Renderer.update(collect());
3077
+ isServer3 ? onUpdate(collect()) : Renderer.update(collect());
3030
3078
  }
3031
3079
  commit();
3032
3080
  return {
@@ -3923,6 +3971,7 @@ function setupProgress({
3923
3971
  }
3924
3972
 
3925
3973
  // src/resetFormFields.ts
3974
+ var FormComponentResetSymbol = Symbol("FormComponentReset");
3926
3975
  function isFormElement(element) {
3927
3976
  return element instanceof HTMLInputElement || element instanceof HTMLSelectElement || element instanceof HTMLTextAreaElement;
3928
3977
  }
@@ -4053,7 +4102,9 @@ function resetFormFields(formElement, defaults, fieldNames) {
4053
4102
  }
4054
4103
  });
4055
4104
  if (hasChanged && resetEntireForm) {
4056
- formElement.dispatchEvent(new Event("reset", { bubbles: true }));
4105
+ formElement.dispatchEvent(
4106
+ new CustomEvent("reset", { bubbles: true, cancelable: true, detail: { [FormComponentResetSymbol]: true } })
4107
+ );
4057
4108
  }
4058
4109
  }
4059
4110