@inertiajs/core 2.1.11 → 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,6 +32,7 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  createHeadManager: () => createHeadManager,
34
34
  formDataToObject: () => formDataToObject,
35
+ getScrollableParent: () => getScrollableParent,
35
36
  hideProgress: () => hide2,
36
37
  hrefToUrl: () => hrefToUrl,
37
38
  isUrlMethodPair: () => isUrlMethodPair,
@@ -44,10 +45,14 @@ __export(index_exports, {
44
45
  setupProgress: () => setupProgress,
45
46
  shouldIntercept: () => shouldIntercept,
46
47
  shouldNavigate: () => shouldNavigate,
47
- urlWithoutHash: () => urlWithoutHash
48
+ urlWithoutHash: () => urlWithoutHash,
49
+ useInfiniteScroll: () => useInfiniteScroll
48
50
  });
49
51
  module.exports = __toCommonJS(index_exports);
50
52
 
53
+ // src/router.ts
54
+ var import_lodash_es3 = require("lodash-es");
55
+
51
56
  // src/debounce.ts
52
57
  function debounce(fn, delay) {
53
58
  let timeoutID;
@@ -76,6 +81,9 @@ var fireFinishEvent = (visit) => {
76
81
  var fireInvalidEvent = (response) => {
77
82
  return fireEvent("invalid", { cancelable: true, detail: { response } });
78
83
  };
84
+ var fireBeforeUpdateEvent = (page2) => {
85
+ return fireEvent("beforeUpdate", { detail: { page: page2 } });
86
+ };
79
87
  var fireNavigateEvent = (page2) => {
80
88
  return fireEvent("navigate", { detail: { page: page2 } });
81
89
  };
@@ -1238,6 +1246,7 @@ var PrefetchedRequests = class {
1238
1246
  "replace",
1239
1247
  "prefetch",
1240
1248
  "onBefore",
1249
+ "onBeforeUpdate",
1241
1250
  "onStart",
1242
1251
  "onProgress",
1243
1252
  "onFinish",
@@ -1266,6 +1275,7 @@ var RequestParams = class _RequestParams {
1266
1275
  } else {
1267
1276
  const wrappedCallbacks = {
1268
1277
  onBefore: this.wrapCallback(params, "onBefore"),
1278
+ onBeforeUpdate: this.wrapCallback(params, "onBeforeUpdate"),
1269
1279
  onStart: this.wrapCallback(params, "onStart"),
1270
1280
  onProgress: this.wrapCallback(params, "onProgress"),
1271
1281
  onFinish: this.wrapCallback(params, "onFinish"),
@@ -1396,6 +1406,9 @@ var RequestParams = class _RequestParams {
1396
1406
  }
1397
1407
  };
1398
1408
 
1409
+ // src/response.ts
1410
+ var import_lodash_es2 = require("lodash-es");
1411
+
1399
1412
  // src/modal.ts
1400
1413
  var modal_default = {
1401
1414
  modal: null,
@@ -1558,6 +1571,8 @@ var Response = class _Response {
1558
1571
  await this.setRememberedState(pageResponse);
1559
1572
  this.requestParams.setPreserveOptions(pageResponse);
1560
1573
  pageResponse.url = history.preserveUrl ? page.get().url : this.pageUrl(pageResponse);
1574
+ this.requestParams.all().onBeforeUpdate(pageResponse);
1575
+ fireBeforeUpdateEvent(pageResponse);
1561
1576
  return page.set(pageResponse, {
1562
1577
  replace: this.requestParams.all().replace,
1563
1578
  preserveScroll: this.requestParams.all().preserveScroll,
@@ -1597,36 +1612,43 @@ var Response = class _Response {
1597
1612
  if (!this.requestParams.isPartial() || pageResponse.component !== page.get().component) {
1598
1613
  return;
1599
1614
  }
1600
- const propsToMerge = pageResponse.mergeProps || [];
1615
+ const propsToAppend = pageResponse.mergeProps || [];
1616
+ const propsToPrepend = pageResponse.prependProps || [];
1601
1617
  const propsToDeepMerge = pageResponse.deepMergeProps || [];
1602
1618
  const matchPropsOn = pageResponse.matchPropsOn || [];
1603
- propsToMerge.forEach((prop) => {
1604
- 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);
1605
1622
  if (Array.isArray(incomingProp)) {
1606
- pageResponse.props[prop] = this.mergeOrMatchItems(
1607
- page.get().props[prop] || [],
1623
+ const newArray = this.mergeOrMatchItems(
1624
+ currentProp || [],
1608
1625
  incomingProp,
1609
1626
  prop,
1610
- matchPropsOn
1627
+ matchPropsOn,
1628
+ shouldAppend
1611
1629
  );
1630
+ (0, import_lodash_es2.set)(pageResponse.props, prop, newArray);
1612
1631
  } else if (typeof incomingProp === "object" && incomingProp !== null) {
1613
- pageResponse.props[prop] = {
1614
- ...page.get().props[prop] || [],
1632
+ const newObject = {
1633
+ ...currentProp || {},
1615
1634
  ...incomingProp
1616
1635
  };
1636
+ (0, import_lodash_es2.set)(pageResponse.props, prop, newObject);
1617
1637
  }
1618
- });
1638
+ };
1639
+ propsToAppend.forEach((prop) => mergeProp(prop, true));
1640
+ propsToPrepend.forEach((prop) => mergeProp(prop, false));
1619
1641
  propsToDeepMerge.forEach((prop) => {
1620
- const incomingProp = pageResponse.props[prop];
1621
1642
  const currentProp = page.get().props[prop];
1622
- const deepMerge = (target, source, currentKey) => {
1643
+ const incomingProp = pageResponse.props[prop];
1644
+ const deepMerge = (target, source, matchProp) => {
1623
1645
  if (Array.isArray(source)) {
1624
- return this.mergeOrMatchItems(target, source, currentKey, matchPropsOn);
1646
+ return this.mergeOrMatchItems(target, source, matchProp, matchPropsOn);
1625
1647
  }
1626
1648
  if (typeof source === "object" && source !== null) {
1627
1649
  return Object.keys(source).reduce(
1628
1650
  (acc, key) => {
1629
- 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}`);
1630
1652
  return acc;
1631
1653
  },
1632
1654
  { ...target }
@@ -1638,32 +1660,52 @@ var Response = class _Response {
1638
1660
  });
1639
1661
  pageResponse.props = { ...page.get().props, ...pageResponse.props };
1640
1662
  }
1641
- mergeOrMatchItems(target, source, currentKey, matchPropsOn) {
1642
- const matchOn = matchPropsOn.find((key) => {
1643
- const path = key.split(".").slice(0, -1).join(".");
1644
- 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;
1645
1668
  });
1646
- if (!matchOn) {
1647
- return [...Array.isArray(target) ? target : [], ...source];
1648
- }
1649
- const uniqueProperty = matchOn.split(".").pop() || "";
1650
- const targetArray = Array.isArray(target) ? target : [];
1651
- const map = /* @__PURE__ */ new Map();
1652
- targetArray.forEach((item) => {
1653
- if (item && typeof item === "object" && uniqueProperty in item) {
1654
- map.set(item[uniqueProperty], item);
1655
- } else {
1656
- 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);
1657
1677
  }
1658
1678
  });
1659
- source.forEach((item) => {
1660
- if (item && typeof item === "object" && uniqueProperty in item) {
1661
- map.set(item[uniqueProperty], item);
1662
- } else {
1663
- 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]);
1664
1702
  }
1703
+ return true;
1665
1704
  });
1666
- return Array.from(map.values());
1705
+ return [...newItems, ...untouchedExisting];
1706
+ }
1707
+ hasUniqueProperty(item, property) {
1708
+ return item && typeof item === "object" && property in item;
1667
1709
  }
1668
1710
  async setRememberedState(pageResponse) {
1669
1711
  const rememberedState = await history.getState(history.rememberedState, {});
@@ -2005,6 +2047,43 @@ var Router = class {
2005
2047
  replace(params) {
2006
2048
  this.clientVisit(params, { replace: true });
2007
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
+ }
2008
2087
  push(params) {
2009
2088
  this.clientVisit(params);
2010
2089
  }
@@ -2097,6 +2176,8 @@ var Router = class {
2097
2176
  }),
2098
2177
  onBefore: options.onBefore || (() => {
2099
2178
  }),
2179
+ onBeforeUpdate: options.onBeforeUpdate || (() => {
2180
+ }),
2100
2181
  onStart: options.onStart || (() => {
2101
2182
  }),
2102
2183
  onProgress: options.onProgress || (() => {
@@ -2124,8 +2205,48 @@ var Router = class {
2124
2205
  }
2125
2206
  };
2126
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
+
2127
2248
  // src/formObject.ts
2128
- var import_lodash_es2 = require("lodash-es");
2249
+ var import_lodash_es4 = require("lodash-es");
2129
2250
  function undotKey(key) {
2130
2251
  if (!key.includes(".")) {
2131
2252
  return key;
@@ -2160,15 +2281,15 @@ function formDataToObject(source) {
2160
2281
  const path = parseKey(undotKey(key));
2161
2282
  if (path[path.length - 1] === "") {
2162
2283
  const arrayPath = path.slice(0, -1);
2163
- const existing = (0, import_lodash_es2.get)(form, arrayPath);
2284
+ const existing = (0, import_lodash_es4.get)(form, arrayPath);
2164
2285
  if (Array.isArray(existing)) {
2165
2286
  existing.push(value);
2166
2287
  } else {
2167
- (0, import_lodash_es2.set)(form, arrayPath, [value]);
2288
+ (0, import_lodash_es4.set)(form, arrayPath, [value]);
2168
2289
  }
2169
2290
  continue;
2170
2291
  }
2171
- (0, import_lodash_es2.set)(form, path, value);
2292
+ (0, import_lodash_es4.set)(form, path, value);
2172
2293
  }
2173
2294
  return form;
2174
2295
  }
@@ -2285,6 +2406,380 @@ function createHeadManager(isServer2, titleCallback, onUpdate) {
2285
2406
  };
2286
2407
  }
2287
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
+
2288
2783
  // src/navigationEvents.ts
2289
2784
  function shouldIntercept(event) {
2290
2785
  const isLink = event.currentTarget.tagName.toLowerCase() === "a";
@@ -2330,7 +2825,7 @@ var configure = (options) => {
2330
2825
  progress2.id = baseComponentSelector;
2331
2826
  progress2.innerHTML = settings.template;
2332
2827
  };
2333
- var set2 = (n) => {
2828
+ var set4 = (n) => {
2334
2829
  const started = isStarted();
2335
2830
  n = clamp(n, settings.minimum, 1);
2336
2831
  status = n === 1 ? null : n;
@@ -2379,7 +2874,7 @@ var set2 = (n) => {
2379
2874
  var isStarted = () => typeof status === "number";
2380
2875
  var start = () => {
2381
2876
  if (!status) {
2382
- set2(0);
2877
+ set4(0);
2383
2878
  }
2384
2879
  const work = function() {
2385
2880
  setTimeout(function() {
@@ -2399,7 +2894,7 @@ var done = (force) => {
2399
2894
  return;
2400
2895
  }
2401
2896
  increaseByRandom(0.3 + 0.5 * Math.random());
2402
- set2(1);
2897
+ set4(1);
2403
2898
  };
2404
2899
  var increaseByRandom = (amount) => {
2405
2900
  const n = status;
@@ -2423,7 +2918,7 @@ var increaseByRandom = (amount) => {
2423
2918
  }
2424
2919
  return 0;
2425
2920
  })();
2426
- return set2(clamp(n + amount, 0, 0.994));
2921
+ return set4(clamp(n + amount, 0, 0.994));
2427
2922
  };
2428
2923
  var render = (fromStart) => {
2429
2924
  if (isRendered()) {
@@ -2569,7 +3064,7 @@ var progress_component_default = {
2569
3064
  configure,
2570
3065
  isStarted,
2571
3066
  done,
2572
- set: set2,
3067
+ set: set4,
2573
3068
  remove,
2574
3069
  start,
2575
3070
  status,