@inertiajs/core 2.1.10 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -32,21 +32,27 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  createHeadManager: () => createHeadManager,
34
34
  formDataToObject: () => formDataToObject,
35
- hideProgress: () => hide,
35
+ getScrollableParent: () => getScrollableParent,
36
+ hideProgress: () => hide2,
36
37
  hrefToUrl: () => hrefToUrl,
37
38
  isUrlMethodPair: () => isUrlMethodPair,
38
39
  mergeDataIntoQueryString: () => mergeDataIntoQueryString,
39
40
  objectToFormData: () => objectToFormData,
41
+ progress: () => progress,
40
42
  resetFormFields: () => resetFormFields,
41
43
  revealProgress: () => reveal,
42
44
  router: () => router,
43
45
  setupProgress: () => setupProgress,
44
46
  shouldIntercept: () => shouldIntercept,
45
47
  shouldNavigate: () => shouldNavigate,
46
- urlWithoutHash: () => urlWithoutHash
48
+ urlWithoutHash: () => urlWithoutHash,
49
+ useInfiniteScroll: () => useInfiniteScroll
47
50
  });
48
51
  module.exports = __toCommonJS(index_exports);
49
52
 
53
+ // src/router.ts
54
+ var import_lodash_es3 = require("lodash-es");
55
+
50
56
  // src/debounce.ts
51
57
  function debounce(fn, delay) {
52
58
  let timeoutID;
@@ -75,6 +81,9 @@ var fireFinishEvent = (visit) => {
75
81
  var fireInvalidEvent = (response) => {
76
82
  return fireEvent("invalid", { cancelable: true, detail: { response } });
77
83
  };
84
+ var fireBeforeUpdateEvent = (page2) => {
85
+ return fireEvent("beforeUpdate", { detail: { page: page2 } });
86
+ };
78
87
  var fireNavigateEvent = (page2) => {
79
88
  return fireEvent("navigate", { detail: { page: page2 } });
80
89
  };
@@ -1237,6 +1246,7 @@ var PrefetchedRequests = class {
1237
1246
  "replace",
1238
1247
  "prefetch",
1239
1248
  "onBefore",
1249
+ "onBeforeUpdate",
1240
1250
  "onStart",
1241
1251
  "onProgress",
1242
1252
  "onFinish",
@@ -1265,6 +1275,7 @@ var RequestParams = class _RequestParams {
1265
1275
  } else {
1266
1276
  const wrappedCallbacks = {
1267
1277
  onBefore: this.wrapCallback(params, "onBefore"),
1278
+ onBeforeUpdate: this.wrapCallback(params, "onBeforeUpdate"),
1268
1279
  onStart: this.wrapCallback(params, "onStart"),
1269
1280
  onProgress: this.wrapCallback(params, "onProgress"),
1270
1281
  onFinish: this.wrapCallback(params, "onFinish"),
@@ -1395,6 +1406,9 @@ var RequestParams = class _RequestParams {
1395
1406
  }
1396
1407
  };
1397
1408
 
1409
+ // src/response.ts
1410
+ var import_lodash_es2 = require("lodash-es");
1411
+
1398
1412
  // src/modal.ts
1399
1413
  var modal_default = {
1400
1414
  modal: null,
@@ -1557,6 +1571,8 @@ var Response = class _Response {
1557
1571
  await this.setRememberedState(pageResponse);
1558
1572
  this.requestParams.setPreserveOptions(pageResponse);
1559
1573
  pageResponse.url = history.preserveUrl ? page.get().url : this.pageUrl(pageResponse);
1574
+ this.requestParams.all().onBeforeUpdate(pageResponse);
1575
+ fireBeforeUpdateEvent(pageResponse);
1560
1576
  return page.set(pageResponse, {
1561
1577
  replace: this.requestParams.all().replace,
1562
1578
  preserveScroll: this.requestParams.all().preserveScroll,
@@ -1596,36 +1612,43 @@ var Response = class _Response {
1596
1612
  if (!this.requestParams.isPartial() || pageResponse.component !== page.get().component) {
1597
1613
  return;
1598
1614
  }
1599
- const propsToMerge = pageResponse.mergeProps || [];
1615
+ const propsToAppend = pageResponse.mergeProps || [];
1616
+ const propsToPrepend = pageResponse.prependProps || [];
1600
1617
  const propsToDeepMerge = pageResponse.deepMergeProps || [];
1601
1618
  const matchPropsOn = pageResponse.matchPropsOn || [];
1602
- propsToMerge.forEach((prop) => {
1603
- const incomingProp = pageResponse.props[prop];
1619
+ const mergeProp = (prop, shouldAppend) => {
1620
+ const currentProp = (0, import_lodash_es2.get)(page.get().props, prop);
1621
+ const incomingProp = (0, import_lodash_es2.get)(pageResponse.props, prop);
1604
1622
  if (Array.isArray(incomingProp)) {
1605
- pageResponse.props[prop] = this.mergeOrMatchItems(
1606
- page.get().props[prop] || [],
1623
+ const newArray = this.mergeOrMatchItems(
1624
+ currentProp || [],
1607
1625
  incomingProp,
1608
1626
  prop,
1609
- matchPropsOn
1627
+ matchPropsOn,
1628
+ shouldAppend
1610
1629
  );
1630
+ (0, import_lodash_es2.set)(pageResponse.props, prop, newArray);
1611
1631
  } else if (typeof incomingProp === "object" && incomingProp !== null) {
1612
- pageResponse.props[prop] = {
1613
- ...page.get().props[prop] || [],
1632
+ const newObject = {
1633
+ ...currentProp || {},
1614
1634
  ...incomingProp
1615
1635
  };
1636
+ (0, import_lodash_es2.set)(pageResponse.props, prop, newObject);
1616
1637
  }
1617
- });
1638
+ };
1639
+ propsToAppend.forEach((prop) => mergeProp(prop, true));
1640
+ propsToPrepend.forEach((prop) => mergeProp(prop, false));
1618
1641
  propsToDeepMerge.forEach((prop) => {
1619
- const incomingProp = pageResponse.props[prop];
1620
1642
  const currentProp = page.get().props[prop];
1621
- const deepMerge = (target, source, currentKey) => {
1643
+ const incomingProp = pageResponse.props[prop];
1644
+ const deepMerge = (target, source, matchProp) => {
1622
1645
  if (Array.isArray(source)) {
1623
- return this.mergeOrMatchItems(target, source, currentKey, matchPropsOn);
1646
+ return this.mergeOrMatchItems(target, source, matchProp, matchPropsOn);
1624
1647
  }
1625
1648
  if (typeof source === "object" && source !== null) {
1626
1649
  return Object.keys(source).reduce(
1627
1650
  (acc, key) => {
1628
- acc[key] = deepMerge(target ? target[key] : void 0, source[key], `${currentKey}.${key}`);
1651
+ acc[key] = deepMerge(target ? target[key] : void 0, source[key], `${matchProp}.${key}`);
1629
1652
  return acc;
1630
1653
  },
1631
1654
  { ...target }
@@ -1637,32 +1660,52 @@ var Response = class _Response {
1637
1660
  });
1638
1661
  pageResponse.props = { ...page.get().props, ...pageResponse.props };
1639
1662
  }
1640
- mergeOrMatchItems(target, source, currentKey, matchPropsOn) {
1641
- const matchOn = matchPropsOn.find((key) => {
1642
- const path = key.split(".").slice(0, -1).join(".");
1643
- return path === currentKey;
1663
+ mergeOrMatchItems(existingItems, newItems, matchProp, matchPropsOn, shouldAppend = true) {
1664
+ const items = Array.isArray(existingItems) ? existingItems : [];
1665
+ const matchingKey = matchPropsOn.find((key) => {
1666
+ const keyPath = key.split(".").slice(0, -1).join(".");
1667
+ return keyPath === matchProp;
1644
1668
  });
1645
- if (!matchOn) {
1646
- return [...Array.isArray(target) ? target : [], ...source];
1647
- }
1648
- const uniqueProperty = matchOn.split(".").pop() || "";
1649
- const targetArray = Array.isArray(target) ? target : [];
1650
- const map = /* @__PURE__ */ new Map();
1651
- targetArray.forEach((item) => {
1652
- if (item && typeof item === "object" && uniqueProperty in item) {
1653
- map.set(item[uniqueProperty], item);
1654
- } else {
1655
- map.set(Symbol(), item);
1669
+ if (!matchingKey) {
1670
+ return shouldAppend ? [...items, ...newItems] : [...newItems, ...items];
1671
+ }
1672
+ const uniqueProperty = matchingKey.split(".").pop() || "";
1673
+ const newItemsMap = /* @__PURE__ */ new Map();
1674
+ newItems.forEach((item) => {
1675
+ if (this.hasUniqueProperty(item, uniqueProperty)) {
1676
+ newItemsMap.set(item[uniqueProperty], item);
1656
1677
  }
1657
1678
  });
1658
- source.forEach((item) => {
1659
- if (item && typeof item === "object" && uniqueProperty in item) {
1660
- map.set(item[uniqueProperty], item);
1661
- } else {
1662
- map.set(Symbol(), item);
1679
+ return shouldAppend ? this.appendWithMatching(items, newItems, newItemsMap, uniqueProperty) : this.prependWithMatching(items, newItems, newItemsMap, uniqueProperty);
1680
+ }
1681
+ appendWithMatching(existingItems, newItems, newItemsMap, uniqueProperty) {
1682
+ const updatedExisting = existingItems.map((item) => {
1683
+ if (this.hasUniqueProperty(item, uniqueProperty) && newItemsMap.has(item[uniqueProperty])) {
1684
+ return newItemsMap.get(item[uniqueProperty]);
1685
+ }
1686
+ return item;
1687
+ });
1688
+ const newItemsToAdd = newItems.filter((item) => {
1689
+ if (!this.hasUniqueProperty(item, uniqueProperty)) {
1690
+ return true;
1691
+ }
1692
+ return !existingItems.some(
1693
+ (existing) => this.hasUniqueProperty(existing, uniqueProperty) && existing[uniqueProperty] === item[uniqueProperty]
1694
+ );
1695
+ });
1696
+ return [...updatedExisting, ...newItemsToAdd];
1697
+ }
1698
+ prependWithMatching(existingItems, newItems, newItemsMap, uniqueProperty) {
1699
+ const untouchedExisting = existingItems.filter((item) => {
1700
+ if (this.hasUniqueProperty(item, uniqueProperty)) {
1701
+ return !newItemsMap.has(item[uniqueProperty]);
1663
1702
  }
1703
+ return true;
1664
1704
  });
1665
- return Array.from(map.values());
1705
+ return [...newItems, ...untouchedExisting];
1706
+ }
1707
+ hasUniqueProperty(item, property) {
1708
+ return item && typeof item === "object" && property in item;
1666
1709
  }
1667
1710
  async setRememberedState(pageResponse) {
1668
1711
  const rememberedState = await history.getState(history.rememberedState, {});
@@ -1918,10 +1961,10 @@ var Router = class {
1918
1961
  };
1919
1962
  const prefetched = prefetchedRequests.get(requestParams);
1920
1963
  if (prefetched) {
1921
- reveal(prefetched.inFlight);
1964
+ progress.reveal(prefetched.inFlight);
1922
1965
  prefetchedRequests.use(prefetched, requestParams);
1923
1966
  } else {
1924
- reveal(true);
1967
+ progress.reveal(true);
1925
1968
  requestStream.send(Request.create(requestParams, page.get()));
1926
1969
  }
1927
1970
  }
@@ -1960,7 +2003,7 @@ var Router = class {
1960
2003
  if (events.onBefore(visit) === false || !fireBeforeEvent(visit)) {
1961
2004
  return;
1962
2005
  }
1963
- hide();
2006
+ progress.hide();
1964
2007
  this.asyncRequestStream.interruptInFlight();
1965
2008
  const requestParams = {
1966
2009
  ...visit,
@@ -2004,6 +2047,43 @@ var Router = class {
2004
2047
  replace(params) {
2005
2048
  this.clientVisit(params, { replace: true });
2006
2049
  }
2050
+ replaceProp(name, value, options) {
2051
+ this.replace({
2052
+ preserveScroll: true,
2053
+ preserveState: true,
2054
+ props(currentProps) {
2055
+ const newValue = typeof value === "function" ? value((0, import_lodash_es3.get)(currentProps, name), currentProps) : value;
2056
+ return (0, import_lodash_es3.set)((0, import_lodash_es3.cloneDeep)(currentProps), name, newValue);
2057
+ },
2058
+ ...options || {}
2059
+ });
2060
+ }
2061
+ appendToProp(name, value, options) {
2062
+ this.replaceProp(
2063
+ name,
2064
+ (currentValue, currentProps) => {
2065
+ const newValue = typeof value === "function" ? value(currentValue, currentProps) : value;
2066
+ if (!Array.isArray(currentValue)) {
2067
+ currentValue = currentValue !== void 0 ? [currentValue] : [];
2068
+ }
2069
+ return [...currentValue, newValue];
2070
+ },
2071
+ options
2072
+ );
2073
+ }
2074
+ prependToProp(name, value, options) {
2075
+ this.replaceProp(
2076
+ name,
2077
+ (currentValue, currentProps) => {
2078
+ const newValue = typeof value === "function" ? value(currentValue, currentProps) : value;
2079
+ if (!Array.isArray(currentValue)) {
2080
+ currentValue = currentValue !== void 0 ? [currentValue] : [];
2081
+ }
2082
+ return [newValue, ...currentValue];
2083
+ },
2084
+ options
2085
+ );
2086
+ }
2007
2087
  push(params) {
2008
2088
  this.clientVisit(params);
2009
2089
  }
@@ -2096,6 +2176,8 @@ var Router = class {
2096
2176
  }),
2097
2177
  onBefore: options.onBefore || (() => {
2098
2178
  }),
2179
+ onBeforeUpdate: options.onBeforeUpdate || (() => {
2180
+ }),
2099
2181
  onStart: options.onStart || (() => {
2100
2182
  }),
2101
2183
  onProgress: options.onProgress || (() => {
@@ -2123,8 +2205,48 @@ var Router = class {
2123
2205
  }
2124
2206
  };
2125
2207
 
2208
+ // src/domUtils.ts
2209
+ var elementInViewport = (el) => {
2210
+ const rect = el.getBoundingClientRect();
2211
+ const verticallyVisible = rect.top < window.innerHeight && rect.bottom >= 0;
2212
+ const horizontallyVisible = rect.left < window.innerWidth && rect.right >= 0;
2213
+ return verticallyVisible && horizontallyVisible;
2214
+ };
2215
+ var getScrollableParent = (element) => {
2216
+ let parent = element?.parentElement;
2217
+ while (parent) {
2218
+ const overflowY = window.getComputedStyle(parent).overflowY;
2219
+ if (overflowY === "auto" || overflowY === "scroll") {
2220
+ return parent;
2221
+ }
2222
+ parent = parent.parentElement;
2223
+ }
2224
+ return null;
2225
+ };
2226
+ var getElementsInViewportFromCollection = (referenceElement, elements) => {
2227
+ const referenceIndex = elements.indexOf(referenceElement);
2228
+ const visibleElements = [];
2229
+ for (let i = referenceIndex; i >= 0; i--) {
2230
+ const element = elements[i];
2231
+ if (elementInViewport(element)) {
2232
+ visibleElements.push(element);
2233
+ } else {
2234
+ break;
2235
+ }
2236
+ }
2237
+ for (let i = referenceIndex + 1; i < elements.length; i++) {
2238
+ const element = elements[i];
2239
+ if (elementInViewport(element)) {
2240
+ visibleElements.push(element);
2241
+ } else {
2242
+ break;
2243
+ }
2244
+ }
2245
+ return visibleElements;
2246
+ };
2247
+
2126
2248
  // src/formObject.ts
2127
- var import_lodash_es2 = require("lodash-es");
2249
+ var import_lodash_es4 = require("lodash-es");
2128
2250
  function undotKey(key) {
2129
2251
  if (!key.includes(".")) {
2130
2252
  return key;
@@ -2159,15 +2281,15 @@ function formDataToObject(source) {
2159
2281
  const path = parseKey(undotKey(key));
2160
2282
  if (path[path.length - 1] === "") {
2161
2283
  const arrayPath = path.slice(0, -1);
2162
- const existing = (0, import_lodash_es2.get)(form, arrayPath);
2284
+ const existing = (0, import_lodash_es4.get)(form, arrayPath);
2163
2285
  if (Array.isArray(existing)) {
2164
2286
  existing.push(value);
2165
2287
  } else {
2166
- (0, import_lodash_es2.set)(form, arrayPath, [value]);
2288
+ (0, import_lodash_es4.set)(form, arrayPath, [value]);
2167
2289
  }
2168
2290
  continue;
2169
2291
  }
2170
- (0, import_lodash_es2.set)(form, path, value);
2292
+ (0, import_lodash_es4.set)(form, path, value);
2171
2293
  }
2172
2294
  return form;
2173
2295
  }
@@ -2284,6 +2406,380 @@ function createHeadManager(isServer2, titleCallback, onUpdate) {
2284
2406
  };
2285
2407
  }
2286
2408
 
2409
+ // src/infiniteScroll/data.ts
2410
+ var MERGE_INTENT_HEADER = "X-Inertia-Infinite-Scroll-Merge-Intent";
2411
+ var useInfiniteScrollData = (options) => {
2412
+ const getScrollPropFromCurrentPage = () => {
2413
+ const scrollProp = page.get().scrollProps?.[options.getPropName()];
2414
+ if (scrollProp) {
2415
+ return scrollProp;
2416
+ }
2417
+ throw new Error(`The page object does not contain a scroll prop named "${options.getPropName()}".`);
2418
+ };
2419
+ const { previousPage, nextPage, currentPage: lastLoadedPage } = getScrollPropFromCurrentPage();
2420
+ const state = {
2421
+ loading: false,
2422
+ previousPage,
2423
+ nextPage,
2424
+ lastLoadedPage
2425
+ };
2426
+ const getScrollPropKeyForSide = (side) => {
2427
+ return side === "next" ? "nextPage" : "previousPage";
2428
+ };
2429
+ const findPageToLoad = (side) => {
2430
+ const pagePropName = getScrollPropKeyForSide(side);
2431
+ return state[pagePropName];
2432
+ };
2433
+ const syncStateOnSuccess = (side) => {
2434
+ const scrollProp = getScrollPropFromCurrentPage();
2435
+ const paginationProp = getScrollPropKeyForSide(side);
2436
+ state.lastLoadedPage = scrollProp.currentPage;
2437
+ state[paginationProp] = scrollProp[paginationProp];
2438
+ };
2439
+ const getPageName = () => getScrollPropFromCurrentPage().pageName;
2440
+ const fetchPage = (side, reloadOptions = {}) => {
2441
+ const page2 = findPageToLoad(side);
2442
+ if (state.loading || page2 === null) {
2443
+ return;
2444
+ }
2445
+ state.loading = true;
2446
+ router.reload({
2447
+ ...reloadOptions,
2448
+ data: { [getPageName()]: page2 },
2449
+ only: [options.getPropName()],
2450
+ preserveUrl: true,
2451
+ // we handle URL updates manually via useInfiniteScrollQueryString()
2452
+ headers: {
2453
+ [MERGE_INTENT_HEADER]: side === "previous" ? "prepend" : "append",
2454
+ ...reloadOptions.headers
2455
+ },
2456
+ onBefore: (visit) => {
2457
+ side === "next" ? options.onBeforeNextRequest() : options.onBeforePreviousRequest();
2458
+ reloadOptions.onBefore?.(visit);
2459
+ },
2460
+ onBeforeUpdate: (page3) => {
2461
+ options.onBeforeUpdate();
2462
+ reloadOptions.onBeforeUpdate?.(page3);
2463
+ },
2464
+ onSuccess: (page3) => {
2465
+ syncStateOnSuccess(side);
2466
+ reloadOptions.onSuccess?.(page3);
2467
+ },
2468
+ onFinish: (visit) => {
2469
+ state.loading = false;
2470
+ side === "next" ? options.onCompleteNextRequest(state.lastLoadedPage) : options.onCompletePreviousRequest(state.lastLoadedPage);
2471
+ reloadOptions.onFinish?.(visit);
2472
+ }
2473
+ });
2474
+ };
2475
+ const getLastLoadedPage = () => state.lastLoadedPage;
2476
+ const hasPrevious = () => !!state.previousPage;
2477
+ const hasNext = () => !!state.nextPage;
2478
+ const fetchPrevious = (reloadOptions) => fetchPage("previous", reloadOptions);
2479
+ const fetchNext = (reloadOptions) => fetchPage("next", reloadOptions);
2480
+ return {
2481
+ getLastLoadedPage,
2482
+ getPageName,
2483
+ hasPrevious,
2484
+ hasNext,
2485
+ fetchNext,
2486
+ fetchPrevious
2487
+ };
2488
+ };
2489
+
2490
+ // src/intersectionObservers.ts
2491
+ var useIntersectionObservers = () => {
2492
+ const intersectionObservers = [];
2493
+ const newIntersectionObserver = (callback, options = {}) => {
2494
+ const observer = new IntersectionObserver((entries) => {
2495
+ for (const entry of entries) {
2496
+ if (entry.isIntersecting) {
2497
+ callback(entry);
2498
+ }
2499
+ }
2500
+ }, options);
2501
+ intersectionObservers.push(observer);
2502
+ return observer;
2503
+ };
2504
+ const flushAll = () => {
2505
+ intersectionObservers.forEach((observer) => observer.disconnect());
2506
+ intersectionObservers.length = 0;
2507
+ };
2508
+ return {
2509
+ new: newIntersectionObserver,
2510
+ flushAll
2511
+ };
2512
+ };
2513
+
2514
+ // src/infiniteScroll/elements.ts
2515
+ var INFINITE_SCROLL_PAGE_KEY = "infiniteScrollPage";
2516
+ var INFINITE_SCROLL_IGNORE_KEY = "infiniteScrollIgnore";
2517
+ var getPageFromElement = (element) => element.dataset[INFINITE_SCROLL_PAGE_KEY];
2518
+ var useInfiniteScrollElementManager = (options) => {
2519
+ const intersectionObservers = useIntersectionObservers();
2520
+ let itemsObserver;
2521
+ let startElementObserver;
2522
+ let endElementObserver;
2523
+ let itemsMutationObserver;
2524
+ let triggersEnabled = false;
2525
+ const setupObservers = () => {
2526
+ itemsMutationObserver = new MutationObserver((mutations) => {
2527
+ mutations.forEach((mutation) => {
2528
+ mutation.addedNodes.forEach((node) => {
2529
+ if (node.nodeType === Node.ELEMENT_NODE) {
2530
+ addedElements.add(node);
2531
+ }
2532
+ });
2533
+ });
2534
+ });
2535
+ itemsMutationObserver.observe(options.getItemsElement(), { childList: true });
2536
+ itemsObserver = intersectionObservers.new(
2537
+ (entry) => options.onItemIntersected(entry.target),
2538
+ { threshold: 0 }
2539
+ );
2540
+ const observerOptions = {
2541
+ root: options.getScrollableParent(),
2542
+ rootMargin: `${Math.max(1, options.getTriggerMargin())}px`
2543
+ };
2544
+ startElementObserver = intersectionObservers.new(options.onPreviousTriggered, observerOptions);
2545
+ endElementObserver = intersectionObservers.new(options.onNextTriggered, observerOptions);
2546
+ };
2547
+ const enableTriggers = () => {
2548
+ if (triggersEnabled) {
2549
+ disableTriggers();
2550
+ }
2551
+ const startElement = options.getStartElement();
2552
+ const endElement = options.getEndElement();
2553
+ if (startElement && options.shouldFetchPrevious()) {
2554
+ startElementObserver.observe(startElement);
2555
+ }
2556
+ if (endElement && options.shouldFetchNext()) {
2557
+ endElementObserver.observe(endElement);
2558
+ }
2559
+ triggersEnabled = true;
2560
+ };
2561
+ const disableTriggers = () => {
2562
+ if (!triggersEnabled) {
2563
+ return;
2564
+ }
2565
+ startElementObserver.disconnect();
2566
+ endElementObserver.disconnect();
2567
+ triggersEnabled = false;
2568
+ };
2569
+ const refreshTriggers = () => {
2570
+ if (triggersEnabled) {
2571
+ enableTriggers();
2572
+ }
2573
+ };
2574
+ const flushAll = () => {
2575
+ intersectionObservers.flushAll();
2576
+ itemsMutationObserver?.disconnect();
2577
+ };
2578
+ const addedElements = /* @__PURE__ */ new Set();
2579
+ const elementIsUntagged = (element) => !(INFINITE_SCROLL_PAGE_KEY in element.dataset) && !(INFINITE_SCROLL_IGNORE_KEY in element.dataset);
2580
+ const processManuallyAddedElements = () => {
2581
+ Array.from(addedElements).forEach((element) => {
2582
+ if (elementIsUntagged(element)) {
2583
+ element.dataset[INFINITE_SCROLL_IGNORE_KEY] = "true";
2584
+ }
2585
+ itemsObserver.observe(element);
2586
+ });
2587
+ addedElements.clear();
2588
+ };
2589
+ const findUntaggedElements = (containerElement) => {
2590
+ return Array.from(
2591
+ containerElement.querySelectorAll(
2592
+ `:scope > *:not([data-infinite-scroll-page]):not([data-infinite-scroll-ignore])`
2593
+ )
2594
+ );
2595
+ };
2596
+ const processServerLoadedElements = (loadedPage) => {
2597
+ findUntaggedElements(options.getItemsElement()).forEach((element) => {
2598
+ if (elementIsUntagged(element)) {
2599
+ element.dataset[INFINITE_SCROLL_PAGE_KEY] = loadedPage?.toString() || "1";
2600
+ }
2601
+ itemsObserver.observe(element);
2602
+ });
2603
+ };
2604
+ return {
2605
+ setupObservers,
2606
+ enableTriggers,
2607
+ disableTriggers,
2608
+ refreshTriggers,
2609
+ flushAll,
2610
+ processManuallyAddedElements,
2611
+ processServerLoadedElements
2612
+ };
2613
+ };
2614
+
2615
+ // src/infiniteScroll/queryString.ts
2616
+ var useInfiniteScrollQueryString = (options) => {
2617
+ const onItemIntersected = debounce((itemElement) => {
2618
+ if (options.shouldPreserveUrl() || !itemElement) {
2619
+ return;
2620
+ }
2621
+ const pageMap = /* @__PURE__ */ new Map();
2622
+ const elements = [...options.getItemsElement().children];
2623
+ getElementsInViewportFromCollection(itemElement, elements).forEach((element) => {
2624
+ const page2 = getPageFromElement(element) ?? "1";
2625
+ if (pageMap.has(page2)) {
2626
+ pageMap.set(page2, pageMap.get(page2) + 1);
2627
+ } else {
2628
+ pageMap.set(page2, 1);
2629
+ }
2630
+ });
2631
+ const sortedPages = Array.from(pageMap.entries()).sort((a, b) => b[1] - a[1]);
2632
+ const mostVisiblePage = sortedPages[0]?.[0];
2633
+ if (mostVisiblePage === void 0) {
2634
+ return;
2635
+ }
2636
+ const url = new URL(window.location.href);
2637
+ if (mostVisiblePage === "1") {
2638
+ url.searchParams.delete(options.getPageName());
2639
+ } else {
2640
+ url.searchParams.set(options.getPageName(), mostVisiblePage.toString());
2641
+ }
2642
+ router.replace({
2643
+ url: url.toString(),
2644
+ preserveScroll: true,
2645
+ preserveState: true
2646
+ });
2647
+ }, 250);
2648
+ return {
2649
+ onItemIntersected
2650
+ };
2651
+ };
2652
+
2653
+ // src/infiniteScroll/scrollPreservation.ts
2654
+ var useInfiniteScrollPreservation = (options) => {
2655
+ const createCallbacks = () => {
2656
+ let currentScrollTop;
2657
+ let referenceElement = null;
2658
+ let referenceElementTop = 0;
2659
+ const captureScrollPosition = () => {
2660
+ const scrollableContainer = options.getScrollableParent();
2661
+ const itemsElement = options.getItemsElement();
2662
+ currentScrollTop = scrollableContainer?.scrollTop || window.scrollY;
2663
+ const visibleElements = getElementsInViewportFromCollection(
2664
+ itemsElement.firstElementChild,
2665
+ [...itemsElement.children]
2666
+ );
2667
+ if (visibleElements.length > 0) {
2668
+ referenceElement = visibleElements[0];
2669
+ const containerRect = scrollableContainer?.getBoundingClientRect() || { top: 0 };
2670
+ const containerTop = scrollableContainer ? containerRect.top : 0;
2671
+ const rect = referenceElement.getBoundingClientRect();
2672
+ referenceElementTop = rect.top - containerTop;
2673
+ }
2674
+ };
2675
+ const restoreScrollPosition = () => {
2676
+ if (!referenceElement) {
2677
+ return;
2678
+ }
2679
+ let attempts = 0;
2680
+ let restored = false;
2681
+ const restore = () => {
2682
+ attempts++;
2683
+ if (restored || attempts > 10) {
2684
+ return false;
2685
+ }
2686
+ const scrollableContainer = options.getScrollableParent();
2687
+ const containerRect = scrollableContainer?.getBoundingClientRect() || { top: 0 };
2688
+ const containerTop = scrollableContainer ? containerRect.top : 0;
2689
+ const newRect = referenceElement.getBoundingClientRect();
2690
+ const newElementTop = newRect.top - containerTop;
2691
+ const adjustment = newElementTop - referenceElementTop;
2692
+ if (adjustment === 0) {
2693
+ window.requestAnimationFrame(restore);
2694
+ return;
2695
+ }
2696
+ if (scrollableContainer) {
2697
+ scrollableContainer.scrollTo({ top: currentScrollTop + adjustment });
2698
+ } else {
2699
+ window.scrollTo(0, window.scrollY + adjustment);
2700
+ }
2701
+ restored = true;
2702
+ };
2703
+ restore();
2704
+ };
2705
+ return {
2706
+ captureScrollPosition,
2707
+ restoreScrollPosition
2708
+ };
2709
+ };
2710
+ return {
2711
+ createCallbacks
2712
+ };
2713
+ };
2714
+
2715
+ // src/infiniteScroll.ts
2716
+ function useInfiniteScroll(options) {
2717
+ const queryStringManager = useInfiniteScrollQueryString({ ...options, getPageName: () => dataManager.getPageName() });
2718
+ const scrollPreservation = useInfiniteScrollPreservation(options);
2719
+ const elementManager = useInfiniteScrollElementManager({
2720
+ ...options,
2721
+ // As items enter viewport, update URL to reflect the most visible page
2722
+ onItemIntersected: queryStringManager.onItemIntersected,
2723
+ onPreviousTriggered: () => dataManager.fetchPrevious(),
2724
+ onNextTriggered: () => dataManager.fetchNext()
2725
+ });
2726
+ const dataManager = useInfiniteScrollData({
2727
+ ...options,
2728
+ // Before updating page data, tag any manually added DOM elements
2729
+ // so they don't get confused with server-loaded content
2730
+ onBeforeUpdate: elementManager.processManuallyAddedElements,
2731
+ // After successful request, tag new server content
2732
+ onCompletePreviousRequest: (loadedPage) => {
2733
+ setTimeout(() => {
2734
+ elementManager.processServerLoadedElements(loadedPage);
2735
+ options.onCompletePreviousRequest();
2736
+ window.queueMicrotask(elementManager.refreshTriggers);
2737
+ });
2738
+ },
2739
+ onCompleteNextRequest: (loadedPage) => {
2740
+ setTimeout(() => {
2741
+ elementManager.processServerLoadedElements(loadedPage);
2742
+ options.onCompleteNextRequest();
2743
+ window.queueMicrotask(elementManager.refreshTriggers);
2744
+ });
2745
+ }
2746
+ });
2747
+ const addScrollPreservationCallbacks = (reloadOptions) => {
2748
+ const { captureScrollPosition, restoreScrollPosition } = scrollPreservation.createCallbacks();
2749
+ const originalOnBeforeUpdate = reloadOptions.onBeforeUpdate || (() => {
2750
+ });
2751
+ const originalOnSuccess = reloadOptions.onSuccess || (() => {
2752
+ });
2753
+ reloadOptions.onBeforeUpdate = (page2) => {
2754
+ originalOnBeforeUpdate(page2);
2755
+ captureScrollPosition();
2756
+ };
2757
+ reloadOptions.onSuccess = (page2) => {
2758
+ originalOnSuccess(page2);
2759
+ restoreScrollPosition();
2760
+ };
2761
+ return reloadOptions;
2762
+ };
2763
+ const originalFetchNext = dataManager.fetchNext;
2764
+ dataManager.fetchNext = (reloadOptions = {}) => {
2765
+ if (options.inReverseMode()) {
2766
+ reloadOptions = addScrollPreservationCallbacks(reloadOptions);
2767
+ }
2768
+ originalFetchNext(reloadOptions);
2769
+ };
2770
+ const originalFetchPrevious = dataManager.fetchPrevious;
2771
+ dataManager.fetchPrevious = (reloadOptions = {}) => {
2772
+ if (!options.inReverseMode()) {
2773
+ reloadOptions = addScrollPreservationCallbacks(reloadOptions);
2774
+ }
2775
+ originalFetchPrevious(reloadOptions);
2776
+ };
2777
+ return {
2778
+ dataManager,
2779
+ elementManager
2780
+ };
2781
+ }
2782
+
2287
2783
  // src/navigationEvents.ts
2288
2784
  function shouldIntercept(event) {
2289
2785
  const isLink = event.currentTarget.tagName.toLowerCase() === "a";
@@ -2296,7 +2792,7 @@ function shouldNavigate(event) {
2296
2792
 
2297
2793
  // src/progress-component.ts
2298
2794
  var baseComponentSelector = "nprogress";
2299
- var progress;
2795
+ var progress2;
2300
2796
  var settings = {
2301
2797
  minimum: 0.08,
2302
2798
  easing: "linear",
@@ -2325,11 +2821,11 @@ var configure = (options) => {
2325
2821
  if (settings.includeCSS) {
2326
2822
  injectCSS(settings.color);
2327
2823
  }
2328
- progress = document.createElement("div");
2329
- progress.id = baseComponentSelector;
2330
- progress.innerHTML = settings.template;
2824
+ progress2 = document.createElement("div");
2825
+ progress2.id = baseComponentSelector;
2826
+ progress2.innerHTML = settings.template;
2331
2827
  };
2332
- var set2 = (n) => {
2828
+ var set4 = (n) => {
2333
2829
  const started = isStarted();
2334
2830
  n = clamp(n, settings.minimum, 1);
2335
2831
  status = n === 1 ? null : n;
@@ -2378,7 +2874,7 @@ var set2 = (n) => {
2378
2874
  var isStarted = () => typeof status === "number";
2379
2875
  var start = () => {
2380
2876
  if (!status) {
2381
- set2(0);
2877
+ set4(0);
2382
2878
  }
2383
2879
  const work = function() {
2384
2880
  setTimeout(function() {
@@ -2398,7 +2894,7 @@ var done = (force) => {
2398
2894
  return;
2399
2895
  }
2400
2896
  increaseByRandom(0.3 + 0.5 * Math.random());
2401
- set2(1);
2897
+ set4(1);
2402
2898
  };
2403
2899
  var increaseByRandom = (amount) => {
2404
2900
  const n = status;
@@ -2422,26 +2918,26 @@ var increaseByRandom = (amount) => {
2422
2918
  }
2423
2919
  return 0;
2424
2920
  })();
2425
- return set2(clamp(n + amount, 0, 0.994));
2921
+ return set4(clamp(n + amount, 0, 0.994));
2426
2922
  };
2427
2923
  var render = (fromStart) => {
2428
2924
  if (isRendered()) {
2429
2925
  return document.getElementById(baseComponentSelector);
2430
2926
  }
2431
2927
  document.documentElement.classList.add(`${baseComponentSelector}-busy`);
2432
- const bar = progress.querySelector(settings.barSelector);
2928
+ const bar = progress2.querySelector(settings.barSelector);
2433
2929
  const perc = fromStart ? "-100" : toBarPercentage(status || 0);
2434
2930
  const parent = getParent();
2435
2931
  bar.style.transition = "all 0 linear";
2436
2932
  bar.style.transform = `translate3d(${perc}%,0,0)`;
2437
2933
  if (!settings.showSpinner) {
2438
- progress.querySelector(settings.spinnerSelector)?.remove();
2934
+ progress2.querySelector(settings.spinnerSelector)?.remove();
2439
2935
  }
2440
2936
  if (parent !== document.body) {
2441
2937
  parent.classList.add(`${baseComponentSelector}-custom-parent`);
2442
2938
  }
2443
- parent.appendChild(progress);
2444
- return progress;
2939
+ parent.appendChild(progress2);
2940
+ return progress2;
2445
2941
  };
2446
2942
  var getParent = () => {
2447
2943
  return isDOM(settings.parent) ? settings.parent : document.querySelector(settings.parent);
@@ -2449,7 +2945,7 @@ var getParent = () => {
2449
2945
  var remove = () => {
2450
2946
  document.documentElement.classList.remove(`${baseComponentSelector}-busy`);
2451
2947
  getParent().classList.remove(`${baseComponentSelector}-custom-parent`);
2452
- progress?.remove();
2948
+ progress2?.remove();
2453
2949
  };
2454
2950
  var isRendered = () => {
2455
2951
  return document.getElementById(baseComponentSelector) !== null;
@@ -2555,67 +3051,95 @@ var injectCSS = (color) => {
2555
3051
  document.head.appendChild(element);
2556
3052
  };
2557
3053
  var show = () => {
2558
- if (progress) {
2559
- progress.style.display = "";
3054
+ if (progress2) {
3055
+ progress2.style.display = "";
2560
3056
  }
2561
3057
  };
2562
- var hide2 = () => {
2563
- if (progress) {
2564
- progress.style.display = "none";
3058
+ var hide = () => {
3059
+ if (progress2) {
3060
+ progress2.style.display = "none";
2565
3061
  }
2566
3062
  };
2567
3063
  var progress_component_default = {
2568
3064
  configure,
2569
3065
  isStarted,
2570
3066
  done,
2571
- set: set2,
3067
+ set: set4,
2572
3068
  remove,
2573
3069
  start,
2574
3070
  status,
2575
3071
  show,
2576
- hide: hide2
3072
+ hide
2577
3073
  };
2578
3074
 
2579
3075
  // src/progress.ts
2580
- var hideCount = 0;
2581
- var reveal = (force = false) => {
2582
- hideCount = Math.max(0, hideCount - 1);
2583
- if (force || hideCount === 0) {
2584
- progress_component_default.show();
3076
+ var Progress = class {
3077
+ constructor() {
3078
+ this.hideCount = 0;
3079
+ }
3080
+ start() {
3081
+ progress_component_default.start();
3082
+ }
3083
+ reveal(force = false) {
3084
+ this.hideCount = Math.max(0, this.hideCount - 1);
3085
+ if (force || this.hideCount === 0) {
3086
+ progress_component_default.show();
3087
+ }
3088
+ }
3089
+ hide() {
3090
+ this.hideCount++;
3091
+ progress_component_default.hide();
3092
+ }
3093
+ set(status2) {
3094
+ progress_component_default.set(Math.max(0, Math.min(1, status2)));
3095
+ }
3096
+ finish() {
3097
+ progress_component_default.done();
3098
+ }
3099
+ reset() {
3100
+ progress_component_default.set(0);
3101
+ }
3102
+ remove() {
3103
+ progress_component_default.done();
3104
+ progress_component_default.remove();
3105
+ }
3106
+ isStarted() {
3107
+ return progress_component_default.isStarted();
3108
+ }
3109
+ getStatus() {
3110
+ return progress_component_default.status;
2585
3111
  }
2586
3112
  };
2587
- var hide = () => {
2588
- hideCount++;
2589
- progress_component_default.hide();
2590
- };
3113
+ var progress = new Progress();
3114
+ var reveal = progress.reveal;
3115
+ var hide2 = progress.hide;
2591
3116
  function addEventListeners(delay) {
2592
- document.addEventListener("inertia:start", (e) => start2(e, delay));
2593
- document.addEventListener("inertia:progress", progress2);
3117
+ document.addEventListener("inertia:start", (e) => handleStartEvent(e, delay));
3118
+ document.addEventListener("inertia:progress", handleProgressEvent);
2594
3119
  }
2595
- function start2(event, delay) {
3120
+ function handleStartEvent(event, delay) {
2596
3121
  if (!event.detail.visit.showProgress) {
2597
- hide();
3122
+ progress.hide();
2598
3123
  }
2599
- const timeout = setTimeout(() => progress_component_default.start(), delay);
3124
+ const timeout = setTimeout(() => progress.start(), delay);
2600
3125
  document.addEventListener("inertia:finish", (e) => finish(e, timeout), { once: true });
2601
3126
  }
2602
- function progress2(event) {
2603
- if (progress_component_default.isStarted() && event.detail.progress?.percentage) {
2604
- progress_component_default.set(Math.max(progress_component_default.status, event.detail.progress.percentage / 100 * 0.9));
3127
+ function handleProgressEvent(event) {
3128
+ if (progress.isStarted() && event.detail.progress?.percentage) {
3129
+ progress.set(Math.max(progress.getStatus(), event.detail.progress.percentage / 100 * 0.9));
2605
3130
  }
2606
3131
  }
2607
3132
  function finish(event, timeout) {
2608
3133
  clearTimeout(timeout);
2609
- if (!progress_component_default.isStarted()) {
3134
+ if (!progress.isStarted()) {
2610
3135
  return;
2611
3136
  }
2612
3137
  if (event.detail.visit.completed) {
2613
- progress_component_default.done();
3138
+ progress.finish();
2614
3139
  } else if (event.detail.visit.interrupted) {
2615
- progress_component_default.set(0);
3140
+ progress.reset();
2616
3141
  } else if (event.detail.visit.cancelled) {
2617
- progress_component_default.done();
2618
- progress_component_default.remove();
3142
+ progress.remove();
2619
3143
  }
2620
3144
  }
2621
3145
  function setupProgress({