@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inertiajs/core",
3
- "version": "2.1.10",
3
+ "version": "2.2.0",
4
4
  "license": "MIT",
5
5
  "description": "A framework for creating server-driven single page apps.",
6
6
  "contributors": [
@@ -45,18 +45,18 @@
45
45
  },
46
46
  "dependencies": {
47
47
  "@types/lodash-es": "^4.17.12",
48
- "axios": "^1.12.0",
48
+ "axios": "^1.12.2",
49
49
  "lodash-es": "^4.17.21",
50
- "qs": "^6.9.0"
50
+ "qs": "^6.14.0"
51
51
  },
52
52
  "devDependencies": {
53
- "@types/deepmerge": "^2.2.0",
54
- "@types/node": "^18.4",
55
- "@types/nprogress": "^0.2.0",
56
- "@types/qs": "^6.9.0",
53
+ "@types/deepmerge": "^2.2.3",
54
+ "@types/node": "^18.19.127",
55
+ "@types/nprogress": "^0.2.3",
56
+ "@types/qs": "^6.14.0",
57
57
  "es-check": "^9.3.1",
58
- "esbuild": "^0.25.0",
59
- "esbuild-node-externals": "^1.6.0",
58
+ "esbuild": "^0.25.10",
59
+ "esbuild-node-externals": "^1.18.0",
60
60
  "typescript": "^5.9.2"
61
61
  },
62
62
  "scripts": {
@@ -0,0 +1,2 @@
1
+ export declare const getScrollableParent: (element: HTMLElement | null) => HTMLElement | null;
2
+ export declare const getElementsInViewportFromCollection: (referenceElement: HTMLElement, elements: HTMLElement[]) => HTMLElement[];
package/types/events.d.ts CHANGED
@@ -4,6 +4,7 @@ export declare const fireErrorEvent: GlobalEventTrigger<'error'>;
4
4
  export declare const fireExceptionEvent: GlobalEventTrigger<'exception'>;
5
5
  export declare const fireFinishEvent: GlobalEventTrigger<'finish'>;
6
6
  export declare const fireInvalidEvent: GlobalEventTrigger<'invalid'>;
7
+ export declare const fireBeforeUpdateEvent: GlobalEventTrigger<'beforeUpdate'>;
7
8
  export declare const fireNavigateEvent: GlobalEventTrigger<'navigate'>;
8
9
  export declare const fireProgressEvent: GlobalEventTrigger<'progress'>;
9
10
  export declare const fireStartEvent: GlobalEventTrigger<'start'>;
package/types/index.d.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  import { Router } from './router';
2
+ export { getScrollableParent } from './domUtils';
2
3
  export { objectToFormData } from './formData';
3
4
  export { formDataToObject } from './formObject';
4
5
  export { default as createHeadManager } from './head';
6
+ export { default as useInfiniteScroll } from './infiniteScroll';
5
7
  export { shouldIntercept, shouldNavigate } from './navigationEvents';
6
- export { hide as hideProgress, reveal as revealProgress, default as setupProgress } from './progress';
8
+ export { hide as hideProgress, progress, reveal as revealProgress, default as setupProgress } from './progress';
7
9
  export { resetFormFields } from './resetFormFields';
8
10
  export * from './types';
9
11
  export { hrefToUrl, isUrlMethodPair, mergeDataIntoQueryString, urlWithoutHash } from './url';
@@ -0,0 +1,9 @@
1
+ import { UseInfiniteScrollDataManager } from '../types';
2
+ export declare const useInfiniteScrollData: (options: {
3
+ getPropName: () => string;
4
+ onBeforeUpdate: () => void;
5
+ onBeforePreviousRequest: () => void;
6
+ onBeforeNextRequest: () => void;
7
+ onCompletePreviousRequest: (loadedPage?: string | number) => void;
8
+ onCompleteNextRequest: (loadedPage?: string | number) => void;
9
+ }) => UseInfiniteScrollDataManager;
@@ -0,0 +1,14 @@
1
+ import { UseInfiniteScrollElementManager } from '../types';
2
+ export declare const getPageFromElement: (element: HTMLElement) => string | undefined;
3
+ export declare const useInfiniteScrollElementManager: (options: {
4
+ shouldFetchNext: () => boolean;
5
+ shouldFetchPrevious: () => boolean;
6
+ getTriggerMargin: () => number;
7
+ getStartElement: () => HTMLElement;
8
+ getEndElement: () => HTMLElement;
9
+ getItemsElement: () => HTMLElement;
10
+ getScrollableParent: () => HTMLElement | null;
11
+ onPreviousTriggered: () => void;
12
+ onNextTriggered: () => void;
13
+ onItemIntersected: (element: HTMLElement) => void;
14
+ }) => UseInfiniteScrollElementManager;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * As users scroll through infinite content, this system updates the URL to reflect
3
+ * which page they're currently viewing. It uses a "most visible page" calculation
4
+ * so that the URL reflects whichever page has the most visible items.
5
+ */
6
+ export declare const useInfiniteScrollQueryString: (options: {
7
+ getPageName: () => string;
8
+ getItemsElement: () => HTMLElement;
9
+ shouldPreserveUrl: () => boolean;
10
+ }) => {
11
+ onItemIntersected: (itemElement: HTMLElement) => void;
12
+ };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * When loading content "before" the current viewport (e.g. loading page 1 when viewing page 2),
3
+ * new content is prepended to the DOM, which naturally pushes existing content down and
4
+ * disrupts the user's scroll position. This system maintains visual stability by:
5
+ *
6
+ * 1. Capturing a reference element and its position before the update
7
+ * 2. After new content is added, calculating how far that reference element moved
8
+ * 3. Adjusting scroll position to keep the reference element in the same visual location
9
+ */
10
+ export declare const useInfiniteScrollPreservation: (options: {
11
+ getScrollableParent: () => HTMLElement | null;
12
+ getItemsElement: () => HTMLElement;
13
+ }) => {
14
+ createCallbacks: () => {
15
+ captureScrollPosition: () => void;
16
+ restoreScrollPosition: () => void;
17
+ };
18
+ };
@@ -0,0 +1,12 @@
1
+ import { UseInfiniteScrollOptions, UseInfiniteScrollProps } from './types';
2
+ /**
3
+ * Core infinite scroll composable that orchestrates data fetching, DOM management,
4
+ * scroll preservation, and URL synchronization.
5
+ *
6
+ * This is the main entry point that coordinates four sub-systems:
7
+ * - Data management: Handles pagination state and server requests
8
+ * - Element management: DOM observation and intersection detection
9
+ * - Query string sync: Updates URL as user scrolls through pages
10
+ * - Scroll preservation: Maintains scroll position during content updates
11
+ */
12
+ export default function useInfiniteScroll(options: UseInfiniteScrollOptions): UseInfiniteScrollProps;
@@ -0,0 +1,7 @@
1
+ type IntersectionObserverCallback = (entry: IntersectionObserverEntry) => void;
2
+ interface IntersectionObserverManager {
3
+ new: (callback: IntersectionObserverCallback, options?: IntersectionObserverInit) => IntersectionObserver;
4
+ flushAll: () => void;
5
+ }
6
+ export declare const useIntersectionObservers: () => IntersectionObserverManager;
7
+ export {};
@@ -1,3 +1,16 @@
1
+ declare class Progress {
2
+ hideCount: number;
3
+ start(): void;
4
+ reveal(force?: boolean): void;
5
+ hide(): void;
6
+ set(status: number): void;
7
+ finish(): void;
8
+ reset(): void;
9
+ remove(): void;
10
+ isStarted(): boolean;
11
+ getStatus(): number | null;
12
+ }
13
+ export declare const progress: Progress;
1
14
  export declare const reveal: (force?: boolean) => void;
2
15
  export declare const hide: () => void;
3
16
  export default function setupProgress({ delay, color, includeCSS, showSpinner, }?: {
@@ -6,3 +19,4 @@ export default function setupProgress({ delay, color, includeCSS, showSpinner, }
6
19
  includeCSS?: boolean | undefined;
7
20
  showSpinner?: boolean | undefined;
8
21
  }): void;
22
+ export {};
@@ -27,7 +27,10 @@ export declare class Response {
27
27
  protected shouldSetPage(pageResponse: Page): boolean;
28
28
  protected pageUrl(pageResponse: Page): string;
29
29
  protected mergeProps(pageResponse: Page): void;
30
- protected mergeOrMatchItems(target: any[], source: any[], currentKey: string, matchPropsOn: string[]): any[];
30
+ protected mergeOrMatchItems(existingItems: any[], newItems: any[], matchProp: string, matchPropsOn: string[], shouldAppend?: boolean): any[];
31
+ protected appendWithMatching(existingItems: any[], newItems: any[], newItemsMap: Map<any, any>, uniqueProperty: string): any[];
32
+ protected prependWithMatching(existingItems: any[], newItems: any[], newItemsMap: Map<any, any>, uniqueProperty: string): any[];
33
+ protected hasUniqueProperty(item: any, property: string): boolean;
31
34
  protected setRememberedState(pageResponse: Page): Promise<void>;
32
35
  protected getScopedErrors(errors: Errors & ErrorBag): Errors;
33
36
  }
package/types/router.d.ts CHANGED
@@ -30,6 +30,9 @@ export declare class Router {
30
30
  decryptHistory(): Promise<Page>;
31
31
  resolveComponent(component: string): Promise<Component>;
32
32
  replace<TProps = Page['props']>(params: ClientSideVisitOptions<TProps>): void;
33
+ replaceProp<TProps = Page['props']>(name: string, value: unknown | ((oldValue: unknown, props: TProps) => unknown), options?: Pick<ClientSideVisitOptions, 'onError' | 'onFinish' | 'onSuccess'>): void;
34
+ appendToProp<TProps = Page['props']>(name: string, value: unknown | unknown[] | ((oldValue: unknown, props: TProps) => unknown | unknown[]), options?: Pick<ClientSideVisitOptions, 'onError' | 'onFinish' | 'onSuccess'>): void;
35
+ prependToProp<TProps = Page['props']>(name: string, value: unknown | unknown[] | ((oldValue: unknown, props: TProps) => unknown | unknown[]), options?: Pick<ClientSideVisitOptions, 'onError' | 'onFinish' | 'onSuccess'>): void;
33
36
  push<TProps = Page['props']>(params: ClientSideVisitOptions<TProps>): void;
34
37
  protected clientVisit<TProps = Page['props']>(params: ClientSideVisitOptions<TProps>, { replace }?: {
35
38
  replace?: boolean;
package/types/types.d.ts CHANGED
@@ -53,6 +53,12 @@ export type RequestPayload = Record<string, FormDataConvertible> | FormData;
53
53
  export interface PageProps {
54
54
  [key: string]: unknown;
55
55
  }
56
+ export type ScrollProp = {
57
+ pageName: string;
58
+ previousPage?: number | string;
59
+ nextPage?: number | string;
60
+ currentPage?: number | string;
61
+ };
56
62
  export interface Page<SharedProps extends PageProps = PageProps> {
57
63
  component: string;
58
64
  props: PageProps & SharedProps & {
@@ -65,8 +71,10 @@ export interface Page<SharedProps extends PageProps = PageProps> {
65
71
  encryptHistory: boolean;
66
72
  deferredProps?: Record<string, VisitOptions['only']>;
67
73
  mergeProps?: string[];
74
+ prependProps?: string[];
68
75
  deepMergeProps?: string[];
69
76
  matchPropsOn?: string[];
77
+ scrollProps?: Record<keyof PageProps, ScrollProp>;
70
78
  /** @internal */
71
79
  rememberedState: Record<string, unknown>;
72
80
  }
@@ -152,6 +160,13 @@ export type GlobalEventsMap<T extends RequestPayload = RequestPayload> = {
152
160
  details: {};
153
161
  result: void;
154
162
  };
163
+ beforeUpdate: {
164
+ parameters: [Page];
165
+ details: {
166
+ page: Page;
167
+ };
168
+ result: void;
169
+ };
155
170
  navigate: {
156
171
  parameters: [Page];
157
172
  details: {
@@ -220,6 +235,7 @@ export type VisitCallbacks<T extends RequestPayload = RequestPayload> = {
220
235
  }): void;
221
236
  };
222
237
  onBefore: GlobalEventCallback<'before', T>;
238
+ onBeforeUpdate: GlobalEventCallback<'beforeUpdate', T>;
223
239
  onStart: GlobalEventCallback<'start', T>;
224
240
  onProgress: GlobalEventCallback<'progress', T>;
225
241
  onFinish: GlobalEventCallback<'finish', T>;
@@ -348,6 +364,77 @@ export type FormComponentState = {
348
364
  };
349
365
  export type FormComponentSlotProps = FormComponentMethods & FormComponentState;
350
366
  export type FormComponentRef = FormComponentSlotProps;
367
+ export interface UseInfiniteScrollOptions {
368
+ getPropName: () => string;
369
+ inReverseMode: () => boolean;
370
+ shouldFetchNext: () => boolean;
371
+ shouldFetchPrevious: () => boolean;
372
+ shouldPreserveUrl: () => boolean;
373
+ getTriggerMargin: () => number;
374
+ getStartElement: () => HTMLElement;
375
+ getEndElement: () => HTMLElement;
376
+ getItemsElement: () => HTMLElement;
377
+ getScrollableParent: () => HTMLElement | null;
378
+ onBeforePreviousRequest: () => void;
379
+ onBeforeNextRequest: () => void;
380
+ onCompletePreviousRequest: () => void;
381
+ onCompleteNextRequest: () => void;
382
+ }
383
+ export interface UseInfiniteScrollDataManager {
384
+ getLastLoadedPage: () => number | string | undefined;
385
+ getPageName: () => string;
386
+ hasPrevious: () => boolean;
387
+ hasNext: () => boolean;
388
+ fetchNext: (reloadOptions?: ReloadOptions) => void;
389
+ fetchPrevious: (reloadOptions?: ReloadOptions) => void;
390
+ }
391
+ export interface UseInfiniteScrollElementManager {
392
+ setupObservers: () => void;
393
+ enableTriggers: () => void;
394
+ disableTriggers: () => void;
395
+ refreshTriggers: () => void;
396
+ flushAll: () => void;
397
+ processManuallyAddedElements: () => void;
398
+ processServerLoadedElements: (loadedPage?: string | number | undefined) => void;
399
+ }
400
+ export interface UseInfiniteScrollProps {
401
+ dataManager: UseInfiniteScrollDataManager;
402
+ elementManager: UseInfiniteScrollElementManager;
403
+ }
404
+ export interface InfiniteScrollSlotProps {
405
+ loading: boolean;
406
+ loadingPrevious: boolean;
407
+ loadingNext: boolean;
408
+ }
409
+ export interface InfiniteScrollActionSlotProps {
410
+ loading: boolean;
411
+ loadingPrevious: boolean;
412
+ loadingNext: boolean;
413
+ fetch: () => void;
414
+ autoMode: boolean;
415
+ manualMode: boolean;
416
+ hasMore: boolean;
417
+ hasPrevious: boolean;
418
+ hasNext: boolean;
419
+ }
420
+ export interface InfiniteScrollRef {
421
+ fetchNext: (reloadOptions?: ReloadOptions) => void;
422
+ fetchPrevious: (reloadOptions?: ReloadOptions) => void;
423
+ hasPrevious: () => boolean;
424
+ hasNext: () => boolean;
425
+ }
426
+ export interface InfiniteScrollComponentBaseProps {
427
+ data?: string;
428
+ buffer?: number;
429
+ as?: string;
430
+ manual?: boolean;
431
+ manualAfter?: number;
432
+ preserveUrl?: boolean;
433
+ reverse?: boolean;
434
+ autoScroll?: boolean;
435
+ onlyNext?: boolean;
436
+ onlyPrevious?: boolean;
437
+ }
351
438
  declare global {
352
439
  interface DocumentEventMap {
353
440
  'inertia:before': GlobalEvent<'before'>;
@@ -358,6 +445,7 @@ declare global {
358
445
  'inertia:invalid': GlobalEvent<'invalid'>;
359
446
  'inertia:exception': GlobalEvent<'exception'>;
360
447
  'inertia:finish': GlobalEvent<'finish'>;
448
+ 'inertia:beforeUpdate': GlobalEvent<'beforeUpdate'>;
361
449
  'inertia:navigate': GlobalEvent<'navigate'>;
362
450
  }
363
451
  }